rnd-20020406-1-src
[rocksndiamonds.git] / src / libgame / system.c
1 /***********************************************************
2 * Artsoft Retro-Game Library                               *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * system.c                                                 *
12 ***********************************************************/
13
14 #include <string.h>
15 #include <signal.h>
16
17 #include "platform.h"
18
19 #if defined(PLATFORM_MSDOS)
20 #include <fcntl.h>
21 #endif
22
23 #include "system.h"
24 #include "sound.h"
25 #include "setup.h"
26 #include "joystick.h"
27 #include "misc.h"
28
29
30 /* ========================================================================= */
31 /* exported variables                                                        */
32 /* ========================================================================= */
33
34 struct ProgramInfo      program;
35 struct OptionInfo       options;
36 struct VideoSystemInfo  video;
37 struct AudioSystemInfo  audio;
38 struct GfxInfo          gfx;
39 struct ArtworkInfo      artwork;
40 struct JoystickInfo     joystick;
41 struct SetupInfo        setup;
42
43 LevelDirTree           *leveldir_first = NULL;
44 LevelDirTree           *leveldir_current = NULL;
45 int                     level_nr;
46
47 Display                *display = NULL;
48 Visual                 *visual = NULL;
49 int                     screen = 0;
50 Colormap                cmap = None;
51
52 DrawWindow             *window = NULL;
53 DrawBuffer             *backbuffer = NULL;
54 DrawBuffer             *drawto = NULL;
55
56 int                     button_status = MB_NOT_PRESSED;
57 boolean                 motion_status = FALSE;
58
59 int                     redraw_mask = REDRAW_NONE;
60 int                     redraw_tiles = 0;
61
62 int                     FrameCounter = 0;
63
64
65 /* ========================================================================= */
66 /* init/close functions                                                      */
67 /* ========================================================================= */
68
69 void InitCommandName(char *argv0)
70 {
71   program.command_basename =
72     (strrchr(argv0, '/') ? strrchr(argv0, '/') + 1 : argv0);
73 }
74
75 void InitExitFunction(void (*exit_function)(int))
76 {
77   program.exit_function = exit_function;
78
79   /* set signal handlers to custom exit function */
80   signal(SIGINT, exit_function);
81   signal(SIGTERM, exit_function);
82
83 #if defined(TARGET_SDL)
84   /* set exit function to automatically cleanup SDL stuff after exit() */
85   atexit(SDL_Quit);
86 #endif
87 }
88
89 void InitPlatformDependantStuff(void)
90 {
91 #if defined(PLATFORM_MSDOS)
92   _fmode = O_BINARY;
93 #endif
94
95 #if !defined(PLATFORM_UNIX)
96   program.userdata_directory = "userdata";
97   initErrorFile();
98 #endif
99
100 #if defined(TARGET_SDL)
101   if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
102     Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
103 #endif
104 }
105
106 void ClosePlatformDependantStuff(void)
107 {
108 #if !defined(PLATFORM_UNIX)
109   dumpErrorFile();
110 #endif
111 }
112
113 void InitProgramInfo(char *unix_userdata_directory, char *program_title,
114                      char *window_title, char *icon_title,
115                      char *x11_icon_basename, char *x11_iconmask_basename,
116                      char *msdos_pointer_basename,
117                      char *cookie_prefix, char *filename_prefix,
118                      int program_version)
119 {
120   char *x11_icon_filename =
121     getPath2(options.graphics_directory, x11_icon_basename);
122   char *x11_iconmask_filename =
123     getPath2(options.graphics_directory, x11_iconmask_basename);
124   char *msdos_pointer_filename =
125     getPath2(options.graphics_directory, msdos_pointer_basename);
126
127 #if defined(PLATFORM_UNIX)
128   program.userdata_directory = unix_userdata_directory;
129 #else
130   program.userdata_directory = "userdata";
131 #endif
132
133   program.program_title = program_title;
134   program.window_title = window_title;
135   program.icon_title = icon_title;
136   program.x11_icon_filename = x11_icon_filename;
137   program.x11_iconmask_filename = x11_iconmask_filename;
138   program.msdos_pointer_filename = msdos_pointer_filename;
139
140   program.cookie_prefix = cookie_prefix;
141   program.filename_prefix = filename_prefix;
142
143   program.version_major = VERSION_MAJOR(program_version);
144   program.version_minor = VERSION_MINOR(program_version);
145   program.version_patch = VERSION_PATCH(program_version);
146 }
147
148 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
149                       int real_sx, int real_sy,
150                       int full_sxsize, int full_sysize)
151 {
152   gfx.sx = sx;
153   gfx.sy = sy;
154   gfx.sxsize = sxsize;
155   gfx.sysize = sysize;
156   gfx.real_sx = real_sx;
157   gfx.real_sy = real_sy;
158   gfx.full_sxsize = full_sxsize;
159   gfx.full_sysize = full_sysize;
160
161   SetDrawDeactivationMask(REDRAW_NONE);         /* do not deactivate drawing */
162 }
163
164 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
165 {
166   gfx.dx = dx;
167   gfx.dy = dy;
168   gfx.dxsize = dxsize;
169   gfx.dysize = dysize;
170 }
171
172 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
173 {
174   gfx.vx = vx;
175   gfx.vy = vy;
176   gfx.vxsize = vxsize;
177   gfx.vysize = vysize;
178 }
179
180 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
181 {
182   /* currently only used by MSDOS code to alloc VRAM buffer, if available */
183   gfx.scrollbuffer_width = scrollbuffer_width;
184   gfx.scrollbuffer_height = scrollbuffer_height;
185 }
186
187 void SetDrawDeactivationMask(int draw_deactivation_mask)
188 {
189   gfx.draw_deactivation_mask = draw_deactivation_mask;
190 }
191
192
193 /* ========================================================================= */
194 /* video functions                                                           */
195 /* ========================================================================= */
196
197 inline static int GetRealDepth(int depth)
198 {
199   return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
200 }
201
202 inline void InitVideoDisplay(void)
203 {
204 #if defined(TARGET_SDL)
205   SDLInitVideoDisplay();
206 #else
207   X11InitVideoDisplay();
208 #endif
209 }
210
211 inline void CloseVideoDisplay(void)
212 {
213   KeyboardAutoRepeatOn();
214
215 #if defined(TARGET_SDL)
216   SDL_QuitSubSystem(SDL_INIT_VIDEO);
217 #else
218
219   if (display)
220     XCloseDisplay(display);
221 #endif
222 }
223
224 inline void InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
225                             int width, int height, int depth,
226                             boolean fullscreen)
227 {
228   video.width = width;
229   video.height = height;
230   video.depth = GetRealDepth(depth);
231   video.fullscreen_available = FULLSCREEN_STATUS;
232   video.fullscreen_enabled = FALSE;
233
234 #ifdef TARGET_SDL
235   SDLInitVideoBuffer(backbuffer, window, fullscreen);
236 #else
237   X11InitVideoBuffer(backbuffer, window);
238 #endif
239 }
240
241 inline Bitmap *CreateBitmapStruct(void)
242 {
243 #ifdef TARGET_SDL
244   return checked_calloc(sizeof(struct SDLSurfaceInfo));
245 #else
246   return checked_calloc(sizeof(struct X11DrawableInfo));
247 #endif
248 }
249
250 inline Bitmap *CreateBitmap(int width, int height, int depth)
251 {
252   Bitmap *new_bitmap = CreateBitmapStruct();
253   int real_depth = GetRealDepth(depth);
254
255 #ifdef TARGET_SDL
256   SDL_Surface *surface_tmp, *surface_native;
257
258   if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height,
259                                           real_depth, 0, 0, 0, 0))
260       == NULL)
261     Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
262
263   if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
264     Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
265
266   SDL_FreeSurface(surface_tmp);
267
268   new_bitmap->surface = surface_native;
269 #else
270   Pixmap pixmap;
271
272   if ((pixmap = XCreatePixmap(display, window->drawable,
273                               width, height, real_depth))
274       == None)
275     Error(ERR_EXIT, "cannot create pixmap");
276
277   new_bitmap->drawable = pixmap;
278
279   if (window == NULL)
280     Error(ERR_EXIT, "Window GC needed for Bitmap -- create Window first");
281
282   new_bitmap->gc = window->gc;
283
284   new_bitmap->line_gc[0] = window->line_gc[0];
285   new_bitmap->line_gc[1] = window->line_gc[1];
286 #endif
287
288   return new_bitmap;
289 }
290
291 inline void FreeBitmap(Bitmap *bitmap)
292 {
293   if (bitmap == NULL)
294     return;
295
296 #ifdef TARGET_SDL
297   if (bitmap->surface)
298     SDL_FreeSurface(bitmap->surface);
299   if (bitmap->surface_masked)
300     SDL_FreeSurface(bitmap->surface_masked);
301 #else
302   if (bitmap->drawable)
303     XFreePixmap(display, bitmap->drawable);
304   if (bitmap->clip_mask)
305     XFreePixmap(display, bitmap->clip_mask);
306   if (bitmap->stored_clip_gc)
307     XFreeGC(display, bitmap->stored_clip_gc);
308 #endif
309
310   if (bitmap->source_filename)
311     free(bitmap->source_filename);
312
313   free(bitmap);
314 }
315
316 inline void CloseWindow(DrawWindow *window)
317 {
318 #ifdef TARGET_X11
319   if (window->drawable)
320   {
321     XUnmapWindow(display, window->drawable);
322     XDestroyWindow(display, window->drawable);
323   }
324   if (window->gc)
325     XFreeGC(display, window->gc);
326 #endif
327 }
328
329 inline boolean DrawingDeactivated(int x, int y, int width, int height)
330 {
331   if (gfx.draw_deactivation_mask != REDRAW_NONE)
332   {
333     if ((gfx.draw_deactivation_mask & REDRAW_FIELD) &&
334         x < gfx.sx + gfx.sxsize)
335       return TRUE;
336   }
337
338   return FALSE;
339 }
340
341 inline void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
342                        int src_x, int src_y,
343                        int width, int height,
344                        int dst_x, int dst_y)
345 {
346   if (DrawingDeactivated(dst_x, dst_y, width, height))
347     return;
348
349 #ifdef TARGET_SDL
350   SDLCopyArea(src_bitmap, dst_bitmap,
351               src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_OPAQUE);
352 #else
353   XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
354             dst_bitmap->gc, src_x, src_y, width, height, dst_x, dst_y);
355 #endif
356 }
357
358 inline void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
359 {
360   if (DrawingDeactivated(x, y, width, height))
361     return;
362
363 #ifdef TARGET_SDL
364   SDLFillRectangle(bitmap, x, y, width, height, 0x000000);
365 #else
366   XFillRectangle(display, bitmap->drawable, bitmap->gc, x, y, width, height);
367 #endif
368 }
369
370 #if 0
371 #ifndef TARGET_SDL
372 static GC last_clip_gc = 0;     /* needed for XCopyArea() through clip mask */
373 #endif
374 #endif
375
376 inline void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
377 {
378 #ifdef TARGET_X11
379   if (clip_gc)
380   {
381     bitmap->clip_gc = clip_gc;
382     XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
383   }
384 #if 0
385   last_clip_gc = clip_gc;
386 #endif
387 #endif
388 }
389
390 inline void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
391 {
392 #ifdef TARGET_X11
393   if (clip_gc)
394   {
395     bitmap->clip_gc = clip_gc;
396     XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
397   }
398 #if 0
399   last_clip_gc = clip_gc;
400 #endif
401 #endif
402 }
403
404 inline void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
405                              int src_x, int src_y,
406                              int width, int height,
407                              int dst_x, int dst_y)
408 {
409   if (DrawingDeactivated(dst_x, dst_y, width, height))
410     return;
411
412 #ifdef TARGET_SDL
413   SDLCopyArea(src_bitmap, dst_bitmap,
414               src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_MASKED);
415 #else
416   XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
417             src_bitmap->clip_gc, src_x, src_y, width, height, dst_x, dst_y);
418 #endif
419 }
420
421 inline void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
422                                 int to_x, int to_y)
423 {
424 #ifdef TARGET_SDL
425   SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, 0xffffff);
426 #else
427   XSetForeground(display, bitmap->gc, WhitePixel(display, screen));
428   XDrawLine(display, bitmap->drawable, bitmap->gc, from_x, from_y, to_x, to_y);
429   XSetForeground(display, bitmap->gc, BlackPixel(display, screen));
430 #endif
431 }
432
433 #if !defined(TARGET_X11_NATIVE)
434 inline void DrawLine(Bitmap *bitmap, int from_x, int from_y,
435                      int to_x, int to_y, Pixel pixel, int line_width)
436 {
437   int x, y;
438
439   for (x=0; x<line_width; x++)
440   {
441     for (y=0; y<line_width; y++)
442     {
443       int dx = x - line_width / 2;
444       int dy = y - line_width / 2;
445
446       if ((x == 0 && y == 0) ||
447           (x == 0 && y == line_width - 1) ||
448           (x == line_width - 1 && y == 0) ||
449           (x == line_width - 1 && y == line_width - 1))
450         continue;
451
452 #if defined(TARGET_SDL)
453       SDLDrawLine(bitmap,
454                   from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
455 #elif defined(TARGET_ALLEGRO)
456       AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
457                       to_x + dx, to_y + dy, pixel);
458 #endif
459     }
460   }
461 }
462 #endif
463
464 inline void DrawLines(Bitmap *bitmap, struct XY *points, int num_points,
465                       Pixel pixel)
466 {
467 #if !defined(TARGET_X11_NATIVE)
468   int line_width = 4;
469   int i;
470
471   for (i=0; i<num_points - 1; i++)
472     DrawLine(bitmap, points[i].x, points[i].y,
473              points[i + 1].x, points[i + 1].y, pixel, line_width);
474
475   /*
476   SDLDrawLines(bitmap->surface, points, num_points, pixel);
477   */
478 #else
479   XSetForeground(display, bitmap->line_gc[1], pixel);
480   XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
481              (XPoint *)points, num_points, CoordModeOrigin);
482   /*
483   XSetForeground(display, gc, BlackPixel(display, screen));
484   */
485 #endif
486 }
487
488 inline Pixel GetPixel(Bitmap *bitmap, int x, int y)
489 {
490 #if defined(TARGET_SDL)
491   return SDLGetPixel(bitmap, x, y);
492 #elif defined(TARGET_ALLEGRO)
493   return AllegroGetPixel(bitmap->drawable, x, y);
494 #else
495   unsigned long pixel_value;
496   XImage *pixel_image;
497
498   pixel_image = XGetImage(display, bitmap->drawable, x, y, 1, 1,
499                           AllPlanes, ZPixmap);
500   pixel_value = XGetPixel(pixel_image, 0, 0);
501
502   XDestroyImage(pixel_image);
503
504   return pixel_value;
505 #endif
506 }
507
508 inline Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
509                              unsigned int color_g, unsigned int color_b)
510 {
511   Pixel pixel;
512
513 #if defined(TARGET_SDL)
514   pixel = SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
515 #elif defined(TARGET_ALLEGRO)
516   pixel = AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
517 #elif defined(TARGET_X11_NATIVE)
518   XColor xcolor;
519
520   xcolor.flags = DoRed | DoGreen | DoBlue;
521   xcolor.red = (color_r << 8);
522   xcolor.green = (color_g << 8);
523   xcolor.blue = (color_b << 8);
524   XAllocColor(display, cmap, &xcolor);
525   pixel = xcolor.pixel;
526 #endif
527
528   return pixel;
529 }
530
531 inline Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
532 {
533   unsigned int color_r = (color >> 16) & 0xff;
534   unsigned int color_g = (color >>  8) & 0xff;
535   unsigned int color_b = (color >>  0) & 0xff;
536
537   return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
538 }
539
540 /* execute all pending screen drawing operations */
541 inline void FlushDisplay(void)
542 {
543 #ifndef TARGET_SDL
544   XFlush(display);
545 #endif
546 }
547
548 /* execute and wait for all pending screen drawing operations */
549 inline void SyncDisplay(void)
550 {
551 #ifndef TARGET_SDL
552   XSync(display, FALSE);
553 #endif
554 }
555
556 inline void KeyboardAutoRepeatOn(void)
557 {
558 #ifdef TARGET_SDL
559   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
560                       SDL_DEFAULT_REPEAT_INTERVAL / 2);
561   SDL_EnableUNICODE(1);
562 #else
563   if (display)
564     XAutoRepeatOn(display);
565 #endif
566 }
567
568 inline void KeyboardAutoRepeatOff(void)
569 {
570 #ifdef TARGET_SDL
571   SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
572   SDL_EnableUNICODE(0);
573 #else
574   if (display)
575     XAutoRepeatOff(display);
576 #endif
577 }
578
579 inline boolean PointerInWindow(DrawWindow *window)
580 {
581 #ifdef TARGET_SDL
582   return TRUE;
583 #else
584   Window root, child;
585   int root_x, root_y;
586   unsigned int mask;
587   int win_x, win_y;
588
589   /* if XQueryPointer() returns False, the pointer
590      is not on the same screen as the specified window */
591   return XQueryPointer(display, window->drawable, &root, &child,
592                        &root_x, &root_y, &win_x, &win_y, &mask);
593 #endif
594 }
595
596 inline boolean SetVideoMode(boolean fullscreen)
597 {
598 #ifdef TARGET_SDL
599   return SDLSetVideoMode(&backbuffer, fullscreen);
600 #else
601   boolean success = TRUE;
602
603   if (fullscreen && video.fullscreen_available)
604   {
605     Error(ERR_WARN, "fullscreen not available in X11 version");
606
607     /* display error message only once */
608     video.fullscreen_available = FALSE;
609
610     success = FALSE;
611   }
612
613   return success;
614 #endif
615 }
616
617 inline boolean ChangeVideoModeIfNeeded(boolean fullscreen)
618 {
619 #ifdef TARGET_SDL
620   if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
621       (!fullscreen && video.fullscreen_enabled))
622     fullscreen = SetVideoMode(fullscreen);
623 #endif
624
625   return fullscreen;
626 }
627
628 Bitmap *LoadImage(char *filename)
629 {
630   Bitmap *new_bitmap;
631
632 #if defined(TARGET_SDL)
633   new_bitmap = SDLLoadImage(filename);
634 #else
635   new_bitmap = X11LoadImage(filename);
636 #endif
637
638   return new_bitmap;
639 }
640
641 Bitmap *LoadCustomImage(char *basename)
642 {
643   char *filename = getCustomImageFilename(basename);
644   Bitmap *new_bitmap;
645
646   if (filename == NULL)
647     Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
648
649   if ((new_bitmap = LoadImage(filename)) == NULL)
650     Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
651
652   new_bitmap->source_filename = getStringCopy(filename);
653
654   return new_bitmap;
655 }
656
657
658 /* ========================================================================= */
659 /* audio functions                                                           */
660 /* ========================================================================= */
661
662 inline void OpenAudio(void)
663 {
664   /* always start with reliable default values */
665   audio.sound_available = FALSE;
666   audio.music_available = FALSE;
667   audio.loops_available = FALSE;
668   audio.mods_available = FALSE;
669   audio.sound_enabled = FALSE;
670
671   audio.soundserver_pipe[0] = audio.soundserver_pipe[1] = 0;
672   audio.soundserver_pid = 0;
673   audio.device_name = NULL;
674   audio.device_fd = 0;
675
676   audio.channels = 0;
677   audio.music_channel = 0;
678   audio.music_nr = 0;
679
680 #if defined(TARGET_SDL)
681   SDLOpenAudio();
682 #elif defined(PLATFORM_UNIX)
683   UnixOpenAudio();
684 #elif defined(PLATFORM_MSDOS)
685   MSDOSOpenAudio();
686 #endif
687 }
688
689 inline void CloseAudio(void)
690 {
691 #if defined(TARGET_SDL)
692   SDLCloseAudio();
693 #elif defined(PLATFORM_UNIX)
694   UnixCloseAudio();
695 #elif defined(PLATFORM_MSDOS)
696   MSDOSCloseAudio();
697 #endif
698
699   audio.sound_enabled = FALSE;
700 }
701
702 inline void SetAudioMode(boolean enabled)
703 {
704   if (!audio.sound_available)
705     return;
706
707   audio.sound_enabled = enabled;
708 }
709
710
711 /* ========================================================================= */
712 /* event functions                                                           */
713 /* ========================================================================= */
714
715 inline void InitEventFilter(EventFilter filter_function)
716 {
717 #ifdef TARGET_SDL
718   /* set event filter to filter out certain events */
719   SDL_SetEventFilter(filter_function);
720 #endif
721 }
722
723 inline boolean PendingEvent(void)
724 {
725 #ifdef TARGET_SDL
726   return (SDL_PollEvent(NULL) ? TRUE : FALSE);
727 #else
728   return (XPending(display) ? TRUE : FALSE);
729 #endif
730 }
731
732 inline void NextEvent(Event *event)
733 {
734 #ifdef TARGET_SDL
735   SDLNextEvent(event);
736 #else
737   XNextEvent(display, event);
738 #endif
739 }
740
741 inline Key GetEventKey(KeyEvent *event, boolean with_modifiers)
742 {
743 #ifdef TARGET_SDL
744 #if 0
745   printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
746          (int)event->keysym.unicode,
747          (int)event->keysym.sym,
748          (int)SDL_GetModState());
749 #endif
750
751   if (with_modifiers && event->keysym.unicode != 0)
752     return event->keysym.unicode;
753   else
754     return event->keysym.sym;
755 #else
756 #if 0
757   printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
758          (int)XLookupKeysym(event, event->state),
759          (int)XLookupKeysym(event, 0));
760 #endif
761
762   if (with_modifiers)
763     return XLookupKeysym(event, event->state);
764   else
765     return XLookupKeysym(event, 0);
766 #endif
767 }
768
769 inline boolean CheckCloseWindowEvent(ClientMessageEvent *event)
770 {
771   if (event->type != EVENT_CLIENTMESSAGE)
772     return FALSE;
773
774 #if defined(TARGET_SDL)
775   return TRUE;          /* the only possible message here is SDL_QUIT */
776 #elif defined(PLATFORM_UNIX)
777   if ((event->window == window->drawable) &&
778       (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
779     return TRUE;
780 #endif
781
782   return FALSE;
783 }
784
785
786 /* ========================================================================= */
787 /* joystick functions                                                        */
788 /* ========================================================================= */
789
790 inline void InitJoysticks()
791 {
792   int i;
793
794 #ifdef NO_JOYSTICK
795   return;       /* joysticks generally deactivated by compile-time directive */
796 #endif
797
798   /* always start with reliable default values */
799   joystick.status = JOYSTICK_NOT_AVAILABLE;
800   for (i=0; i<MAX_PLAYERS; i++)
801     joystick.fd[i] = -1;                /* joystick device closed */
802
803 #if defined(TARGET_SDL)
804   SDLInitJoysticks();
805 #elif defined(PLATFORM_UNIX)
806   UnixInitJoysticks();
807 #elif defined(PLATFORM_MSDOS)
808   MSDOSInitJoysticks();
809 #endif
810 }
811
812 inline boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
813 {
814 #if defined(TARGET_SDL)
815   return SDLReadJoystick(nr, x, y, b1, b2);
816 #elif defined(PLATFORM_UNIX)
817   return UnixReadJoystick(nr, x, y, b1, b2);
818 #elif defined(PLATFORM_MSDOS)
819   return MSDOSReadJoystick(nr, x, y, b1, b2);
820 #endif
821 }