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 #if defined(TARGET_SDL)
453 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
455 X11InitVideoBuffer(&backbuffer, &window);
461 inline static void FreeBitmapPointers(Bitmap *bitmap)
466 #if defined(TARGET_SDL)
467 SDLFreeBitmapPointers(bitmap);
469 X11FreeBitmapPointers(bitmap);
472 checked_free(bitmap->source_filename);
473 bitmap->source_filename = NULL;
476 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
479 if (src_bitmap == NULL || dst_bitmap == NULL)
482 FreeBitmapPointers(dst_bitmap);
484 *dst_bitmap = *src_bitmap;
487 void FreeBitmap(Bitmap *bitmap)
492 FreeBitmapPointers(bitmap);
497 Bitmap *CreateBitmapStruct(void)
499 #if defined(TARGET_SDL)
500 return checked_calloc(sizeof(struct SDLSurfaceInfo));
502 return checked_calloc(sizeof(struct X11DrawableInfo));
506 Bitmap *CreateBitmap(int width, int height, int depth)
508 Bitmap *new_bitmap = CreateBitmapStruct();
509 int real_width = MAX(1, width); /* prevent zero bitmap width */
510 int real_height = MAX(1, height); /* prevent zero bitmap height */
511 int real_depth = GetRealDepth(depth);
513 #if defined(TARGET_SDL)
514 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
516 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
519 new_bitmap->width = real_width;
520 new_bitmap->height = real_height;
525 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
527 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
531 *bitmap = new_bitmap;
535 TransferBitmapPointers(new_bitmap, *bitmap);
540 void CloseWindow(DrawWindow *window)
542 #if defined(TARGET_X11)
543 X11CloseWindow(window);
547 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
550 if (draw_mask == REDRAW_NONE)
553 if (draw_mask & REDRAW_ALL)
556 if ((draw_mask & REDRAW_FIELD) &&
557 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
560 if ((draw_mask & REDRAW_DOOR_1) &&
561 x >= gfx.dx && y < gfx.dy + gfx.dysize)
564 if ((draw_mask & REDRAW_DOOR_2) &&
565 x >= gfx.dx && y >= gfx.vy)
571 boolean DrawingDeactivated(int x, int y, int width, int height)
573 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
576 boolean DrawingOnBackground(int x, int y)
578 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
579 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
582 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
583 int *width, int *height, boolean is_dest)
586 int clip_x, clip_y, clip_width, clip_height;
588 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
590 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
591 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
592 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
593 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
599 clip_width = bitmap->width;
600 clip_height = bitmap->height;
603 /* skip if rectangle completely outside bitmap */
605 if (*x + *width <= clip_x ||
606 *y + *height <= clip_y ||
607 *x >= clip_x + clip_width ||
608 *y >= clip_y + clip_height)
611 /* clip if rectangle overlaps bitmap */
615 *width -= clip_x - *x;
618 else if (*x + *width > clip_x + clip_width)
620 *width = clip_x + clip_width - *x;
625 *height -= clip_y - *y;
628 else if (*y + *height > clip_y + clip_height)
630 *height = clip_y + clip_height - *y;
637 /* skip if rectangle completely outside bitmap */
639 if (*x + *width <= 0 ||
641 *x >= bitmap->width ||
642 *y >= bitmap->height)
645 /* clip if rectangle overlaps bitmap */
652 else if (*x + *width > bitmap->width)
654 *width = bitmap->width - *x;
662 else if (*y + *height > bitmap->height)
664 *height = bitmap->height - *y;
671 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
672 int src_x, int src_y, int width, int height,
673 int dst_x, int dst_y)
675 int dst_x_unclipped = dst_x;
676 int dst_y_unclipped = dst_y;
678 if (DrawingDeactivated(dst_x, dst_y, width, height))
682 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
683 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
686 /* source x/y might need adjustment if destination x/y was clipped top/left */
687 src_x += dst_x - dst_x_unclipped;
688 src_y += dst_y - dst_y_unclipped;
691 /* skip if rectangle starts outside bitmap */
692 if (src_x >= src_bitmap->width ||
693 src_y >= src_bitmap->height ||
694 dst_x >= dst_bitmap->width ||
695 dst_y >= dst_bitmap->height)
698 /* clip if rectangle overlaps bitmap */
699 if (src_x + width > src_bitmap->width)
700 width = src_bitmap->width - src_x;
701 if (src_y + height > src_bitmap->height)
702 height = src_bitmap->height - src_y;
703 if (dst_x + width > dst_bitmap->width)
704 width = dst_bitmap->width - dst_x;
705 if (dst_y + height > dst_bitmap->height)
706 height = dst_bitmap->height - dst_y;
710 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
712 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
713 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
714 but is already fixed in SVN and should therefore finally be fixed with
715 the next official SDL release, which is probably version 1.2.14.) */
717 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
718 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
719 #if defined(TARGET_SDL2)
720 if (src_bitmap == dst_bitmap)
722 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
724 /* needed when blitting directly to same bitmap -- should not be needed with
725 recent SDL libraries, but apparently does not work in 1.2.11 directly */
727 static Bitmap *tmp_bitmap = NULL;
728 static int tmp_bitmap_xsize = 0;
729 static int tmp_bitmap_ysize = 0;
731 /* start with largest static bitmaps for initial bitmap size ... */
732 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
734 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
735 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
738 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
739 if (src_bitmap->width > tmp_bitmap_xsize ||
740 src_bitmap->height > tmp_bitmap_ysize)
742 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
743 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
745 FreeBitmap(tmp_bitmap);
750 if (tmp_bitmap == NULL)
751 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
754 sysCopyArea(src_bitmap, tmp_bitmap,
755 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
756 sysCopyArea(tmp_bitmap, dst_bitmap,
757 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
767 if (dst_x < gfx.sx + gfx.sxsize)
768 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
769 FrameCounter, dst_x, dst_y, width, height);
772 sysCopyArea(src_bitmap, dst_bitmap,
773 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
776 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
777 int src_x, int src_y, int src_width, int src_height,
778 int dst_x, int dst_y, int dst_width, int dst_height)
780 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
781 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
782 int dst_xsize = dst_width;
783 int dst_ysize = dst_height;
784 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
785 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
788 for (y = 0; y < src_ysteps; y++)
790 for (x = 0; x < src_xsteps; x++)
792 int draw_x = dst_x + x * src_xsize;
793 int draw_y = dst_y + y * src_ysize;
794 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
795 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
797 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
803 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
804 int fade_mode, int fade_delay, int post_delay,
805 void (*draw_border_function)(void))
808 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
809 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
813 #if defined(TARGET_SDL)
814 SDLFadeRectangle(bitmap_cross, x, y, width, height,
815 fade_mode, fade_delay, post_delay, draw_border_function);
817 X11FadeRectangle(bitmap_cross, x, y, width, height,
818 fade_mode, fade_delay, post_delay, draw_border_function);
822 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
825 if (DrawingDeactivated(x, y, width, height))
829 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
832 /* skip if rectangle starts outside bitmap */
833 if (x >= bitmap->width ||
837 /* clip if rectangle overlaps bitmap */
838 if (x + width > bitmap->width)
839 width = bitmap->width - x;
840 if (y + height > bitmap->height)
841 height = bitmap->height - y;
844 sysFillRectangle(bitmap, x, y, width, height, color);
847 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
849 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
852 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
853 int width, int height)
855 if (DrawingOnBackground(x, y))
856 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
858 ClearRectangle(bitmap, x, y, width, height);
861 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
863 #if defined(TARGET_X11)
866 bitmap->clip_gc = clip_gc;
867 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
872 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
874 #if defined(TARGET_X11)
877 bitmap->clip_gc = clip_gc;
878 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
883 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
884 int src_x, int src_y, int width, int height,
885 int dst_x, int dst_y)
887 if (DrawingDeactivated(dst_x, dst_y, width, height))
890 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
891 dst_x, dst_y, BLIT_MASKED);
894 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
895 int src_x, int src_y, int width, int height,
896 int dst_x, int dst_y)
898 if (DrawingOnBackground(dst_x, dst_y))
900 /* draw background */
901 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
904 /* draw foreground */
905 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
906 dst_x - src_x, dst_y - src_y);
907 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
911 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
915 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
918 #if defined(TARGET_SDL)
919 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
921 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
925 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
928 #if defined(TARGET_SDL)
929 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
931 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
935 #if !defined(TARGET_X11_NATIVE)
936 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
937 int to_x, int to_y, Pixel pixel, int line_width)
941 for (x = 0; x < line_width; x++)
943 for (y = 0; y < line_width; y++)
945 int dx = x - line_width / 2;
946 int dy = y - line_width / 2;
948 if ((x == 0 && y == 0) ||
949 (x == 0 && y == line_width - 1) ||
950 (x == line_width - 1 && y == 0) ||
951 (x == line_width - 1 && y == line_width - 1))
954 #if defined(TARGET_SDL)
956 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
957 #elif defined(TARGET_ALLEGRO)
958 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
959 to_x + dx, to_y + dy, pixel);
966 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
968 #if !defined(TARGET_X11_NATIVE)
972 for (i = 0; i < num_points - 1; i++)
973 DrawLine(bitmap, points[i].x, points[i].y,
974 points[i + 1].x, points[i + 1].y, pixel, line_width);
977 SDLDrawLines(bitmap->surface, points, num_points, pixel);
980 XSetForeground(display, bitmap->line_gc[1], pixel);
981 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
982 (XPoint *)points, num_points, CoordModeOrigin);
986 Pixel GetPixel(Bitmap *bitmap, int x, int y)
988 if (x < 0 || x >= bitmap->width ||
989 y < 0 || y >= bitmap->height)
992 #if defined(TARGET_SDL)
993 return SDLGetPixel(bitmap, x, y);
994 #elif defined(TARGET_ALLEGRO)
995 return AllegroGetPixel(bitmap->drawable, x, y);
997 return X11GetPixel(bitmap, x, y);
1001 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1002 unsigned int color_g, unsigned int color_b)
1004 #if defined(TARGET_SDL)
1005 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1006 #elif defined(TARGET_ALLEGRO)
1007 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1009 return X11GetPixelFromRGB(color_r, color_g, color_b);
1013 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1015 unsigned int color_r = (color >> 16) & 0xff;
1016 unsigned int color_g = (color >> 8) & 0xff;
1017 unsigned int color_b = (color >> 0) & 0xff;
1019 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1022 /* execute all pending screen drawing operations */
1023 void FlushDisplay(void)
1025 #if !defined(TARGET_SDL)
1030 /* execute and wait for all pending screen drawing operations */
1031 void SyncDisplay(void)
1033 #if !defined(TARGET_SDL)
1034 XSync(display, FALSE);
1038 void KeyboardAutoRepeatOn(void)
1040 #if defined(TARGET_SDL)
1041 #if defined(TARGET_SDL2)
1042 keyrepeat_status = TRUE;
1044 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1045 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1046 SDL_EnableUNICODE(1);
1050 XAutoRepeatOn(display);
1054 void KeyboardAutoRepeatOff(void)
1056 #if defined(TARGET_SDL)
1057 #if defined(TARGET_SDL2)
1058 keyrepeat_status = FALSE;
1060 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1061 SDL_EnableUNICODE(0);
1065 XAutoRepeatOff(display);
1069 boolean PointerInWindow(DrawWindow *window)
1071 #if defined(TARGET_SDL)
1079 /* if XQueryPointer() returns False, the pointer
1080 is not on the same screen as the specified window */
1081 return XQueryPointer(display, window->drawable, &root, &child,
1082 &root_x, &root_y, &win_x, &win_y, &mask);
1086 boolean SetVideoMode(boolean fullscreen)
1088 #if defined(TARGET_SDL)
1089 return SDLSetVideoMode(&backbuffer, fullscreen);
1091 boolean success = TRUE;
1093 if (fullscreen && video.fullscreen_available)
1095 Error(ERR_WARN, "fullscreen not available in X11 version");
1097 /* display error message only once */
1098 video.fullscreen_available = FALSE;
1107 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1109 #if defined(TARGET_SDL)
1110 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1111 (!fullscreen && video.fullscreen_enabled))
1112 fullscreen = SetVideoMode(fullscreen);
1118 Bitmap *LoadImage(char *filename)
1122 #if defined(TARGET_SDL)
1123 new_bitmap = SDLLoadImage(filename);
1125 new_bitmap = X11LoadImage(filename);
1129 new_bitmap->source_filename = getStringCopy(filename);
1134 Bitmap *LoadCustomImage(char *basename)
1136 char *filename = getCustomImageFilename(basename);
1139 if (filename == NULL)
1140 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1142 if ((new_bitmap = LoadImage(filename)) == NULL)
1143 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1148 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1150 char *filename = getCustomImageFilename(basename);
1153 if (filename == NULL) /* (should never happen) */
1155 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1159 if (strEqual(filename, bitmap->source_filename))
1161 /* The old and new image are the same (have the same filename and path).
1162 This usually means that this image does not exist in this graphic set
1163 and a fallback to the existing image is done. */
1168 if ((new_bitmap = LoadImage(filename)) == NULL)
1170 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1174 if (bitmap->width != new_bitmap->width ||
1175 bitmap->height != new_bitmap->height)
1177 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1179 FreeBitmap(new_bitmap);
1183 TransferBitmapPointers(new_bitmap, bitmap);
1187 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1189 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1191 #if defined(TARGET_SDL)
1192 SDLZoomBitmap(src_bitmap, dst_bitmap);
1194 X11ZoomBitmap(src_bitmap, dst_bitmap);
1200 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1201 boolean create_small_bitmaps)
1205 Bitmap *tmp_bitmap_1;
1206 Bitmap *tmp_bitmap_2;
1207 Bitmap *tmp_bitmap_4;
1208 Bitmap *tmp_bitmap_8;
1209 Bitmap *tmp_bitmap_16;
1210 Bitmap *tmp_bitmap_32;
1211 int width_1, height_1;
1212 int width_2, height_2;
1213 int width_4, height_4;
1214 int width_8, height_8;
1215 int width_16, height_16;
1217 int width_32, height_32;
1219 int new_width, new_height;
1221 /* calculate new image dimensions for normal sized image */
1222 width_1 = old_bitmap->width * zoom_factor;
1223 height_1 = old_bitmap->height * zoom_factor;
1225 /* get image with normal size (this might require scaling up) */
1226 if (zoom_factor != 1)
1227 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1229 tmp_bitmap_1 = old_bitmap;
1231 /* this is only needed to make compilers happy */
1232 tmp_bitmap_2 = NULL;
1233 tmp_bitmap_4 = NULL;
1234 tmp_bitmap_8 = NULL;
1235 tmp_bitmap_16 = NULL;
1236 tmp_bitmap_32 = NULL;
1238 if (create_small_bitmaps)
1240 /* calculate new image dimensions for small images */
1241 width_2 = width_1 / 2;
1242 height_2 = height_1 / 2;
1243 width_4 = width_1 / 4;
1244 height_4 = height_1 / 4;
1245 width_8 = width_1 / 8;
1246 height_8 = height_1 / 8;
1247 width_16 = width_1 / 16;
1248 height_16 = height_1 / 16;
1250 width_32 = width_1 / 32;
1251 height_32 = height_1 / 32;
1254 UPDATE_BUSY_STATE();
1256 /* get image with 1/2 of normal size (for use in the level editor) */
1257 if (zoom_factor != 2)
1258 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1260 tmp_bitmap_2 = old_bitmap;
1262 UPDATE_BUSY_STATE();
1264 /* get image with 1/4 of normal size (for use in the level editor) */
1265 if (zoom_factor != 4)
1266 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1268 tmp_bitmap_4 = old_bitmap;
1270 UPDATE_BUSY_STATE();
1272 /* get image with 1/8 of normal size (for use on the preview screen) */
1273 if (zoom_factor != 8)
1274 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1276 tmp_bitmap_8 = old_bitmap;
1278 UPDATE_BUSY_STATE();
1280 /* get image with 1/16 of normal size (for use on the preview screen) */
1281 if (zoom_factor != 16)
1282 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1284 tmp_bitmap_16 = old_bitmap;
1286 UPDATE_BUSY_STATE();
1288 /* get image with 1/32 of normal size (for use on the preview screen) */
1289 if (zoom_factor != 32)
1290 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1292 tmp_bitmap_32 = old_bitmap;
1294 UPDATE_BUSY_STATE();
1298 /* if image was scaled up, create new clipmask for normal size image */
1299 if (zoom_factor != 1)
1301 #if defined(TARGET_X11)
1302 if (old_bitmap->clip_mask)
1303 XFreePixmap(display, old_bitmap->clip_mask);
1305 old_bitmap->clip_mask =
1306 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1308 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1310 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1312 if (old_bitmap->surface_masked)
1313 SDL_FreeSurface(old_bitmap->surface_masked);
1315 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1316 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1317 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1318 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1319 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1324 if (create_small_bitmaps)
1326 new_width = width_1;
1327 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1329 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1331 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1332 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1334 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1335 width_1 / 2, height_1);
1336 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1337 3 * width_1 / 4, height_1);
1338 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1339 7 * width_1 / 8, height_1);
1340 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1341 15 * width_1 / 16, height_1);
1343 UPDATE_BUSY_STATE();
1347 new_width = width_1;
1348 new_height = height_1;
1350 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1353 if (create_small_bitmaps)
1355 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1356 if (zoom_factor != 1)
1357 FreeBitmap(tmp_bitmap_1);
1359 if (zoom_factor != 2)
1360 FreeBitmap(tmp_bitmap_2);
1362 if (zoom_factor != 4)
1363 FreeBitmap(tmp_bitmap_4);
1365 if (zoom_factor != 8)
1366 FreeBitmap(tmp_bitmap_8);
1368 if (zoom_factor != 16)
1369 FreeBitmap(tmp_bitmap_16);
1371 if (zoom_factor != 32)
1372 FreeBitmap(tmp_bitmap_32);
1375 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1376 #if defined(TARGET_SDL)
1377 swap_bitmap.surface = old_bitmap->surface;
1378 old_bitmap->surface = new_bitmap->surface;
1379 new_bitmap->surface = swap_bitmap.surface;
1381 swap_bitmap.drawable = old_bitmap->drawable;
1382 old_bitmap->drawable = new_bitmap->drawable;
1383 new_bitmap->drawable = swap_bitmap.drawable;
1386 old_bitmap->width = new_bitmap->width;
1387 old_bitmap->height = new_bitmap->height;
1390 /* this replaces all blit masks created when loading -- maybe optimize this */
1392 #if defined(TARGET_X11)
1393 if (old_bitmap->clip_mask)
1394 XFreePixmap(display, old_bitmap->clip_mask);
1396 old_bitmap->clip_mask =
1397 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1399 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1401 SDL_Surface *old_surface = old_bitmap->surface;
1403 if (old_bitmap->surface_masked)
1404 SDL_FreeSurface(old_bitmap->surface_masked);
1406 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1407 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1408 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1409 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1410 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1415 UPDATE_BUSY_STATE();
1417 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1420 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1422 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1425 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1427 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1431 /* ------------------------------------------------------------------------- */
1432 /* mouse pointer functions */
1433 /* ------------------------------------------------------------------------- */
1435 #if !defined(PLATFORM_MSDOS)
1436 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1437 /* XPM image definitions */
1438 static const char *cursor_image_none[] =
1440 /* width height num_colors chars_per_pixel */
1469 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1470 static const char *cursor_image_dot[] =
1472 /* width height num_colors chars_per_pixel */
1501 static const char **cursor_image_playfield = cursor_image_dot;
1503 /* some people complained about a "white dot" on the screen and thought it
1504 was a graphical error... OK, let's just remove the whole pointer :-) */
1505 static const char **cursor_image_playfield = cursor_image_none;
1508 #if defined(TARGET_SDL)
1509 static const int cursor_bit_order = BIT_ORDER_MSB;
1510 #elif defined(TARGET_X11_NATIVE)
1511 static const int cursor_bit_order = BIT_ORDER_LSB;
1514 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1516 struct MouseCursorInfo *cursor;
1517 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1518 int header_lines = 4;
1521 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1523 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1526 for (y = 0; y < cursor->width; y++)
1528 for (x = 0; x < cursor->height; x++)
1531 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1536 cursor->data[i] = cursor->mask[i] = 0;
1539 switch (image[header_lines + y][x])
1542 cursor->data[i] |= bit_mask;
1543 cursor->mask[i] |= bit_mask;
1547 cursor->mask[i] |= bit_mask;
1556 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1560 #endif /* !PLATFORM_MSDOS */
1562 void SetMouseCursor(int mode)
1564 #if !defined(PLATFORM_MSDOS)
1565 static struct MouseCursorInfo *cursor_none = NULL;
1566 static struct MouseCursorInfo *cursor_playfield = NULL;
1567 struct MouseCursorInfo *cursor_new;
1569 if (cursor_none == NULL)
1570 cursor_none = get_cursor_from_image(cursor_image_none);
1572 if (cursor_playfield == NULL)
1573 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1575 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1576 mode == CURSOR_NONE ? cursor_none :
1577 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1579 #if defined(TARGET_SDL)
1580 SDLSetMouseCursor(cursor_new);
1581 #elif defined(TARGET_X11_NATIVE)
1582 X11SetMouseCursor(cursor_new);
1588 /* ========================================================================= */
1589 /* audio functions */
1590 /* ========================================================================= */
1592 void OpenAudio(void)
1594 /* always start with reliable default values */
1595 audio.sound_available = FALSE;
1596 audio.music_available = FALSE;
1597 audio.loops_available = FALSE;
1599 audio.sound_enabled = FALSE;
1600 audio.sound_deactivated = FALSE;
1602 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1603 audio.mixer_pid = 0;
1604 audio.device_name = NULL;
1605 audio.device_fd = -1;
1607 audio.num_channels = 0;
1608 audio.music_channel = 0;
1609 audio.first_sound_channel = 0;
1611 #if defined(TARGET_SDL)
1613 #elif defined(PLATFORM_UNIX)
1615 #elif defined(PLATFORM_MSDOS)
1620 void CloseAudio(void)
1622 #if defined(TARGET_SDL)
1624 #elif defined(PLATFORM_UNIX)
1626 #elif defined(PLATFORM_MSDOS)
1630 audio.sound_enabled = FALSE;
1633 void SetAudioMode(boolean enabled)
1635 if (!audio.sound_available)
1638 audio.sound_enabled = enabled;
1642 /* ========================================================================= */
1643 /* event functions */
1644 /* ========================================================================= */
1646 void InitEventFilter(EventFilter filter_function)
1648 /* set event filter to filter out certain events */
1649 #if defined(TARGET_SDL)
1650 #if defined(TARGET_SDL2)
1651 SDL_SetEventFilter(filter_function, NULL);
1653 SDL_SetEventFilter(filter_function);
1658 boolean PendingEvent(void)
1660 #if defined(TARGET_SDL)
1661 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1663 return (XPending(display) ? TRUE : FALSE);
1667 void NextEvent(Event *event)
1669 #if defined(TARGET_SDL)
1670 SDLNextEvent(event);
1672 XNextEvent(display, event);
1676 void PeekEvent(Event *event)
1678 #if defined(TARGET_SDL)
1679 #if defined(TARGET_SDL2)
1680 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1682 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1685 XPeekEvent(display, event);
1689 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1691 #if defined(TARGET_SDL)
1692 #if defined(TARGET_SDL2)
1693 /* key up/down events in SDL2 do not return text characters anymore */
1694 return event->keysym.sym;
1698 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1699 (int)event->keysym.unicode,
1700 (int)event->keysym.sym,
1701 (int)SDL_GetModState());
1704 if (with_modifiers &&
1705 event->keysym.unicode > 0x0000 &&
1706 event->keysym.unicode < 0x2000)
1707 return event->keysym.unicode;
1709 return event->keysym.sym;
1715 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1716 (int)XLookupKeysym(event, event->state),
1717 (int)XLookupKeysym(event, 0));
1721 return XLookupKeysym(event, event->state);
1723 return XLookupKeysym(event, 0);
1727 KeyMod HandleKeyModState(Key key, int key_status)
1729 static KeyMod current_modifiers = KMOD_None;
1731 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1733 KeyMod new_modifier = KMOD_None;
1738 new_modifier = KMOD_Shift_L;
1741 new_modifier = KMOD_Shift_R;
1743 case KSYM_Control_L:
1744 new_modifier = KMOD_Control_L;
1746 case KSYM_Control_R:
1747 new_modifier = KMOD_Control_R;
1750 new_modifier = KMOD_Meta_L;
1753 new_modifier = KMOD_Meta_R;
1756 new_modifier = KMOD_Alt_L;
1759 new_modifier = KMOD_Alt_R;
1765 if (key_status == KEY_PRESSED)
1766 current_modifiers |= new_modifier;
1768 current_modifiers &= ~new_modifier;
1771 return current_modifiers;
1774 KeyMod GetKeyModState()
1776 #if defined(TARGET_SDL)
1777 return (KeyMod)SDL_GetModState();
1779 return HandleKeyModState(KSYM_UNDEFINED, 0);
1783 KeyMod GetKeyModStateFromEvents()
1785 /* always use key modifier state as tracked from key events (this is needed
1786 if the modifier key event was injected into the event queue, but the key
1787 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1788 query the keys as held pressed on the keyboard) -- this case is currently
1789 only used to filter out clipboard insert events from "True X-Mouse" tool */
1791 return HandleKeyModState(KSYM_UNDEFINED, 0);
1794 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1796 if (event->type != EVENT_CLIENTMESSAGE)
1799 #if defined(TARGET_SDL)
1800 return TRUE; /* the only possible message here is SDL_QUIT */
1801 #elif defined(PLATFORM_UNIX)
1802 if ((event->window == window->drawable) &&
1803 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1811 /* ========================================================================= */
1812 /* joystick functions */
1813 /* ========================================================================= */
1815 void InitJoysticks()
1819 #if defined(NO_JOYSTICK)
1820 return; /* joysticks generally deactivated by compile-time directive */
1823 /* always start with reliable default values */
1824 joystick.status = JOYSTICK_NOT_AVAILABLE;
1825 for (i = 0; i < MAX_PLAYERS; i++)
1826 joystick.fd[i] = -1; /* joystick device closed */
1828 #if defined(TARGET_SDL)
1830 #elif defined(PLATFORM_UNIX)
1831 UnixInitJoysticks();
1832 #elif defined(PLATFORM_MSDOS)
1833 MSDOSInitJoysticks();
1837 for (i = 0; i < MAX_PLAYERS; i++)
1838 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1842 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1844 #if defined(TARGET_SDL)
1845 return SDLReadJoystick(nr, x, y, b1, b2);
1846 #elif defined(PLATFORM_UNIX)
1847 return UnixReadJoystick(nr, x, y, b1, b2);
1848 #elif defined(PLATFORM_MSDOS)
1849 return MSDOSReadJoystick(nr, x, y, b1, b2);