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