/* ========================== gopizza.c ============================ = = = THIS IS CS476 PROJECT TWO = = This file is the implementation file for an Xlib program that = = creates an interface for ordering pizza. The program requires = = at least two, but not more than six interfaces. Program is = = written in C for UNIX and is adapted from the example code = = found on the ODU CS476/576 web page. = = Author: Kevin Seavey (seavey@cs.odu.edu) = = Old Dominion University, CS476, Fall 98, Dr. Abdul Wahab = = = ================================================================== */ #include #include #include #include #include #define MAXUSERS 6 #define NUMBUTTONS 8 #define MAX(A,B) ((A) > (B) ? (A) : (B)) #define SQ_WIDTH 60 /* sendquitButton Width */ #define SQ_HEIGHT 25 /* sendquitButton Height */ #define SY_WIDHIG 22 /* yesnoButton Width & Height */ #define SB_LONGLABEL 50 /* Longest MenuButton label */ #define SQ_CURSOR XC_target /* Cursor for inside sendquitButton */ #define SY_CURSOR XC_question_arrow /* Cursor for inside topsButton */ #define SB_INPUTMASK ExposureMask | EnterWindowMask | LeaveWindowMask | \ ButtonPressMask | ButtonReleaseMask #define eventmask ExposureMask #define TRUE 1 #define FALSE 0 #define stdfont "9x15" XEvent event, button_event; XFontStruct *font_info; long fgcolor, bgcolor; Display *display[MAXUSERS]; Window root[MAXUSERS], window[MAXUSERS], cwindow[MAXUSERS]; int screen[MAXUSERS]; GC draw[MAXUSERS]; GC erase[MAXUSERS]; int closed[MAXUSERS]; int sent[MAXUSERS]; int topflags[MAXUSERS][NUMBUTTONS]; XSetWindowAttributes setwinattr; int NC; /* number of participants */ int numresp = 0; /* number of respondents */ int errorcount = 0; int numeaters, numpeprs, numcheeses, numvegs, numanchs; char votesleft[3]; char peprs[3]; char cheeses[3]; char vegs[3]; char anchs[3]; struct { Window window; char label[SB_LONGLABEL]; int (*func)(int u); } MenuButton[MAXUSERS][NUMBUTTONS]; int send(int u), checkp(int u), checkc(int u), checkv(int u), checka(int u), confirm(int u), Exit(int u), Continue(int u); main(argc,argv) int argc; char **argv; { int i,j; XGCValues gcval; if (argc == 1 || argc == 2) { perror("Usage: gopizza display1 display2 [d3 ... dn]"); exit(1); } else NC = argc-1; for (i = 0; i < NC; i++) { if (!(display[i - errorcount] = XOpenDisplay(argv[i+1]))) { if (i == 0) { perror("XOpenDisplay"); exit(1); } else { errorcount++; printf("ERROR : XOpenDisplay %s\n", argv[i+1]); } } } NC = NC - errorcount; numpeprs = 0; numcheeses = 0; numvegs = 0; numanchs = 0; numeaters = NC; sprintf(votesleft, "%d", numeaters); sprintf(peprs, "%d", numpeprs); sprintf(cheeses, "%d", numcheeses); sprintf(vegs, "%d", numvegs); sprintf(anchs, "%d", numanchs); for (i = 0; i < NC; i++) { sent[i] = FALSE; closed[i] = FALSE; screen[i] = DefaultScreen(display[i]); root[i] = RootWindow(display[i], screen[i]); fgcolor = BlackPixel(display[i], screen[i]); bgcolor = WhitePixel(display[i], screen[i]); font_info = XLoadQueryFont(display[i], stdfont); window[i] = XCreateSimpleWindow(display[i], root[i],0,0, 360,450,2,fgcolor,bgcolor); if (i == 0) XStoreName(display[i], window[i],"INITIATOR"); else XStoreName(display[i], window[i],"INVITEE"); gcval.foreground = fgcolor; gcval.background = bgcolor; gcval.font = font_info->fid; draw[i] = XCreateGC(display[i],window[i], GCForeground|GCBackground|GCFont,&gcval); XSetGraphicsExposures(display[i], draw[i], 0); gcval.foreground = bgcolor; gcval.background = fgcolor; gcval.font = font_info->fid; erase[i] = XCreateGC(display[i],window[i], GCForeground|GCBackground|GCFont,&gcval); XSetGraphicsExposures(display[i], erase[i], 0); MakeButton(70, 390, SQ_WIDTH, SQ_HEIGHT, "Send", send, i, 0, window[i]); MakeButton(230, 390, SQ_WIDTH, SQ_HEIGHT, "Quit", confirm, i, 1, window[i]); MakeButton(180, 144, SY_WIDHIG, SY_WIDHIG, " ", checkp, i, 2, window[i]); MakeButton(180, 194, SY_WIDHIG, SY_WIDHIG, " ", checkc, i, 3, window[i]); MakeButton(180, 244, SY_WIDHIG, SY_WIDHIG, " ", checkv, i, 4, window[i]); MakeButton(180, 294, SY_WIDHIG, SY_WIDHIG, " ", checka, i, 5, window[i]); XMapWindow(display[i],window[i]); XFlush(display[i]); XSelectInput(display[i],window[i],eventmask); } for (i = 0; i < NC; i++) { if (closed[i] == FALSE) { XDrawString(display[i],window[i],draw[i],140,30,"GoPizza!", strlen("GoPizza!")); XDrawString(display[i],window[i],draw[i],40,60,"Countdown:", strlen("Countdown:")); XDrawRectangle(display[i],window[i],draw[i],260,49, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,65,votesleft, strlen(votesleft)); XDrawString(display[i],window[i],draw[i],266,65,votesleft, strlen(votesleft)); XDrawLine(display[i],window[i],draw[i],0,90,360,90); XDrawString(display[i],window[i],draw[i],40,115, "Select Toppings:",strlen("Select Toppings:")); XDrawString(display[i],window[i],draw[i],240,115,"Totals:", strlen("Totals:")); XDrawString(display[i],window[i],draw[i],50,155, "Pepperoni:",strlen("Pepperoni:")); XDrawRectangle(display[i],window[i],draw[i],260,144, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,160,peprs, strlen(peprs)); XDrawString(display[i],window[i],draw[i],50,205,"Cheese:", strlen("Cheese:")); XDrawRectangle(display[i],window[i],draw[i],260,194, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,210,cheeses, strlen(cheeses)); XDrawString(display[i],window[i],draw[i],50,255,"Veggies:", strlen("Veggies:")); XDrawRectangle(display[i],window[i],draw[i],260,244, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,260,vegs, strlen(vegs)); XDrawString(display[i],window[i],draw[i],50,305, "Anchovies:",strlen("Anchovies:")); XDrawRectangle(display[i],window[i],draw[i],260,294, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,310,anchs, strlen(anchs)); XDrawLine(display[i],window[i],draw[i],0,360,360,360); } } for (;;) { for(i = 0; i < NC ;i++) { if (closed[i] == FALSE) { for (j = 0; j < NUMBUTTONS; j++) { if (XCheckWindowEvent(display[i], MenuButton[i][j].window, SB_INPUTMASK, &button_event )) HandleButton( i,j, &button_event ); } if (XCheckWindowEvent(display[i],window[i],eventmask,&event)) { switch (event.type) { case Expose: if (closed[i] == FALSE) { XDrawString(display[i],window[i],draw[i],140,30,"GoPizza!", strlen("GoPizza!")); XDrawString(display[i],window[i],draw[i],40,60,"Countdown:", strlen("Countdown:")); XDrawRectangle(display[i],window[i],draw[i],260,49, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,65,votesleft, strlen(votesleft)); XDrawLine(display[i],window[i],draw[i],0,90,360,90); XDrawString(display[i],window[i],draw[i],40,115, "Select Toppings:",strlen("Select Toppings:")); XDrawString(display[i],window[i],draw[i],240,115,"Totals:", strlen("Totals:")); XDrawString(display[i],window[i],draw[i],50,155, "Pepperoni:",strlen("Pepperoni:")); XDrawRectangle(display[i],window[i],draw[i],260,144, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,160,peprs, strlen(peprs)); XDrawString(display[i],window[i],draw[i],50,205,"Cheese:", strlen("Cheese:")); XDrawRectangle(display[i],window[i],draw[i],260,194, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,210,cheeses, strlen(cheeses)); XDrawString(display[i],window[i],draw[i],50,255,"Veggies:", strlen("Veggies:")); XDrawRectangle(display[i],window[i],draw[i],260,244, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,260,vegs, strlen(vegs)); XDrawString(display[i],window[i],draw[i],50,305, "Anchovies:",strlen("Anchovies:")); XDrawRectangle(display[i],window[i],draw[i],260,294, SY_WIDHIG,SY_WIDHIG); XDrawString(display[i],window[i],draw[i],266,310,anchs, strlen(anchs)); XDrawLine(display[i],window[i],draw[i],0,360,360,360); } break; default: break; } } } } } } MakeButton( x, y, w, h, label, fun, i, d, wind) Window wind; int i,d; int w,h; int x,y; /* Where to put it */ char *label; /* What to put in it */ int (*fun)(int i); /* What to do with it*/ { Cursor tempcursor; strncpy( MenuButton[i][d].label, label, SB_LONGLABEL ); MenuButton[i][d].func = fun; MenuButton[i][d].window = XCreateSimpleWindow( display[i], wind, x, y, w, h, 1, fgcolor, bgcolor); XSelectInput( display[i], MenuButton[i][d].window, SB_INPUTMASK ); if (d < 2) tempcursor = XCreateFontCursor( display[i], SQ_CURSOR ); else tempcursor = XCreateFontCursor( display[i], SY_CURSOR ); XDefineCursor( display[i], MenuButton[i][d].window, tempcursor ); setwinattr.backing_store = Always; XChangeWindowAttributes(display[i], MenuButton[i][d].window, CWBackingStore, &setwinattr); XMapWindow( display[i], MenuButton[i][d].window ); } int HandleButton( i, d, event ) int i; int d; XEvent *event; { switch( event->type ) { case Expose: ExposeButton( i,d ); break; case EnterNotify: if (closed[i] == FALSE) { if (d < 2 || d > 5) XDrawRectangle( display[i], MenuButton[i][d].window, draw[i], 1,1, SQ_WIDTH-3, SQ_HEIGHT-3 ); else XDrawRectangle( display[i], MenuButton[i][d].window, draw[i], 1,1, SY_WIDHIG-3, SY_WIDHIG-3 ); } break; case LeaveNotify: ExposeButton( i,d ); break; case ButtonPress: if (d < 2 || d > 5) XDrawRectangle( display[i], MenuButton[i][d].window, draw[i], 0,0, SQ_WIDTH-1,SQ_HEIGHT-1 ); else XDrawRectangle( display[i], MenuButton[i][d].window, draw[i], 0,0, SY_WIDHIG-1,SY_WIDHIG-1 ); break; case ButtonRelease: if (closed[i] == FALSE) { if (event->xmotion.window == MenuButton[i][d].window) { MenuButton[i][d].func(i); if ( closed[i] == FALSE) { ExposeButton(i,d); if (d < 2 || d > 5) XDrawRectangle( display[i], MenuButton[i][d].window, draw[i], 1,1, SQ_WIDTH-3, SQ_HEIGHT-3 ); else XDrawRectangle( display[i], MenuButton[i][d].window, draw[i], 1,1, SY_WIDHIG-3, SY_WIDHIG-3 ); } } } break; default: break; } } ExposeButton( i,d ) int i; int d; { int width, center; if (closed[i] == FALSE) { XClearWindow( display[i], MenuButton[i][d].window); width = XTextWidth( font_info, MenuButton[i][d].label, strlen(MenuButton[i][d].label) ); center = MAX((SY_WIDHIG-width)/2,6); XDrawString(display[i], MenuButton[i][d].window,draw[i], center, font_info->ascent, MenuButton[i][d].label, strlen(MenuButton[i][d].label) ); XFlush(display[i]); } } checkp (int u) { int width, center; if (sent[u] == FALSE) { if ((strcmp(MenuButton[u][2].label, " ")) == 0) { strncpy(MenuButton[u][2].label, "X", SB_LONGLABEL); width = XTextWidth(font_info, MenuButton[u][2].label, strlen(MenuButton[u][2].label)); center = MAX((SY_WIDHIG-width)/2,6); XDrawString(display[u], MenuButton[u][2].window, draw[u], center, font_info->ascent, MenuButton[u][2].label, strlen(MenuButton[u][2].label)); topflags[u][2] = TRUE; } else { strncpy(MenuButton[u][2].label, " ", SB_LONGLABEL); width = XTextWidth(font_info, "X", strlen("X")); center = MAX((SY_WIDHIG-width)/2,6); XDrawString(display[u], MenuButton[u][2].window, erase[u], center, font_info->ascent, "X", strlen("X")); topflags[u][2] = FALSE; } } } checkc (int u) { int width, center; if (sent[u] == FALSE) { if ((strcmp(MenuButton[u][3].label, " ")) == 0) { strncpy(MenuButton[u][3].label, "X", SB_LONGLABEL); width = XTextWidth(font_info, MenuButton[u][3].label, strlen(MenuButton[u][3].label)); center = MAX((SY_WIDHIG-width)/2,6); XDrawString(display[u], MenuButton[u][3].window, draw[u], center, font_info->ascent, MenuButton[u][3].label, strlen(MenuButton[u][3].label)); topflags[u][3] = TRUE; } else { strncpy(MenuButton[u][3].label, " ", SB_LONGLABEL); width = XTextWidth(font_info, "X", strlen("X")); center = MAX((SY_WIDHIG-width)/2,6); XDrawString(display[u], MenuButton[u][3].window, erase[u], center, font_info->ascent, "X", strlen("X")); topflags[u][3] = FALSE; } } } checkv (int u) { int width, center; if (sent[u] == FALSE) { if ((strcmp(MenuButton[u][4].label, " ")) == 0) { strncpy(MenuButton[u][4].label, "X", SB_LONGLABEL); width = XTextWidth(font_info, MenuButton[u][4].label, strlen(MenuButton[u][4].label)); center = MAX((SY_WIDHIG-width)/2,6); XDrawString(display[u], MenuButton[u][4].window, draw[u], center, font_info->ascent, MenuButton[u][4].label, strlen(MenuButton[u][4].label)); topflags[u][4] = TRUE; } else { strncpy(MenuButton[u][4].label, " ", SB_LONGLABEL); width = XTextWidth(font_info, "X", strlen("X")); center = MAX((SY_WIDHIG-width)/2,6); XDrawString(display[u], MenuButton[u][4].window, erase[u], center, font_info->ascent, "X", strlen("X")); topflags[u][4] = FALSE; } } } checka (int u) { int width, center; if (sent[u] == FALSE) { if ((strcmp(MenuButton[u][5].label, " ")) == 0) { strncpy(MenuButton[u][5].label, "X", SB_LONGLABEL); width = XTextWidth(font_info, MenuButton[u][5].label, strlen(MenuButton[u][5].label)); center = MAX((SY_WIDHIG-width)/2,6); XDrawString(display[u], MenuButton[u][5].window, draw[u], center, font_info->ascent, MenuButton[u][5].label, strlen(MenuButton[u][5].label)); topflags[u][5] = TRUE; } else { strncpy(MenuButton[u][5].label, " ", SB_LONGLABEL); width = XTextWidth(font_info, "X", strlen("X")); center = MAX((SY_WIDHIG-width)/2,6); XDrawString(display[u], MenuButton[u][5].window, erase[u], center, font_info->ascent, "X", strlen("X")); topflags[u][5] = FALSE; } } } send (int u) { int i; if (sent[u] == TRUE) { XBell(display[u], 100); XBell(display[u], 100); } else { numresp++; sent[u] = TRUE; for (i = 0; i < NC; i++) { if (closed[i] == FALSE) { XDrawString(display[i], window[i], erase[i], 266, 65, votesleft, strlen(votesleft)); XDrawString(display[i], window[i], erase[i], 266, 160, peprs, strlen(peprs)); XDrawString(display[i], window[i], erase[i], 266, 210, cheeses, strlen(cheeses)); XDrawString(display[i], window[i], erase[i], 266, 260, vegs, strlen(vegs)); XDrawString(display[i], window[i], erase[i], 266, 310, anchs, strlen(anchs)); } } numeaters--; sprintf(votesleft, "%d", numeaters); if (topflags[u][2] == TRUE) { numpeprs++; sprintf(peprs, "%d", numpeprs); } if (topflags[u][3] == TRUE) { numcheeses++; sprintf(cheeses, "%d", numcheeses); } if (topflags[u][4] == TRUE) { numvegs++; sprintf(vegs, "%d", numvegs); } if (topflags[u][5] == TRUE) { numanchs++; sprintf(anchs, "%d", numanchs); } for (i = 0; i < NC; i++) { if (closed[i] == FALSE) { XDrawString(display[i], window[i], draw[i], 266, 65, votesleft, strlen(votesleft)); XDrawString(display[i], window[i], draw[i], 266, 160, peprs, strlen(peprs)); XDrawString(display[i], window[i], draw[i], 266, 210, cheeses, strlen(cheeses)); XDrawString(display[i], window[i], draw[i], 266, 260, vegs, strlen(vegs)); XDrawString(display[i], window[i], draw[i], 266, 310, anchs, strlen(anchs)); } } } } confirm(int u) { int i; cwindow[u] = XCreateSimpleWindow(display[u], root[u], 0, 0, 280, 100, 2, fgcolor, bgcolor); XStoreName(display[u], cwindow[u], "Confirm Quit?"); MakeButton(50, 70, SQ_WIDTH, SQ_HEIGHT, "Yes", Exit, u, 6, cwindow[u]); MakeButton(170, 70, SQ_WIDTH, SQ_HEIGHT, "No", Continue, u, 7, cwindow[u]); XMapWindow(display[u], cwindow[u]); XFlush(display[u]); XSelectInput(display[u], cwindow[u], eventmask); XDrawString(display[u], cwindow[u], draw[u], 20, 30, "Do you really want to quit?", strlen("Do you really want to quit?")); } Exit(int u) { int i; FILE *fp; if (u == 0) { fp = fopen("GoPizza.output", "w"); fprintf(fp, "Number of persons invited: %d\nNumber of persons responded: %d\nPepperoni: %d\nCheese: %d\nVeggies: %d\nAnchovies: %d\n", NC, numresp, numpeprs, numcheeses, numvegs, numanchs); fclose(fp); printf("Hope you enjoy your pizza!\n"); for (i = 0; i < NC - errorcount; i++) { XDestroyWindow(display[i],window[i]); exit(0); } } else { closed[u] = TRUE; XDestroyWindow(display[u], cwindow[u]); XDestroyWindow(display[u], window[u]); if (!sent[u]) { for(i = 0; i < NC; i++) { if(closed[i] == FALSE) { XDrawString(display[i], window[i], erase[i], 266,65, votesleft, strlen(votesleft)); } } numeaters--; sprintf(votesleft, "%d", numeaters); for(i = 0; i < NC; i++) { if(closed[i] == FALSE) { XDrawString(display[i], window[i], draw[i], 266,65, votesleft, strlen(votesleft)); } } } } } Continue(int u) { XUnmapWindow(display[u], cwindow[u]); }