|
|
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.