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,
83 char *x11_icon_filename, char *x11_iconmask_filename,
84 char *sdl_icon_filename, char *msdos_cursor_filename,
85 char *cookie_prefix, char *filename_prefix,
88 program.command_basepath = getBasePath(argv0);
89 program.command_basename = getBaseName(argv0);
91 program.userdata_subdir = userdata_subdir;
92 program.userdata_subdir_unix = userdata_subdir_unix;
93 program.userdata_path = getUserGameDataDir();
95 program.program_title = program_title;
97 program.window_title = "(undefined)";
99 program.window_title = window_title;
101 program.icon_title = icon_title;
103 program.x11_icon_filename = x11_icon_filename;
104 program.x11_iconmask_filename = x11_iconmask_filename;
105 program.sdl_icon_filename = sdl_icon_filename;
106 program.msdos_cursor_filename = msdos_cursor_filename;
108 program.cookie_prefix = cookie_prefix;
109 program.filename_prefix = filename_prefix;
111 program.version_major = VERSION_MAJOR(program_version);
112 program.version_minor = VERSION_MINOR(program_version);
113 program.version_patch = VERSION_PATCH(program_version);
115 program.error_filename = getErrorFilename(ERROR_BASENAME);
116 program.error_file = stderr;
119 void SetWindowTitle()
121 program.window_title = program.window_title_function();
123 #if defined(TARGET_SDL)
128 void InitWindowTitleFunction(char *(*window_title_function)(void))
130 program.window_title_function = window_title_function;
133 void InitExitMessageFunction(void (*exit_message_function)(char *, va_list))
135 program.exit_message_function = exit_message_function;
138 void InitExitFunction(void (*exit_function)(int))
140 program.exit_function = exit_function;
142 /* set signal handlers to custom exit function */
143 signal(SIGINT, exit_function);
144 signal(SIGTERM, exit_function);
146 #if defined(TARGET_SDL)
147 /* set exit function to automatically cleanup SDL stuff after exit() */
152 void InitPlatformDependentStuff(void)
154 // this is initialized in GetOptions(), but may already be used before
155 options.verbose = TRUE;
157 #if defined(PLATFORM_MSDOS)
161 #if defined(PLATFORM_MACOSX)
162 updateUserGameDataDir();
168 #if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
173 #if defined(TARGET_SDL)
174 #if defined(TARGET_SDL2)
175 int sdl_init_flags = SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE;
177 int sdl_init_flags = SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE;
180 if (SDL_Init(sdl_init_flags) < 0)
181 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
187 void ClosePlatformDependentStuff(void)
189 #if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
193 #if defined(PLATFORM_MSDOS)
198 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
199 int real_sx, int real_sy,
200 int full_sxsize, int full_sysize,
201 Bitmap *field_save_buffer)
207 gfx.real_sx = real_sx;
208 gfx.real_sy = real_sy;
209 gfx.full_sxsize = full_sxsize;
210 gfx.full_sysize = full_sysize;
212 gfx.field_save_buffer = field_save_buffer;
215 gfx.background_bitmap = NULL;
216 gfx.background_bitmap_mask = REDRAW_NONE;
219 SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
220 SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
223 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
231 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
239 void InitGfxDoor3Info(int ex, int ey, int exsize, int eysize)
247 void InitGfxWindowInfo(int win_xsize, int win_ysize)
249 gfx.win_xsize = win_xsize;
250 gfx.win_ysize = win_ysize;
253 gfx.background_bitmap_mask = REDRAW_NONE;
255 ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize, DEFAULT_DEPTH);
259 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
261 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
262 /* 2009-03-24: also (temporarily?) used for overlapping blit workaround */
263 gfx.scrollbuffer_width = scrollbuffer_width;
264 gfx.scrollbuffer_height = scrollbuffer_height;
267 void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height)
269 gfx.clipping_enabled = enabled;
272 gfx.clip_width = width;
273 gfx.clip_height = height;
276 void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
278 gfx.draw_busy_anim_function = draw_busy_anim_function;
281 void InitGfxCustomArtworkInfo()
283 gfx.override_level_graphics = FALSE;
284 gfx.override_level_sounds = FALSE;
285 gfx.override_level_music = FALSE;
287 gfx.draw_init_text = TRUE;
290 void SetDrawDeactivationMask(int draw_deactivation_mask)
292 gfx.draw_deactivation_mask = draw_deactivation_mask;
295 void SetDrawBackgroundMask(int draw_background_mask)
297 gfx.draw_background_mask = draw_background_mask;
302 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
303 int dest_x, int dest_y, int width, int height)
305 int bitmap_xsize = width;
306 int bitmap_ysize = height;
307 int tile_xsize = tile->width;
308 int tile_ysize = tile->height;
309 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
310 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
313 for (y = 0; y < tile_ysteps; y++)
315 for (x = 0; x < tile_xsteps; x++)
317 int draw_x = dest_x + x * tile_xsize;
318 int draw_y = dest_y + y * tile_ysize;
319 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
320 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
322 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
327 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
329 if (background_bitmap_tile != NULL)
330 gfx.background_bitmap_mask |= mask;
332 gfx.background_bitmap_mask &= ~mask;
335 if (gfx.background_bitmap == NULL)
336 gfx.background_bitmap = CreateBitmap(video.width, video.height,
340 if (background_bitmap_tile == NULL) /* empty background requested */
343 if (mask == REDRAW_ALL)
344 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
345 0, 0, video.width, video.height);
346 else if (mask == REDRAW_FIELD)
347 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
348 gfx.real_sx, gfx.real_sy,
349 gfx.full_sxsize, gfx.full_sysize);
350 else if (mask == REDRAW_DOOR_1)
351 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
353 gfx.dxsize, gfx.dysize);
358 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
360 if (background_bitmap_tile != NULL)
361 gfx.background_bitmap_mask |= mask;
363 gfx.background_bitmap_mask &= ~mask;
366 if (gfx.background_bitmap == NULL)
367 gfx.background_bitmap = CreateBitmap(video.width, video.height,
371 if (background_bitmap_tile == NULL) /* empty background requested */
374 if (mask == REDRAW_ALL)
375 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
376 0, 0, video.width, video.height);
377 else if (mask == REDRAW_FIELD)
378 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
379 gfx.real_sx, gfx.real_sy, gfx.full_sxsize, gfx.full_sysize);
380 else if (mask == REDRAW_DOOR_1)
381 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
382 gfx.dx, gfx.dy, gfx.dxsize, gfx.dysize);
387 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
389 /* remove every mask before setting mask for window */
390 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
391 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
392 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
395 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
397 /* remove window area mask before setting mask for main area */
398 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
399 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
400 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
403 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
405 /* remove window area mask before setting mask for door area */
406 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
407 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
408 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
412 /* ========================================================================= */
413 /* video functions */
414 /* ========================================================================= */
416 inline static int GetRealDepth(int depth)
418 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
421 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
422 int width, int height, Pixel color)
424 #if defined(TARGET_SDL)
425 SDLFillRectangle(bitmap, x, y, width, height, color);
427 X11FillRectangle(bitmap, x, y, width, height, color);
431 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
432 int src_x, int src_y, int width, int height,
433 int dst_x, int dst_y, int mask_mode)
435 #if defined(TARGET_SDL)
436 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
437 dst_x, dst_y, mask_mode);
439 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
440 dst_x, dst_y, mask_mode);
444 void LimitScreenUpdates(boolean enable)
446 #if defined(TARGET_SDL)
447 SDLLimitScreenUpdates(enable);
451 void InitVideoDisplay(void)
453 #if defined(TARGET_SDL)
454 SDLInitVideoDisplay();
456 X11InitVideoDisplay();
460 void CloseVideoDisplay(void)
462 KeyboardAutoRepeatOn();
464 #if defined(TARGET_SDL)
465 SDL_QuitSubSystem(SDL_INIT_VIDEO);
468 XCloseDisplay(display);
472 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
475 printf("::: InitVideoBuffer\n");
479 video.height = height;
480 video.depth = GetRealDepth(depth);
482 video.fullscreen_available = FULLSCREEN_STATUS;
483 video.fullscreen_enabled = FALSE;
484 // video.fullscreen_initial = FALSE;
486 video.fullscreen_mode_current = NULL;
487 video.fullscreen_modes = NULL;
490 video.window_scaling_available = WINDOW_SCALING_STATUS;
492 #if defined(TARGET_SDL)
493 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
495 X11InitVideoBuffer(&backbuffer, &window);
501 inline static void FreeBitmapPointers(Bitmap *bitmap)
506 #if defined(TARGET_SDL)
507 SDLFreeBitmapPointers(bitmap);
509 X11FreeBitmapPointers(bitmap);
512 checked_free(bitmap->source_filename);
513 bitmap->source_filename = NULL;
516 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
519 if (src_bitmap == NULL || dst_bitmap == NULL)
522 FreeBitmapPointers(dst_bitmap);
524 *dst_bitmap = *src_bitmap;
527 void FreeBitmap(Bitmap *bitmap)
532 FreeBitmapPointers(bitmap);
537 Bitmap *CreateBitmapStruct(void)
539 #if defined(TARGET_SDL)
540 return checked_calloc(sizeof(struct SDLSurfaceInfo));
542 return checked_calloc(sizeof(struct X11DrawableInfo));
546 Bitmap *CreateBitmap(int width, int height, int depth)
548 Bitmap *new_bitmap = CreateBitmapStruct();
549 int real_width = MAX(1, width); /* prevent zero bitmap width */
550 int real_height = MAX(1, height); /* prevent zero bitmap height */
551 int real_depth = GetRealDepth(depth);
553 #if defined(TARGET_SDL)
554 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
556 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
559 new_bitmap->width = real_width;
560 new_bitmap->height = real_height;
565 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
567 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
571 *bitmap = new_bitmap;
575 TransferBitmapPointers(new_bitmap, *bitmap);
580 void CloseWindow(DrawWindow *window)
582 #if defined(TARGET_X11)
583 X11CloseWindow(window);
587 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
590 if (draw_mask == REDRAW_NONE)
593 if (draw_mask & REDRAW_ALL)
597 if ((draw_mask & REDRAW_FIELD) && IN_GFX_FIELD_FULL(x, y))
600 if ((draw_mask & REDRAW_DOOR_1) && IN_GFX_DOOR_1(x, y))
603 if ((draw_mask & REDRAW_DOOR_2) && IN_GFX_DOOR_2(x, y))
606 if ((draw_mask & REDRAW_DOOR_3) && IN_GFX_DOOR_3(x, y))
609 if ((draw_mask & REDRAW_FIELD) &&
610 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
613 if ((draw_mask & REDRAW_DOOR_1) &&
614 x >= gfx.dx && y < gfx.dy + gfx.dysize)
617 if ((draw_mask & REDRAW_DOOR_2) &&
618 x >= gfx.dx && y >= gfx.vy)
625 boolean DrawingDeactivated(int x, int y, int width, int height)
627 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
630 boolean DrawingOnBackground(int x, int y)
632 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
633 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
636 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
637 int *width, int *height, boolean is_dest)
640 int clip_x, clip_y, clip_width, clip_height;
642 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
644 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
645 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
646 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
647 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
653 clip_width = bitmap->width;
654 clip_height = bitmap->height;
657 /* skip if rectangle completely outside bitmap */
659 if (*x + *width <= clip_x ||
660 *y + *height <= clip_y ||
661 *x >= clip_x + clip_width ||
662 *y >= clip_y + clip_height)
665 /* clip if rectangle overlaps bitmap */
669 *width -= clip_x - *x;
672 else if (*x + *width > clip_x + clip_width)
674 *width = clip_x + clip_width - *x;
679 *height -= clip_y - *y;
682 else if (*y + *height > clip_y + clip_height)
684 *height = clip_y + clip_height - *y;
691 /* skip if rectangle completely outside bitmap */
693 if (*x + *width <= 0 ||
695 *x >= bitmap->width ||
696 *y >= bitmap->height)
699 /* clip if rectangle overlaps bitmap */
706 else if (*x + *width > bitmap->width)
708 *width = bitmap->width - *x;
716 else if (*y + *height > bitmap->height)
718 *height = bitmap->height - *y;
725 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
726 int src_x, int src_y, int width, int height,
727 int dst_x, int dst_y)
729 int dst_x_unclipped = dst_x;
730 int dst_y_unclipped = dst_y;
732 if (src_bitmap == NULL || dst_bitmap == NULL)
735 if (DrawingDeactivated(dst_x, dst_y, width, height))
739 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
740 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
743 /* source x/y might need adjustment if destination x/y was clipped top/left */
744 src_x += dst_x - dst_x_unclipped;
745 src_y += dst_y - dst_y_unclipped;
748 /* skip if rectangle starts outside bitmap */
749 if (src_x >= src_bitmap->width ||
750 src_y >= src_bitmap->height ||
751 dst_x >= dst_bitmap->width ||
752 dst_y >= dst_bitmap->height)
755 /* clip if rectangle overlaps bitmap */
756 if (src_x + width > src_bitmap->width)
757 width = src_bitmap->width - src_x;
758 if (src_y + height > src_bitmap->height)
759 height = src_bitmap->height - src_y;
760 if (dst_x + width > dst_bitmap->width)
761 width = dst_bitmap->width - dst_x;
762 if (dst_y + height > dst_bitmap->height)
763 height = dst_bitmap->height - dst_y;
767 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
769 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
770 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
771 but is already fixed in SVN and should therefore finally be fixed with
772 the next official SDL release, which is probably version 1.2.14.) */
774 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
775 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
776 #if defined(TARGET_SDL2)
777 if (src_bitmap == dst_bitmap)
779 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
781 /* needed when blitting directly to same bitmap -- should not be needed with
782 recent SDL libraries, but apparently does not work in 1.2.11 directly */
784 static Bitmap *tmp_bitmap = NULL;
785 static int tmp_bitmap_xsize = 0;
786 static int tmp_bitmap_ysize = 0;
788 /* start with largest static bitmaps for initial bitmap size ... */
789 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
791 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
792 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
795 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
796 if (src_bitmap->width > tmp_bitmap_xsize ||
797 src_bitmap->height > tmp_bitmap_ysize)
799 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
800 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
802 FreeBitmap(tmp_bitmap);
807 if (tmp_bitmap == NULL)
808 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
811 sysCopyArea(src_bitmap, tmp_bitmap,
812 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
813 sysCopyArea(tmp_bitmap, dst_bitmap,
814 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
824 if (dst_x < gfx.sx + gfx.sxsize)
825 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
826 FrameCounter, dst_x, dst_y, width, height);
829 sysCopyArea(src_bitmap, dst_bitmap,
830 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
833 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
834 int src_x, int src_y, int src_width, int src_height,
835 int dst_x, int dst_y, int dst_width, int dst_height)
837 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
838 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
839 int dst_xsize = dst_width;
840 int dst_ysize = dst_height;
841 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
842 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
845 for (y = 0; y < src_ysteps; y++)
847 for (x = 0; x < src_xsteps; x++)
849 int draw_x = dst_x + x * src_xsize;
850 int draw_y = dst_y + y * src_ysize;
851 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
852 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
854 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
860 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
861 int fade_mode, int fade_delay, int post_delay,
862 void (*draw_border_function)(void))
865 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
866 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
870 #if defined(TARGET_SDL)
871 SDLFadeRectangle(bitmap_cross, x, y, width, height,
872 fade_mode, fade_delay, post_delay, draw_border_function);
874 X11FadeRectangle(bitmap_cross, x, y, width, height,
875 fade_mode, fade_delay, post_delay, draw_border_function);
879 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
882 if (DrawingDeactivated(x, y, width, height))
886 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
889 /* skip if rectangle starts outside bitmap */
890 if (x >= bitmap->width ||
894 /* clip if rectangle overlaps bitmap */
895 if (x + width > bitmap->width)
896 width = bitmap->width - x;
897 if (y + height > bitmap->height)
898 height = bitmap->height - y;
901 sysFillRectangle(bitmap, x, y, width, height, color);
904 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
906 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
909 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
910 int width, int height)
912 if (DrawingOnBackground(x, y))
913 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
915 ClearRectangle(bitmap, x, y, width, height);
918 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
920 #if defined(TARGET_X11)
923 bitmap->clip_gc = clip_gc;
924 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
929 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
931 #if defined(TARGET_X11)
934 bitmap->clip_gc = clip_gc;
935 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
940 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
941 int src_x, int src_y, int width, int height,
942 int dst_x, int dst_y)
944 if (DrawingDeactivated(dst_x, dst_y, width, height))
947 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
948 dst_x, dst_y, BLIT_MASKED);
951 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
952 int src_x, int src_y, int width, int height,
953 int dst_x, int dst_y)
955 if (DrawingOnBackground(dst_x, dst_y))
957 /* draw background */
958 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
961 /* draw foreground */
962 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
963 dst_x - src_x, dst_y - src_y);
964 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
968 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
972 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
975 #if defined(TARGET_SDL)
976 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
978 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
982 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
985 #if defined(TARGET_SDL)
986 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
988 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
992 #if !defined(TARGET_X11_NATIVE)
993 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
994 int to_x, int to_y, Pixel pixel, int line_width)
998 for (x = 0; x < line_width; x++)
1000 for (y = 0; y < line_width; y++)
1002 int dx = x - line_width / 2;
1003 int dy = y - line_width / 2;
1005 if ((x == 0 && y == 0) ||
1006 (x == 0 && y == line_width - 1) ||
1007 (x == line_width - 1 && y == 0) ||
1008 (x == line_width - 1 && y == line_width - 1))
1011 #if defined(TARGET_SDL)
1013 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
1014 #elif defined(TARGET_ALLEGRO)
1015 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
1016 to_x + dx, to_y + dy, pixel);
1023 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
1025 #if !defined(TARGET_X11_NATIVE)
1029 for (i = 0; i < num_points - 1; i++)
1030 DrawLine(bitmap, points[i].x, points[i].y,
1031 points[i + 1].x, points[i + 1].y, pixel, line_width);
1034 SDLDrawLines(bitmap->surface, points, num_points, pixel);
1037 XSetForeground(display, bitmap->line_gc[1], pixel);
1038 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
1039 (XPoint *)points, num_points, CoordModeOrigin);
1043 Pixel GetPixel(Bitmap *bitmap, int x, int y)
1045 if (x < 0 || x >= bitmap->width ||
1046 y < 0 || y >= bitmap->height)
1049 #if defined(TARGET_SDL)
1050 return SDLGetPixel(bitmap, x, y);
1051 #elif defined(TARGET_ALLEGRO)
1052 return AllegroGetPixel(bitmap->drawable, x, y);
1054 return X11GetPixel(bitmap, x, y);
1058 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1059 unsigned int color_g, unsigned int color_b)
1061 #if defined(TARGET_SDL)
1062 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1063 #elif defined(TARGET_ALLEGRO)
1064 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1066 return X11GetPixelFromRGB(color_r, color_g, color_b);
1070 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1072 unsigned int color_r = (color >> 16) & 0xff;
1073 unsigned int color_g = (color >> 8) & 0xff;
1074 unsigned int color_b = (color >> 0) & 0xff;
1076 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1079 /* execute all pending screen drawing operations */
1080 void FlushDisplay(void)
1082 #if !defined(TARGET_SDL)
1087 /* execute and wait for all pending screen drawing operations */
1088 void SyncDisplay(void)
1090 #if !defined(TARGET_SDL)
1091 XSync(display, FALSE);
1095 void KeyboardAutoRepeatOn(void)
1097 #if defined(TARGET_SDL)
1098 #if defined(TARGET_SDL2)
1099 keyrepeat_status = TRUE;
1101 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1102 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1103 SDL_EnableUNICODE(1);
1107 XAutoRepeatOn(display);
1111 void KeyboardAutoRepeatOff(void)
1113 #if defined(TARGET_SDL)
1114 #if defined(TARGET_SDL2)
1115 keyrepeat_status = FALSE;
1117 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1118 SDL_EnableUNICODE(0);
1122 XAutoRepeatOff(display);
1126 boolean PointerInWindow(DrawWindow *window)
1128 #if defined(TARGET_SDL)
1136 /* if XQueryPointer() returns False, the pointer
1137 is not on the same screen as the specified window */
1138 return XQueryPointer(display, window->drawable, &root, &child,
1139 &root_x, &root_y, &win_x, &win_y, &mask);
1143 boolean SetVideoMode(boolean fullscreen)
1145 #if defined(TARGET_SDL)
1146 return SDLSetVideoMode(&backbuffer, fullscreen);
1148 boolean success = TRUE;
1150 if (fullscreen && video.fullscreen_available)
1152 Error(ERR_WARN, "fullscreen not available in X11 version");
1154 /* display error message only once */
1155 video.fullscreen_available = FALSE;
1164 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1166 #if defined(TARGET_SDL)
1167 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1168 (!fullscreen && video.fullscreen_enabled))
1169 fullscreen = SetVideoMode(fullscreen);
1175 Bitmap *LoadImage(char *filename)
1179 #if defined(TARGET_SDL)
1180 new_bitmap = SDLLoadImage(filename);
1182 new_bitmap = X11LoadImage(filename);
1186 new_bitmap->source_filename = getStringCopy(filename);
1191 Bitmap *LoadCustomImage(char *basename)
1193 char *filename = getCustomImageFilename(basename);
1196 if (filename == NULL)
1197 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1199 if ((new_bitmap = LoadImage(filename)) == NULL)
1200 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1205 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1207 char *filename = getCustomImageFilename(basename);
1210 if (filename == NULL) /* (should never happen) */
1212 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1216 if (strEqual(filename, bitmap->source_filename))
1218 /* The old and new image are the same (have the same filename and path).
1219 This usually means that this image does not exist in this graphic set
1220 and a fallback to the existing image is done. */
1225 if ((new_bitmap = LoadImage(filename)) == NULL)
1227 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1231 if (bitmap->width != new_bitmap->width ||
1232 bitmap->height != new_bitmap->height)
1234 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1236 FreeBitmap(new_bitmap);
1240 TransferBitmapPointers(new_bitmap, bitmap);
1244 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1246 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1248 #if defined(TARGET_SDL)
1249 SDLZoomBitmap(src_bitmap, dst_bitmap);
1251 X11ZoomBitmap(src_bitmap, dst_bitmap);
1257 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1258 boolean create_small_bitmaps)
1262 Bitmap *tmp_bitmap_1;
1263 Bitmap *tmp_bitmap_2;
1264 Bitmap *tmp_bitmap_4;
1265 Bitmap *tmp_bitmap_8;
1266 Bitmap *tmp_bitmap_16;
1267 Bitmap *tmp_bitmap_32;
1268 int width_1, height_1;
1269 int width_2, height_2;
1270 int width_4, height_4;
1271 int width_8, height_8;
1272 int width_16, height_16;
1274 int width_32, height_32;
1276 int new_width, new_height;
1278 /* calculate new image dimensions for normal sized image */
1279 width_1 = old_bitmap->width * zoom_factor;
1280 height_1 = old_bitmap->height * zoom_factor;
1282 /* get image with normal size (this might require scaling up) */
1283 if (zoom_factor != 1)
1284 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1286 tmp_bitmap_1 = old_bitmap;
1288 /* this is only needed to make compilers happy */
1289 tmp_bitmap_2 = NULL;
1290 tmp_bitmap_4 = NULL;
1291 tmp_bitmap_8 = NULL;
1292 tmp_bitmap_16 = NULL;
1293 tmp_bitmap_32 = NULL;
1295 if (create_small_bitmaps)
1297 /* calculate new image dimensions for small images */
1298 width_2 = width_1 / 2;
1299 height_2 = height_1 / 2;
1300 width_4 = width_1 / 4;
1301 height_4 = height_1 / 4;
1302 width_8 = width_1 / 8;
1303 height_8 = height_1 / 8;
1304 width_16 = width_1 / 16;
1305 height_16 = height_1 / 16;
1307 width_32 = width_1 / 32;
1308 height_32 = height_1 / 32;
1311 UPDATE_BUSY_STATE();
1313 /* get image with 1/2 of normal size (for use in the level editor) */
1314 if (zoom_factor != 2)
1315 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1317 tmp_bitmap_2 = old_bitmap;
1319 UPDATE_BUSY_STATE();
1321 /* get image with 1/4 of normal size (for use in the level editor) */
1322 if (zoom_factor != 4)
1323 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1325 tmp_bitmap_4 = old_bitmap;
1327 UPDATE_BUSY_STATE();
1329 /* get image with 1/8 of normal size (for use on the preview screen) */
1330 if (zoom_factor != 8)
1331 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1333 tmp_bitmap_8 = old_bitmap;
1335 UPDATE_BUSY_STATE();
1337 /* get image with 1/16 of normal size (for use on the preview screen) */
1338 if (zoom_factor != 16)
1339 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1341 tmp_bitmap_16 = old_bitmap;
1343 UPDATE_BUSY_STATE();
1345 /* get image with 1/32 of normal size (for use on the preview screen) */
1346 if (zoom_factor != 32)
1347 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1349 tmp_bitmap_32 = old_bitmap;
1351 UPDATE_BUSY_STATE();
1355 /* if image was scaled up, create new clipmask for normal size image */
1356 if (zoom_factor != 1)
1358 #if defined(TARGET_X11)
1359 if (old_bitmap->clip_mask)
1360 XFreePixmap(display, old_bitmap->clip_mask);
1362 old_bitmap->clip_mask =
1363 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1365 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1367 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1369 if (old_bitmap->surface_masked)
1370 SDL_FreeSurface(old_bitmap->surface_masked);
1372 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1373 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1374 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1375 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1376 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1381 if (create_small_bitmaps)
1383 new_width = width_1;
1384 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1386 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1388 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1389 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1391 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1392 width_1 / 2, height_1);
1393 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1394 3 * width_1 / 4, height_1);
1395 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1396 7 * width_1 / 8, height_1);
1397 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1398 15 * width_1 / 16, height_1);
1400 UPDATE_BUSY_STATE();
1404 new_width = width_1;
1405 new_height = height_1;
1407 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1410 if (create_small_bitmaps)
1412 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1413 if (zoom_factor != 1)
1414 FreeBitmap(tmp_bitmap_1);
1416 if (zoom_factor != 2)
1417 FreeBitmap(tmp_bitmap_2);
1419 if (zoom_factor != 4)
1420 FreeBitmap(tmp_bitmap_4);
1422 if (zoom_factor != 8)
1423 FreeBitmap(tmp_bitmap_8);
1425 if (zoom_factor != 16)
1426 FreeBitmap(tmp_bitmap_16);
1428 if (zoom_factor != 32)
1429 FreeBitmap(tmp_bitmap_32);
1432 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1433 #if defined(TARGET_SDL)
1434 swap_bitmap.surface = old_bitmap->surface;
1435 old_bitmap->surface = new_bitmap->surface;
1436 new_bitmap->surface = swap_bitmap.surface;
1438 swap_bitmap.drawable = old_bitmap->drawable;
1439 old_bitmap->drawable = new_bitmap->drawable;
1440 new_bitmap->drawable = swap_bitmap.drawable;
1443 old_bitmap->width = new_bitmap->width;
1444 old_bitmap->height = new_bitmap->height;
1447 /* this replaces all blit masks created when loading -- maybe optimize this */
1449 #if defined(TARGET_X11)
1450 if (old_bitmap->clip_mask)
1451 XFreePixmap(display, old_bitmap->clip_mask);
1453 old_bitmap->clip_mask =
1454 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1456 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1458 SDL_Surface *old_surface = old_bitmap->surface;
1460 if (old_bitmap->surface_masked)
1461 SDL_FreeSurface(old_bitmap->surface_masked);
1463 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1464 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1465 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1466 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1467 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1472 UPDATE_BUSY_STATE();
1474 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1477 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1479 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1482 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1484 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1488 /* ------------------------------------------------------------------------- */
1489 /* mouse pointer functions */
1490 /* ------------------------------------------------------------------------- */
1492 #if !defined(PLATFORM_MSDOS)
1493 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1494 /* XPM image definitions */
1495 static const char *cursor_image_none[] =
1497 /* width height num_colors chars_per_pixel */
1526 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1527 static const char *cursor_image_dot[] =
1529 /* width height num_colors chars_per_pixel */
1558 static const char **cursor_image_playfield = cursor_image_dot;
1560 /* some people complained about a "white dot" on the screen and thought it
1561 was a graphical error... OK, let's just remove the whole pointer :-) */
1562 static const char **cursor_image_playfield = cursor_image_none;
1565 #if defined(TARGET_SDL)
1566 static const int cursor_bit_order = BIT_ORDER_MSB;
1567 #elif defined(TARGET_X11_NATIVE)
1568 static const int cursor_bit_order = BIT_ORDER_LSB;
1571 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1573 struct MouseCursorInfo *cursor;
1574 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1575 int header_lines = 4;
1578 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1580 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1583 for (y = 0; y < cursor->width; y++)
1585 for (x = 0; x < cursor->height; x++)
1588 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1593 cursor->data[i] = cursor->mask[i] = 0;
1596 switch (image[header_lines + y][x])
1599 cursor->data[i] |= bit_mask;
1600 cursor->mask[i] |= bit_mask;
1604 cursor->mask[i] |= bit_mask;
1613 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1617 #endif /* !PLATFORM_MSDOS */
1619 void SetMouseCursor(int mode)
1621 #if !defined(PLATFORM_MSDOS)
1622 static struct MouseCursorInfo *cursor_none = NULL;
1623 static struct MouseCursorInfo *cursor_playfield = NULL;
1624 struct MouseCursorInfo *cursor_new;
1626 if (cursor_none == NULL)
1627 cursor_none = get_cursor_from_image(cursor_image_none);
1629 if (cursor_playfield == NULL)
1630 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1632 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1633 mode == CURSOR_NONE ? cursor_none :
1634 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1636 #if defined(TARGET_SDL)
1637 SDLSetMouseCursor(cursor_new);
1638 #elif defined(TARGET_X11_NATIVE)
1639 X11SetMouseCursor(cursor_new);
1645 /* ========================================================================= */
1646 /* audio functions */
1647 /* ========================================================================= */
1649 void OpenAudio(void)
1651 /* always start with reliable default values */
1652 audio.sound_available = FALSE;
1653 audio.music_available = FALSE;
1654 audio.loops_available = FALSE;
1656 audio.sound_enabled = FALSE;
1657 audio.sound_deactivated = FALSE;
1659 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1660 audio.mixer_pid = 0;
1661 audio.device_name = NULL;
1662 audio.device_fd = -1;
1664 audio.num_channels = 0;
1665 audio.music_channel = 0;
1666 audio.first_sound_channel = 0;
1668 #if defined(TARGET_SDL)
1670 #elif defined(PLATFORM_UNIX)
1672 #elif defined(PLATFORM_MSDOS)
1677 void CloseAudio(void)
1679 #if defined(TARGET_SDL)
1681 #elif defined(PLATFORM_UNIX)
1683 #elif defined(PLATFORM_MSDOS)
1687 audio.sound_enabled = FALSE;
1690 void SetAudioMode(boolean enabled)
1692 if (!audio.sound_available)
1695 audio.sound_enabled = enabled;
1699 /* ========================================================================= */
1700 /* event functions */
1701 /* ========================================================================= */
1703 void InitEventFilter(EventFilter filter_function)
1705 /* set event filter to filter out certain events */
1706 #if defined(TARGET_SDL)
1707 #if defined(TARGET_SDL2)
1708 SDL_SetEventFilter(filter_function, NULL);
1710 SDL_SetEventFilter(filter_function);
1715 boolean PendingEvent(void)
1717 #if defined(TARGET_SDL)
1718 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1720 return (XPending(display) ? TRUE : FALSE);
1724 void NextEvent(Event *event)
1726 #if defined(TARGET_SDL)
1727 SDLNextEvent(event);
1729 XNextEvent(display, event);
1733 void PeekEvent(Event *event)
1735 #if defined(TARGET_SDL)
1736 #if defined(TARGET_SDL2)
1737 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1739 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1742 XPeekEvent(display, event);
1746 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1748 #if defined(TARGET_SDL)
1749 #if defined(TARGET_SDL2)
1750 /* key up/down events in SDL2 do not return text characters anymore */
1751 return event->keysym.sym;
1755 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1756 (int)event->keysym.unicode,
1757 (int)event->keysym.sym,
1758 (int)SDL_GetModState());
1761 if (with_modifiers &&
1762 event->keysym.unicode > 0x0000 &&
1763 event->keysym.unicode < 0x2000)
1764 return event->keysym.unicode;
1766 return event->keysym.sym;
1772 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1773 (int)XLookupKeysym(event, event->state),
1774 (int)XLookupKeysym(event, 0));
1778 return XLookupKeysym(event, event->state);
1780 return XLookupKeysym(event, 0);
1784 KeyMod HandleKeyModState(Key key, int key_status)
1786 static KeyMod current_modifiers = KMOD_None;
1788 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1790 KeyMod new_modifier = KMOD_None;
1795 new_modifier = KMOD_Shift_L;
1798 new_modifier = KMOD_Shift_R;
1800 case KSYM_Control_L:
1801 new_modifier = KMOD_Control_L;
1803 case KSYM_Control_R:
1804 new_modifier = KMOD_Control_R;
1807 new_modifier = KMOD_Meta_L;
1810 new_modifier = KMOD_Meta_R;
1813 new_modifier = KMOD_Alt_L;
1816 new_modifier = KMOD_Alt_R;
1822 if (key_status == KEY_PRESSED)
1823 current_modifiers |= new_modifier;
1825 current_modifiers &= ~new_modifier;
1828 return current_modifiers;
1831 KeyMod GetKeyModState()
1833 #if defined(TARGET_SDL)
1834 return (KeyMod)SDL_GetModState();
1836 return HandleKeyModState(KSYM_UNDEFINED, 0);
1840 KeyMod GetKeyModStateFromEvents()
1842 /* always use key modifier state as tracked from key events (this is needed
1843 if the modifier key event was injected into the event queue, but the key
1844 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1845 query the keys as held pressed on the keyboard) -- this case is currently
1846 only used to filter out clipboard insert events from "True X-Mouse" tool */
1848 return HandleKeyModState(KSYM_UNDEFINED, 0);
1851 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1853 if (event->type != EVENT_CLIENTMESSAGE)
1856 #if defined(TARGET_SDL)
1857 return TRUE; /* the only possible message here is SDL_QUIT */
1858 #elif defined(PLATFORM_UNIX)
1859 if ((event->window == window->drawable) &&
1860 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1868 /* ========================================================================= */
1869 /* joystick functions */
1870 /* ========================================================================= */
1872 void InitJoysticks()
1876 #if defined(NO_JOYSTICK)
1877 return; /* joysticks generally deactivated by compile-time directive */
1880 /* always start with reliable default values */
1881 joystick.status = JOYSTICK_NOT_AVAILABLE;
1882 for (i = 0; i < MAX_PLAYERS; i++)
1883 joystick.fd[i] = -1; /* joystick device closed */
1885 #if defined(TARGET_SDL)
1887 #elif defined(PLATFORM_UNIX)
1888 UnixInitJoysticks();
1889 #elif defined(PLATFORM_MSDOS)
1890 MSDOSInitJoysticks();
1894 for (i = 0; i < MAX_PLAYERS; i++)
1895 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1899 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1901 #if defined(TARGET_SDL)
1902 return SDLReadJoystick(nr, x, y, b1, b2);
1903 #elif defined(PLATFORM_UNIX)
1904 return UnixReadJoystick(nr, x, y, b1, b2);
1905 #elif defined(PLATFORM_MSDOS)
1906 return MSDOSReadJoystick(nr, x, y, b1, b2);