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 #if defined(PLATFORM_MSDOS)
136 #if defined(PLATFORM_MACOSX)
137 updateUserGameDataDir();
143 #if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
148 #if defined(TARGET_SDL)
149 #if defined(TARGET_SDL2)
150 int sdl_init_flags = SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE;
152 int sdl_init_flags = SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE;
155 if (SDL_Init(sdl_init_flags) < 0)
156 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
162 void ClosePlatformDependentStuff(void)
164 #if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
168 #if defined(PLATFORM_MSDOS)
173 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
174 int real_sx, int real_sy,
175 int full_sxsize, int full_sysize,
176 Bitmap *field_save_buffer)
182 gfx.real_sx = real_sx;
183 gfx.real_sy = real_sy;
184 gfx.full_sxsize = full_sxsize;
185 gfx.full_sysize = full_sysize;
187 gfx.field_save_buffer = field_save_buffer;
190 gfx.background_bitmap = NULL;
191 gfx.background_bitmap_mask = REDRAW_NONE;
194 SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
195 SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
198 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
206 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
214 void InitGfxWindowInfo(int win_xsize, int win_ysize)
216 gfx.win_xsize = win_xsize;
217 gfx.win_ysize = win_ysize;
220 gfx.background_bitmap_mask = REDRAW_NONE;
222 ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize, DEFAULT_DEPTH);
226 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
228 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
229 /* 2009-03-24: also (temporarily?) used for overlapping blit workaround */
230 gfx.scrollbuffer_width = scrollbuffer_width;
231 gfx.scrollbuffer_height = scrollbuffer_height;
234 void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height)
236 gfx.clipping_enabled = enabled;
239 gfx.clip_width = width;
240 gfx.clip_height = height;
243 void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
245 gfx.draw_busy_anim_function = draw_busy_anim_function;
248 void InitGfxCustomArtworkInfo()
250 gfx.override_level_graphics = FALSE;
251 gfx.override_level_sounds = FALSE;
252 gfx.override_level_music = FALSE;
254 gfx.draw_init_text = TRUE;
257 void SetDrawDeactivationMask(int draw_deactivation_mask)
259 gfx.draw_deactivation_mask = draw_deactivation_mask;
262 void SetDrawBackgroundMask(int draw_background_mask)
264 gfx.draw_background_mask = draw_background_mask;
269 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
270 int dest_x, int dest_y, int width, int height)
272 int bitmap_xsize = width;
273 int bitmap_ysize = height;
274 int tile_xsize = tile->width;
275 int tile_ysize = tile->height;
276 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
277 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
280 for (y = 0; y < tile_ysteps; y++)
282 for (x = 0; x < tile_xsteps; x++)
284 int draw_x = dest_x + x * tile_xsize;
285 int draw_y = dest_y + y * tile_ysize;
286 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
287 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
289 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
294 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
296 if (background_bitmap_tile != NULL)
297 gfx.background_bitmap_mask |= mask;
299 gfx.background_bitmap_mask &= ~mask;
302 if (gfx.background_bitmap == NULL)
303 gfx.background_bitmap = CreateBitmap(video.width, video.height,
307 if (background_bitmap_tile == NULL) /* empty background requested */
310 if (mask == REDRAW_ALL)
311 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
312 0, 0, video.width, video.height);
313 else if (mask == REDRAW_FIELD)
314 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
315 gfx.real_sx, gfx.real_sy,
316 gfx.full_sxsize, gfx.full_sysize);
317 else if (mask == REDRAW_DOOR_1)
319 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
321 gfx.dxsize, gfx.dysize);
327 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
329 if (background_bitmap_tile != NULL)
330 gfx.background_bitmap_mask |= mask;
332 gfx.background_bitmap_mask &= ~mask;
335 if (gfx.background_bitmap == NULL)
336 gfx.background_bitmap = CreateBitmap(video.width, video.height,
340 if (background_bitmap_tile == NULL) /* empty background requested */
343 if (mask == REDRAW_ALL)
344 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
345 0, 0, video.width, video.height);
346 else if (mask == REDRAW_FIELD)
347 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
348 gfx.real_sx, gfx.real_sy, gfx.full_sxsize, gfx.full_sysize);
349 else if (mask == REDRAW_DOOR_1)
351 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
352 gfx.dx, gfx.dy, gfx.dxsize, gfx.dysize);
358 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
360 /* remove every mask before setting mask for window */
361 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
362 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
363 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
366 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
368 /* remove window area mask before setting mask for main area */
369 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
370 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
371 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
374 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
376 /* remove window area mask before setting mask for door area */
377 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
378 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
379 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
383 /* ========================================================================= */
384 /* video functions */
385 /* ========================================================================= */
387 inline static int GetRealDepth(int depth)
389 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
392 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
393 int width, int height, Pixel color)
395 #if defined(TARGET_SDL)
396 SDLFillRectangle(bitmap, x, y, width, height, color);
398 X11FillRectangle(bitmap, x, y, width, height, color);
402 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
403 int src_x, int src_y, int width, int height,
404 int dst_x, int dst_y, int mask_mode)
406 #if defined(TARGET_SDL)
407 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
408 dst_x, dst_y, mask_mode);
410 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
411 dst_x, dst_y, mask_mode);
415 void InitVideoDisplay(void)
417 #if defined(TARGET_SDL)
418 SDLInitVideoDisplay();
420 X11InitVideoDisplay();
424 void CloseVideoDisplay(void)
426 KeyboardAutoRepeatOn();
428 #if defined(TARGET_SDL)
429 SDL_QuitSubSystem(SDL_INIT_VIDEO);
432 XCloseDisplay(display);
436 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
439 video.height = height;
440 video.depth = GetRealDepth(depth);
442 video.fullscreen_available = FULLSCREEN_STATUS;
443 video.fullscreen_enabled = FALSE;
445 video.fullscreen_mode_current = NULL;
446 video.fullscreen_modes = NULL;
449 #if defined(TARGET_SDL)
450 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
452 X11InitVideoBuffer(&backbuffer, &window);
458 inline static void FreeBitmapPointers(Bitmap *bitmap)
463 #if defined(TARGET_SDL)
464 SDLFreeBitmapPointers(bitmap);
466 X11FreeBitmapPointers(bitmap);
469 checked_free(bitmap->source_filename);
470 bitmap->source_filename = NULL;
473 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
476 if (src_bitmap == NULL || dst_bitmap == NULL)
479 FreeBitmapPointers(dst_bitmap);
481 *dst_bitmap = *src_bitmap;
484 void FreeBitmap(Bitmap *bitmap)
489 FreeBitmapPointers(bitmap);
494 Bitmap *CreateBitmapStruct(void)
496 #if defined(TARGET_SDL)
497 return checked_calloc(sizeof(struct SDLSurfaceInfo));
499 return checked_calloc(sizeof(struct X11DrawableInfo));
503 Bitmap *CreateBitmap(int width, int height, int depth)
505 Bitmap *new_bitmap = CreateBitmapStruct();
506 int real_width = MAX(1, width); /* prevent zero bitmap width */
507 int real_height = MAX(1, height); /* prevent zero bitmap height */
508 int real_depth = GetRealDepth(depth);
510 #if defined(TARGET_SDL)
511 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
513 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
516 new_bitmap->width = real_width;
517 new_bitmap->height = real_height;
522 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
524 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
528 *bitmap = new_bitmap;
532 TransferBitmapPointers(new_bitmap, *bitmap);
537 void CloseWindow(DrawWindow *window)
539 #if defined(TARGET_X11)
540 X11CloseWindow(window);
544 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
547 if (draw_mask == REDRAW_NONE)
550 if (draw_mask & REDRAW_ALL)
553 if ((draw_mask & REDRAW_FIELD) &&
554 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
557 if ((draw_mask & REDRAW_DOOR_1) &&
558 x >= gfx.dx && y < gfx.dy + gfx.dysize)
561 if ((draw_mask & REDRAW_DOOR_2) &&
562 x >= gfx.dx && y >= gfx.vy)
568 boolean DrawingDeactivated(int x, int y, int width, int height)
570 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
573 boolean DrawingOnBackground(int x, int y)
575 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
576 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
579 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
580 int *width, int *height, boolean is_dest)
583 int clip_x, clip_y, clip_width, clip_height;
585 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
587 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
588 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
589 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
590 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
596 clip_width = bitmap->width;
597 clip_height = bitmap->height;
600 /* skip if rectangle completely outside bitmap */
602 if (*x + *width <= clip_x ||
603 *y + *height <= clip_y ||
604 *x >= clip_x + clip_width ||
605 *y >= clip_y + clip_height)
608 /* clip if rectangle overlaps bitmap */
612 *width -= clip_x - *x;
615 else if (*x + *width > clip_x + clip_width)
617 *width = clip_x + clip_width - *x;
622 *height -= clip_y - *y;
625 else if (*y + *height > clip_y + clip_height)
627 *height = clip_y + clip_height - *y;
634 /* skip if rectangle completely outside bitmap */
636 if (*x + *width <= 0 ||
638 *x >= bitmap->width ||
639 *y >= bitmap->height)
642 /* clip if rectangle overlaps bitmap */
649 else if (*x + *width > bitmap->width)
651 *width = bitmap->width - *x;
659 else if (*y + *height > bitmap->height)
661 *height = bitmap->height - *y;
668 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
669 int src_x, int src_y, int width, int height,
670 int dst_x, int dst_y)
672 int dst_x_unclipped = dst_x;
673 int dst_y_unclipped = dst_y;
675 if (DrawingDeactivated(dst_x, dst_y, width, height))
679 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
680 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
683 /* source x/y might need adjustment if destination x/y was clipped top/left */
684 src_x += dst_x - dst_x_unclipped;
685 src_y += dst_y - dst_y_unclipped;
688 /* skip if rectangle starts outside bitmap */
689 if (src_x >= src_bitmap->width ||
690 src_y >= src_bitmap->height ||
691 dst_x >= dst_bitmap->width ||
692 dst_y >= dst_bitmap->height)
695 /* clip if rectangle overlaps bitmap */
696 if (src_x + width > src_bitmap->width)
697 width = src_bitmap->width - src_x;
698 if (src_y + height > src_bitmap->height)
699 height = src_bitmap->height - src_y;
700 if (dst_x + width > dst_bitmap->width)
701 width = dst_bitmap->width - dst_x;
702 if (dst_y + height > dst_bitmap->height)
703 height = dst_bitmap->height - dst_y;
707 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
708 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
709 but is already fixed in SVN and should therefore finally be fixed with
710 the next official SDL release, which is probably version 1.2.14.) */
712 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
713 #if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
714 if (src_bitmap == dst_bitmap)
716 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
718 /* needed when blitting directly to same bitmap -- should not be needed with
719 recent SDL libraries, but apparently does not work in 1.2.11 directly */
721 static Bitmap *tmp_bitmap = NULL;
722 static int tmp_bitmap_xsize = 0;
723 static int tmp_bitmap_ysize = 0;
725 /* start with largest static bitmaps for initial bitmap size ... */
726 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
728 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
729 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
732 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
733 if (src_bitmap->width > tmp_bitmap_xsize ||
734 src_bitmap->height > tmp_bitmap_ysize)
736 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
737 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
739 FreeBitmap(tmp_bitmap);
744 if (tmp_bitmap == NULL)
745 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
748 sysCopyArea(src_bitmap, tmp_bitmap,
749 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
750 sysCopyArea(tmp_bitmap, dst_bitmap,
751 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
760 if (dst_x < gfx.sx + gfx.sxsize)
761 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
762 FrameCounter, dst_x, dst_y, width, height);
765 sysCopyArea(src_bitmap, dst_bitmap,
766 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
769 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
770 int src_x, int src_y, int src_width, int src_height,
771 int dst_x, int dst_y, int dst_width, int dst_height)
773 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
774 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
775 int dst_xsize = dst_width;
776 int dst_ysize = dst_height;
777 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
778 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
781 for (y = 0; y < src_ysteps; y++)
783 for (x = 0; x < src_xsteps; x++)
785 int draw_x = dst_x + x * src_xsize;
786 int draw_y = dst_y + y * src_ysize;
787 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
788 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
790 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
796 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
797 int fade_mode, int fade_delay, int post_delay,
798 void (*draw_border_function)(void))
801 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
802 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
806 #if defined(TARGET_SDL)
807 SDLFadeRectangle(bitmap_cross, x, y, width, height,
808 fade_mode, fade_delay, post_delay, draw_border_function);
810 X11FadeRectangle(bitmap_cross, x, y, width, height,
811 fade_mode, fade_delay, post_delay, draw_border_function);
815 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
818 if (DrawingDeactivated(x, y, width, height))
822 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
825 /* skip if rectangle starts outside bitmap */
826 if (x >= bitmap->width ||
830 /* clip if rectangle overlaps bitmap */
831 if (x + width > bitmap->width)
832 width = bitmap->width - x;
833 if (y + height > bitmap->height)
834 height = bitmap->height - y;
837 sysFillRectangle(bitmap, x, y, width, height, color);
840 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
842 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
845 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
846 int width, int height)
848 if (DrawingOnBackground(x, y))
849 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
851 ClearRectangle(bitmap, x, y, width, height);
854 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
856 #if defined(TARGET_X11)
859 bitmap->clip_gc = clip_gc;
860 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
865 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
867 #if defined(TARGET_X11)
870 bitmap->clip_gc = clip_gc;
871 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
876 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
877 int src_x, int src_y, int width, int height,
878 int dst_x, int dst_y)
880 if (DrawingDeactivated(dst_x, dst_y, width, height))
883 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
884 dst_x, dst_y, BLIT_MASKED);
887 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
888 int src_x, int src_y, int width, int height,
889 int dst_x, int dst_y)
891 if (DrawingOnBackground(dst_x, dst_y))
893 /* draw background */
894 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
897 /* draw foreground */
898 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
899 dst_x - src_x, dst_y - src_y);
900 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
904 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
908 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
911 #if defined(TARGET_SDL)
912 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
914 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
918 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
921 #if defined(TARGET_SDL)
922 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
924 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
928 #if !defined(TARGET_X11_NATIVE)
929 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
930 int to_x, int to_y, Pixel pixel, int line_width)
934 for (x = 0; x < line_width; x++)
936 for (y = 0; y < line_width; y++)
938 int dx = x - line_width / 2;
939 int dy = y - line_width / 2;
941 if ((x == 0 && y == 0) ||
942 (x == 0 && y == line_width - 1) ||
943 (x == line_width - 1 && y == 0) ||
944 (x == line_width - 1 && y == line_width - 1))
947 #if defined(TARGET_SDL)
949 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
950 #elif defined(TARGET_ALLEGRO)
951 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
952 to_x + dx, to_y + dy, pixel);
959 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
961 #if !defined(TARGET_X11_NATIVE)
965 for (i = 0; i < num_points - 1; i++)
966 DrawLine(bitmap, points[i].x, points[i].y,
967 points[i + 1].x, points[i + 1].y, pixel, line_width);
970 SDLDrawLines(bitmap->surface, points, num_points, pixel);
973 XSetForeground(display, bitmap->line_gc[1], pixel);
974 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
975 (XPoint *)points, num_points, CoordModeOrigin);
979 Pixel GetPixel(Bitmap *bitmap, int x, int y)
981 if (x < 0 || x >= bitmap->width ||
982 y < 0 || y >= bitmap->height)
985 #if defined(TARGET_SDL)
986 return SDLGetPixel(bitmap, x, y);
987 #elif defined(TARGET_ALLEGRO)
988 return AllegroGetPixel(bitmap->drawable, x, y);
990 return X11GetPixel(bitmap, x, y);
994 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
995 unsigned int color_g, unsigned int color_b)
997 #if defined(TARGET_SDL)
998 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
999 #elif defined(TARGET_ALLEGRO)
1000 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1002 return X11GetPixelFromRGB(color_r, color_g, color_b);
1006 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1008 unsigned int color_r = (color >> 16) & 0xff;
1009 unsigned int color_g = (color >> 8) & 0xff;
1010 unsigned int color_b = (color >> 0) & 0xff;
1012 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1015 /* execute all pending screen drawing operations */
1016 void FlushDisplay(void)
1018 #if !defined(TARGET_SDL)
1023 /* execute and wait for all pending screen drawing operations */
1024 void SyncDisplay(void)
1026 #if !defined(TARGET_SDL)
1027 XSync(display, FALSE);
1031 void KeyboardAutoRepeatOn(void)
1033 #if defined(TARGET_SDL)
1034 #if defined(TARGET_SDL2)
1035 keyrepeat_status = TRUE;
1037 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1038 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1039 SDL_EnableUNICODE(1);
1043 XAutoRepeatOn(display);
1047 void KeyboardAutoRepeatOff(void)
1049 #if defined(TARGET_SDL)
1050 #if defined(TARGET_SDL2)
1051 keyrepeat_status = FALSE;
1053 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1054 SDL_EnableUNICODE(0);
1058 XAutoRepeatOff(display);
1062 boolean PointerInWindow(DrawWindow *window)
1064 #if defined(TARGET_SDL)
1072 /* if XQueryPointer() returns False, the pointer
1073 is not on the same screen as the specified window */
1074 return XQueryPointer(display, window->drawable, &root, &child,
1075 &root_x, &root_y, &win_x, &win_y, &mask);
1079 boolean SetVideoMode(boolean fullscreen)
1081 #if defined(TARGET_SDL)
1082 return SDLSetVideoMode(&backbuffer, fullscreen);
1084 boolean success = TRUE;
1086 if (fullscreen && video.fullscreen_available)
1088 Error(ERR_WARN, "fullscreen not available in X11 version");
1090 /* display error message only once */
1091 video.fullscreen_available = FALSE;
1100 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1102 #if defined(TARGET_SDL)
1103 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1104 (!fullscreen && video.fullscreen_enabled))
1105 fullscreen = SetVideoMode(fullscreen);
1111 Bitmap *LoadImage(char *filename)
1115 #if defined(TARGET_SDL)
1116 new_bitmap = SDLLoadImage(filename);
1118 new_bitmap = X11LoadImage(filename);
1122 new_bitmap->source_filename = getStringCopy(filename);
1127 Bitmap *LoadCustomImage(char *basename)
1129 char *filename = getCustomImageFilename(basename);
1132 if (filename == NULL)
1133 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1135 if ((new_bitmap = LoadImage(filename)) == NULL)
1136 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1141 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1143 char *filename = getCustomImageFilename(basename);
1146 if (filename == NULL) /* (should never happen) */
1148 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1152 if (strEqual(filename, bitmap->source_filename))
1154 /* The old and new image are the same (have the same filename and path).
1155 This usually means that this image does not exist in this graphic set
1156 and a fallback to the existing image is done. */
1161 if ((new_bitmap = LoadImage(filename)) == NULL)
1163 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1167 if (bitmap->width != new_bitmap->width ||
1168 bitmap->height != new_bitmap->height)
1170 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1172 FreeBitmap(new_bitmap);
1176 TransferBitmapPointers(new_bitmap, bitmap);
1180 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1182 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1184 #if defined(TARGET_SDL)
1185 SDLZoomBitmap(src_bitmap, dst_bitmap);
1187 X11ZoomBitmap(src_bitmap, dst_bitmap);
1193 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1194 boolean create_small_bitmaps)
1198 Bitmap *tmp_bitmap_1;
1199 Bitmap *tmp_bitmap_2;
1200 Bitmap *tmp_bitmap_4;
1201 Bitmap *tmp_bitmap_8;
1202 Bitmap *tmp_bitmap_16;
1203 Bitmap *tmp_bitmap_32;
1204 int width_1, height_1;
1205 int width_2, height_2;
1206 int width_4, height_4;
1207 int width_8, height_8;
1208 int width_16, height_16;
1210 int width_32, height_32;
1212 int new_width, new_height;
1214 /* calculate new image dimensions for normal sized image */
1215 width_1 = old_bitmap->width * zoom_factor;
1216 height_1 = old_bitmap->height * zoom_factor;
1218 /* get image with normal size (this might require scaling up) */
1219 if (zoom_factor != 1)
1220 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1222 tmp_bitmap_1 = old_bitmap;
1224 /* this is only needed to make compilers happy */
1225 tmp_bitmap_2 = NULL;
1226 tmp_bitmap_4 = NULL;
1227 tmp_bitmap_8 = NULL;
1228 tmp_bitmap_16 = NULL;
1229 tmp_bitmap_32 = NULL;
1231 if (create_small_bitmaps)
1233 /* calculate new image dimensions for small images */
1234 width_2 = width_1 / 2;
1235 height_2 = height_1 / 2;
1236 width_4 = width_1 / 4;
1237 height_4 = height_1 / 4;
1238 width_8 = width_1 / 8;
1239 height_8 = height_1 / 8;
1240 width_16 = width_1 / 16;
1241 height_16 = height_1 / 16;
1243 width_32 = width_1 / 32;
1244 height_32 = height_1 / 32;
1247 UPDATE_BUSY_STATE();
1249 /* get image with 1/2 of normal size (for use in the level editor) */
1250 if (zoom_factor != 2)
1251 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1253 tmp_bitmap_2 = old_bitmap;
1255 UPDATE_BUSY_STATE();
1257 /* get image with 1/4 of normal size (for use in the level editor) */
1258 if (zoom_factor != 4)
1259 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1261 tmp_bitmap_4 = old_bitmap;
1263 UPDATE_BUSY_STATE();
1265 /* get image with 1/8 of normal size (for use on the preview screen) */
1266 if (zoom_factor != 8)
1267 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1269 tmp_bitmap_8 = old_bitmap;
1271 UPDATE_BUSY_STATE();
1273 /* get image with 1/16 of normal size (for use on the preview screen) */
1274 if (zoom_factor != 16)
1275 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1277 tmp_bitmap_16 = old_bitmap;
1279 UPDATE_BUSY_STATE();
1281 /* get image with 1/32 of normal size (for use on the preview screen) */
1282 if (zoom_factor != 32)
1283 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1285 tmp_bitmap_32 = old_bitmap;
1287 UPDATE_BUSY_STATE();
1291 /* if image was scaled up, create new clipmask for normal size image */
1292 if (zoom_factor != 1)
1294 #if defined(TARGET_X11)
1295 if (old_bitmap->clip_mask)
1296 XFreePixmap(display, old_bitmap->clip_mask);
1298 old_bitmap->clip_mask =
1299 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1301 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1303 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1305 if (old_bitmap->surface_masked)
1306 SDL_FreeSurface(old_bitmap->surface_masked);
1308 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1309 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1310 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1311 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1312 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1317 if (create_small_bitmaps)
1319 new_width = width_1;
1320 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1322 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1324 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1325 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1327 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1328 width_1 / 2, height_1);
1329 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1330 3 * width_1 / 4, height_1);
1331 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1332 7 * width_1 / 8, height_1);
1333 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1334 15 * width_1 / 16, height_1);
1336 UPDATE_BUSY_STATE();
1340 new_width = width_1;
1341 new_height = height_1;
1343 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1346 if (create_small_bitmaps)
1348 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1349 if (zoom_factor != 1)
1350 FreeBitmap(tmp_bitmap_1);
1352 if (zoom_factor != 2)
1353 FreeBitmap(tmp_bitmap_2);
1355 if (zoom_factor != 4)
1356 FreeBitmap(tmp_bitmap_4);
1358 if (zoom_factor != 8)
1359 FreeBitmap(tmp_bitmap_8);
1361 if (zoom_factor != 16)
1362 FreeBitmap(tmp_bitmap_16);
1364 if (zoom_factor != 32)
1365 FreeBitmap(tmp_bitmap_32);
1368 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1369 #if defined(TARGET_SDL)
1370 swap_bitmap.surface = old_bitmap->surface;
1371 old_bitmap->surface = new_bitmap->surface;
1372 new_bitmap->surface = swap_bitmap.surface;
1374 swap_bitmap.drawable = old_bitmap->drawable;
1375 old_bitmap->drawable = new_bitmap->drawable;
1376 new_bitmap->drawable = swap_bitmap.drawable;
1379 old_bitmap->width = new_bitmap->width;
1380 old_bitmap->height = new_bitmap->height;
1383 /* this replaces all blit masks created when loading -- maybe optimize this */
1385 #if defined(TARGET_X11)
1386 if (old_bitmap->clip_mask)
1387 XFreePixmap(display, old_bitmap->clip_mask);
1389 old_bitmap->clip_mask =
1390 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1392 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1394 SDL_Surface *old_surface = old_bitmap->surface;
1396 if (old_bitmap->surface_masked)
1397 SDL_FreeSurface(old_bitmap->surface_masked);
1399 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1400 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1401 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1402 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1403 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1408 UPDATE_BUSY_STATE();
1410 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1413 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1415 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1418 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1420 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1424 /* ------------------------------------------------------------------------- */
1425 /* mouse pointer functions */
1426 /* ------------------------------------------------------------------------- */
1428 #if !defined(PLATFORM_MSDOS)
1429 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1430 /* XPM image definitions */
1431 static const char *cursor_image_none[] =
1433 /* width height num_colors chars_per_pixel */
1462 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1463 static const char *cursor_image_dot[] =
1465 /* width height num_colors chars_per_pixel */
1494 static const char **cursor_image_playfield = cursor_image_dot;
1496 /* some people complained about a "white dot" on the screen and thought it
1497 was a graphical error... OK, let's just remove the whole pointer :-) */
1498 static const char **cursor_image_playfield = cursor_image_none;
1501 #if defined(TARGET_SDL)
1502 static const int cursor_bit_order = BIT_ORDER_MSB;
1503 #elif defined(TARGET_X11_NATIVE)
1504 static const int cursor_bit_order = BIT_ORDER_LSB;
1507 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1509 struct MouseCursorInfo *cursor;
1510 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1511 int header_lines = 4;
1514 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1516 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1519 for (y = 0; y < cursor->width; y++)
1521 for (x = 0; x < cursor->height; x++)
1524 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1529 cursor->data[i] = cursor->mask[i] = 0;
1532 switch (image[header_lines + y][x])
1535 cursor->data[i] |= bit_mask;
1536 cursor->mask[i] |= bit_mask;
1540 cursor->mask[i] |= bit_mask;
1549 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1553 #endif /* !PLATFORM_MSDOS */
1555 void SetMouseCursor(int mode)
1557 #if !defined(PLATFORM_MSDOS)
1558 static struct MouseCursorInfo *cursor_none = NULL;
1559 static struct MouseCursorInfo *cursor_playfield = NULL;
1560 struct MouseCursorInfo *cursor_new;
1562 if (cursor_none == NULL)
1563 cursor_none = get_cursor_from_image(cursor_image_none);
1565 if (cursor_playfield == NULL)
1566 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1568 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1569 mode == CURSOR_NONE ? cursor_none :
1570 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1572 #if defined(TARGET_SDL)
1573 SDLSetMouseCursor(cursor_new);
1574 #elif defined(TARGET_X11_NATIVE)
1575 X11SetMouseCursor(cursor_new);
1581 /* ========================================================================= */
1582 /* audio functions */
1583 /* ========================================================================= */
1585 void OpenAudio(void)
1587 /* always start with reliable default values */
1588 audio.sound_available = FALSE;
1589 audio.music_available = FALSE;
1590 audio.loops_available = FALSE;
1592 audio.sound_enabled = FALSE;
1593 audio.sound_deactivated = FALSE;
1595 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1596 audio.mixer_pid = 0;
1597 audio.device_name = NULL;
1598 audio.device_fd = -1;
1600 audio.num_channels = 0;
1601 audio.music_channel = 0;
1602 audio.first_sound_channel = 0;
1604 #if defined(TARGET_SDL)
1606 #elif defined(PLATFORM_UNIX)
1608 #elif defined(PLATFORM_MSDOS)
1613 void CloseAudio(void)
1615 #if defined(TARGET_SDL)
1617 #elif defined(PLATFORM_UNIX)
1619 #elif defined(PLATFORM_MSDOS)
1623 audio.sound_enabled = FALSE;
1626 void SetAudioMode(boolean enabled)
1628 if (!audio.sound_available)
1631 audio.sound_enabled = enabled;
1635 /* ========================================================================= */
1636 /* event functions */
1637 /* ========================================================================= */
1639 void InitEventFilter(EventFilter filter_function)
1641 /* set event filter to filter out certain events */
1642 #if defined(TARGET_SDL)
1643 #if defined(TARGET_SDL2)
1644 SDL_SetEventFilter(filter_function, NULL);
1646 SDL_SetEventFilter(filter_function);
1651 boolean PendingEvent(void)
1653 #if defined(TARGET_SDL)
1654 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1656 return (XPending(display) ? TRUE : FALSE);
1660 void NextEvent(Event *event)
1662 #if defined(TARGET_SDL)
1663 SDLNextEvent(event);
1665 XNextEvent(display, event);
1669 void PeekEvent(Event *event)
1671 #if defined(TARGET_SDL)
1672 #if defined(TARGET_SDL2)
1673 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1675 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1678 XPeekEvent(display, event);
1682 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1684 #if defined(TARGET_SDL)
1685 #if defined(TARGET_SDL2)
1686 /* key up/down events in SDL2 do not return text characters anymore */
1687 return event->keysym.sym;
1691 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1692 (int)event->keysym.unicode,
1693 (int)event->keysym.sym,
1694 (int)SDL_GetModState());
1697 if (with_modifiers &&
1698 event->keysym.unicode > 0x0000 &&
1699 event->keysym.unicode < 0x2000)
1700 return event->keysym.unicode;
1702 return event->keysym.sym;
1708 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1709 (int)XLookupKeysym(event, event->state),
1710 (int)XLookupKeysym(event, 0));
1714 return XLookupKeysym(event, event->state);
1716 return XLookupKeysym(event, 0);
1720 KeyMod HandleKeyModState(Key key, int key_status)
1722 static KeyMod current_modifiers = KMOD_None;
1724 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1726 KeyMod new_modifier = KMOD_None;
1731 new_modifier = KMOD_Shift_L;
1734 new_modifier = KMOD_Shift_R;
1736 case KSYM_Control_L:
1737 new_modifier = KMOD_Control_L;
1739 case KSYM_Control_R:
1740 new_modifier = KMOD_Control_R;
1743 new_modifier = KMOD_Meta_L;
1746 new_modifier = KMOD_Meta_R;
1749 new_modifier = KMOD_Alt_L;
1752 new_modifier = KMOD_Alt_R;
1758 if (key_status == KEY_PRESSED)
1759 current_modifiers |= new_modifier;
1761 current_modifiers &= ~new_modifier;
1764 return current_modifiers;
1767 KeyMod GetKeyModState()
1769 #if defined(TARGET_SDL)
1770 return (KeyMod)SDL_GetModState();
1772 return HandleKeyModState(KSYM_UNDEFINED, 0);
1776 KeyMod GetKeyModStateFromEvents()
1778 /* always use key modifier state as tracked from key events (this is needed
1779 if the modifier key event was injected into the event queue, but the key
1780 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1781 query the keys as held pressed on the keyboard) -- this case is currently
1782 only used to filter out clipboard insert events from "True X-Mouse" tool */
1784 return HandleKeyModState(KSYM_UNDEFINED, 0);
1787 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1789 if (event->type != EVENT_CLIENTMESSAGE)
1792 #if defined(TARGET_SDL)
1793 return TRUE; /* the only possible message here is SDL_QUIT */
1794 #elif defined(PLATFORM_UNIX)
1795 if ((event->window == window->drawable) &&
1796 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1804 /* ========================================================================= */
1805 /* joystick functions */
1806 /* ========================================================================= */
1808 void InitJoysticks()
1812 #if defined(NO_JOYSTICK)
1813 return; /* joysticks generally deactivated by compile-time directive */
1816 /* always start with reliable default values */
1817 joystick.status = JOYSTICK_NOT_AVAILABLE;
1818 for (i = 0; i < MAX_PLAYERS; i++)
1819 joystick.fd[i] = -1; /* joystick device closed */
1821 #if defined(TARGET_SDL)
1823 #elif defined(PLATFORM_UNIX)
1824 UnixInitJoysticks();
1825 #elif defined(PLATFORM_MSDOS)
1826 MSDOSInitJoysticks();
1830 for (i = 0; i < MAX_PLAYERS; i++)
1831 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1835 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1837 #if defined(TARGET_SDL)
1838 return SDLReadJoystick(nr, x, y, b1, b2);
1839 #elif defined(PLATFORM_UNIX)
1840 return UnixReadJoystick(nr, x, y, b1, b2);
1841 #elif defined(PLATFORM_MSDOS)
1842 return MSDOSReadJoystick(nr, x, y, b1, b2);