1 /* XDigger  Copyright (C) 1988-99 Alexander Lang.
2 
3 XDigger is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7 
8 XDigger is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License
14 along with this program; see the file COPYING.  If not, write to
15 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
16 
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <signal.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 
27 #include <X11/Xatom.h>
28 #include <X11/Xlib.h>
29 #include <X11/Xutil.h>
30 
31 #include "configure.h"
32 #include "drawpixmaps.h"
33 #include "drawtext.h"
34 #include "highscore.h"
35 #include "icon.h"
36 #include "runlevels.h"
37 #include "title.h"
38 #include "sound.h"
39 #include "xdigger.h"
40 
41 char *level_filename = NULL;
42 int pargc;
43 char **pargv;
44 char progname[256];
45 char *LastArgv = NULL;       /* end of argv */
46 char *display_name = NULL;
47 
48 Atom protocol[1];
49 Display *display;
50 int screen;
51 Window rootwindow, mainwindow, toolswindow = 0;
52 GC gc;
53 XStandardColormap xstandardcolormap;
54 Colormap colormap;
55 int kcf_tuerkis, kcf_gelb, kcf_weiss, kcb_blau, kcb_rot, kcb_tuerkis;
56 int xpmmag = 2, iconmag = 3;
57 Bool vert240 = False;
58 Bool laszlo = False; /* especially for Laszlo (Hi Laszlo!) */
59 int vertvar;
60 Bool iconmove = True;
61 Bool blink = True;
62 Bool use_standardcolor = False;
63 struct itimerval timervalue = {{0, 0},{0, TAKT_LENGTH}};
64 Bool takt = False, icontakt = False;
65 /* Bool sigterm = False; */
66 Bool quit = False, back = False;
67 Bool in_xdigger_idle = False;
68 Bool debug = False;
69 
70 static int signal_list[] = {SIGINT, SIGQUIT, SIGILL, SIGTERM,
71 			    SIGSEGV, 0};
72 
73 int zaehler;
74 
all_done(int s)75 void all_done(int s)
76 {
77   sound_done();
78   if(s == 0)
79     {
80     }
81   else
82     {
83       switch (s)
84       {
85         case SIGILL:
86         case SIGSEGV:
87           /*fprintf(stderr, "Program received signal %d.\n", s);*/
88           psignal(s, progname);
89       }
90     }
91   exit(0);
92 }
93 
ErrorHandler(Display * display,XErrorEvent * xerrorevent)94 int ErrorHandler(Display *display, XErrorEvent *xerrorevent)
95 {
96   char buffer[1024];
97 
98   XGetErrorText(display, xerrorevent->error_code, buffer, sizeof(buffer));
99   fprintf(stderr, "%s: xlib: %s\n", progname, buffer);
100   return 0;
101 }
102 
IOErrorHandler(Display * display)103 int IOErrorHandler(Display *display)
104 {
105   fprintf(stderr, "%s: connection to X server lost.\n", progname);
106   all_done(0);
107   return 0;
108 }
109 
TimerHandler()110 void TimerHandler()
111 {
112   takt = True;
113   signal(SIGALRM, &TimerHandler);
114 
115   if (!in_runlevels || in_LevelEditor)
116     setitimer(ITIMER_REAL, &timervalue ,0);
117 
118   if (++zaehler == STEP_MAX) zaehler = 0;
119   /*if ((zaehler == 1) && iconmove && (!in_handle_icon)) Handle_Icon();*/
120   if (zaehler == 1) icontakt = True;
121 } /* TimerHandler() */
122 
My_USleep(unsigned long usec)123 int My_USleep(unsigned long usec)
124 {
125   fd_set readfds, wrfds, exfds;
126   struct timeval timeout;
127   unsigned long mask;
128   int nfds, nfound;
129 
130   nfds = ConnectionNumber(display);
131   mask = (1 << nfds);
132 
133   readfds.fds_bits[0] = mask;
134   wrfds.fds_bits[0] = exfds.fds_bits[0] = 0;
135 
136   timeout.tv_sec = 0;
137   timeout.tv_usec = usec;
138   nfound = select(nfds, &readfds, &wrfds, &exfds, &timeout);
139   return(nfound);
140 } /* int My_USleep(unsigned long usec) */
141 
XDigger_Idle()142 void XDigger_Idle()
143 {
144   in_xdigger_idle = True;
145   My_USleep(1000);
146   if (icontakt)
147   {
148     icontakt = False;
149     if (iconmove && (!in_handle_icon)) Handle_Icon();
150   }
151   in_xdigger_idle = False;
152 } /* void XDigger_Idle() */
153 
MyRand(int rand_max)154 int MyRand(int rand_max)
155 {
156   int i;
157 
158   i = rand() % rand_max;
159   /* i = ((rand() / RAND_MAX) * rand_max) */
160   return (i);
161 } /* int MyRand(int rand_max) */
162 
File_Exists(char * filename)163 Bool File_Exists(char *filename)
164 {
165   FILE *f;
166 
167   if ((f = fopen(filename, "r")) == NULL) return False;
168   fclose(f);
169   return True;
170 }
171 
Determine_Level_Filename()172 Bool Determine_Level_Filename()
173 {
174   FILE *f;
175 
176   if (level_filename == NULL)
177   {
178     level_filename = malloc(256);
179     strcat(strcpy(level_filename, XDIGGER_LIB_DIR), "/xdigger.level");
180     if ((f = fopen(level_filename, "r")) == NULL)
181     {
182       fprintf(stderr, "%s: can't open %s\n", progname, level_filename);
183       strcpy(level_filename, progname); strcat(level_filename, ".level");
184       fprintf(stderr, "%s: try %s... ", progname, level_filename);
185       if ((f = fopen(level_filename, "r")) == NULL)
186       {
187         fprintf(stderr, "failed.\n");
188         return(False);
189       }
190       else fprintf(stderr, "ok.\n");
191     }
192   }
193   else
194   {
195     if ((f = fopen(level_filename, "r")) == NULL)
196     {
197       fprintf(stderr, "%s: can't open %s\n", progname, level_filename);
198       return(False);
199     }
200   }
201   fclose(f);
202   return(True);
203 }
204 
MakeWindow(int argc,char ** argv)205 void MakeWindow(int argc, char **argv)
206 {
207   XSizeHints main_win_sizehints;
208   XClassHint classhint;
209   int main_win_width, main_win_height;
210 /*   XSetWindowAttributes winattr; */
211 /*   int i; */
212 
213   main_win_width = 320 * xpmmag;
214   main_win_height = (240 + vertvar*16) * xpmmag;
215 
216   display = XOpenDisplay(display_name);
217   if (display == NULL)
218     {
219       if(display_name == NULL)
220 	fprintf(stderr, "%s: can't open display (null)\n", progname);
221       else
222 	fprintf(stderr, "%s: can't open display %s\n", progname, display_name);
223       exit(1);
224     }
225   screen = DefaultScreen(display);
226 
227   rootwindow = DefaultRootWindow(display);
228   mainwindow = XCreateSimpleWindow(display, rootwindow, 0, 0,
229 				   main_win_width, main_win_height,
230 				   border_width,
231 				   WhitePixel(display, screen),
232 				   BlackPixel(display, screen));
233 
234   main_win_sizehints.width = main_win_width;
235   main_win_sizehints.height = main_win_height;
236   main_win_sizehints.min_width = 320; /*main_win_width;*/
237   main_win_sizehints.min_height = (240 + vertvar*16); /*main_win_height;*/
238   /*main_win_sizehints.max_width = main_win_width;*/
239     /*main_win_sizehints.max_height = main_win_height;*/
240   main_win_sizehints.width_inc = 320;
241   main_win_sizehints.height_inc = (240 + vertvar*16);
242   main_win_sizehints.min_aspect.x = 20;
243   main_win_sizehints.min_aspect.y = (15 + vertvar);
244   main_win_sizehints.max_aspect.x = main_win_sizehints.min_aspect.x;
245   main_win_sizehints.max_aspect.y = main_win_sizehints.min_aspect.y;
246   main_win_sizehints.flags = PSize | PMinSize /*| PMaxSize*/ | PResizeInc | PAspect;
247 
248   XSetStandardProperties(display, mainwindow, main_win_title, main_win_title,
249 			 None, argv, argc, &main_win_sizehints);
250   /*XSetWMNormalHints(display, mainwindow, &main_win_sizehints);*/
251   /*winattr.colormap = xstdclrmap.colormap;*/
252   /*XChangeWindowAttributes(display, mainwindow, CWColormap, &winattr);*/
253   classhint.res_name =  "xdigger";
254   classhint.res_class = "XDigger";
255   XSetClassHint(display, mainwindow, &classhint);
256 } /* MakeWindow(int argc, char **argv) */
257 
MakeColorsAndGCs()258 void MakeColorsAndGCs()
259 {
260   XGCValues gcvalues;
261   unsigned long gcvaluemask;
262   XColor color;
263 /*   Status status; */
264 /*   int count; */
265 
266 /*   status = XGetStandardColormap(display, rootwindow, &xstandardcolormap, */
267 /* 				XA_RGB_DEFAULT_MAP); */
268 /*   xstandardcolormap = XAllocStandardColormap(); */
269 /*   xstandardcolormap = NULL; */
270 /*   count = 1; */
271 /*   status = XGetRGBColormaps(display, mainwindow, &xstandardcolormap, &count, */
272 /* 			    XA_RGB_COLOR_MAP); */
273 /*   if (status == 0) */
274 /*     fprintf(stderr, "Can't get standard colormap."); */
275 
276   colormap = DefaultColormap(display, screen);
277   XParseColor(display, colormap, KCF_TUERKIS, &color);
278   XAllocColor(display, colormap, &color);
279   kcf_tuerkis = color.pixel;
280   XParseColor(display, colormap, KCF_GELB, &color);
281   XAllocColor(display, colormap, &color);
282   kcf_gelb = color.pixel;
283   XParseColor(display, colormap, KCF_WEISS, &color);
284   XAllocColor(display, colormap, &color);
285   kcf_weiss = color.pixel;
286   XParseColor(display, colormap, KCB_BLAU, &color);
287   XAllocColor(display, colormap, &color);
288   kcb_blau = color.pixel;
289   XParseColor(display, colormap, KCB_ROT, &color);
290   XAllocColor(display, colormap, &color);
291   kcb_rot = color.pixel;
292   XParseColor(display, colormap, KCB_TUERKIS, &color);
293   XAllocColor(display, colormap, &color);
294   kcb_tuerkis = color.pixel;
295 
296   gcvalues.foreground = WhitePixel(display, screen);
297   gcvalues.background = BlackPixel(display, screen);
298   gcvaluemask = GCForeground | GCBackground;
299   gc = XCreateGC(display, mainwindow, gcvaluemask, &gcvalues);
300 
301   gc_text_values.foreground = 0;
302   gc_text_values.background = 0;
303   gc_text_mask = GCForeground | GCBackground;
304   gc_text = XCreateGC(display, mainwindow, gc_text_mask, &gc_text_values);
305 } /* MakeColorsAndGCs() */
306 
create_audiofiles()307 void create_audiofiles()
308 {
309   int fd;
310 
311   Fill_TonBuffer(TON_AUDIO_LOW, TON_AUDIO_HIGH, TON_AUDIO_RATE, True);
312 
313 #ifdef __FreeBSD__
314   fd = open(XDIGGER_LIB_DIR "/diamond.au", O_CREAT | O_WRONLY);
315 #else
316   fd = open("audio/diamond.au", O_CREAT | O_WRONLY);
317 #endif
318   fchmod(fd, 0644);
319   write(fd, &ton_buffer[TON_DIAMANT], ton_laenge[TON_DIAMANT]+24);
320   close(fd);
321 
322 #ifdef __FreeBSD__
323   fd = open(XDIGGER_LIB_DIR "/stone.au", O_CREAT | O_WRONLY);
324 #else
325   fd = open("audio/stone.au", O_CREAT | O_WRONLY);
326 #endif
327   fchmod(fd, 0644);
328   write(fd, &ton_buffer[TON_STEINE], ton_laenge[TON_STEINE]+24);
329   close(fd);
330 
331 #ifdef __FreeBSD__
332   fd = open(XDIGGER_LIB_DIR "/step.au", O_CREAT | O_WRONLY);
333 #else
334   fd = open("audio/step.au", O_CREAT | O_WRONLY);
335 #endif
336   fchmod(fd, 0644);
337   write(fd, &ton_buffer[TON_SCHRITT], ton_laenge[TON_SCHRITT]+24);
338   close(fd);
339   exit(0);
340 }
341 
Version()342 void Version()
343 {
344   printf("XDigger Version %s\n", VERSION);
345   exit(1);
346 } /* Version() */
347 
Help()348 void Help()
349 {
350   printf("Usage: xdigger [-display display] [-1|2|3|...] [-noblink] [-noiconmove] [-vert240] [-sound ");
351 #ifdef SOUND_DSP_AUDIO
352 #if ( defined(linux) || defined(__FreeBSD__) )
353   printf("dsp|");
354 #endif
355   printf("audio|");
356 #endif
357   printf("xbell|");
358 #ifdef SOUND_RPLAY
359   printf("rplay|");
360 #endif
361 #ifdef SOUND_NAS
362   printf("nas|");
363 #endif
364   printf("auto|off] [-v] [-h]\n");
365   /*printf("       where n is a positive integer (default is 2)\n");*/
366   exit(1);
367 } /* Help() */
368 
main(int argc,char ** argv)369 int main(int argc, char **argv)
370 {
371   int i, m = 0;
372   char c;
373   /*XWMHints wmhints;*/
374 
375   pargc = argc;
376   pargv = argv;
377   strcpy(progname, argv[0]);
378   LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
379 
380   for (i = 1; i < argc; i++)
381   {
382     if (!strcmp(argv[i], "-display")) display_name = argv[++i]; else
383       if ((!strcmp(argv[i], "-s")) ||
384           (!strcmp(argv[i], "-sound")) ||
385           (!strcmp(argv[i], "--sound")))
386           {
387             i++;
388             if(i == argc) Help();
389             if(!strcmp(argv[i], "auto")) sound_device = SD_AUTO; else
390 #ifdef SOUND_RPLAY
391             if(!strcmp(argv[i], "rplay")) sound_device = SD_RPLAY; else
392 #endif
393             if(!strcmp(argv[i], "nas"))
394 #ifdef SOUND_NAS
395               sound_device = SD_NAS; else
396 #else
397             {
398               fprintf(stderr, "%s: edit configure.h and recompile "
399                       "xdigger for NAS-support\n", progname);
400               exit(1);
401             }
402 #endif
403 #ifdef SOUND_DSP_AUDIO
404 #if ( defined(linux) || defined(__FreeBSD__) )
405             if(!strcmp(argv[i], "dsp")) sound_device = SD_DSP; else
406 #endif
407             if(!strcmp(argv[i], "audio")) sound_device = SD_AUDIO; else
408 #endif
409             if(!strcmp(argv[i], "xbell")) sound_device = SD_XBELL; else
410             if(!strcmp(argv[i], "off") ||
411                !strcmp(argv[i], "none")) sound_device = SD_NONE; else Help();
412           } else
413       if (!strcmp(argv[i], "--nosound")) sound_device = SD_NONE; else
414       if (!strcmp(argv[i], "-iconmove") ||
415 	  !strcmp(argv[i], "--iconmove")) iconmove = True; else
416       if (!strcmp(argv[i], "-noiconmove") ||
417 	  !strcmp(argv[i], "--noiconmove")) iconmove = False; else
418       if (!strcmp(argv[i], "-standardcolor") ||
419 	  !strcmp(argv[i], "--standardcolor")) use_standardcolor = True; else
420       if (!strcmp(argv[i], "-vert240") ||
421 	  !strcmp(argv[i], "--vert240")) vert240 = True; else
422       if (!strcmp(argv[i], "-blink") ||
423 	  !strcmp(argv[i], "--blink")) blink = True; else
424       if (!strcmp(argv[i], "-noblink") ||
425 	  !strcmp(argv[i], "--noblink")) blink = False; else
426       if (!strcmp(argv[i], "--laszlo")) laszlo = True; else
427       if ( sscanf(argv[i], "-%d", &m) && (m > 0)) xpmmag = m; else
428       if (!strcmp(argv[i], "-v") ||
429           !strcmp(argv[i], "--version")) Version(); else
430       if (!strcmp(argv[i], "-?") ||
431 	  !strcmp(argv[i], "-h") ||
432 	  !strcmp(argv[i], "--help")) Help(); else
433       if (!strcmp(argv[i], "--create_audiofiles")) create_audiofiles(); else
434       if (!strcmp(argv[i], "-f") ||
435           !strcmp(argv[i], "-levelfilename") ||
436           !strcmp(argv[i], "--levelfilename"))
437         level_filename = strdup(argv[++i]); else
438       if (!strcmp(argv[i], "-d")) debug = True; else
439       if ((argv[i][0] != '-') && (File_Exists(argv[i])))
440         level_filename = strdup(argv[i]);
441     }
442 
443   if (vert240) vertvar = 0; else vertvar = 1;
444   /*if (xpmmag != 2) iconmove = False;*/
445 
446   if (!Determine_Level_Filename()) exit(1);
447 
448   XSetErrorHandler(ErrorHandler);
449   XSetIOErrorHandler(IOErrorHandler);
450   MakeWindow(argc, argv);
451   MakeIconWindow();
452   MakeColorsAndGCs();
453   MakeXPixmaps(True);
454   ClearCharField(BlackPixel(display, screen), False);
455 
456   /*wmhints.icon_pixmap = main_win_icon_pixmap;
457   wmhints.flags = IconPixmapHint;
458   XSetWMHints(display, mainwindow, &wmhints);*/
459 
460   XSelectInput(display, mainwindow, ButtonPressMask | ButtonMotionMask |
461                KeyPressMask | KeyReleaseMask | ExposureMask);
462   XMapRaised(display, mainwindow);
463 
464   protocol[0] = XInternAtom(display, "WM_DELETE_WINDOW", False);
465   XSetWMProtocols(display, mainwindow, protocol, 1);
466 
467   sound_init();
468 
469   /* Timer initialisieren & anstossen */
470   signal(SIGALRM, &TimerHandler);
471   {
472     int i;
473     for(i=0; signal_list[i] != 0; i++)
474       signal(signal_list[i], &all_done);
475   }
476   setitimer(ITIMER_REAL, &timervalue ,0);
477 
478   while (!quit)
479     {
480       c = Title();
481       if (quit) break;
482       if (c == 'p')
483 	{
484 	  RunLevels(1, -1);
485 	  if (quit) break;
486 	  if (!back) HighScore(score);
487 	}
488       if (c == 'l')
489 	{
490 	  ALookAtTheRooms();
491 	  if (quit) break;
492 	}
493       if (c == 'e')
494 	{
495 	  LevelEditor();
496 	  if (quit) break;
497 	}
498     }
499   all_done(0);
500   return 0;
501 } /* main(int argc, char **argv) */
502