rocks_n_diamonds-0.9b
[rocksndiamonds.git] / src / init.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  ©1995 Artsoft Development                               *
5 *        Holger Schemel                                    *
6 *        33659 Bielefeld-Senne                             *
7 *        Telefon: (0521) 493245                            *
8 *        eMail: aeglos@valinor.owl.de                      *
9 *               aeglos@uni-paderborn.de                    *
10 *               q99492@pbhrzx.uni-paderborn.de             *
11 *----------------------------------------------------------*
12 *  init.c                                                  *
13 ***********************************************************/
14
15 #include "init.h"
16 #include "misc.h"
17 #include "sound.h"
18 #include "screens.h"
19 #include "files.h"
20 #include <signal.h>
21
22 static int sound_process_id = 0;
23
24 void OpenAll(int argc, char *argv[])
25 {
26   InitLevelAndPlayerInfo();
27
28   InitCounter();
29   InitSound();
30   InitSoundProcess();
31   InitJoystick();
32   InitRND(NEW_RANDOMIZE);
33
34   signal(SIGINT, CloseAll);
35   signal(SIGTERM, CloseAll);
36
37   InitDisplay(argc, argv);
38   InitWindow(argc, argv);
39   InitGfx();
40   InitElementProperties();
41
42   DrawMainMenu();
43
44   XMapWindow(display, window);
45   XFlush(display);
46 }
47
48 void InitLevelAndPlayerInfo()
49 {
50   if (!LoadLevelInfo())                 /* global level info */
51     CloseAll();
52
53   LoadPlayerInfo(PLAYER_SETUP);         /* global setup info */
54   LoadPlayerInfo(PLAYER_LEVEL);         /* level specific info */
55 }
56
57 void InitSound()
58 {
59   int i;
60
61   if (sound_status==SOUND_OFF)
62     return;
63
64   if (access(sound_device_name,W_OK)<0)
65   {
66     fprintf(stderr,"%s: cannot access sound device - no sounds\n",progname);
67     sound_status=SOUND_OFF;
68     return;
69   }
70
71   if ((sound_device=open(sound_device_name,O_WRONLY))<0)
72   {
73     fprintf(stderr,"%s: cannot open sound device - no sounds\n",progname);
74     sound_status=SOUND_OFF;
75     return;
76   }
77
78   close(sound_device);
79   sound_status=SOUND_AVAILABLE;
80
81 #ifdef VOXWARE
82   sound_loops_allowed = TRUE;
83   sound_loops_on = TRUE;
84 #endif
85
86   for(i=0;i<NUM_SOUNDS;i++)
87   {
88     Sound[i].name = sound_name[i];
89     if (!LoadSound(&Sound[i]))
90     {
91       sound_status=SOUND_OFF;
92       return;
93     }
94   }
95 }
96
97 void InitSoundProcess()
98 {
99   if (sound_status==SOUND_OFF)
100     return;
101
102   if (pipe(sound_pipe)<0)
103   {
104     fprintf(stderr,"%s: cannot create pipe - no sounds\n",progname);
105     sound_status=SOUND_OFF;
106     return;
107   }
108
109   if ((sound_process_id=fork())<0)
110   {       
111     fprintf(stderr,"%s: cannot create child process - no sounds\n",progname);
112     sound_status=SOUND_OFF;
113     return;
114   }
115
116   if (!sound_process_id)        /* we are child */
117     SoundServer();
118   else                          /* we are parent */
119     close(sound_pipe[0]);       /* no reading from pipe needed */
120 }
121
122 void InitJoystick()
123 {
124   if (global_joystick_status==JOYSTICK_OFF)
125     return;
126
127   if (access(joystick_device_name[joystick_nr],R_OK)<0)
128   {
129     fprintf(stderr,"%s: cannot access joystick device '%s'\n",
130             progname,joystick_device_name[joystick_nr]);
131     joystick_status = JOYSTICK_OFF;
132     return;
133   }
134
135   if ((joystick_device=open(joystick_device_name[joystick_nr],O_RDONLY))<0)
136   {
137     fprintf(stderr,"%s: cannot open joystick device '%s'\n",
138             progname,joystick_device_name[joystick_nr]);
139     joystick_status = JOYSTICK_OFF;
140     return;
141   }
142
143   joystick_status = JOYSTICK_AVAILABLE;
144   LoadJoystickData();
145 }
146
147 void InitDisplay(int argc, char *argv[])
148 {
149   char *display_name = NULL;
150   int i;
151
152   /* get X server to connect to, if given as an argument */
153   for (i=1;i<argc-1;i++)
154   {
155     char *dispstr="-display";
156     int len=MAX(strlen(dispstr),strlen(argv[i]));
157
158     if (len<4)
159       continue;
160     else if (!strncmp(argv[i],dispstr,len))
161     {
162       display_name=argv[i+1];
163       break;
164     }
165   }
166
167   /* connect to X server */
168   if (!(display=XOpenDisplay(display_name)))
169   {
170     fprintf(stderr,"%s: cannot connect to X server %s\n", 
171             progname, XDisplayName(display_name));
172     exit(-1);
173   }
174   
175   screen = DefaultScreen(display);
176   cmap   = DefaultColormap(display, screen);
177   pen_fg = WhitePixel(display,screen);
178   pen_bg = BlackPixel(display,screen);
179 }
180
181 void InitWindow(int argc, char *argv[])
182 {
183   unsigned int border_width = 4;
184   Pixmap icon_pixmap, iconmask_pixmap;
185   unsigned int icon_width,icon_height;
186   int icon_hot_x,icon_hot_y;
187   char icon_filename[256];
188   XSizeHints size_hints;
189   XWMHints wm_hints;
190   XClassHint class_hints;
191   XTextProperty windowName, iconName;
192   XGCValues gc_values;
193   unsigned long gc_valuemask;
194   char *window_name = "Rocks'n'Diamonds";
195   char *icon_name = "Rocks'n'Diamonds";
196   long window_event_mask;
197   static struct PictureFile icon_pic =
198   {
199     "rocks_icon.xbm",
200     "rocks_iconmask.xbm"
201   };
202
203   width = WIN_XSIZE;
204   height = WIN_YSIZE;
205
206   window = XCreateSimpleWindow(display, RootWindow(display, screen),
207                             WIN_XPOS, WIN_YPOS, width, height, border_width,
208                             pen_fg, pen_bg);
209
210   sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picture_filename);
211   XReadBitmapFile(display,window,icon_filename,
212                   &icon_width,&icon_height,
213                   &icon_pixmap,&icon_hot_x,&icon_hot_y);
214   if (!icon_pixmap)
215   {
216     fprintf(stderr, "%s: cannot read icon bitmap file '%s'.\n",
217             progname,icon_filename);
218     exit(-1);
219   }
220
221   sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picturemask_filename);
222   XReadBitmapFile(display,window,icon_filename,
223                   &icon_width,&icon_height,
224                   &iconmask_pixmap,&icon_hot_x,&icon_hot_y);
225   if (!iconmask_pixmap)
226   {
227     fprintf(stderr, "%s: cannot read icon bitmap file '%s'.\n",
228             progname,icon_filename);
229     exit(-1);
230   }
231
232   size_hints.flags = PSize | PMinSize | PMaxSize;
233   size_hints.width  = size_hints.min_width  = size_hints.max_width  = width;
234   size_hints.height = size_hints.min_height = size_hints.max_height = height;
235
236   if (!XStringListToTextProperty(&window_name, 1, &windowName))
237   {
238     fprintf(stderr, "%s: structure allocation for windowName failed.\n",
239             progname);
240     exit(-1);
241   }
242
243   if (!XStringListToTextProperty(&icon_name, 1, &iconName))
244   {
245     fprintf(stderr, "%s: structure allocation for iconName failed.\n",
246             progname);
247     exit(-1);
248   }
249
250   wm_hints.initial_state = NormalState;
251   wm_hints.input = True;
252   wm_hints.icon_pixmap = icon_pixmap;
253   wm_hints.icon_mask = iconmask_pixmap;
254   wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
255
256   class_hints.res_name = progname;
257   class_hints.res_class = "Rocks'n'Diamonds";
258
259   XSetWMProperties(display, window, &windowName, &iconName, 
260                    argv, argc, &size_hints, &wm_hints, 
261                    &class_hints);
262
263   XFree(windowName.value);
264   XFree(iconName.value);
265
266   /* Select event types wanted */
267   window_event_mask = ExposureMask | StructureNotifyMask | FocusChangeMask |
268                       ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
269                       KeyPressMask | KeyReleaseMask;
270   XSelectInput(display, window, window_event_mask);
271
272   /* create GC for drawing with window depth */
273   gc_values.graphics_exposures = False;
274   gc_values.foreground = pen_bg;
275   gc_values.background = pen_bg;
276   gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
277   gc = XCreateGC(display, window, gc_valuemask, &gc_values);
278 }
279
280 void InitGfx()
281 {
282   int i,j,x,y;
283   int xpm_err, xbm_err;
284   unsigned int width,height;
285   int hot_x,hot_y;
286   XGCValues gc_values;
287   unsigned long gc_valuemask;
288   XGCValues clip_gc_values;
289   unsigned long clip_gc_valuemask;
290   char filename[256];
291   Pixmap shapemask;
292
293   static struct PictureFile pic[NUM_PICTURES] =
294   {
295     "RocksScreen.xpm",          "RocksScreenMaske.xbm",
296     "RocksDoor.xpm",            "RocksDoorMaske.xbm",
297     "RocksToons.xpm",           "RocksToonsMaske.xbm",
298     "RocksFont.xpm",            NULL,
299     "RocksFont2.xpm",           NULL
300   }; 
301
302   for(i=0;i<NUM_PICTURES;i++)
303   {
304     if (pic[i].picture_filename)
305     {
306       sprintf(filename,"%s/%s",GFX_PATH,pic[i].picture_filename);
307
308       xpm_att[i].valuemask = XpmCloseness;
309       xpm_att[i].closeness = 20000;
310       xpm_err = XpmReadFileToPixmap(display,window,filename,
311                                     &pix[i],&shapemask,&xpm_att[i]);
312       switch(xpm_err)
313       {
314         case XpmOpenFailed:
315           fprintf(stderr,"Xpm file open failed on '%s' !\n",filename);
316           CloseAll();
317           exit(-1);
318         case XpmFileInvalid:
319           fprintf(stderr,"Invalid Xpm file '%s'!\n",filename);
320           CloseAll();
321           exit(-1);
322         case XpmNoMemory:
323           fprintf(stderr,"Not enough memory !\n");      
324           CloseAll();
325           exit(1);
326         case XpmColorFailed:
327           fprintf(stderr,"Can`t get any colors...\n");
328           CloseAll();
329           exit(-1);
330         default:
331           break;
332       }
333       if (!pix[i])
334       {
335         fprintf(stderr, "%s: cannot read Xpm file '%s'.\n",
336                 progname,filename);
337         CloseAll();
338         exit(-1);
339       }
340     }
341
342     if (pic[i].picturemask_filename)
343     {
344       sprintf(filename,"%s/%s",GFX_PATH,pic[i].picturemask_filename);
345
346       xbm_err = XReadBitmapFile(display,window,filename,
347                                 &width,&height,&clipmask[i],&hot_x,&hot_y);
348       switch(xbm_err)
349       {
350         case BitmapSuccess:
351           break;
352         case BitmapOpenFailed:
353           fprintf(stderr,"Bitmap file open failed on '%s' !\n",filename);
354           CloseAll();
355           exit(-1);
356           break;
357         case BitmapFileInvalid:
358           fprintf(stderr,"Bitmap file invalid: '%s' !\n",filename);
359           CloseAll();
360           exit(-1);
361           break;
362         case BitmapNoMemory:
363           fprintf(stderr,"No memory for file '%s' !\n",filename);
364           CloseAll();
365           exit(-1);
366           break;
367         default:
368           break;
369       }
370       if (!clipmask[i])
371       {
372         fprintf(stderr, "%s: cannot read X11 bitmap file '%s'.\n",
373                 progname,filename);
374         CloseAll();
375         exit(-1);
376       }
377     }
378   }
379
380   pix[PIX_DB_BACK] = XCreatePixmap(display, window,
381                                    WIN_XSIZE,WIN_YSIZE,
382                                    XDefaultDepth(display,screen));
383   pix[PIX_DB_DOOR] = XCreatePixmap(display, window,
384                                    3*DXSIZE,DYSIZE+VYSIZE,
385                                    XDefaultDepth(display,screen));
386
387   clipmask[PIX_FADEMASK] = XCreatePixmap(display, window,
388                                          SXSIZE+TILEX,SYSIZE+TILEY,1);
389
390   if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR] || !clipmask[PIX_FADEMASK])
391   {
392     fprintf(stderr, "%s: cannot create additional Pixmaps!\n",progname);
393     CloseAll();
394     exit(-1);
395   }
396
397   /* create GC for drawing with bitplane depth */
398   gc_values.graphics_exposures = False;
399   gc_values.foreground = pen_bg;
400   gc_values.background = pen_bg;
401   gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
402   plane_gc = XCreateGC(display, clipmask[PIX_BACK], gc_valuemask, &gc_values);
403
404   for(y=0;y<=SCR_FIELDY;y++) for(x=0;x<=SCR_FIELDX;x++)
405     XCopyArea(display,clipmask[PIX_BACK],clipmask[PIX_FADEMASK],plane_gc,
406               SX+2*TILEX,SY+10*TILEY,TILEX,TILEY,x*TILEX,y*TILEY);
407
408   for(i=0;i<NUM_PIXMAPS;i++)
409   {
410     if (clipmask[i])
411     {
412       clip_gc_values.graphics_exposures = False;
413       clip_gc_values.foreground = pen_fg;
414       clip_gc_values.background = pen_bg;
415       clip_gc_values.clip_mask = clipmask[i];
416       clip_gc_valuemask =
417         GCGraphicsExposures | GCForeground | GCBackground | GCClipMask;
418       clip_gc[i] = XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
419     }
420   }
421
422   drawto = drawto_field = backbuffer = pix[PIX_DB_BACK];
423
424   XCopyArea(display,pix[PIX_BACK],backbuffer,gc,
425             0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
426   XFillRectangle(display,backbuffer,gc,
427                  REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
428
429   for(i=0;i<SCR_FIELDX;i++)
430     for(j=0;j<SCR_FIELDY;j++)
431       redraw[i][j]=0;
432   redraw_tiles=0;
433   redraw_mask=REDRAW_ALL;
434 }
435
436 void InitElementProperties()
437 {
438   int i,j;
439
440   static int ep_amoebalive[] =
441   {
442     EL_AMOEBE_NASS,
443     EL_AMOEBE_NORM,
444     EL_AMOEBE_VOLL
445   };
446   static int ep_amoebalive_num = sizeof(ep_amoebalive)/sizeof(int);
447
448   static int ep_amoeboid[] =
449   {
450     EL_AMOEBE_TOT,
451     EL_AMOEBE_NASS,
452     EL_AMOEBE_NORM,
453     EL_AMOEBE_VOLL
454   };
455   static int ep_amoeboid_num = sizeof(ep_amoeboid)/sizeof(int);
456
457   static int ep_badewannoid[] =
458   {
459     EL_BADEWANNE1,
460     EL_BADEWANNE2,
461     EL_BADEWANNE3,
462     EL_BADEWANNE4,
463     EL_BADEWANNE5
464   };
465   static int ep_badewannoid_num = sizeof(ep_badewannoid)/sizeof(int);
466
467   static int ep_schluessel[] =
468   {
469     EL_SCHLUESSEL1,
470     EL_SCHLUESSEL2,
471     EL_SCHLUESSEL3,
472     EL_SCHLUESSEL4
473   };
474   static int ep_schluessel_num = sizeof(ep_schluessel)/sizeof(int);
475
476   static int ep_pforte[] =
477   {
478     EL_PFORTE1,
479     EL_PFORTE2,
480     EL_PFORTE3,
481     EL_PFORTE4,
482     EL_PFORTE1X,
483     EL_PFORTE2X,
484     EL_PFORTE3X,
485     EL_PFORTE4X
486   };
487   static int ep_pforte_num = sizeof(ep_pforte)/sizeof(int);
488
489   static int ep_solid[] =
490   {
491     EL_BETON,
492     EL_MAUERWERK,
493     EL_FELSBODEN,
494     EL_AUSGANG_ZU,
495     EL_AUSGANG_ACT,
496     EL_AUSGANG_AUF,
497     EL_AMOEBE_TOT,
498     EL_AMOEBE_NASS,
499     EL_AMOEBE_NORM,
500     EL_AMOEBE_VOLL,
501     EL_MORAST_VOLL,
502     EL_MORAST_LEER,
503     EL_SIEB_VOLL,
504     EL_SIEB_LEER,
505     EL_LIFE,
506     EL_LIFE_ASYNC,
507     EL_BADEWANNE1,
508     EL_BADEWANNE2,
509     EL_BADEWANNE3,
510     EL_BADEWANNE4,
511     EL_BADEWANNE5
512   };
513   static int ep_solid_num = sizeof(ep_solid)/sizeof(int);
514
515   static int ep_massiv[] =
516   {
517     EL_BETON,
518     EL_SALZSAEURE,
519     EL_BADEWANNE1,
520     EL_BADEWANNE2,
521     EL_BADEWANNE3,
522     EL_BADEWANNE4,
523     EL_BADEWANNE5,
524     EL_PFORTE1,
525     EL_PFORTE2,
526     EL_PFORTE3,
527     EL_PFORTE4,
528     EL_PFORTE1X,
529     EL_PFORTE2X,
530     EL_PFORTE3X,
531     EL_PFORTE4X
532   };
533   static int ep_massiv_num = sizeof(ep_massiv)/sizeof(int);
534
535   static int ep_slippery[] =
536   {
537     EL_FELSBODEN,
538     EL_FELSBROCKEN,
539     EL_EDELSTEIN,
540     EL_DIAMANT,
541     EL_BOMBE,
542     EL_KOKOSNUSS,
543     EL_ABLENK_EIN,
544     EL_ABLENK_AUS,
545     EL_ZEIT_VOLL,
546     EL_ZEIT_LEER,
547     EL_BIRNE_EIN,
548     EL_BIRNE_AUS,
549     EL_BADEWANNE1,
550     EL_BADEWANNE2
551   };
552   static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int);
553
554   static int ep_enemy[] =
555   {
556     EL_KAEFER,
557     EL_FLIEGER,
558     EL_MAMPFER,
559     EL_ZOMBIE,
560     EL_PACMAN
561   };
562   static int ep_enemy_num = sizeof(ep_enemy)/sizeof(int);
563
564   static int ep_can_fall[] =
565   {
566     EL_FELSBROCKEN,
567     EL_EDELSTEIN,
568     EL_DIAMANT,
569     EL_BOMBE,
570     EL_KOKOSNUSS,
571     EL_TROPFEN,
572     EL_MORAST_VOLL,
573     EL_SIEB_VOLL,
574     EL_ZEIT_VOLL,
575     EL_ZEIT_LEER
576   };
577   static int ep_can_fall_num = sizeof(ep_can_fall)/sizeof(int);
578
579   static int ep_can_smash[] =
580   {
581     EL_FELSBROCKEN,
582     EL_EDELSTEIN,
583     EL_DIAMANT,
584     EL_SCHLUESSEL1,
585     EL_SCHLUESSEL2,
586     EL_SCHLUESSEL3,
587     EL_SCHLUESSEL4,
588     EL_BOMBE,
589     EL_KOKOSNUSS,
590     EL_TROPFEN,
591     EL_ZEIT_VOLL,
592     EL_ZEIT_LEER
593   };
594   static int ep_can_smash_num = sizeof(ep_can_smash)/sizeof(int);
595
596   static int ep_can_change[] =
597   {
598     EL_FELSBROCKEN,
599     EL_EDELSTEIN,
600     EL_DIAMANT
601   };
602   static int ep_can_change_num = sizeof(ep_can_change)/sizeof(int);
603
604   static int ep_can_move[] =
605   {
606     EL_KAEFER,
607     EL_FLIEGER,
608     EL_MAMPFER,
609     EL_ZOMBIE,
610     EL_PACMAN
611   };
612   static int ep_can_move_num = sizeof(ep_can_move)/sizeof(int);
613
614   static int ep_could_move[] =
615   {
616     EL_KAEFER_R,
617     EL_KAEFER_O,
618     EL_KAEFER_L,
619     EL_KAEFER_U,
620     EL_FLIEGER_R,
621     EL_FLIEGER_O,
622     EL_FLIEGER_L,
623     EL_FLIEGER_U,
624     EL_PACMAN_R,
625     EL_PACMAN_O,
626     EL_PACMAN_L,
627     EL_PACMAN_U
628   };
629   static int ep_could_move_num = sizeof(ep_could_move)/sizeof(int);
630
631   static int ep_dont_touch[] =
632   {
633     EL_KAEFER,
634     EL_FLIEGER
635   };
636   static int ep_dont_touch_num = sizeof(ep_dont_touch)/sizeof(int);
637
638   static int ep_dont_go_to[] =
639   {
640     EL_KAEFER,
641     EL_FLIEGER,
642     EL_MAMPFER,
643     EL_ZOMBIE,
644     EL_PACMAN,
645     EL_TROPFEN,
646     EL_SALZSAEURE
647   };
648   static int ep_dont_go_to_num = sizeof(ep_dont_go_to)/sizeof(int);
649
650   static long ep_bit[] =
651   {
652     EP_BIT_AMOEBALIVE,
653     EP_BIT_AMOEBOID,
654     EP_BIT_BADEWANNOID,
655     EP_BIT_SCHLUESSEL,
656     EP_BIT_PFORTE,
657     EP_BIT_SOLID,
658     EP_BIT_MASSIV,
659     EP_BIT_SLIPPERY,
660     EP_BIT_ENEMY,
661     EP_BIT_CAN_FALL,
662     EP_BIT_CAN_SMASH,
663     EP_BIT_CAN_CHANGE,
664     EP_BIT_CAN_MOVE,
665     EP_BIT_COULD_MOVE,
666     EP_BIT_DONT_TOUCH,
667     EP_BIT_DONT_GO_TO
668   };
669   static int *ep_array[] =
670   {
671     ep_amoebalive,
672     ep_amoeboid,
673     ep_badewannoid,
674     ep_schluessel,
675     ep_pforte,
676     ep_solid,
677     ep_massiv,
678     ep_slippery,
679     ep_enemy,
680     ep_can_fall,
681     ep_can_smash,
682     ep_can_change,
683     ep_can_move,
684     ep_could_move,
685     ep_dont_touch,
686     ep_dont_go_to
687   };
688   static int *ep_num[] =
689   {
690     &ep_amoebalive_num,
691     &ep_amoeboid_num,
692     &ep_badewannoid_num,
693     &ep_schluessel_num,
694     &ep_pforte_num,
695     &ep_solid_num,
696     &ep_massiv_num,
697     &ep_slippery_num,
698     &ep_enemy_num,
699     &ep_can_fall_num,
700     &ep_can_smash_num,
701     &ep_can_change_num,
702     &ep_can_move_num,
703     &ep_could_move_num,
704     &ep_dont_touch_num,
705     &ep_dont_go_to_num
706   };
707   static int num_properties = sizeof(ep_num)/sizeof(int *);
708
709   for(i=0;i<MAX_ELEMENTS;i++)
710     Elementeigenschaften[i] = 0;
711
712   for(i=0;i<num_properties;i++)
713     for(j=0;j<*(ep_num[i]);j++)
714       Elementeigenschaften[(ep_array[i])[j]] |= ep_bit[i];
715   for(i=EL_CHAR_START;i<EL_CHAR_END;i++)
716     Elementeigenschaften[i] |= EP_BIT_CHAR;
717 }
718
719 void CloseAll()
720 {
721   int i;
722
723   if (sound_process_id)
724   {
725     StopSounds();
726     kill(sound_process_id, SIGTERM);
727     FreeSounds(NUM_SOUNDS);
728   }
729
730   for(i=0;i<NUM_PIXMAPS;i++)
731   {
732     if (pix[i])
733     {
734       if (i<NUM_PICTURES)       /* XPM pictures */
735       {
736         XFreeColors(display,DefaultColormap(display,screen),
737                     xpm_att[i].pixels,xpm_att[i].npixels,0);
738         XpmFreeAttributes(&xpm_att[i]);
739       }
740       XFreePixmap(display,pix[i]);
741     }
742     if (clipmask[i])
743       XFreePixmap(display,clipmask[i]);
744     if (clip_gc[i])
745       XFreeGC(display, clip_gc[i]);
746   }
747
748   if (gc)
749     XFreeGC(display, gc);
750   if (plane_gc)
751     XFreeGC(display, plane_gc);
752
753   XCloseDisplay(display);
754
755   exit(0);
756 }