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 (DrawingDeactivated(dst_x, dst_y, width, height))
692 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
693 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
696 /* source x/y might need adjustment if destination x/y was clipped top/left */
697 src_x += dst_x - dst_x_unclipped;
698 src_y += dst_y - dst_y_unclipped;
701 /* skip if rectangle starts outside bitmap */
702 if (src_x >= src_bitmap->width ||
703 src_y >= src_bitmap->height ||
704 dst_x >= dst_bitmap->width ||
705 dst_y >= dst_bitmap->height)
708 /* clip if rectangle overlaps bitmap */
709 if (src_x + width > src_bitmap->width)
710 width = src_bitmap->width - src_x;
711 if (src_y + height > src_bitmap->height)
712 height = src_bitmap->height - src_y;
713 if (dst_x + width > dst_bitmap->width)
714 width = dst_bitmap->width - dst_x;
715 if (dst_y + height > dst_bitmap->height)
716 height = dst_bitmap->height - dst_y;
720 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
722 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
723 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
724 but is already fixed in SVN and should therefore finally be fixed with
725 the next official SDL release, which is probably version 1.2.14.) */
727 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
728 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
729 #if defined(TARGET_SDL2)
730 if (src_bitmap == dst_bitmap)
732 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
734 /* needed when blitting directly to same bitmap -- should not be needed with
735 recent SDL libraries, but apparently does not work in 1.2.11 directly */
737 static Bitmap *tmp_bitmap = NULL;
738 static int tmp_bitmap_xsize = 0;
739 static int tmp_bitmap_ysize = 0;
741 /* start with largest static bitmaps for initial bitmap size ... */
742 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
744 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
745 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
748 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
749 if (src_bitmap->width > tmp_bitmap_xsize ||
750 src_bitmap->height > tmp_bitmap_ysize)
752 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
753 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
755 FreeBitmap(tmp_bitmap);
760 if (tmp_bitmap == NULL)
761 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
764 sysCopyArea(src_bitmap, tmp_bitmap,
765 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
766 sysCopyArea(tmp_bitmap, dst_bitmap,
767 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
777 if (dst_x < gfx.sx + gfx.sxsize)
778 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
779 FrameCounter, dst_x, dst_y, width, height);
782 sysCopyArea(src_bitmap, dst_bitmap,
783 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
786 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
787 int src_x, int src_y, int src_width, int src_height,
788 int dst_x, int dst_y, int dst_width, int dst_height)
790 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
791 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
792 int dst_xsize = dst_width;
793 int dst_ysize = dst_height;
794 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
795 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
798 for (y = 0; y < src_ysteps; y++)
800 for (x = 0; x < src_xsteps; x++)
802 int draw_x = dst_x + x * src_xsize;
803 int draw_y = dst_y + y * src_ysize;
804 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
805 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
807 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
813 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
814 int fade_mode, int fade_delay, int post_delay,
815 void (*draw_border_function)(void))
818 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
819 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
823 #if defined(TARGET_SDL)
824 SDLFadeRectangle(bitmap_cross, x, y, width, height,
825 fade_mode, fade_delay, post_delay, draw_border_function);
827 X11FadeRectangle(bitmap_cross, x, y, width, height,
828 fade_mode, fade_delay, post_delay, draw_border_function);
832 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
835 if (DrawingDeactivated(x, y, width, height))
839 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
842 /* skip if rectangle starts outside bitmap */
843 if (x >= bitmap->width ||
847 /* clip if rectangle overlaps bitmap */
848 if (x + width > bitmap->width)
849 width = bitmap->width - x;
850 if (y + height > bitmap->height)
851 height = bitmap->height - y;
854 sysFillRectangle(bitmap, x, y, width, height, color);
857 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
859 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
862 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
863 int width, int height)
865 if (DrawingOnBackground(x, y))
866 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
868 ClearRectangle(bitmap, x, y, width, height);
871 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
873 #if defined(TARGET_X11)
876 bitmap->clip_gc = clip_gc;
877 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
882 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
884 #if defined(TARGET_X11)
887 bitmap->clip_gc = clip_gc;
888 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
893 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
894 int src_x, int src_y, int width, int height,
895 int dst_x, int dst_y)
897 if (DrawingDeactivated(dst_x, dst_y, width, height))
900 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
901 dst_x, dst_y, BLIT_MASKED);
904 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
905 int src_x, int src_y, int width, int height,
906 int dst_x, int dst_y)
908 if (DrawingOnBackground(dst_x, dst_y))
910 /* draw background */
911 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
914 /* draw foreground */
915 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
916 dst_x - src_x, dst_y - src_y);
917 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
921 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
925 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
928 #if defined(TARGET_SDL)
929 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
931 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
935 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
938 #if defined(TARGET_SDL)
939 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
941 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
945 #if !defined(TARGET_X11_NATIVE)
946 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
947 int to_x, int to_y, Pixel pixel, int line_width)
951 for (x = 0; x < line_width; x++)
953 for (y = 0; y < line_width; y++)
955 int dx = x - line_width / 2;
956 int dy = y - line_width / 2;
958 if ((x == 0 && y == 0) ||
959 (x == 0 && y == line_width - 1) ||
960 (x == line_width - 1 && y == 0) ||
961 (x == line_width - 1 && y == line_width - 1))
964 #if defined(TARGET_SDL)
966 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
967 #elif defined(TARGET_ALLEGRO)
968 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
969 to_x + dx, to_y + dy, pixel);
976 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
978 #if !defined(TARGET_X11_NATIVE)
982 for (i = 0; i < num_points - 1; i++)
983 DrawLine(bitmap, points[i].x, points[i].y,
984 points[i + 1].x, points[i + 1].y, pixel, line_width);
987 SDLDrawLines(bitmap->surface, points, num_points, pixel);
990 XSetForeground(display, bitmap->line_gc[1], pixel);
991 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
992 (XPoint *)points, num_points, CoordModeOrigin);
996 Pixel GetPixel(Bitmap *bitmap, int x, int y)
998 if (x < 0 || x >= bitmap->width ||
999 y < 0 || y >= bitmap->height)
1002 #if defined(TARGET_SDL)
1003 return SDLGetPixel(bitmap, x, y);
1004 #elif defined(TARGET_ALLEGRO)
1005 return AllegroGetPixel(bitmap->drawable, x, y);
1007 return X11GetPixel(bitmap, x, y);
1011 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1012 unsigned int color_g, unsigned int color_b)
1014 #if defined(TARGET_SDL)
1015 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1016 #elif defined(TARGET_ALLEGRO)
1017 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1019 return X11GetPixelFromRGB(color_r, color_g, color_b);
1023 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1025 unsigned int color_r = (color >> 16) & 0xff;
1026 unsigned int color_g = (color >> 8) & 0xff;
1027 unsigned int color_b = (color >> 0) & 0xff;
1029 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1032 /* execute all pending screen drawing operations */
1033 void FlushDisplay(void)
1035 #if !defined(TARGET_SDL)
1040 /* execute and wait for all pending screen drawing operations */
1041 void SyncDisplay(void)
1043 #if !defined(TARGET_SDL)
1044 XSync(display, FALSE);
1048 void KeyboardAutoRepeatOn(void)
1050 #if defined(TARGET_SDL)
1051 #if defined(TARGET_SDL2)
1052 keyrepeat_status = TRUE;
1054 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1055 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1056 SDL_EnableUNICODE(1);
1060 XAutoRepeatOn(display);
1064 void KeyboardAutoRepeatOff(void)
1066 #if defined(TARGET_SDL)
1067 #if defined(TARGET_SDL2)
1068 keyrepeat_status = FALSE;
1070 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1071 SDL_EnableUNICODE(0);
1075 XAutoRepeatOff(display);
1079 boolean PointerInWindow(DrawWindow *window)
1081 #if defined(TARGET_SDL)
1089 /* if XQueryPointer() returns False, the pointer
1090 is not on the same screen as the specified window */
1091 return XQueryPointer(display, window->drawable, &root, &child,
1092 &root_x, &root_y, &win_x, &win_y, &mask);
1096 boolean SetVideoMode(boolean fullscreen)
1098 #if defined(TARGET_SDL)
1099 return SDLSetVideoMode(&backbuffer, fullscreen);
1101 boolean success = TRUE;
1103 if (fullscreen && video.fullscreen_available)
1105 Error(ERR_WARN, "fullscreen not available in X11 version");
1107 /* display error message only once */
1108 video.fullscreen_available = FALSE;
1117 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1119 #if defined(TARGET_SDL)
1120 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1121 (!fullscreen && video.fullscreen_enabled))
1122 fullscreen = SetVideoMode(fullscreen);
1128 Bitmap *LoadImage(char *filename)
1132 #if defined(TARGET_SDL)
1133 new_bitmap = SDLLoadImage(filename);
1135 new_bitmap = X11LoadImage(filename);
1139 new_bitmap->source_filename = getStringCopy(filename);
1144 Bitmap *LoadCustomImage(char *basename)
1146 char *filename = getCustomImageFilename(basename);
1149 if (filename == NULL)
1150 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1152 if ((new_bitmap = LoadImage(filename)) == NULL)
1153 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1158 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1160 char *filename = getCustomImageFilename(basename);
1163 if (filename == NULL) /* (should never happen) */
1165 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1169 if (strEqual(filename, bitmap->source_filename))
1171 /* The old and new image are the same (have the same filename and path).
1172 This usually means that this image does not exist in this graphic set
1173 and a fallback to the existing image is done. */
1178 if ((new_bitmap = LoadImage(filename)) == NULL)
1180 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1184 if (bitmap->width != new_bitmap->width ||
1185 bitmap->height != new_bitmap->height)
1187 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1189 FreeBitmap(new_bitmap);
1193 TransferBitmapPointers(new_bitmap, bitmap);
1197 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1199 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1201 #if defined(TARGET_SDL)
1202 SDLZoomBitmap(src_bitmap, dst_bitmap);
1204 X11ZoomBitmap(src_bitmap, dst_bitmap);
1210 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1211 boolean create_small_bitmaps)
1215 Bitmap *tmp_bitmap_1;
1216 Bitmap *tmp_bitmap_2;
1217 Bitmap *tmp_bitmap_4;
1218 Bitmap *tmp_bitmap_8;
1219 Bitmap *tmp_bitmap_16;
1220 Bitmap *tmp_bitmap_32;
1221 int width_1, height_1;
1222 int width_2, height_2;
1223 int width_4, height_4;
1224 int width_8, height_8;
1225 int width_16, height_16;
1227 int width_32, height_32;
1229 int new_width, new_height;
1231 /* calculate new image dimensions for normal sized image */
1232 width_1 = old_bitmap->width * zoom_factor;
1233 height_1 = old_bitmap->height * zoom_factor;
1235 /* get image with normal size (this might require scaling up) */
1236 if (zoom_factor != 1)
1237 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1239 tmp_bitmap_1 = old_bitmap;
1241 /* this is only needed to make compilers happy */
1242 tmp_bitmap_2 = NULL;
1243 tmp_bitmap_4 = NULL;
1244 tmp_bitmap_8 = NULL;
1245 tmp_bitmap_16 = NULL;
1246 tmp_bitmap_32 = NULL;
1248 if (create_small_bitmaps)
1250 /* calculate new image dimensions for small images */
1251 width_2 = width_1 / 2;
1252 height_2 = height_1 / 2;
1253 width_4 = width_1 / 4;
1254 height_4 = height_1 / 4;
1255 width_8 = width_1 / 8;
1256 height_8 = height_1 / 8;
1257 width_16 = width_1 / 16;
1258 height_16 = height_1 / 16;
1260 width_32 = width_1 / 32;
1261 height_32 = height_1 / 32;
1264 UPDATE_BUSY_STATE();
1266 /* get image with 1/2 of normal size (for use in the level editor) */
1267 if (zoom_factor != 2)
1268 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1270 tmp_bitmap_2 = old_bitmap;
1272 UPDATE_BUSY_STATE();
1274 /* get image with 1/4 of normal size (for use in the level editor) */
1275 if (zoom_factor != 4)
1276 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1278 tmp_bitmap_4 = old_bitmap;
1280 UPDATE_BUSY_STATE();
1282 /* get image with 1/8 of normal size (for use on the preview screen) */
1283 if (zoom_factor != 8)
1284 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1286 tmp_bitmap_8 = old_bitmap;
1288 UPDATE_BUSY_STATE();
1290 /* get image with 1/16 of normal size (for use on the preview screen) */
1291 if (zoom_factor != 16)
1292 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1294 tmp_bitmap_16 = old_bitmap;
1296 UPDATE_BUSY_STATE();
1298 /* get image with 1/32 of normal size (for use on the preview screen) */
1299 if (zoom_factor != 32)
1300 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1302 tmp_bitmap_32 = old_bitmap;
1304 UPDATE_BUSY_STATE();
1308 /* if image was scaled up, create new clipmask for normal size image */
1309 if (zoom_factor != 1)
1311 #if defined(TARGET_X11)
1312 if (old_bitmap->clip_mask)
1313 XFreePixmap(display, old_bitmap->clip_mask);
1315 old_bitmap->clip_mask =
1316 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1318 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1320 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1322 if (old_bitmap->surface_masked)
1323 SDL_FreeSurface(old_bitmap->surface_masked);
1325 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1326 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1327 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1328 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1329 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1334 if (create_small_bitmaps)
1336 new_width = width_1;
1337 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1339 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1341 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1342 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1344 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1345 width_1 / 2, height_1);
1346 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1347 3 * width_1 / 4, height_1);
1348 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1349 7 * width_1 / 8, height_1);
1350 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1351 15 * width_1 / 16, height_1);
1353 UPDATE_BUSY_STATE();
1357 new_width = width_1;
1358 new_height = height_1;
1360 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1363 if (create_small_bitmaps)
1365 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1366 if (zoom_factor != 1)
1367 FreeBitmap(tmp_bitmap_1);
1369 if (zoom_factor != 2)
1370 FreeBitmap(tmp_bitmap_2);
1372 if (zoom_factor != 4)
1373 FreeBitmap(tmp_bitmap_4);
1375 if (zoom_factor != 8)
1376 FreeBitmap(tmp_bitmap_8);
1378 if (zoom_factor != 16)
1379 FreeBitmap(tmp_bitmap_16);
1381 if (zoom_factor != 32)
1382 FreeBitmap(tmp_bitmap_32);
1385 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1386 #if defined(TARGET_SDL)
1387 swap_bitmap.surface = old_bitmap->surface;
1388 old_bitmap->surface = new_bitmap->surface;
1389 new_bitmap->surface = swap_bitmap.surface;
1391 swap_bitmap.drawable = old_bitmap->drawable;
1392 old_bitmap->drawable = new_bitmap->drawable;
1393 new_bitmap->drawable = swap_bitmap.drawable;
1396 old_bitmap->width = new_bitmap->width;
1397 old_bitmap->height = new_bitmap->height;
1400 /* this replaces all blit masks created when loading -- maybe optimize this */
1402 #if defined(TARGET_X11)
1403 if (old_bitmap->clip_mask)
1404 XFreePixmap(display, old_bitmap->clip_mask);
1406 old_bitmap->clip_mask =
1407 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1409 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1411 SDL_Surface *old_surface = old_bitmap->surface;
1413 if (old_bitmap->surface_masked)
1414 SDL_FreeSurface(old_bitmap->surface_masked);
1416 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1417 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1418 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1419 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1420 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1425 UPDATE_BUSY_STATE();
1427 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1430 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1432 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1435 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1437 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1441 /* ------------------------------------------------------------------------- */
1442 /* mouse pointer functions */
1443 /* ------------------------------------------------------------------------- */
1445 #if !defined(PLATFORM_MSDOS)
1446 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1447 /* XPM image definitions */
1448 static const char *cursor_image_none[] =
1450 /* width height num_colors chars_per_pixel */
1479 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1480 static const char *cursor_image_dot[] =
1482 /* width height num_colors chars_per_pixel */
1511 static const char **cursor_image_playfield = cursor_image_dot;
1513 /* some people complained about a "white dot" on the screen and thought it
1514 was a graphical error... OK, let's just remove the whole pointer :-) */
1515 static const char **cursor_image_playfield = cursor_image_none;
1518 #if defined(TARGET_SDL)
1519 static const int cursor_bit_order = BIT_ORDER_MSB;
1520 #elif defined(TARGET_X11_NATIVE)
1521 static const int cursor_bit_order = BIT_ORDER_LSB;
1524 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1526 struct MouseCursorInfo *cursor;
1527 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1528 int header_lines = 4;
1531 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1533 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1536 for (y = 0; y < cursor->width; y++)
1538 for (x = 0; x < cursor->height; x++)
1541 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1546 cursor->data[i] = cursor->mask[i] = 0;
1549 switch (image[header_lines + y][x])
1552 cursor->data[i] |= bit_mask;
1553 cursor->mask[i] |= bit_mask;
1557 cursor->mask[i] |= bit_mask;
1566 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1570 #endif /* !PLATFORM_MSDOS */
1572 void SetMouseCursor(int mode)
1574 #if !defined(PLATFORM_MSDOS)
1575 static struct MouseCursorInfo *cursor_none = NULL;
1576 static struct MouseCursorInfo *cursor_playfield = NULL;
1577 struct MouseCursorInfo *cursor_new;
1579 if (cursor_none == NULL)
1580 cursor_none = get_cursor_from_image(cursor_image_none);
1582 if (cursor_playfield == NULL)
1583 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1585 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1586 mode == CURSOR_NONE ? cursor_none :
1587 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1589 #if defined(TARGET_SDL)
1590 SDLSetMouseCursor(cursor_new);
1591 #elif defined(TARGET_X11_NATIVE)
1592 X11SetMouseCursor(cursor_new);
1598 /* ========================================================================= */
1599 /* audio functions */
1600 /* ========================================================================= */
1602 void OpenAudio(void)
1604 /* always start with reliable default values */
1605 audio.sound_available = FALSE;
1606 audio.music_available = FALSE;
1607 audio.loops_available = FALSE;
1609 audio.sound_enabled = FALSE;
1610 audio.sound_deactivated = FALSE;
1612 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1613 audio.mixer_pid = 0;
1614 audio.device_name = NULL;
1615 audio.device_fd = -1;
1617 audio.num_channels = 0;
1618 audio.music_channel = 0;
1619 audio.first_sound_channel = 0;
1621 #if defined(TARGET_SDL)
1623 #elif defined(PLATFORM_UNIX)
1625 #elif defined(PLATFORM_MSDOS)
1630 void CloseAudio(void)
1632 #if defined(TARGET_SDL)
1634 #elif defined(PLATFORM_UNIX)
1636 #elif defined(PLATFORM_MSDOS)
1640 audio.sound_enabled = FALSE;
1643 void SetAudioMode(boolean enabled)
1645 if (!audio.sound_available)
1648 audio.sound_enabled = enabled;
1652 /* ========================================================================= */
1653 /* event functions */
1654 /* ========================================================================= */
1656 void InitEventFilter(EventFilter filter_function)
1658 /* set event filter to filter out certain events */
1659 #if defined(TARGET_SDL)
1660 #if defined(TARGET_SDL2)
1661 SDL_SetEventFilter(filter_function, NULL);
1663 SDL_SetEventFilter(filter_function);
1668 boolean PendingEvent(void)
1670 #if defined(TARGET_SDL)
1671 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1673 return (XPending(display) ? TRUE : FALSE);
1677 void NextEvent(Event *event)
1679 #if defined(TARGET_SDL)
1680 SDLNextEvent(event);
1682 XNextEvent(display, event);
1686 void PeekEvent(Event *event)
1688 #if defined(TARGET_SDL)
1689 #if defined(TARGET_SDL2)
1690 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1692 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1695 XPeekEvent(display, event);
1699 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1701 #if defined(TARGET_SDL)
1702 #if defined(TARGET_SDL2)
1703 /* key up/down events in SDL2 do not return text characters anymore */
1704 return event->keysym.sym;
1708 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1709 (int)event->keysym.unicode,
1710 (int)event->keysym.sym,
1711 (int)SDL_GetModState());
1714 if (with_modifiers &&
1715 event->keysym.unicode > 0x0000 &&
1716 event->keysym.unicode < 0x2000)
1717 return event->keysym.unicode;
1719 return event->keysym.sym;
1725 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1726 (int)XLookupKeysym(event, event->state),
1727 (int)XLookupKeysym(event, 0));
1731 return XLookupKeysym(event, event->state);
1733 return XLookupKeysym(event, 0);
1737 KeyMod HandleKeyModState(Key key, int key_status)
1739 static KeyMod current_modifiers = KMOD_None;
1741 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1743 KeyMod new_modifier = KMOD_None;
1748 new_modifier = KMOD_Shift_L;
1751 new_modifier = KMOD_Shift_R;
1753 case KSYM_Control_L:
1754 new_modifier = KMOD_Control_L;
1756 case KSYM_Control_R:
1757 new_modifier = KMOD_Control_R;
1760 new_modifier = KMOD_Meta_L;
1763 new_modifier = KMOD_Meta_R;
1766 new_modifier = KMOD_Alt_L;
1769 new_modifier = KMOD_Alt_R;
1775 if (key_status == KEY_PRESSED)
1776 current_modifiers |= new_modifier;
1778 current_modifiers &= ~new_modifier;
1781 return current_modifiers;
1784 KeyMod GetKeyModState()
1786 #if defined(TARGET_SDL)
1787 return (KeyMod)SDL_GetModState();
1789 return HandleKeyModState(KSYM_UNDEFINED, 0);
1793 KeyMod GetKeyModStateFromEvents()
1795 /* always use key modifier state as tracked from key events (this is needed
1796 if the modifier key event was injected into the event queue, but the key
1797 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1798 query the keys as held pressed on the keyboard) -- this case is currently
1799 only used to filter out clipboard insert events from "True X-Mouse" tool */
1801 return HandleKeyModState(KSYM_UNDEFINED, 0);
1804 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1806 if (event->type != EVENT_CLIENTMESSAGE)
1809 #if defined(TARGET_SDL)
1810 return TRUE; /* the only possible message here is SDL_QUIT */
1811 #elif defined(PLATFORM_UNIX)
1812 if ((event->window == window->drawable) &&
1813 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1821 /* ========================================================================= */
1822 /* joystick functions */
1823 /* ========================================================================= */
1825 void InitJoysticks()
1829 #if defined(NO_JOYSTICK)
1830 return; /* joysticks generally deactivated by compile-time directive */
1833 /* always start with reliable default values */
1834 joystick.status = JOYSTICK_NOT_AVAILABLE;
1835 for (i = 0; i < MAX_PLAYERS; i++)
1836 joystick.fd[i] = -1; /* joystick device closed */
1838 #if defined(TARGET_SDL)
1840 #elif defined(PLATFORM_UNIX)
1841 UnixInitJoysticks();
1842 #elif defined(PLATFORM_MSDOS)
1843 MSDOSInitJoysticks();
1847 for (i = 0; i < MAX_PLAYERS; i++)
1848 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1852 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1854 #if defined(TARGET_SDL)
1855 return SDLReadJoystick(nr, x, y, b1, b2);
1856 #elif defined(PLATFORM_UNIX)
1857 return UnixReadJoystick(nr, x, y, b1, b2);
1858 #elif defined(PLATFORM_MSDOS)
1859 return MSDOSReadJoystick(nr, x, y, b1, b2);