1 /* X include files */
2
3 #include <stdio.h>
4 #include <X11/Xlib.h>
5 #include <X11/Xutil.h>
6 #include <X11/X.h>
7 #include <X11/Xresource.h>
8 #include <strings.h>
9
10 #include "covered.pat"
11 #include "uncovered.pat"
12 #include "gray.pat"
13 #include "uncoveredcolor.pat"
14 #include "mine.pat"
15 #include "highlight.pat"
16 #include "ohno.pat"
17 #include "smiley.pat"
18 #include "shades.pat"
19 #include "marked.pat"
20
21 #include "xmines.h"
22
23 extern int score;
24 extern int height;
25 extern int width;
26
27 char *getenv();
28
29 char fontname[80] = "8x13bold";
30 Display *display;
31 int screen;
32 Window window;
33 Window hswindow = 0;
34 XEvent event;
35 XSizeHints hint;
36 GC gc,hsgc;
37 GC highlightgc;
38 XFontStruct *xfontinfo;
39 KeySym key;
40 Pixmap graypix;
41 Pixmap flagpix;
42 Pixmap minepix;
43 Pixmap boompix;
44 Pixmap ohnopix;
45 Pixmap highpix;
46 Pixmap markpix;
47 Pixmap missmarkpix;
48 Pixmap uncoveredpix;
49 Pixmap coveredpix;
50 Pixmap smileypix;
51 Pixmap patpix[16];
52 XColor exact_def;
53 Colormap cmap;
54 unsigned long foreground, background,patbg,patfg;
55 unsigned long getcolor();
56 char colorname[10][64] =
57 {
58 "white","red","blue","green","yellow","cyan","magenta",
59 "orange","violet"
60 };
61 int depth;
62 int pauseflag = 0;
63 int volume;
64
65 #define SWIDTH 20
66 #define SHEIGHT 20
67 #define BWIDTH 14
68 #define XOFFSET 14
69 #define YOFFSET 80
70 #define BHEIGHT 14
71
72 char DisplayName[256];
73 int showscores = 0;
74
75 typedef struct S_BUTTON
76 {
77 int x,y;
78 int w,h;
79 char name[80];
80 int (*func)();
81 } BUTTON;
82
83 int paws();
84 int quit();
85 int show_high_scores();
86
87 #define NUMBUTTONS 3
88 BUTTON button[NUMBUTTONS] =
89 {
90 {XOFFSET+10*SWIDTH+10,280,40,20,"Scores",show_high_scores},
91 {XOFFSET+10*SWIDTH+10,310,40,20,"Pause",paws},
92 {XOFFSET+10*SWIDTH+10,340,40,20,"Quit",quit}
93 };
94
paws()95 paws()
96 {
97 extern int start_time;
98 static int pause_start;
99 if (pauseflag) {
100 start_time += (time(0) - pause_start);
101 }
102 else {
103 pause_start = time(0);
104 }
105 pauseflag = pauseflag ^ 1;
106 draw_screen();
107 }
108
quit()109 quit()
110 {
111 exit(1);
112 }
113
114 static int opTableEntries = 2;
115 static XrmOptionDescRec opTable[] =
116 {
117 {"-display", ".display", XrmoptionSepArg, (caddr_t) NULL},
118 {"-volume", ".volume", XrmoptionSepArg, (caddr_t) NULL}
119 };
120
121 static XrmDatabase rDB;
122 static XrmDatabase homeDB;
123 static XrmDatabase commandlineDB;
124
parseOptions(argc,argv)125 parseOptions(argc,argv)
126 int argc;
127 char *argv[];
128 {
129 XrmValue value;
130 char *str_type[40];
131 char str[80];
132 char buffer[80];
133 char filename[1024];
134 char *sptr;
135 int i;
136
137 /* Get command line options */
138 XrmParseCommand(&commandlineDB,opTable,opTableEntries, "xmines",
139 &argc, argv);
140 DisplayName[0] = '\0';
141
142 if(XrmGetResource(commandlineDB, "xmines.display",
143 "Xcol.Display", str_type, &value) == True)
144 {
145 strncpy(DisplayName,value.addr,(int) value.size);
146 }
147
148 sptr = getenv("HOME");
149 strncpy(filename,sptr,sizeof(filename));
150 strncat(filename,"/.Xdefaults",sizeof(filename) - strlen(filename));
151 filename[sizeof(filename)-1] = '\0';
152 homeDB = XrmGetFileDatabase(filename);
153 XrmMergeDatabases(homeDB,&rDB);
154 XrmMergeDatabases(commandlineDB,&rDB);
155
156 if(XrmGetResource(rDB, "xcol.volume",
157 "Xcol.Volume", str_type, &value) == True)
158 {
159 strncpy(buffer,value.addr,(int) value.size);
160 buffer[value.size] = '\0';
161 volume = atoi(buffer);
162 if(0 <= volume && volume <= 100)
163 {
164 volume = 2*volume - 100;
165 }
166 }
167 else
168 {
169 volume = 0;
170 }
171 for(i=1; i < 9; i++)
172 {
173 sprintf(str,"xcol.color%1d",i);
174 if(XrmGetResource(rDB, str,
175 "Xcol.Color", str_type, &value) == True)
176 {
177 strncpy(colorname[i],value.addr,(int) value.size);
178 colorname[i][value.size] = '\0';
179 }
180 }
181 }
182
183 char *pixstr[] =
184 {
185 "0","1","2","3","4","5","6","7","8","9","10"
186 };
187
188 int hsdone;
189
XStuff(argc,argv)190 XStuff(argc,argv)
191 int argc;
192 char *argv[];
193 {
194 int i;
195 unsigned long bg;
196
197
198 /* initialization */
199 if(!(display = XOpenDisplay(DisplayName)))
200 {
201 fprintf(stderr,"Error: can't open display\n");
202 exit(1);
203 }
204 screen = DefaultScreen(display);
205 depth = DefaultDepth(display,screen);
206
207 /* default pixel values */
208 cmap = DefaultColormap(display,screen);
209
210 background = WhitePixel(display,screen);
211 foreground = BlackPixel(display,screen);
212 bg = getcolor("gray",background);
213
214 /* default program-specified window position and size */
215 hint.x = 20; hint.y = 30;
216 hint.width = width*SWIDTH+BWIDTH+XOFFSET;
217 hint.height = (height)*SHEIGHT+YOFFSET+BHEIGHT;
218 hint.flags = PPosition | PSize;
219
220 /* window creation */
221 window = XCreateSimpleWindow (display,
222 DefaultRootWindow(display),
223 hint.x, hint.y, hint.width, hint.height,
224 5, foreground, bg);
225 XSetStandardProperties(display, window,"xmines", "xmines",
226 None, argv, argc, &hint);
227
228 /* GC creation and initialization */
229 gc = XCreateGC(display, window, 0, 0);
230 XSetBackground(display, gc, background);
231 XSetForeground(display, gc, foreground);
232 highlightgc = XCreateGC(display, window, 0, 0);
233
234 if((xfontinfo = XLoadQueryFont(display,fontname)) == NULL)
235 {
236 fprintf(stderr,"Can't find font '%s'\n",fontname);
237 xfontinfo = XQueryFont(display,XGContextFromGC(gc));
238 }
239 XSetFont(display,gc,xfontinfo->fid);
240
241 /* input event selection */
242 XSelectInput(display, window,
243 Button1MotionMask | Button2MotionMask | Button3MotionMask |
244 ButtonPressMask | ButtonReleaseMask |
245 KeyPressMask | ExposureMask);
246
247 CreatePixmaps();
248
249 if(depth == 1)
250 {
251 XSetWindowBackgroundPixmap(display,window,graypix);
252 }
253
254 /* window mapping */
255 XMapRaised(display, window);
256 XFlush(display);
257 }
258
CreatePixmaps()259 CreatePixmaps()
260 {
261 int i;
262
263 for(i=0; i < 9; i++)
264 {
265 if(depth != 1)
266 {
267 patbg = getcolor("gray",background);
268 patpix[i] = XCreatePixmapFromBitmapData(display,window,
269 uncoveredcolor_bits,SWIDTH,SHEIGHT,foreground,
270 patbg, depth);
271
272 }
273 else
274 {
275 patpix[i] = XCreatePixmapFromBitmapData(display,window,
276 uncovered_bits,SWIDTH,SHEIGHT,foreground,
277 background, depth);
278 }
279 if(i != 0)
280 {
281 patfg = getcolor(colorname[i],foreground);
282 XSetForeground(display, gc, patfg);
283 XDrawString(display,patpix[i],gc,
284 (SWIDTH-XTextWidth(xfontinfo,pixstr[i],strlen(pixstr[i])))/2,
285 SHEIGHT - ((xfontinfo->ascent+xfontinfo->descent))/2,
286 pixstr[i],1);
287 XSetForeground(display, gc, foreground);
288 }
289 patbg = getcolor("gray",background);
290 missmarkpix = XCreatePixmapFromBitmapData(display,window,
291 mine_bits,SWIDTH,SHEIGHT,foreground,
292 patbg, depth);
293 minepix = XCreatePixmapFromBitmapData(display,window,
294 mine_bits,SWIDTH,SHEIGHT,foreground,
295 patbg, depth);
296 XSetForeground(display, gc, getcolor("red",foreground));
297 XDrawLine(display,missmarkpix,gc,1,1,SWIDTH-2,SHEIGHT-2);
298 XDrawLine(display,missmarkpix,gc,1,SHEIGHT-2,SWIDTH-2,1);
299 XSetForeground(display, gc, foreground);
300 patbg = getcolor("red",foreground);
301 patfg = getcolor("black",background);
302 boompix = XCreatePixmapFromBitmapData(display,window,
303 mine_bits,SWIDTH,SHEIGHT,patfg,
304 patbg, depth);
305 graypix = XCreatePixmapFromBitmapData(display,window,
306 gray_bits,SWIDTH,SHEIGHT,foreground,
307 background, depth);
308 coveredpix = XCreatePixmapFromBitmapData(display,window,
309 covered_bits,SWIDTH,SHEIGHT,foreground,
310 background, depth);
311 if(depth != 1)
312 {
313 XSetForeground(display, gc, getcolor("gray",foreground));
314
315 XFillRectangle(display,coveredpix,gc,2,2,
316 SWIDTH-4,SHEIGHT-4);
317 XSetForeground(display, gc, foreground);
318 }
319 CreateMarked();
320
321 /*
322 highpix = XCreatePixmapFromBitmapData(display,window,
323 highlight_bits,SWIDTH,SHEIGHT,foreground,
324 background, depth);
325 */
326 highpix = patpix[0];
327 ohnopix = XCreatePixmapFromBitmapData(display,window,
328 ohno_bits,SWIDTH,SHEIGHT,foreground,
329 background, depth);
330 smileypix = XCreatePixmapFromBitmapData(display,window,
331 smiley_bits,SWIDTH,SHEIGHT,foreground,
332 background, depth);
333 }
334 }
335
336 XPoint flag[3] =
337 {
338 {11,4},{11,10},{6,7}
339 };
340
341 XPoint base[3] =
342 {
343 {7,16},{16,16},{11,12}
344 };
345
CreateMarked()346 CreateMarked()
347 {
348 GC gc;
349
350 gc = XCreateGC(display, window, 0, 0);
351 XSetBackground(display, gc, background);
352 XSetForeground(display, gc, foreground);
353
354 markpix = XCreatePixmapFromBitmapData(display,window,
355 marked_bits,SWIDTH,SHEIGHT,foreground,
356 background, depth);
357
358 if(depth != 1)
359 {
360 XSetForeground(display, gc, getcolor("gray",foreground));
361
362 XFillRectangle(display,markpix,gc,2,2,
363 SWIDTH-4,SHEIGHT-4);
364 }
365 patfg = getcolor("red",foreground);
366 XSetForeground(display, gc, patfg);
367 XFillPolygon(display,markpix,gc,flag,3,Convex,CoordModeOrigin);
368 XSetForeground(display, gc, foreground);
369 XDrawLine(display,markpix,gc,11,4,11,14);
370 XFillPolygon(display,markpix,gc,base,3,Convex,CoordModeOrigin);
371 }
372
getcolor(s,monocolor)373 unsigned long getcolor(s,monocolor)
374 char *s;
375 unsigned long monocolor;
376 {
377 if(depth != 1)
378 {
379 XParseColor(display,cmap,s,&exact_def);
380 XAllocColor(display,cmap,&exact_def);
381 return exact_def.pixel;
382 }
383 else
384 {
385 return monocolor;
386 }
387 }
388
CheckforEvent()389 CheckforEvent()
390 {
391 while((XPending(display)) || pauseflag)
392 {
393 getXevent();
394 }
395 }
396
getXevent()397 getXevent()
398 {
399 char text[10];
400 int i,j;
401 static int x,y;
402 int newx,newy;
403
404 XNextEvent(display, &event);
405 switch(event.type)
406 {
407 case Expose:
408 if(event.xexpose.window == window)
409 {
410 if(event.xexpose.count == 0)
411 {
412 draw_screen();
413 }
414 }
415 else if(event.xexpose.window == hswindow)
416 {
417 print_scores();
418 }
419 break;
420 case KeyPress:
421 if(event.xkey.window == window && !showscores)
422 {
423 i = XLookupString(&event.xkey, text, 1, &key, 0);
424 keyboard(text[0]);
425 }
426 else if (event.xkey.window == hswindow)
427 {
428 hsdone = 1;
429 }
430 break;
431 case MotionNotify:
432 if(!pauseflag)
433 {
434 newx = (event.xmotion.x-XOFFSET)/SWIDTH;
435 newy = (event.xmotion.y-YOFFSET)/SHEIGHT;
436 if(newx != x || newy != y)
437 {
438
439 if(event.xmotion.state & Button1Mask)
440 {
441 unHighlight(x,y);
442 Highlight(newx,newy);
443 }
444 else if(event.xmotion.state & Button2Mask)
445 {
446 unhighlightInvisible(x,y);
447 highlightInvisible(newx,newy);
448 }
449 x = newx; y = newy;
450 }
451 }
452 break;
453 case ButtonPress:
454 if(event.xkey.window == window && !showscores && !pauseflag)
455 {
456 x = (event.xbutton.x-XOFFSET)/SWIDTH;
457 y = (event.xbutton.y-YOFFSET)/SHEIGHT;
458 if(InArray(x,y))
459 {
460 switch(event.xbutton.button)
461 {
462 case Button1:
463 ohno();
464 Highlight(x,y);
465 break;
466 case Button2:
467 ohno();
468 highlightInvisible(x,y);
469 break;
470 default:
471 break;
472 }
473 }
474 }
475 break;
476 case ButtonRelease:
477 if(event.xkey.window == window && !showscores && !pauseflag)
478 {
479 /*
480 checkbuttons(event.xbutton.x,event.xbutton.y);
481 */
482 x = (event.xbutton.x-XOFFSET)/SWIDTH;
483 y = (event.xbutton.y-YOFFSET)/SHEIGHT;
484 if(InArray(x,y))
485 {
486 switch(event.xbutton.button)
487 {
488 case Button1:
489 Show(x,y);
490 break;
491 case Button2:
492 fillNumbers(x,y);
493 break;
494 case Button3:
495 MarkCell(x,y);
496 break;
497 default:
498 break;
499 }
500 }
501 smiley();
502 }
503 else if (event.xkey.window == hswindow)
504 {
505 hsdone = 1;
506 }
507 break;
508 default:
509 break;
510 }
511 }
512
DrawButton(button)513 DrawButton(button)
514 BUTTON *button;
515 {
516 int yoffset;
517 int xoffset;
518
519 yoffset = (button->h - (xfontinfo->ascent+xfontinfo->descent))/2;
520 yoffset = yoffset+button->y+xfontinfo->ascent+1;
521 xoffset = XTextWidth(xfontinfo,button->name,strlen(button->name));
522 xoffset = button->x+(button->w - xoffset)/2+1;
523 XDrawRectangle(display,window,gc,button->x,button->y,
524 button->w,button->h);
525 XDrawImageString(display,window,gc,xoffset,yoffset,
526 button->name,strlen(button->name));
527
528 }
529
checkbuttons(mx,my)530 checkbuttons(mx,my)
531 {
532 int i;
533
534 for(i=0; i < NUMBUTTONS; i++)
535 {
536 if(button[i].x < mx && mx < button[i].x + button[i].w &&
537 button[i].y < my && my < button[i].y + button[i].h)
538 {
539 button[i].func();
540 }
541 }
542 }
543
show_high_scores(blank)544 show_high_scores(blank)
545 {
546 int i;
547 int tmpflag;
548
549 readScores();
550 tmpflag = pauseflag;
551 if(blank)
552 {
553 pauseflag = 1;
554 }
555 draw_screen();
556 /* window creation */
557 showscores = 1;
558 if (! hswindow) {
559 hswindow = XCreateSimpleWindow (display,
560 DefaultRootWindow(display),
561 0, 0, 200, 300,
562 5, foreground, background);
563 hsgc = XCreateGC(display, hswindow, 0, 0);
564 XSetBackground(display, hsgc, background);
565 XSetForeground(display, hsgc, foreground);
566 XSelectInput(display, hswindow,
567 ButtonPressMask | ButtonReleaseMask |
568 KeyPressMask | ExposureMask);
569 XSetStandardProperties(display, hswindow,
570 "high scores", "high score list",
571 None, NULL, 0, &hint);
572 XMapRaised(display, hswindow);
573 }
574 else {
575 XClearArea(display, hswindow, 0, 0, 200, 300, True);
576 XRaiseWindow(display, hswindow);
577 }
578
579 hsdone = 0;
580 while(!hsdone)
581 {
582 getXevent();
583 }
584 pauseflag = tmpflag;
585 draw_screen();
586 showscores = 0;
587 }
588
draw_screen()589 draw_screen()
590 {
591 int i;
592
593 for(i=0; i < NUMBUTTONS; i++)
594 {
595 /*
596 DrawButton(&button[i]);
597 */
598 }
599 show_score(1);
600 smiley();
601 DrawShadow(0,0,hint.width-1,hint.height-1,3);
602 DrawShadow(XOFFSET-4,10,XOFFSET+width*SWIDTH+3,
603 YOFFSET-10,-3);
604 DrawShadow(XOFFSET-4,YOFFSET-4,XOFFSET+width*SWIDTH+3,
605 YOFFSET+height*SHEIGHT+3,-3);
606 if(pauseflag)
607 {
608 /* keep bill from cheating */
609 XFillRectangle(display,window,gc,XOFFSET-1,YOFFSET-1,
610 width*SWIDTH+1,height*SHEIGHT+1);
611
612 }
613 else
614 {
615 XDrawRectangle(display,window,gc,XOFFSET-1,YOFFSET-1,
616 width*SWIDTH+1,height*SHEIGHT+1);
617 redraw_array();
618 }
619 }
620
DrawShadow(x1,y1,x2,y2,dir)621 DrawShadow(x1,y1,x2,y2,dir)
622 {
623 int i;
624 GC highlightgc,shadowgc;
625
626 highlightgc = XCreateGC(display, window, 0, 0);
627
628 shadowgc = XCreateGC(display, window, 0, 0);
629
630 if(dir < 0)
631 {
632 XSetForeground(display, highlightgc, foreground);
633 XSetForeground(display, shadowgc, background);
634 dir = -dir;
635 }
636 else
637 {
638 XSetForeground(display, shadowgc, foreground);
639 XSetForeground(display, highlightgc, background);
640 }
641
642 for(i=0; i < dir; i++)
643 {
644 XDrawLine(display,window,highlightgc,x1,y1,x1,y2);
645 XDrawLine(display,window,shadowgc,x1,y2,x2,y2);
646 XDrawLine(display,window,shadowgc,x2,y1,x2,y2);
647 XDrawLine(display,window,highlightgc,x1,y1,x2,y1);
648 x1++; x2--; y1++; y2--;
649 }
650 }
651
keyboard(c)652 keyboard(c)
653 int c;
654 {
655 switch(c)
656 {
657 case 'p':
658 paws();
659 break;
660 case 'q':
661 quit();
662 break;
663 default:
664 break;
665 }
666 }
667
redraw_array()668 redraw_array()
669 {
670 int i;
671 int j;
672
673 for(i=0; i <height; i++)
674 {
675 for(j=0; j < width; j++)
676 {
677 DrawCell(j,i);
678 }
679 }
680 }
681
DrawCell(x,y)682 DrawCell(x,y)
683 int x;
684 int y;
685 {
686 int val;
687
688 val = ReadCell(x,y);
689
690 if(InArray(x,y))
691 {
692 if(val < 9)
693 {
694 XDrawCell(x,y,patpix[val]);
695 }
696 else if(val == 10)
697 {
698 XDrawCell(x,y,missmarkpix);
699 }
700 else if(val == 11)
701 {
702 XDrawCell(x,y,boompix);
703 }
704 else if(IsMarked(x,y))
705 {
706 XDrawCell(x,y,markpix);
707 }
708 else if(!IsVisible(x,y))
709 {
710 XDrawCell(x,y,coveredpix);
711 }
712 else if(IsMine(x,y))
713 {
714 XDrawCell(x,y,minepix);
715 }
716 }
717 }
718
ohno()719 ohno()
720 {
721 XCopyArea(display,ohnopix,window,gc,0,0,SWIDTH,SHEIGHT
722 ,(width*SWIDTH)/2+XOFFSET,30);
723 }
724
smiley()725 smiley()
726 {
727 XCopyArea(display,smileypix,window,gc,0,0,SWIDTH,SHEIGHT
728 ,(width*SWIDTH)/2+XOFFSET,30);
729 }
730
DrawHighlight(x,y)731 DrawHighlight(x,y)
732 {
733 if(InArray(x,y))
734 {
735 XCopyArea(display,highpix,window,gc,0,0,SWIDTH,SHEIGHT
736 ,x*SWIDTH+XOFFSET,y*SHEIGHT+YOFFSET);
737 }
738 }
739
XDrawCell(x,y,pixmap)740 XDrawCell(x,y,pixmap)
741 int x,y;
742 Pixmap pixmap;
743 {
744 XCopyArea(display,pixmap,window,gc,0,0,SWIDTH,SHEIGHT
745 ,x*SWIDTH+XOFFSET,y*SHEIGHT+YOFFSET);
746 }
747
show_score(force)748 show_score(force)
749 int force;
750 {
751 char s[10];
752 static int mines = 0;
753 static int score = 1000;
754 int nmines, nscore;
755
756 nmines = getminesleft();
757 nscore = getscore();
758
759 if (nmines != mines || nscore != score || force) {
760 mines = nmines;
761 score = nscore;
762 sprintf(s,"%6d",getminesleft());
763 XDrawImageString(display,window,gc,
764 XOFFSET+10,50,s,strlen(s));
765 sprintf(s,"%6d",getscore());
766 XDrawImageString(display,window,gc,
767 width*SWIDTH+XOFFSET-60,50,s,strlen(s));
768 }
769 }
770
WriteScore(i,s)771 WriteScore(i,s)
772 int i;
773 char *s;
774 {
775 XDrawImageString(display,hswindow,hsgc,10
776 ,i*(xfontinfo->ascent+xfontinfo->descent) +
777 xfontinfo->ascent
778 ,s,strlen(s));
779 }
780