home *** CD-ROM | disk | FTP | other *** search
- /* PAINT.C
- *
- * Scott R. Houck
- * Written in Turbo C 2.0
- *
- * Add the EGAVGA.BGI driver to graphics.lib using the BGIOBJ program.
- *
- * Compile with: tcc -ml paint graphics.lib
- *
- * This is a simple paint program
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <dos.h>
- #include <mem.h>
- #include <alloc.h>
- #include <conio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <io.h>
- #include <ctype.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
-
- /* Menu choices */
-
- #define IGNORE -1
- #define PAINT 0
- #define FILL 1
- #define ERASER 2
- #define CLEAR 3
- #define SAVE 4
- #define LOAD 5
- #define QUIT 6
- #define RUBBER_LINE 7
- #define RUBBER_RECTANGLE 8
-
-
- #define LINE 0
- #define RECTANGLE 1
-
- /* Some useful typedefs */
-
- typedef struct pointtype POINT; /* A point with x and y as ints */
- typedef POINT EXTENT [2]; /* Rectangular extent */
-
-
- /* Function prototypes */
-
- void InitializeGraphics(void);
- void DrawScreen(void);
- int MouseReset(int *);
- void MouseOn(void);
- void MouseOff(void);
- int MouseStatus(POINT *);
- void MouseWaitForPress(int, POINT *);
- void MouseWaitForRelease(int, POINT *);
- void MouseSetCursor(int [16][2]);
- void HighlightMenu(int, int, int);
- int PointInExtent(POINT, EXTENT);
- void HandleDraw(POINT);
- int PickCorrInMenu(POINT);
- int PickCorrInColor(POINT);
- int PickCorrInPattern(POINT);
- void HandlePick(POINT);
- void SetForeground(int);
- void SetBackground(int);
- void SetPattern(int);
- void DoPaint(POINT);
- void DoFill(POINT);
- void DoEraser(POINT);
- void DoClear(void);
- void DoSave(void);
- void DoLoad(void);
- void DoRubber(int, POINT);
- int DialogBox(void);
- void Beep(void);
- void LowBeep(void);
- int GetChar(char *, char *, int *);
- char * GetString(char *, int, int, int, char *, char *, char *, int,
- int (*)(int, int));
- int PromptForFilename(char *);
-
-
- /* Global variables */
-
- int maxx, maxy; /* Maximum pixel values */
- int dminx, dminy, dmaxx, dmaxy; /* Drawing area coordinates */
- int bgminx, bgminy, bgmaxx, bgmaxy; /* Background box */
- int fgminx, fgminy, fgmaxx, fgmaxy; /* Foreground box */
- int rl1x, rl1y, rl2x, rl2y; /* Rubber line coordinates */
- int rr1x, rr1y, rr2x, rr2y; /* Rubber rectangle coordinates */
- int xminx, xminy, xmaxx, xmaxy; /* Dialog box coordinates */
- EXTENT drawExtent; /* Extent of the drawing area */
- EXTENT colorExtent[16]; /* Extents of the 16 color boxes */
- EXTENT patternExtent[11]; /* Extents of the 11 patterns */
- EXTENT yesExtent, noExtent; /* Extent of the YES/NO buttons */
- int currentColor; /* Current foreground color */
- int fillPattern; /* Current fill pattern */
- int fillColor; /* Current fill color */
- unsigned dialogSize; /* Dialog box image size */
- unsigned drawSize; /* Drawing size */
- unsigned promptSize; /* Size of prompt box */
- void *dialogBuffer, *saveBuffer; /* Dialog box and screen buffers */
- void *promptBuffer, *drawBuffer; /* Prompt box and drawing buffers */
- int fminx, fminy, fmaxx, fmaxy; /* File prompt box coords */
- int promptx, prompty; /* File prompt x and y coords */
-
- struct {
- EXTENT extent;
- char *text;
- } menuBox[10]; /* menu buttons */
-
- int mode; /* current mode */
-
-
- /* The following two arrays define the eraser-type cursor and the
- * regular arrow cursor for use in the MouseSetCursor() routine.
- */
-
- int eraser [16][2] = {
- { 0xFFFF, 0xFFFF }, /* screen mask */
- { 0xFFFF, 0xFFFF },
- { 0xFFFF, 0xFFFF },
- { 0xFFFF, 0xFFFF },
- { 0xFFFF, 0xFFFF },
- { 0xFFFF, 0xFFFF },
- { 0xFFFF, 0xFFFF },
- { 0xFFFF, 0xFFFF },
-
- { 0xFFFF, 0x8001 }, /* cursor mask */
- { 0x8001, 0x8001 },
- { 0x8001, 0x8001 },
- { 0x8001, 0xFFFF },
- { 0x0000, 0x0000 },
- { 0x0000, 0x0000 },
- { 0x0000, 0x0000 },
- { 0x0000, 0x0000 }
- };
-
- int cursor [16][2] = {
- { 0x3FFF, 0x1FFF }, /* screen mask */
- { 0x0FFF, 0x07FF },
- { 0x03FF, 0x01FF },
- { 0x00FF, 0x007F },
- { 0x003F, 0x001F },
- { 0x01FF, 0x10FF },
- { 0x30FF, 0xF87F },
- { 0xF87F, 0xFC7F },
-
- { 0x0000, 0x4000 }, /* cursor mask */
- { 0x6000, 0x7000 },
- { 0x7800, 0x7C00 },
- { 0x7E00, 0x7F00 },
- { 0x7F80, 0x7C00 },
- { 0x6C00, 0x4600 },
- { 0x0600, 0x0300 },
- { 0x0300, 0x0000 }
- };
-
-
-
- main()
- {
- POINT position;
- int buttonPressed;
-
- InitializeGraphics();
- DrawScreen();
- MouseOn();
-
- HighlightMenu(mode = PAINT, LIGHTGRAY, BLACK);
-
- while (mode != QUIT)
- {
- do
- {
- buttonPressed = MouseStatus(&position);
- if (mode == ERASER && PointInExtent(position, drawExtent))
- MouseSetCursor(eraser);
- else
- MouseSetCursor(cursor);
- }
- while (!(buttonPressed & (RIGHTBUTTON | LEFTBUTTON)));
-
- if (PointInExtent(position, drawExtent))
- HandleDraw(position);
- else
- HandlePick(position);
- }
-
- 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);
- }
-
- /* Get maximum x and y screen coordinates */
-
- maxx = getmaxx();
- maxy = getmaxy();
- }
-
-
- void DrawScreen()
- {
- int i;
- int cminx, cminy, cmaxx, cmaxy; /* color box coordinates */
- int pminx, pminy, pmaxx, pmaxy; /* pattern box coordinates */
- int cwidth; /* width of color box */
- int cheight; /* height of color box */
- int pwidth; /* width of pattern box */
- int gap; /* gap between various objects */
- int bminx, bminy, bmaxx, bmaxy; /* Menu buttons */
- int bwidth, bheight, bgap, bstart; /* Menu buttons */
- int dwidth, dheight; /* Drawing area dimensions */
- int xwidth, xheight; /* Dialog box dimensions */
- int yminx, yminy, ymaxx, ymaxy; /* YES button */
- int nminx, nminy, nmaxx, nmaxy; /* NO button */
- int fwidth, fheight; /* Height of file prompt box */
- static char *boxText[] = { "PAINT", "FILL", "ERASER", "CLEAR", "SAVE",
- "LOAD", "QUIT", "", "" };
-
- setvisualpage(0);
- setactivepage(0);
-
- /* Draw the main background */
-
- setcolor(WHITE);
- rectangle(0, 0, maxx, maxy);
- setfillstyle(INTERLEAVE_FILL, CYAN);
- floodfill(1, 1, WHITE);
-
- /* Draw the drawing area */
-
- drawExtent[0].x = dminx = (int)(0.30 * maxx);
- drawExtent[0].y = dminy = (int)(0.05 * maxy);
- drawExtent[1].x = dmaxx = (int)(0.95 * maxx);
- drawExtent[1].y = dmaxy = (int)(0.80 * maxy);
-
- drawSize = imagesize(dminx, dminy, dmaxx, dmaxy);
- drawBuffer = malloc(drawSize);
-
- dwidth = dmaxx - dminx;
- dheight = dmaxy - dminy;
-
- setfillstyle(SOLID_FILL, WHITE);
- setcolor(WHITE);
- rectangle(dminx-1, dminy-1, dmaxx+1, dmaxy+1);
- floodfill(dminx, dminy, WHITE);
-
- /* Draw the dialog box */
-
- setactivepage(1);
-
- xwidth = (int)(0.35 * dwidth);
- xheight = (int)(0.25 * dheight);
- xminx = dminx + (dwidth - xwidth) / 2;
- xminy = dminy + (dheight - xheight) / 2;
- xmaxx = xminx + xwidth;
- xmaxy = xminy + xheight;
- rectangle(xminx, xminy, xmaxx, xmaxy); /* The outline */
-
- yesExtent[0].x = yminx = xminx + (int)(0.10 * xwidth);
- yesExtent[0].y = yminy = xminy + (int)(0.60 * xheight);
- yesExtent[1].x = ymaxx = xminx + (int)(0.40 * xwidth);
- yesExtent[1].y = ymaxy = xminy + (int)(0.90 * xheight);
- rectangle(yminx, yminy, ymaxx, ymaxy);
- setfillstyle(SOLID_FILL, BLUE);
- floodfill(yminx+1, yminy+1, WHITE); /* YES button */
-
- noExtent[0].x = nminx = xminx + (int)(0.60 * xwidth);
- noExtent[0].y = nminy = yminy;
- noExtent[1].x = nmaxx = xminx + (int)(0.90 * xwidth);
- noExtent[1].y = nmaxy = ymaxy;
- rectangle(nminx, nminy, nmaxx, nmaxy);
- floodfill(nminx+1, nminy+1, WHITE); /* NO button */
-
- setfillstyle(SOLID_FILL, LIGHTGRAY);
- floodfill(xminx+1, xminy+1, WHITE); /* The interior */
-
- settextjustify(CENTER_TEXT, CENTER_TEXT);
- moveto(xminx+xwidth/2, xminy+(yminy-xminy)/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(xminx, xminy, xmaxx, xmaxy);
- dialogBuffer = malloc(dialogSize);
- getimage(xminx, xminy, xmaxx, xmaxy, dialogBuffer);
-
- /* Draw the prompt box */
-
- cleardevice();
- fwidth = (int)(0.35 * dwidth);
- fheight = (int)(0.20 * dheight);
- fminx = dminx + (int)(0.25 * dwidth);
- fminy = dminy + (dheight - fheight) / 2;
- fmaxx = fminx + fwidth;
- fmaxy = fminy + fheight;
- rectangle(fminx, fminy, fmaxx, fmaxy); /* The outline */
-
- promptx = fminx + (int)(0.40 * fwidth);
- prompty = (fminy + fmaxy) / 2;
- rectangle(promptx-5, prompty-fheight/6, fminx + (int)(0.90 * fwidth),
- prompty+fheight/6); /* Draw the filename input box */
-
- setfillstyle(SOLID_FILL, CYAN);
- floodfill(fminx+1, fminy+1, WHITE);
- moveto(fminx+8, prompty);
- setcolor(BLACK);
- settextjustify(LEFT_TEXT, CENTER_TEXT);
- outtext("File:");
- setcolor(WHITE);
-
- setfillstyle(SOLID_FILL, WHITE);
- floodfill(promptx+1, prompty, WHITE);
-
- /* Save the prompt box in memory */
-
- promptSize = imagesize(fminx, fminy, fmaxx, fmaxy);
- promptBuffer = malloc(promptSize);
- getimage(fminx, fminy, fmaxx, fmaxy, promptBuffer);
-
- setactivepage(0);
-
- /* Draw the color boxes */
-
- cwidth = (int)((dmaxx - dminx) / 16.0);
- cheight = (int)(0.07 * maxy);
- gap = (int)(0.025 * maxy);
-
- cminy = dmaxy + gap;
- cmaxy = cminy + cheight;
-
- for (i = 0; i < 16; i++)
- {
- colorExtent[i][0].x = cminx = dminx + i * cwidth;
- colorExtent[i][0].y = cminy;
- colorExtent[i][1].x = cmaxx = cminx + cwidth;
- colorExtent[i][1].y = cmaxy;
- rectangle(cminx, cminy, cmaxx, cmaxy);
- setfillstyle(SOLID_FILL, i);
- floodfill(cminx+3, cminy+3, WHITE);
- }
-
- /* Draw the pattern boxes */
-
- pwidth = (int)((dmaxx - dminx) / 11.0);
- pminy = cmaxy + gap;
- pmaxy = pminy + cheight;
-
- for (i = 0; i < 11; i++)
- {
- patternExtent[i][0].x = pminx = dminx + i * pwidth;
- patternExtent[i][0].y = pminy;
- patternExtent[i][1].x = pmaxx = pminx + pwidth;
- patternExtent[i][1].y = pmaxy;
- rectangle(pminx, pminy, pmaxx, pmaxy);
- setfillstyle(i+1, WHITE);
- floodfill(pminx+3, pminy+3, WHITE);
- }
-
- /* Draw the menu buttons */
-
- bheight = (int)(0.055 * maxy);
- bwidth = (int)(0.150 * maxx);
- bgap = (int)(0.025 * maxy);
- bstart = (int)(0.050 * maxy);
- setfillstyle(SOLID_FILL, BLUE);
- bminx = (int)(0.05 * maxx);
- for (i = 0; i < 9; 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);
- settextjustify(CENTER_TEXT, CENTER_TEXT);
- 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];
-
- if (i == RUBBER_LINE)
- {
- rl1x = bminx + (int)(0.20 * (bmaxx-bminx));
- rl1y = bmaxy - (int)(0.20 * (bmaxy-bminy));
- rl2x = bmaxx - (int)(0.20 * (bmaxx-bminx));
- rl2y = bminy + (int)(0.20 * (bmaxy-bminy));
- line(rl1x, rl1y, rl2x, rl2y);
- }
-
- if (i == RUBBER_RECTANGLE)
- {
- rr1x = bminx + (int)(0.20 * (bmaxx-bminx));
- rr1y = bminy + (int)(0.20 * (bmaxy-bminy));
- rr2x = bmaxx - (int)(0.20 * (bmaxx-bminx));
- rr2y = bmaxy - (int)(0.20 * (bmaxy-bminy));
- rectangle(rr1x, rr1y, rr2x, rr2y);
- }
- }
-
- /* Draw the foreground/background box */
-
- bgminx = (int)(0.15 * maxx);
- bgminy = (int)(0.83 * maxy);
- bgmaxx = (int)(0.25 * maxx);
- bgmaxy = (int)(0.97 * maxy);
- rectangle(bgminx, bgminy, bgmaxx, bgmaxy);
-
- fgminx = bgminx + (int)(0.20 * (bgmaxx-bgminx));
- fgminy = bgminy + (int)(0.20 * (bgmaxy-bgminy));
- fgmaxx = bgmaxx - (int)(0.20 * (bgmaxx-bgminx));
- fgmaxy = bgmaxy - (int)(0.20 * (bgmaxy-bgminy));
- rectangle(fgminx, fgminy, fgmaxx, fgmaxy);
-
- setfillstyle(SOLID_FILL, WHITE);
- floodfill(bgminx+3, bgminy+3, WHITE);
-
- setfillstyle(SOLID_FILL, BLACK);
- floodfill(fgminx+3, fgminy+3, WHITE);
-
- /* Set defaults */
-
- currentColor = BLACK;
- fillPattern = SOLID_FILL;
- fillColor = WHITE;
- setcolor(currentColor);
- setfillstyle(fillPattern, fillColor);
- setviewport(dminx, dminy, dmaxx, dmaxy, CLIPPING_ON);
- }
-
-
- /* 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);
- }
-
-
- void MouseSetCursor(int picture[16][2])
- {
- struct SREGS segregs;
- union REGS inregs, outregs;
-
- segread(&segregs);
- inregs.x.ax = 9; /* Mouse function 9 -- Set Graphics Cursor */
- inregs.x.bx = 0;
- inregs.x.cx = 0;
- inregs.x.dx = (int) picture;
- segregs.es = segregs.ds;
- int86x(0x33, &inregs, &outregs, &segregs);
- }
-
-
- /* 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);
- setcolor(WHITE);
- 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);
-
- if (box == RUBBER_LINE)
- line(rl1x, rl1y, rl2x, rl2y);
-
- if (box == RUBBER_RECTANGLE)
- rectangle(rr1x, rr1y, rr2x, rr2y);
-
- /* Reset attributes */
-
- setviewport(view.left, view.top, view.right, view.bottom, view.clip);
- setfillstyle(fill.pattern, fill.color);
- setcolor(color);
-
- MouseOn();
- }
-
-
- /* 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;
- }
-
-
- /* HandleDraw() dispatches to the correct routine depending on the
- * current mode while the user has the mouse cursor in the drawing
- * area.
- */
- void HandleDraw(POINT position)
- {
- int numberOfButtons;
-
- switch (mode)
- {
- case PAINT:
- DoPaint(position);
- break;
-
- case FILL:
- DoFill(position);
- break;
-
- case ERASER:
- DoEraser(position);
- break;
-
- case RUBBER_LINE:
- DoRubber(LINE, position);
- break;
-
- case RUBBER_RECTANGLE:
- DoRubber(RECTANGLE, position);
- break;
- }
- }
-
-
- /* PickCorrInMenu() performs pick correlation within the menu box area. */
-
- int PickCorrInMenu(POINT pt)
- {
- int i;
-
- for (i = 0; i < 9; i++)
- if (PointInExtent(pt, menuBox[i].extent))
- return i;
-
- return IGNORE;
- }
-
-
- /* PickCorrInColor() performs pick correlation within the foreground and
- * background color boxes.
- */
- int PickCorrInColor(POINT pt)
- {
- int i;
-
- for (i = 0; i < 16; i++)
- if (PointInExtent(pt, colorExtent[i]))
- return i;
-
- return IGNORE;
- }
-
-
- /* PickCorrInPattern() performs pick correlation within the pattern
- * boxes.
- */
- int PickCorrInPattern(POINT pt)
- {
- int i;
-
- for (i = 0; i < 11; i++)
- if (PointInExtent(pt, patternExtent[i]))
- return i;
-
- return IGNORE;
- }
-
-
- /* HandlePick() sets the current mode of the program and handles other
- * cases when the mouse cursor is outside of the drawing area.
- */
- void HandlePick(POINT position)
- {
- int choice;
-
- if ((choice = PickCorrInMenu(position)) != IGNORE)
- switch (choice)
- {
- case PAINT:
- HighlightMenu(mode, BLUE, WHITE);
- HighlightMenu(mode = PAINT, LIGHTGRAY, BLACK);
- break;
-
- case FILL:
- HighlightMenu(mode, BLUE, WHITE);
- HighlightMenu(mode = FILL, LIGHTGRAY, BLACK);
- break;
-
- case ERASER:
- HighlightMenu(mode, BLUE, WHITE);
- HighlightMenu(mode = ERASER, LIGHTGRAY, BLACK);
- break;
-
- case CLEAR:
- HighlightMenu(mode, BLUE, WHITE);
- HighlightMenu(CLEAR, LIGHTGRAY, BLACK);
- DoClear();
- HighlightMenu(CLEAR, BLUE, WHITE);
- HighlightMenu(mode = PAINT, LIGHTGRAY, BLACK);
- break;
-
- case SAVE:
- HighlightMenu(mode, BLUE, WHITE);
- HighlightMenu(SAVE, LIGHTGRAY, BLACK);
- DoSave();
- HighlightMenu(SAVE, BLUE, WHITE);
- HighlightMenu(mode, LIGHTGRAY, BLACK);
- break;
-
- case LOAD:
- HighlightMenu(mode, BLUE, WHITE);
- HighlightMenu(LOAD, LIGHTGRAY, BLACK);
- DoLoad();
- HighlightMenu(LOAD, BLUE, WHITE);
- HighlightMenu(mode, LIGHTGRAY, BLACK);
- break;
-
- case QUIT:
- if (DialogBox() == YES)
- mode = QUIT;
- break;
-
- case RUBBER_LINE:
- HighlightMenu(mode, BLUE, WHITE);
- HighlightMenu(mode = RUBBER_LINE, LIGHTGRAY, BLACK);
- break;
-
- case RUBBER_RECTANGLE:
- HighlightMenu(mode, BLUE, WHITE);
- HighlightMenu(mode = RUBBER_RECTANGLE, LIGHTGRAY, BLACK);
- break;
- }
-
- else if ((choice = PickCorrInColor(position)) != IGNORE)
- {
- if (MouseStatus(&position) & LEFTBUTTON)
- SetForeground(choice);
- else
- SetBackground(choice);
- }
-
- else if ((choice = PickCorrInPattern(position)) != IGNORE)
- SetPattern(choice);
- }
-
-
- /* SetForeground() sets the current color (foreground) which is used
- * when drawing.
- */
- void SetForeground(int color)
- {
- MouseOff();
- currentColor = color;
- setcolor(currentColor);
- setviewport(fgminx+1, fgminy+1, fgmaxx-1, fgmaxy-1, CLIPPING_ON);
- clearviewport();
- setfillstyle(SOLID_FILL, color);
- floodfill(3, 3, WHITE);
- setfillstyle(fillPattern, fillColor);
- setviewport(dminx, dminy, dmaxx, dmaxy, CLIPPING_ON);
- MouseOn();
- }
-
-
- /* SetBackground() sets the current fill color, which is also the color
- * used when the drawing area is cleared by selecting the CLEAR option
- * from the menu buttons.
- */
- void SetBackground(int color)
- {
- MouseOff();
- fillColor = color;
- setviewport(bgminx+1, bgminy+1, bgmaxx-1, bgmaxy-1, CLIPPING_ON);
- clearviewport();
- setfillstyle(fillPattern, fillColor);
- floodfill(3, 3, WHITE);
- MouseOn();
- SetForeground(currentColor);
- }
-
-
- /* SetPattern() sets the current fill pattern, which is also the pattern
- * used when the drawing area is cleared by selecting the CLEAR option
- * from the menu buttons.
- */
- void SetPattern(int pattern)
- {
- MouseOff();
- fillPattern = pattern + 1;
- setfillstyle(fillPattern, fillColor);
- MouseOn();
- SetBackground(fillColor);
- }
-
-
- /* DoPaint() handles the paint option. */
-
- void DoPaint(POINT position)
- {
- int first = TRUE;
- POINT oldpt = position;
-
- moveto(position.x-dminx, position.y-dminy);
-
- while (MouseStatus(&position) & LEFTBUTTON)
- if (first || position.x != oldpt.x || position.y != oldpt.y)
- {
- first = FALSE;
- MouseOff();
- lineto(position.x-dminx, position.y-dminy);
- oldpt = position;
- MouseOn();
- }
- }
-
-
- /* DoFill() handles the fill option. The floodfill() function requires
- * that the border color be specified, so DoFill() compares pixels in
- * increasing x coordinates until a different color is found, and then
- * uses that color as the border color argument to floodfill().
- */
- void DoFill(POINT position)
- {
- int interior, border;
- int x = position.x-dminx;
-
- MouseWaitForRelease(LEFTBUTTON, &position);
-
- MouseOff();
-
- interior = getpixel(position.x-dminx, position.y-dminy);
- do
- border = getpixel(++x, position.y-dminy);
- while (border == interior);
-
- floodfill(position.x-dminx, position.y-dminy, border);
-
- MouseOn();
- }
-
-
- /* DoEraser handles the ERASER option. It uses a rectangular cursor as
- * an eraser, drawing lines in the background color. If the cursor is
- * moved outside the drawing area, the eraser reverts to the normal cursor
- * shape.
- */
- void DoEraser(POINT position)
- {
- int i, x, y, first = TRUE;
- POINT oldpt = position;
-
- setcolor(fillColor);
-
- while (MouseStatus(&position) & LEFTBUTTON)
- {
- if (PointInExtent(position, drawExtent))
- MouseSetCursor(eraser);
- else
- MouseSetCursor(cursor);
- if (first || position.x != oldpt.x || position.y != oldpt.y)
- {
- first = FALSE;
- MouseOff();
- x = position.x - dminx;
- y = position.y - dminy;
- for (i = 0; i < 8; i++)
- line(x, y+i, x+15, y+i);
- oldpt = position;
- MouseOn();
- }
- }
-
- setcolor(currentColor);
- }
-
-
- /* DoClear() clears the drawing area in the current background color and
- * pattern after receiving confirmation from the user by means of a dialog
- * box.
- */
- void DoClear()
- {
- if (DialogBox() == YES)
- {
- MouseOff();
- clearviewport();
- floodfill(5, 5, WHITE);
- MouseOn();
- }
- }
-
-
- /* DoSave() saves the drawing */
-
- void DoSave()
- {
- FILE *outfile;
- char filename[13];
-
- PromptForFile(filename);
-
- if ((outfile = fopen(filename, "wb")) == NULL)
- return;
- setviewport(0, 0, maxx, maxy, CLIPPING_ON);
-
- MouseOff();
- getimage(dminx, dminy, dmaxx, dmaxy, drawBuffer);
- MouseOn();
-
- setviewport(dminx, dminy, dmaxx, dmaxy, CLIPPING_ON);
- fwrite(drawBuffer, drawSize, 1, outfile);
- fclose(outfile);
- }
-
-
- /* DoLoad() loads a file into the drawing area. */
-
- void DoLoad()
- {
- FILE *infile;
- char filename[13];
- int status;
-
- status = PromptForFile(filename);
- if (status != 0) /* File does not exist */
- {
- LowBeep();
- return;
- }
-
- if ((infile = fopen(filename, "rb")) == NULL)
- return;
- fread(drawBuffer, drawSize, 1, infile);
- fclose(infile);
- setviewport(0, 0, maxx, maxy, CLIPPING_ON);
-
- MouseOff();
- putimage(dminx, dminy, drawBuffer, COPY_PUT);
- MouseOn();
-
- setviewport(dminx, dminy, dmaxx, dmaxy, CLIPPING_ON);
- }
-
-
- /* DoRubber() performs a rubber line/rectangle drawing routine. */
-
- void DoRubber(int type, POINT position)
- {
- POINT anchor = position;
- POINT oldpt = position;
-
- setwritemode(XOR_PUT);
- setcolor(currentColor ^ 15);
- moveto(anchor.x-dminx, anchor.y-dminy);
-
- while (MouseStatus(&position) & LEFTBUTTON)
- {
- if (position.x != oldpt.x || position.y != oldpt.y)
- {
- MouseOff();
- /* erase old and draw new */
- if (type == LINE)
- {
- line(anchor.x-dminx, anchor.y-dminy, oldpt.x-dminx,
- oldpt.y-dminy);
- line(anchor.x-dminx, anchor.y-dminy, position.x-dminx,
- position.y-dminy);
- }
- else
- {
- rectangle(anchor.x-dminx, anchor.y-dminy, oldpt.x-dminx,
- oldpt.y-dminy);
- rectangle(anchor.x-dminx, anchor.y-dminy, position.x-dminx,
- position.y-dminy);
- }
- oldpt = position;
- MouseOn();
- }
- }
-
- setcolor(currentColor);
- setwritemode(COPY_PUT);
-
- /* draw final */
- MouseOff();
- if (type == LINE)
- line(anchor.x-dminx, anchor.y-dminy, position.x-dminx,
- position.y-dminy);
- else
- rectangle(anchor.x-dminx, anchor.y-dminy, position.x-dminx,
- position.y-dminy);
- MouseOn();
- }
-
-
- /* DialogBox() pops up a dialog box containing the message "Are you sure?"
- * It returns YES or NO depending on the user's choice.
- */
- 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(xminx, xminy, xmaxx, xmaxy, saveBuffer);
-
- /* Display the dialog box */
- putimage(xminx, xminy, dialogBuffer, COPY_PUT);
-
- MouseOn();
-
- 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(xminx, xminy, saveBuffer, COPY_PUT);
- free(saveBuffer);
- MouseOn();
-
- setviewport(view.left, view.top, view.right, view.bottom, view.clip);
- return choice;
- }
-
-
- void Beep()
- {
- sound(1000);
- delay(150);
- nosound();
- }
-
-
- void LowBeep()
- {
- sound(100);
- delay(150);
- nosound();
- }
-
-
- /* GetChar() gets a character from the keyboard. legalchars and
- * legalscans are strings that contain the characters and scan codes
- * that the function will accept.
- */
- int GetChar(char *legalchars, char *legalscans, int *scancode)
- {
- int ch, ok;
-
- do
- {
- ch = getch();
- if ((ch == '\0') && kbhit()) /* extended key */
- ok = (strchr(legalscans, *scancode = getch()) != NULL);
- else
- ok = (strchr(legalchars, ch) != NULL);
- if (!ok)
- Beep();
- }
- while (!ok);
-
- return ch;
- }
-
-
- /* GetString() gets a string of input */
-
- char *GetString(char *inpstr, int x, int y, int width, char *deflt,
- char *legalchars, char *legalscans, int upcaseFlag,
- int (*keyHandler)(int, int))
- {
- char ch, temp[2], blanks[80];
- int len, scancode, done = FALSE;
-
- /* blanks is a string of character 219's -- block characters */
- memset(blanks, 219, width);
- blanks[width] = '\0';
-
- settextjustify(LEFT_TEXT, CENTER_TEXT);
-
- inpstr[0] = '\0'; /* Initialize the string to empty */
-
- /* Write the default */
- moveto(x, y);
- outtext(deflt);
-
- do
- {
- len = strlen(inpstr);
- ch = GetChar(legalchars, legalscans, &scancode);
- if (upcaseFlag)
- ch = toupper(ch);
- switch (ch)
- {
- case '\b': /* Backspace */
- if (len == 0)
- Beep();
- else
- {
- inpstr[len-1] = '\0'; /* Truncate the string */
- /* Blank out the input area and write the input string */
- setcolor(WHITE);
- moveto(x, y);
- outtext(blanks);
- setcolor(BLACK);
- moveto(x, y);
- if (strlen(inpstr) == 0)
- outtext(deflt);
- else
- outtext(inpstr);
- }
- break;
-
- case '\x1b': /* Escape key */
- /* Blank out the input area and write the default */
- setcolor(WHITE);
- moveto(x, y);
- outtext(blanks);
- setcolor(BLACK);
- inpstr[0] = '\0';
- moveto(x, y);
- outtext(deflt);
- break;
-
- case '\r':
- done = TRUE;
- break;
-
- case '\0': /* Handle function keys if desired */
- done = (*keyHandler)(ch, scancode);
- break;
-
- default:
- if (len < width)
- {
- if (len == 0)
- {
- setcolor(WHITE);
- moveto(x, y);
- outtext(blanks);
- setcolor(BLACK);
- moveto(x, y);
- }
- temp[0] = ch;
- temp[1] = '\0';
- strcat(inpstr, temp); /* accept the character */
- outtext(temp);
- }
- else
- Beep(); /* len was equal to width */
- }
- }
- while (!done);
-
- if (len == 0)
- strcpy(inpstr, deflt);
-
- return inpstr;
- }
-
-
-
- /* PromptForFile prompts the user for a filename. It returns 0 if the
- * file exists, 1 if it does not exist.
- */
- int PromptForFile(char *filename)
- {
- struct viewporttype view;
- int ch, scancode;
-
- /* Don't allow backslashes, periods, colons, etc. */
- char *legalchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
- "abcdefghijklmnopqrstuvwxyz" \
- "01234567890!@#$%^&()-_=`~[]{}'\"" \
- "\b\x1b\r";
-
- MouseOff();
-
- getviewsettings(&view);
- setviewport(0, 0, maxx, maxy, CLIPPING_OFF); /* Entire screen */
-
- /* Save the screen area under where the prompt box will display */
- saveBuffer = malloc(promptSize);
- getimage(fminx, fminy, fmaxx, fmaxy, saveBuffer);
-
- /* Display the prompt box */
- putimage(fminx, fminy, promptBuffer, COPY_PUT);
-
- MouseOn();
-
- /* Get the filename from the user */
- GetString(filename, promptx, prompty, 8, "PAINT", legalchars,
- NULL, TRUE, NULL);
-
- strcat(filename, ".pic");
-
- /* Restore the screen area and free the buffer */
-
- MouseOff();
- putimage(fminx, fminy, saveBuffer, COPY_PUT);
- MouseOn();
-
- free(saveBuffer);
-
- setviewport(view.left, view.top, view.right, view.bottom, view.clip);
- return access(filename, 0);
- }
-
-