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.