1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
19 #if defined(PLATFORM_MSDOS)
31 /* ========================================================================= */
32 /* exported variables */
33 /* ========================================================================= */
35 struct ProgramInfo program;
36 struct OptionInfo options;
37 struct VideoSystemInfo video;
38 struct AudioSystemInfo audio;
40 struct ArtworkInfo artwork;
41 struct JoystickInfo joystick;
42 struct SetupInfo setup;
44 LevelDirTree *leveldir_first_all = NULL;
45 LevelDirTree *leveldir_first = NULL;
46 LevelDirTree *leveldir_current = NULL;
49 struct LevelStats level_stats[MAX_LEVELS];
51 Display *display = NULL;
52 Visual *visual = NULL;
56 DrawWindow *window = NULL;
57 DrawBuffer *backbuffer = NULL;
58 DrawBuffer *drawto = NULL;
60 int button_status = MB_NOT_PRESSED;
61 boolean motion_status = FALSE;
62 #if defined(TARGET_SDL2)
63 boolean keyrepeat_status = TRUE;
66 int redraw_mask = REDRAW_NONE;
72 /* ========================================================================= */
73 /* init/close functions */
74 /* ========================================================================= */
76 void InitProgramInfo(char *argv0,
77 char *userdata_subdir, char *userdata_subdir_unix,
78 char *program_title, char *window_title, char *icon_title,
79 char *x11_icon_filename, char *x11_iconmask_filename,
80 char *sdl_icon_filename, char *msdos_cursor_filename,
81 char *cookie_prefix, char *filename_prefix,
84 program.command_basepath = getBasePath(argv0);
85 program.command_basename = getBaseName(argv0);
87 program.userdata_subdir = userdata_subdir;
88 program.userdata_subdir_unix = userdata_subdir_unix;
89 program.userdata_path = getUserGameDataDir();
91 program.program_title = program_title;
92 program.window_title = window_title;
93 program.icon_title = icon_title;
95 program.x11_icon_filename = x11_icon_filename;
96 program.x11_iconmask_filename = x11_iconmask_filename;
97 program.sdl_icon_filename = sdl_icon_filename;
98 program.msdos_cursor_filename = msdos_cursor_filename;
100 program.cookie_prefix = cookie_prefix;
101 program.filename_prefix = filename_prefix;
103 program.version_major = VERSION_MAJOR(program_version);
104 program.version_minor = VERSION_MINOR(program_version);
105 program.version_patch = VERSION_PATCH(program_version);
107 program.error_filename = getErrorFilename(ERROR_BASENAME);
108 program.error_file = stderr;
111 void InitExitMessageFunction(void (*exit_message_function)(char *, va_list))
113 program.exit_message_function = exit_message_function;
116 void InitExitFunction(void (*exit_function)(int))
118 program.exit_function = exit_function;
120 /* set signal handlers to custom exit function */
121 signal(SIGINT, exit_function);
122 signal(SIGTERM, exit_function);
124 #if defined(TARGET_SDL)
125 /* set exit function to automatically cleanup SDL stuff after exit() */
130 void InitPlatformDependentStuff(void)
132 // this is initialized in GetOptions(), but may already be used before
133 options.verbose = TRUE;
135 #if defined(PLATFORM_MSDOS)
139 #if defined(PLATFORM_MACOSX)
140 updateUserGameDataDir();
146 #if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
151 #if defined(TARGET_SDL)
152 #if defined(TARGET_SDL2)
153 int sdl_init_flags = SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE;
155 int sdl_init_flags = SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE;
158 if (SDL_Init(sdl_init_flags) < 0)
159 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
165 void ClosePlatformDependentStuff(void)
167 #if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
171 #if defined(PLATFORM_MSDOS)
176 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
177 int real_sx, int real_sy,
178 int full_sxsize, int full_sysize,
179 Bitmap *field_save_buffer)
185 gfx.real_sx = real_sx;
186 gfx.real_sy = real_sy;
187 gfx.full_sxsize = full_sxsize;
188 gfx.full_sysize = full_sysize;
190 gfx.field_save_buffer = field_save_buffer;
193 gfx.background_bitmap = NULL;
194 gfx.background_bitmap_mask = REDRAW_NONE;
197 SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
198 SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
201 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
209 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
217 void InitGfxWindowInfo(int win_xsize, int win_ysize)
219 gfx.win_xsize = win_xsize;
220 gfx.win_ysize = win_ysize;
223 gfx.background_bitmap_mask = REDRAW_NONE;
225 ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize, DEFAULT_DEPTH);
229 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
231 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
232 /* 2009-03-24: also (temporarily?) used for overlapping blit workaround */
233 gfx.scrollbuffer_width = scrollbuffer_width;
234 gfx.scrollbuffer_height = scrollbuffer_height;
237 void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height)
239 gfx.clipping_enabled = enabled;
242 gfx.clip_width = width;
243 gfx.clip_height = height;
246 void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
248 gfx.draw_busy_anim_function = draw_busy_anim_function;
251 void InitGfxCustomArtworkInfo()
253 gfx.override_level_graphics = FALSE;
254 gfx.override_level_sounds = FALSE;
255 gfx.override_level_music = FALSE;
257 gfx.draw_init_text = TRUE;
260 void SetDrawDeactivationMask(int draw_deactivation_mask)
262 gfx.draw_deactivation_mask = draw_deactivation_mask;
265 void SetDrawBackgroundMask(int draw_background_mask)
267 gfx.draw_background_mask = draw_background_mask;
272 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
273 int dest_x, int dest_y, int width, int height)
275 int bitmap_xsize = width;
276 int bitmap_ysize = height;
277 int tile_xsize = tile->width;
278 int tile_ysize = tile->height;
279 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
280 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
283 for (y = 0; y < tile_ysteps; y++)
285 for (x = 0; x < tile_xsteps; x++)
287 int draw_x = dest_x + x * tile_xsize;
288 int draw_y = dest_y + y * tile_ysize;
289 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
290 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
292 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
297 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
299 if (background_bitmap_tile != NULL)
300 gfx.background_bitmap_mask |= mask;
302 gfx.background_bitmap_mask &= ~mask;
305 if (gfx.background_bitmap == NULL)
306 gfx.background_bitmap = CreateBitmap(video.width, video.height,
310 if (background_bitmap_tile == NULL) /* empty background requested */
313 if (mask == REDRAW_ALL)
314 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
315 0, 0, video.width, video.height);
316 else if (mask == REDRAW_FIELD)
317 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
318 gfx.real_sx, gfx.real_sy,
319 gfx.full_sxsize, gfx.full_sysize);
320 else if (mask == REDRAW_DOOR_1)
322 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
324 gfx.dxsize, gfx.dysize);
330 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
332 if (background_bitmap_tile != NULL)
333 gfx.background_bitmap_mask |= mask;
335 gfx.background_bitmap_mask &= ~mask;
338 if (gfx.background_bitmap == NULL)
339 gfx.background_bitmap = CreateBitmap(video.width, video.height,
343 if (background_bitmap_tile == NULL) /* empty background requested */
346 if (mask == REDRAW_ALL)
347 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
348 0, 0, video.width, video.height);
349 else if (mask == REDRAW_FIELD)
350 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
351 gfx.real_sx, gfx.real_sy, gfx.full_sxsize, gfx.full_sysize);
352 else if (mask == REDRAW_DOOR_1)
354 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
355 gfx.dx, gfx.dy, gfx.dxsize, gfx.dysize);
361 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
363 /* remove every mask before setting mask for window */
364 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
365 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
366 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
369 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
371 /* remove window area mask before setting mask for main area */
372 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
373 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
374 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
377 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
379 /* remove window area mask before setting mask for door area */
380 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
381 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
382 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
386 /* ========================================================================= */
387 /* video functions */
388 /* ========================================================================= */
390 inline static int GetRealDepth(int depth)
392 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
395 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
396 int width, int height, Pixel color)
398 #if defined(TARGET_SDL)
399 SDLFillRectangle(bitmap, x, y, width, height, color);
401 X11FillRectangle(bitmap, x, y, width, height, color);
405 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
406 int src_x, int src_y, int width, int height,
407 int dst_x, int dst_y, int mask_mode)
409 #if defined(TARGET_SDL)
410 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
411 dst_x, dst_y, mask_mode);
413 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
414 dst_x, dst_y, mask_mode);
418 void InitVideoDisplay(void)
420 #if defined(TARGET_SDL)
421 SDLInitVideoDisplay();
423 X11InitVideoDisplay();
427 void CloseVideoDisplay(void)
429 KeyboardAutoRepeatOn();
431 #if defined(TARGET_SDL)
432 SDL_QuitSubSystem(SDL_INIT_VIDEO);
435 XCloseDisplay(display);
439 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
442 printf("::: InitVideoBuffer\n");
446 video.height = height;
447 video.depth = GetRealDepth(depth);
449 video.fullscreen_available = FULLSCREEN_STATUS;
450 video.fullscreen_enabled = FALSE;
451 // video.fullscreen_initial = FALSE;
453 video.fullscreen_mode_current = NULL;
454 video.fullscreen_modes = NULL;
457 video.window_scaling_available = WINDOW_SCALING_STATUS;
459 #if defined(TARGET_SDL)
460 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
462 X11InitVideoBuffer(&backbuffer, &window);
468 inline static void FreeBitmapPointers(Bitmap *bitmap)
473 #if defined(TARGET_SDL)
474 SDLFreeBitmapPointers(bitmap);
476 X11FreeBitmapPointers(bitmap);
479 checked_free(bitmap->source_filename);
480 bitmap->source_filename = NULL;
483 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
486 if (src_bitmap == NULL || dst_bitmap == NULL)
489 FreeBitmapPointers(dst_bitmap);
491 *dst_bitmap = *src_bitmap;
494 void FreeBitmap(Bitmap *bitmap)
499 FreeBitmapPointers(bitmap);
504 Bitmap *CreateBitmapStruct(void)
506 #if defined(TARGET_SDL)
507 return checked_calloc(sizeof(struct SDLSurfaceInfo));
509 return checked_calloc(sizeof(struct X11DrawableInfo));
513 Bitmap *CreateBitmap(int width, int height, int depth)
515 Bitmap *new_bitmap = CreateBitmapStruct();
516 int real_width = MAX(1, width); /* prevent zero bitmap width */
517 int real_height = MAX(1, height); /* prevent zero bitmap height */
518 int real_depth = GetRealDepth(depth);
520 #if defined(TARGET_SDL)
521 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
523 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
526 new_bitmap->width = real_width;
527 new_bitmap->height = real_height;
532 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
534 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
538 *bitmap = new_bitmap;
542 TransferBitmapPointers(new_bitmap, *bitmap);
547 void CloseWindow(DrawWindow *window)
549 #if defined(TARGET_X11)
550 X11CloseWindow(window);
554 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
557 if (draw_mask == REDRAW_NONE)
560 if (draw_mask & REDRAW_ALL)
563 if ((draw_mask & REDRAW_FIELD) &&
564 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
567 if ((draw_mask & REDRAW_DOOR_1) &&
568 x >= gfx.dx && y < gfx.dy + gfx.dysize)
571 if ((draw_mask & REDRAW_DOOR_2) &&
572 x >= gfx.dx && y >= gfx.vy)
578 boolean DrawingDeactivated(int x, int y, int width, int height)
580 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
583 boolean DrawingOnBackground(int x, int y)
585 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
586 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
589 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
590 int *width, int *height, boolean is_dest)
593 int clip_x, clip_y, clip_width, clip_height;
595 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
597 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
598 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
599 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
600 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
606 clip_width = bitmap->width;
607 clip_height = bitmap->height;
610 /* skip if rectangle completely outside bitmap */
612 if (*x + *width <= clip_x ||
613 *y + *height <= clip_y ||
614 *x >= clip_x + clip_width ||
615 *y >= clip_y + clip_height)
618 /* clip if rectangle overlaps bitmap */
622 *width -= clip_x - *x;
625 else if (*x + *width > clip_x + clip_width)
627 *width = clip_x + clip_width - *x;
632 *height -= clip_y - *y;
635 else if (*y + *height > clip_y + clip_height)
637 *height = clip_y + clip_height - *y;
644 /* skip if rectangle completely outside bitmap */
646 if (*x + *width <= 0 ||
648 *x >= bitmap->width ||
649 *y >= bitmap->height)
652 /* clip if rectangle overlaps bitmap */
659 else if (*x + *width > bitmap->width)
661 *width = bitmap->width - *x;
669 else if (*y + *height > bitmap->height)
671 *height = bitmap->height - *y;
678 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
679 int src_x, int src_y, int width, int height,
680 int dst_x, int dst_y)
682 int dst_x_unclipped = dst_x;
683 int dst_y_unclipped = dst_y;
685 if (DrawingDeactivated(dst_x, dst_y, width, height))
689 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
690 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
693 /* source x/y might need adjustment if destination x/y was clipped top/left */
694 src_x += dst_x - dst_x_unclipped;
695 src_y += dst_y - dst_y_unclipped;
698 /* skip if rectangle starts outside bitmap */
699 if (src_x >= src_bitmap->width ||
700 src_y >= src_bitmap->height ||
701 dst_x >= dst_bitmap->width ||
702 dst_y >= dst_bitmap->height)
705 /* clip if rectangle overlaps bitmap */
706 if (src_x + width > src_bitmap->width)
707 width = src_bitmap->width - src_x;
708 if (src_y + height > src_bitmap->height)
709 height = src_bitmap->height - src_y;
710 if (dst_x + width > dst_bitmap->width)
711 width = dst_bitmap->width - dst_x;
712 if (dst_y + height > dst_bitmap->height)
713 height = dst_bitmap->height - dst_y;
717 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
719 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
720 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
721 but is already fixed in SVN and should therefore finally be fixed with
722 the next official SDL release, which is probably version 1.2.14.) */
724 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
725 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
726 #if defined(TARGET_SDL2)
727 if (src_bitmap == dst_bitmap)
729 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
731 /* needed when blitting directly to same bitmap -- should not be needed with
732 recent SDL libraries, but apparently does not work in 1.2.11 directly */
734 static Bitmap *tmp_bitmap = NULL;
735 static int tmp_bitmap_xsize = 0;
736 static int tmp_bitmap_ysize = 0;
738 /* start with largest static bitmaps for initial bitmap size ... */
739 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
741 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
742 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
745 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
746 if (src_bitmap->width > tmp_bitmap_xsize ||
747 src_bitmap->height > tmp_bitmap_ysize)
749 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
750 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
752 FreeBitmap(tmp_bitmap);
757 if (tmp_bitmap == NULL)
758 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
761 sysCopyArea(src_bitmap, tmp_bitmap,
762 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
763 sysCopyArea(tmp_bitmap, dst_bitmap,
764 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
774 if (dst_x < gfx.sx + gfx.sxsize)
775 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
776 FrameCounter, dst_x, dst_y, width, height);
779 sysCopyArea(src_bitmap, dst_bitmap,
780 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
783 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
784 int src_x, int src_y, int src_width, int src_height,
785 int dst_x, int dst_y, int dst_width, int dst_height)
787 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
788 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
789 int dst_xsize = dst_width;
790 int dst_ysize = dst_height;
791 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
792 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
795 for (y = 0; y < src_ysteps; y++)
797 for (x = 0; x < src_xsteps; x++)
799 int draw_x = dst_x + x * src_xsize;
800 int draw_y = dst_y + y * src_ysize;
801 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
802 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
804 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
810 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
811 int fade_mode, int fade_delay, int post_delay,
812 void (*draw_border_function)(void))
815 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
816 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
820 #if defined(TARGET_SDL)
821 SDLFadeRectangle(bitmap_cross, x, y, width, height,
822 fade_mode, fade_delay, post_delay, draw_border_function);
824 X11FadeRectangle(bitmap_cross, x, y, width, height,
825 fade_mode, fade_delay, post_delay, draw_border_function);
829 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
832 if (DrawingDeactivated(x, y, width, height))
836 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
839 /* skip if rectangle starts outside bitmap */
840 if (x >= bitmap->width ||
844 /* clip if rectangle overlaps bitmap */
845 if (x + width > bitmap->width)
846 width = bitmap->width - x;
847 if (y + height > bitmap->height)
848 height = bitmap->height - y;
851 sysFillRectangle(bitmap, x, y, width, height, color);
854 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
856 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
859 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
860 int width, int height)
862 if (DrawingOnBackground(x, y))
863 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
865 ClearRectangle(bitmap, x, y, width, height);
868 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
870 #if defined(TARGET_X11)
873 bitmap->clip_gc = clip_gc;
874 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
879 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
881 #if defined(TARGET_X11)
884 bitmap->clip_gc = clip_gc;
885 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
890 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
891 int src_x, int src_y, int width, int height,
892 int dst_x, int dst_y)
894 if (DrawingDeactivated(dst_x, dst_y, width, height))
897 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
898 dst_x, dst_y, BLIT_MASKED);
901 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
902 int src_x, int src_y, int width, int height,
903 int dst_x, int dst_y)
905 if (DrawingOnBackground(dst_x, dst_y))
907 /* draw background */
908 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
911 /* draw foreground */
912 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
913 dst_x - src_x, dst_y - src_y);
914 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
918 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
922 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
925 #if defined(TARGET_SDL)
926 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
928 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
932 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
935 #if defined(TARGET_SDL)
936 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
938 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
942 #if !defined(TARGET_X11_NATIVE)
943 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
944 int to_x, int to_y, Pixel pixel, int line_width)
948 for (x = 0; x < line_width; x++)
950 for (y = 0; y < line_width; y++)
952 int dx = x - line_width / 2;
953 int dy = y - line_width / 2;
955 if ((x == 0 && y == 0) ||
956 (x == 0 && y == line_width - 1) ||
957 (x == line_width - 1 && y == 0) ||
958 (x == line_width - 1 && y == line_width - 1))
961 #if defined(TARGET_SDL)
963 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
964 #elif defined(TARGET_ALLEGRO)
965 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
966 to_x + dx, to_y + dy, pixel);
973 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
975 #if !defined(TARGET_X11_NATIVE)
979 for (i = 0; i < num_points - 1; i++)
980 DrawLine(bitmap, points[i].x, points[i].y,
981 points[i + 1].x, points[i + 1].y, pixel, line_width);
984 SDLDrawLines(bitmap->surface, points, num_points, pixel);
987 XSetForeground(display, bitmap->line_gc[1], pixel);
988 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
989 (XPoint *)points, num_points, CoordModeOrigin);
993 Pixel GetPixel(Bitmap *bitmap, int x, int y)
995 if (x < 0 || x >= bitmap->width ||
996 y < 0 || y >= bitmap->height)
999 #if defined(TARGET_SDL)
1000 return SDLGetPixel(bitmap, x, y);
1001 #elif defined(TARGET_ALLEGRO)
1002 return AllegroGetPixel(bitmap->drawable, x, y);
1004 return X11GetPixel(bitmap, x, y);
1008 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1009 unsigned int color_g, unsigned int color_b)
1011 #if defined(TARGET_SDL)
1012 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1013 #elif defined(TARGET_ALLEGRO)
1014 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1016 return X11GetPixelFromRGB(color_r, color_g, color_b);
1020 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1022 unsigned int color_r = (color >> 16) & 0xff;
1023 unsigned int color_g = (color >> 8) & 0xff;
1024 unsigned int color_b = (color >> 0) & 0xff;
1026 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1029 /* execute all pending screen drawing operations */
1030 void FlushDisplay(void)
1032 #if !defined(TARGET_SDL)
1037 /* execute and wait for all pending screen drawing operations */
1038 void SyncDisplay(void)
1040 #if !defined(TARGET_SDL)
1041 XSync(display, FALSE);
1045 void KeyboardAutoRepeatOn(void)
1047 #if defined(TARGET_SDL)
1048 #if defined(TARGET_SDL2)
1049 keyrepeat_status = TRUE;
1051 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1052 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1053 SDL_EnableUNICODE(1);
1057 XAutoRepeatOn(display);
1061 void KeyboardAutoRepeatOff(void)
1063 #if defined(TARGET_SDL)
1064 #if defined(TARGET_SDL2)
1065 keyrepeat_status = FALSE;
1067 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1068 SDL_EnableUNICODE(0);
1072 XAutoRepeatOff(display);
1076 boolean PointerInWindow(DrawWindow *window)
1078 #if defined(TARGET_SDL)
1086 /* if XQueryPointer() returns False, the pointer
1087 is not on the same screen as the specified window */
1088 return XQueryPointer(display, window->drawable, &root, &child,
1089 &root_x, &root_y, &win_x, &win_y, &mask);
1093 boolean SetVideoMode(boolean fullscreen)
1095 #if defined(TARGET_SDL)
1096 return SDLSetVideoMode(&backbuffer, fullscreen);
1098 boolean success = TRUE;
1100 if (fullscreen && video.fullscreen_available)
1102 Error(ERR_WARN, "fullscreen not available in X11 version");
1104 /* display error message only once */
1105 video.fullscreen_available = FALSE;
1114 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1116 #if defined(TARGET_SDL)
1117 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1118 (!fullscreen && video.fullscreen_enabled))
1119 fullscreen = SetVideoMode(fullscreen);
1125 Bitmap *LoadImage(char *filename)
1129 #if defined(TARGET_SDL)
1130 new_bitmap = SDLLoadImage(filename);
1132 new_bitmap = X11LoadImage(filename);
1136 new_bitmap->source_filename = getStringCopy(filename);
1141 Bitmap *LoadCustomImage(char *basename)
1143 char *filename = getCustomImageFilename(basename);
1146 if (filename == NULL)
1147 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1149 if ((new_bitmap = LoadImage(filename)) == NULL)
1150 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1155 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1157 char *filename = getCustomImageFilename(basename);
1160 if (filename == NULL) /* (should never happen) */
1162 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1166 if (strEqual(filename, bitmap->source_filename))
1168 /* The old and new image are the same (have the same filename and path).
1169 This usually means that this image does not exist in this graphic set
1170 and a fallback to the existing image is done. */
1175 if ((new_bitmap = LoadImage(filename)) == NULL)
1177 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1181 if (bitmap->width != new_bitmap->width ||
1182 bitmap->height != new_bitmap->height)
1184 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1186 FreeBitmap(new_bitmap);
1190 TransferBitmapPointers(new_bitmap, bitmap);
1194 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1196 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1198 #if defined(TARGET_SDL)
1199 SDLZoomBitmap(src_bitmap, dst_bitmap);
1201 X11ZoomBitmap(src_bitmap, dst_bitmap);
1207 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1208 boolean create_small_bitmaps)
1212 Bitmap *tmp_bitmap_1;
1213 Bitmap *tmp_bitmap_2;
1214 Bitmap *tmp_bitmap_4;
1215 Bitmap *tmp_bitmap_8;
1216 Bitmap *tmp_bitmap_16;
1217 Bitmap *tmp_bitmap_32;
1218 int width_1, height_1;
1219 int width_2, height_2;
1220 int width_4, height_4;
1221 int width_8, height_8;
1222 int width_16, height_16;
1224 int width_32, height_32;
1226 int new_width, new_height;
1228 /* calculate new image dimensions for normal sized image */
1229 width_1 = old_bitmap->width * zoom_factor;
1230 height_1 = old_bitmap->height * zoom_factor;
1232 /* get image with normal size (this might require scaling up) */
1233 if (zoom_factor != 1)
1234 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1236 tmp_bitmap_1 = old_bitmap;
1238 /* this is only needed to make compilers happy */
1239 tmp_bitmap_2 = NULL;
1240 tmp_bitmap_4 = NULL;
1241 tmp_bitmap_8 = NULL;
1242 tmp_bitmap_16 = NULL;
1243 tmp_bitmap_32 = NULL;
1245 if (create_small_bitmaps)
1247 /* calculate new image dimensions for small images */
1248 width_2 = width_1 / 2;
1249 height_2 = height_1 / 2;
1250 width_4 = width_1 / 4;
1251 height_4 = height_1 / 4;
1252 width_8 = width_1 / 8;
1253 height_8 = height_1 / 8;
1254 width_16 = width_1 / 16;
1255 height_16 = height_1 / 16;
1257 width_32 = width_1 / 32;
1258 height_32 = height_1 / 32;
1261 UPDATE_BUSY_STATE();
1263 /* get image with 1/2 of normal size (for use in the level editor) */
1264 if (zoom_factor != 2)
1265 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1267 tmp_bitmap_2 = old_bitmap;
1269 UPDATE_BUSY_STATE();
1271 /* get image with 1/4 of normal size (for use in the level editor) */
1272 if (zoom_factor != 4)
1273 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1275 tmp_bitmap_4 = old_bitmap;
1277 UPDATE_BUSY_STATE();
1279 /* get image with 1/8 of normal size (for use on the preview screen) */
1280 if (zoom_factor != 8)
1281 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1283 tmp_bitmap_8 = old_bitmap;
1285 UPDATE_BUSY_STATE();
1287 /* get image with 1/16 of normal size (for use on the preview screen) */
1288 if (zoom_factor != 16)
1289 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1291 tmp_bitmap_16 = old_bitmap;
1293 UPDATE_BUSY_STATE();
1295 /* get image with 1/32 of normal size (for use on the preview screen) */
1296 if (zoom_factor != 32)
1297 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1299 tmp_bitmap_32 = old_bitmap;
1301 UPDATE_BUSY_STATE();
1305 /* if image was scaled up, create new clipmask for normal size image */
1306 if (zoom_factor != 1)
1308 #if defined(TARGET_X11)
1309 if (old_bitmap->clip_mask)
1310 XFreePixmap(display, old_bitmap->clip_mask);
1312 old_bitmap->clip_mask =
1313 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1315 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1317 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1319 if (old_bitmap->surface_masked)
1320 SDL_FreeSurface(old_bitmap->surface_masked);
1322 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1323 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1324 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1325 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1326 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1331 if (create_small_bitmaps)
1333 new_width = width_1;
1334 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1336 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1338 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1339 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1341 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1342 width_1 / 2, height_1);
1343 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1344 3 * width_1 / 4, height_1);
1345 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1346 7 * width_1 / 8, height_1);
1347 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1348 15 * width_1 / 16, height_1);
1350 UPDATE_BUSY_STATE();
1354 new_width = width_1;
1355 new_height = height_1;
1357 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1360 if (create_small_bitmaps)
1362 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1363 if (zoom_factor != 1)
1364 FreeBitmap(tmp_bitmap_1);
1366 if (zoom_factor != 2)
1367 FreeBitmap(tmp_bitmap_2);
1369 if (zoom_factor != 4)
1370 FreeBitmap(tmp_bitmap_4);
1372 if (zoom_factor != 8)
1373 FreeBitmap(tmp_bitmap_8);
1375 if (zoom_factor != 16)
1376 FreeBitmap(tmp_bitmap_16);
1378 if (zoom_factor != 32)
1379 FreeBitmap(tmp_bitmap_32);
1382 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1383 #if defined(TARGET_SDL)
1384 swap_bitmap.surface = old_bitmap->surface;
1385 old_bitmap->surface = new_bitmap->surface;
1386 new_bitmap->surface = swap_bitmap.surface;
1388 swap_bitmap.drawable = old_bitmap->drawable;
1389 old_bitmap->drawable = new_bitmap->drawable;
1390 new_bitmap->drawable = swap_bitmap.drawable;
1393 old_bitmap->width = new_bitmap->width;
1394 old_bitmap->height = new_bitmap->height;
1397 /* this replaces all blit masks created when loading -- maybe optimize this */
1399 #if defined(TARGET_X11)
1400 if (old_bitmap->clip_mask)
1401 XFreePixmap(display, old_bitmap->clip_mask);
1403 old_bitmap->clip_mask =
1404 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1406 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1408 SDL_Surface *old_surface = old_bitmap->surface;
1410 if (old_bitmap->surface_masked)
1411 SDL_FreeSurface(old_bitmap->surface_masked);
1413 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1414 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1415 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1416 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1417 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1422 UPDATE_BUSY_STATE();
1424 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1427 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1429 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1432 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1434 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1438 /* ------------------------------------------------------------------------- */
1439 /* mouse pointer functions */
1440 /* ------------------------------------------------------------------------- */
1442 #if !defined(PLATFORM_MSDOS)
1443 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1444 /* XPM image definitions */
1445 static const char *cursor_image_none[] =
1447 /* width height num_colors chars_per_pixel */
1476 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1477 static const char *cursor_image_dot[] =
1479 /* width height num_colors chars_per_pixel */
1508 static const char **cursor_image_playfield = cursor_image_dot;
1510 /* some people complained about a "white dot" on the screen and thought it
1511 was a graphical error... OK, let's just remove the whole pointer :-) */
1512 static const char **cursor_image_playfield = cursor_image_none;
1515 #if defined(TARGET_SDL)
1516 static const int cursor_bit_order = BIT_ORDER_MSB;
1517 #elif defined(TARGET_X11_NATIVE)
1518 static const int cursor_bit_order = BIT_ORDER_LSB;
1521 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1523 struct MouseCursorInfo *cursor;
1524 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1525 int header_lines = 4;
1528 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1530 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1533 for (y = 0; y < cursor->width; y++)
1535 for (x = 0; x < cursor->height; x++)
1538 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1543 cursor->data[i] = cursor->mask[i] = 0;
1546 switch (image[header_lines + y][x])
1549 cursor->data[i] |= bit_mask;
1550 cursor->mask[i] |= bit_mask;
1554 cursor->mask[i] |= bit_mask;
1563 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1567 #endif /* !PLATFORM_MSDOS */
1569 void SetMouseCursor(int mode)
1571 #if !defined(PLATFORM_MSDOS)
1572 static struct MouseCursorInfo *cursor_none = NULL;
1573 static struct MouseCursorInfo *cursor_playfield = NULL;
1574 struct MouseCursorInfo *cursor_new;
1576 if (cursor_none == NULL)
1577 cursor_none = get_cursor_from_image(cursor_image_none);
1579 if (cursor_playfield == NULL)
1580 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1582 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1583 mode == CURSOR_NONE ? cursor_none :
1584 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1586 #if defined(TARGET_SDL)
1587 SDLSetMouseCursor(cursor_new);
1588 #elif defined(TARGET_X11_NATIVE)
1589 X11SetMouseCursor(cursor_new);
1595 /* ========================================================================= */
1596 /* audio functions */
1597 /* ========================================================================= */
1599 void OpenAudio(void)
1601 /* always start with reliable default values */
1602 audio.sound_available = FALSE;
1603 audio.music_available = FALSE;
1604 audio.loops_available = FALSE;
1606 audio.sound_enabled = FALSE;
1607 audio.sound_deactivated = FALSE;
1609 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1610 audio.mixer_pid = 0;
1611 audio.device_name = NULL;
1612 audio.device_fd = -1;
1614 audio.num_channels = 0;
1615 audio.music_channel = 0;
1616 audio.first_sound_channel = 0;
1618 #if defined(TARGET_SDL)
1620 #elif defined(PLATFORM_UNIX)
1622 #elif defined(PLATFORM_MSDOS)
1627 void CloseAudio(void)
1629 #if defined(TARGET_SDL)
1631 #elif defined(PLATFORM_UNIX)
1633 #elif defined(PLATFORM_MSDOS)
1637 audio.sound_enabled = FALSE;
1640 void SetAudioMode(boolean enabled)
1642 if (!audio.sound_available)
1645 audio.sound_enabled = enabled;
1649 /* ========================================================================= */
1650 /* event functions */
1651 /* ========================================================================= */
1653 void InitEventFilter(EventFilter filter_function)
1655 /* set event filter to filter out certain events */
1656 #if defined(TARGET_SDL)
1657 #if defined(TARGET_SDL2)
1658 SDL_SetEventFilter(filter_function, NULL);
1660 SDL_SetEventFilter(filter_function);
1665 boolean PendingEvent(void)
1667 #if defined(TARGET_SDL)
1668 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1670 return (XPending(display) ? TRUE : FALSE);
1674 void NextEvent(Event *event)
1676 #if defined(TARGET_SDL)
1677 SDLNextEvent(event);
1679 XNextEvent(display, event);
1683 void PeekEvent(Event *event)
1685 #if defined(TARGET_SDL)
1686 #if defined(TARGET_SDL2)
1687 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1689 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1692 XPeekEvent(display, event);
1696 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1698 #if defined(TARGET_SDL)
1699 #if defined(TARGET_SDL2)
1700 /* key up/down events in SDL2 do not return text characters anymore */
1701 return event->keysym.sym;
1705 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1706 (int)event->keysym.unicode,
1707 (int)event->keysym.sym,
1708 (int)SDL_GetModState());
1711 if (with_modifiers &&
1712 event->keysym.unicode > 0x0000 &&
1713 event->keysym.unicode < 0x2000)
1714 return event->keysym.unicode;
1716 return event->keysym.sym;
1722 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1723 (int)XLookupKeysym(event, event->state),
1724 (int)XLookupKeysym(event, 0));
1728 return XLookupKeysym(event, event->state);
1730 return XLookupKeysym(event, 0);
1734 KeyMod HandleKeyModState(Key key, int key_status)
1736 static KeyMod current_modifiers = KMOD_None;
1738 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1740 KeyMod new_modifier = KMOD_None;
1745 new_modifier = KMOD_Shift_L;
1748 new_modifier = KMOD_Shift_R;
1750 case KSYM_Control_L:
1751 new_modifier = KMOD_Control_L;
1753 case KSYM_Control_R:
1754 new_modifier = KMOD_Control_R;
1757 new_modifier = KMOD_Meta_L;
1760 new_modifier = KMOD_Meta_R;
1763 new_modifier = KMOD_Alt_L;
1766 new_modifier = KMOD_Alt_R;
1772 if (key_status == KEY_PRESSED)
1773 current_modifiers |= new_modifier;
1775 current_modifiers &= ~new_modifier;
1778 return current_modifiers;
1781 KeyMod GetKeyModState()
1783 #if defined(TARGET_SDL)
1784 return (KeyMod)SDL_GetModState();
1786 return HandleKeyModState(KSYM_UNDEFINED, 0);
1790 KeyMod GetKeyModStateFromEvents()
1792 /* always use key modifier state as tracked from key events (this is needed
1793 if the modifier key event was injected into the event queue, but the key
1794 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1795 query the keys as held pressed on the keyboard) -- this case is currently
1796 only used to filter out clipboard insert events from "True X-Mouse" tool */
1798 return HandleKeyModState(KSYM_UNDEFINED, 0);
1801 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1803 if (event->type != EVENT_CLIENTMESSAGE)
1806 #if defined(TARGET_SDL)
1807 return TRUE; /* the only possible message here is SDL_QUIT */
1808 #elif defined(PLATFORM_UNIX)
1809 if ((event->window == window->drawable) &&
1810 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1818 /* ========================================================================= */
1819 /* joystick functions */
1820 /* ========================================================================= */
1822 void InitJoysticks()
1826 #if defined(NO_JOYSTICK)
1827 return; /* joysticks generally deactivated by compile-time directive */
1830 /* always start with reliable default values */
1831 joystick.status = JOYSTICK_NOT_AVAILABLE;
1832 for (i = 0; i < MAX_PLAYERS; i++)
1833 joystick.fd[i] = -1; /* joystick device closed */
1835 #if defined(TARGET_SDL)
1837 #elif defined(PLATFORM_UNIX)
1838 UnixInitJoysticks();
1839 #elif defined(PLATFORM_MSDOS)
1840 MSDOSInitJoysticks();
1844 for (i = 0; i < MAX_PLAYERS; i++)
1845 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1849 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1851 #if defined(TARGET_SDL)
1852 return SDLReadJoystick(nr, x, y, b1, b2);
1853 #elif defined(PLATFORM_UNIX)
1854 return UnixReadJoystick(nr, x, y, b1, b2);
1855 #elif defined(PLATFORM_MSDOS)
1856 return MSDOSReadJoystick(nr, x, y, b1, b2);