#define GET_STRAT_DEF #define THREADS_H #include "threads.h" #include #include #include #include // these are also defined in vision_simplest.h #define BLACK 0 #define RED 1 #define GREEN 2 #define BLUE 3 #define TIGHTRED 4 #define TIGHTGREEN 5 #define TIGHTBLUE 6 #define NONE 7 #define YELLOW 8 #define WHITE 9 // highlight values for buttons and radios #define LIGHT_HIGHLIGHT 0xe0 #define DARK_HIGHLIGHT 0x70 #define MIDDLE_HIGHLIGHT 0xc0 // background and foreground colors for strings #define STRING_BG_COLOR 0xc0c0c0 #define STRING_FG_COLOR 0x000000 // the x position for a lot of the text #define OFFENSE_X 25 // y positions for various button sections #define O_D_SELECT_Y 30 #define OFFENSES_Y (O_D_SELECT_Y + 80) #define DEFENSES_Y (OFFENSES_Y + 80) #define OPPONENTS_Y (DEFENSES_Y + 80) #define OPPONENTS_Y2 (OPPONENTS_Y + 45) // the x offset for the score #define SCORE_X (OFFENSE_X+100) #define SCORE_Y 460 #define OPP_SCORE_Y (SCORE_Y + 20) #define USE_LML_HEADER #include char hexsfilename[25]; XImage *ximg; void* memArea; Display *dpy; Window w; Pixmap p; GC gc; int fd; // the handle for the thread that runs the robot pthread_t jcontrol_thread; // the thread that runs the robot void *the_thread(void *parameter) { printf("Starting jcontrol!\n"); jcontrol(ssettings); printf("Finishing jcontrol!\n"); } // stops the robot's motors void stop_motors(void) { system("s"); } int main() { int i, tst='u'; char str[40]; // start with no objects numobjs=0; // create and initialize the window MakeWindow(&dpy, &w, &gc, &p, &ElementMap); // button to quit the program btnQuit = createButton(dpy, p, gc, "Quit", OFFENSE_X+100+440, 500, 45, 30, 0, STRING_FG_COLOR, STRING_BG_COLOR); // button to start the robot btnStart = createButton(dpy, p, gc, "Start", OFFENSE_X+100, 500, 100, 30, 1, 0x000000, 0x00ff00); // button to end the robot btnEnd = createButton(dpy, p, gc, "End", OFFENSE_X+100+110, 500, 100, 30, 1, 0x000000, 0xff0000); // button to stop the robot's motors (end just stops the robot's main processing loop btnStopMotors = createButton(dpy, p, gc, "Stop Motors", OFFENSE_X+100+220, 500, 100, 30, 1, STRING_FG_COLOR, STRING_BG_COLOR); // button to tell the robot to perform an RF check btnRFCheck = createButton(dpy, p, gc, "RF Check", OFFENSE_X+100+330, 500, 100, 30, 1, STRING_FG_COLOR, STRING_BG_COLOR); // increment Prometheus's score btnPScoreUp = createButton(dpy, p, gc, "Win++!", OFFENSE_X+100, 400, 100, 30, 6, STRING_FG_COLOR, STRING_BG_COLOR); // increment the opponent's score btnOpScoreUp = createButton(dpy, p, gc, "Loss++!", OFFENSE_X+100+220, 400, 100, 30, 6, STRING_FG_COLOR, STRING_BG_COLOR); // decrement P's and O's scores (just in case you make a mistake) btnPScoreDn = createButton(dpy, p, gc, "Win--!", OFFENSE_X+100+110, 400, 100, 30, 6, STRING_FG_COLOR, STRING_BG_COLOR); btnOpScoreDn = createButton(dpy, p, gc, "Loss--!", OFFENSE_X+100+330, 400, 100, 30, 6, STRING_FG_COLOR, STRING_BG_COLOR); // attack the blue goal radioOffenseYellow = createRadio(dpy, p, gc, "Attack Blue", OFFENSE_X+100, O_D_SELECT_Y, 100, 30, 2, CLICKED, STRING_FG_COLOR, 0xff0000); // defend the blue goal radioDefenseBlue = createRadio(dpy, p, gc, "Defend Blue", OFFENSE_X+100+110, O_D_SELECT_Y, 100, 30, 2, UNCLICKED, STRING_FG_COLOR, 0x0000ff); // attack the yellow goal radioOffenseBlue = createRadio(dpy, p, gc, "Attack Yellow", OFFENSE_X+100+220, O_D_SELECT_Y, 100, 30, 2, UNCLICKED, STRING_FG_COLOR, 0xff0000); // defend the yellow goal radioDefenseYellow = createRadio(dpy, p, gc, "Defend Yellow", OFFENSE_X+100+330, O_D_SELECT_Y, 100, 30, 2, UNCLICKED, STRING_FG_COLOR, 0x0000ff); /////////////////// Set which offensive mode to use ////////////////// drawString(dpy, p, gc, OFFENSE_X, OFFENSES_Y+20, "Offenses:", STRING_FG_COLOR, STRING_BG_COLOR); radioOpenGoalAttack = createRadio(dpy, p, gc, "Open Goal", OFFENSE_X+100, OFFENSES_Y, 100, 30, 3, CLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioBehindBackAttack = createRadio(dpy, p, gc, "Behind the Back", OFFENSE_X+100+110, OFFENSES_Y, 100, 30, 3, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioFakeAttack = createRadio(dpy, p, gc, "Fake", OFFENSE_X+100+220, OFFENSES_Y, 100, 30, 3, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioRicochetAttack = createRadio(dpy, p, gc, "Ricochet", OFFENSE_X+100+330, OFFENSES_Y, 100, 30, 3, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioTrapBallAttack = createRadio(dpy, p, gc, "Trap Ball", OFFENSE_X+100, OFFENSES_Y+40, 100, 30, 3, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioPlayDeadAttack = createRadio(dpy, p, gc, "Wait", OFFENSE_X+100+110, OFFENSES_Y+40, 100, 30, 3, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioFake2Attack = createRadio(dpy, p, gc, "Fake2", OFFENSE_X+100+220, OFFENSES_Y+40, 100, 30, 3, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); /////////////////// Set which defensive mode to use ////////////////// drawString(dpy, p, gc, OFFENSE_X, DEFENSES_Y+20, "Defenses:", STRING_FG_COLOR, STRING_BG_COLOR); radioGoalDefense = createRadio(dpy, p, gc, "Goal", OFFENSE_X+100, DEFENSES_Y, 100, 30, 4, CLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioStayGoalDefense = createRadio(dpy, p, gc, "Stay in Goal", OFFENSE_X+100+110, DEFENSES_Y, 100, 30, 4, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioChargeDefense = createRadio(dpy, p, gc, "Charge", OFFENSE_X+100+220, DEFENSES_Y, 100, 30, 4, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); /////////////////// Set which opponent we're facing //////////////////// drawString(dpy, p, gc, OFFENSE_X, OPPONENTS_Y+20, "Opponents:", STRING_FG_COLOR, STRING_BG_COLOR); radioArizona = createRadio(dpy, p, gc, "Arizona", OFFENSE_X+100, OPPONENTS_Y, 100, 30, 5, CLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioDefiant = createRadio(dpy, p, gc, "Defiant", OFFENSE_X+100+110, OPPONENTS_Y, 100, 30, 5, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioExecutor = createRadio(dpy, p, gc, "Executor", OFFENSE_X+100+220, OPPONENTS_Y, 100, 30, 5, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioHannibal = createRadio(dpy, p, gc, "Hannibal", OFFENSE_X+100+330, OPPONENTS_Y, 100, 30, 5, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioMadmax = createRadio(dpy, p, gc, "Madmax", OFFENSE_X+100, OPPONENTS_Y2, 100, 30, 5, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioTaz = createRadio(dpy, p, gc, "Taz", OFFENSE_X+100+110, OPPONENTS_Y2, 100, 30, 5, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); radioXNor = createRadio(dpy, p, gc, "XNor", OFFENSE_X+100+220, OPPONENTS_Y2, 100, 30, 5, UNCLICKED, STRING_FG_COLOR, STRING_BG_COLOR); // defaults ssettings.openingoffense = 1; ssettings.openingdefense = 0; ssettings.startingattackstrategy = 0; ssettings.startingdefensivestrategy = 0; ssettings.opponent = arizona; ssettings.FLIPBOARD = 1; ssettings.robotcolor = 1; ssettings.score = 0; ssettings.oppscore = 0; ssettings.RFCHECK = 0; drawString(dpy, p, gc, OFFENSE_X, SCORE_Y, "Prometheus:", STRING_FG_COLOR, STRING_BG_COLOR); drawString(dpy, p, gc, OFFENSE_X, OPP_SCORE_Y, "Opponents:", STRING_FG_COLOR, STRING_BG_COLOR); XSetFunction(dpy, gc, GXcopy); sprintf(str,"%d ",ssettings.score); drawString(dpy, p, gc, SCORE_X, SCORE_Y, str, STRING_FG_COLOR, STRING_BG_COLOR); sprintf(str,"%d ",ssettings.oppscore); drawString(dpy, p, gc, SCORE_X, OPP_SCORE_Y, str, STRING_FG_COLOR, STRING_BG_COLOR); // display everything XCopyArea(dpy, p, w, gc, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); XFlush(dpy); // the event loop--most of the processing is done in checkNextEvent(...) for(;;) { // redraw the screen switch(tst) { case 'u': XCopyArea(dpy, p, w, gc, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); XFlush(dpy); break; default: break; } if ((tst=checkNextEvent(dpy,p,gc))=='q') break; } XUnmapWindow(dpy,w); XFreePixmap(dpy,p); close(fd); } void MakeWindow(Display **d, Window *w, GC *g, Drawable *p, int **EMap) { // Open the display *d = XOpenDisplay(0); assert(d); // Create the window *w = XCreateSimpleWindow(*d, DefaultRootWindow(*d), 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0xC0C0C0); *p = XCreatePixmap(*d, *w, SCREEN_WIDTH, SCREEN_HEIGHT, DefaultDepth(*d, DefaultScreen(*d))); // We want to get MapNotify events XSelectInput(*d, *w, StructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); // "Map" the window (that is, make it appear on the screen) XMapWindow(*d, *w); *g = XCreateGC(*d, *p, 0, 0); XStoreName(*d, *w, "Prometheus Startup Interface"); XSetIconName(*d, *w, "Prometheus"); XSetFillStyle(*d, *g, FillSolid); XSetForeground(*d, *g, 0xc0c0c0); XFillRectangle(*d, *p, *g, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); XSetBackground(*d, *g, 0xc0c0c0); XSetForeground(*d, *g, 0x000000); for(;;) { XEvent e; XNextEvent(*d, &e); if (e.type == MapNotify) break; } XClearWindow(*d,*w); *EMap = (int *)malloc(SCREEN_WIDTH*SCREEN_HEIGHT*sizeof(int)); { int c1; for(c1 = 0; c1 < SCREEN_WIDTH*SCREEN_HEIGHT; c1++) (*EMap)[c1] = -1; } } // starts the jcontrol thread void startJThread(void) { pthread_create(&jcontrol_thread, NULL, the_thread, NULL); } // ends the jcontrol thread void endJThread(void) { pthread_cancel(jcontrol_thread); stop_motors(); LeftVelocity = 0; RightVelocity = 0; ssettings.RFCHECK = 0; } // the event handler--does most of the work for the threads program int checkNextEvent(Display *dpy, Drawable p, GC gc) { int x, y; unsigned int er,eg,eb; int i; char str[80]; XEvent e; static int btndown = -1; XNextEvent(dpy, &e); if (e.type == ConfigureNotify) { XConfigureEvent xe = e.xconfigure; x=xe.x; y=xe.y; } else if (e.type == KeyPress) { if (e.xkey.keycode == 24) //"q" pressed; exit program return 'q'; } else { printf("keycode %d pressed\n",e.xkey.keycode); return 'u'; } } else if (e.type == ButtonPress) { // the user pressed a button MyObject* myobj = findobjectat(e.xbutton.x,e.xbutton.y); x=e.xbutton.x; y=e.xbutton.y; if (myobj==(0)) { return; } // btndown keeps track of the last object clicked btndown = myobj->objnum; // if the user clicked on a button or a radio, depress the button or radio if(myobj->objtype==MYBUTTON) { clickButton(myobj,CLICKED); } if(myobj->objtype==MYRADIO) { clickRadio(myobj,CLICKED); } } else if (e.type == ButtonRelease) { // if an object was clicked if(btndown != -1) { // if the object was a button if(objarray[btndown].objtype == MYBUTTON) { // quit the program! if(btndown == btnQuit->objnum) { clickButton(btnQuit,UNCLICKED); return 'q'; } if (btndown==btnStart->objnum) { // start the robot! clickButton(btnStart,UNCLICKED); startJThread(); } else if (btndown==btnEnd->objnum) { // stop the robot! clickButton(btnEnd,UNCLICKED); endJThread(); } else if (btndown==btnStopMotors->objnum) { // stop the robot's motors! (best if the robot is already stopped) clickButton(btnStopMotors,UNCLICKED); stop_motors(); } else if (btndown==btnRFCheck->objnum) { // perform an RF check! clickButton(btnRFCheck,UNCLICKED); ssettings.RFCHECK = 1; startJThread(); } else if (btndown == btnPScoreUp->objnum) { // increment Prometheus's score! char num[10]; clickButton(btnPScoreUp,UNCLICKED); ssettings.score++; sprintf(num,"%d ",ssettings.score); drawString(dpy, p, gc, SCORE_X, SCORE_Y, num, STRING_FG_COLOR, STRING_BG_COLOR); btndown = -1; return 'u'; } else if (btndown == btnOpScoreUp->objnum) { // increment the opponent's score! char num[10]; clickButton(btnOpScoreUp,UNCLICKED); ssettings.oppscore++; sprintf(num,"%d ",ssettings.oppscore); drawString(dpy, p, gc, SCORE_X, OPP_SCORE_Y, num, STRING_FG_COLOR, STRING_BG_COLOR); btndown = -1; return 'u'; } else if (btndown == btnPScoreDn->objnum) { // decrement Prometheus's score! char num[10]; clickButton(btnPScoreDn,UNCLICKED); ssettings.score--; sprintf(num,"%d ",ssettings.score); drawString(dpy, p, gc, SCORE_X, SCORE_Y, num, STRING_FG_COLOR, STRING_BG_COLOR); btndown = -1; return 'u'; } else if (btndown == btnOpScoreDn->objnum) { // decrement the opponent's score! char num[10]; clickButton(btnOpScoreDn,UNCLICKED); ssettings.oppscore--; sprintf(num,"%d ",ssettings.oppscore); drawString(dpy, p, gc, SCORE_X, OPP_SCORE_Y, num, STRING_FG_COLOR, STRING_BG_COLOR); btndown = -1; return 'u'; } } else // if the object was a radio button if (objarray[btndown].objtype == MYRADIO) { if (btndown == radioOffenseYellow->objnum) { ssettings.openingoffense = 1; ssettings.openingdefense = 0; ssettings.FLIPBOARD = 1; ssettings.robotcolor = 1; } else if (btndown == radioDefenseBlue->objnum) { ssettings.openingoffense = 0; ssettings.openingdefense = 1; ssettings.FLIPBOARD = 0; ssettings.robotcolor = 0; } else if (btndown == radioOffenseBlue->objnum) { ssettings.openingoffense = 1; ssettings.openingdefense = 0; ssettings.FLIPBOARD = 0; ssettings.robotcolor = 1; } else if (btndown == radioDefenseYellow->objnum) { ssettings.openingoffense = 0; ssettings.openingdefense = 0; ssettings.FLIPBOARD = 1; ssettings.robotcolor = 0; } else if (btndown == radioOpenGoalAttack->objnum) { ssettings.startingattackstrategy = opengoalattack; } else if (btndown == radioBehindBackAttack->objnum) { ssettings.startingattackstrategy = behindbackattack; } else if (btndown == radioFakeAttack->objnum) { ssettings.startingattackstrategy = fakeattack; } else if (btndown == radioFake2Attack->objnum) { ssettings.startingattackstrategy = fake2attack; } else if (btndown == radioRicochetAttack->objnum) { ssettings.startingattackstrategy = ricochetattack; } else if (btndown == radioTrapBallAttack->objnum) { ssettings.startingattackstrategy = trapballattack; } else if (btndown == radioPlayDeadAttack->objnum) { ssettings.startingattackstrategy = playdeadattack; } else if (btndown == radioGoalDefense->objnum) { ssettings.startingdefensivestrategy = goaldefense; } else if (btndown == radioStayGoalDefense->objnum) { ssettings.startingdefensivestrategy = staygoaldefense; } else if (btndown == radioChargeDefense->objnum) { ssettings.startingdefensivestrategy = chargedefense; } else if (btndown == radioArizona->objnum) { ssettings.opponent = arizona; } else if (btndown == radioDefiant->objnum) { ssettings.opponent = defiant; } else if (btndown == radioExecutor->objnum) { ssettings.opponent = executor; } else if (btndown == radioHannibal->objnum) { ssettings.opponent = hannibal; } else if (btndown == radioMadmax->objnum) { ssettings.opponent = madmax; } else if (btndown == radioTaz->objnum) { ssettings.opponent = taz; } else if (btndown == radioXNor->objnum) { ssettings.opponent = xnor; } } btndown = -1; } } else if (e.type == Expose) { return 'u'; } } // find what object is at location (x,y), if any MyObject* findobjectat(int x, int y) { int i = ElementMap[y*SCREEN_WIDTH+x]; if(i != -1) return &(objarray[i]); else return 0; } // default-set-up the object MyObject* initobject(ObjType objtype, int x, int y, int xs, int ys, int group, int clicked) { int c1,c2; MyObject *myobj = &objarray[numobjs++]; myobj->objtype = objtype; myobj->objnum = numobjs-1; myobj->x = x; myobj->y = y; myobj->xsize = xs; myobj->ysize = ys; myobj->image = NULL; myobj->clicked_image = NULL; myobj->label = NULL; myobj->clicked_status = clicked; myobj->data1a = myobj->data2a = myobj->data3a = 0; myobj->data1b = myobj->data2b = myobj->data3b = -1; myobj->group = group; // fill the element map with this object's number; it's the users responsibility // to make sure that nothing overlaps for(c1 = 0; c1 < ys; c1++) for(c2 = 0; c2 < xs; c2++) ElementMap[(y+c1)*SCREEN_WIDTH+(x+c2)] = numobjs-1; return myobj; } // create a button (imagine!) MyObject* createButton(Display *dpy, Drawable p, GC gc, char* str, int x, int y, int xs, int ys, int group, unsigned fg, unsigned bg) { int tw,c1,c2; unsigned char redmask,greenmask,bluemask; MyObject* myobj; myobj = initobject(MYBUTTON, x, y, xs, ys, group, UNCLICKED); // allocate memory for the image of the button and the clicked image of the button myobj->image = (unsigned char *)malloc(xs*ys*3); myobj->clicked_image = (unsigned char *)malloc(xs*ys*3); if(myobj->image == NULL || myobj->clicked_image == NULL) { printf("Failed to allocate memory!\n"); return 0; } // for setting the button's color redmask = (unsigned char)((bg & 0x00ff0000) >> 16); greenmask = (unsigned char)((bg & 0x0000ff00) >> 8); bluemask = (unsigned char)(bg & 0x000000ff); for(c1 = 0; c1 < ys; c1++) for(c2 = 0; c2 < xs; c2++) { // set the left and top highlights of the button if(c2 < BUTTON_HIGHLIGHT_WIDTH || c1 < BUTTON_HIGHLIGHT_WIDTH) { myobj->image[(c1*xs+c2)*3] = LIGHT_HIGHLIGHT; myobj->image[(c1*xs+c2)*3+1] = LIGHT_HIGHLIGHT; myobj->image[(c1*xs+c2)*3+2] = LIGHT_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3] = DARK_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3+1] = DARK_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3+2] = DARK_HIGHLIGHT; } else // set the right and bottom shadows of the button if(c2 > xs-BUTTON_HIGHLIGHT_WIDTH-1 || c1 > ys-BUTTON_HIGHLIGHT_WIDTH-1) { myobj->image[(c1*xs+c2)*3] = DARK_HIGHLIGHT; myobj->image[(c1*xs+c2)*3+1] = DARK_HIGHLIGHT; myobj->image[(c1*xs+c2)*3+2] = DARK_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3] = LIGHT_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3+1] = LIGHT_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3+2] = LIGHT_HIGHLIGHT; } else { // set the rest of the button color myobj->image[(c1*xs+c2)*3] = MIDDLE_HIGHLIGHT | bluemask; myobj->image[(c1*xs+c2)*3+1] = MIDDLE_HIGHLIGHT | greenmask; myobj->image[(c1*xs+c2)*3+2] = MIDDLE_HIGHLIGHT | redmask; myobj->clicked_image[(c1*xs+c2)*3] = MIDDLE_HIGHLIGHT | bluemask; myobj->clicked_image[(c1*xs+c2)*3+1] = MIDDLE_HIGHLIGHT | greenmask; myobj->clicked_image[(c1*xs+c2)*3+2] = MIDDLE_HIGHLIGHT | redmask; } } // create the XImages of the button and the clicked button myobj->img = XCreateImage(dpy, XDefaultVisual(dpy, XDefaultScreen(dpy)), 24, ZPixmap, 0, myobj->image, xs, ys, 16, 0); myobj->img->bits_per_pixel = 24; myobj->img->bytes_per_line = xs*3; myobj->clckd = XCreateImage(dpy, XDefaultVisual(dpy, XDefaultScreen(dpy)), 24, ZPixmap, 0, myobj->clicked_image, xs, ys, 16, 0); myobj->clckd->bits_per_pixel = 24; myobj->clckd->bytes_per_line = xs*3; myobj->label = str; XPutImage(dpy, p, gc, myobj->img, 0, 0, x, y, xs, ys); XSetForeground(dpy, gc, fg); XSetBackground(dpy, gc, STRING_BG_COLOR | bg); myobj->background = STRING_BG_COLOR | bg; tw=XTextWidth(XQueryFont(dpy,XGContextFromGC(gc)),str,strlen(str)); XDrawImageString(dpy, p, gc, x+xs/2-tw/2, y+ys/2+5, str, strlen(str)); XFlush(dpy); return myobj; } // see the comments in createButton above and replace "button" with "radio" MyObject* createRadio(Display *dpy, Drawable p, GC gc, char* str, int x, int y, int xs, int ys, int group, int clicked, unsigned fg, unsigned bg) { int tw,c1,c2; unsigned char redmask,greenmask,bluemask; MyObject* myobj; myobj = initobject(MYRADIO, x, y, xs, ys, group, clicked); myobj->image = (unsigned char *)malloc(xs*ys*3); myobj->clicked_image = (unsigned char *)malloc(xs*ys*3); if(myobj->image == NULL || myobj->clicked_image == NULL) { printf("Failed to allocate memory!\n"); return 0; } redmask = (unsigned char)((bg & 0x00ff0000) >> 16); greenmask = (unsigned char)((bg & 0x0000ff00) >> 8); bluemask = (unsigned char)(bg & 0x000000ff); for(c1 = 0; c1 < ys; c1++) for(c2 = 0; c2 < xs; c2++) { if(c2 < BUTTON_HIGHLIGHT_WIDTH || c1 < BUTTON_HIGHLIGHT_WIDTH) { myobj->image[(c1*xs+c2)*3] = LIGHT_HIGHLIGHT; myobj->image[(c1*xs+c2)*3+1] = LIGHT_HIGHLIGHT; myobj->image[(c1*xs+c2)*3+2] = LIGHT_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3] = DARK_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3+1] = DARK_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3+2] = DARK_HIGHLIGHT; } else if(c2 > xs-BUTTON_HIGHLIGHT_WIDTH-1 || c1 > ys-BUTTON_HIGHLIGHT_WIDTH-1) { myobj->image[(c1*xs+c2)*3] = DARK_HIGHLIGHT; myobj->image[(c1*xs+c2)*3+1] = DARK_HIGHLIGHT; myobj->image[(c1*xs+c2)*3+2] = DARK_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3] = LIGHT_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3+1] = LIGHT_HIGHLIGHT; myobj->clicked_image[(c1*xs+c2)*3+2] = LIGHT_HIGHLIGHT; } else { myobj->image[(c1*xs+c2)*3] = MIDDLE_HIGHLIGHT | bluemask; myobj->image[(c1*xs+c2)*3+1] = MIDDLE_HIGHLIGHT | greenmask; myobj->image[(c1*xs+c2)*3+2] = MIDDLE_HIGHLIGHT | redmask; myobj->clicked_image[(c1*xs+c2)*3] = MIDDLE_HIGHLIGHT | bluemask; myobj->clicked_image[(c1*xs+c2)*3+1] = MIDDLE_HIGHLIGHT | greenmask; myobj->clicked_image[(c1*xs+c2)*3+2] = MIDDLE_HIGHLIGHT | redmask; } } myobj->img = XCreateImage(dpy, XDefaultVisual(dpy, XDefaultScreen(dpy)), 24, ZPixmap, 0, myobj->image, xs, ys, 16, 0); myobj->img->bits_per_pixel = 24; myobj->img->bytes_per_line = xs*3; myobj->clckd = XCreateImage(dpy, XDefaultVisual(dpy, XDefaultScreen(dpy)), 24, ZPixmap, 0, myobj->clicked_image, xs, ys, 16, 0); myobj->clckd->bits_per_pixel = 24; myobj->clckd->bytes_per_line = xs*3; myobj->label = str; // this is the default radio button in the group... if(clicked == UNCLICKED) XPutImage(dpy, p, gc, myobj->img, 0, 0, x, y, xs, ys); // ...or not else XPutImage(dpy, p, gc, myobj->clckd, 0, 0, x, y, xs, ys); XSetForeground(dpy, gc, fg); XSetBackground(dpy, gc, STRING_BG_COLOR | bg); myobj->background = STRING_BG_COLOR | bg; tw=XTextWidth(XQueryFont(dpy,XGContextFromGC(gc)),str,strlen(str)); XDrawImageString(dpy, p, gc, x+xs/2-tw/2, y+ys/2+5, str, strlen(str)); XFlush(dpy); XSetForeground(dpy, gc, STRING_FG_COLOR); XSetBackground(dpy, gc, STRING_BG_COLOR); return myobj; } // click or unclick the button (in accordance with the value passed into "clicked") void clickButton(MyObject *button,int clicked) { int tw, oldbg; if(clicked == UNCLICKED) { XPutImage(dpy, p, gc, button->img, 0, 0, button->x, button->y, button->xsize, button->ysize); } else { XPutImage(dpy, p, gc, button->clckd, 0, 0, button->x, button->y, button->xsize, button->ysize); } XSetBackground(dpy, gc, button->background); XSetForeground(dpy, gc, STRING_FG_COLOR); tw=XTextWidth(XQueryFont(dpy,XGContextFromGC(gc)),button->label,strlen(button->label)); XDrawImageString(dpy, p, gc, button->x+button->xsize/2-tw/2, button->y+button->ysize/2+5, button->label, strlen(button->label)); XCopyArea(dpy, p, w, gc, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); XFlush(dpy); XSetBackground(dpy, gc, STRING_BG_COLOR); } // click or unclick the radio button (decided by the clicked variable) void clickRadio(MyObject *radio,int clicked) { int tw, c1; if(clicked == UNCLICKED) { // if the radio is to be unclicked, display the unclicked button XPutImage(dpy, p, gc, radio->img, 0, 0, radio->x, radio->y, radio->xsize, radio->ysize); XSetForeground(dpy, gc, STRING_FG_COLOR); tw=XTextWidth(XQueryFont(dpy,XGContextFromGC(gc)),radio->label,strlen(radio->label)); XSetBackground(dpy, gc, radio->background); XDrawImageString(dpy, p, gc, radio->x+radio->xsize/2-tw/2, radio->y+radio->ysize/2+5, radio->label, strlen(radio->label)); XSetBackground(dpy, gc, STRING_BG_COLOR); radio->clicked_status = UNCLICKED; return; } else { // if the radio is to be clicked, find the clicked radio in the group and unclick // it, then display the radio button to be clicked as clicked for(c1 = 0; c1 < numobjs; c1++) { if(objarray[c1].objtype == MYRADIO && objarray[c1].group == radio->group && objarray[c1].clicked_status == CLICKED) clickRadio(&(objarray[c1]),UNCLICKED); } XPutImage(dpy, p, gc, radio->clckd, 0, 0, radio->x, radio->y, radio->xsize, radio->ysize); XSetForeground(dpy, gc, STRING_FG_COLOR); XSetBackground(dpy, gc, radio->background); tw=XTextWidth(XQueryFont(dpy,XGContextFromGC(gc)),radio->label,strlen(radio->label)); XDrawImageString(dpy, p, gc, radio->x+radio->xsize/2-tw/2, radio->y+radio->ysize/2+5, radio->label, strlen(radio->label)); XCopyArea(dpy, p, w, gc, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); XFlush(dpy); XSetBackground(dpy, gc, STRING_BG_COLOR); radio->clicked_status = CLICKED; } } void drawString(Display *dpy, Drawable w, GC gc, int x, int y, char *str, int fg, int bg) { XSetForeground(dpy, gc, fg); XSetBackground(dpy, gc, bg); XDrawImageString(dpy, w, gc, x, y, str, strlen(str)); XFlush(dpy); }