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 static boolean initialized = FALSE;
446 video.height = height;
447 video.depth = GetRealDepth(depth);
449 video.fullscreen_available = FULLSCREEN_STATUS;
450 video.fullscreen_enabled = FALSE;
452 video.fullscreen_mode_current = NULL;
453 video.fullscreen_modes = NULL;
456 video.window_scaling_available = WINDOW_SCALING_STATUS;
459 #if defined(PLATFORM_ANDROID)
461 video.fullscreen_enabled = TRUE;
465 #if defined(TARGET_SDL)
466 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
468 X11InitVideoBuffer(&backbuffer, &window);
478 inline static void FreeBitmapPointers(Bitmap *bitmap)
483 #if defined(TARGET_SDL)
484 SDLFreeBitmapPointers(bitmap);
486 X11FreeBitmapPointers(bitmap);
489 checked_free(bitmap->source_filename);
490 bitmap->source_filename = NULL;
493 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
496 if (src_bitmap == NULL || dst_bitmap == NULL)
499 FreeBitmapPointers(dst_bitmap);
501 *dst_bitmap = *src_bitmap;
504 void FreeBitmap(Bitmap *bitmap)
509 FreeBitmapPointers(bitmap);
514 Bitmap *CreateBitmapStruct(void)
516 #if defined(TARGET_SDL)
517 return checked_calloc(sizeof(struct SDLSurfaceInfo));
519 return checked_calloc(sizeof(struct X11DrawableInfo));
523 Bitmap *CreateBitmap(int width, int height, int depth)
525 Bitmap *new_bitmap = CreateBitmapStruct();
526 int real_width = MAX(1, width); /* prevent zero bitmap width */
527 int real_height = MAX(1, height); /* prevent zero bitmap height */
528 int real_depth = GetRealDepth(depth);
530 #if defined(TARGET_SDL)
531 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
533 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
536 new_bitmap->width = real_width;
537 new_bitmap->height = real_height;
542 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
544 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
548 *bitmap = new_bitmap;
552 TransferBitmapPointers(new_bitmap, *bitmap);
557 void CloseWindow(DrawWindow *window)
559 #if defined(TARGET_X11)
560 X11CloseWindow(window);
564 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
567 if (draw_mask == REDRAW_NONE)
570 if (draw_mask & REDRAW_ALL)
573 if ((draw_mask & REDRAW_FIELD) &&
574 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
577 if ((draw_mask & REDRAW_DOOR_1) &&
578 x >= gfx.dx && y < gfx.dy + gfx.dysize)
581 if ((draw_mask & REDRAW_DOOR_2) &&
582 x >= gfx.dx && y >= gfx.vy)
588 boolean DrawingDeactivated(int x, int y, int width, int height)
590 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
593 boolean DrawingOnBackground(int x, int y)
595 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
596 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
599 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
600 int *width, int *height, boolean is_dest)
603 int clip_x, clip_y, clip_width, clip_height;
605 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
607 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
608 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
609 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
610 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
616 clip_width = bitmap->width;
617 clip_height = bitmap->height;
620 /* skip if rectangle completely outside bitmap */
622 if (*x + *width <= clip_x ||
623 *y + *height <= clip_y ||
624 *x >= clip_x + clip_width ||
625 *y >= clip_y + clip_height)
628 /* clip if rectangle overlaps bitmap */
632 *width -= clip_x - *x;
635 else if (*x + *width > clip_x + clip_width)
637 *width = clip_x + clip_width - *x;
642 *height -= clip_y - *y;
645 else if (*y + *height > clip_y + clip_height)
647 *height = clip_y + clip_height - *y;
654 /* skip if rectangle completely outside bitmap */
656 if (*x + *width <= 0 ||
658 *x >= bitmap->width ||
659 *y >= bitmap->height)
662 /* clip if rectangle overlaps bitmap */
669 else if (*x + *width > bitmap->width)
671 *width = bitmap->width - *x;
679 else if (*y + *height > bitmap->height)
681 *height = bitmap->height - *y;
688 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
689 int src_x, int src_y, int width, int height,
690 int dst_x, int dst_y)
692 int dst_x_unclipped = dst_x;
693 int dst_y_unclipped = dst_y;
695 if (DrawingDeactivated(dst_x, dst_y, width, height))
699 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
700 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
703 /* source x/y might need adjustment if destination x/y was clipped top/left */
704 src_x += dst_x - dst_x_unclipped;
705 src_y += dst_y - dst_y_unclipped;
708 /* skip if rectangle starts outside bitmap */
709 if (src_x >= src_bitmap->width ||
710 src_y >= src_bitmap->height ||
711 dst_x >= dst_bitmap->width ||
712 dst_y >= dst_bitmap->height)
715 /* clip if rectangle overlaps bitmap */
716 if (src_x + width > src_bitmap->width)
717 width = src_bitmap->width - src_x;
718 if (src_y + height > src_bitmap->height)
719 height = src_bitmap->height - src_y;
720 if (dst_x + width > dst_bitmap->width)
721 width = dst_bitmap->width - dst_x;
722 if (dst_y + height > dst_bitmap->height)
723 height = dst_bitmap->height - dst_y;
727 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
729 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
730 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
731 but is already fixed in SVN and should therefore finally be fixed with
732 the next official SDL release, which is probably version 1.2.14.) */
734 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
735 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
736 #if defined(TARGET_SDL2)
737 if (src_bitmap == dst_bitmap)
739 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
741 /* needed when blitting directly to same bitmap -- should not be needed with
742 recent SDL libraries, but apparently does not work in 1.2.11 directly */
744 static Bitmap *tmp_bitmap = NULL;
745 static int tmp_bitmap_xsize = 0;
746 static int tmp_bitmap_ysize = 0;
748 /* start with largest static bitmaps for initial bitmap size ... */
749 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
751 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
752 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
755 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
756 if (src_bitmap->width > tmp_bitmap_xsize ||
757 src_bitmap->height > tmp_bitmap_ysize)
759 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
760 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
762 FreeBitmap(tmp_bitmap);
767 if (tmp_bitmap == NULL)
768 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
771 sysCopyArea(src_bitmap, tmp_bitmap,
772 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
773 sysCopyArea(tmp_bitmap, dst_bitmap,
774 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
784 if (dst_x < gfx.sx + gfx.sxsize)
785 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
786 FrameCounter, dst_x, dst_y, width, height);
789 sysCopyArea(src_bitmap, dst_bitmap,
790 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
793 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
794 int src_x, int src_y, int src_width, int src_height,
795 int dst_x, int dst_y, int dst_width, int dst_height)
797 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
798 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
799 int dst_xsize = dst_width;
800 int dst_ysize = dst_height;
801 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
802 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
805 for (y = 0; y < src_ysteps; y++)
807 for (x = 0; x < src_xsteps; x++)
809 int draw_x = dst_x + x * src_xsize;
810 int draw_y = dst_y + y * src_ysize;
811 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
812 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
814 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
820 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
821 int fade_mode, int fade_delay, int post_delay,
822 void (*draw_border_function)(void))
825 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
826 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
830 #if defined(TARGET_SDL)
831 SDLFadeRectangle(bitmap_cross, x, y, width, height,
832 fade_mode, fade_delay, post_delay, draw_border_function);
834 X11FadeRectangle(bitmap_cross, x, y, width, height,
835 fade_mode, fade_delay, post_delay, draw_border_function);
839 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
842 if (DrawingDeactivated(x, y, width, height))
846 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
849 /* skip if rectangle starts outside bitmap */
850 if (x >= bitmap->width ||
854 /* clip if rectangle overlaps bitmap */
855 if (x + width > bitmap->width)
856 width = bitmap->width - x;
857 if (y + height > bitmap->height)
858 height = bitmap->height - y;
861 sysFillRectangle(bitmap, x, y, width, height, color);
864 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
866 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
869 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
870 int width, int height)
872 if (DrawingOnBackground(x, y))
873 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
875 ClearRectangle(bitmap, x, y, width, height);
878 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
880 #if defined(TARGET_X11)
883 bitmap->clip_gc = clip_gc;
884 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
889 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
891 #if defined(TARGET_X11)
894 bitmap->clip_gc = clip_gc;
895 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
900 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
901 int src_x, int src_y, int width, int height,
902 int dst_x, int dst_y)
904 if (DrawingDeactivated(dst_x, dst_y, width, height))
907 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
908 dst_x, dst_y, BLIT_MASKED);
911 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
912 int src_x, int src_y, int width, int height,
913 int dst_x, int dst_y)
915 if (DrawingOnBackground(dst_x, dst_y))
917 /* draw background */
918 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
921 /* draw foreground */
922 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
923 dst_x - src_x, dst_y - src_y);
924 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
928 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
932 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
935 #if defined(TARGET_SDL)
936 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
938 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
942 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
945 #if defined(TARGET_SDL)
946 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
948 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
952 #if !defined(TARGET_X11_NATIVE)
953 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
954 int to_x, int to_y, Pixel pixel, int line_width)
958 for (x = 0; x < line_width; x++)
960 for (y = 0; y < line_width; y++)
962 int dx = x - line_width / 2;
963 int dy = y - line_width / 2;
965 if ((x == 0 && y == 0) ||
966 (x == 0 && y == line_width - 1) ||
967 (x == line_width - 1 && y == 0) ||
968 (x == line_width - 1 && y == line_width - 1))
971 #if defined(TARGET_SDL)
973 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
974 #elif defined(TARGET_ALLEGRO)
975 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
976 to_x + dx, to_y + dy, pixel);
983 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
985 #if !defined(TARGET_X11_NATIVE)
989 for (i = 0; i < num_points - 1; i++)
990 DrawLine(bitmap, points[i].x, points[i].y,
991 points[i + 1].x, points[i + 1].y, pixel, line_width);
994 SDLDrawLines(bitmap->surface, points, num_points, pixel);
997 XSetForeground(display, bitmap->line_gc[1], pixel);
998 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
999 (XPoint *)points, num_points, CoordModeOrigin);
1003 Pixel GetPixel(Bitmap *bitmap, int x, int y)
1005 if (x < 0 || x >= bitmap->width ||
1006 y < 0 || y >= bitmap->height)
1009 #if defined(TARGET_SDL)
1010 return SDLGetPixel(bitmap, x, y);
1011 #elif defined(TARGET_ALLEGRO)
1012 return AllegroGetPixel(bitmap->drawable, x, y);
1014 return X11GetPixel(bitmap, x, y);
1018 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1019 unsigned int color_g, unsigned int color_b)
1021 #if defined(TARGET_SDL)
1022 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1023 #elif defined(TARGET_ALLEGRO)
1024 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1026 return X11GetPixelFromRGB(color_r, color_g, color_b);
1030 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1032 unsigned int color_r = (color >> 16) & 0xff;
1033 unsigned int color_g = (color >> 8) & 0xff;
1034 unsigned int color_b = (color >> 0) & 0xff;
1036 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1039 /* execute all pending screen drawing operations */
1040 void FlushDisplay(void)
1042 #if !defined(TARGET_SDL)
1047 /* execute and wait for all pending screen drawing operations */
1048 void SyncDisplay(void)
1050 #if !defined(TARGET_SDL)
1051 XSync(display, FALSE);
1055 void KeyboardAutoRepeatOn(void)
1057 #if defined(TARGET_SDL)
1058 #if defined(TARGET_SDL2)
1059 keyrepeat_status = TRUE;
1061 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1062 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1063 SDL_EnableUNICODE(1);
1067 XAutoRepeatOn(display);
1071 void KeyboardAutoRepeatOff(void)
1073 #if defined(TARGET_SDL)
1074 #if defined(TARGET_SDL2)
1075 keyrepeat_status = FALSE;
1077 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1078 SDL_EnableUNICODE(0);
1082 XAutoRepeatOff(display);
1086 boolean PointerInWindow(DrawWindow *window)
1088 #if defined(TARGET_SDL)
1096 /* if XQueryPointer() returns False, the pointer
1097 is not on the same screen as the specified window */
1098 return XQueryPointer(display, window->drawable, &root, &child,
1099 &root_x, &root_y, &win_x, &win_y, &mask);
1103 boolean SetVideoMode(boolean fullscreen)
1105 #if defined(TARGET_SDL)
1106 return SDLSetVideoMode(&backbuffer, fullscreen);
1108 boolean success = TRUE;
1110 if (fullscreen && video.fullscreen_available)
1112 Error(ERR_WARN, "fullscreen not available in X11 version");
1114 /* display error message only once */
1115 video.fullscreen_available = FALSE;
1124 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1126 #if defined(TARGET_SDL)
1127 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1128 (!fullscreen && video.fullscreen_enabled))
1129 fullscreen = SetVideoMode(fullscreen);
1135 Bitmap *LoadImage(char *filename)
1139 #if defined(TARGET_SDL)
1140 new_bitmap = SDLLoadImage(filename);
1142 new_bitmap = X11LoadImage(filename);
1146 new_bitmap->source_filename = getStringCopy(filename);
1151 Bitmap *LoadCustomImage(char *basename)
1153 char *filename = getCustomImageFilename(basename);
1156 if (filename == NULL)
1157 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1159 if ((new_bitmap = LoadImage(filename)) == NULL)
1160 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1165 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1167 char *filename = getCustomImageFilename(basename);
1170 if (filename == NULL) /* (should never happen) */
1172 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1176 if (strEqual(filename, bitmap->source_filename))
1178 /* The old and new image are the same (have the same filename and path).
1179 This usually means that this image does not exist in this graphic set
1180 and a fallback to the existing image is done. */
1185 if ((new_bitmap = LoadImage(filename)) == NULL)
1187 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1191 if (bitmap->width != new_bitmap->width ||
1192 bitmap->height != new_bitmap->height)
1194 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1196 FreeBitmap(new_bitmap);
1200 TransferBitmapPointers(new_bitmap, bitmap);
1204 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1206 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1208 #if defined(TARGET_SDL)
1209 SDLZoomBitmap(src_bitmap, dst_bitmap);
1211 X11ZoomBitmap(src_bitmap, dst_bitmap);
1217 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1218 boolean create_small_bitmaps)
1222 Bitmap *tmp_bitmap_1;
1223 Bitmap *tmp_bitmap_2;
1224 Bitmap *tmp_bitmap_4;
1225 Bitmap *tmp_bitmap_8;
1226 Bitmap *tmp_bitmap_16;
1227 Bitmap *tmp_bitmap_32;
1228 int width_1, height_1;
1229 int width_2, height_2;
1230 int width_4, height_4;
1231 int width_8, height_8;
1232 int width_16, height_16;
1234 int width_32, height_32;
1236 int new_width, new_height;
1238 /* calculate new image dimensions for normal sized image */
1239 width_1 = old_bitmap->width * zoom_factor;
1240 height_1 = old_bitmap->height * zoom_factor;
1242 /* get image with normal size (this might require scaling up) */
1243 if (zoom_factor != 1)
1244 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1246 tmp_bitmap_1 = old_bitmap;
1248 /* this is only needed to make compilers happy */
1249 tmp_bitmap_2 = NULL;
1250 tmp_bitmap_4 = NULL;
1251 tmp_bitmap_8 = NULL;
1252 tmp_bitmap_16 = NULL;
1253 tmp_bitmap_32 = NULL;
1255 if (create_small_bitmaps)
1257 /* calculate new image dimensions for small images */
1258 width_2 = width_1 / 2;
1259 height_2 = height_1 / 2;
1260 width_4 = width_1 / 4;
1261 height_4 = height_1 / 4;
1262 width_8 = width_1 / 8;
1263 height_8 = height_1 / 8;
1264 width_16 = width_1 / 16;
1265 height_16 = height_1 / 16;
1267 width_32 = width_1 / 32;
1268 height_32 = height_1 / 32;
1271 UPDATE_BUSY_STATE();
1273 /* get image with 1/2 of normal size (for use in the level editor) */
1274 if (zoom_factor != 2)
1275 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1277 tmp_bitmap_2 = old_bitmap;
1279 UPDATE_BUSY_STATE();
1281 /* get image with 1/4 of normal size (for use in the level editor) */
1282 if (zoom_factor != 4)
1283 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1285 tmp_bitmap_4 = old_bitmap;
1287 UPDATE_BUSY_STATE();
1289 /* get image with 1/8 of normal size (for use on the preview screen) */
1290 if (zoom_factor != 8)
1291 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1293 tmp_bitmap_8 = old_bitmap;
1295 UPDATE_BUSY_STATE();
1297 /* get image with 1/16 of normal size (for use on the preview screen) */
1298 if (zoom_factor != 16)
1299 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1301 tmp_bitmap_16 = old_bitmap;
1303 UPDATE_BUSY_STATE();
1305 /* get image with 1/32 of normal size (for use on the preview screen) */
1306 if (zoom_factor != 32)
1307 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1309 tmp_bitmap_32 = old_bitmap;
1311 UPDATE_BUSY_STATE();
1315 /* if image was scaled up, create new clipmask for normal size image */
1316 if (zoom_factor != 1)
1318 #if defined(TARGET_X11)
1319 if (old_bitmap->clip_mask)
1320 XFreePixmap(display, old_bitmap->clip_mask);
1322 old_bitmap->clip_mask =
1323 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1325 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1327 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1329 if (old_bitmap->surface_masked)
1330 SDL_FreeSurface(old_bitmap->surface_masked);
1332 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1333 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1334 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1335 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1336 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1341 if (create_small_bitmaps)
1343 new_width = width_1;
1344 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1346 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1348 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1349 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1351 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1352 width_1 / 2, height_1);
1353 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1354 3 * width_1 / 4, height_1);
1355 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1356 7 * width_1 / 8, height_1);
1357 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1358 15 * width_1 / 16, height_1);
1360 UPDATE_BUSY_STATE();
1364 new_width = width_1;
1365 new_height = height_1;
1367 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1370 if (create_small_bitmaps)
1372 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1373 if (zoom_factor != 1)
1374 FreeBitmap(tmp_bitmap_1);
1376 if (zoom_factor != 2)
1377 FreeBitmap(tmp_bitmap_2);
1379 if (zoom_factor != 4)
1380 FreeBitmap(tmp_bitmap_4);
1382 if (zoom_factor != 8)
1383 FreeBitmap(tmp_bitmap_8);
1385 if (zoom_factor != 16)
1386 FreeBitmap(tmp_bitmap_16);
1388 if (zoom_factor != 32)
1389 FreeBitmap(tmp_bitmap_32);
1392 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1393 #if defined(TARGET_SDL)
1394 swap_bitmap.surface = old_bitmap->surface;
1395 old_bitmap->surface = new_bitmap->surface;
1396 new_bitmap->surface = swap_bitmap.surface;
1398 swap_bitmap.drawable = old_bitmap->drawable;
1399 old_bitmap->drawable = new_bitmap->drawable;
1400 new_bitmap->drawable = swap_bitmap.drawable;
1403 old_bitmap->width = new_bitmap->width;
1404 old_bitmap->height = new_bitmap->height;
1407 /* this replaces all blit masks created when loading -- maybe optimize this */
1409 #if defined(TARGET_X11)
1410 if (old_bitmap->clip_mask)
1411 XFreePixmap(display, old_bitmap->clip_mask);
1413 old_bitmap->clip_mask =
1414 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1416 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1418 SDL_Surface *old_surface = old_bitmap->surface;
1420 if (old_bitmap->surface_masked)
1421 SDL_FreeSurface(old_bitmap->surface_masked);
1423 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1424 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1425 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1426 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1427 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1432 UPDATE_BUSY_STATE();
1434 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1437 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1439 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1442 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1444 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1448 /* ------------------------------------------------------------------------- */
1449 /* mouse pointer functions */
1450 /* ------------------------------------------------------------------------- */
1452 #if !defined(PLATFORM_MSDOS)
1453 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1454 /* XPM image definitions */
1455 static const char *cursor_image_none[] =
1457 /* width height num_colors chars_per_pixel */
1486 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1487 static const char *cursor_image_dot[] =
1489 /* width height num_colors chars_per_pixel */
1518 static const char **cursor_image_playfield = cursor_image_dot;
1520 /* some people complained about a "white dot" on the screen and thought it
1521 was a graphical error... OK, let's just remove the whole pointer :-) */
1522 static const char **cursor_image_playfield = cursor_image_none;
1525 #if defined(TARGET_SDL)
1526 static const int cursor_bit_order = BIT_ORDER_MSB;
1527 #elif defined(TARGET_X11_NATIVE)
1528 static const int cursor_bit_order = BIT_ORDER_LSB;
1531 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1533 struct MouseCursorInfo *cursor;
1534 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1535 int header_lines = 4;
1538 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1540 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1543 for (y = 0; y < cursor->width; y++)
1545 for (x = 0; x < cursor->height; x++)
1548 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1553 cursor->data[i] = cursor->mask[i] = 0;
1556 switch (image[header_lines + y][x])
1559 cursor->data[i] |= bit_mask;
1560 cursor->mask[i] |= bit_mask;
1564 cursor->mask[i] |= bit_mask;
1573 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1577 #endif /* !PLATFORM_MSDOS */
1579 void SetMouseCursor(int mode)
1581 #if !defined(PLATFORM_MSDOS)
1582 static struct MouseCursorInfo *cursor_none = NULL;
1583 static struct MouseCursorInfo *cursor_playfield = NULL;
1584 struct MouseCursorInfo *cursor_new;
1586 if (cursor_none == NULL)
1587 cursor_none = get_cursor_from_image(cursor_image_none);
1589 if (cursor_playfield == NULL)
1590 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1592 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1593 mode == CURSOR_NONE ? cursor_none :
1594 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1596 #if defined(TARGET_SDL)
1597 SDLSetMouseCursor(cursor_new);
1598 #elif defined(TARGET_X11_NATIVE)
1599 X11SetMouseCursor(cursor_new);
1605 /* ========================================================================= */
1606 /* audio functions */
1607 /* ========================================================================= */
1609 void OpenAudio(void)
1611 /* always start with reliable default values */
1612 audio.sound_available = FALSE;
1613 audio.music_available = FALSE;
1614 audio.loops_available = FALSE;
1616 audio.sound_enabled = FALSE;
1617 audio.sound_deactivated = FALSE;
1619 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1620 audio.mixer_pid = 0;
1621 audio.device_name = NULL;
1622 audio.device_fd = -1;
1624 audio.num_channels = 0;
1625 audio.music_channel = 0;
1626 audio.first_sound_channel = 0;
1628 #if defined(TARGET_SDL)
1630 #elif defined(PLATFORM_UNIX)
1632 #elif defined(PLATFORM_MSDOS)
1637 void CloseAudio(void)
1639 #if defined(TARGET_SDL)
1641 #elif defined(PLATFORM_UNIX)
1643 #elif defined(PLATFORM_MSDOS)
1647 audio.sound_enabled = FALSE;
1650 void SetAudioMode(boolean enabled)
1652 if (!audio.sound_available)
1655 audio.sound_enabled = enabled;
1659 /* ========================================================================= */
1660 /* event functions */
1661 /* ========================================================================= */
1663 void InitEventFilter(EventFilter filter_function)
1665 /* set event filter to filter out certain events */
1666 #if defined(TARGET_SDL)
1667 #if defined(TARGET_SDL2)
1668 SDL_SetEventFilter(filter_function, NULL);
1670 SDL_SetEventFilter(filter_function);
1675 boolean PendingEvent(void)
1677 #if defined(TARGET_SDL)
1678 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1680 return (XPending(display) ? TRUE : FALSE);
1684 void NextEvent(Event *event)
1686 #if defined(TARGET_SDL)
1687 SDLNextEvent(event);
1689 XNextEvent(display, event);
1693 void PeekEvent(Event *event)
1695 #if defined(TARGET_SDL)
1696 #if defined(TARGET_SDL2)
1697 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1699 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1702 XPeekEvent(display, event);
1706 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1708 #if defined(TARGET_SDL)
1709 #if defined(TARGET_SDL2)
1710 /* key up/down events in SDL2 do not return text characters anymore */
1711 return event->keysym.sym;
1715 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1716 (int)event->keysym.unicode,
1717 (int)event->keysym.sym,
1718 (int)SDL_GetModState());
1721 if (with_modifiers &&
1722 event->keysym.unicode > 0x0000 &&
1723 event->keysym.unicode < 0x2000)
1724 return event->keysym.unicode;
1726 return event->keysym.sym;
1732 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1733 (int)XLookupKeysym(event, event->state),
1734 (int)XLookupKeysym(event, 0));
1738 return XLookupKeysym(event, event->state);
1740 return XLookupKeysym(event, 0);
1744 KeyMod HandleKeyModState(Key key, int key_status)
1746 static KeyMod current_modifiers = KMOD_None;
1748 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1750 KeyMod new_modifier = KMOD_None;
1755 new_modifier = KMOD_Shift_L;
1758 new_modifier = KMOD_Shift_R;
1760 case KSYM_Control_L:
1761 new_modifier = KMOD_Control_L;
1763 case KSYM_Control_R:
1764 new_modifier = KMOD_Control_R;
1767 new_modifier = KMOD_Meta_L;
1770 new_modifier = KMOD_Meta_R;
1773 new_modifier = KMOD_Alt_L;
1776 new_modifier = KMOD_Alt_R;
1782 if (key_status == KEY_PRESSED)
1783 current_modifiers |= new_modifier;
1785 current_modifiers &= ~new_modifier;
1788 return current_modifiers;
1791 KeyMod GetKeyModState()
1793 #if defined(TARGET_SDL)
1794 return (KeyMod)SDL_GetModState();
1796 return HandleKeyModState(KSYM_UNDEFINED, 0);
1800 KeyMod GetKeyModStateFromEvents()
1802 /* always use key modifier state as tracked from key events (this is needed
1803 if the modifier key event was injected into the event queue, but the key
1804 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1805 query the keys as held pressed on the keyboard) -- this case is currently
1806 only used to filter out clipboard insert events from "True X-Mouse" tool */
1808 return HandleKeyModState(KSYM_UNDEFINED, 0);
1811 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1813 if (event->type != EVENT_CLIENTMESSAGE)
1816 #if defined(TARGET_SDL)
1817 return TRUE; /* the only possible message here is SDL_QUIT */
1818 #elif defined(PLATFORM_UNIX)
1819 if ((event->window == window->drawable) &&
1820 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1828 /* ========================================================================= */
1829 /* joystick functions */
1830 /* ========================================================================= */
1832 void InitJoysticks()
1836 #if defined(NO_JOYSTICK)
1837 return; /* joysticks generally deactivated by compile-time directive */
1840 /* always start with reliable default values */
1841 joystick.status = JOYSTICK_NOT_AVAILABLE;
1842 for (i = 0; i < MAX_PLAYERS; i++)
1843 joystick.fd[i] = -1; /* joystick device closed */
1845 #if defined(TARGET_SDL)
1847 #elif defined(PLATFORM_UNIX)
1848 UnixInitJoysticks();
1849 #elif defined(PLATFORM_MSDOS)
1850 MSDOSInitJoysticks();
1854 for (i = 0; i < MAX_PLAYERS; i++)
1855 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1859 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1861 #if defined(TARGET_SDL)
1862 return SDLReadJoystick(nr, x, y, b1, b2);
1863 #elif defined(PLATFORM_UNIX)
1864 return UnixReadJoystick(nr, x, y, b1, b2);
1865 #elif defined(PLATFORM_MSDOS)
1866 return MSDOSReadJoystick(nr, x, y, b1, b2);