rnd-20070427-1-src
[rocksndiamonds.git] / src / libgame / system.c
1 /***********************************************************
2 * Artsoft Retro-Game Library                               *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 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 "image.h"
25 #include "sound.h"
26 #include "setup.h"
27 #include "joystick.h"
28 #include "misc.h"
29
30
31 /* ========================================================================= */
32 /* exported variables                                                        */
33 /* ========================================================================= */
34
35 struct ProgramInfo      program;
36 struct OptionInfo       options;
37 struct VideoSystemInfo  video;
38 struct AudioSystemInfo  audio;
39 struct GfxInfo          gfx;
40 struct ArtworkInfo      artwork;
41 struct JoystickInfo     joystick;
42 struct SetupInfo        setup;
43
44 LevelDirTree           *leveldir_first_all = NULL;
45 LevelDirTree           *leveldir_first = NULL;
46 LevelDirTree           *leveldir_current = NULL;
47 int                     level_nr;
48
49 Display                *display = NULL;
50 Visual                 *visual = NULL;
51 int                     screen = 0;
52 Colormap                cmap = None;
53
54 DrawWindow             *window = NULL;
55 DrawBuffer             *backbuffer = NULL;
56 DrawBuffer             *drawto = NULL;
57
58 int                     button_status = MB_NOT_PRESSED;
59 boolean                 motion_status = FALSE;
60
61 int                     redraw_mask = REDRAW_NONE;
62 int                     redraw_tiles = 0;
63
64 int                     FrameCounter = 0;
65
66
67 /* ========================================================================= */
68 /* init/close functions                                                      */
69 /* ========================================================================= */
70
71 void InitProgramInfo(char *argv0,
72                      char *userdata_subdir, char *userdata_subdir_unix,
73                      char *program_title, char *window_title, char *icon_title,
74                      char *x11_icon_filename, char *x11_iconmask_filename,
75                      char *sdl_icon_filename, char *msdos_cursor_filename,
76                      char *cookie_prefix, char *filename_prefix,
77                      int program_version)
78 {
79   program.command_basepath = getBasePath(argv0);
80   program.command_basename = getBaseName(argv0);
81
82   program.userdata_subdir = userdata_subdir;
83   program.userdata_subdir_unix = userdata_subdir_unix;
84   program.userdata_path = getUserGameDataDir();
85
86   program.program_title = program_title;
87   program.window_title = window_title;
88   program.icon_title = icon_title;
89
90   program.x11_icon_filename = x11_icon_filename;
91   program.x11_iconmask_filename = x11_iconmask_filename;
92   program.sdl_icon_filename = sdl_icon_filename;
93   program.msdos_cursor_filename = msdos_cursor_filename;
94
95   program.cookie_prefix = cookie_prefix;
96   program.filename_prefix = filename_prefix;
97
98   program.version_major = VERSION_MAJOR(program_version);
99   program.version_minor = VERSION_MINOR(program_version);
100   program.version_patch = VERSION_PATCH(program_version);
101
102   program.error_filename = getErrorFilename(ERROR_BASENAME);
103   program.error_file = stderr;
104 }
105
106 void InitExitFunction(void (*exit_function)(int))
107 {
108   program.exit_function = exit_function;
109
110   /* set signal handlers to custom exit function */
111   signal(SIGINT, exit_function);
112   signal(SIGTERM, exit_function);
113
114 #if defined(TARGET_SDL)
115   /* set exit function to automatically cleanup SDL stuff after exit() */
116   atexit(SDL_Quit);
117 #endif
118 }
119
120 void InitPlatformDependentStuff(void)
121 {
122 #if defined(PLATFORM_MSDOS)
123   _fmode = O_BINARY;
124 #endif
125
126 #if defined(PLATFORM_MACOSX)
127   updateUserGameDataDir();
128 #endif
129
130 #if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
131   openErrorFile();
132 #endif
133
134 #if defined(TARGET_SDL)
135   if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
136     Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
137
138   SDLNet_Init();
139 #endif
140 }
141
142 void ClosePlatformDependentStuff(void)
143 {
144 #if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
145   closeErrorFile();
146 #endif
147
148 #if defined(PLATFORM_MSDOS)
149   dumpErrorFile();
150 #endif
151 }
152
153 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
154                       int real_sx, int real_sy,
155                       int full_sxsize, int full_sysize,
156                       Bitmap *field_save_buffer)
157 {
158   gfx.sx = sx;
159   gfx.sy = sy;
160   gfx.sxsize = sxsize;
161   gfx.sysize = sysize;
162   gfx.real_sx = real_sx;
163   gfx.real_sy = real_sy;
164   gfx.full_sxsize = full_sxsize;
165   gfx.full_sysize = full_sysize;
166
167   gfx.field_save_buffer = field_save_buffer;
168
169   gfx.background_bitmap = NULL;
170   gfx.background_bitmap_mask = REDRAW_NONE;
171
172   SetDrawDeactivationMask(REDRAW_NONE);         /* do not deactivate drawing */
173   SetDrawBackgroundMask(REDRAW_NONE);           /* deactivate masked drawing */
174 }
175
176 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
177 {
178   gfx.dx = dx;
179   gfx.dy = dy;
180   gfx.dxsize = dxsize;
181   gfx.dysize = dysize;
182 }
183
184 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
185 {
186   gfx.vx = vx;
187   gfx.vy = vy;
188   gfx.vxsize = vxsize;
189   gfx.vysize = vysize;
190 }
191
192 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
193 {
194   /* currently only used by MSDOS code to alloc VRAM buffer, if available */
195   gfx.scrollbuffer_width = scrollbuffer_width;
196   gfx.scrollbuffer_height = scrollbuffer_height;
197 }
198
199 void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
200 {
201   gfx.draw_busy_anim_function = draw_busy_anim_function;
202 }
203
204 void SetDrawDeactivationMask(int draw_deactivation_mask)
205 {
206   gfx.draw_deactivation_mask = draw_deactivation_mask;
207 }
208
209 void SetDrawBackgroundMask(int draw_background_mask)
210 {
211   gfx.draw_background_mask = draw_background_mask;
212 }
213
214 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
215                                int dest_x, int dest_y, int width, int height)
216 {
217   int bitmap_xsize = width;
218   int bitmap_ysize = height;
219   int tile_xsize = tile->width;
220   int tile_ysize = tile->height;
221   int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
222   int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
223   int x, y;
224
225   for (y = 0; y < tile_ysteps; y++)
226   {
227     for (x = 0; x < tile_xsteps; x++)
228     {
229       int draw_x = dest_x + x * tile_xsize;
230       int draw_y = dest_y + y * tile_ysize;
231       int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
232       int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
233
234       BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
235     }
236   }
237 }
238
239 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
240 {
241   if (background_bitmap_tile != NULL)
242     gfx.background_bitmap_mask |= mask;
243   else
244     gfx.background_bitmap_mask &= ~mask;
245
246   if (gfx.background_bitmap == NULL)
247     gfx.background_bitmap = CreateBitmap(video.width, video.height,
248                                          DEFAULT_DEPTH);
249
250   if (background_bitmap_tile == NULL)   /* empty background requested */
251     return;
252
253   if (mask == REDRAW_ALL)
254     DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
255                        0, 0, video.width, video.height);
256   else if (mask == REDRAW_FIELD)
257     DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
258                        gfx.real_sx, gfx.real_sy,
259                        gfx.full_sxsize, gfx.full_sysize);
260   else if (mask == REDRAW_DOOR_1)
261   {
262     DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
263                        gfx.dx, gfx.dy,
264                        gfx.dxsize, gfx.dysize);
265   }
266 }
267
268 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
269 {
270   SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
271 }
272
273 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
274 {
275   SetBackgroundBitmap(NULL, REDRAW_ALL);        /* !!! FIX THIS !!! */
276   SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
277 }
278
279 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
280 {
281   SetBackgroundBitmap(NULL, REDRAW_ALL);        /* !!! FIX THIS !!! */
282   SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
283 }
284
285
286 /* ========================================================================= */
287 /* video functions                                                           */
288 /* ========================================================================= */
289
290 inline static int GetRealDepth(int depth)
291 {
292   return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
293 }
294
295 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
296                                int width, int height, Pixel color)
297 {
298 #if defined(TARGET_SDL)
299   SDLFillRectangle(bitmap, x, y, width, height, color);
300 #else
301   X11FillRectangle(bitmap, x, y, width, height, color);
302 #endif
303 }
304
305 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
306                                int src_x, int src_y, int width, int height,
307                                int dst_x, int dst_y, int mask_mode)
308 {
309 #if defined(TARGET_SDL)
310   SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
311               dst_x, dst_y, mask_mode);
312 #else
313   X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
314               dst_x, dst_y, mask_mode);
315 #endif
316 }
317
318 void InitVideoDisplay(void)
319 {
320 #if defined(TARGET_SDL)
321   SDLInitVideoDisplay();
322 #else
323   X11InitVideoDisplay();
324 #endif
325 }
326
327 void CloseVideoDisplay(void)
328 {
329   KeyboardAutoRepeatOn();
330
331 #if defined(TARGET_SDL)
332   SDL_QuitSubSystem(SDL_INIT_VIDEO);
333 #else
334   if (display)
335     XCloseDisplay(display);
336 #endif
337 }
338
339 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
340 {
341   video.width = width;
342   video.height = height;
343   video.depth = GetRealDepth(depth);
344
345   video.fullscreen_available = FULLSCREEN_STATUS;
346   video.fullscreen_enabled = FALSE;
347   video.fullscreen_modes = NULL;
348   video.fullscreen_mode_current = NULL;
349
350 #if defined(TARGET_SDL)
351   SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
352 #else
353   X11InitVideoBuffer(&backbuffer, &window);
354 #endif
355
356   drawto = backbuffer;
357 }
358
359 Bitmap *CreateBitmapStruct(void)
360 {
361 #if defined(TARGET_SDL)
362   return checked_calloc(sizeof(struct SDLSurfaceInfo));
363 #else
364   return checked_calloc(sizeof(struct X11DrawableInfo));
365 #endif
366 }
367
368 Bitmap *CreateBitmap(int width, int height, int depth)
369 {
370   Bitmap *new_bitmap = CreateBitmapStruct();
371   int real_depth = GetRealDepth(depth);
372
373 #if defined(TARGET_SDL)
374   SDLCreateBitmapContent(new_bitmap, width, height, real_depth);
375 #else
376   X11CreateBitmapContent(new_bitmap, width, height, real_depth);
377 #endif
378
379   new_bitmap->width = width;
380   new_bitmap->height = height;
381
382   return new_bitmap;
383 }
384
385 inline static void FreeBitmapPointers(Bitmap *bitmap)
386 {
387   if (bitmap == NULL)
388     return;
389
390 #if defined(TARGET_SDL)
391   SDLFreeBitmapPointers(bitmap);
392 #else
393   X11FreeBitmapPointers(bitmap);
394 #endif
395
396   checked_free(bitmap->source_filename);
397   bitmap->source_filename = NULL;
398 }
399
400 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
401                                           Bitmap *dst_bitmap)
402 {
403   if (src_bitmap == NULL || dst_bitmap == NULL)
404     return;
405
406   FreeBitmapPointers(dst_bitmap);
407
408   *dst_bitmap = *src_bitmap;
409 }
410
411 void FreeBitmap(Bitmap *bitmap)
412 {
413   if (bitmap == NULL)
414     return;
415
416   FreeBitmapPointers(bitmap);
417
418   free(bitmap);
419 }
420
421 void CloseWindow(DrawWindow *window)
422 {
423 #if defined(TARGET_X11)
424   if (window->drawable)
425   {
426     XUnmapWindow(display, window->drawable);
427     XDestroyWindow(display, window->drawable);
428   }
429   if (window->gc)
430     XFreeGC(display, window->gc);
431 #endif
432 }
433
434 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
435                                        int draw_mask)
436 {
437   if (draw_mask == REDRAW_NONE)
438     return FALSE;
439
440   if (draw_mask & REDRAW_ALL)
441     return TRUE;
442
443   if ((draw_mask & REDRAW_FIELD) &&
444       x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
445     return TRUE;
446
447   if ((draw_mask & REDRAW_DOOR_1) &&
448       x >= gfx.dx && y < gfx.dy + gfx.dysize)
449     return TRUE;
450
451   if ((draw_mask & REDRAW_DOOR_2) &&
452       x >= gfx.dx && y >= gfx.vy)
453     return TRUE;
454
455   return FALSE;
456 }
457
458 boolean DrawingDeactivated(int x, int y, int width, int height)
459 {
460   return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
461 }
462
463 boolean DrawingOnBackground(int x, int y)
464 {
465   return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
466           CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
467 }
468
469 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
470                 int src_x, int src_y, int width, int height,
471                 int dst_x, int dst_y)
472 {
473   if (DrawingDeactivated(dst_x, dst_y, width, height))
474     return;
475
476   sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
477               dst_x, dst_y, BLIT_OPAQUE);
478 }
479
480 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
481                    int fade_mode, int fade_delay, int post_delay,
482                    void (*draw_border_function)(void))
483 {
484 #if defined(TARGET_SDL)
485   SDLFadeRectangle(bitmap_cross, x, y, width, height,
486                    fade_mode, fade_delay, post_delay, draw_border_function);
487 #else
488   X11FadeRectangle(bitmap_cross, x, y, width, height,
489                    fade_mode, fade_delay, post_delay, draw_border_function);
490 #endif
491 }
492
493 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
494                    Pixel color)
495 {
496   if (DrawingDeactivated(x, y, width, height))
497     return;
498
499   sysFillRectangle(bitmap, x, y, width, height, color);
500 }
501
502 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
503 {
504   FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
505 }
506
507 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
508                                 int width, int height)
509 {
510   if (DrawingOnBackground(x, y))
511     BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
512   else
513     ClearRectangle(bitmap, x, y, width, height);
514 }
515
516 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
517 {
518 #if defined(TARGET_X11)
519   if (clip_gc)
520   {
521     bitmap->clip_gc = clip_gc;
522     XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
523   }
524 #endif
525 }
526
527 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
528 {
529 #if defined(TARGET_X11)
530   if (clip_gc)
531   {
532     bitmap->clip_gc = clip_gc;
533     XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
534   }
535 #endif
536 }
537
538 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
539                       int src_x, int src_y, int width, int height,
540                       int dst_x, int dst_y)
541 {
542   if (DrawingDeactivated(dst_x, dst_y, width, height))
543     return;
544
545   sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
546               dst_x, dst_y, BLIT_MASKED);
547 }
548
549 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
550                             int src_x, int src_y, int width, int height,
551                             int dst_x, int dst_y)
552 {
553   if (DrawingOnBackground(dst_x, dst_y))
554   {
555     /* draw background */
556     BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
557                dst_x, dst_y);
558
559     /* draw foreground */
560     SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
561                   dst_x - src_x, dst_y - src_y);
562     BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
563                      dst_x, dst_y);
564   }
565   else
566     BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
567                dst_x, dst_y);
568 }
569
570 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
571                          int to_x, int to_y)
572 {
573 #if defined(TARGET_SDL)
574   SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
575 #else
576   X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
577 #endif
578 }
579
580 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
581                          int to_x, int to_y)
582 {
583 #if defined(TARGET_SDL)
584   SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
585 #else
586   X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
587 #endif
588 }
589
590 #if !defined(TARGET_X11_NATIVE)
591 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
592               int to_x, int to_y, Pixel pixel, int line_width)
593 {
594   int x, y;
595
596   for (x = 0; x < line_width; x++)
597   {
598     for (y = 0; y < line_width; y++)
599     {
600       int dx = x - line_width / 2;
601       int dy = y - line_width / 2;
602
603       if ((x == 0 && y == 0) ||
604           (x == 0 && y == line_width - 1) ||
605           (x == line_width - 1 && y == 0) ||
606           (x == line_width - 1 && y == line_width - 1))
607         continue;
608
609 #if defined(TARGET_SDL)
610       SDLDrawLine(bitmap,
611                   from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
612 #elif defined(TARGET_ALLEGRO)
613       AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
614                       to_x + dx, to_y + dy, pixel);
615 #endif
616     }
617   }
618 }
619 #endif
620
621 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
622 {
623 #if !defined(TARGET_X11_NATIVE)
624   int line_width = 4;
625   int i;
626
627   for (i = 0; i < num_points - 1; i++)
628     DrawLine(bitmap, points[i].x, points[i].y,
629              points[i + 1].x, points[i + 1].y, pixel, line_width);
630
631   /*
632   SDLDrawLines(bitmap->surface, points, num_points, pixel);
633   */
634 #else
635   XSetForeground(display, bitmap->line_gc[1], pixel);
636   XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
637              (XPoint *)points, num_points, CoordModeOrigin);
638 #endif
639 }
640
641 Pixel GetPixel(Bitmap *bitmap, int x, int y)
642 {
643   if (x < 0 || x >= bitmap->width ||
644       y < 0 || y >= bitmap->height)
645     return BLACK_PIXEL;
646
647 #if defined(TARGET_SDL)
648   return SDLGetPixel(bitmap, x, y);
649 #elif defined(TARGET_ALLEGRO)
650   return AllegroGetPixel(bitmap->drawable, x, y);
651 #else
652   return X11GetPixel(bitmap, x, y);
653 #endif
654 }
655
656 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
657                       unsigned int color_g, unsigned int color_b)
658 {
659 #if defined(TARGET_SDL)
660   return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
661 #elif defined(TARGET_ALLEGRO)
662   return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
663 #else
664   return X11GetPixelFromRGB(color_r, color_g, color_b);
665 #endif
666 }
667
668 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
669 {
670   unsigned int color_r = (color >> 16) & 0xff;
671   unsigned int color_g = (color >>  8) & 0xff;
672   unsigned int color_b = (color >>  0) & 0xff;
673
674   return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
675 }
676
677 /* execute all pending screen drawing operations */
678 void FlushDisplay(void)
679 {
680 #ifndef TARGET_SDL
681   XFlush(display);
682 #endif
683 }
684
685 /* execute and wait for all pending screen drawing operations */
686 void SyncDisplay(void)
687 {
688 #ifndef TARGET_SDL
689   XSync(display, FALSE);
690 #endif
691 }
692
693 void KeyboardAutoRepeatOn(void)
694 {
695 #if defined(TARGET_SDL)
696   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
697                       SDL_DEFAULT_REPEAT_INTERVAL / 2);
698   SDL_EnableUNICODE(1);
699 #else
700   if (display)
701     XAutoRepeatOn(display);
702 #endif
703 }
704
705 void KeyboardAutoRepeatOff(void)
706 {
707 #if defined(TARGET_SDL)
708   SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
709   SDL_EnableUNICODE(0);
710 #else
711   if (display)
712     XAutoRepeatOff(display);
713 #endif
714 }
715
716 boolean PointerInWindow(DrawWindow *window)
717 {
718 #if defined(TARGET_SDL)
719   return TRUE;
720 #else
721   Window root, child;
722   int root_x, root_y;
723   unsigned int mask;
724   int win_x, win_y;
725
726   /* if XQueryPointer() returns False, the pointer
727      is not on the same screen as the specified window */
728   return XQueryPointer(display, window->drawable, &root, &child,
729                        &root_x, &root_y, &win_x, &win_y, &mask);
730 #endif
731 }
732
733 boolean SetVideoMode(boolean fullscreen)
734 {
735 #if defined(TARGET_SDL)
736   return SDLSetVideoMode(&backbuffer, fullscreen);
737 #else
738   boolean success = TRUE;
739
740   if (fullscreen && video.fullscreen_available)
741   {
742     Error(ERR_WARN, "fullscreen not available in X11 version");
743
744     /* display error message only once */
745     video.fullscreen_available = FALSE;
746
747     success = FALSE;
748   }
749
750   return success;
751 #endif
752 }
753
754 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
755 {
756 #if defined(TARGET_SDL)
757   if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
758       (!fullscreen && video.fullscreen_enabled))
759     fullscreen = SetVideoMode(fullscreen);
760 #endif
761
762   return fullscreen;
763 }
764
765 Bitmap *LoadImage(char *filename)
766 {
767   Bitmap *new_bitmap;
768
769 #if defined(TARGET_SDL)
770   new_bitmap = SDLLoadImage(filename);
771 #else
772   new_bitmap = X11LoadImage(filename);
773 #endif
774
775   if (new_bitmap)
776     new_bitmap->source_filename = getStringCopy(filename);
777
778   return new_bitmap;
779 }
780
781 Bitmap *LoadCustomImage(char *basename)
782 {
783   char *filename = getCustomImageFilename(basename);
784   Bitmap *new_bitmap;
785
786   if (filename == NULL)
787     Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
788
789   if ((new_bitmap = LoadImage(filename)) == NULL)
790     Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
791
792   return new_bitmap;
793 }
794
795 void ReloadCustomImage(Bitmap *bitmap, char *basename)
796 {
797   char *filename = getCustomImageFilename(basename);
798   Bitmap *new_bitmap;
799
800   if (filename == NULL)         /* (should never happen) */
801   {
802     Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
803     return;
804   }
805
806   if (strEqual(filename, bitmap->source_filename))
807   {
808     /* The old and new image are the same (have the same filename and path).
809        This usually means that this image does not exist in this graphic set
810        and a fallback to the existing image is done. */
811
812     return;
813   }
814
815   if ((new_bitmap = LoadImage(filename)) == NULL)
816   {
817     Error(ERR_WARN, "LoadImage() failed: %s", GetError());
818     return;
819   }
820
821   if (bitmap->width != new_bitmap->width ||
822       bitmap->height != new_bitmap->height)
823   {
824     Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
825           filename);
826     FreeBitmap(new_bitmap);
827     return;
828   }
829
830   TransferBitmapPointers(new_bitmap, bitmap);
831   free(new_bitmap);
832 }
833
834 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
835 {
836   Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
837
838 #if defined(TARGET_SDL)
839   SDLZoomBitmap(src_bitmap, dst_bitmap);
840 #else
841   X11ZoomBitmap(src_bitmap, dst_bitmap);
842 #endif
843
844   return dst_bitmap;
845 }
846
847 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
848                                 boolean create_small_bitmaps)
849 {
850   Bitmap swap_bitmap;
851   Bitmap *new_bitmap;
852   Bitmap *tmp_bitmap_1;
853   Bitmap *tmp_bitmap_2;
854   Bitmap *tmp_bitmap_4;
855   Bitmap *tmp_bitmap_8;
856   Bitmap *tmp_bitmap_16;
857   Bitmap *tmp_bitmap_32;
858   int width_1, height_1;
859   int width_2, height_2;
860   int width_4, height_4;
861   int width_8, height_8;
862   int width_16, height_16;
863   int width_32, height_32;
864   int new_width, new_height;
865
866   /* calculate new image dimensions for normal sized image */
867   width_1  = old_bitmap->width  * zoom_factor;
868   height_1 = old_bitmap->height * zoom_factor;
869
870   /* get image with normal size (this might require scaling up) */
871   if (zoom_factor != 1)
872     tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
873   else
874     tmp_bitmap_1 = old_bitmap;
875
876   /* this is only needed to make compilers happy */
877   tmp_bitmap_2 = NULL;
878   tmp_bitmap_4 = NULL;
879   tmp_bitmap_8 = NULL;
880   tmp_bitmap_16 = NULL;
881   tmp_bitmap_32 = NULL;
882
883   if (create_small_bitmaps)
884   {
885     /* calculate new image dimensions for small images */
886     width_2  = width_1  / 2;
887     height_2 = height_1 / 2;
888     width_4  = width_1  / 4;
889     height_4 = height_1 / 4;
890     width_8  = width_1  / 8;
891     height_8 = height_1 / 8;
892     width_16  = width_1  / 16;
893     height_16 = height_1 / 16;
894     width_32  = width_1  / 32;
895     height_32 = height_1 / 32;
896
897     UPDATE_BUSY_STATE();
898
899     /* get image with 1/2 of normal size (for use in the level editor) */
900     if (zoom_factor != 2)
901       tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
902     else
903       tmp_bitmap_2 = old_bitmap;
904
905     UPDATE_BUSY_STATE();
906
907     /* get image with 1/4 of normal size (for use in the level editor) */
908     if (zoom_factor != 4)
909       tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
910     else
911       tmp_bitmap_4 = old_bitmap;
912
913     UPDATE_BUSY_STATE();
914
915     /* get image with 1/8 of normal size (for use on the preview screen) */
916     if (zoom_factor != 8)
917       tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
918     else
919       tmp_bitmap_8 = old_bitmap;
920
921     UPDATE_BUSY_STATE();
922
923     /* get image with 1/16 of normal size (for use on the preview screen) */
924     if (zoom_factor != 16)
925       tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
926     else
927       tmp_bitmap_16 = old_bitmap;
928
929     UPDATE_BUSY_STATE();
930
931     /* get image with 1/32 of normal size (for use on the preview screen) */
932     if (zoom_factor != 32)
933       tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
934     else
935       tmp_bitmap_32 = old_bitmap;
936
937     UPDATE_BUSY_STATE();
938   }
939
940 #if 0
941   /* if image was scaled up, create new clipmask for normal size image */
942   if (zoom_factor != 1)
943   {
944 #if defined(TARGET_X11)
945     if (old_bitmap->clip_mask)
946       XFreePixmap(display, old_bitmap->clip_mask);
947
948     old_bitmap->clip_mask =
949       Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
950
951     XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
952 #else
953     SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
954
955     if (old_bitmap->surface_masked)
956       SDL_FreeSurface(old_bitmap->surface_masked);
957
958     SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
959                     SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
960     if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
961       Error(ERR_EXIT, "SDL_DisplayFormat() failed");
962     SDL_SetColorKey(tmp_surface_1, 0, 0);       /* reset transparent pixel */
963 #endif
964   }
965 #endif
966
967   if (create_small_bitmaps)
968   {
969     new_width  = width_1;
970     new_height = height_1 + (height_1 + 1) / 2;     /* prevent odd height */
971
972     new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
973
974     BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
975     BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
976                0, height_1);
977     BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
978                width_1 / 2, height_1);
979     BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
980                3 * width_1 / 4, height_1);
981     BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
982                7 * width_1 / 8, height_1);
983     BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
984                15 * width_1 / 16, height_1);
985
986     UPDATE_BUSY_STATE();
987   }
988   else
989   {
990     new_width  = width_1;
991     new_height = height_1;
992
993     new_bitmap = tmp_bitmap_1;  /* directly use tmp_bitmap_1 as new bitmap */
994   }
995
996   if (create_small_bitmaps)
997   {
998     /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
999     if (zoom_factor != 1)
1000       FreeBitmap(tmp_bitmap_1);
1001
1002     if (zoom_factor != 2)
1003       FreeBitmap(tmp_bitmap_2);
1004
1005     if (zoom_factor != 4)
1006       FreeBitmap(tmp_bitmap_4);
1007
1008     if (zoom_factor != 8)
1009       FreeBitmap(tmp_bitmap_8);
1010
1011     if (zoom_factor != 16)
1012       FreeBitmap(tmp_bitmap_16);
1013
1014     if (zoom_factor != 32)
1015       FreeBitmap(tmp_bitmap_32);
1016   }
1017
1018   /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1019 #if defined(TARGET_SDL)
1020   swap_bitmap.surface = old_bitmap->surface;
1021   old_bitmap->surface = new_bitmap->surface;
1022   new_bitmap->surface = swap_bitmap.surface;
1023 #else
1024   swap_bitmap.drawable = old_bitmap->drawable;
1025   old_bitmap->drawable = new_bitmap->drawable;
1026   new_bitmap->drawable = swap_bitmap.drawable;
1027 #endif
1028
1029   old_bitmap->width  = new_bitmap->width;
1030   old_bitmap->height = new_bitmap->height;
1031
1032 #if 1
1033   /* this replaces all blit masks created when loading -- maybe optimize this */
1034   {
1035 #if defined(TARGET_X11)
1036     if (old_bitmap->clip_mask)
1037       XFreePixmap(display, old_bitmap->clip_mask);
1038
1039     old_bitmap->clip_mask =
1040       Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1041
1042     XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1043 #else
1044     SDL_Surface *old_surface = old_bitmap->surface;
1045
1046     if (old_bitmap->surface_masked)
1047       SDL_FreeSurface(old_bitmap->surface_masked);
1048
1049     SDL_SetColorKey(old_surface, SDL_SRCCOLORKEY,
1050                     SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1051     if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1052       Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1053     SDL_SetColorKey(old_surface, 0, 0);         /* reset transparent pixel */
1054 #endif
1055   }
1056 #endif
1057
1058   UPDATE_BUSY_STATE();
1059
1060   FreeBitmap(new_bitmap);       /* this actually frees the _old_ bitmap now */
1061 }
1062
1063 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1064 {
1065   CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1066 }
1067
1068 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1069 {
1070   CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1071 }
1072
1073
1074 /* ------------------------------------------------------------------------- */
1075 /* mouse pointer functions                                                   */
1076 /* ------------------------------------------------------------------------- */
1077
1078 #if !defined(PLATFORM_MSDOS)
1079 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER            0
1080 /* XPM image definitions */
1081 static const char *cursor_image_none[] =
1082 {
1083   /* width height num_colors chars_per_pixel */
1084   "    16    16        3            1",
1085
1086   /* colors */
1087   "X c #000000",
1088   ". c #ffffff",
1089   "  c None",
1090
1091   /* pixels */
1092   "                ",
1093   "                ",
1094   "                ",
1095   "                ",
1096   "                ",
1097   "                ",
1098   "                ",
1099   "                ",
1100   "                ",
1101   "                ",
1102   "                ",
1103   "                ",
1104   "                ",
1105   "                ",
1106   "                ",
1107   "                ",
1108
1109   /* hot spot */
1110   "0,0"
1111 };
1112 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1113 static const char *cursor_image_dot[] =
1114 {
1115   /* width height num_colors chars_per_pixel */
1116   "    16    16        3            1",
1117
1118   /* colors */
1119   "X c #000000",
1120   ". c #ffffff",
1121   "  c None",
1122
1123   /* pixels */
1124   " X              ",
1125   "X.X             ",
1126   " X              ",
1127   "                ",
1128   "                ",
1129   "                ",
1130   "                ",
1131   "                ",
1132   "                ",
1133   "                ",
1134   "                ",
1135   "                ",
1136   "                ",
1137   "                ",
1138   "                ",
1139   "                ",
1140
1141   /* hot spot */
1142   "1,1"
1143 };
1144 static const char **cursor_image_playfield = cursor_image_dot;
1145 #else
1146 /* some people complained about a "white dot" on the screen and thought it
1147    was a graphical error... OK, let's just remove the whole pointer :-) */
1148 static const char **cursor_image_playfield = cursor_image_none;
1149 #endif
1150
1151 #if defined(TARGET_SDL)
1152 static const int cursor_bit_order = BIT_ORDER_MSB;
1153 #elif defined(TARGET_X11_NATIVE)
1154 static const int cursor_bit_order = BIT_ORDER_LSB;
1155 #endif
1156
1157 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1158 {
1159   struct MouseCursorInfo *cursor;
1160   boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1161   int header_lines = 4;
1162   int x, y, i;
1163
1164   cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1165
1166   sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1167
1168   i = -1;
1169   for (y = 0; y < cursor->width; y++)
1170   {
1171     for (x = 0; x < cursor->height; x++)
1172     {
1173       int bit_nr = x % 8;
1174       int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1175
1176       if (bit_nr == 0)
1177       {
1178         i++;
1179         cursor->data[i] = cursor->mask[i] = 0;
1180       }
1181
1182       switch (image[header_lines + y][x])
1183       {
1184         case 'X':
1185           cursor->data[i] |= bit_mask;
1186           cursor->mask[i] |= bit_mask;
1187           break;
1188
1189         case '.':
1190           cursor->mask[i] |= bit_mask;
1191           break;
1192
1193         case ' ':
1194           break;
1195       }
1196     }
1197   }
1198
1199   sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1200
1201   return cursor;
1202 }
1203 #endif  /* !PLATFORM_MSDOS */
1204
1205 void SetMouseCursor(int mode)
1206 {
1207 #if !defined(PLATFORM_MSDOS)
1208   static struct MouseCursorInfo *cursor_none = NULL;
1209   static struct MouseCursorInfo *cursor_playfield = NULL;
1210   struct MouseCursorInfo *cursor_new;
1211
1212   if (cursor_none == NULL)
1213     cursor_none = get_cursor_from_image(cursor_image_none);
1214
1215   if (cursor_playfield == NULL)
1216     cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1217
1218   cursor_new = (mode == CURSOR_DEFAULT   ? NULL :
1219                 mode == CURSOR_NONE      ? cursor_none :
1220                 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1221
1222 #if defined(TARGET_SDL)
1223   SDLSetMouseCursor(cursor_new);
1224 #elif defined(TARGET_X11_NATIVE)
1225   X11SetMouseCursor(cursor_new);
1226 #endif
1227 #endif
1228 }
1229
1230
1231 /* ========================================================================= */
1232 /* audio functions                                                           */
1233 /* ========================================================================= */
1234
1235 void OpenAudio(void)
1236 {
1237   /* always start with reliable default values */
1238   audio.sound_available = FALSE;
1239   audio.music_available = FALSE;
1240   audio.loops_available = FALSE;
1241
1242   audio.sound_enabled = FALSE;
1243   audio.sound_deactivated = FALSE;
1244
1245   audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1246   audio.mixer_pid = 0;
1247   audio.device_name = NULL;
1248   audio.device_fd = -1;
1249
1250   audio.num_channels = 0;
1251   audio.music_channel = 0;
1252   audio.first_sound_channel = 0;
1253
1254 #if defined(TARGET_SDL)
1255   SDLOpenAudio();
1256 #elif defined(PLATFORM_UNIX)
1257   UnixOpenAudio();
1258 #elif defined(PLATFORM_MSDOS)
1259   MSDOSOpenAudio();
1260 #endif
1261 }
1262
1263 void CloseAudio(void)
1264 {
1265 #if defined(TARGET_SDL)
1266   SDLCloseAudio();
1267 #elif defined(PLATFORM_UNIX)
1268   UnixCloseAudio();
1269 #elif defined(PLATFORM_MSDOS)
1270   MSDOSCloseAudio();
1271 #endif
1272
1273   audio.sound_enabled = FALSE;
1274 }
1275
1276 void SetAudioMode(boolean enabled)
1277 {
1278   if (!audio.sound_available)
1279     return;
1280
1281   audio.sound_enabled = enabled;
1282 }
1283
1284
1285 /* ========================================================================= */
1286 /* event functions                                                           */
1287 /* ========================================================================= */
1288
1289 void InitEventFilter(EventFilter filter_function)
1290 {
1291 #if defined(TARGET_SDL)
1292   /* set event filter to filter out certain events */
1293   SDL_SetEventFilter(filter_function);
1294 #endif
1295 }
1296
1297 boolean PendingEvent(void)
1298 {
1299 #if defined(TARGET_SDL)
1300   return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1301 #else
1302   return (XPending(display) ? TRUE : FALSE);
1303 #endif
1304 }
1305
1306 void NextEvent(Event *event)
1307 {
1308 #if defined(TARGET_SDL)
1309   SDLNextEvent(event);
1310 #else
1311   XNextEvent(display, event);
1312 #endif
1313 }
1314
1315 void PeekEvent(Event *event)
1316 {
1317 #if defined(TARGET_SDL)
1318   SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1319 #else
1320   XPeekEvent(display, event);
1321 #endif
1322 }
1323
1324 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1325 {
1326 #if defined(TARGET_SDL)
1327
1328 #if 0
1329   printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1330          (int)event->keysym.unicode,
1331          (int)event->keysym.sym,
1332          (int)SDL_GetModState());
1333 #endif
1334
1335   if (with_modifiers &&
1336       event->keysym.unicode > 0x0000 &&
1337       event->keysym.unicode < 0x2000)
1338     return event->keysym.unicode;
1339   else
1340     return event->keysym.sym;
1341
1342 #else
1343
1344 #if 0
1345   printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1346          (int)XLookupKeysym(event, event->state),
1347          (int)XLookupKeysym(event, 0));
1348 #endif
1349
1350   if (with_modifiers)
1351     return XLookupKeysym(event, event->state);
1352   else
1353     return XLookupKeysym(event, 0);
1354 #endif
1355 }
1356
1357 KeyMod HandleKeyModState(Key key, int key_status)
1358 {
1359   static KeyMod current_modifiers = KMOD_None;
1360
1361   if (key != KSYM_UNDEFINED)    /* new key => check for modifier key change */
1362   {
1363     KeyMod new_modifier = KMOD_None;
1364
1365     switch(key)
1366     {
1367       case KSYM_Shift_L:
1368         new_modifier = KMOD_Shift_L;
1369         break;
1370       case KSYM_Shift_R:
1371         new_modifier = KMOD_Shift_R;
1372         break;
1373       case KSYM_Control_L:
1374         new_modifier = KMOD_Control_L;
1375         break;
1376       case KSYM_Control_R:
1377         new_modifier = KMOD_Control_R;
1378         break;
1379       case KSYM_Meta_L:
1380         new_modifier = KMOD_Meta_L;
1381         break;
1382       case KSYM_Meta_R:
1383         new_modifier = KMOD_Meta_R;
1384         break;
1385       case KSYM_Alt_L:
1386         new_modifier = KMOD_Alt_L;
1387         break;
1388       case KSYM_Alt_R:
1389         new_modifier = KMOD_Alt_R;
1390         break;
1391       default:
1392         break;
1393     }
1394
1395     if (key_status == KEY_PRESSED)
1396       current_modifiers |= new_modifier;
1397     else
1398       current_modifiers &= ~new_modifier;
1399   }
1400
1401   return current_modifiers;
1402 }
1403
1404 KeyMod GetKeyModState()
1405 {
1406 #if defined(TARGET_SDL)
1407   return (KeyMod)SDL_GetModState();
1408 #else
1409   return HandleKeyModState(KSYM_UNDEFINED, 0);
1410 #endif
1411 }
1412
1413 KeyMod GetKeyModStateFromEvents()
1414 {
1415   /* always use key modifier state as tracked from key events (this is needed
1416      if the modifier key event was injected into the event queue, but the key
1417      was not really pressed on keyboard -- SDL_GetModState() seems to directly
1418      query the keys as held pressed on the keyboard) -- this case is currently
1419      only used to filter out clipboard insert events from "True X-Mouse" tool */
1420
1421   return HandleKeyModState(KSYM_UNDEFINED, 0);
1422 }
1423
1424 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1425 {
1426   if (event->type != EVENT_CLIENTMESSAGE)
1427     return FALSE;
1428
1429 #if defined(TARGET_SDL)
1430   return TRUE;          /* the only possible message here is SDL_QUIT */
1431 #elif defined(PLATFORM_UNIX)
1432   if ((event->window == window->drawable) &&
1433       (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1434     return TRUE;
1435 #endif
1436
1437   return FALSE;
1438 }
1439
1440
1441 /* ========================================================================= */
1442 /* joystick functions                                                        */
1443 /* ========================================================================= */
1444
1445 void InitJoysticks()
1446 {
1447   int i;
1448
1449 #if defined(NO_JOYSTICK)
1450   return;       /* joysticks generally deactivated by compile-time directive */
1451 #endif
1452
1453   /* always start with reliable default values */
1454   joystick.status = JOYSTICK_NOT_AVAILABLE;
1455   for (i = 0; i < MAX_PLAYERS; i++)
1456     joystick.fd[i] = -1;                /* joystick device closed */
1457
1458 #if defined(TARGET_SDL)
1459   SDLInitJoysticks();
1460 #elif defined(PLATFORM_UNIX)
1461   UnixInitJoysticks();
1462 #elif defined(PLATFORM_MSDOS)
1463   MSDOSInitJoysticks();
1464 #endif
1465
1466 #if 0
1467   for (i = 0; i < MAX_PLAYERS; i++)
1468     printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1469 #endif
1470 }
1471
1472 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1473 {
1474 #if defined(TARGET_SDL)
1475   return SDLReadJoystick(nr, x, y, b1, b2);
1476 #elif defined(PLATFORM_UNIX)
1477   return UnixReadJoystick(nr, x, y, b1, b2);
1478 #elif defined(PLATFORM_MSDOS)
1479   return MSDOSReadJoystick(nr, x, y, b1, b2);
1480 #endif
1481 }