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 InitVideoDisplay(void)
420 #if defined(TARGET_SDL)
421 SDLInitVideoDisplay();
423 X11InitVideoDisplay();
427 void CloseVideoDisplay(void)
429 KeyboardAutoRepeatOn();
431 #if defined(TARGET_SDL)
432 SDL_QuitSubSystem(SDL_INIT_VIDEO);
435 XCloseDisplay(display);
439 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
442 video.height = height;
443 video.depth = GetRealDepth(depth);
445 video.fullscreen_available = FULLSCREEN_STATUS;
446 video.fullscreen_enabled = FALSE;
448 video.fullscreen_mode_current = NULL;
449 video.fullscreen_modes = NULL;
452 video.window_scaling_available = TRUE;
454 #if defined(TARGET_SDL)
455 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
457 X11InitVideoBuffer(&backbuffer, &window);
463 inline static void FreeBitmapPointers(Bitmap *bitmap)
468 #if defined(TARGET_SDL)
469 SDLFreeBitmapPointers(bitmap);
471 X11FreeBitmapPointers(bitmap);
474 checked_free(bitmap->source_filename);
475 bitmap->source_filename = NULL;
478 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
481 if (src_bitmap == NULL || dst_bitmap == NULL)
484 FreeBitmapPointers(dst_bitmap);
486 *dst_bitmap = *src_bitmap;
489 void FreeBitmap(Bitmap *bitmap)
494 FreeBitmapPointers(bitmap);
499 Bitmap *CreateBitmapStruct(void)
501 #if defined(TARGET_SDL)
502 return checked_calloc(sizeof(struct SDLSurfaceInfo));
504 return checked_calloc(sizeof(struct X11DrawableInfo));
508 Bitmap *CreateBitmap(int width, int height, int depth)
510 Bitmap *new_bitmap = CreateBitmapStruct();
511 int real_width = MAX(1, width); /* prevent zero bitmap width */
512 int real_height = MAX(1, height); /* prevent zero bitmap height */
513 int real_depth = GetRealDepth(depth);
515 #if defined(TARGET_SDL)
516 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
518 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
521 new_bitmap->width = real_width;
522 new_bitmap->height = real_height;
527 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
529 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
533 *bitmap = new_bitmap;
537 TransferBitmapPointers(new_bitmap, *bitmap);
542 void CloseWindow(DrawWindow *window)
544 #if defined(TARGET_X11)
545 X11CloseWindow(window);
549 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
552 if (draw_mask == REDRAW_NONE)
555 if (draw_mask & REDRAW_ALL)
558 if ((draw_mask & REDRAW_FIELD) &&
559 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
562 if ((draw_mask & REDRAW_DOOR_1) &&
563 x >= gfx.dx && y < gfx.dy + gfx.dysize)
566 if ((draw_mask & REDRAW_DOOR_2) &&
567 x >= gfx.dx && y >= gfx.vy)
573 boolean DrawingDeactivated(int x, int y, int width, int height)
575 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
578 boolean DrawingOnBackground(int x, int y)
580 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
581 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
584 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
585 int *width, int *height, boolean is_dest)
588 int clip_x, clip_y, clip_width, clip_height;
590 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
592 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
593 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
594 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
595 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
601 clip_width = bitmap->width;
602 clip_height = bitmap->height;
605 /* skip if rectangle completely outside bitmap */
607 if (*x + *width <= clip_x ||
608 *y + *height <= clip_y ||
609 *x >= clip_x + clip_width ||
610 *y >= clip_y + clip_height)
613 /* clip if rectangle overlaps bitmap */
617 *width -= clip_x - *x;
620 else if (*x + *width > clip_x + clip_width)
622 *width = clip_x + clip_width - *x;
627 *height -= clip_y - *y;
630 else if (*y + *height > clip_y + clip_height)
632 *height = clip_y + clip_height - *y;
639 /* skip if rectangle completely outside bitmap */
641 if (*x + *width <= 0 ||
643 *x >= bitmap->width ||
644 *y >= bitmap->height)
647 /* clip if rectangle overlaps bitmap */
654 else if (*x + *width > bitmap->width)
656 *width = bitmap->width - *x;
664 else if (*y + *height > bitmap->height)
666 *height = bitmap->height - *y;
673 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
674 int src_x, int src_y, int width, int height,
675 int dst_x, int dst_y)
677 int dst_x_unclipped = dst_x;
678 int dst_y_unclipped = dst_y;
680 if (DrawingDeactivated(dst_x, dst_y, width, height))
684 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
685 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
688 /* source x/y might need adjustment if destination x/y was clipped top/left */
689 src_x += dst_x - dst_x_unclipped;
690 src_y += dst_y - dst_y_unclipped;
693 /* skip if rectangle starts outside bitmap */
694 if (src_x >= src_bitmap->width ||
695 src_y >= src_bitmap->height ||
696 dst_x >= dst_bitmap->width ||
697 dst_y >= dst_bitmap->height)
700 /* clip if rectangle overlaps bitmap */
701 if (src_x + width > src_bitmap->width)
702 width = src_bitmap->width - src_x;
703 if (src_y + height > src_bitmap->height)
704 height = src_bitmap->height - src_y;
705 if (dst_x + width > dst_bitmap->width)
706 width = dst_bitmap->width - dst_x;
707 if (dst_y + height > dst_bitmap->height)
708 height = dst_bitmap->height - dst_y;
712 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
714 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
715 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
716 but is already fixed in SVN and should therefore finally be fixed with
717 the next official SDL release, which is probably version 1.2.14.) */
719 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
720 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
721 #if defined(TARGET_SDL2)
722 if (src_bitmap == dst_bitmap)
724 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
726 /* needed when blitting directly to same bitmap -- should not be needed with
727 recent SDL libraries, but apparently does not work in 1.2.11 directly */
729 static Bitmap *tmp_bitmap = NULL;
730 static int tmp_bitmap_xsize = 0;
731 static int tmp_bitmap_ysize = 0;
733 /* start with largest static bitmaps for initial bitmap size ... */
734 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
736 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
737 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
740 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
741 if (src_bitmap->width > tmp_bitmap_xsize ||
742 src_bitmap->height > tmp_bitmap_ysize)
744 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
745 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
747 FreeBitmap(tmp_bitmap);
752 if (tmp_bitmap == NULL)
753 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
756 sysCopyArea(src_bitmap, tmp_bitmap,
757 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
758 sysCopyArea(tmp_bitmap, dst_bitmap,
759 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
769 if (dst_x < gfx.sx + gfx.sxsize)
770 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
771 FrameCounter, dst_x, dst_y, width, height);
774 sysCopyArea(src_bitmap, dst_bitmap,
775 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
778 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
779 int src_x, int src_y, int src_width, int src_height,
780 int dst_x, int dst_y, int dst_width, int dst_height)
782 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
783 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
784 int dst_xsize = dst_width;
785 int dst_ysize = dst_height;
786 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
787 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
790 for (y = 0; y < src_ysteps; y++)
792 for (x = 0; x < src_xsteps; x++)
794 int draw_x = dst_x + x * src_xsize;
795 int draw_y = dst_y + y * src_ysize;
796 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
797 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
799 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
805 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
806 int fade_mode, int fade_delay, int post_delay,
807 void (*draw_border_function)(void))
810 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
811 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
815 #if defined(TARGET_SDL)
816 SDLFadeRectangle(bitmap_cross, x, y, width, height,
817 fade_mode, fade_delay, post_delay, draw_border_function);
819 X11FadeRectangle(bitmap_cross, x, y, width, height,
820 fade_mode, fade_delay, post_delay, draw_border_function);
824 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
827 if (DrawingDeactivated(x, y, width, height))
831 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
834 /* skip if rectangle starts outside bitmap */
835 if (x >= bitmap->width ||
839 /* clip if rectangle overlaps bitmap */
840 if (x + width > bitmap->width)
841 width = bitmap->width - x;
842 if (y + height > bitmap->height)
843 height = bitmap->height - y;
846 sysFillRectangle(bitmap, x, y, width, height, color);
849 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
851 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
854 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
855 int width, int height)
857 if (DrawingOnBackground(x, y))
858 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
860 ClearRectangle(bitmap, x, y, width, height);
863 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
865 #if defined(TARGET_X11)
868 bitmap->clip_gc = clip_gc;
869 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
874 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
876 #if defined(TARGET_X11)
879 bitmap->clip_gc = clip_gc;
880 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
885 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
886 int src_x, int src_y, int width, int height,
887 int dst_x, int dst_y)
889 if (DrawingDeactivated(dst_x, dst_y, width, height))
892 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
893 dst_x, dst_y, BLIT_MASKED);
896 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
897 int src_x, int src_y, int width, int height,
898 int dst_x, int dst_y)
900 if (DrawingOnBackground(dst_x, dst_y))
902 /* draw background */
903 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
906 /* draw foreground */
907 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
908 dst_x - src_x, dst_y - src_y);
909 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
913 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
917 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
920 #if defined(TARGET_SDL)
921 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
923 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
927 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
930 #if defined(TARGET_SDL)
931 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
933 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
937 #if !defined(TARGET_X11_NATIVE)
938 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
939 int to_x, int to_y, Pixel pixel, int line_width)
943 for (x = 0; x < line_width; x++)
945 for (y = 0; y < line_width; y++)
947 int dx = x - line_width / 2;
948 int dy = y - line_width / 2;
950 if ((x == 0 && y == 0) ||
951 (x == 0 && y == line_width - 1) ||
952 (x == line_width - 1 && y == 0) ||
953 (x == line_width - 1 && y == line_width - 1))
956 #if defined(TARGET_SDL)
958 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
959 #elif defined(TARGET_ALLEGRO)
960 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
961 to_x + dx, to_y + dy, pixel);
968 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
970 #if !defined(TARGET_X11_NATIVE)
974 for (i = 0; i < num_points - 1; i++)
975 DrawLine(bitmap, points[i].x, points[i].y,
976 points[i + 1].x, points[i + 1].y, pixel, line_width);
979 SDLDrawLines(bitmap->surface, points, num_points, pixel);
982 XSetForeground(display, bitmap->line_gc[1], pixel);
983 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
984 (XPoint *)points, num_points, CoordModeOrigin);
988 Pixel GetPixel(Bitmap *bitmap, int x, int y)
990 if (x < 0 || x >= bitmap->width ||
991 y < 0 || y >= bitmap->height)
994 #if defined(TARGET_SDL)
995 return SDLGetPixel(bitmap, x, y);
996 #elif defined(TARGET_ALLEGRO)
997 return AllegroGetPixel(bitmap->drawable, x, y);
999 return X11GetPixel(bitmap, x, y);
1003 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1004 unsigned int color_g, unsigned int color_b)
1006 #if defined(TARGET_SDL)
1007 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1008 #elif defined(TARGET_ALLEGRO)
1009 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1011 return X11GetPixelFromRGB(color_r, color_g, color_b);
1015 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1017 unsigned int color_r = (color >> 16) & 0xff;
1018 unsigned int color_g = (color >> 8) & 0xff;
1019 unsigned int color_b = (color >> 0) & 0xff;
1021 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1024 /* execute all pending screen drawing operations */
1025 void FlushDisplay(void)
1027 #if !defined(TARGET_SDL)
1032 /* execute and wait for all pending screen drawing operations */
1033 void SyncDisplay(void)
1035 #if !defined(TARGET_SDL)
1036 XSync(display, FALSE);
1040 void KeyboardAutoRepeatOn(void)
1042 #if defined(TARGET_SDL)
1043 #if defined(TARGET_SDL2)
1044 keyrepeat_status = TRUE;
1046 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1047 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1048 SDL_EnableUNICODE(1);
1052 XAutoRepeatOn(display);
1056 void KeyboardAutoRepeatOff(void)
1058 #if defined(TARGET_SDL)
1059 #if defined(TARGET_SDL2)
1060 keyrepeat_status = FALSE;
1062 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1063 SDL_EnableUNICODE(0);
1067 XAutoRepeatOff(display);
1071 boolean PointerInWindow(DrawWindow *window)
1073 #if defined(TARGET_SDL)
1081 /* if XQueryPointer() returns False, the pointer
1082 is not on the same screen as the specified window */
1083 return XQueryPointer(display, window->drawable, &root, &child,
1084 &root_x, &root_y, &win_x, &win_y, &mask);
1088 boolean SetVideoMode(boolean fullscreen)
1090 #if defined(TARGET_SDL)
1091 return SDLSetVideoMode(&backbuffer, fullscreen);
1093 boolean success = TRUE;
1095 if (fullscreen && video.fullscreen_available)
1097 Error(ERR_WARN, "fullscreen not available in X11 version");
1099 /* display error message only once */
1100 video.fullscreen_available = FALSE;
1109 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1111 #if defined(TARGET_SDL)
1112 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1113 (!fullscreen && video.fullscreen_enabled))
1114 fullscreen = SetVideoMode(fullscreen);
1120 Bitmap *LoadImage(char *filename)
1124 #if defined(TARGET_SDL)
1125 new_bitmap = SDLLoadImage(filename);
1127 new_bitmap = X11LoadImage(filename);
1131 new_bitmap->source_filename = getStringCopy(filename);
1136 Bitmap *LoadCustomImage(char *basename)
1138 char *filename = getCustomImageFilename(basename);
1141 if (filename == NULL)
1142 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1144 if ((new_bitmap = LoadImage(filename)) == NULL)
1145 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1150 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1152 char *filename = getCustomImageFilename(basename);
1155 if (filename == NULL) /* (should never happen) */
1157 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1161 if (strEqual(filename, bitmap->source_filename))
1163 /* The old and new image are the same (have the same filename and path).
1164 This usually means that this image does not exist in this graphic set
1165 and a fallback to the existing image is done. */
1170 if ((new_bitmap = LoadImage(filename)) == NULL)
1172 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1176 if (bitmap->width != new_bitmap->width ||
1177 bitmap->height != new_bitmap->height)
1179 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1181 FreeBitmap(new_bitmap);
1185 TransferBitmapPointers(new_bitmap, bitmap);
1189 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1191 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1193 #if defined(TARGET_SDL)
1194 SDLZoomBitmap(src_bitmap, dst_bitmap);
1196 X11ZoomBitmap(src_bitmap, dst_bitmap);
1202 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1203 boolean create_small_bitmaps)
1207 Bitmap *tmp_bitmap_1;
1208 Bitmap *tmp_bitmap_2;
1209 Bitmap *tmp_bitmap_4;
1210 Bitmap *tmp_bitmap_8;
1211 Bitmap *tmp_bitmap_16;
1212 Bitmap *tmp_bitmap_32;
1213 int width_1, height_1;
1214 int width_2, height_2;
1215 int width_4, height_4;
1216 int width_8, height_8;
1217 int width_16, height_16;
1219 int width_32, height_32;
1221 int new_width, new_height;
1223 /* calculate new image dimensions for normal sized image */
1224 width_1 = old_bitmap->width * zoom_factor;
1225 height_1 = old_bitmap->height * zoom_factor;
1227 /* get image with normal size (this might require scaling up) */
1228 if (zoom_factor != 1)
1229 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1231 tmp_bitmap_1 = old_bitmap;
1233 /* this is only needed to make compilers happy */
1234 tmp_bitmap_2 = NULL;
1235 tmp_bitmap_4 = NULL;
1236 tmp_bitmap_8 = NULL;
1237 tmp_bitmap_16 = NULL;
1238 tmp_bitmap_32 = NULL;
1240 if (create_small_bitmaps)
1242 /* calculate new image dimensions for small images */
1243 width_2 = width_1 / 2;
1244 height_2 = height_1 / 2;
1245 width_4 = width_1 / 4;
1246 height_4 = height_1 / 4;
1247 width_8 = width_1 / 8;
1248 height_8 = height_1 / 8;
1249 width_16 = width_1 / 16;
1250 height_16 = height_1 / 16;
1252 width_32 = width_1 / 32;
1253 height_32 = height_1 / 32;
1256 UPDATE_BUSY_STATE();
1258 /* get image with 1/2 of normal size (for use in the level editor) */
1259 if (zoom_factor != 2)
1260 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1262 tmp_bitmap_2 = old_bitmap;
1264 UPDATE_BUSY_STATE();
1266 /* get image with 1/4 of normal size (for use in the level editor) */
1267 if (zoom_factor != 4)
1268 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1270 tmp_bitmap_4 = old_bitmap;
1272 UPDATE_BUSY_STATE();
1274 /* get image with 1/8 of normal size (for use on the preview screen) */
1275 if (zoom_factor != 8)
1276 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1278 tmp_bitmap_8 = old_bitmap;
1280 UPDATE_BUSY_STATE();
1282 /* get image with 1/16 of normal size (for use on the preview screen) */
1283 if (zoom_factor != 16)
1284 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1286 tmp_bitmap_16 = old_bitmap;
1288 UPDATE_BUSY_STATE();
1290 /* get image with 1/32 of normal size (for use on the preview screen) */
1291 if (zoom_factor != 32)
1292 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1294 tmp_bitmap_32 = old_bitmap;
1296 UPDATE_BUSY_STATE();
1300 /* if image was scaled up, create new clipmask for normal size image */
1301 if (zoom_factor != 1)
1303 #if defined(TARGET_X11)
1304 if (old_bitmap->clip_mask)
1305 XFreePixmap(display, old_bitmap->clip_mask);
1307 old_bitmap->clip_mask =
1308 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1310 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1312 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1314 if (old_bitmap->surface_masked)
1315 SDL_FreeSurface(old_bitmap->surface_masked);
1317 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1318 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1319 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1320 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1321 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1326 if (create_small_bitmaps)
1328 new_width = width_1;
1329 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1331 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1333 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1334 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1336 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1337 width_1 / 2, height_1);
1338 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1339 3 * width_1 / 4, height_1);
1340 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1341 7 * width_1 / 8, height_1);
1342 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1343 15 * width_1 / 16, height_1);
1345 UPDATE_BUSY_STATE();
1349 new_width = width_1;
1350 new_height = height_1;
1352 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1355 if (create_small_bitmaps)
1357 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1358 if (zoom_factor != 1)
1359 FreeBitmap(tmp_bitmap_1);
1361 if (zoom_factor != 2)
1362 FreeBitmap(tmp_bitmap_2);
1364 if (zoom_factor != 4)
1365 FreeBitmap(tmp_bitmap_4);
1367 if (zoom_factor != 8)
1368 FreeBitmap(tmp_bitmap_8);
1370 if (zoom_factor != 16)
1371 FreeBitmap(tmp_bitmap_16);
1373 if (zoom_factor != 32)
1374 FreeBitmap(tmp_bitmap_32);
1377 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1378 #if defined(TARGET_SDL)
1379 swap_bitmap.surface = old_bitmap->surface;
1380 old_bitmap->surface = new_bitmap->surface;
1381 new_bitmap->surface = swap_bitmap.surface;
1383 swap_bitmap.drawable = old_bitmap->drawable;
1384 old_bitmap->drawable = new_bitmap->drawable;
1385 new_bitmap->drawable = swap_bitmap.drawable;
1388 old_bitmap->width = new_bitmap->width;
1389 old_bitmap->height = new_bitmap->height;
1392 /* this replaces all blit masks created when loading -- maybe optimize this */
1394 #if defined(TARGET_X11)
1395 if (old_bitmap->clip_mask)
1396 XFreePixmap(display, old_bitmap->clip_mask);
1398 old_bitmap->clip_mask =
1399 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1401 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1403 SDL_Surface *old_surface = old_bitmap->surface;
1405 if (old_bitmap->surface_masked)
1406 SDL_FreeSurface(old_bitmap->surface_masked);
1408 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1409 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1410 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1411 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1412 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1417 UPDATE_BUSY_STATE();
1419 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1422 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1424 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1427 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1429 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1433 /* ------------------------------------------------------------------------- */
1434 /* mouse pointer functions */
1435 /* ------------------------------------------------------------------------- */
1437 #if !defined(PLATFORM_MSDOS)
1438 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1439 /* XPM image definitions */
1440 static const char *cursor_image_none[] =
1442 /* width height num_colors chars_per_pixel */
1471 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1472 static const char *cursor_image_dot[] =
1474 /* width height num_colors chars_per_pixel */
1503 static const char **cursor_image_playfield = cursor_image_dot;
1505 /* some people complained about a "white dot" on the screen and thought it
1506 was a graphical error... OK, let's just remove the whole pointer :-) */
1507 static const char **cursor_image_playfield = cursor_image_none;
1510 #if defined(TARGET_SDL)
1511 static const int cursor_bit_order = BIT_ORDER_MSB;
1512 #elif defined(TARGET_X11_NATIVE)
1513 static const int cursor_bit_order = BIT_ORDER_LSB;
1516 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1518 struct MouseCursorInfo *cursor;
1519 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1520 int header_lines = 4;
1523 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1525 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1528 for (y = 0; y < cursor->width; y++)
1530 for (x = 0; x < cursor->height; x++)
1533 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1538 cursor->data[i] = cursor->mask[i] = 0;
1541 switch (image[header_lines + y][x])
1544 cursor->data[i] |= bit_mask;
1545 cursor->mask[i] |= bit_mask;
1549 cursor->mask[i] |= bit_mask;
1558 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1562 #endif /* !PLATFORM_MSDOS */
1564 void SetMouseCursor(int mode)
1566 #if !defined(PLATFORM_MSDOS)
1567 static struct MouseCursorInfo *cursor_none = NULL;
1568 static struct MouseCursorInfo *cursor_playfield = NULL;
1569 struct MouseCursorInfo *cursor_new;
1571 if (cursor_none == NULL)
1572 cursor_none = get_cursor_from_image(cursor_image_none);
1574 if (cursor_playfield == NULL)
1575 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1577 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1578 mode == CURSOR_NONE ? cursor_none :
1579 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1581 #if defined(TARGET_SDL)
1582 SDLSetMouseCursor(cursor_new);
1583 #elif defined(TARGET_X11_NATIVE)
1584 X11SetMouseCursor(cursor_new);
1590 /* ========================================================================= */
1591 /* audio functions */
1592 /* ========================================================================= */
1594 void OpenAudio(void)
1596 /* always start with reliable default values */
1597 audio.sound_available = FALSE;
1598 audio.music_available = FALSE;
1599 audio.loops_available = FALSE;
1601 audio.sound_enabled = FALSE;
1602 audio.sound_deactivated = FALSE;
1604 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1605 audio.mixer_pid = 0;
1606 audio.device_name = NULL;
1607 audio.device_fd = -1;
1609 audio.num_channels = 0;
1610 audio.music_channel = 0;
1611 audio.first_sound_channel = 0;
1613 #if defined(TARGET_SDL)
1615 #elif defined(PLATFORM_UNIX)
1617 #elif defined(PLATFORM_MSDOS)
1622 void CloseAudio(void)
1624 #if defined(TARGET_SDL)
1626 #elif defined(PLATFORM_UNIX)
1628 #elif defined(PLATFORM_MSDOS)
1632 audio.sound_enabled = FALSE;
1635 void SetAudioMode(boolean enabled)
1637 if (!audio.sound_available)
1640 audio.sound_enabled = enabled;
1644 /* ========================================================================= */
1645 /* event functions */
1646 /* ========================================================================= */
1648 void InitEventFilter(EventFilter filter_function)
1650 /* set event filter to filter out certain events */
1651 #if defined(TARGET_SDL)
1652 #if defined(TARGET_SDL2)
1653 SDL_SetEventFilter(filter_function, NULL);
1655 SDL_SetEventFilter(filter_function);
1660 boolean PendingEvent(void)
1662 #if defined(TARGET_SDL)
1663 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1665 return (XPending(display) ? TRUE : FALSE);
1669 void NextEvent(Event *event)
1671 #if defined(TARGET_SDL)
1672 SDLNextEvent(event);
1674 XNextEvent(display, event);
1678 void PeekEvent(Event *event)
1680 #if defined(TARGET_SDL)
1681 #if defined(TARGET_SDL2)
1682 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1684 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1687 XPeekEvent(display, event);
1691 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1693 #if defined(TARGET_SDL)
1694 #if defined(TARGET_SDL2)
1695 /* key up/down events in SDL2 do not return text characters anymore */
1696 return event->keysym.sym;
1700 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1701 (int)event->keysym.unicode,
1702 (int)event->keysym.sym,
1703 (int)SDL_GetModState());
1706 if (with_modifiers &&
1707 event->keysym.unicode > 0x0000 &&
1708 event->keysym.unicode < 0x2000)
1709 return event->keysym.unicode;
1711 return event->keysym.sym;
1717 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1718 (int)XLookupKeysym(event, event->state),
1719 (int)XLookupKeysym(event, 0));
1723 return XLookupKeysym(event, event->state);
1725 return XLookupKeysym(event, 0);
1729 KeyMod HandleKeyModState(Key key, int key_status)
1731 static KeyMod current_modifiers = KMOD_None;
1733 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1735 KeyMod new_modifier = KMOD_None;
1740 new_modifier = KMOD_Shift_L;
1743 new_modifier = KMOD_Shift_R;
1745 case KSYM_Control_L:
1746 new_modifier = KMOD_Control_L;
1748 case KSYM_Control_R:
1749 new_modifier = KMOD_Control_R;
1752 new_modifier = KMOD_Meta_L;
1755 new_modifier = KMOD_Meta_R;
1758 new_modifier = KMOD_Alt_L;
1761 new_modifier = KMOD_Alt_R;
1767 if (key_status == KEY_PRESSED)
1768 current_modifiers |= new_modifier;
1770 current_modifiers &= ~new_modifier;
1773 return current_modifiers;
1776 KeyMod GetKeyModState()
1778 #if defined(TARGET_SDL)
1779 return (KeyMod)SDL_GetModState();
1781 return HandleKeyModState(KSYM_UNDEFINED, 0);
1785 KeyMod GetKeyModStateFromEvents()
1787 /* always use key modifier state as tracked from key events (this is needed
1788 if the modifier key event was injected into the event queue, but the key
1789 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1790 query the keys as held pressed on the keyboard) -- this case is currently
1791 only used to filter out clipboard insert events from "True X-Mouse" tool */
1793 return HandleKeyModState(KSYM_UNDEFINED, 0);
1796 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1798 if (event->type != EVENT_CLIENTMESSAGE)
1801 #if defined(TARGET_SDL)
1802 return TRUE; /* the only possible message here is SDL_QUIT */
1803 #elif defined(PLATFORM_UNIX)
1804 if ((event->window == window->drawable) &&
1805 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1813 /* ========================================================================= */
1814 /* joystick functions */
1815 /* ========================================================================= */
1817 void InitJoysticks()
1821 #if defined(NO_JOYSTICK)
1822 return; /* joysticks generally deactivated by compile-time directive */
1825 /* always start with reliable default values */
1826 joystick.status = JOYSTICK_NOT_AVAILABLE;
1827 for (i = 0; i < MAX_PLAYERS; i++)
1828 joystick.fd[i] = -1; /* joystick device closed */
1830 #if defined(TARGET_SDL)
1832 #elif defined(PLATFORM_UNIX)
1833 UnixInitJoysticks();
1834 #elif defined(PLATFORM_MSDOS)
1835 MSDOSInitJoysticks();
1839 for (i = 0; i < MAX_PLAYERS; i++)
1840 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1844 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1846 #if defined(TARGET_SDL)
1847 return SDLReadJoystick(nr, x, y, b1, b2);
1848 #elif defined(PLATFORM_UNIX)
1849 return UnixReadJoystick(nr, x, y, b1, b2);
1850 #elif defined(PLATFORM_MSDOS)
1851 return MSDOSReadJoystick(nr, x, y, b1, b2);