PROGRAM 1
/* filename: program1.c author: anthony f. ortiz */
/* this program implements a pull-down menu package with a layout application
that allows the user to draw objects (elipses, squares, and triangles) on
the screen. the user may also redraw the screen, save scene to file,
restore the scene from a file, or quit. */
#include "srgp.h"
#include "geom.h"
#include
#include
#include
#define string_size 15
#define array_size 20
#define max_shapes 50
typedef char str [string_size + 1];
#define x_min 0
#define y_min 0
#define x_max 639
#define y_max 479
/* the screen layout (file, edit, pen-shape, pattern, etc) */
struct boxes
{
int box_x_min;
int box_y_min;
int box_x_max;
int box_y_max;
str header;
} buttons [array_size];
static int count = 0;
/* the objects that the user draws on the screen, vital for saving and
restoring from a file. */
struct shapes
{
int bottomleftx;
int bottomlefty;
int toprightx;
int toprighty;
int kind;
} shapes [max_shapes];
/* i did not use these definitions. however, a clearer program would use
these 19 definitions throughout the source code. */
#define menu_bar 0
#define file 1
#define edit 2
#define pen_shape 3
#define pattern 4
#define quit 5
#define save 6
#define open 7
#define delete 8
#define cut 9
#define paste 10
#define circle 11
#define square 12
#define slash 13
#define solid 14
#define opaque 15
#define transparent 16
#define ellipse 17
#define rect 18
#define triangle 19
void input_headers ();
void initialize_buttons ();
void draw_menu ();
void highlevelinteractionhandler (locator_measure measureoflocator);
int correlatemenubar (point measureoflocator);
int performpulldownmenu (int menuid);
int performactionchosenfrommenu (int choosenitemindex);
int correlatedrawingarea (point measureoflocator);
void processobject (int objectid);
void highlevelinteractionhandler2 (char * measure);
int correlatemenubar2 (char measure);
/* main program */
void main ()
{
locator_measure measureoflocator;
int device;
char * keymeasure;
SRGP_begin ("top-down menu", SCREEN_WIDTH, SCREEN_HEIGHT, 3, FALSE);
input_headers ();
initialize_buttons ();
draw_menu ();
SRGP_setInputMode (LOCATOR, EVENT);
SRGP_setLocatorButtonMask (LEFT_BUTTON_MASK | RIGHT_BUTTON_MASK);
SRGP_setInputMode (KEYBOARD, EVENT);
SRGP_setKeyboardProcessingMode (RAW);
SRGP_setBackgroundColor (COLOR_BLACK);
SRGP_setColor (COLOR_WHITE);
do
{
device = SRGP_waitEvent (INDEFINITE);
if (device == LOCATOR)
SRGP_getLocator (&measureoflocator);
else
SRGP_getKeyboard (keymeasure, 2);
if (device == LOCATOR)
{
highlevelinteractionhandler (measureoflocator);
measureoflocator.button_chord [0] = UP;
}
else if (device == KEYBOARD)
{
highlevelinteractionhandler2 (keymeasure);
keymeasure [0] = '\0';
}
}
while (1);
}
/* get the menu headers from a data file and put them in an array. */
void input_headers ()
{
FILE * infile;
int i = 0;
infile = fopen ("headers.dat", "r");
while (! feof (infile))
{
fscanf (infile, "%s", buttons [i].header);
i++;
}
fclose (infile);
}
/* store the initial screen layout in an array of records. */
void initialize_buttons ()
{
int i;
buttons [0].box_x_min = x_min + 5;
buttons [0].box_y_min = y_max - y_max / 5.0;
buttons [0].box_x_max = x_max - 5;
buttons [0].box_y_max = y_max - 5;
for (i = 1; i <= 4; i++)
{
buttons [i].box_x_min = buttons [0].box_x_min + (i - 1) * 100 + 10;
buttons [i].box_y_min = buttons [0].box_y_min + 10;
buttons [i].box_x_max = buttons [0].box_x_min + i * 100;
buttons [i].box_y_max = buttons [0].box_y_max - 10;
}
for (i = 5; i <= 8; i++)
{
buttons [i].box_x_min = buttons [1].box_x_min;
buttons [i].box_y_min = buttons [0].box_y_min - (i - 4) * 50;
buttons [i].box_x_max = buttons [1].box_x_max;
buttons [i].box_y_max = buttons [0].box_y_min - (i - 5) * 50;
}
for (i = 9; i <= 10; i++)
{
buttons [i].box_x_min = buttons [2].box_x_min;
buttons [i].box_y_min = buttons [0].box_y_min - (i - 8) * 50;
buttons [i].box_x_max = buttons [2].box_x_max;
buttons [i].box_y_max = buttons [0].box_y_min - (i - 9) * 50;
}
for (i = 11; i <= 13; i++)
{
buttons [i].box_x_min = buttons [3].box_x_min;
buttons [i].box_y_min = buttons [0].box_y_min - (i - 10) * 50;
buttons [i].box_x_max = buttons [3].box_x_max;
buttons [i].box_y_max = buttons [0].box_y_min - (i - 11) * 50;
}
for (i = 14; i <= 16; i++)
{
buttons [i].box_x_min = buttons [4].box_x_min;
buttons [i].box_y_min = buttons [0].box_y_min - (i - 13) * 50;
buttons [i].box_x_max = buttons [4].box_x_max;
buttons [i].box_y_max = buttons [0].box_y_min - (i - 14) * 50;
}
for (i = 17; i <= 19; i++)
{
buttons [i].box_x_min = buttons [0].box_x_max - 100;
buttons [i].box_y_min = buttons [0].box_y_min - (i - 16) * 85;
buttons [i].box_x_max = buttons [0].box_x_max;
buttons [i].box_y_max = buttons [0].box_y_min - (i - 17) * 85 - 10;
}
}
/* draw the initial screen. also draw the sub-menus on a second screen
that will be visible later on in the program. */
void draw_menu ()
{
int i, width, height, descent, menucanvasid;
point centerofbutton, textorigin, pt1, pt2, pt3;
rectangle rec;
SRGP_rectangleCoord (buttons [0].box_x_min, buttons [0].box_y_min, buttons [0].box_x_max, buttons [0].box_y_max);
for (i = 1; i <= 4; i++)
{
SRGP_rectangleCoord (buttons [i].box_x_min, buttons [i].box_y_min, buttons [i].box_x_max, buttons [i].box_y_max);
SRGP_inquireTextExtent (buttons [i].header, &width, &height, &descent);
centerofbutton.x = (buttons [i].box_x_min + buttons [i].box_x_max)/2;
centerofbutton.y = (buttons [i].box_y_min + buttons [i].box_y_max)/2;
textorigin.x = centerofbutton.x - (width / 2);
textorigin.y = centerofbutton.y - (height / 2);
SRGP_text (textorigin, buttons [i].header);
}
for (i = 17; i <= 19; i++)
{
SRGP_rectangleCoord (buttons [i].box_x_min, buttons [i].box_y_min, buttons [i].box_x_max, buttons [i].box_y_max);
}
rec.bottom_left.x = buttons [17].box_x_min + 10;
rec.bottom_left.y = buttons [17].box_y_min + 10;
rec.top_right.x = buttons [17].box_x_max - 10;
rec.top_right.y = buttons [17].box_y_max - 10;
SRGP_ellipseArc (rec, 0.0, 360.0);
SRGP_rectangleCoord (buttons [18].box_x_min + 10, buttons [18].box_y_min + 10, buttons [18].box_x_max - 10, buttons [18].box_y_max - 10);
pt1.x = (buttons [19].box_x_max + buttons [19].box_x_min) / 2.0;
pt1.y = buttons [19].box_y_max - 10;
pt2.x = buttons [19].box_x_min + 10;
pt2.y = buttons [19].box_y_min + 10;
pt3.x = buttons [19].box_x_max - 10;
pt3.y = buttons [19].box_y_min + 10;
SRGP_line (pt1, pt2);
SRGP_line (pt2, pt3);
SRGP_line (pt3, pt1);
menucanvasid = SRGP_createCanvas (x_max, y_max);
SRGP_useCanvas (menucanvasid);
for (i = 5; i <= 8; i++)
{
SRGP_rectangleCoord (buttons [i].box_x_min, buttons [i].box_y_min, buttons [i].box_x_max, buttons [i].box_y_max);
SRGP_inquireTextExtent (buttons [i].header, &width, &height, &descent);
centerofbutton.x = (buttons [i].box_x_min + buttons [i].box_x_max)/2;
centerofbutton.y = (buttons [i].box_y_min + buttons [i].box_y_max)/2;
textorigin.x = centerofbutton.x - (width / 2);
textorigin.y = centerofbutton.y - (height / 2);
SRGP_text (textorigin, buttons [i].header);
}
for (i = 9; i <= 10; i++)
{
SRGP_rectangleCoord (buttons [i].box_x_min, buttons [i].box_y_min, buttons [i].box_x_max, buttons [i].box_y_max);
SRGP_inquireTextExtent (buttons [i].header, &width, &height, &descent);
centerofbutton.x = (buttons [i].box_x_min + buttons [i].box_x_max)/2;
centerofbutton.y = (buttons [i].box_y_min + buttons [i].box_y_max)/2;
textorigin.x = centerofbutton.x - (width / 2);
textorigin.y = centerofbutton.y - (height / 2);
SRGP_text (textorigin, buttons [i].header);
}
for (i = 11; i <= 13; i++)
{
SRGP_rectangleCoord (buttons [i].box_x_min, buttons [i].box_y_min, buttons [i].box_x_max, buttons [i].box_y_max);
SRGP_inquireTextExtent (buttons [i].header, &width, &height, &descent);
centerofbutton.x = (buttons [i].box_x_min + buttons [i].box_x_max)/2;
centerofbutton.y = (buttons [i].box_y_min + buttons [i].box_y_max)/2;
textorigin.x = centerofbutton.x - (width / 2);
textorigin.y = centerofbutton.y - (height / 2);
SRGP_text (textorigin, buttons [i].header);
}
for (i = 14; i <= 16; i++)
{
SRGP_rectangleCoord (buttons [i].box_x_min, buttons [i].box_y_min, buttons [i].box_x_max, buttons [i].box_y_max);
SRGP_inquireTextExtent (buttons [i].header, &width, &height, &descent);
centerofbutton.x = (buttons [i].box_x_min + buttons [i].box_x_max)/2;
centerofbutton.y = (buttons [i].box_y_min + buttons [i].box_y_max)/2;
textorigin.x = centerofbutton.x - (width / 2);
textorigin.y = centerofbutton.y - (height / 2);
SRGP_text (textorigin, buttons [i].header);
}
SRGP_useCanvas (SCREEN_CANVAS);
}
/* this is a high level interaction handler for mouse events. */
void highlevelinteractionhandler (locator_measure measureoflocator)
{
int i, menuid, chosenitemindex, objectid;
rectangle menubarextent;
/* SRGP_defRectangle does not work. */
menubarextent.top_right.x = buttons [0].box_x_max;
menubarextent.top_right.y = buttons [0].box_y_max;
menubarextent.bottom_left.x = buttons [0].box_x_min;
menubarextent.bottom_left.y = buttons [0].box_y_min;
if (GEOM_ptInRect (measureoflocator.position, menubarextent))
{
menuid = correlatemenubar (measureoflocator.position);
if (menuid > 0)
{
chosenitemindex = performpulldownmenu (menuid);
if (chosenitemindex > 0)
{
performactionchosenfrommenu (chosenitemindex);
}
}
}
else
{
objectid = correlatedrawingarea (measureoflocator.position);
if (objectid > 0) processobject (objectid);
}
}
/* see if the user chose one of the menus with the mouse. */
int correlatemenubar (point measureoflocator)
{
rectangle menubarextent;
int i;
for (i = 1; i <= 4; i++)
{
menubarextent.top_right.x = buttons [i].box_x_max;
menubarextent.top_right.y = buttons [i].box_y_max;
menubarextent.bottom_left.x = buttons [i].box_x_min;
menubarextent.bottom_left.y = buttons [i].box_y_min;
if (GEOM_ptInRect (measureoflocator, menubarextent))
{
return i;
}
}
return 0;
}
/* activate the sub-menus, deactivate them, and get a choice from the
sub-menus. */
int performpulldownmenu (int menuid)
{
int device, i, width, height, descent, savecanvasid, menucanvasid;
point centerofbutton, textorigin;
rectangle menucanvasextent, savecanvas, submenuextent;
locator_measure measureoflocator;
char * keymeasure;
switch (menuid)
{
case 1: menucanvasextent.top_right.x = buttons [5].box_x_max;
menucanvasextent.top_right.y = buttons [5].box_y_max;
menucanvasextent.bottom_left.x = buttons [8].box_x_min;
menucanvasextent.bottom_left.y = buttons [8].box_y_min;
savecanvas.bottom_left.x = 200;
savecanvas.bottom_left.y = 0;
savecanvas.top_right.x = 200 + buttons [5].box_x_max - buttons [8].box_x_min;
savecanvas.top_right.y = buttons [5].box_y_max - buttons [8].box_y_min;
break;
case 2: menucanvasextent.top_right.x = buttons [9].box_x_max;
menucanvasextent.top_right.y = buttons [9].box_y_max;
menucanvasextent.bottom_left.x = buttons [10].box_x_min;
menucanvasextent.bottom_left.y = buttons [10].box_y_min;
savecanvas.bottom_left.x = 200;
savecanvas.bottom_left.y = 0;
savecanvas.top_right.x = 200 + buttons [9].box_x_max - buttons [10].box_x_min;
savecanvas.top_right.y = buttons [9].box_y_max - buttons [10].box_y_min;
break;
case 3: menucanvasextent.top_right.x = buttons [11].box_x_max;
menucanvasextent.top_right.y = buttons [11].box_y_max;
menucanvasextent.bottom_left.x = buttons [13].box_x_min;
menucanvasextent.bottom_left.y = buttons [13].box_y_min;
savecanvas.bottom_left.x = 200;
savecanvas.bottom_left.y = 0;
savecanvas.top_right.x = 200 + buttons [11].box_x_max - buttons [13].box_x_min;
savecanvas.top_right.y = buttons [11].box_y_max - buttons [13].box_y_min;
break;
case 4: menucanvasextent.top_right.x = buttons [14].box_x_max;
menucanvasextent.top_right.y = buttons [14].box_y_max;
menucanvasextent.bottom_left.x = buttons [16].box_x_min;
menucanvasextent.bottom_left.y = buttons [16].box_y_min;
savecanvas.bottom_left.x = 200;
savecanvas.bottom_left.y = 0;
savecanvas.top_right.x = 200 + buttons [14].box_x_max - buttons [16].box_x_min;
savecanvas.top_right.y = buttons [14].box_y_max - buttons [16].box_y_min;
break;
}
SRGP_useCanvas (1);
SRGP_copyPixel (SCREEN_CANVAS,menucanvasextent,savecanvas.bottom_left);
savecanvasid = SRGP_inquireActiveCanvas ();
SRGP_useCanvas (SCREEN_CANVAS);
SRGP_copyPixel (savecanvasid, menucanvasextent, menucanvasextent.bottom_left);
measureoflocator.button_chord [0] = UP;
keymeasure [0] = '\0';
do
{
device = SRGP_waitEvent (INDEFINITE);
if (device == LOCATOR)
{
SRGP_getLocator (&measureoflocator);
if (measureoflocator.button_chord [0] == DOWN)
SRGP_copyPixel (savecanvasid, savecanvas, menucanvasextent.bottom_left);
}
else
{
SRGP_getKeyboard (keymeasure, 2);
if (keymeasure [0] != '\0')
SRGP_copyPixel (savecanvasid, savecanvas, menucanvasextent.bottom_left);
}
}
while (measureoflocator.button_chord [0] == UP && keymeasure [0] == '\0');
if (device == LOCATOR)
{
for (i = 5; i <= 16; i++)
{
submenuextent.top_right.x = buttons [i].box_x_max;
submenuextent.top_right.y = buttons [i].box_y_max;
submenuextent.bottom_left.x = buttons [i].box_x_min;
submenuextent.bottom_left.y = buttons [i].box_y_min;
if (GEOM_ptInRect (measureoflocator.position, submenuextent))
{
return i;
}
}
}
else if (device == KEYBOARD)
{
switch (keymeasure [0])
{
case 'q': return 5;
case 's': return 6;
case 'o': return 7;
case 'd': return 8;
}
}
return 0;
}
/* perform one of the actions associated with the sub-menus. */
int performactionchosenfrommenu (int choosenitemindex)
{
int i;
FILE * outfile, *infile;
rectangle clearscreen, rec;
point pt1, pt2, pt3, pt4;
switch (choosenitemindex)
{
case 5: SRGP_end ();
exit (0);
break;
case 6: outfile = fopen ("shapes.out", "w");
for (i = 0; i < count; i++)
{
fprintf (outfile, "%d ", shapes [i].bottomleftx);
fprintf (outfile, "%d ", shapes [i].bottomlefty);
fprintf (outfile, "%d ", shapes [i].toprightx);
fprintf (outfile, "%d ", shapes [i].toprighty);
fprintf (outfile, "%d\n", shapes [i].kind);
}
fclose (outfile);
break;
case 7: count = 0;
for (i = 0; i < max_shapes; i++)
shapes [i].kind = 0;
clearscreen.bottom_left.x = 0;
clearscreen.bottom_left.y = 0;
clearscreen.top_right.x = buttons [17].box_x_min - 1;
clearscreen.top_right.y = buttons [17].box_y_max - 1;
SRGP_setFillStyle (SOLID);
SRGP_setColor (COLOR_BLACK);
SRGP_fillRectangle (clearscreen);
SRGP_setColor (COLOR_WHITE);count = 0;
infile = fopen ("shapes.out", "r");
while (!feof (infile))
{
fscanf (infile, "%d", &shapes [count].bottomleftx);
fscanf (infile, "%d", &shapes [count].bottomlefty);
fscanf (infile, "%d", &shapes [count].toprightx);
fscanf (infile, "%d", &shapes [count].toprighty);
fscanf (infile, "%d", &shapes [count].kind);
switch (shapes [count].kind)
{
case 17: rec.bottom_left.x = shapes [count].bottomleftx;
rec.bottom_left.y = shapes [count].bottomlefty;
rec.top_right.x = shapes [count].toprightx;
rec.top_right.y = shapes [count].toprighty;
SRGP_ellipseArc (rec, 0.0, 360.0);
break;
case 18: SRGP_rectangleCoord (shapes [count].bottomleftx, shapes [count].bottomlefty, shapes [count].toprightx, shapes [count].toprighty);
break;
case 19: pt1.x = shapes [count].bottomleftx;
pt1.y = shapes [count].bottomlefty;
pt2.x = shapes [count].toprightx;
pt2.y = shapes [count].toprighty;
pt3.x = (shapes [count].bottomleftx + shapes [count].toprightx) / 2;
pt3.y = shapes [count].toprighty;
pt4.x = shapes [count].toprightx;
pt4.y = shapes [count].bottomlefty;
SRGP_line (pt1, pt3);
SRGP_line (pt3, pt4);
SRGP_line (pt4, pt1);
break;
}
count = count + 1;
}
fclose (infile);
break;
case 8: for (i = 0; i < max_shapes; i++)
shapes [i].kind = 0;
clearscreen.bottom_left.x = 0;
clearscreen.bottom_left.y = 0;
clearscreen.top_right.x = buttons [17].box_x_min - 1;
clearscreen.top_right.y = buttons [17].box_y_max - 1;
SRGP_setFillStyle (SOLID);
SRGP_setColor (COLOR_BLACK);
SRGP_fillRectangle (clearscreen);
SRGP_setColor (COLOR_WHITE);
count = 0;
break;
}
return 0;
}
/* see if the user picked one of the objects with the mouse. */
int correlatedrawingarea (point measureoflocator)
{
int i;
rectangle objectextent;
for (i = 17; i <= 19; i++)
{
objectextent.top_right.x = buttons [i].box_x_max;
objectextent.top_right.y = buttons [i].box_y_max;
objectextent.bottom_left.x = buttons [i].box_x_min;
objectextent.bottom_left.y = buttons [i].box_y_min;
if (GEOM_ptInRect (measureoflocator, objectextent))
{
return i;
}
}
return 0;
}
/* put an object on the screen using the mouse. */
void processobject (int objectid)
{
int device;
point pt1, pt2, pt3, pt4;
rectangle rec;
locator_measure measureoflocator;
measureoflocator.button_chord [0] = UP;
do
{
device = SRGP_waitEvent (INDEFINITE);
SRGP_getLocator (&measureoflocator);
if (measureoflocator.button_chord [0] == DOWN)
pt1 = measureoflocator.position;
}
while (measureoflocator.button_chord [0] == UP);
measureoflocator.button_chord [0] = UP;
do
{
device = SRGP_waitEvent (INDEFINITE);
SRGP_getLocator (&measureoflocator);
if (measureoflocator.button_chord [0] == DOWN)
pt2 = measureoflocator.position;
}
while (measureoflocator.button_chord [0] == UP);
shapes [count].bottomleftx = pt1.x;
shapes [count].bottomlefty = pt1.y;
shapes [count].toprightx = pt2.x;
shapes [count].toprighty = pt2.y;
shapes [count].kind = objectid;
switch (objectid)
{
case 17: rec.bottom_left.x = pt1.x;
rec.bottom_left.y = pt1.y;
rec.top_right.x = pt2.x;
rec.top_right.y = pt2.y;
SRGP_ellipseArc (rec, 0.0, 360.0);
break;
case 18: SRGP_rectangleCoord (pt1.x, pt1.y, pt2.x, pt2.y);
break;
case 19: pt3.x = (pt1.x + pt2.x) / 2;
pt3.y = pt2.y;
pt4.x = pt2.x;
pt4.y = pt1.y;
SRGP_line (pt1, pt3);
SRGP_line (pt3, pt4);
SRGP_line (pt4, pt1);
break;
}
count = count + 1;
}
/* this is a high level interaction handler for the keyboard. */
void highlevelinteractionhandler2 (char * measure)
{
int menuid, chosenitemindex;
if (measure [0] == 'f' || measure [0] == 'e' || measure [0] == 's' || measure [0] == 'p')
{
menuid = correlatemenubar2 (measure [0]);
if (menuid > 0)
chosenitemindex = performpulldownmenu (menuid);
if (chosenitemindex > 0)
performactionchosenfrommenu (chosenitemindex);
}
}
/* see whether the user picked one of the menus with the keyboard. */
int correlatemenubar2 (char measure)
{
switch (measure)
{
case 'f': return 1;
case 'e': return 2;
case 's': return 3;
case 'p': return 4;
}
return 0;
}
/* data file: headers.dat */
*
file
font_size
font_style
colors
action
quit
save
open
delete
size_12
size_24
times
roman
modern
red
green
blue
rotate
move
scale_down
scale_up
/* outfile: prog1.out */
/* sorry, can't show you the output for this program. */
BACK TO CS4840 PAGE.