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 LimitScreenUpdates(boolean enable)
420 #if defined(TARGET_SDL)
421 SDLLimitScreenUpdates(enable);
425 void InitVideoDisplay(void)
427 #if defined(TARGET_SDL)
428 SDLInitVideoDisplay();
430 X11InitVideoDisplay();
434 void CloseVideoDisplay(void)
436 KeyboardAutoRepeatOn();
438 #if defined(TARGET_SDL)
439 SDL_QuitSubSystem(SDL_INIT_VIDEO);
442 XCloseDisplay(display);
446 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
449 printf("::: InitVideoBuffer\n");
453 video.height = height;
454 video.depth = GetRealDepth(depth);
456 video.fullscreen_available = FULLSCREEN_STATUS;
457 video.fullscreen_enabled = FALSE;
458 // video.fullscreen_initial = FALSE;
460 video.fullscreen_mode_current = NULL;
461 video.fullscreen_modes = NULL;
464 video.window_scaling_available = WINDOW_SCALING_STATUS;
466 #if defined(TARGET_SDL)
467 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
469 X11InitVideoBuffer(&backbuffer, &window);
475 inline static void FreeBitmapPointers(Bitmap *bitmap)
480 #if defined(TARGET_SDL)
481 SDLFreeBitmapPointers(bitmap);
483 X11FreeBitmapPointers(bitmap);
486 checked_free(bitmap->source_filename);
487 bitmap->source_filename = NULL;
490 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
493 if (src_bitmap == NULL || dst_bitmap == NULL)
496 FreeBitmapPointers(dst_bitmap);
498 *dst_bitmap = *src_bitmap;
501 void FreeBitmap(Bitmap *bitmap)
506 FreeBitmapPointers(bitmap);
511 Bitmap *CreateBitmapStruct(void)
513 #if defined(TARGET_SDL)
514 return checked_calloc(sizeof(struct SDLSurfaceInfo));
516 return checked_calloc(sizeof(struct X11DrawableInfo));
520 Bitmap *CreateBitmap(int width, int height, int depth)
522 Bitmap *new_bitmap = CreateBitmapStruct();
523 int real_width = MAX(1, width); /* prevent zero bitmap width */
524 int real_height = MAX(1, height); /* prevent zero bitmap height */
525 int real_depth = GetRealDepth(depth);
527 #if defined(TARGET_SDL)
528 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
530 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
533 new_bitmap->width = real_width;
534 new_bitmap->height = real_height;
539 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
541 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
545 *bitmap = new_bitmap;
549 TransferBitmapPointers(new_bitmap, *bitmap);
554 void CloseWindow(DrawWindow *window)
556 #if defined(TARGET_X11)
557 X11CloseWindow(window);
561 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
564 if (draw_mask == REDRAW_NONE)
567 if (draw_mask & REDRAW_ALL)
570 if ((draw_mask & REDRAW_FIELD) &&
571 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
574 if ((draw_mask & REDRAW_DOOR_1) &&
575 x >= gfx.dx && y < gfx.dy + gfx.dysize)
578 if ((draw_mask & REDRAW_DOOR_2) &&
579 x >= gfx.dx && y >= gfx.vy)
585 boolean DrawingDeactivated(int x, int y, int width, int height)
587 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
590 boolean DrawingOnBackground(int x, int y)
592 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
593 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
596 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
597 int *width, int *height, boolean is_dest)
600 int clip_x, clip_y, clip_width, clip_height;
602 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
604 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
605 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
606 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
607 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
613 clip_width = bitmap->width;
614 clip_height = bitmap->height;
617 /* skip if rectangle completely outside bitmap */
619 if (*x + *width <= clip_x ||
620 *y + *height <= clip_y ||
621 *x >= clip_x + clip_width ||
622 *y >= clip_y + clip_height)
625 /* clip if rectangle overlaps bitmap */
629 *width -= clip_x - *x;
632 else if (*x + *width > clip_x + clip_width)
634 *width = clip_x + clip_width - *x;
639 *height -= clip_y - *y;
642 else if (*y + *height > clip_y + clip_height)
644 *height = clip_y + clip_height - *y;
651 /* skip if rectangle completely outside bitmap */
653 if (*x + *width <= 0 ||
655 *x >= bitmap->width ||
656 *y >= bitmap->height)
659 /* clip if rectangle overlaps bitmap */
666 else if (*x + *width > bitmap->width)
668 *width = bitmap->width - *x;
676 else if (*y + *height > bitmap->height)
678 *height = bitmap->height - *y;
685 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
686 int src_x, int src_y, int width, int height,
687 int dst_x, int dst_y)
689 int dst_x_unclipped = dst_x;
690 int dst_y_unclipped = dst_y;
692 if (DrawingDeactivated(dst_x, dst_y, width, height))
696 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
697 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
700 /* source x/y might need adjustment if destination x/y was clipped top/left */
701 src_x += dst_x - dst_x_unclipped;
702 src_y += dst_y - dst_y_unclipped;
705 /* skip if rectangle starts outside bitmap */
706 if (src_x >= src_bitmap->width ||
707 src_y >= src_bitmap->height ||
708 dst_x >= dst_bitmap->width ||
709 dst_y >= dst_bitmap->height)
712 /* clip if rectangle overlaps bitmap */
713 if (src_x + width > src_bitmap->width)
714 width = src_bitmap->width - src_x;
715 if (src_y + height > src_bitmap->height)
716 height = src_bitmap->height - src_y;
717 if (dst_x + width > dst_bitmap->width)
718 width = dst_bitmap->width - dst_x;
719 if (dst_y + height > dst_bitmap->height)
720 height = dst_bitmap->height - dst_y;
724 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
726 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
727 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
728 but is already fixed in SVN and should therefore finally be fixed with
729 the next official SDL release, which is probably version 1.2.14.) */
731 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
732 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
733 #if defined(TARGET_SDL2)
734 if (src_bitmap == dst_bitmap)
736 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
738 /* needed when blitting directly to same bitmap -- should not be needed with
739 recent SDL libraries, but apparently does not work in 1.2.11 directly */
741 static Bitmap *tmp_bitmap = NULL;
742 static int tmp_bitmap_xsize = 0;
743 static int tmp_bitmap_ysize = 0;
745 /* start with largest static bitmaps for initial bitmap size ... */
746 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
748 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
749 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
752 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
753 if (src_bitmap->width > tmp_bitmap_xsize ||
754 src_bitmap->height > tmp_bitmap_ysize)
756 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
757 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
759 FreeBitmap(tmp_bitmap);
764 if (tmp_bitmap == NULL)
765 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
768 sysCopyArea(src_bitmap, tmp_bitmap,
769 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
770 sysCopyArea(tmp_bitmap, dst_bitmap,
771 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
781 if (dst_x < gfx.sx + gfx.sxsize)
782 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
783 FrameCounter, dst_x, dst_y, width, height);
786 sysCopyArea(src_bitmap, dst_bitmap,
787 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
790 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
791 int src_x, int src_y, int src_width, int src_height,
792 int dst_x, int dst_y, int dst_width, int dst_height)
794 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
795 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
796 int dst_xsize = dst_width;
797 int dst_ysize = dst_height;
798 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
799 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
802 for (y = 0; y < src_ysteps; y++)
804 for (x = 0; x < src_xsteps; x++)
806 int draw_x = dst_x + x * src_xsize;
807 int draw_y = dst_y + y * src_ysize;
808 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
809 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
811 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
817 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
818 int fade_mode, int fade_delay, int post_delay,
819 void (*draw_border_function)(void))
822 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
823 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
827 #if defined(TARGET_SDL)
828 SDLFadeRectangle(bitmap_cross, x, y, width, height,
829 fade_mode, fade_delay, post_delay, draw_border_function);
831 X11FadeRectangle(bitmap_cross, x, y, width, height,
832 fade_mode, fade_delay, post_delay, draw_border_function);
836 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
839 if (DrawingDeactivated(x, y, width, height))
843 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
846 /* skip if rectangle starts outside bitmap */
847 if (x >= bitmap->width ||
851 /* clip if rectangle overlaps bitmap */
852 if (x + width > bitmap->width)
853 width = bitmap->width - x;
854 if (y + height > bitmap->height)
855 height = bitmap->height - y;
858 sysFillRectangle(bitmap, x, y, width, height, color);
861 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
863 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
866 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
867 int width, int height)
869 if (DrawingOnBackground(x, y))
870 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
872 ClearRectangle(bitmap, x, y, width, height);
875 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
877 #if defined(TARGET_X11)
880 bitmap->clip_gc = clip_gc;
881 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
886 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
888 #if defined(TARGET_X11)
891 bitmap->clip_gc = clip_gc;
892 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
897 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
898 int src_x, int src_y, int width, int height,
899 int dst_x, int dst_y)
901 if (DrawingDeactivated(dst_x, dst_y, width, height))
904 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
905 dst_x, dst_y, BLIT_MASKED);
908 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
909 int src_x, int src_y, int width, int height,
910 int dst_x, int dst_y)
912 if (DrawingOnBackground(dst_x, dst_y))
914 /* draw background */
915 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
918 /* draw foreground */
919 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
920 dst_x - src_x, dst_y - src_y);
921 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
925 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
929 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
932 #if defined(TARGET_SDL)
933 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
935 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
939 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
942 #if defined(TARGET_SDL)
943 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
945 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
949 #if !defined(TARGET_X11_NATIVE)
950 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
951 int to_x, int to_y, Pixel pixel, int line_width)
955 for (x = 0; x < line_width; x++)
957 for (y = 0; y < line_width; y++)
959 int dx = x - line_width / 2;
960 int dy = y - line_width / 2;
962 if ((x == 0 && y == 0) ||
963 (x == 0 && y == line_width - 1) ||
964 (x == line_width - 1 && y == 0) ||
965 (x == line_width - 1 && y == line_width - 1))
968 #if defined(TARGET_SDL)
970 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
971 #elif defined(TARGET_ALLEGRO)
972 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
973 to_x + dx, to_y + dy, pixel);
980 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
982 #if !defined(TARGET_X11_NATIVE)
986 for (i = 0; i < num_points - 1; i++)
987 DrawLine(bitmap, points[i].x, points[i].y,
988 points[i + 1].x, points[i + 1].y, pixel, line_width);
991 SDLDrawLines(bitmap->surface, points, num_points, pixel);
994 XSetForeground(display, bitmap->line_gc[1], pixel);
995 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
996 (XPoint *)points, num_points, CoordModeOrigin);
1000 Pixel GetPixel(Bitmap *bitmap, int x, int y)
1002 if (x < 0 || x >= bitmap->width ||
1003 y < 0 || y >= bitmap->height)
1006 #if defined(TARGET_SDL)
1007 return SDLGetPixel(bitmap, x, y);
1008 #elif defined(TARGET_ALLEGRO)
1009 return AllegroGetPixel(bitmap->drawable, x, y);
1011 return X11GetPixel(bitmap, x, y);
1015 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1016 unsigned int color_g, unsigned int color_b)
1018 #if defined(TARGET_SDL)
1019 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1020 #elif defined(TARGET_ALLEGRO)
1021 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1023 return X11GetPixelFromRGB(color_r, color_g, color_b);
1027 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1029 unsigned int color_r = (color >> 16) & 0xff;
1030 unsigned int color_g = (color >> 8) & 0xff;
1031 unsigned int color_b = (color >> 0) & 0xff;
1033 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1036 /* execute all pending screen drawing operations */
1037 void FlushDisplay(void)
1039 #if !defined(TARGET_SDL)
1044 /* execute and wait for all pending screen drawing operations */
1045 void SyncDisplay(void)
1047 #if !defined(TARGET_SDL)
1048 XSync(display, FALSE);
1052 void KeyboardAutoRepeatOn(void)
1054 #if defined(TARGET_SDL)
1055 #if defined(TARGET_SDL2)
1056 keyrepeat_status = TRUE;
1058 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1059 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1060 SDL_EnableUNICODE(1);
1064 XAutoRepeatOn(display);
1068 void KeyboardAutoRepeatOff(void)
1070 #if defined(TARGET_SDL)
1071 #if defined(TARGET_SDL2)
1072 keyrepeat_status = FALSE;
1074 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1075 SDL_EnableUNICODE(0);
1079 XAutoRepeatOff(display);
1083 boolean PointerInWindow(DrawWindow *window)
1085 #if defined(TARGET_SDL)
1093 /* if XQueryPointer() returns False, the pointer
1094 is not on the same screen as the specified window */
1095 return XQueryPointer(display, window->drawable, &root, &child,
1096 &root_x, &root_y, &win_x, &win_y, &mask);
1100 boolean SetVideoMode(boolean fullscreen)
1102 #if defined(TARGET_SDL)
1103 return SDLSetVideoMode(&backbuffer, fullscreen);
1105 boolean success = TRUE;
1107 if (fullscreen && video.fullscreen_available)
1109 Error(ERR_WARN, "fullscreen not available in X11 version");
1111 /* display error message only once */
1112 video.fullscreen_available = FALSE;
1121 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1123 #if defined(TARGET_SDL)
1124 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1125 (!fullscreen && video.fullscreen_enabled))
1126 fullscreen = SetVideoMode(fullscreen);
1132 Bitmap *LoadImage(char *filename)
1136 #if defined(TARGET_SDL)
1137 new_bitmap = SDLLoadImage(filename);
1139 new_bitmap = X11LoadImage(filename);
1143 new_bitmap->source_filename = getStringCopy(filename);
1148 Bitmap *LoadCustomImage(char *basename)
1150 char *filename = getCustomImageFilename(basename);
1153 if (filename == NULL)
1154 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1156 if ((new_bitmap = LoadImage(filename)) == NULL)
1157 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1162 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1164 char *filename = getCustomImageFilename(basename);
1167 if (filename == NULL) /* (should never happen) */
1169 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1173 if (strEqual(filename, bitmap->source_filename))
1175 /* The old and new image are the same (have the same filename and path).
1176 This usually means that this image does not exist in this graphic set
1177 and a fallback to the existing image is done. */
1182 if ((new_bitmap = LoadImage(filename)) == NULL)
1184 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1188 if (bitmap->width != new_bitmap->width ||
1189 bitmap->height != new_bitmap->height)
1191 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1193 FreeBitmap(new_bitmap);
1197 TransferBitmapPointers(new_bitmap, bitmap);
1201 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1203 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1205 #if defined(TARGET_SDL)
1206 SDLZoomBitmap(src_bitmap, dst_bitmap);
1208 X11ZoomBitmap(src_bitmap, dst_bitmap);
1214 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1215 boolean create_small_bitmaps)
1219 Bitmap *tmp_bitmap_1;
1220 Bitmap *tmp_bitmap_2;
1221 Bitmap *tmp_bitmap_4;
1222 Bitmap *tmp_bitmap_8;
1223 Bitmap *tmp_bitmap_16;
1224 Bitmap *tmp_bitmap_32;
1225 int width_1, height_1;
1226 int width_2, height_2;
1227 int width_4, height_4;
1228 int width_8, height_8;
1229 int width_16, height_16;
1231 int width_32, height_32;
1233 int new_width, new_height;
1235 /* calculate new image dimensions for normal sized image */
1236 width_1 = old_bitmap->width * zoom_factor;
1237 height_1 = old_bitmap->height * zoom_factor;
1239 /* get image with normal size (this might require scaling up) */
1240 if (zoom_factor != 1)
1241 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1243 tmp_bitmap_1 = old_bitmap;
1245 /* this is only needed to make compilers happy */
1246 tmp_bitmap_2 = NULL;
1247 tmp_bitmap_4 = NULL;
1248 tmp_bitmap_8 = NULL;
1249 tmp_bitmap_16 = NULL;
1250 tmp_bitmap_32 = NULL;
1252 if (create_small_bitmaps)
1254 /* calculate new image dimensions for small images */
1255 width_2 = width_1 / 2;
1256 height_2 = height_1 / 2;
1257 width_4 = width_1 / 4;
1258 height_4 = height_1 / 4;
1259 width_8 = width_1 / 8;
1260 height_8 = height_1 / 8;
1261 width_16 = width_1 / 16;
1262 height_16 = height_1 / 16;
1264 width_32 = width_1 / 32;
1265 height_32 = height_1 / 32;
1268 UPDATE_BUSY_STATE();
1270 /* get image with 1/2 of normal size (for use in the level editor) */
1271 if (zoom_factor != 2)
1272 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1274 tmp_bitmap_2 = old_bitmap;
1276 UPDATE_BUSY_STATE();
1278 /* get image with 1/4 of normal size (for use in the level editor) */
1279 if (zoom_factor != 4)
1280 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1282 tmp_bitmap_4 = old_bitmap;
1284 UPDATE_BUSY_STATE();
1286 /* get image with 1/8 of normal size (for use on the preview screen) */
1287 if (zoom_factor != 8)
1288 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1290 tmp_bitmap_8 = old_bitmap;
1292 UPDATE_BUSY_STATE();
1294 /* get image with 1/16 of normal size (for use on the preview screen) */
1295 if (zoom_factor != 16)
1296 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1298 tmp_bitmap_16 = old_bitmap;
1300 UPDATE_BUSY_STATE();
1302 /* get image with 1/32 of normal size (for use on the preview screen) */
1303 if (zoom_factor != 32)
1304 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1306 tmp_bitmap_32 = old_bitmap;
1308 UPDATE_BUSY_STATE();
1312 /* if image was scaled up, create new clipmask for normal size image */
1313 if (zoom_factor != 1)
1315 #if defined(TARGET_X11)
1316 if (old_bitmap->clip_mask)
1317 XFreePixmap(display, old_bitmap->clip_mask);
1319 old_bitmap->clip_mask =
1320 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1322 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1324 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1326 if (old_bitmap->surface_masked)
1327 SDL_FreeSurface(old_bitmap->surface_masked);
1329 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1330 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1331 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1332 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1333 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1338 if (create_small_bitmaps)
1340 new_width = width_1;
1341 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1343 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1345 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1346 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1348 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1349 width_1 / 2, height_1);
1350 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1351 3 * width_1 / 4, height_1);
1352 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1353 7 * width_1 / 8, height_1);
1354 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1355 15 * width_1 / 16, height_1);
1357 UPDATE_BUSY_STATE();
1361 new_width = width_1;
1362 new_height = height_1;
1364 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1367 if (create_small_bitmaps)
1369 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1370 if (zoom_factor != 1)
1371 FreeBitmap(tmp_bitmap_1);
1373 if (zoom_factor != 2)
1374 FreeBitmap(tmp_bitmap_2);
1376 if (zoom_factor != 4)
1377 FreeBitmap(tmp_bitmap_4);
1379 if (zoom_factor != 8)
1380 FreeBitmap(tmp_bitmap_8);
1382 if (zoom_factor != 16)
1383 FreeBitmap(tmp_bitmap_16);
1385 if (zoom_factor != 32)
1386 FreeBitmap(tmp_bitmap_32);
1389 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1390 #if defined(TARGET_SDL)
1391 swap_bitmap.surface = old_bitmap->surface;
1392 old_bitmap->surface = new_bitmap->surface;
1393 new_bitmap->surface = swap_bitmap.surface;
1395 swap_bitmap.drawable = old_bitmap->drawable;
1396 old_bitmap->drawable = new_bitmap->drawable;
1397 new_bitmap->drawable = swap_bitmap.drawable;
1400 old_bitmap->width = new_bitmap->width;
1401 old_bitmap->height = new_bitmap->height;
1404 /* this replaces all blit masks created when loading -- maybe optimize this */
1406 #if defined(TARGET_X11)
1407 if (old_bitmap->clip_mask)
1408 XFreePixmap(display, old_bitmap->clip_mask);
1410 old_bitmap->clip_mask =
1411 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1413 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1415 SDL_Surface *old_surface = old_bitmap->surface;
1417 if (old_bitmap->surface_masked)
1418 SDL_FreeSurface(old_bitmap->surface_masked);
1420 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1421 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1422 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1423 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1424 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1429 UPDATE_BUSY_STATE();
1431 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1434 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1436 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1439 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1441 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1445 /* ------------------------------------------------------------------------- */
1446 /* mouse pointer functions */
1447 /* ------------------------------------------------------------------------- */
1449 #if !defined(PLATFORM_MSDOS)
1450 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1451 /* XPM image definitions */
1452 static const char *cursor_image_none[] =
1454 /* width height num_colors chars_per_pixel */
1483 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1484 static const char *cursor_image_dot[] =
1486 /* width height num_colors chars_per_pixel */
1515 static const char **cursor_image_playfield = cursor_image_dot;
1517 /* some people complained about a "white dot" on the screen and thought it
1518 was a graphical error... OK, let's just remove the whole pointer :-) */
1519 static const char **cursor_image_playfield = cursor_image_none;
1522 #if defined(TARGET_SDL)
1523 static const int cursor_bit_order = BIT_ORDER_MSB;
1524 #elif defined(TARGET_X11_NATIVE)
1525 static const int cursor_bit_order = BIT_ORDER_LSB;
1528 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1530 struct MouseCursorInfo *cursor;
1531 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1532 int header_lines = 4;
1535 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1537 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1540 for (y = 0; y < cursor->width; y++)
1542 for (x = 0; x < cursor->height; x++)
1545 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1550 cursor->data[i] = cursor->mask[i] = 0;
1553 switch (image[header_lines + y][x])
1556 cursor->data[i] |= bit_mask;
1557 cursor->mask[i] |= bit_mask;
1561 cursor->mask[i] |= bit_mask;
1570 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1574 #endif /* !PLATFORM_MSDOS */
1576 void SetMouseCursor(int mode)
1578 #if !defined(PLATFORM_MSDOS)
1579 static struct MouseCursorInfo *cursor_none = NULL;
1580 static struct MouseCursorInfo *cursor_playfield = NULL;
1581 struct MouseCursorInfo *cursor_new;
1583 if (cursor_none == NULL)
1584 cursor_none = get_cursor_from_image(cursor_image_none);
1586 if (cursor_playfield == NULL)
1587 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1589 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1590 mode == CURSOR_NONE ? cursor_none :
1591 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1593 #if defined(TARGET_SDL)
1594 SDLSetMouseCursor(cursor_new);
1595 #elif defined(TARGET_X11_NATIVE)
1596 X11SetMouseCursor(cursor_new);
1602 /* ========================================================================= */
1603 /* audio functions */
1604 /* ========================================================================= */
1606 void OpenAudio(void)
1608 /* always start with reliable default values */
1609 audio.sound_available = FALSE;
1610 audio.music_available = FALSE;
1611 audio.loops_available = FALSE;
1613 audio.sound_enabled = FALSE;
1614 audio.sound_deactivated = FALSE;
1616 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1617 audio.mixer_pid = 0;
1618 audio.device_name = NULL;
1619 audio.device_fd = -1;
1621 audio.num_channels = 0;
1622 audio.music_channel = 0;
1623 audio.first_sound_channel = 0;
1625 #if defined(TARGET_SDL)
1627 #elif defined(PLATFORM_UNIX)
1629 #elif defined(PLATFORM_MSDOS)
1634 void CloseAudio(void)
1636 #if defined(TARGET_SDL)
1638 #elif defined(PLATFORM_UNIX)
1640 #elif defined(PLATFORM_MSDOS)
1644 audio.sound_enabled = FALSE;
1647 void SetAudioMode(boolean enabled)
1649 if (!audio.sound_available)
1652 audio.sound_enabled = enabled;
1656 /* ========================================================================= */
1657 /* event functions */
1658 /* ========================================================================= */
1660 void InitEventFilter(EventFilter filter_function)
1662 /* set event filter to filter out certain events */
1663 #if defined(TARGET_SDL)
1664 #if defined(TARGET_SDL2)
1665 SDL_SetEventFilter(filter_function, NULL);
1667 SDL_SetEventFilter(filter_function);
1672 boolean PendingEvent(void)
1674 #if defined(TARGET_SDL)
1675 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1677 return (XPending(display) ? TRUE : FALSE);
1681 void NextEvent(Event *event)
1683 #if defined(TARGET_SDL)
1684 SDLNextEvent(event);
1686 XNextEvent(display, event);
1690 void PeekEvent(Event *event)
1692 #if defined(TARGET_SDL)
1693 #if defined(TARGET_SDL2)
1694 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1696 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1699 XPeekEvent(display, event);
1703 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1705 #if defined(TARGET_SDL)
1706 #if defined(TARGET_SDL2)
1707 /* key up/down events in SDL2 do not return text characters anymore */
1708 return event->keysym.sym;
1712 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1713 (int)event->keysym.unicode,
1714 (int)event->keysym.sym,
1715 (int)SDL_GetModState());
1718 if (with_modifiers &&
1719 event->keysym.unicode > 0x0000 &&
1720 event->keysym.unicode < 0x2000)
1721 return event->keysym.unicode;
1723 return event->keysym.sym;
1729 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1730 (int)XLookupKeysym(event, event->state),
1731 (int)XLookupKeysym(event, 0));
1735 return XLookupKeysym(event, event->state);
1737 return XLookupKeysym(event, 0);
1741 KeyMod HandleKeyModState(Key key, int key_status)
1743 static KeyMod current_modifiers = KMOD_None;
1745 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1747 KeyMod new_modifier = KMOD_None;
1752 new_modifier = KMOD_Shift_L;
1755 new_modifier = KMOD_Shift_R;
1757 case KSYM_Control_L:
1758 new_modifier = KMOD_Control_L;
1760 case KSYM_Control_R:
1761 new_modifier = KMOD_Control_R;
1764 new_modifier = KMOD_Meta_L;
1767 new_modifier = KMOD_Meta_R;
1770 new_modifier = KMOD_Alt_L;
1773 new_modifier = KMOD_Alt_R;
1779 if (key_status == KEY_PRESSED)
1780 current_modifiers |= new_modifier;
1782 current_modifiers &= ~new_modifier;
1785 return current_modifiers;
1788 KeyMod GetKeyModState()
1790 #if defined(TARGET_SDL)
1791 return (KeyMod)SDL_GetModState();
1793 return HandleKeyModState(KSYM_UNDEFINED, 0);
1797 KeyMod GetKeyModStateFromEvents()
1799 /* always use key modifier state as tracked from key events (this is needed
1800 if the modifier key event was injected into the event queue, but the key
1801 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1802 query the keys as held pressed on the keyboard) -- this case is currently
1803 only used to filter out clipboard insert events from "True X-Mouse" tool */
1805 return HandleKeyModState(KSYM_UNDEFINED, 0);
1808 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1810 if (event->type != EVENT_CLIENTMESSAGE)
1813 #if defined(TARGET_SDL)
1814 return TRUE; /* the only possible message here is SDL_QUIT */
1815 #elif defined(PLATFORM_UNIX)
1816 if ((event->window == window->drawable) &&
1817 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1825 /* ========================================================================= */
1826 /* joystick functions */
1827 /* ========================================================================= */
1829 void InitJoysticks()
1833 #if defined(NO_JOYSTICK)
1834 return; /* joysticks generally deactivated by compile-time directive */
1837 /* always start with reliable default values */
1838 joystick.status = JOYSTICK_NOT_AVAILABLE;
1839 for (i = 0; i < MAX_PLAYERS; i++)
1840 joystick.fd[i] = -1; /* joystick device closed */
1842 #if defined(TARGET_SDL)
1844 #elif defined(PLATFORM_UNIX)
1845 UnixInitJoysticks();
1846 #elif defined(PLATFORM_MSDOS)
1847 MSDOSInitJoysticks();
1851 for (i = 0; i < MAX_PLAYERS; i++)
1852 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1856 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1858 #if defined(TARGET_SDL)
1859 return SDLReadJoystick(nr, x, y, b1, b2);
1860 #elif defined(PLATFORM_UNIX)
1861 return UnixReadJoystick(nr, x, y, b1, b2);
1862 #elif defined(PLATFORM_MSDOS)
1863 return MSDOSReadJoystick(nr, x, y, b1, b2);