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)
321 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
323 gfx.dxsize, gfx.dysize);
328 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
330 if (background_bitmap_tile != NULL)
331 gfx.background_bitmap_mask |= mask;
333 gfx.background_bitmap_mask &= ~mask;
336 if (gfx.background_bitmap == NULL)
337 gfx.background_bitmap = CreateBitmap(video.width, video.height,
341 if (background_bitmap_tile == NULL) /* empty background requested */
344 if (mask == REDRAW_ALL)
345 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
346 0, 0, video.width, video.height);
347 else if (mask == REDRAW_FIELD)
348 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
349 gfx.real_sx, gfx.real_sy, gfx.full_sxsize, gfx.full_sysize);
350 else if (mask == REDRAW_DOOR_1)
351 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
352 gfx.dx, gfx.dy, gfx.dxsize, gfx.dysize);
357 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
359 /* remove every mask before setting mask for window */
360 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
361 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
362 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
365 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
367 /* remove window area mask before setting mask for main area */
368 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
369 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
370 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
373 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
375 /* remove window area mask before setting mask for door area */
376 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
377 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
378 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
382 /* ========================================================================= */
383 /* video functions */
384 /* ========================================================================= */
386 inline static int GetRealDepth(int depth)
388 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
391 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
392 int width, int height, Pixel color)
394 #if defined(TARGET_SDL)
395 SDLFillRectangle(bitmap, x, y, width, height, color);
397 X11FillRectangle(bitmap, x, y, width, height, color);
401 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
402 int src_x, int src_y, int width, int height,
403 int dst_x, int dst_y, int mask_mode)
405 #if defined(TARGET_SDL)
406 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
407 dst_x, dst_y, mask_mode);
409 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
410 dst_x, dst_y, mask_mode);
414 void LimitScreenUpdates(boolean enable)
416 #if defined(TARGET_SDL)
417 SDLLimitScreenUpdates(enable);
421 void InitVideoDisplay(void)
423 #if defined(TARGET_SDL)
424 SDLInitVideoDisplay();
426 X11InitVideoDisplay();
430 void CloseVideoDisplay(void)
432 KeyboardAutoRepeatOn();
434 #if defined(TARGET_SDL)
435 SDL_QuitSubSystem(SDL_INIT_VIDEO);
438 XCloseDisplay(display);
442 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
445 printf("::: InitVideoBuffer\n");
449 video.height = height;
450 video.depth = GetRealDepth(depth);
452 video.fullscreen_available = FULLSCREEN_STATUS;
453 video.fullscreen_enabled = FALSE;
454 // video.fullscreen_initial = FALSE;
456 video.fullscreen_mode_current = NULL;
457 video.fullscreen_modes = NULL;
460 video.window_scaling_available = WINDOW_SCALING_STATUS;
462 #if defined(TARGET_SDL)
463 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
465 X11InitVideoBuffer(&backbuffer, &window);
471 inline static void FreeBitmapPointers(Bitmap *bitmap)
476 #if defined(TARGET_SDL)
477 SDLFreeBitmapPointers(bitmap);
479 X11FreeBitmapPointers(bitmap);
482 checked_free(bitmap->source_filename);
483 bitmap->source_filename = NULL;
486 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
489 if (src_bitmap == NULL || dst_bitmap == NULL)
492 FreeBitmapPointers(dst_bitmap);
494 *dst_bitmap = *src_bitmap;
497 void FreeBitmap(Bitmap *bitmap)
502 FreeBitmapPointers(bitmap);
507 Bitmap *CreateBitmapStruct(void)
509 #if defined(TARGET_SDL)
510 return checked_calloc(sizeof(struct SDLSurfaceInfo));
512 return checked_calloc(sizeof(struct X11DrawableInfo));
516 Bitmap *CreateBitmap(int width, int height, int depth)
518 Bitmap *new_bitmap = CreateBitmapStruct();
519 int real_width = MAX(1, width); /* prevent zero bitmap width */
520 int real_height = MAX(1, height); /* prevent zero bitmap height */
521 int real_depth = GetRealDepth(depth);
523 #if defined(TARGET_SDL)
524 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
526 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
529 new_bitmap->width = real_width;
530 new_bitmap->height = real_height;
535 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
537 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
541 *bitmap = new_bitmap;
545 TransferBitmapPointers(new_bitmap, *bitmap);
550 void CloseWindow(DrawWindow *window)
552 #if defined(TARGET_X11)
553 X11CloseWindow(window);
557 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
560 if (draw_mask == REDRAW_NONE)
563 if (draw_mask & REDRAW_ALL)
566 if ((draw_mask & REDRAW_FIELD) &&
567 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
570 if ((draw_mask & REDRAW_DOOR_1) &&
571 x >= gfx.dx && y < gfx.dy + gfx.dysize)
574 if ((draw_mask & REDRAW_DOOR_2) &&
575 x >= gfx.dx && y >= gfx.vy)
581 boolean DrawingDeactivated(int x, int y, int width, int height)
583 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
586 boolean DrawingOnBackground(int x, int y)
588 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
589 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
592 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
593 int *width, int *height, boolean is_dest)
596 int clip_x, clip_y, clip_width, clip_height;
598 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
600 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
601 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
602 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
603 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
609 clip_width = bitmap->width;
610 clip_height = bitmap->height;
613 /* skip if rectangle completely outside bitmap */
615 if (*x + *width <= clip_x ||
616 *y + *height <= clip_y ||
617 *x >= clip_x + clip_width ||
618 *y >= clip_y + clip_height)
621 /* clip if rectangle overlaps bitmap */
625 *width -= clip_x - *x;
628 else if (*x + *width > clip_x + clip_width)
630 *width = clip_x + clip_width - *x;
635 *height -= clip_y - *y;
638 else if (*y + *height > clip_y + clip_height)
640 *height = clip_y + clip_height - *y;
647 /* skip if rectangle completely outside bitmap */
649 if (*x + *width <= 0 ||
651 *x >= bitmap->width ||
652 *y >= bitmap->height)
655 /* clip if rectangle overlaps bitmap */
662 else if (*x + *width > bitmap->width)
664 *width = bitmap->width - *x;
672 else if (*y + *height > bitmap->height)
674 *height = bitmap->height - *y;
681 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
682 int src_x, int src_y, int width, int height,
683 int dst_x, int dst_y)
685 int dst_x_unclipped = dst_x;
686 int dst_y_unclipped = dst_y;
688 if (src_bitmap == NULL || dst_bitmap == NULL)
691 if (DrawingDeactivated(dst_x, dst_y, width, height))
695 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
696 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
699 /* source x/y might need adjustment if destination x/y was clipped top/left */
700 src_x += dst_x - dst_x_unclipped;
701 src_y += dst_y - dst_y_unclipped;
704 /* skip if rectangle starts outside bitmap */
705 if (src_x >= src_bitmap->width ||
706 src_y >= src_bitmap->height ||
707 dst_x >= dst_bitmap->width ||
708 dst_y >= dst_bitmap->height)
711 /* clip if rectangle overlaps bitmap */
712 if (src_x + width > src_bitmap->width)
713 width = src_bitmap->width - src_x;
714 if (src_y + height > src_bitmap->height)
715 height = src_bitmap->height - src_y;
716 if (dst_x + width > dst_bitmap->width)
717 width = dst_bitmap->width - dst_x;
718 if (dst_y + height > dst_bitmap->height)
719 height = dst_bitmap->height - dst_y;
723 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
725 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
726 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
727 but is already fixed in SVN and should therefore finally be fixed with
728 the next official SDL release, which is probably version 1.2.14.) */
730 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
731 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
732 #if defined(TARGET_SDL2)
733 if (src_bitmap == dst_bitmap)
735 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
737 /* needed when blitting directly to same bitmap -- should not be needed with
738 recent SDL libraries, but apparently does not work in 1.2.11 directly */
740 static Bitmap *tmp_bitmap = NULL;
741 static int tmp_bitmap_xsize = 0;
742 static int tmp_bitmap_ysize = 0;
744 /* start with largest static bitmaps for initial bitmap size ... */
745 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
747 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
748 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
751 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
752 if (src_bitmap->width > tmp_bitmap_xsize ||
753 src_bitmap->height > tmp_bitmap_ysize)
755 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
756 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
758 FreeBitmap(tmp_bitmap);
763 if (tmp_bitmap == NULL)
764 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
767 sysCopyArea(src_bitmap, tmp_bitmap,
768 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
769 sysCopyArea(tmp_bitmap, dst_bitmap,
770 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
780 if (dst_x < gfx.sx + gfx.sxsize)
781 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
782 FrameCounter, dst_x, dst_y, width, height);
785 sysCopyArea(src_bitmap, dst_bitmap,
786 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
789 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
790 int src_x, int src_y, int src_width, int src_height,
791 int dst_x, int dst_y, int dst_width, int dst_height)
793 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
794 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
795 int dst_xsize = dst_width;
796 int dst_ysize = dst_height;
797 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
798 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
801 for (y = 0; y < src_ysteps; y++)
803 for (x = 0; x < src_xsteps; x++)
805 int draw_x = dst_x + x * src_xsize;
806 int draw_y = dst_y + y * src_ysize;
807 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
808 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
810 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
816 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
817 int fade_mode, int fade_delay, int post_delay,
818 void (*draw_border_function)(void))
821 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
822 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
826 #if defined(TARGET_SDL)
827 SDLFadeRectangle(bitmap_cross, x, y, width, height,
828 fade_mode, fade_delay, post_delay, draw_border_function);
830 X11FadeRectangle(bitmap_cross, x, y, width, height,
831 fade_mode, fade_delay, post_delay, draw_border_function);
835 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
838 if (DrawingDeactivated(x, y, width, height))
842 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
845 /* skip if rectangle starts outside bitmap */
846 if (x >= bitmap->width ||
850 /* clip if rectangle overlaps bitmap */
851 if (x + width > bitmap->width)
852 width = bitmap->width - x;
853 if (y + height > bitmap->height)
854 height = bitmap->height - y;
857 sysFillRectangle(bitmap, x, y, width, height, color);
860 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
862 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
865 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
866 int width, int height)
868 if (DrawingOnBackground(x, y))
869 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
871 ClearRectangle(bitmap, x, y, width, height);
874 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
876 #if defined(TARGET_X11)
879 bitmap->clip_gc = clip_gc;
880 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
885 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
887 #if defined(TARGET_X11)
890 bitmap->clip_gc = clip_gc;
891 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
896 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
897 int src_x, int src_y, int width, int height,
898 int dst_x, int dst_y)
900 if (DrawingDeactivated(dst_x, dst_y, width, height))
903 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
904 dst_x, dst_y, BLIT_MASKED);
907 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
908 int src_x, int src_y, int width, int height,
909 int dst_x, int dst_y)
911 if (DrawingOnBackground(dst_x, dst_y))
913 /* draw background */
914 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
917 /* draw foreground */
918 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
919 dst_x - src_x, dst_y - src_y);
920 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
924 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
928 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
931 #if defined(TARGET_SDL)
932 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
934 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
938 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
941 #if defined(TARGET_SDL)
942 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
944 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
948 #if !defined(TARGET_X11_NATIVE)
949 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
950 int to_x, int to_y, Pixel pixel, int line_width)
954 for (x = 0; x < line_width; x++)
956 for (y = 0; y < line_width; y++)
958 int dx = x - line_width / 2;
959 int dy = y - line_width / 2;
961 if ((x == 0 && y == 0) ||
962 (x == 0 && y == line_width - 1) ||
963 (x == line_width - 1 && y == 0) ||
964 (x == line_width - 1 && y == line_width - 1))
967 #if defined(TARGET_SDL)
969 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
970 #elif defined(TARGET_ALLEGRO)
971 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
972 to_x + dx, to_y + dy, pixel);
979 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
981 #if !defined(TARGET_X11_NATIVE)
985 for (i = 0; i < num_points - 1; i++)
986 DrawLine(bitmap, points[i].x, points[i].y,
987 points[i + 1].x, points[i + 1].y, pixel, line_width);
990 SDLDrawLines(bitmap->surface, points, num_points, pixel);
993 XSetForeground(display, bitmap->line_gc[1], pixel);
994 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
995 (XPoint *)points, num_points, CoordModeOrigin);
999 Pixel GetPixel(Bitmap *bitmap, int x, int y)
1001 if (x < 0 || x >= bitmap->width ||
1002 y < 0 || y >= bitmap->height)
1005 #if defined(TARGET_SDL)
1006 return SDLGetPixel(bitmap, x, y);
1007 #elif defined(TARGET_ALLEGRO)
1008 return AllegroGetPixel(bitmap->drawable, x, y);
1010 return X11GetPixel(bitmap, x, y);
1014 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1015 unsigned int color_g, unsigned int color_b)
1017 #if defined(TARGET_SDL)
1018 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1019 #elif defined(TARGET_ALLEGRO)
1020 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1022 return X11GetPixelFromRGB(color_r, color_g, color_b);
1026 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1028 unsigned int color_r = (color >> 16) & 0xff;
1029 unsigned int color_g = (color >> 8) & 0xff;
1030 unsigned int color_b = (color >> 0) & 0xff;
1032 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1035 /* execute all pending screen drawing operations */
1036 void FlushDisplay(void)
1038 #if !defined(TARGET_SDL)
1043 /* execute and wait for all pending screen drawing operations */
1044 void SyncDisplay(void)
1046 #if !defined(TARGET_SDL)
1047 XSync(display, FALSE);
1051 void KeyboardAutoRepeatOn(void)
1053 #if defined(TARGET_SDL)
1054 #if defined(TARGET_SDL2)
1055 keyrepeat_status = TRUE;
1057 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1058 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1059 SDL_EnableUNICODE(1);
1063 XAutoRepeatOn(display);
1067 void KeyboardAutoRepeatOff(void)
1069 #if defined(TARGET_SDL)
1070 #if defined(TARGET_SDL2)
1071 keyrepeat_status = FALSE;
1073 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1074 SDL_EnableUNICODE(0);
1078 XAutoRepeatOff(display);
1082 boolean PointerInWindow(DrawWindow *window)
1084 #if defined(TARGET_SDL)
1092 /* if XQueryPointer() returns False, the pointer
1093 is not on the same screen as the specified window */
1094 return XQueryPointer(display, window->drawable, &root, &child,
1095 &root_x, &root_y, &win_x, &win_y, &mask);
1099 boolean SetVideoMode(boolean fullscreen)
1101 #if defined(TARGET_SDL)
1102 return SDLSetVideoMode(&backbuffer, fullscreen);
1104 boolean success = TRUE;
1106 if (fullscreen && video.fullscreen_available)
1108 Error(ERR_WARN, "fullscreen not available in X11 version");
1110 /* display error message only once */
1111 video.fullscreen_available = FALSE;
1120 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1122 #if defined(TARGET_SDL)
1123 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1124 (!fullscreen && video.fullscreen_enabled))
1125 fullscreen = SetVideoMode(fullscreen);
1131 Bitmap *LoadImage(char *filename)
1135 #if defined(TARGET_SDL)
1136 new_bitmap = SDLLoadImage(filename);
1138 new_bitmap = X11LoadImage(filename);
1142 new_bitmap->source_filename = getStringCopy(filename);
1147 Bitmap *LoadCustomImage(char *basename)
1149 char *filename = getCustomImageFilename(basename);
1152 if (filename == NULL)
1153 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1155 if ((new_bitmap = LoadImage(filename)) == NULL)
1156 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1161 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1163 char *filename = getCustomImageFilename(basename);
1166 if (filename == NULL) /* (should never happen) */
1168 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1172 if (strEqual(filename, bitmap->source_filename))
1174 /* The old and new image are the same (have the same filename and path).
1175 This usually means that this image does not exist in this graphic set
1176 and a fallback to the existing image is done. */
1181 if ((new_bitmap = LoadImage(filename)) == NULL)
1183 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1187 if (bitmap->width != new_bitmap->width ||
1188 bitmap->height != new_bitmap->height)
1190 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1192 FreeBitmap(new_bitmap);
1196 TransferBitmapPointers(new_bitmap, bitmap);
1200 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1202 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1204 #if defined(TARGET_SDL)
1205 SDLZoomBitmap(src_bitmap, dst_bitmap);
1207 X11ZoomBitmap(src_bitmap, dst_bitmap);
1213 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1214 boolean create_small_bitmaps)
1218 Bitmap *tmp_bitmap_1;
1219 Bitmap *tmp_bitmap_2;
1220 Bitmap *tmp_bitmap_4;
1221 Bitmap *tmp_bitmap_8;
1222 Bitmap *tmp_bitmap_16;
1223 Bitmap *tmp_bitmap_32;
1224 int width_1, height_1;
1225 int width_2, height_2;
1226 int width_4, height_4;
1227 int width_8, height_8;
1228 int width_16, height_16;
1230 int width_32, height_32;
1232 int new_width, new_height;
1234 /* calculate new image dimensions for normal sized image */
1235 width_1 = old_bitmap->width * zoom_factor;
1236 height_1 = old_bitmap->height * zoom_factor;
1238 /* get image with normal size (this might require scaling up) */
1239 if (zoom_factor != 1)
1240 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1242 tmp_bitmap_1 = old_bitmap;
1244 /* this is only needed to make compilers happy */
1245 tmp_bitmap_2 = NULL;
1246 tmp_bitmap_4 = NULL;
1247 tmp_bitmap_8 = NULL;
1248 tmp_bitmap_16 = NULL;
1249 tmp_bitmap_32 = NULL;
1251 if (create_small_bitmaps)
1253 /* calculate new image dimensions for small images */
1254 width_2 = width_1 / 2;
1255 height_2 = height_1 / 2;
1256 width_4 = width_1 / 4;
1257 height_4 = height_1 / 4;
1258 width_8 = width_1 / 8;
1259 height_8 = height_1 / 8;
1260 width_16 = width_1 / 16;
1261 height_16 = height_1 / 16;
1263 width_32 = width_1 / 32;
1264 height_32 = height_1 / 32;
1267 UPDATE_BUSY_STATE();
1269 /* get image with 1/2 of normal size (for use in the level editor) */
1270 if (zoom_factor != 2)
1271 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1273 tmp_bitmap_2 = old_bitmap;
1275 UPDATE_BUSY_STATE();
1277 /* get image with 1/4 of normal size (for use in the level editor) */
1278 if (zoom_factor != 4)
1279 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1281 tmp_bitmap_4 = old_bitmap;
1283 UPDATE_BUSY_STATE();
1285 /* get image with 1/8 of normal size (for use on the preview screen) */
1286 if (zoom_factor != 8)
1287 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1289 tmp_bitmap_8 = old_bitmap;
1291 UPDATE_BUSY_STATE();
1293 /* get image with 1/16 of normal size (for use on the preview screen) */
1294 if (zoom_factor != 16)
1295 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1297 tmp_bitmap_16 = old_bitmap;
1299 UPDATE_BUSY_STATE();
1301 /* get image with 1/32 of normal size (for use on the preview screen) */
1302 if (zoom_factor != 32)
1303 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1305 tmp_bitmap_32 = old_bitmap;
1307 UPDATE_BUSY_STATE();
1311 /* if image was scaled up, create new clipmask for normal size image */
1312 if (zoom_factor != 1)
1314 #if defined(TARGET_X11)
1315 if (old_bitmap->clip_mask)
1316 XFreePixmap(display, old_bitmap->clip_mask);
1318 old_bitmap->clip_mask =
1319 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1321 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1323 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1325 if (old_bitmap->surface_masked)
1326 SDL_FreeSurface(old_bitmap->surface_masked);
1328 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1329 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1330 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1331 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1332 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1337 if (create_small_bitmaps)
1339 new_width = width_1;
1340 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1342 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1344 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1345 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1347 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1348 width_1 / 2, height_1);
1349 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1350 3 * width_1 / 4, height_1);
1351 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1352 7 * width_1 / 8, height_1);
1353 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1354 15 * width_1 / 16, height_1);
1356 UPDATE_BUSY_STATE();
1360 new_width = width_1;
1361 new_height = height_1;
1363 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1366 if (create_small_bitmaps)
1368 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1369 if (zoom_factor != 1)
1370 FreeBitmap(tmp_bitmap_1);
1372 if (zoom_factor != 2)
1373 FreeBitmap(tmp_bitmap_2);
1375 if (zoom_factor != 4)
1376 FreeBitmap(tmp_bitmap_4);
1378 if (zoom_factor != 8)
1379 FreeBitmap(tmp_bitmap_8);
1381 if (zoom_factor != 16)
1382 FreeBitmap(tmp_bitmap_16);
1384 if (zoom_factor != 32)
1385 FreeBitmap(tmp_bitmap_32);
1388 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1389 #if defined(TARGET_SDL)
1390 swap_bitmap.surface = old_bitmap->surface;
1391 old_bitmap->surface = new_bitmap->surface;
1392 new_bitmap->surface = swap_bitmap.surface;
1394 swap_bitmap.drawable = old_bitmap->drawable;
1395 old_bitmap->drawable = new_bitmap->drawable;
1396 new_bitmap->drawable = swap_bitmap.drawable;
1399 old_bitmap->width = new_bitmap->width;
1400 old_bitmap->height = new_bitmap->height;
1403 /* this replaces all blit masks created when loading -- maybe optimize this */
1405 #if defined(TARGET_X11)
1406 if (old_bitmap->clip_mask)
1407 XFreePixmap(display, old_bitmap->clip_mask);
1409 old_bitmap->clip_mask =
1410 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1412 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1414 SDL_Surface *old_surface = old_bitmap->surface;
1416 if (old_bitmap->surface_masked)
1417 SDL_FreeSurface(old_bitmap->surface_masked);
1419 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1420 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1421 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1422 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1423 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1428 UPDATE_BUSY_STATE();
1430 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1433 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1435 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1438 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1440 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1444 /* ------------------------------------------------------------------------- */
1445 /* mouse pointer functions */
1446 /* ------------------------------------------------------------------------- */
1448 #if !defined(PLATFORM_MSDOS)
1449 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1450 /* XPM image definitions */
1451 static const char *cursor_image_none[] =
1453 /* width height num_colors chars_per_pixel */
1482 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1483 static const char *cursor_image_dot[] =
1485 /* width height num_colors chars_per_pixel */
1514 static const char **cursor_image_playfield = cursor_image_dot;
1516 /* some people complained about a "white dot" on the screen and thought it
1517 was a graphical error... OK, let's just remove the whole pointer :-) */
1518 static const char **cursor_image_playfield = cursor_image_none;
1521 #if defined(TARGET_SDL)
1522 static const int cursor_bit_order = BIT_ORDER_MSB;
1523 #elif defined(TARGET_X11_NATIVE)
1524 static const int cursor_bit_order = BIT_ORDER_LSB;
1527 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1529 struct MouseCursorInfo *cursor;
1530 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1531 int header_lines = 4;
1534 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1536 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1539 for (y = 0; y < cursor->width; y++)
1541 for (x = 0; x < cursor->height; x++)
1544 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1549 cursor->data[i] = cursor->mask[i] = 0;
1552 switch (image[header_lines + y][x])
1555 cursor->data[i] |= bit_mask;
1556 cursor->mask[i] |= bit_mask;
1560 cursor->mask[i] |= bit_mask;
1569 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1573 #endif /* !PLATFORM_MSDOS */
1575 void SetMouseCursor(int mode)
1577 #if !defined(PLATFORM_MSDOS)
1578 static struct MouseCursorInfo *cursor_none = NULL;
1579 static struct MouseCursorInfo *cursor_playfield = NULL;
1580 struct MouseCursorInfo *cursor_new;
1582 if (cursor_none == NULL)
1583 cursor_none = get_cursor_from_image(cursor_image_none);
1585 if (cursor_playfield == NULL)
1586 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1588 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1589 mode == CURSOR_NONE ? cursor_none :
1590 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1592 #if defined(TARGET_SDL)
1593 SDLSetMouseCursor(cursor_new);
1594 #elif defined(TARGET_X11_NATIVE)
1595 X11SetMouseCursor(cursor_new);
1601 /* ========================================================================= */
1602 /* audio functions */
1603 /* ========================================================================= */
1605 void OpenAudio(void)
1607 /* always start with reliable default values */
1608 audio.sound_available = FALSE;
1609 audio.music_available = FALSE;
1610 audio.loops_available = FALSE;
1612 audio.sound_enabled = FALSE;
1613 audio.sound_deactivated = FALSE;
1615 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1616 audio.mixer_pid = 0;
1617 audio.device_name = NULL;
1618 audio.device_fd = -1;
1620 audio.num_channels = 0;
1621 audio.music_channel = 0;
1622 audio.first_sound_channel = 0;
1624 #if defined(TARGET_SDL)
1626 #elif defined(PLATFORM_UNIX)
1628 #elif defined(PLATFORM_MSDOS)
1633 void CloseAudio(void)
1635 #if defined(TARGET_SDL)
1637 #elif defined(PLATFORM_UNIX)
1639 #elif defined(PLATFORM_MSDOS)
1643 audio.sound_enabled = FALSE;
1646 void SetAudioMode(boolean enabled)
1648 if (!audio.sound_available)
1651 audio.sound_enabled = enabled;
1655 /* ========================================================================= */
1656 /* event functions */
1657 /* ========================================================================= */
1659 void InitEventFilter(EventFilter filter_function)
1661 /* set event filter to filter out certain events */
1662 #if defined(TARGET_SDL)
1663 #if defined(TARGET_SDL2)
1664 SDL_SetEventFilter(filter_function, NULL);
1666 SDL_SetEventFilter(filter_function);
1671 boolean PendingEvent(void)
1673 #if defined(TARGET_SDL)
1674 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1676 return (XPending(display) ? TRUE : FALSE);
1680 void NextEvent(Event *event)
1682 #if defined(TARGET_SDL)
1683 SDLNextEvent(event);
1685 XNextEvent(display, event);
1689 void PeekEvent(Event *event)
1691 #if defined(TARGET_SDL)
1692 #if defined(TARGET_SDL2)
1693 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1695 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1698 XPeekEvent(display, event);
1702 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1704 #if defined(TARGET_SDL)
1705 #if defined(TARGET_SDL2)
1706 /* key up/down events in SDL2 do not return text characters anymore */
1707 return event->keysym.sym;
1711 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1712 (int)event->keysym.unicode,
1713 (int)event->keysym.sym,
1714 (int)SDL_GetModState());
1717 if (with_modifiers &&
1718 event->keysym.unicode > 0x0000 &&
1719 event->keysym.unicode < 0x2000)
1720 return event->keysym.unicode;
1722 return event->keysym.sym;
1728 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1729 (int)XLookupKeysym(event, event->state),
1730 (int)XLookupKeysym(event, 0));
1734 return XLookupKeysym(event, event->state);
1736 return XLookupKeysym(event, 0);
1740 KeyMod HandleKeyModState(Key key, int key_status)
1742 static KeyMod current_modifiers = KMOD_None;
1744 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1746 KeyMod new_modifier = KMOD_None;
1751 new_modifier = KMOD_Shift_L;
1754 new_modifier = KMOD_Shift_R;
1756 case KSYM_Control_L:
1757 new_modifier = KMOD_Control_L;
1759 case KSYM_Control_R:
1760 new_modifier = KMOD_Control_R;
1763 new_modifier = KMOD_Meta_L;
1766 new_modifier = KMOD_Meta_R;
1769 new_modifier = KMOD_Alt_L;
1772 new_modifier = KMOD_Alt_R;
1778 if (key_status == KEY_PRESSED)
1779 current_modifiers |= new_modifier;
1781 current_modifiers &= ~new_modifier;
1784 return current_modifiers;
1787 KeyMod GetKeyModState()
1789 #if defined(TARGET_SDL)
1790 return (KeyMod)SDL_GetModState();
1792 return HandleKeyModState(KSYM_UNDEFINED, 0);
1796 KeyMod GetKeyModStateFromEvents()
1798 /* always use key modifier state as tracked from key events (this is needed
1799 if the modifier key event was injected into the event queue, but the key
1800 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1801 query the keys as held pressed on the keyboard) -- this case is currently
1802 only used to filter out clipboard insert events from "True X-Mouse" tool */
1804 return HandleKeyModState(KSYM_UNDEFINED, 0);
1807 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1809 if (event->type != EVENT_CLIENTMESSAGE)
1812 #if defined(TARGET_SDL)
1813 return TRUE; /* the only possible message here is SDL_QUIT */
1814 #elif defined(PLATFORM_UNIX)
1815 if ((event->window == window->drawable) &&
1816 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1824 /* ========================================================================= */
1825 /* joystick functions */
1826 /* ========================================================================= */
1828 void InitJoysticks()
1832 #if defined(NO_JOYSTICK)
1833 return; /* joysticks generally deactivated by compile-time directive */
1836 /* always start with reliable default values */
1837 joystick.status = JOYSTICK_NOT_AVAILABLE;
1838 for (i = 0; i < MAX_PLAYERS; i++)
1839 joystick.fd[i] = -1; /* joystick device closed */
1841 #if defined(TARGET_SDL)
1843 #elif defined(PLATFORM_UNIX)
1844 UnixInitJoysticks();
1845 #elif defined(PLATFORM_MSDOS)
1846 MSDOSInitJoysticks();
1850 for (i = 0; i < MAX_PLAYERS; i++)
1851 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1855 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1857 #if defined(TARGET_SDL)
1858 return SDLReadJoystick(nr, x, y, b1, b2);
1859 #elif defined(PLATFORM_UNIX)
1860 return UnixReadJoystick(nr, x, y, b1, b2);
1861 #elif defined(PLATFORM_MSDOS)
1862 return MSDOSReadJoystick(nr, x, y, b1, b2);