|
|
1.1 ! root 1: ! 2: /** Puzzle ! 3: ** ! 4: ** Don Bennett, HP Labs ! 5: ** ! 6: ** this is the interface code for the puzzle program. ! 7: **/ ! 8: ! 9: #include <stdio.h> ! 10: #include <X11/Xatom.h> ! 11: #include <X11/Xlib.h> ! 12: #include <X11/Xutil.h> ! 13: ! 14: #include "ac.cursor" ! 15: #include "ac_mask" ! 16: ! 17: #define max(x,y) (x>y?x:y) ! 18: #define min(x,y) (x>y?y:x) ! 19: ! 20: #define PUZZLE_BORDER_WIDTH 2 ! 21: ! 22: #define TITLE_WINDOW_HEIGHT 25 ! 23: #define BOUNDARY_HEIGHT 3 ! 24: ! 25: #define BOX_WIDTH 10 ! 26: #define BOX_HEIGHT 10 ! 27: ! 28: #define MIN_TILE_HEIGHT 25 ! 29: #define MIN_TILE_WIDTH 25 ! 30: ! 31: #define MAX_STEPS 1000 ! 32: ! 33: int BoxWidth = BOX_WIDTH; ! 34: int BoxHeight = BOX_HEIGHT; ! 35: ! 36: int PuzzleSize = 4; ! 37: int PuzzleWidth=4, PuzzleHeight=4; ! 38: ! 39: int TileHeight, TileWidth; ! 40: int Tx, Ty; ! 41: int TitleWinHeight, BoundaryHeight, TileWinHeight; ! 42: ! 43: int FgPixel, BgPixel; ! 44: ! 45: Display *dpy; ! 46: int screen; ! 47: GC gc, rect_gc; ! 48: Colormap PuzzleColormap; ! 49: ! 50: typedef struct { ! 51: Window root; ! 52: int x,y; ! 53: u_int width, height; ! 54: u_int border_width; ! 55: u_int depth; ! 56: } WindowGeom; ! 57: ! 58: WindowGeom PuzzleWinInfo; ! 59: ! 60: Window PuzzleRoot, TitleWindow, TileWindow, ! 61: ScrambleWindow, SolveWindow; ! 62: ! 63: char *ProgName; ! 64: ! 65: char *TitleFontName = "8x13"; ! 66: char *TileFontName = "vtbold"; ! 67: ! 68: XFontStruct *TitleFontInfo, ! 69: *TileFontInfo; ! 70: ! 71: extern int OutputLogging; ! 72: extern int *position; ! 73: extern int space_x, space_y; ! 74: ! 75: int UsePicture = 0; ! 76: int UseDisplay = 0; ! 77: char *PictureFileName; ! 78: ! 79: int PictureWidth; ! 80: int PictureHeight; ! 81: Pixmap PicturePixmap; ! 82: ! 83: int MoveSteps; ! 84: int VertStepSize[MAX_STEPS]; ! 85: int HoriStepSize[MAX_STEPS]; ! 86: ! 87: #define LEFT 0 ! 88: #define RIGHT 1 ! 89: #define UP 2 ! 90: #define DOWN 3 ! 91: ! 92: #define indx(x,y) (((y)*PuzzleWidth) + (x)) ! 93: #define isdigit(x) ((x)>= '0' && (x) <= '9') ! 94: ! 95: #define ulx(x,y) ((x)*TileWidth) ! 96: #define llx(x,y) ((x)*TileWidth) ! 97: #define urx(x,y) (((x)+1)*TileWidth - 1) ! 98: #define lrx(x,y) (((x)+1)*TileWidth - 1) ! 99: #define uly(x,y) ((y)*TileHeight) ! 100: #define ury(x,y) ((y)*TileHeight) ! 101: #define lly(x,y) (((y)+1)*TileHeight - 1) ! 102: #define lry(x,y) (((y)+1)*TileHeight - 1) ! 103: ! 104: /* ! 105: * PuzzlePending - XPending entry point fo the other module. ! 106: */ ! 107: ! 108: PuzzlePending() ! 109: { ! 110: return(XPending(dpy)); ! 111: } ! 112: ! 113: /* ! 114: * SetupDisplay - eastablish the connection to the X server. ! 115: */ ! 116: ! 117: SetupDisplay(server) ! 118: char *server; ! 119: { ! 120: dpy = XOpenDisplay(server); ! 121: if (dpy == NULL) { ! 122: fprintf(stderr, "SetupDisplay: can't open display \"%s\"\n",server); ! 123: exit(1); ! 124: } ! 125: screen = DefaultScreen(dpy); ! 126: } ! 127: ! 128: XQueryWindow(window,frame) ! 129: Window window; ! 130: WindowGeom *frame; ! 131: { ! 132: XGetGeometry(dpy, window, ! 133: &(frame->root), ! 134: &(frame->x), &(frame->y), ! 135: &(frame->width), &(frame->height), ! 136: &(frame->border_width), ! 137: &(frame->depth)); ! 138: } ! 139: ! 140: RectSet(W,x,y,w,h,pixel) ! 141: Window W; ! 142: int x,y; ! 143: u_int w,h; ! 144: u_long pixel; ! 145: { ! 146: XSetForeground(dpy, rect_gc, pixel); ! 147: XFillRectangle(dpy, W, rect_gc, x, y, w, h); ! 148: } ! 149: ! 150: MoveArea(W,src_x,src_y,dst_x,dst_y,w,h) ! 151: Window W; ! 152: int src_x, src_y, dst_x, dst_y; ! 153: u_int w, h; ! 154: { ! 155: XCopyArea(dpy,W,W,gc,src_x,src_y,w,h,dst_x,dst_y); ! 156: } ! 157: ! 158: /** RepaintTitle - puts the program title in the title bar **/ ! 159: ! 160: RepaintTitle() ! 161: { ! 162: int Twidth,Theight, Box_x,Box_y; ! 163: ! 164: Twidth = XTextWidth(TitleFontInfo,ProgName,strlen(ProgName)); ! 165: Theight = TitleFontInfo->ascent + TitleFontInfo->descent; ! 166: Tx = (PuzzleWinInfo.width-Twidth)/2; ! 167: Ty = (TitleWinHeight-Theight)/2 + TitleFontInfo->ascent; ! 168: ! 169: XSetFont(dpy, gc, TitleFontInfo->fid); ! 170: XDrawString(dpy, TitleWindow, gc, ! 171: Tx, Ty, ProgName,strlen(ProgName)); ! 172: } ! 173: ! 174: /* ! 175: * RepaintBar - Repaint the bar between the title window and ! 176: * the tile window; ! 177: */ ! 178: RepaintBar() ! 179: { ! 180: XFillRectangle(dpy, PuzzleRoot, gc, ! 181: 0, TitleWinHeight, ! 182: PuzzleWinInfo.width, BoundaryHeight); ! 183: } ! 184: ! 185: /** ! 186: ** RepaintTiles - draw the numbers in the tiles to match the ! 187: ** locations array; ! 188: **/ ! 189: RepaintTiles() ! 190: { ! 191: if (UsePicture) ! 192: RepaintPictureTiles(); ! 193: else ! 194: RepaintNumberTiles(); ! 195: } ! 196: ! 197: RepaintNumberTiles() ! 198: { ! 199: int i,j,counter; ! 200: int width,height; ! 201: int x_offset,y_offset; ! 202: char str[30]; ! 203: ! 204: /** cut the TileWindow into a grid of nxn pieces by inscribing ! 205: ** each rectangle with a black border; ! 206: ** I don't want to use subwindows for each tile so that I can ! 207: ** slide groups of tiles together as a single unit, rather than ! 208: ** being forced to move one tile at a time. ! 209: **/ ! 210: ! 211: #define line(x1,y1,x2,y2) XDrawLine(dpy,TileWindow,gc,(x1),(y1),(x2),(y2)) ! 212: ! 213: #define rect(x,y) (line(ulx(x,y),uly(x,y),urx(x,y),ury(x,y)), \ ! 214: line(urx(x,y),ury(x,y),lrx(x,y),lry(x,y)), \ ! 215: line(lrx(x,y),lry(x,y),llx(x,y),lly(x,y)), \ ! 216: line(llx(x,y),lly(x,y),ulx(x,y),uly(x,y))) ! 217: ! 218: ! 219: for (i=0; i<PuzzleHeight;i++) /** iterate y values **/ ! 220: for(j=0; j<PuzzleWidth; j++) { /** iterate x values **/ ! 221: RectSet(TileWindow,ulx(j,i),uly(j,i),TileWidth,TileHeight,BgPixel); ! 222: rect(j,i); ! 223: } ! 224: height = TileFontInfo->ascent + TileFontInfo->descent; ! 225: y_offset = (TileHeight - height)/2; ! 226: ! 227: XSetFont(dpy, gc, TileFontInfo->fid); ! 228: ! 229: counter = 0; ! 230: for (i=0; i<PuzzleHeight; i++) ! 231: for (j=0; j<PuzzleWidth; j++) { ! 232: if (position[counter] == 0) { ! 233: RectSet(TileWindow,ulx(j,i),uly(j,i), ! 234: TileWidth,TileHeight,FgPixel); ! 235: } ! 236: else { ! 237: sprintf(str,"%d",position[counter]); ! 238: width = XTextWidth(TileFontInfo,str,strlen(str)); ! 239: x_offset = (TileWidth - width)/2; ! 240: XDrawString(dpy, TileWindow, gc, ! 241: ulx(j,i)+x_offset,uly(j,i)+y_offset, ! 242: str,strlen(str)); ! 243: } ! 244: counter++; ! 245: } ! 246: } ! 247: ! 248: RepaintPictureTiles() ! 249: { ! 250: int i, j, counter; ! 251: int tmp, orig_x,orig_y; ! 252: ! 253: counter = 0; ! 254: for (i=0; i<PuzzleHeight; i++) ! 255: for (j=0; j<PuzzleWidth; j++) { ! 256: if (position[counter] == 0) ! 257: RectSet(TileWindow,ulx(j,i),uly(j,i), ! 258: TileWidth,TileHeight,FgPixel); ! 259: else { ! 260: tmp = position[counter] - 1; ! 261: orig_x = tmp % PuzzleWidth; ! 262: orig_y = tmp / PuzzleWidth; ! 263: ! 264: XCopyArea(dpy,PicturePixmap,TileWindow,gc, ! 265: ulx(orig_x,orig_y), uly(orig_x,orig_y), ! 266: TileWidth, TileHeight, ! 267: ulx(j,i), uly(j,i)); ! 268: } ! 269: counter++; ! 270: } ! 271: ! 272: } ! 273: ! 274: /** ! 275: ** Setup - Perform initial window creation, etc. ! 276: **/ ! 277: ! 278: Setup(server,geom,argc,argv) ! 279: char *server,*geom; ! 280: int argc; ! 281: char *argv[]; ! 282: { ! 283: Cursor ArrowCrossCursor; ! 284: int minwidth, minheight; ! 285: Pixmap VEGsetup(); ! 286: Visual visual; ! 287: XGCValues xgcv; ! 288: XSetWindowAttributes xswa; ! 289: XSizeHints sizehints; ! 290: ! 291: /*******************************************/ ! 292: /** let the puzzle code initialize itself **/ ! 293: /*******************************************/ ! 294: initialize(); ! 295: OutputLogging = 1; ! 296: ! 297: SetupDisplay(server); ! 298: ! 299: FgPixel = BlackPixel(dpy,screen); ! 300: BgPixel = WhitePixel(dpy,screen); ! 301: ! 302: /*****************************************************/ ! 303: /** if we want to use a picture file, initialize it **/ ! 304: /*****************************************************/ ! 305: if (UsePicture) { ! 306: #ifdef UNDEFINED ! 307: /** ! 308: ** This was fun to do back with X10 when you could create ! 309: ** a pixmap from the current display contents; Maybe eventually ! 310: ** I'll do the same with X11. ! 311: **/ ! 312: if (UseDisplay) { ! 313: WindowGeom RootWinInfo; ! 314: int x,y; ! 315: ! 316: x = PUZZLE_BORDER_WIDTH; ! 317: y = TITLE_WINDOW_HEIGHT + BOUNDARY_HEIGHT + PUZZLE_BORDER_WIDTH; ! 318: XQueryWindow(RootWindow(dpy, screen),&RootWinInfo); ! 319: PictureWidth = RootWinInfo.width - x; ! 320: PictureHeight = RootWinInfo.height - y; ! 321: PicturePixmap = XPixmapSave(RootWindow(dpy,screen), ! 322: x,y,PictureWidth,PictureHeight); ! 323: } ! 324: else ! 325: #endif UNDEFINED ! 326: PuzzleColormap = XCreateColormap(dpy,RootWindow(dpy,screen), ! 327: DefaultVisual(dpy,screen),AllocNone); ! 328: PicturePixmap = VEGsetup(PictureFileName,&PictureWidth,&PictureHeight); ! 329: } ! 330: ! 331: if (UsePicture) { ! 332: minwidth = PuzzleWidth; ! 333: minheight = PuzzleHeight + TITLE_WINDOW_HEIGHT + BOUNDARY_HEIGHT; ! 334: } ! 335: else { ! 336: minwidth = MIN_TILE_WIDTH * PuzzleWidth; ! 337: minheight = MIN_TILE_HEIGHT * PuzzleHeight + TITLE_WINDOW_HEIGHT + ! 338: BOUNDARY_HEIGHT; ! 339: } ! 340: ! 341: /*************************************/ ! 342: /** configure the window size hints **/ ! 343: /*************************************/ ! 344: ! 345: { ! 346: int x, y, width, height; ! 347: int flags; ! 348: ! 349: sizehints.flags = PMinSize | PPosition | PSize; ! 350: sizehints.min_width = minwidth; ! 351: sizehints.min_height = minheight; ! 352: sizehints.width = minwidth; ! 353: sizehints.height = minheight; ! 354: sizehints.x = 100; ! 355: sizehints.y = 300; ! 356: ! 357: if(strlen(geom)) { ! 358: flags = XParseGeometry(geom, &x, &y, &width, &height); ! 359: if(WidthValue & flags) { ! 360: sizehints.flags |= USSize; ! 361: if (width > sizehints.min_width) ! 362: sizehints.width = width; ! 363: } ! 364: if(HeightValue & flags) { ! 365: sizehints.flags |= USSize; ! 366: if (height > sizehints.min_height) ! 367: sizehints.height = height; ! 368: } ! 369: if(XValue & flags) { ! 370: if(XNegative & flags) ! 371: x = DisplayWidth(dpy, DefaultScreen(dpy)) + x ! 372: - sizehints.width; ! 373: sizehints.flags |= USPosition; ! 374: sizehints.x = x; ! 375: } ! 376: if(YValue & flags) { ! 377: if(YNegative & flags) ! 378: y = DisplayHeight(dpy, DefaultScreen(dpy)) + y ! 379: -sizehints.height; ! 380: sizehints.flags |= USPosition; ! 381: sizehints.y = y; ! 382: } ! 383: } ! 384: } ! 385: ! 386: /*******************************************************************/ ! 387: /** create the puzzle main window and set its standard properties **/ ! 388: /*******************************************************************/ ! 389: ! 390: xswa.event_mask = ExposureMask; ! 391: visual.visualid = CopyFromParent; ! 392: ! 393: #ifdef UNDEFINED ! 394: PuzzleRoot = XCreateWindow(dpy, RootWindow(dpy,screen), ! 395: sizehints.x, sizehints.y, ! 396: sizehints.width, sizehints.height, ! 397: PUZZLE_BORDER_WIDTH, ! 398: DefaultDepth(dpy,screen), ! 399: InputOutput, ! 400: &visual, ! 401: CWEventMask, &xswa); ! 402: #endif UNDEFINED ! 403: PuzzleRoot = XCreateSimpleWindow(dpy, RootWindow(dpy,screen), ! 404: sizehints.x, sizehints.y, ! 405: sizehints.width, sizehints.height, ! 406: PUZZLE_BORDER_WIDTH, FgPixel,BgPixel); ! 407: ! 408: XSetStandardProperties(dpy, PuzzleRoot,"puzzle","Puzzle", ! 409: None, argv, argc, &sizehints); ! 410: ! 411: xgcv.foreground = FgPixel; ! 412: xgcv.background = BgPixel; ! 413: xgcv.line_width = 1; ! 414: gc = XCreateGC(dpy, PuzzleRoot, ! 415: GCForeground|GCBackground|GCLineWidth, ! 416: &xgcv); ! 417: ! 418: #ifdef UNDEFINED ! 419: /*********************************/ ! 420: /** load the arrow-cross cursor **/ ! 421: /*********************************/ ! 422: ! 423: /** This code really works, but I haven't converted the cursor to the ! 424: ** the new format, so it looks pretty mangled; ! 425: **/ ! 426: { ! 427: Pixmap ACPixmap, ACMask; ! 428: Cursor ACCursor; ! 429: XColor FGcolor, BGcolor; ! 430: ! 431: FGcolor.red = 0; FGcolor.green = 0; FGcolor.blue = 0; ! 432: BGcolor.red = 0xffff; BGcolor.green = 0xffff; BGcolor.blue = 0xffff; ! 433: ! 434: ACPixmap = XCreateBitmapFromData(dpy,RootWindow(dpy,screen), ! 435: arrow_cross_bits, ! 436: arrow_cross_width, arrow_cross_height); ! 437: ACMask = XCreateBitmapFromData(dpy,RootWindow(dpy,screen), ! 438: arrow_cross_mask_bits, ! 439: arrow_cross_width, arrow_cross_height); ! 440: ACCursor = XCreatePixmapCursor(dpy,ACPixmap,ACMask, ! 441: FGcolor,BGcolor, ! 442: 8,8); ! 443: if (ACCursor == NULL) ! 444: error("Unable to store ArrowCrossCursor."); ! 445: ! 446: XDefineCursor(dpy,PuzzleRoot,ACCursor); ! 447: } ! 448: #endif UNDEFINED ! 449: ! 450: /*****************************************/ ! 451: /** allocate the fonts we will be using **/ ! 452: /*****************************************/ ! 453: ! 454: TitleFontInfo = XLoadQueryFont(dpy,TitleFontName); ! 455: TileFontInfo = XLoadQueryFont(dpy,TileFontName); ! 456: ! 457: if (TitleFontInfo == NULL) error("Opening title font.\n"); ! 458: if (TileFontInfo == NULL) error("Opening tile font.\n"); ! 459: ! 460: XQueryWindow(PuzzleRoot,&PuzzleWinInfo); ! 461: Reset(); ! 462: } ! 463: ! 464: static short old_height = -1; ! 465: static short old_width = -1; ! 466: ! 467: SizeChanged() ! 468: { ! 469: XQueryWindow(PuzzleRoot,&PuzzleWinInfo); ! 470: ! 471: if (PuzzleWinInfo.width == old_width && ! 472: PuzzleWinInfo.height == old_height) ! 473: return(0); ! 474: else ! 475: return(1); ! 476: } ! 477: ! 478: Reset() ! 479: { ! 480: int width,height,Box_x,Box_y; ! 481: int i,j; ! 482: int TileBgPixel; ! 483: ! 484: /** TileWindow is that portion of PuzzleRoot that contains ! 485: ** the sliding pieces; ! 486: **/ ! 487: ! 488: if (UsePicture) ! 489: TileBgPixel = BlackPixel(dpy,screen); ! 490: else ! 491: TileBgPixel = WhitePixel(dpy,screen); ! 492: ! 493: XDestroySubwindows(dpy,PuzzleRoot); ! 494: ! 495: old_width = PuzzleWinInfo.width; ! 496: old_height = PuzzleWinInfo.height; ! 497: ! 498: TitleWinHeight = TITLE_WINDOW_HEIGHT; ! 499: BoundaryHeight = BOUNDARY_HEIGHT; ! 500: ! 501: /** fix the dimensions of PuzzleRoot so the height and width ! 502: ** of the TileWindow will work out to be multiples of PuzzleSize; ! 503: **/ ! 504: ! 505: /** If we're dealing with a picture, the tile region can be no larger ! 506: ** than the picture! ! 507: **/ ! 508: ! 509: if (UsePicture) { ! 510: int tmp; ! 511: ! 512: tmp = PuzzleWinInfo.height - TitleWinHeight - BoundaryHeight; ! 513: if (tmp > PictureHeight) ! 514: PuzzleWinInfo.height = PictureHeight+TitleWinHeight+BoundaryHeight; ! 515: if (PuzzleWinInfo.width > PictureWidth) ! 516: PuzzleWinInfo.width = PictureWidth; ! 517: } ! 518: ! 519: TileHeight=(PuzzleWinInfo.height-TitleWinHeight-BoundaryHeight)/PuzzleHeight; ! 520: PuzzleWinInfo.height = TileHeight*PuzzleHeight+TitleWinHeight+BoundaryHeight; ! 521: ! 522: TileWidth = PuzzleWinInfo.width/PuzzleWidth; ! 523: PuzzleWinInfo.width = TileWidth * PuzzleWidth; ! 524: ! 525: /** fixup the size of PuzzleRoot **/ ! 526: ! 527: XResizeWindow(dpy,PuzzleRoot,PuzzleWinInfo.width,PuzzleWinInfo.height); ! 528: TileWinHeight = PuzzleWinInfo.height - TitleWinHeight; ! 529: ! 530: TitleWindow = XCreateSimpleWindow(dpy, PuzzleRoot, ! 531: 0,0, ! 532: PuzzleWinInfo.width, TitleWinHeight, ! 533: 0,0,BgPixel); ! 534: ! 535: TileWindow = XCreateSimpleWindow(dpy, PuzzleRoot, ! 536: 0,TitleWinHeight+BoundaryHeight, ! 537: PuzzleWinInfo.width, TileWinHeight, ! 538: 0,0,TileBgPixel); ! 539: ! 540: rect_gc = XCreateGC(dpy,TileWindow,0,0); ! 541: XCopyGC(dpy, gc, -1, rect_gc); ! 542: ! 543: XMapWindow(dpy,PuzzleRoot); ! 544: XMapWindow(dpy,TitleWindow); ! 545: XMapWindow(dpy,TileWindow); ! 546: ! 547: RepaintBar(); ! 548: RepaintTitle(); ! 549: ! 550: /** locate the two check boxes **/ ! 551: ! 552: Box_x = Tx/2 - BoxWidth/2; ! 553: Box_y = TitleWinHeight/2 - BoxHeight/2; ! 554: ! 555: ScrambleWindow = XCreateSimpleWindow(dpy, TitleWindow, ! 556: Box_x, Box_y, ! 557: BoxWidth, BoxHeight, ! 558: 1,FgPixel,BgPixel); ! 559: ! 560: Box_x = PuzzleWinInfo.width - Box_x - BoxWidth; ! 561: ! 562: SolveWindow = XCreateSimpleWindow(dpy, TitleWindow, ! 563: Box_x,Box_y, ! 564: BoxWidth,BoxHeight, ! 565: 1,FgPixel,BgPixel); ! 566: ! 567: XMapWindow(dpy,ScrambleWindow); ! 568: XMapWindow(dpy,SolveWindow); ! 569: ! 570: XSelectInput(dpy, TitleWindow, ButtonPressMask|ExposureMask); ! 571: XSelectInput(dpy, TileWindow, ButtonPressMask|ExposureMask| ! 572: VisibilityChangeMask); ! 573: XSelectInput(dpy, ScrambleWindow,ButtonPressMask|ExposureMask); ! 574: XSelectInput(dpy, SolveWindow, ButtonPressMask|ExposureMask); ! 575: ! 576: RepaintTiles(); ! 577: CalculateStepsize(); ! 578: XSync(dpy,1); ! 579: } ! 580: ! 581: CalculateStepsize() ! 582: { ! 583: int i, rem; ! 584: int error,sum; ! 585: ! 586: for (i=0; i<MoveSteps; i++) ! 587: VertStepSize[i] = TileHeight/MoveSteps; ! 588: ! 589: rem = TileHeight % MoveSteps; ! 590: error = - MoveSteps/2; ! 591: ! 592: if (rem > 0) ! 593: for (i=0; i<MoveSteps; i++) { ! 594: if (error >= 0) { ! 595: VertStepSize[i]++; ! 596: error -= MoveSteps; ! 597: } ! 598: error += rem; ! 599: } ! 600: ! 601: for (i=0; i<MoveSteps; i++) ! 602: HoriStepSize[i] = TileWidth/MoveSteps; ! 603: ! 604: rem = TileWidth % MoveSteps; ! 605: error = - MoveSteps/2; ! 606: ! 607: if (rem > 0) ! 608: for (i=0; i<MoveSteps; i++) { ! 609: if (error >= 0) { ! 610: HoriStepSize[i]++; ! 611: error -= MoveSteps; ! 612: } ! 613: error += rem; ! 614: } ! 615: ! 616: /** This code is a little screwed up and I don't want to fix it ! 617: ** right now, so just do a little hack to make sure the total ! 618: ** distance comes out right; ! 619: **/ ! 620: ! 621: sum = 0; ! 622: for (i=0; i<MoveSteps; i++) ! 623: sum += HoriStepSize[i]; ! 624: HoriStepSize[0] += TileWidth - sum; ! 625: ! 626: sum = 0; ! 627: for (i=0; i<MoveSteps; i++) ! 628: sum += VertStepSize[i]; ! 629: VertStepSize[0] += TileHeight - sum; ! 630: } ! 631: ! 632: SlidePieces(event) ! 633: XButtonEvent *event; ! 634: { ! 635: int x,y; ! 636: ! 637: x = (*event).x / TileWidth; ! 638: y = (*event).y / TileHeight; ! 639: if (x == space_x || y == space_y) ! 640: move_space_to(indx(x,y)); ! 641: } ! 642: ! 643: ProcessButton(event) ! 644: XButtonEvent *event; ! 645: { ! 646: Window w; ! 647: ! 648: /* printf("state: 0x%-4x\n",event->state); */ ! 649: w = event->window; ! 650: if (w == TileWindow) { ! 651: if (SolvingStatus()) ! 652: AbortSolving(); ! 653: else ! 654: SlidePieces(event); ! 655: } ! 656: else if (w == ScrambleWindow) { ! 657: AbortSolving(); ! 658: Scramble(); ! 659: RepaintTiles(); ! 660: } ! 661: else if (w == SolveWindow) ! 662: Solve(); ! 663: else if (w == TitleWindow) /* && (*event).state == MiddleButton) */ ! 664: exit(0); ! 665: } ! 666: ! 667: ProcessEvents() ! 668: { ! 669: XEvent event; ! 670: ! 671: while(XPending(dpy)) { ! 672: XNextEvent(dpy,&event); ! 673: ProcessEvent(&event); ! 674: } ! 675: } ! 676: ! 677: ProcessInput() ! 678: { ! 679: XEvent event; ! 680: ! 681: while(1) { ! 682: XNextEvent(dpy, &event); ! 683: ProcessEvent(&event); ! 684: } ! 685: } ! 686: ! 687: ProcessEvent(event) ! 688: XEvent *event; ! 689: { ! 690: /* printf("type: %d\n",event->type); */ ! 691: ! 692: switch(event->type) { ! 693: case ButtonPress: ProcessButton(event); ! 694: break; ! 695: case Expose: if (SizeChanged()) ! 696: Reset(); ! 697: else { ! 698: if (event->xany.window == TitleWindow) ! 699: RepaintTitle(); ! 700: else if (event->xany.window == TileWindow) ! 701: RepaintTiles(); ! 702: else if (event->xany.window == PuzzleRoot) ! 703: RepaintBar(); ! 704: } ! 705: break; ! 706: #ifdef UNDEFINED ! 707: case Visibility: ! 708: RedrawWindows(); ! 709: break; ! 710: #endif ! 711: default: break; ! 712: } ! 713: } ! 714: ! 715: main(argc,argv) ! 716: int argc; ! 717: char *argv[]; ! 718: { ! 719: int i, count; ! 720: char *ServerName, *Geometry; ! 721: ! 722: ServerName = ""; ! 723: Geometry = ""; ! 724: MoveSteps = 1; ! 725: ! 726: ProgName = argv[0]; ! 727: ! 728: /********************************/ ! 729: /** parse command line options **/ ! 730: /********************************/ ! 731: ! 732: for (i=1; i<argc; i++) { ! 733: if (argv[i][0] == '=') ! 734: Geometry = argv[i]; ! 735: else if (strchr(argv[i],':') != NULL) ! 736: ServerName = argv[i]; ! 737: else if (strchr(argv[i],'x') != NULL) { ! 738: sscanf(argv[i],"%dx%d",&PuzzleWidth,&PuzzleHeight); ! 739: if (PuzzleWidth<4 || PuzzleHeight<4) { ! 740: printf("Puzzle size must be at least 4x4.\n"); ! 741: exit(1); ! 742: } ! 743: PuzzleSize = min((PuzzleWidth/2)*2,(PuzzleHeight/2)*2); ! 744: } ! 745: else if (strncmp(argv[i],"-s",2) == 0) { ! 746: count = sscanf(&(argv[i][2]),"%d",&MoveSteps); ! 747: if (count != 1) usage(ProgName); ! 748: if (MoveSteps > MAX_STEPS) { ! 749: fprintf(stderr,"max steps=%d\n",MAX_STEPS); ! 750: exit(1); ! 751: } ! 752: } ! 753: else if (strncmp(argv[i],"-p",2) == 0) { ! 754: if (argv[i][2] == 0) { ! 755: UseDisplay++; ! 756: UsePicture++; ! 757: } ! 758: else { ! 759: UsePicture++; ! 760: PictureFileName = &(argv[i][2]); ! 761: } ! 762: } ! 763: else if (isdigit(argv[i][0])) { ! 764: sscanf(argv[i],"%d",&PuzzleSize); ! 765: if (PuzzleSize<4) { ! 766: printf("Puzzle size must be at least 4x4.\n"); ! 767: exit(1); ! 768: } ! 769: PuzzleWidth = PuzzleSize; ! 770: PuzzleHeight = PuzzleSize; ! 771: PuzzleSize = (PuzzleSize/2) * 2; ! 772: } ! 773: else ! 774: usage(ProgName); ! 775: } ! 776: ! 777: Setup(ServerName,Geometry,argc,argv); ! 778: ProcessInput(); ! 779: } ! 780: ! 781: usage(name) ! 782: char *name; ! 783: { ! 784: fprintf(stderr,"usage: %s [geometry] [display] [size]\n", name); ! 785: fprintf(stderr," [-s<move-steps>] [-p<picture-file>]\n"); ! 786: exit(1); ! 787: } ! 788: ! 789: error(str) ! 790: char *str; ! 791: { ! 792: fprintf(stderr,"Error %s\n",str); ! 793: exit(1); ! 794: } ! 795: ! 796: LogMoveSpace(first_x,first_y,last_x,last_y,dir) ! 797: int first_x,first_y,last_x,last_y,dir; ! 798: { ! 799: int min_x,min_y,max_x,max_y; ! 800: int x,y,w,h,dx,dy,x2,y2; ! 801: int i, clear_x, clear_y; ! 802: ! 803: ! 804: max_x = max(first_x,last_x); ! 805: min_x = min(first_x,last_x); ! 806: max_y = max(first_y,last_y); ! 807: min_y = min(first_y,last_y); ! 808: ! 809: x = ulx(min_x,0); ! 810: y = uly(0,min_y); ! 811: w = (max_x - min_x + 1)*TileWidth; ! 812: h = (max_y - min_y + 1)*TileHeight; ! 813: ! 814: dx = x; ! 815: dy = y; ! 816: ! 817: x2 = x; ! 818: y2 = y; ! 819: ! 820: switch(dir) { ! 821: case UP: clear_x = llx(max_x,0); ! 822: clear_y = lly(0,max_y) + 1; ! 823: ! 824: for (i=0; i<MoveSteps; i++) { ! 825: dy = VertStepSize[i]; ! 826: y2 = y - dy; ! 827: clear_y -= dy; ! 828: ! 829: MoveArea(TileWindow,x,y,x2,y2,w,h); ! 830: RectSet(TileWindow,clear_x,clear_y, ! 831: TileWidth,dy,FgPixel); ! 832: y -= dy; ! 833: } ! 834: break; ! 835: case DOWN: clear_x = llx(max_x,0); ! 836: clear_y = uly(0,min_y); ! 837: ! 838: for (i=0; i<MoveSteps; i++) { ! 839: dy = VertStepSize[i]; ! 840: y2 = y + dy; ! 841: ! 842: MoveArea(TileWindow,x,y,x2,y2,w,h); ! 843: RectSet(TileWindow,clear_x,clear_y, ! 844: TileWidth,dy,FgPixel); ! 845: y += dy; ! 846: clear_y += dy; ! 847: } ! 848: break; ! 849: case LEFT: clear_x = urx(max_x,0) + 1; ! 850: clear_y = ury(0,max_y); ! 851: ! 852: for (i=0; i<MoveSteps; i++) { ! 853: dx = HoriStepSize[i]; ! 854: x2 = x - dx; ! 855: clear_x -= dx; ! 856: ! 857: MoveArea(TileWindow,x,y,x2,y2,w,h); ! 858: RectSet(TileWindow,clear_x,clear_y, ! 859: dx,TileHeight,FgPixel); ! 860: x -= dx; ! 861: } ! 862: break; ! 863: case RIGHT: clear_x = ulx(min_x,0); ! 864: clear_y = uly(0,max_y); ! 865: ! 866: for (i=0; i<MoveSteps; i++) { ! 867: dx = HoriStepSize[i]; ! 868: x2 = x + dx; ! 869: ! 870: MoveArea(TileWindow,x,y,x2,y2,w,h); ! 871: RectSet(TileWindow,clear_x,clear_y, ! 872: dx,TileHeight,FgPixel); ! 873: x += dx; ! 874: clear_x += dx; ! 875: } ! 876: break; ! 877: } ! 878: ! 879: XFlush(dpy); ! 880: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.