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 InitGfxDoor3Info(int ex, int ey, int exsize, int eysize)
225 void InitGfxWindowInfo(int win_xsize, int win_ysize)
227 gfx.win_xsize = win_xsize;
228 gfx.win_ysize = win_ysize;
231 gfx.background_bitmap_mask = REDRAW_NONE;
233 ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize, DEFAULT_DEPTH);
237 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
239 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
240 /* 2009-03-24: also (temporarily?) used for overlapping blit workaround */
241 gfx.scrollbuffer_width = scrollbuffer_width;
242 gfx.scrollbuffer_height = scrollbuffer_height;
245 void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height)
247 gfx.clipping_enabled = enabled;
250 gfx.clip_width = width;
251 gfx.clip_height = height;
254 void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
256 gfx.draw_busy_anim_function = draw_busy_anim_function;
259 void InitGfxCustomArtworkInfo()
261 gfx.override_level_graphics = FALSE;
262 gfx.override_level_sounds = FALSE;
263 gfx.override_level_music = FALSE;
265 gfx.draw_init_text = TRUE;
268 void SetDrawDeactivationMask(int draw_deactivation_mask)
270 gfx.draw_deactivation_mask = draw_deactivation_mask;
273 void SetDrawBackgroundMask(int draw_background_mask)
275 gfx.draw_background_mask = draw_background_mask;
280 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
281 int dest_x, int dest_y, int width, int height)
283 int bitmap_xsize = width;
284 int bitmap_ysize = height;
285 int tile_xsize = tile->width;
286 int tile_ysize = tile->height;
287 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
288 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
291 for (y = 0; y < tile_ysteps; y++)
293 for (x = 0; x < tile_xsteps; x++)
295 int draw_x = dest_x + x * tile_xsize;
296 int draw_y = dest_y + y * tile_ysize;
297 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
298 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
300 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
305 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
307 if (background_bitmap_tile != NULL)
308 gfx.background_bitmap_mask |= mask;
310 gfx.background_bitmap_mask &= ~mask;
313 if (gfx.background_bitmap == NULL)
314 gfx.background_bitmap = CreateBitmap(video.width, video.height,
318 if (background_bitmap_tile == NULL) /* empty background requested */
321 if (mask == REDRAW_ALL)
322 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
323 0, 0, video.width, video.height);
324 else if (mask == REDRAW_FIELD)
325 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
326 gfx.real_sx, gfx.real_sy,
327 gfx.full_sxsize, gfx.full_sysize);
328 else if (mask == REDRAW_DOOR_1)
329 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
331 gfx.dxsize, gfx.dysize);
336 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
338 if (background_bitmap_tile != NULL)
339 gfx.background_bitmap_mask |= mask;
341 gfx.background_bitmap_mask &= ~mask;
344 if (gfx.background_bitmap == NULL)
345 gfx.background_bitmap = CreateBitmap(video.width, video.height,
349 if (background_bitmap_tile == NULL) /* empty background requested */
352 if (mask == REDRAW_ALL)
353 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
354 0, 0, video.width, video.height);
355 else if (mask == REDRAW_FIELD)
356 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
357 gfx.real_sx, gfx.real_sy, gfx.full_sxsize, gfx.full_sysize);
358 else if (mask == REDRAW_DOOR_1)
359 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
360 gfx.dx, gfx.dy, gfx.dxsize, gfx.dysize);
365 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
367 /* remove every mask before setting mask for window */
368 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
369 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
370 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
373 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
375 /* remove window area mask before setting mask for main area */
376 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
377 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
378 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
381 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
383 /* remove window area mask before setting mask for door area */
384 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
385 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
386 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
390 /* ========================================================================= */
391 /* video functions */
392 /* ========================================================================= */
394 inline static int GetRealDepth(int depth)
396 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
399 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
400 int width, int height, Pixel color)
402 #if defined(TARGET_SDL)
403 SDLFillRectangle(bitmap, x, y, width, height, color);
405 X11FillRectangle(bitmap, x, y, width, height, color);
409 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
410 int src_x, int src_y, int width, int height,
411 int dst_x, int dst_y, int mask_mode)
413 #if defined(TARGET_SDL)
414 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
415 dst_x, dst_y, mask_mode);
417 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
418 dst_x, dst_y, mask_mode);
422 void LimitScreenUpdates(boolean enable)
424 #if defined(TARGET_SDL)
425 SDLLimitScreenUpdates(enable);
429 void InitVideoDisplay(void)
431 #if defined(TARGET_SDL)
432 SDLInitVideoDisplay();
434 X11InitVideoDisplay();
438 void CloseVideoDisplay(void)
440 KeyboardAutoRepeatOn();
442 #if defined(TARGET_SDL)
443 SDL_QuitSubSystem(SDL_INIT_VIDEO);
446 XCloseDisplay(display);
450 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
453 printf("::: InitVideoBuffer\n");
457 video.height = height;
458 video.depth = GetRealDepth(depth);
460 video.fullscreen_available = FULLSCREEN_STATUS;
461 video.fullscreen_enabled = FALSE;
462 // video.fullscreen_initial = FALSE;
464 video.fullscreen_mode_current = NULL;
465 video.fullscreen_modes = NULL;
468 video.window_scaling_available = WINDOW_SCALING_STATUS;
470 #if defined(TARGET_SDL)
471 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
473 X11InitVideoBuffer(&backbuffer, &window);
479 inline static void FreeBitmapPointers(Bitmap *bitmap)
484 #if defined(TARGET_SDL)
485 SDLFreeBitmapPointers(bitmap);
487 X11FreeBitmapPointers(bitmap);
490 checked_free(bitmap->source_filename);
491 bitmap->source_filename = NULL;
494 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
497 if (src_bitmap == NULL || dst_bitmap == NULL)
500 FreeBitmapPointers(dst_bitmap);
502 *dst_bitmap = *src_bitmap;
505 void FreeBitmap(Bitmap *bitmap)
510 FreeBitmapPointers(bitmap);
515 Bitmap *CreateBitmapStruct(void)
517 #if defined(TARGET_SDL)
518 return checked_calloc(sizeof(struct SDLSurfaceInfo));
520 return checked_calloc(sizeof(struct X11DrawableInfo));
524 Bitmap *CreateBitmap(int width, int height, int depth)
526 Bitmap *new_bitmap = CreateBitmapStruct();
527 int real_width = MAX(1, width); /* prevent zero bitmap width */
528 int real_height = MAX(1, height); /* prevent zero bitmap height */
529 int real_depth = GetRealDepth(depth);
531 #if defined(TARGET_SDL)
532 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
534 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
537 new_bitmap->width = real_width;
538 new_bitmap->height = real_height;
543 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
545 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
549 *bitmap = new_bitmap;
553 TransferBitmapPointers(new_bitmap, *bitmap);
558 void CloseWindow(DrawWindow *window)
560 #if defined(TARGET_X11)
561 X11CloseWindow(window);
565 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
568 if (draw_mask == REDRAW_NONE)
571 if (draw_mask & REDRAW_ALL)
575 if ((draw_mask & REDRAW_FIELD) && IN_GFX_FIELD_FULL(x, y))
578 if ((draw_mask & REDRAW_DOOR_1) && IN_GFX_DOOR_1(x, y))
581 if ((draw_mask & REDRAW_DOOR_2) && IN_GFX_DOOR_2(x, y))
584 if ((draw_mask & REDRAW_DOOR_3) && IN_GFX_DOOR_3(x, y))
587 if ((draw_mask & REDRAW_FIELD) &&
588 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
591 if ((draw_mask & REDRAW_DOOR_1) &&
592 x >= gfx.dx && y < gfx.dy + gfx.dysize)
595 if ((draw_mask & REDRAW_DOOR_2) &&
596 x >= gfx.dx && y >= gfx.vy)
603 boolean DrawingDeactivated(int x, int y, int width, int height)
605 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
608 boolean DrawingOnBackground(int x, int y)
610 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
611 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
614 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
615 int *width, int *height, boolean is_dest)
618 int clip_x, clip_y, clip_width, clip_height;
620 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
622 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
623 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
624 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
625 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
631 clip_width = bitmap->width;
632 clip_height = bitmap->height;
635 /* skip if rectangle completely outside bitmap */
637 if (*x + *width <= clip_x ||
638 *y + *height <= clip_y ||
639 *x >= clip_x + clip_width ||
640 *y >= clip_y + clip_height)
643 /* clip if rectangle overlaps bitmap */
647 *width -= clip_x - *x;
650 else if (*x + *width > clip_x + clip_width)
652 *width = clip_x + clip_width - *x;
657 *height -= clip_y - *y;
660 else if (*y + *height > clip_y + clip_height)
662 *height = clip_y + clip_height - *y;
669 /* skip if rectangle completely outside bitmap */
671 if (*x + *width <= 0 ||
673 *x >= bitmap->width ||
674 *y >= bitmap->height)
677 /* clip if rectangle overlaps bitmap */
684 else if (*x + *width > bitmap->width)
686 *width = bitmap->width - *x;
694 else if (*y + *height > bitmap->height)
696 *height = bitmap->height - *y;
703 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
704 int src_x, int src_y, int width, int height,
705 int dst_x, int dst_y)
707 int dst_x_unclipped = dst_x;
708 int dst_y_unclipped = dst_y;
710 if (src_bitmap == NULL || dst_bitmap == NULL)
713 if (DrawingDeactivated(dst_x, dst_y, width, height))
717 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
718 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
721 /* source x/y might need adjustment if destination x/y was clipped top/left */
722 src_x += dst_x - dst_x_unclipped;
723 src_y += dst_y - dst_y_unclipped;
726 /* skip if rectangle starts outside bitmap */
727 if (src_x >= src_bitmap->width ||
728 src_y >= src_bitmap->height ||
729 dst_x >= dst_bitmap->width ||
730 dst_y >= dst_bitmap->height)
733 /* clip if rectangle overlaps bitmap */
734 if (src_x + width > src_bitmap->width)
735 width = src_bitmap->width - src_x;
736 if (src_y + height > src_bitmap->height)
737 height = src_bitmap->height - src_y;
738 if (dst_x + width > dst_bitmap->width)
739 width = dst_bitmap->width - dst_x;
740 if (dst_y + height > dst_bitmap->height)
741 height = dst_bitmap->height - dst_y;
745 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
747 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
748 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
749 but is already fixed in SVN and should therefore finally be fixed with
750 the next official SDL release, which is probably version 1.2.14.) */
752 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
753 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
754 #if defined(TARGET_SDL2)
755 if (src_bitmap == dst_bitmap)
757 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
759 /* needed when blitting directly to same bitmap -- should not be needed with
760 recent SDL libraries, but apparently does not work in 1.2.11 directly */
762 static Bitmap *tmp_bitmap = NULL;
763 static int tmp_bitmap_xsize = 0;
764 static int tmp_bitmap_ysize = 0;
766 /* start with largest static bitmaps for initial bitmap size ... */
767 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
769 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
770 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
773 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
774 if (src_bitmap->width > tmp_bitmap_xsize ||
775 src_bitmap->height > tmp_bitmap_ysize)
777 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
778 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
780 FreeBitmap(tmp_bitmap);
785 if (tmp_bitmap == NULL)
786 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
789 sysCopyArea(src_bitmap, tmp_bitmap,
790 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
791 sysCopyArea(tmp_bitmap, dst_bitmap,
792 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
802 if (dst_x < gfx.sx + gfx.sxsize)
803 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
804 FrameCounter, dst_x, dst_y, width, height);
807 sysCopyArea(src_bitmap, dst_bitmap,
808 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
811 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
812 int src_x, int src_y, int src_width, int src_height,
813 int dst_x, int dst_y, int dst_width, int dst_height)
815 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
816 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
817 int dst_xsize = dst_width;
818 int dst_ysize = dst_height;
819 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
820 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
823 for (y = 0; y < src_ysteps; y++)
825 for (x = 0; x < src_xsteps; x++)
827 int draw_x = dst_x + x * src_xsize;
828 int draw_y = dst_y + y * src_ysize;
829 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
830 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
832 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
838 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
839 int fade_mode, int fade_delay, int post_delay,
840 void (*draw_border_function)(void))
843 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
844 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
848 #if defined(TARGET_SDL)
849 SDLFadeRectangle(bitmap_cross, x, y, width, height,
850 fade_mode, fade_delay, post_delay, draw_border_function);
852 X11FadeRectangle(bitmap_cross, x, y, width, height,
853 fade_mode, fade_delay, post_delay, draw_border_function);
857 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
860 if (DrawingDeactivated(x, y, width, height))
864 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
867 /* skip if rectangle starts outside bitmap */
868 if (x >= bitmap->width ||
872 /* clip if rectangle overlaps bitmap */
873 if (x + width > bitmap->width)
874 width = bitmap->width - x;
875 if (y + height > bitmap->height)
876 height = bitmap->height - y;
879 sysFillRectangle(bitmap, x, y, width, height, color);
882 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
884 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
887 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
888 int width, int height)
890 if (DrawingOnBackground(x, y))
891 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
893 ClearRectangle(bitmap, x, y, width, height);
896 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
898 #if defined(TARGET_X11)
901 bitmap->clip_gc = clip_gc;
902 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
907 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
909 #if defined(TARGET_X11)
912 bitmap->clip_gc = clip_gc;
913 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
918 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
919 int src_x, int src_y, int width, int height,
920 int dst_x, int dst_y)
922 if (DrawingDeactivated(dst_x, dst_y, width, height))
925 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
926 dst_x, dst_y, BLIT_MASKED);
929 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
930 int src_x, int src_y, int width, int height,
931 int dst_x, int dst_y)
933 if (DrawingOnBackground(dst_x, dst_y))
935 /* draw background */
936 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
939 /* draw foreground */
940 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
941 dst_x - src_x, dst_y - src_y);
942 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
946 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
950 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
953 #if defined(TARGET_SDL)
954 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
956 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
960 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
963 #if defined(TARGET_SDL)
964 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
966 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
970 #if !defined(TARGET_X11_NATIVE)
971 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
972 int to_x, int to_y, Pixel pixel, int line_width)
976 for (x = 0; x < line_width; x++)
978 for (y = 0; y < line_width; y++)
980 int dx = x - line_width / 2;
981 int dy = y - line_width / 2;
983 if ((x == 0 && y == 0) ||
984 (x == 0 && y == line_width - 1) ||
985 (x == line_width - 1 && y == 0) ||
986 (x == line_width - 1 && y == line_width - 1))
989 #if defined(TARGET_SDL)
991 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
992 #elif defined(TARGET_ALLEGRO)
993 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
994 to_x + dx, to_y + dy, pixel);
1001 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
1003 #if !defined(TARGET_X11_NATIVE)
1007 for (i = 0; i < num_points - 1; i++)
1008 DrawLine(bitmap, points[i].x, points[i].y,
1009 points[i + 1].x, points[i + 1].y, pixel, line_width);
1012 SDLDrawLines(bitmap->surface, points, num_points, pixel);
1015 XSetForeground(display, bitmap->line_gc[1], pixel);
1016 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
1017 (XPoint *)points, num_points, CoordModeOrigin);
1021 Pixel GetPixel(Bitmap *bitmap, int x, int y)
1023 if (x < 0 || x >= bitmap->width ||
1024 y < 0 || y >= bitmap->height)
1027 #if defined(TARGET_SDL)
1028 return SDLGetPixel(bitmap, x, y);
1029 #elif defined(TARGET_ALLEGRO)
1030 return AllegroGetPixel(bitmap->drawable, x, y);
1032 return X11GetPixel(bitmap, x, y);
1036 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1037 unsigned int color_g, unsigned int color_b)
1039 #if defined(TARGET_SDL)
1040 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1041 #elif defined(TARGET_ALLEGRO)
1042 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1044 return X11GetPixelFromRGB(color_r, color_g, color_b);
1048 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1050 unsigned int color_r = (color >> 16) & 0xff;
1051 unsigned int color_g = (color >> 8) & 0xff;
1052 unsigned int color_b = (color >> 0) & 0xff;
1054 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1057 /* execute all pending screen drawing operations */
1058 void FlushDisplay(void)
1060 #if !defined(TARGET_SDL)
1065 /* execute and wait for all pending screen drawing operations */
1066 void SyncDisplay(void)
1068 #if !defined(TARGET_SDL)
1069 XSync(display, FALSE);
1073 void KeyboardAutoRepeatOn(void)
1075 #if defined(TARGET_SDL)
1076 #if defined(TARGET_SDL2)
1077 keyrepeat_status = TRUE;
1079 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1080 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1081 SDL_EnableUNICODE(1);
1085 XAutoRepeatOn(display);
1089 void KeyboardAutoRepeatOff(void)
1091 #if defined(TARGET_SDL)
1092 #if defined(TARGET_SDL2)
1093 keyrepeat_status = FALSE;
1095 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1096 SDL_EnableUNICODE(0);
1100 XAutoRepeatOff(display);
1104 boolean PointerInWindow(DrawWindow *window)
1106 #if defined(TARGET_SDL)
1114 /* if XQueryPointer() returns False, the pointer
1115 is not on the same screen as the specified window */
1116 return XQueryPointer(display, window->drawable, &root, &child,
1117 &root_x, &root_y, &win_x, &win_y, &mask);
1121 boolean SetVideoMode(boolean fullscreen)
1123 #if defined(TARGET_SDL)
1124 return SDLSetVideoMode(&backbuffer, fullscreen);
1126 boolean success = TRUE;
1128 if (fullscreen && video.fullscreen_available)
1130 Error(ERR_WARN, "fullscreen not available in X11 version");
1132 /* display error message only once */
1133 video.fullscreen_available = FALSE;
1142 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1144 #if defined(TARGET_SDL)
1145 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1146 (!fullscreen && video.fullscreen_enabled))
1147 fullscreen = SetVideoMode(fullscreen);
1153 Bitmap *LoadImage(char *filename)
1157 #if defined(TARGET_SDL)
1158 new_bitmap = SDLLoadImage(filename);
1160 new_bitmap = X11LoadImage(filename);
1164 new_bitmap->source_filename = getStringCopy(filename);
1169 Bitmap *LoadCustomImage(char *basename)
1171 char *filename = getCustomImageFilename(basename);
1174 if (filename == NULL)
1175 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1177 if ((new_bitmap = LoadImage(filename)) == NULL)
1178 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1183 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1185 char *filename = getCustomImageFilename(basename);
1188 if (filename == NULL) /* (should never happen) */
1190 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1194 if (strEqual(filename, bitmap->source_filename))
1196 /* The old and new image are the same (have the same filename and path).
1197 This usually means that this image does not exist in this graphic set
1198 and a fallback to the existing image is done. */
1203 if ((new_bitmap = LoadImage(filename)) == NULL)
1205 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1209 if (bitmap->width != new_bitmap->width ||
1210 bitmap->height != new_bitmap->height)
1212 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1214 FreeBitmap(new_bitmap);
1218 TransferBitmapPointers(new_bitmap, bitmap);
1222 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1224 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1226 #if defined(TARGET_SDL)
1227 SDLZoomBitmap(src_bitmap, dst_bitmap);
1229 X11ZoomBitmap(src_bitmap, dst_bitmap);
1235 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1236 boolean create_small_bitmaps)
1240 Bitmap *tmp_bitmap_1;
1241 Bitmap *tmp_bitmap_2;
1242 Bitmap *tmp_bitmap_4;
1243 Bitmap *tmp_bitmap_8;
1244 Bitmap *tmp_bitmap_16;
1245 Bitmap *tmp_bitmap_32;
1246 int width_1, height_1;
1247 int width_2, height_2;
1248 int width_4, height_4;
1249 int width_8, height_8;
1250 int width_16, height_16;
1252 int width_32, height_32;
1254 int new_width, new_height;
1256 /* calculate new image dimensions for normal sized image */
1257 width_1 = old_bitmap->width * zoom_factor;
1258 height_1 = old_bitmap->height * zoom_factor;
1260 /* get image with normal size (this might require scaling up) */
1261 if (zoom_factor != 1)
1262 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1264 tmp_bitmap_1 = old_bitmap;
1266 /* this is only needed to make compilers happy */
1267 tmp_bitmap_2 = NULL;
1268 tmp_bitmap_4 = NULL;
1269 tmp_bitmap_8 = NULL;
1270 tmp_bitmap_16 = NULL;
1271 tmp_bitmap_32 = NULL;
1273 if (create_small_bitmaps)
1275 /* calculate new image dimensions for small images */
1276 width_2 = width_1 / 2;
1277 height_2 = height_1 / 2;
1278 width_4 = width_1 / 4;
1279 height_4 = height_1 / 4;
1280 width_8 = width_1 / 8;
1281 height_8 = height_1 / 8;
1282 width_16 = width_1 / 16;
1283 height_16 = height_1 / 16;
1285 width_32 = width_1 / 32;
1286 height_32 = height_1 / 32;
1289 UPDATE_BUSY_STATE();
1291 /* get image with 1/2 of normal size (for use in the level editor) */
1292 if (zoom_factor != 2)
1293 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1295 tmp_bitmap_2 = old_bitmap;
1297 UPDATE_BUSY_STATE();
1299 /* get image with 1/4 of normal size (for use in the level editor) */
1300 if (zoom_factor != 4)
1301 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1303 tmp_bitmap_4 = old_bitmap;
1305 UPDATE_BUSY_STATE();
1307 /* get image with 1/8 of normal size (for use on the preview screen) */
1308 if (zoom_factor != 8)
1309 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1311 tmp_bitmap_8 = old_bitmap;
1313 UPDATE_BUSY_STATE();
1315 /* get image with 1/16 of normal size (for use on the preview screen) */
1316 if (zoom_factor != 16)
1317 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1319 tmp_bitmap_16 = old_bitmap;
1321 UPDATE_BUSY_STATE();
1323 /* get image with 1/32 of normal size (for use on the preview screen) */
1324 if (zoom_factor != 32)
1325 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1327 tmp_bitmap_32 = old_bitmap;
1329 UPDATE_BUSY_STATE();
1333 /* if image was scaled up, create new clipmask for normal size image */
1334 if (zoom_factor != 1)
1336 #if defined(TARGET_X11)
1337 if (old_bitmap->clip_mask)
1338 XFreePixmap(display, old_bitmap->clip_mask);
1340 old_bitmap->clip_mask =
1341 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1343 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1345 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1347 if (old_bitmap->surface_masked)
1348 SDL_FreeSurface(old_bitmap->surface_masked);
1350 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1351 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1352 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1353 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1354 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1359 if (create_small_bitmaps)
1361 new_width = width_1;
1362 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1364 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1366 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1367 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1369 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1370 width_1 / 2, height_1);
1371 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1372 3 * width_1 / 4, height_1);
1373 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1374 7 * width_1 / 8, height_1);
1375 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1376 15 * width_1 / 16, height_1);
1378 UPDATE_BUSY_STATE();
1382 new_width = width_1;
1383 new_height = height_1;
1385 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1388 if (create_small_bitmaps)
1390 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1391 if (zoom_factor != 1)
1392 FreeBitmap(tmp_bitmap_1);
1394 if (zoom_factor != 2)
1395 FreeBitmap(tmp_bitmap_2);
1397 if (zoom_factor != 4)
1398 FreeBitmap(tmp_bitmap_4);
1400 if (zoom_factor != 8)
1401 FreeBitmap(tmp_bitmap_8);
1403 if (zoom_factor != 16)
1404 FreeBitmap(tmp_bitmap_16);
1406 if (zoom_factor != 32)
1407 FreeBitmap(tmp_bitmap_32);
1410 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1411 #if defined(TARGET_SDL)
1412 swap_bitmap.surface = old_bitmap->surface;
1413 old_bitmap->surface = new_bitmap->surface;
1414 new_bitmap->surface = swap_bitmap.surface;
1416 swap_bitmap.drawable = old_bitmap->drawable;
1417 old_bitmap->drawable = new_bitmap->drawable;
1418 new_bitmap->drawable = swap_bitmap.drawable;
1421 old_bitmap->width = new_bitmap->width;
1422 old_bitmap->height = new_bitmap->height;
1425 /* this replaces all blit masks created when loading -- maybe optimize this */
1427 #if defined(TARGET_X11)
1428 if (old_bitmap->clip_mask)
1429 XFreePixmap(display, old_bitmap->clip_mask);
1431 old_bitmap->clip_mask =
1432 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1434 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1436 SDL_Surface *old_surface = old_bitmap->surface;
1438 if (old_bitmap->surface_masked)
1439 SDL_FreeSurface(old_bitmap->surface_masked);
1441 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1442 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1443 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1444 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1445 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1450 UPDATE_BUSY_STATE();
1452 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1455 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1457 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1460 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1462 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1466 /* ------------------------------------------------------------------------- */
1467 /* mouse pointer functions */
1468 /* ------------------------------------------------------------------------- */
1470 #if !defined(PLATFORM_MSDOS)
1471 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1472 /* XPM image definitions */
1473 static const char *cursor_image_none[] =
1475 /* width height num_colors chars_per_pixel */
1504 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1505 static const char *cursor_image_dot[] =
1507 /* width height num_colors chars_per_pixel */
1536 static const char **cursor_image_playfield = cursor_image_dot;
1538 /* some people complained about a "white dot" on the screen and thought it
1539 was a graphical error... OK, let's just remove the whole pointer :-) */
1540 static const char **cursor_image_playfield = cursor_image_none;
1543 #if defined(TARGET_SDL)
1544 static const int cursor_bit_order = BIT_ORDER_MSB;
1545 #elif defined(TARGET_X11_NATIVE)
1546 static const int cursor_bit_order = BIT_ORDER_LSB;
1549 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1551 struct MouseCursorInfo *cursor;
1552 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1553 int header_lines = 4;
1556 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1558 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1561 for (y = 0; y < cursor->width; y++)
1563 for (x = 0; x < cursor->height; x++)
1566 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1571 cursor->data[i] = cursor->mask[i] = 0;
1574 switch (image[header_lines + y][x])
1577 cursor->data[i] |= bit_mask;
1578 cursor->mask[i] |= bit_mask;
1582 cursor->mask[i] |= bit_mask;
1591 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1595 #endif /* !PLATFORM_MSDOS */
1597 void SetMouseCursor(int mode)
1599 #if !defined(PLATFORM_MSDOS)
1600 static struct MouseCursorInfo *cursor_none = NULL;
1601 static struct MouseCursorInfo *cursor_playfield = NULL;
1602 struct MouseCursorInfo *cursor_new;
1604 if (cursor_none == NULL)
1605 cursor_none = get_cursor_from_image(cursor_image_none);
1607 if (cursor_playfield == NULL)
1608 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1610 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1611 mode == CURSOR_NONE ? cursor_none :
1612 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1614 #if defined(TARGET_SDL)
1615 SDLSetMouseCursor(cursor_new);
1616 #elif defined(TARGET_X11_NATIVE)
1617 X11SetMouseCursor(cursor_new);
1623 /* ========================================================================= */
1624 /* audio functions */
1625 /* ========================================================================= */
1627 void OpenAudio(void)
1629 /* always start with reliable default values */
1630 audio.sound_available = FALSE;
1631 audio.music_available = FALSE;
1632 audio.loops_available = FALSE;
1634 audio.sound_enabled = FALSE;
1635 audio.sound_deactivated = FALSE;
1637 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1638 audio.mixer_pid = 0;
1639 audio.device_name = NULL;
1640 audio.device_fd = -1;
1642 audio.num_channels = 0;
1643 audio.music_channel = 0;
1644 audio.first_sound_channel = 0;
1646 #if defined(TARGET_SDL)
1648 #elif defined(PLATFORM_UNIX)
1650 #elif defined(PLATFORM_MSDOS)
1655 void CloseAudio(void)
1657 #if defined(TARGET_SDL)
1659 #elif defined(PLATFORM_UNIX)
1661 #elif defined(PLATFORM_MSDOS)
1665 audio.sound_enabled = FALSE;
1668 void SetAudioMode(boolean enabled)
1670 if (!audio.sound_available)
1673 audio.sound_enabled = enabled;
1677 /* ========================================================================= */
1678 /* event functions */
1679 /* ========================================================================= */
1681 void InitEventFilter(EventFilter filter_function)
1683 /* set event filter to filter out certain events */
1684 #if defined(TARGET_SDL)
1685 #if defined(TARGET_SDL2)
1686 SDL_SetEventFilter(filter_function, NULL);
1688 SDL_SetEventFilter(filter_function);
1693 boolean PendingEvent(void)
1695 #if defined(TARGET_SDL)
1696 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1698 return (XPending(display) ? TRUE : FALSE);
1702 void NextEvent(Event *event)
1704 #if defined(TARGET_SDL)
1705 SDLNextEvent(event);
1707 XNextEvent(display, event);
1711 void PeekEvent(Event *event)
1713 #if defined(TARGET_SDL)
1714 #if defined(TARGET_SDL2)
1715 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1717 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1720 XPeekEvent(display, event);
1724 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1726 #if defined(TARGET_SDL)
1727 #if defined(TARGET_SDL2)
1728 /* key up/down events in SDL2 do not return text characters anymore */
1729 return event->keysym.sym;
1733 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1734 (int)event->keysym.unicode,
1735 (int)event->keysym.sym,
1736 (int)SDL_GetModState());
1739 if (with_modifiers &&
1740 event->keysym.unicode > 0x0000 &&
1741 event->keysym.unicode < 0x2000)
1742 return event->keysym.unicode;
1744 return event->keysym.sym;
1750 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1751 (int)XLookupKeysym(event, event->state),
1752 (int)XLookupKeysym(event, 0));
1756 return XLookupKeysym(event, event->state);
1758 return XLookupKeysym(event, 0);
1762 KeyMod HandleKeyModState(Key key, int key_status)
1764 static KeyMod current_modifiers = KMOD_None;
1766 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1768 KeyMod new_modifier = KMOD_None;
1773 new_modifier = KMOD_Shift_L;
1776 new_modifier = KMOD_Shift_R;
1778 case KSYM_Control_L:
1779 new_modifier = KMOD_Control_L;
1781 case KSYM_Control_R:
1782 new_modifier = KMOD_Control_R;
1785 new_modifier = KMOD_Meta_L;
1788 new_modifier = KMOD_Meta_R;
1791 new_modifier = KMOD_Alt_L;
1794 new_modifier = KMOD_Alt_R;
1800 if (key_status == KEY_PRESSED)
1801 current_modifiers |= new_modifier;
1803 current_modifiers &= ~new_modifier;
1806 return current_modifiers;
1809 KeyMod GetKeyModState()
1811 #if defined(TARGET_SDL)
1812 return (KeyMod)SDL_GetModState();
1814 return HandleKeyModState(KSYM_UNDEFINED, 0);
1818 KeyMod GetKeyModStateFromEvents()
1820 /* always use key modifier state as tracked from key events (this is needed
1821 if the modifier key event was injected into the event queue, but the key
1822 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1823 query the keys as held pressed on the keyboard) -- this case is currently
1824 only used to filter out clipboard insert events from "True X-Mouse" tool */
1826 return HandleKeyModState(KSYM_UNDEFINED, 0);
1829 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1831 if (event->type != EVENT_CLIENTMESSAGE)
1834 #if defined(TARGET_SDL)
1835 return TRUE; /* the only possible message here is SDL_QUIT */
1836 #elif defined(PLATFORM_UNIX)
1837 if ((event->window == window->drawable) &&
1838 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1846 /* ========================================================================= */
1847 /* joystick functions */
1848 /* ========================================================================= */
1850 void InitJoysticks()
1854 #if defined(NO_JOYSTICK)
1855 return; /* joysticks generally deactivated by compile-time directive */
1858 /* always start with reliable default values */
1859 joystick.status = JOYSTICK_NOT_AVAILABLE;
1860 for (i = 0; i < MAX_PLAYERS; i++)
1861 joystick.fd[i] = -1; /* joystick device closed */
1863 #if defined(TARGET_SDL)
1865 #elif defined(PLATFORM_UNIX)
1866 UnixInitJoysticks();
1867 #elif defined(PLATFORM_MSDOS)
1868 MSDOSInitJoysticks();
1872 for (i = 0; i < MAX_PLAYERS; i++)
1873 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1877 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1879 #if defined(TARGET_SDL)
1880 return SDLReadJoystick(nr, x, y, b1, b2);
1881 #elif defined(PLATFORM_UNIX)
1882 return UnixReadJoystick(nr, x, y, b1, b2);
1883 #elif defined(PLATFORM_MSDOS)
1884 return MSDOSReadJoystick(nr, x, y, b1, b2);