rnd-19981025-1
[rocksndiamonds.git] / src / init.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  init.c                                                  *
12 ***********************************************************/
13
14 #include <signal.h>
15
16 #include "init.h"
17 #include "misc.h"
18 #include "sound.h"
19 #include "screens.h"
20 #include "tools.h"
21 #include "files.h"
22 #include "joystick.h"
23 #include "gfxload.h"
24 #include "gifload.h"
25 #include "network.h"
26 #include "netserv.h"
27
28 #ifdef DEBUG
29 /*
30 #define DEBUG_TIMING
31 */
32 #endif
33
34 struct PictureFileInfo
35 {
36   char *picture_filename;
37   boolean picture_with_mask;
38 };
39
40 struct IconFileInfo
41 {
42   char *picture_filename;
43   char *picturemask_filename;
44 };
45
46 static int sound_process_id = 0;
47
48 static void InitLevelAndPlayerInfo(void);
49 static void InitNetworkServer(void);
50 static void InitDisplay(void);
51 static void InitSound(void);
52 static void InitSoundServer(void);
53 static void InitWindow(int, char **);
54 static void InitGfx(void);
55 static void LoadGfx(int, struct PictureFileInfo *);
56 static void InitElementProperties(void);
57
58 void OpenAll(int argc, char *argv[])
59 {
60   if (options.serveronly)
61   {
62     NetworkServer(options.server_port, options.serveronly);
63
64     /* never reached */
65     exit(0);
66   }
67
68   InitLevelAndPlayerInfo();
69
70   InitCounter();
71   InitSound();
72   InitSoundServer();
73   InitJoystick();
74   InitRND(NEW_RANDOMIZE);
75
76   signal(SIGINT, CloseAllAndExit);
77   signal(SIGTERM, CloseAllAndExit);
78
79   InitDisplay();
80   InitWindow(argc, argv);
81
82   XMapWindow(display, window);
83   XFlush(display);
84
85   InitGfx();
86   InitElementProperties();
87
88   DrawMainMenu();
89
90   InitNetworkServer();
91 }
92
93 void InitLevelAndPlayerInfo()
94 {
95   int i;
96
97
98 #if 0
99
100   /* initialize local setup */
101   setup.sound_on = TRUE;
102   setup.sound_loops_on = FALSE;
103   setup.sound_music_on = FALSE;
104   setup.sound_simple_on = FALSE;
105   setup.toons_on = TRUE;
106   setup.direct_draw_on = FALSE;
107   setup.scroll_delay_on = FALSE;
108   setup.soft_scrolling_on = TRUE;
109   setup.fading_on = FALSE;
110   setup.autorecord_on = FALSE;
111   setup.quick_doors = FALSE;
112   for (i=0; i<MAX_PLAYERS; i++)
113   {
114     setup.input[i].use_joystick = FALSE;
115     setup.input[i].joystick_nr = 0;
116     setup.input[i].joy.snap  = (i == 0 ? JOY_BUTTON_1 : 0);
117     setup.input[i].joy.bomb  = (i == 0 ? JOY_BUTTON_2 : 0);
118     setup.input[i].key.left  = (i == 0 ? DEFAULT_KEY_LEFT  : KEY_UNDEFINDED);
119     setup.input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KEY_UNDEFINDED);
120     setup.input[i].key.up    = (i == 0 ? DEFAULT_KEY_UP    : KEY_UNDEFINDED);
121     setup.input[i].key.down  = (i == 0 ? DEFAULT_KEY_DOWN  : KEY_UNDEFINDED);
122     setup.input[i].key.snap  = (i == 0 ? DEFAULT_KEY_SNAP  : KEY_UNDEFINDED);
123     setup.input[i].key.bomb  = (i == 0 ? DEFAULT_KEY_BOMB  : KEY_UNDEFINDED);
124   }
125
126 #endif
127
128
129
130   /* choose default local player */
131   local_player = &stored_player[0];
132
133   if (!LoadLevelInfo())                 /* global level info */
134     Error(ERR_EXIT, NULL);
135
136
137
138   LoadSetup();
139
140
141
142   LoadPlayerInfo(PLAYER_SETUP);         /* global setup info */
143   LoadPlayerInfo(PLAYER_LEVEL);         /* level specific info */
144
145   /* after LoadPlayerInfo(), because it overwrites 'local_player' */
146   for (i=0; i<MAX_PLAYERS; i++)
147   {
148     stored_player[i].connected = FALSE;
149     stored_player[i].local = FALSE;
150   }
151   local_player->connected = TRUE;
152   local_player->local = TRUE;
153 }
154
155 void InitNetworkServer()
156 {
157   int nr_wanted;
158
159   if (!options.network)
160     return;
161
162   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
163
164   if (!ConnectToServer(options.server_host, options.server_port))
165     Error(ERR_EXIT, "cannot connect to multiplayer server");
166
167   SendToServer_Nickname(local_player->alias_name);
168   SendToServer_ProtocolVersion();
169
170   if (nr_wanted)
171     SendToServer_NrWanted(nr_wanted);
172 }
173
174 void InitSound()
175 {
176   int i;
177
178   if (sound_status == SOUND_OFF)
179     return;
180
181 #ifndef MSDOS
182   if (access(sound_device_name,W_OK)<0)
183   {
184     Error(ERR_RETURN, "cannot access sound device - no sounds");
185     sound_status = SOUND_OFF;
186     return;
187   }
188
189   if ((sound_device = open(sound_device_name,O_WRONLY))<0)
190   {
191     Error(ERR_RETURN, "cannot open sound device - no sounds");
192     sound_status = SOUND_OFF;
193     return;
194   }
195
196   close(sound_device);
197   sound_status = SOUND_AVAILABLE;
198
199 #ifdef VOXWARE
200   sound_loops_allowed = TRUE;
201   setup.sound_loops_on = TRUE;
202 #endif
203 #else
204   sound_loops_allowed = TRUE;
205   setup.sound_loops_on = TRUE;
206 #endif
207
208   for(i=0; i<NUM_SOUNDS; i++)
209   {
210 #ifdef MSDOS
211   sprintf(sound_name[i], "%d", i+1);
212 #endif
213     Sound[i].name = sound_name[i];
214     if (!LoadSound(&Sound[i]))
215     {
216       sound_status = SOUND_OFF;
217       return;
218     }
219   }
220 }
221
222 void InitSoundServer()
223 {
224   if (sound_status == SOUND_OFF)
225     return;
226
227 #ifndef MSDOS
228   if (pipe(sound_pipe)<0)
229   {
230     Error(ERR_RETURN, "cannot create pipe - no sounds");
231     sound_status = SOUND_OFF;
232     return;
233   }
234
235   if ((sound_process_id = fork()) < 0)
236   {       
237     Error(ERR_RETURN, "cannot create sound server process - no sounds");
238     sound_status = SOUND_OFF;
239     return;
240   }
241
242   if (!sound_process_id)        /* we are child */
243   {
244     SoundServer();
245
246     /* never reached */
247     exit(0);
248   }
249   else                          /* we are parent */
250     close(sound_pipe[0]);       /* no reading from pipe needed */
251 #else
252   SoundServer();
253 #endif
254 }
255
256 void InitJoystick()
257 {
258   int joystick_nr = setup.input[0].joystick_nr;
259
260   if (global_joystick_status == JOYSTICK_OFF)
261     return;
262
263 #ifndef MSDOS
264   if (access(joystick_device_name[joystick_nr], R_OK) < 0)
265   {
266     Error(ERR_RETURN, "cannot access joystick device '%s'",
267           joystick_device_name[joystick_nr]);
268     joystick_status = JOYSTICK_OFF;
269     return;
270   }
271
272   if ((joystick_device =
273        open(joystick_device_name[joystick_nr], O_RDONLY)) < 0)
274   {
275     Error(ERR_RETURN, "cannot open joystick device '%s'",
276           joystick_device_name[joystick_nr]);
277     joystick_status = JOYSTICK_OFF;
278     return;
279   }
280
281   joystick_status = JOYSTICK_AVAILABLE;
282   LoadJoystickData();
283 #else
284   joystick_status = JOYSTICK_AVAILABLE;
285 #endif
286 }
287
288 void InitDisplay()
289 {
290   XVisualInfo vinfo_template, *vinfo;
291   int num_visuals;
292   unsigned int depth;
293
294   /* connect to X server */
295   if (!(display = XOpenDisplay(options.display_name)))
296     Error(ERR_EXIT, "cannot connect to X server %s",
297           XDisplayName(options.display_name));
298
299   screen = DefaultScreen(display);
300   visual = DefaultVisual(display, screen);
301   depth  = DefaultDepth(display, screen);
302   cmap   = DefaultColormap(display, screen);
303
304   /* look for good enough visual */
305   vinfo_template.screen = screen;
306   vinfo_template.class = (depth == 8 ? PseudoColor : TrueColor);
307   vinfo_template.depth = depth;
308   if ((vinfo = XGetVisualInfo(display, VisualScreenMask | VisualClassMask |
309                               VisualDepthMask, &vinfo_template, &num_visuals)))
310   {
311     visual = vinfo->visual;
312     XFree((void *)vinfo);
313   }
314
315   /* got appropriate visual? */
316   if (depth < 8)
317   {
318     printf("Sorry, displays with less than 8 bits per pixel not supported.\n");
319     exit(-1);
320   }
321   else if ((depth ==8 && visual->class != PseudoColor) ||
322            (depth > 8 && visual->class != TrueColor &&
323             visual->class != DirectColor))
324   {
325     printf("Sorry, cannot get appropriate visual.\n");
326     exit(-1);
327   }
328 }
329
330 void InitWindow(int argc, char *argv[])
331 {
332   unsigned int border_width = 4;
333   Pixmap icon_pixmap, iconmask_pixmap;
334   unsigned int icon_width,icon_height;
335   int icon_hot_x,icon_hot_y;
336   char icon_filename[256];
337   XSizeHints size_hints;
338   XWMHints wm_hints;
339   XClassHint class_hints;
340   XTextProperty windowName, iconName;
341   XGCValues gc_values;
342   unsigned long gc_valuemask;
343   char *window_name = WINDOWTITLE_STRING;
344   char *icon_name = WINDOWTITLE_STRING;
345   long window_event_mask;
346   Atom proto_atom = None, delete_atom = None;
347   int screen_width, screen_height;
348   int win_xpos = WIN_XPOS, win_ypos = WIN_YPOS;
349   unsigned long pen_fg = WhitePixel(display,screen);
350   unsigned long pen_bg = BlackPixel(display,screen);
351
352 #ifndef MSDOS
353   static struct IconFileInfo icon_pic =
354   {
355     "rocks_icon.xbm",
356     "rocks_iconmask.xbm"
357   };
358 #endif
359
360   screen_width = XDisplayWidth(display, screen);
361   screen_height = XDisplayHeight(display, screen);
362
363   width = WIN_XSIZE;
364   height = WIN_YSIZE;
365
366   win_xpos = (screen_width - width) / 2;
367   win_ypos = (screen_height - height) / 2;
368
369   window = XCreateSimpleWindow(display, RootWindow(display, screen),
370                                win_xpos, win_ypos, width, height, border_width,
371                                pen_fg, pen_bg);
372
373 #ifndef MSDOS
374   proto_atom = XInternAtom(display, "WM_PROTOCOLS", FALSE);
375   delete_atom = XInternAtom(display, "WM_DELETE_WINDOW", FALSE);
376   if ((proto_atom != None) && (delete_atom != None))
377     XChangeProperty(display, window, proto_atom, XA_ATOM, 32,
378                     PropModePrepend, (unsigned char *) &delete_atom, 1);
379
380   sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picture_filename);
381   XReadBitmapFile(display,window,icon_filename,
382                   &icon_width,&icon_height,
383                   &icon_pixmap,&icon_hot_x,&icon_hot_y);
384   if (!icon_pixmap)
385     Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
386
387   sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picturemask_filename);
388   XReadBitmapFile(display,window,icon_filename,
389                   &icon_width,&icon_height,
390                   &iconmask_pixmap,&icon_hot_x,&icon_hot_y);
391   if (!iconmask_pixmap)
392     Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
393
394   size_hints.width  = size_hints.min_width  = size_hints.max_width  = width;
395   size_hints.height = size_hints.min_height = size_hints.max_height = height;
396   size_hints.flags = PSize | PMinSize | PMaxSize;
397
398   if (win_xpos || win_ypos)
399   {
400     size_hints.x = win_xpos;
401     size_hints.y = win_ypos;
402     size_hints.flags |= PPosition;
403   }
404
405   if (!XStringListToTextProperty(&window_name, 1, &windowName))
406     Error(ERR_EXIT, "structure allocation for windowName failed");
407
408   if (!XStringListToTextProperty(&icon_name, 1, &iconName))
409     Error(ERR_EXIT, "structure allocation for iconName failed");
410
411   wm_hints.initial_state = NormalState;
412   wm_hints.input = True;
413   wm_hints.icon_pixmap = icon_pixmap;
414   wm_hints.icon_mask = iconmask_pixmap;
415   wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
416
417   class_hints.res_name = program_name;
418   class_hints.res_class = "Rocks'n'Diamonds";
419
420   XSetWMProperties(display, window, &windowName, &iconName, 
421                    argv, argc, &size_hints, &wm_hints, 
422                    &class_hints);
423
424   XFree(windowName.value);
425   XFree(iconName.value);
426
427   /* Select event types wanted */
428   window_event_mask = ExposureMask | StructureNotifyMask | FocusChangeMask |
429                       ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
430                       KeyPressMask | KeyReleaseMask;
431   XSelectInput(display, window, window_event_mask);
432 #endif
433
434   /* create GC for drawing with window depth */
435   gc_values.graphics_exposures = False;
436   gc_values.foreground = pen_bg;
437   gc_values.background = pen_bg;
438   gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
439   gc = XCreateGC(display, window, gc_valuemask, &gc_values);
440 }
441
442 void DrawInitText(char *text, int ypos, int color)
443 {
444   if (display && window && pix[PIX_SMALLFONT])
445   {
446     XFillRectangle(display,window,gc,0,ypos, WIN_XSIZE,FONT2_YSIZE);
447     DrawTextExt(window,gc,(WIN_XSIZE-strlen(text)*FONT2_XSIZE)/2,
448                 ypos,text,FS_SMALL,color);
449     XFlush(display);
450   }
451 }
452
453 void InitGfx()
454 {
455   int i,j;
456   GC copy_clipmask_gc;
457   XGCValues clip_gc_values;
458   unsigned long clip_gc_valuemask;
459
460 #ifdef MSDOS
461   static struct PictureFileInfo pic[NUM_PICTURES] =
462   {
463     { "Screen", TRUE },
464     { "Door",   TRUE },
465     { "Heroes", TRUE },
466     { "Toons",  TRUE },
467     { "Font",   FALSE },
468     { "Font2",  FALSE }
469   }; 
470 #else
471   static struct PictureFileInfo pic[NUM_PICTURES] =
472   {
473     { "RocksScreen",    TRUE },
474     { "RocksDoor",      TRUE },
475     { "RocksHeroes",    TRUE },
476     { "RocksToons",     TRUE },
477     { "RocksFont",      FALSE },
478     { "RocksFont2",     FALSE }
479   }; 
480 #endif
481
482   static struct
483   {
484     int start;
485     int count;
486   }
487   tile_needs_clipping[] =
488   {
489     { GFX_SPIELER1_UP, 4 },
490     { GFX_SPIELER1_DOWN, 4 },
491     { GFX_SPIELER1_LEFT, 4 },
492     { GFX_SPIELER1_RIGHT, 4 },
493     { GFX_SPIELER1_PUSH_LEFT, 4 },
494     { GFX_SPIELER1_PUSH_RIGHT, 4 },
495     { GFX_SPIELER2_UP, 4 },
496     { GFX_SPIELER2_DOWN, 4 },
497     { GFX_SPIELER2_LEFT, 4 },
498     { GFX_SPIELER2_RIGHT, 4 },
499     { GFX_SPIELER2_PUSH_LEFT, 4 },
500     { GFX_SPIELER2_PUSH_RIGHT, 4 },
501     { GFX_SPIELER3_UP, 4 },
502     { GFX_SPIELER3_DOWN, 4 },
503     { GFX_SPIELER3_LEFT, 4 },
504     { GFX_SPIELER3_RIGHT, 4 },
505     { GFX_SPIELER3_PUSH_LEFT, 4 },
506     { GFX_SPIELER3_PUSH_RIGHT, 4 },
507     { GFX_SPIELER4_UP, 4 },
508     { GFX_SPIELER4_DOWN, 4 },
509     { GFX_SPIELER4_LEFT, 4 },
510     { GFX_SPIELER4_RIGHT, 4 },
511     { GFX_SPIELER4_PUSH_LEFT, 4 },
512     { GFX_SPIELER4_PUSH_RIGHT, 4 },
513     { GFX_GEBLUBBER, 4 },
514     { GFX_DYNAMIT, 7 },
515     { GFX_DYNABOMB, 4 },
516     { GFX_EXPLOSION, 8 },
517     { GFX_SOKOBAN_OBJEKT, 1 },
518     { GFX_FUNKELN_BLAU, 3 },
519     { GFX_FUNKELN_WEISS, 3 },
520     { -1, 0 }
521   };
522
523 #ifdef DEBUG_TIMING
524   long count1, count2;
525   count1 = Counter();
526 #endif
527
528   LoadGfx(PIX_SMALLFONT,&pic[PIX_SMALLFONT]);
529   DrawInitText(WINDOWTITLE_STRING,20,FC_YELLOW);
530   DrawInitText(COPYRIGHT_STRING,50,FC_RED);
531 #ifdef MSDOS
532   DrawInitText("MSDOS version done by Guido Schulz",210,FC_BLUE);
533   rest(200);
534 #endif MSDOS
535   DrawInitText("Loading graphics:",120,FC_GREEN);
536
537   for(i=0; i<NUM_PICTURES; i++)
538     if (i != PIX_SMALLFONT)
539       LoadGfx(i,&pic[i]);
540
541 #ifdef DEBUG_TIMING
542   count2 = Counter();
543   printf("SUMMARY: %.2f SECONDS LOADING TIME\n",(float)(count2-count1)/1000.0);
544 #endif
545
546
547   pix[PIX_DB_BACK] = XCreatePixmap(display, window,
548                                    WIN_XSIZE,WIN_YSIZE,
549                                    XDefaultDepth(display,screen));
550   pix[PIX_DB_DOOR] = XCreatePixmap(display, window,
551                                    3*DXSIZE,DYSIZE+VYSIZE,
552                                    XDefaultDepth(display,screen));
553   pix[PIX_DB_FIELD] = XCreatePixmap(display, window,
554                                     FXSIZE,FYSIZE,
555                                     XDefaultDepth(display,screen));
556
557   clip_gc_values.graphics_exposures = False;
558   clip_gc_valuemask = GCGraphicsExposures;
559   copy_clipmask_gc =
560     XCreateGC(display,clipmask[PIX_BACK],clip_gc_valuemask,&clip_gc_values);
561
562   clip_gc_values.graphics_exposures = False;
563   clip_gc_valuemask = GCGraphicsExposures;
564   tile_clip_gc =
565     XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
566
567   /* initialize pixmap array to Pixmap 'None' */
568   for(i=0; i<NUM_TILES; i++)
569     tile_clipmask[i] = None;
570
571   /* create only those clipping Pixmaps we really need */
572   for(i=0; tile_needs_clipping[i].start>=0; i++)
573   {
574     for(j=0; j<tile_needs_clipping[i].count; j++)
575     {
576       int tile = tile_needs_clipping[i].start + j;
577       int graphic = tile;
578       int src_x, src_y;
579       Pixmap src_pixmap;
580
581       if (graphic >= GFX_START_ROCKSSCREEN &&
582           graphic <= GFX_END_ROCKSSCREEN)
583       {
584         src_pixmap = clipmask[PIX_BACK];
585         graphic -= GFX_START_ROCKSSCREEN;
586         src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
587         src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
588       }
589       else if (graphic >= GFX_START_ROCKSHEROES &&
590                graphic <= GFX_END_ROCKSHEROES)
591       {
592         src_pixmap = clipmask[PIX_HEROES];
593         graphic -= GFX_START_ROCKSHEROES;
594         src_x = (graphic % HEROES_PER_LINE) * TILEX;
595         src_y = (graphic / HEROES_PER_LINE) * TILEY;
596       }
597       else if (graphic >= GFX_START_ROCKSFONT &&
598                graphic <= GFX_END_ROCKSFONT)
599       {
600         src_pixmap = clipmask[PIX_BIGFONT];
601         graphic -= GFX_START_ROCKSFONT;
602         src_x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
603         src_y = (graphic / FONT_CHARS_PER_LINE) * TILEY +
604           FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY;
605       }
606       else
607         break;
608
609       tile_clipmask[tile] = XCreatePixmap(display, window, TILEX,TILEY, 1);
610
611       XCopyArea(display,src_pixmap,tile_clipmask[tile],copy_clipmask_gc,
612                 src_x,src_y, TILEX,TILEY, 0,0);
613     }
614   }
615
616   if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR])
617     Error(ERR_EXIT, "cannot create additional pixmaps");
618
619   for(i=0; i<NUM_PIXMAPS; i++)
620   {
621     if (clipmask[i])
622     {
623       clip_gc_values.graphics_exposures = False;
624       clip_gc_values.clip_mask = clipmask[i];
625       clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
626       clip_gc[i] = XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
627     }
628   }
629
630   drawto = backbuffer = pix[PIX_DB_BACK];
631   fieldbuffer = pix[PIX_DB_FIELD];
632   SetDrawtoField(DRAW_BACKBUFFER);
633
634   XCopyArea(display,pix[PIX_BACK],backbuffer,gc,
635             0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
636   XFillRectangle(display,pix[PIX_DB_BACK],gc,
637                  REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
638   XFillRectangle(display,pix[PIX_DB_DOOR],gc,
639                  0,0, 3*DXSIZE,DYSIZE+VYSIZE);
640
641   for(i=0; i<MAX_BUF_XSIZE; i++)
642     for(j=0; j<MAX_BUF_YSIZE; j++)
643       redraw[i][j] = 0;
644   redraw_tiles = 0;
645   redraw_mask = REDRAW_ALL;
646 }
647
648 void LoadGfx(int pos, struct PictureFileInfo *pic)
649 {
650   char basefilename[256];
651   char filename[256];
652
653 #ifdef XPM_INCLUDE_FILE
654   int xpm_err, xbm_err;
655   unsigned int width,height;
656   int hot_x,hot_y;
657   Pixmap shapemask;
658   char *picture_ext = ".xpm";
659   char *picturemask_ext = "Mask.xbm";
660 #else
661   int gif_err;
662   char *picture_ext = ".gif";
663 #endif
664
665 #ifdef DEBUG_TIMING
666   long count1, count2;
667 #endif
668
669   /* Grafik laden */
670   if (pic->picture_filename)
671   {
672     sprintf(basefilename,"%s%s",pic->picture_filename,picture_ext);
673     DrawInitText(basefilename,150,FC_YELLOW);
674     sprintf(filename,"%s/%s",GFX_PATH,basefilename);
675
676 #ifdef MSDOS
677     rest(100);
678 #endif MSDOS
679
680 #ifdef DEBUG_TIMING
681     count1 = Counter();
682 #endif
683
684 #ifdef XPM_INCLUDE_FILE
685
686     xpm_att[pos].valuemask = XpmCloseness;
687     xpm_att[pos].closeness = 20000;
688     xpm_err = XpmReadFileToPixmap(display,window,filename,
689                                   &pix[pos],&shapemask,&xpm_att[pos]);
690
691     switch(xpm_err)
692     {
693       case XpmOpenFailed:
694         Error(ERR_EXIT, "cannot open XPM file '%s'", filename);
695       case XpmFileInvalid:
696         Error(ERR_EXIT, "invalid XPM file '%s'", filename);
697       case XpmNoMemory:
698         Error(ERR_EXIT, "not enough memory for XPM file '%s'", filename);
699       case XpmColorFailed:
700         Error(ERR_EXIT, "cannot get colors for XPM file '%s'", filename);
701       default:
702         break;
703     }
704
705 #ifdef DEBUG_TIMING
706     count2 = Counter();
707     printf("XPM LOADING %s IN %.2f SECONDS\n",
708            filename,(float)(count2-count1)/1000.0);
709 #endif
710
711 #else 
712
713     gif_err = Read_GIF_to_Pixmaps(display, window, filename,
714                                   &pix[pos], &clipmask[pos]);
715
716     switch(gif_err)
717     {
718       case GIF_Success:
719         break;
720       case GIF_OpenFailed:
721         Error(ERR_EXIT, "cannot open GIF file '%s'", filename);
722       case GIF_ReadFailed:
723         Error(ERR_EXIT, "cannot read GIF file '%s'", filename);
724       case GIF_FileInvalid:
725         Error(ERR_EXIT, "invalid GIF file '%s'", filename);
726       case GIF_NoMemory:
727         Error(ERR_EXIT, "not enough memory for GIF file '%s'", filename);
728       case GIF_ColorFailed:
729         Error(ERR_EXIT, "cannot get colors for GIF file '%s'", filename);
730       default:
731         break;
732     }
733
734 #ifdef DEBUG_TIMING
735     count2 = Counter();
736     printf("GIF LOADING %s IN %.2f SECONDS\n",
737            filename,(float)(count2-count1)/1000.0);
738 #endif
739
740 #endif
741
742     if (!pix[pos])
743       Error(ERR_EXIT, "cannot get graphics for '%s'", pic->picture_filename);
744   }
745
746   /* zugehörige Maske laden (wenn vorhanden) */
747   if (pic->picture_with_mask)
748   {
749
750 #ifdef XPM_INCLUDE_FILE
751
752     sprintf(basefilename,"%s%s",pic->picture_filename,picturemask_ext);
753     DrawInitText(basefilename,150,FC_YELLOW);
754     sprintf(filename,"%s/%s",GFX_PATH,basefilename);
755
756 #ifdef DEBUG_TIMING
757     count1 = Counter();
758 #endif
759
760     xbm_err = XReadBitmapFile(display,window,filename,
761                               &width,&height,&clipmask[pos],&hot_x,&hot_y);
762
763     switch(xbm_err)
764     {
765       case BitmapSuccess:
766         break;
767       case BitmapOpenFailed:
768         Error(ERR_EXIT, "cannot open XBM file '%s'", filename);
769       case BitmapFileInvalid:
770         Error(ERR_EXIT, "invalid XBM file '%s'", filename);
771       case BitmapNoMemory:
772         Error(ERR_EXIT, "not enough memory for XBM file '%s'", filename);
773         break;
774       default:
775         break;
776     }
777
778 #ifdef DEBUG_TIMING
779     count2 = Counter();
780     printf("XBM LOADING %s IN %.2f SECONDS\n",
781            filename,(float)(count2-count1)/1000.0);
782 #endif
783
784 #endif
785
786     if (!clipmask[pos])
787       Error(ERR_EXIT, "cannot get clipmask for '%s'", pic->picture_filename);
788   }
789 }
790
791 void InitElementProperties()
792 {
793   int i,j;
794
795   static int ep_amoebalive[] =
796   {
797     EL_AMOEBE_NASS,
798     EL_AMOEBE_NORM,
799     EL_AMOEBE_VOLL,
800     EL_AMOEBE_BD
801   };
802   static int ep_amoebalive_num = sizeof(ep_amoebalive)/sizeof(int);
803
804   static int ep_amoeboid[] =
805   {
806     EL_AMOEBE_TOT,
807     EL_AMOEBE_NASS,
808     EL_AMOEBE_NORM,
809     EL_AMOEBE_VOLL,
810     EL_AMOEBE_BD
811   };
812   static int ep_amoeboid_num = sizeof(ep_amoeboid)/sizeof(int);
813
814   static int ep_schluessel[] =
815   {
816     EL_SCHLUESSEL1,
817     EL_SCHLUESSEL2,
818     EL_SCHLUESSEL3,
819     EL_SCHLUESSEL4
820   };
821   static int ep_schluessel_num = sizeof(ep_schluessel)/sizeof(int);
822
823   static int ep_pforte[] =
824   {
825     EL_PFORTE1,
826     EL_PFORTE2,
827     EL_PFORTE3,
828     EL_PFORTE4,
829     EL_PFORTE1X,
830     EL_PFORTE2X,
831     EL_PFORTE3X,
832     EL_PFORTE4X
833   };
834   static int ep_pforte_num = sizeof(ep_pforte)/sizeof(int);
835
836   static int ep_solid[] =
837   {
838     EL_BETON,
839     EL_MAUERWERK,
840     EL_MAUER_LEBT,
841     EL_MAUER_X,
842     EL_MAUER_Y,
843     EL_MAUER_XY,
844     EL_FELSBODEN,
845     EL_AUSGANG_ZU,
846     EL_AUSGANG_ACT,
847     EL_AUSGANG_AUF,
848     EL_AMOEBE_TOT,
849     EL_AMOEBE_NASS,
850     EL_AMOEBE_NORM,
851     EL_AMOEBE_VOLL,
852     EL_AMOEBE_BD,
853     EL_MORAST_VOLL,
854     EL_MORAST_LEER,
855     EL_SIEB_VOLL,
856     EL_SIEB_LEER,
857     EL_SIEB_TOT,
858     EL_SIEB2_VOLL,
859     EL_SIEB2_LEER,
860     EL_SIEB2_TOT,
861     EL_LIFE,
862     EL_LIFE_ASYNC,
863     EL_BADEWANNE1,
864     EL_BADEWANNE2,
865     EL_BADEWANNE3,
866     EL_BADEWANNE4,
867     EL_BADEWANNE5
868   };
869   static int ep_solid_num = sizeof(ep_solid)/sizeof(int);
870
871   static int ep_massiv[] =
872   {
873     EL_BETON,
874     EL_SALZSAEURE,
875     EL_BADEWANNE1,
876     EL_BADEWANNE2,
877     EL_BADEWANNE3,
878     EL_BADEWANNE4,
879     EL_BADEWANNE5,
880     EL_PFORTE1,
881     EL_PFORTE2,
882     EL_PFORTE3,
883     EL_PFORTE4,
884     EL_PFORTE1X,
885     EL_PFORTE2X,
886     EL_PFORTE3X,
887     EL_PFORTE4X
888   };
889   static int ep_massiv_num = sizeof(ep_massiv)/sizeof(int);
890
891   static int ep_slippery[] =
892   {
893     EL_FELSBODEN,
894     EL_FELSBROCKEN,
895     EL_EDELSTEIN,
896     EL_EDELSTEIN_BD,
897     EL_EDELSTEIN_GELB,
898     EL_EDELSTEIN_ROT,
899     EL_EDELSTEIN_LILA,
900     EL_DIAMANT,
901     EL_BOMBE,
902     EL_KOKOSNUSS,
903     EL_ABLENK_EIN,
904     EL_ABLENK_AUS,
905     EL_ZEIT_VOLL,
906     EL_ZEIT_LEER,
907     EL_BIRNE_EIN,
908     EL_BIRNE_AUS,
909     EL_BADEWANNE1,
910     EL_BADEWANNE2,
911     EL_SONDE
912   };
913   static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int);
914
915   static int ep_enemy[] =
916   {
917     EL_KAEFER,
918     EL_FLIEGER,
919     EL_BUTTERFLY,
920     EL_FIREFLY,
921     EL_MAMPFER,
922     EL_MAMPFER2,
923     EL_ROBOT,
924     EL_PACMAN
925   };
926   static int ep_enemy_num = sizeof(ep_enemy)/sizeof(int);
927
928   static int ep_mauer[] =
929   {
930     EL_BETON,
931     EL_PFORTE1,
932     EL_PFORTE2,
933     EL_PFORTE3,
934     EL_PFORTE4,
935     EL_PFORTE1X,
936     EL_PFORTE2X,
937     EL_PFORTE3X,
938     EL_PFORTE4X,
939     EL_AUSGANG_ZU,
940     EL_AUSGANG_ACT,
941     EL_AUSGANG_AUF,
942     EL_MAUERWERK,
943     EL_FELSBODEN,
944     EL_MAUER_LEBT,
945     EL_MAUER_X,
946     EL_MAUER_Y,
947     EL_MAUER_XY,
948     EL_MAUERND
949   };
950   static int ep_mauer_num = sizeof(ep_mauer)/sizeof(int);
951
952   static int ep_can_fall[] =
953   {
954     EL_FELSBROCKEN,
955     EL_EDELSTEIN,
956     EL_EDELSTEIN_BD,
957     EL_EDELSTEIN_GELB,
958     EL_EDELSTEIN_ROT,
959     EL_EDELSTEIN_LILA,
960     EL_DIAMANT,
961     EL_BOMBE,
962     EL_KOKOSNUSS,
963     EL_TROPFEN,
964     EL_MORAST_VOLL,
965     EL_SIEB_VOLL,
966     EL_SIEB2_VOLL,
967     EL_ZEIT_VOLL,
968     EL_ZEIT_LEER
969   };
970   static int ep_can_fall_num = sizeof(ep_can_fall)/sizeof(int);
971
972   static int ep_can_smash[] =
973   {
974     EL_FELSBROCKEN,
975     EL_EDELSTEIN,
976     EL_EDELSTEIN_BD,
977     EL_EDELSTEIN_GELB,
978     EL_EDELSTEIN_ROT,
979     EL_EDELSTEIN_LILA,
980     EL_DIAMANT,
981     EL_SCHLUESSEL1,
982     EL_SCHLUESSEL2,
983     EL_SCHLUESSEL3,
984     EL_SCHLUESSEL4,
985     EL_BOMBE,
986     EL_KOKOSNUSS,
987     EL_TROPFEN,
988     EL_ZEIT_VOLL,
989     EL_ZEIT_LEER
990   };
991   static int ep_can_smash_num = sizeof(ep_can_smash)/sizeof(int);
992
993   static int ep_can_change[] =
994   {
995     EL_FELSBROCKEN,
996     EL_EDELSTEIN,
997     EL_EDELSTEIN_BD,
998     EL_EDELSTEIN_GELB,
999     EL_EDELSTEIN_ROT,
1000     EL_EDELSTEIN_LILA,
1001     EL_DIAMANT
1002   };
1003   static int ep_can_change_num = sizeof(ep_can_change)/sizeof(int);
1004
1005   static int ep_can_move[] =
1006   {
1007     EL_KAEFER,
1008     EL_FLIEGER,
1009     EL_BUTTERFLY,
1010     EL_FIREFLY,
1011     EL_MAMPFER,
1012     EL_MAMPFER2,
1013     EL_ROBOT,
1014     EL_PACMAN,
1015     EL_MAULWURF,
1016     EL_PINGUIN,
1017     EL_SCHWEIN,
1018     EL_DRACHE,
1019     EL_SONDE
1020   };
1021   static int ep_can_move_num = sizeof(ep_can_move)/sizeof(int);
1022
1023   static int ep_could_move[] =
1024   {
1025     EL_KAEFER_R,
1026     EL_KAEFER_O,
1027     EL_KAEFER_L,
1028     EL_KAEFER_U,
1029     EL_FLIEGER_R,
1030     EL_FLIEGER_O,
1031     EL_FLIEGER_L,
1032     EL_FLIEGER_U,
1033     EL_BUTTERFLY_R,
1034     EL_BUTTERFLY_O,
1035     EL_BUTTERFLY_L,
1036     EL_BUTTERFLY_U,
1037     EL_FIREFLY_R,
1038     EL_FIREFLY_O,
1039     EL_FIREFLY_L,
1040     EL_FIREFLY_U,
1041     EL_PACMAN_R,
1042     EL_PACMAN_O,
1043     EL_PACMAN_L,
1044     EL_PACMAN_U
1045   };
1046   static int ep_could_move_num = sizeof(ep_could_move)/sizeof(int);
1047
1048   static int ep_dont_touch[] =
1049   {
1050     EL_KAEFER,
1051     EL_FLIEGER,
1052     EL_BUTTERFLY,
1053     EL_FIREFLY
1054   };
1055   static int ep_dont_touch_num = sizeof(ep_dont_touch)/sizeof(int);
1056
1057   static int ep_dont_go_to[] =
1058   {
1059     EL_KAEFER,
1060     EL_FLIEGER,
1061     EL_BUTTERFLY,
1062     EL_FIREFLY,
1063     EL_MAMPFER,
1064     EL_MAMPFER2,
1065     EL_ROBOT,
1066     EL_PACMAN,
1067     EL_TROPFEN,
1068     EL_SALZSAEURE
1069   };
1070   static int ep_dont_go_to_num = sizeof(ep_dont_go_to)/sizeof(int);
1071
1072   static int ep_mampf2[] =
1073   {
1074     EL_ERDREICH,
1075     EL_KAEFER,
1076     EL_FLIEGER,
1077     EL_BUTTERFLY,
1078     EL_FIREFLY,
1079     EL_MAMPFER,
1080     EL_ROBOT,
1081     EL_PACMAN,
1082     EL_TROPFEN,
1083     EL_AMOEBE_TOT,
1084     EL_AMOEBE_NASS,
1085     EL_AMOEBE_NORM,
1086     EL_AMOEBE_VOLL,
1087     EL_AMOEBE_BD,
1088     EL_EDELSTEIN,
1089     EL_EDELSTEIN_BD,
1090     EL_EDELSTEIN_GELB,
1091     EL_EDELSTEIN_ROT,
1092     EL_EDELSTEIN_LILA,
1093     EL_DIAMANT
1094   };
1095   static int ep_mampf2_num = sizeof(ep_mampf2)/sizeof(int);
1096
1097   static int ep_bd_element[] =
1098   {
1099     EL_LEERRAUM,
1100     EL_ERDREICH,
1101     EL_FELSBODEN,
1102     EL_FELSBROCKEN,
1103     EL_EDELSTEIN_BD,
1104     EL_SIEB2_LEER,
1105     EL_AUSGANG_ZU,
1106     EL_AUSGANG_AUF,
1107     EL_BETON,
1108     EL_SPIELFIGUR,
1109     EL_FIREFLY,
1110     EL_FIREFLY_1,
1111     EL_FIREFLY_2,
1112     EL_FIREFLY_3,
1113     EL_FIREFLY_4,
1114     EL_BUTTERFLY,
1115     EL_BUTTERFLY_1,
1116     EL_BUTTERFLY_2,
1117     EL_BUTTERFLY_3,
1118     EL_BUTTERFLY_4,
1119     EL_AMOEBE_BD,
1120     EL_CHAR_FRAGE
1121   };
1122   static int ep_bd_element_num = sizeof(ep_bd_element)/sizeof(int);
1123
1124   static int ep_sb_element[] =
1125   {
1126     EL_LEERRAUM,
1127     EL_BETON,
1128     EL_SOKOBAN_OBJEKT,
1129     EL_SOKOBAN_FELD_LEER,
1130     EL_SOKOBAN_FELD_VOLL,
1131     EL_SPIELFIGUR
1132   };
1133   static int ep_sb_element_num = sizeof(ep_sb_element)/sizeof(int);
1134
1135   static int ep_gem[] =
1136   {
1137     EL_EDELSTEIN,
1138     EL_EDELSTEIN_BD,
1139     EL_EDELSTEIN_GELB,
1140     EL_EDELSTEIN_ROT,
1141     EL_EDELSTEIN_LILA,
1142     EL_DIAMANT
1143   };
1144   static int ep_gem_num = sizeof(ep_gem)/sizeof(int);
1145
1146   static int ep_inactive[] =
1147   {
1148     EL_LEERRAUM,
1149     EL_ERDREICH,
1150     EL_MAUERWERK,
1151     EL_FELSBODEN,
1152     EL_SCHLUESSEL,
1153     EL_BETON,
1154     EL_AMOEBE_TOT,
1155     EL_MORAST_LEER,
1156     EL_BADEWANNE,
1157     EL_ABLENK_AUS,
1158     EL_SCHLUESSEL1,
1159     EL_SCHLUESSEL2,
1160     EL_SCHLUESSEL3,
1161     EL_SCHLUESSEL4,
1162     EL_PFORTE1,
1163     EL_PFORTE2,
1164     EL_PFORTE3,
1165     EL_PFORTE4,
1166     EL_PFORTE1X,
1167     EL_PFORTE2X,
1168     EL_PFORTE3X,
1169     EL_PFORTE4X,
1170     EL_DYNAMIT_AUS,
1171     EL_UNSICHTBAR,
1172     EL_BIRNE_AUS,
1173     EL_BIRNE_EIN,
1174     EL_ERZ_EDEL,
1175     EL_ERZ_DIAM,
1176     EL_ERZ_EDEL_BD,
1177     EL_ERZ_EDEL_GELB,
1178     EL_DYNABOMB_NR,
1179     EL_DYNABOMB_SZ,
1180     EL_DYNABOMB_XL,
1181     EL_SOKOBAN_OBJEKT,
1182     EL_SOKOBAN_FELD_LEER,
1183     EL_SOKOBAN_FELD_VOLL,
1184     EL_ERZ_EDEL_ROT,
1185     EL_ERZ_EDEL_LILA,
1186     EL_BADEWANNE1,
1187     EL_BADEWANNE2,
1188     EL_BADEWANNE3,
1189     EL_BADEWANNE4,
1190     EL_BADEWANNE5,
1191     EL_SIEB_TOT,
1192     EL_SIEB2_TOT,
1193     EL_AMOEBA2DIAM,
1194     EL_BLOCKED
1195   };
1196   static int ep_inactive_num = sizeof(ep_inactive)/sizeof(int);
1197
1198   static int ep_explosive[] =
1199   {
1200     EL_BOMBE,
1201     EL_DYNAMIT,
1202     EL_DYNAMIT_AUS,
1203     EL_DYNABOMB,
1204     EL_DYNABOMB_NR,
1205     EL_DYNABOMB_SZ,
1206     EL_DYNABOMB_XL,
1207     EL_KAEFER,
1208     EL_MAULWURF,
1209     EL_PINGUIN,
1210     EL_SCHWEIN,
1211     EL_DRACHE,
1212     EL_SONDE
1213   };
1214   static int ep_explosive_num = sizeof(ep_explosive)/sizeof(int);
1215
1216   static int ep_mampf3[] =
1217   {
1218     EL_EDELSTEIN,
1219     EL_EDELSTEIN_BD,
1220     EL_EDELSTEIN_GELB,
1221     EL_EDELSTEIN_ROT,
1222     EL_EDELSTEIN_LILA,
1223     EL_DIAMANT
1224   };
1225   static int ep_mampf3_num = sizeof(ep_mampf3)/sizeof(int);
1226
1227   static int ep_pushable[] =
1228   {
1229     EL_FELSBROCKEN,
1230     EL_BOMBE,
1231     EL_KOKOSNUSS,
1232     EL_ZEIT_LEER,
1233     EL_SOKOBAN_FELD_VOLL,
1234     EL_SOKOBAN_OBJEKT,
1235     EL_SONDE
1236   };
1237   static int ep_pushable_num = sizeof(ep_pushable)/sizeof(int);
1238
1239   static int ep_player[] =
1240   {
1241     EL_SPIELFIGUR,
1242     EL_SPIELER1,
1243     EL_SPIELER2,
1244     EL_SPIELER3,
1245     EL_SPIELER4
1246   };
1247   static int ep_player_num = sizeof(ep_player)/sizeof(int);
1248
1249   static long ep_bit[] =
1250   {
1251     EP_BIT_AMOEBALIVE,
1252     EP_BIT_AMOEBOID,
1253     EP_BIT_SCHLUESSEL,
1254     EP_BIT_PFORTE,
1255     EP_BIT_SOLID,
1256     EP_BIT_MASSIV,
1257     EP_BIT_SLIPPERY,
1258     EP_BIT_ENEMY,
1259     EP_BIT_MAUER,
1260     EP_BIT_CAN_FALL,
1261     EP_BIT_CAN_SMASH,
1262     EP_BIT_CAN_CHANGE,
1263     EP_BIT_CAN_MOVE,
1264     EP_BIT_COULD_MOVE,
1265     EP_BIT_DONT_TOUCH,
1266     EP_BIT_DONT_GO_TO,
1267     EP_BIT_MAMPF2,
1268     EP_BIT_BD_ELEMENT,
1269     EP_BIT_SB_ELEMENT,
1270     EP_BIT_GEM,
1271     EP_BIT_INACTIVE,
1272     EP_BIT_EXPLOSIVE,
1273     EP_BIT_MAMPF3,
1274     EP_BIT_PUSHABLE,
1275     EP_BIT_PLAYER
1276   };
1277   static int *ep_array[] =
1278   {
1279     ep_amoebalive,
1280     ep_amoeboid,
1281     ep_schluessel,
1282     ep_pforte,
1283     ep_solid,
1284     ep_massiv,
1285     ep_slippery,
1286     ep_enemy,
1287     ep_mauer,
1288     ep_can_fall,
1289     ep_can_smash,
1290     ep_can_change,
1291     ep_can_move,
1292     ep_could_move,
1293     ep_dont_touch,
1294     ep_dont_go_to,
1295     ep_mampf2,
1296     ep_bd_element,
1297     ep_sb_element,
1298     ep_gem,
1299     ep_inactive,
1300     ep_explosive,
1301     ep_mampf3,
1302     ep_pushable,
1303     ep_player
1304   };
1305   static int *ep_num[] =
1306   {
1307     &ep_amoebalive_num,
1308     &ep_amoeboid_num,
1309     &ep_schluessel_num,
1310     &ep_pforte_num,
1311     &ep_solid_num,
1312     &ep_massiv_num,
1313     &ep_slippery_num,
1314     &ep_enemy_num,
1315     &ep_mauer_num,
1316     &ep_can_fall_num,
1317     &ep_can_smash_num,
1318     &ep_can_change_num,
1319     &ep_can_move_num,
1320     &ep_could_move_num,
1321     &ep_dont_touch_num,
1322     &ep_dont_go_to_num,
1323     &ep_mampf2_num,
1324     &ep_bd_element_num,
1325     &ep_sb_element_num,
1326     &ep_gem_num,
1327     &ep_inactive_num,
1328     &ep_explosive_num,
1329     &ep_mampf3_num,
1330     &ep_pushable_num,
1331     &ep_player_num
1332   };
1333   static int num_properties = sizeof(ep_num)/sizeof(int *);
1334
1335   for(i=0; i<MAX_ELEMENTS; i++)
1336     Elementeigenschaften[i] = 0;
1337
1338   for(i=0; i<num_properties; i++)
1339     for(j=0; j<*(ep_num[i]); j++)
1340       Elementeigenschaften[(ep_array[i])[j]] |= ep_bit[i];
1341   for(i=EL_CHAR_START; i<EL_CHAR_END; i++)
1342     Elementeigenschaften[i] |= (EP_BIT_CHAR | EP_BIT_INACTIVE);
1343 }
1344
1345 void CloseAllAndExit(int exit_value)
1346 {
1347   int i;
1348
1349   if (sound_process_id)
1350   {
1351     StopSounds();
1352     kill(sound_process_id, SIGTERM);
1353     FreeSounds(NUM_SOUNDS);
1354   }
1355
1356   for(i=0; i<NUM_PIXMAPS; i++)
1357   {
1358     if (pix[i])
1359     {
1360 #ifdef XPM_INCLUDE_FILE
1361       if (i<NUM_PICTURES)       /* XPM pictures */
1362       {
1363         XFreeColors(display,DefaultColormap(display,screen),
1364                     xpm_att[i].pixels,xpm_att[i].npixels,0);
1365         XpmFreeAttributes(&xpm_att[i]);
1366       }
1367 #endif
1368       XFreePixmap(display,pix[i]);
1369     }
1370     if (clipmask[i])
1371       XFreePixmap(display,clipmask[i]);
1372     if (clip_gc[i])
1373       XFreeGC(display, clip_gc[i]);
1374   }
1375
1376   if (gc)
1377     XFreeGC(display, gc);
1378
1379   if (display)
1380   {
1381     XAutoRepeatOn(display);
1382     XCloseDisplay(display);
1383   }
1384
1385   exit(exit_value);
1386 }