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 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
711 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
712 but is already fixed in SVN and should therefore finally be fixed with
713 the next official SDL release, which is probably version 1.2.14.) */
715 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
716 #if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
717 if (src_bitmap == dst_bitmap)
719 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
721 /* needed when blitting directly to same bitmap -- should not be needed with
722 recent SDL libraries, but apparently does not work in 1.2.11 directly */
724 static Bitmap *tmp_bitmap = NULL;
725 static int tmp_bitmap_xsize = 0;
726 static int tmp_bitmap_ysize = 0;
728 /* start with largest static bitmaps for initial bitmap size ... */
729 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
731 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
732 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
735 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
736 if (src_bitmap->width > tmp_bitmap_xsize ||
737 src_bitmap->height > tmp_bitmap_ysize)
739 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
740 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
742 FreeBitmap(tmp_bitmap);
747 if (tmp_bitmap == NULL)
748 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
751 sysCopyArea(src_bitmap, tmp_bitmap,
752 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
753 sysCopyArea(tmp_bitmap, dst_bitmap,
754 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
763 if (dst_x < gfx.sx + gfx.sxsize)
764 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
765 FrameCounter, dst_x, dst_y, width, height);
768 sysCopyArea(src_bitmap, dst_bitmap,
769 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
772 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
773 int src_x, int src_y, int src_width, int src_height,
774 int dst_x, int dst_y, int dst_width, int dst_height)
776 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
777 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
778 int dst_xsize = dst_width;
779 int dst_ysize = dst_height;
780 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
781 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
784 for (y = 0; y < src_ysteps; y++)
786 for (x = 0; x < src_xsteps; x++)
788 int draw_x = dst_x + x * src_xsize;
789 int draw_y = dst_y + y * src_ysize;
790 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
791 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
793 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
799 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
800 int fade_mode, int fade_delay, int post_delay,
801 void (*draw_border_function)(void))
804 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
805 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
809 #if defined(TARGET_SDL)
810 SDLFadeRectangle(bitmap_cross, x, y, width, height,
811 fade_mode, fade_delay, post_delay, draw_border_function);
813 X11FadeRectangle(bitmap_cross, x, y, width, height,
814 fade_mode, fade_delay, post_delay, draw_border_function);
818 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
821 if (DrawingDeactivated(x, y, width, height))
825 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
828 /* skip if rectangle starts outside bitmap */
829 if (x >= bitmap->width ||
833 /* clip if rectangle overlaps bitmap */
834 if (x + width > bitmap->width)
835 width = bitmap->width - x;
836 if (y + height > bitmap->height)
837 height = bitmap->height - y;
840 sysFillRectangle(bitmap, x, y, width, height, color);
843 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
845 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
848 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
849 int width, int height)
851 if (DrawingOnBackground(x, y))
852 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
854 ClearRectangle(bitmap, x, y, width, height);
857 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
859 #if defined(TARGET_X11)
862 bitmap->clip_gc = clip_gc;
863 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
868 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
870 #if defined(TARGET_X11)
873 bitmap->clip_gc = clip_gc;
874 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
879 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
880 int src_x, int src_y, int width, int height,
881 int dst_x, int dst_y)
883 if (DrawingDeactivated(dst_x, dst_y, width, height))
886 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
887 dst_x, dst_y, BLIT_MASKED);
890 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
891 int src_x, int src_y, int width, int height,
892 int dst_x, int dst_y)
894 if (DrawingOnBackground(dst_x, dst_y))
896 /* draw background */
897 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
900 /* draw foreground */
901 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
902 dst_x - src_x, dst_y - src_y);
903 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
907 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
911 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
914 #if defined(TARGET_SDL)
915 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
917 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
921 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
924 #if defined(TARGET_SDL)
925 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
927 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
931 #if !defined(TARGET_X11_NATIVE)
932 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
933 int to_x, int to_y, Pixel pixel, int line_width)
937 for (x = 0; x < line_width; x++)
939 for (y = 0; y < line_width; y++)
941 int dx = x - line_width / 2;
942 int dy = y - line_width / 2;
944 if ((x == 0 && y == 0) ||
945 (x == 0 && y == line_width - 1) ||
946 (x == line_width - 1 && y == 0) ||
947 (x == line_width - 1 && y == line_width - 1))
950 #if defined(TARGET_SDL)
952 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
953 #elif defined(TARGET_ALLEGRO)
954 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
955 to_x + dx, to_y + dy, pixel);
962 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
964 #if !defined(TARGET_X11_NATIVE)
968 for (i = 0; i < num_points - 1; i++)
969 DrawLine(bitmap, points[i].x, points[i].y,
970 points[i + 1].x, points[i + 1].y, pixel, line_width);
973 SDLDrawLines(bitmap->surface, points, num_points, pixel);
976 XSetForeground(display, bitmap->line_gc[1], pixel);
977 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
978 (XPoint *)points, num_points, CoordModeOrigin);
982 Pixel GetPixel(Bitmap *bitmap, int x, int y)
984 if (x < 0 || x >= bitmap->width ||
985 y < 0 || y >= bitmap->height)
988 #if defined(TARGET_SDL)
989 return SDLGetPixel(bitmap, x, y);
990 #elif defined(TARGET_ALLEGRO)
991 return AllegroGetPixel(bitmap->drawable, x, y);
993 return X11GetPixel(bitmap, x, y);
997 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
998 unsigned int color_g, unsigned int color_b)
1000 #if defined(TARGET_SDL)
1001 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1002 #elif defined(TARGET_ALLEGRO)
1003 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1005 return X11GetPixelFromRGB(color_r, color_g, color_b);
1009 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1011 unsigned int color_r = (color >> 16) & 0xff;
1012 unsigned int color_g = (color >> 8) & 0xff;
1013 unsigned int color_b = (color >> 0) & 0xff;
1015 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1018 /* execute all pending screen drawing operations */
1019 void FlushDisplay(void)
1021 #if !defined(TARGET_SDL)
1026 /* execute and wait for all pending screen drawing operations */
1027 void SyncDisplay(void)
1029 #if !defined(TARGET_SDL)
1030 XSync(display, FALSE);
1034 void KeyboardAutoRepeatOn(void)
1036 #if defined(TARGET_SDL)
1037 #if defined(TARGET_SDL2)
1038 keyrepeat_status = TRUE;
1040 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1041 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1042 SDL_EnableUNICODE(1);
1046 XAutoRepeatOn(display);
1050 void KeyboardAutoRepeatOff(void)
1052 #if defined(TARGET_SDL)
1053 #if defined(TARGET_SDL2)
1054 keyrepeat_status = FALSE;
1056 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1057 SDL_EnableUNICODE(0);
1061 XAutoRepeatOff(display);
1065 boolean PointerInWindow(DrawWindow *window)
1067 #if defined(TARGET_SDL)
1075 /* if XQueryPointer() returns False, the pointer
1076 is not on the same screen as the specified window */
1077 return XQueryPointer(display, window->drawable, &root, &child,
1078 &root_x, &root_y, &win_x, &win_y, &mask);
1082 boolean SetVideoMode(boolean fullscreen)
1084 #if defined(TARGET_SDL)
1085 return SDLSetVideoMode(&backbuffer, fullscreen);
1087 boolean success = TRUE;
1089 if (fullscreen && video.fullscreen_available)
1091 Error(ERR_WARN, "fullscreen not available in X11 version");
1093 /* display error message only once */
1094 video.fullscreen_available = FALSE;
1103 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1105 #if defined(TARGET_SDL)
1106 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1107 (!fullscreen && video.fullscreen_enabled))
1108 fullscreen = SetVideoMode(fullscreen);
1114 Bitmap *LoadImage(char *filename)
1118 #if defined(TARGET_SDL)
1119 new_bitmap = SDLLoadImage(filename);
1121 new_bitmap = X11LoadImage(filename);
1125 new_bitmap->source_filename = getStringCopy(filename);
1130 Bitmap *LoadCustomImage(char *basename)
1132 char *filename = getCustomImageFilename(basename);
1135 if (filename == NULL)
1136 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1138 if ((new_bitmap = LoadImage(filename)) == NULL)
1139 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1144 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1146 char *filename = getCustomImageFilename(basename);
1149 if (filename == NULL) /* (should never happen) */
1151 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1155 if (strEqual(filename, bitmap->source_filename))
1157 /* The old and new image are the same (have the same filename and path).
1158 This usually means that this image does not exist in this graphic set
1159 and a fallback to the existing image is done. */
1164 if ((new_bitmap = LoadImage(filename)) == NULL)
1166 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1170 if (bitmap->width != new_bitmap->width ||
1171 bitmap->height != new_bitmap->height)
1173 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1175 FreeBitmap(new_bitmap);
1179 TransferBitmapPointers(new_bitmap, bitmap);
1183 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1185 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1187 #if defined(TARGET_SDL)
1188 SDLZoomBitmap(src_bitmap, dst_bitmap);
1190 X11ZoomBitmap(src_bitmap, dst_bitmap);
1196 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1197 boolean create_small_bitmaps)
1201 Bitmap *tmp_bitmap_1;
1202 Bitmap *tmp_bitmap_2;
1203 Bitmap *tmp_bitmap_4;
1204 Bitmap *tmp_bitmap_8;
1205 Bitmap *tmp_bitmap_16;
1206 Bitmap *tmp_bitmap_32;
1207 int width_1, height_1;
1208 int width_2, height_2;
1209 int width_4, height_4;
1210 int width_8, height_8;
1211 int width_16, height_16;
1213 int width_32, height_32;
1215 int new_width, new_height;
1217 /* calculate new image dimensions for normal sized image */
1218 width_1 = old_bitmap->width * zoom_factor;
1219 height_1 = old_bitmap->height * zoom_factor;
1221 /* get image with normal size (this might require scaling up) */
1222 if (zoom_factor != 1)
1223 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1225 tmp_bitmap_1 = old_bitmap;
1227 /* this is only needed to make compilers happy */
1228 tmp_bitmap_2 = NULL;
1229 tmp_bitmap_4 = NULL;
1230 tmp_bitmap_8 = NULL;
1231 tmp_bitmap_16 = NULL;
1232 tmp_bitmap_32 = NULL;
1234 if (create_small_bitmaps)
1236 /* calculate new image dimensions for small images */
1237 width_2 = width_1 / 2;
1238 height_2 = height_1 / 2;
1239 width_4 = width_1 / 4;
1240 height_4 = height_1 / 4;
1241 width_8 = width_1 / 8;
1242 height_8 = height_1 / 8;
1243 width_16 = width_1 / 16;
1244 height_16 = height_1 / 16;
1246 width_32 = width_1 / 32;
1247 height_32 = height_1 / 32;
1250 UPDATE_BUSY_STATE();
1252 /* get image with 1/2 of normal size (for use in the level editor) */
1253 if (zoom_factor != 2)
1254 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1256 tmp_bitmap_2 = old_bitmap;
1258 UPDATE_BUSY_STATE();
1260 /* get image with 1/4 of normal size (for use in the level editor) */
1261 if (zoom_factor != 4)
1262 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1264 tmp_bitmap_4 = old_bitmap;
1266 UPDATE_BUSY_STATE();
1268 /* get image with 1/8 of normal size (for use on the preview screen) */
1269 if (zoom_factor != 8)
1270 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1272 tmp_bitmap_8 = old_bitmap;
1274 UPDATE_BUSY_STATE();
1276 /* get image with 1/16 of normal size (for use on the preview screen) */
1277 if (zoom_factor != 16)
1278 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1280 tmp_bitmap_16 = old_bitmap;
1282 UPDATE_BUSY_STATE();
1284 /* get image with 1/32 of normal size (for use on the preview screen) */
1285 if (zoom_factor != 32)
1286 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1288 tmp_bitmap_32 = old_bitmap;
1290 UPDATE_BUSY_STATE();
1294 /* if image was scaled up, create new clipmask for normal size image */
1295 if (zoom_factor != 1)
1297 #if defined(TARGET_X11)
1298 if (old_bitmap->clip_mask)
1299 XFreePixmap(display, old_bitmap->clip_mask);
1301 old_bitmap->clip_mask =
1302 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1304 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1306 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1308 if (old_bitmap->surface_masked)
1309 SDL_FreeSurface(old_bitmap->surface_masked);
1311 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1312 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1313 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1314 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1315 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1320 if (create_small_bitmaps)
1322 new_width = width_1;
1323 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1325 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1327 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1328 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1330 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1331 width_1 / 2, height_1);
1332 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1333 3 * width_1 / 4, height_1);
1334 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1335 7 * width_1 / 8, height_1);
1336 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1337 15 * width_1 / 16, height_1);
1339 UPDATE_BUSY_STATE();
1343 new_width = width_1;
1344 new_height = height_1;
1346 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1349 if (create_small_bitmaps)
1351 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1352 if (zoom_factor != 1)
1353 FreeBitmap(tmp_bitmap_1);
1355 if (zoom_factor != 2)
1356 FreeBitmap(tmp_bitmap_2);
1358 if (zoom_factor != 4)
1359 FreeBitmap(tmp_bitmap_4);
1361 if (zoom_factor != 8)
1362 FreeBitmap(tmp_bitmap_8);
1364 if (zoom_factor != 16)
1365 FreeBitmap(tmp_bitmap_16);
1367 if (zoom_factor != 32)
1368 FreeBitmap(tmp_bitmap_32);
1371 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1372 #if defined(TARGET_SDL)
1373 swap_bitmap.surface = old_bitmap->surface;
1374 old_bitmap->surface = new_bitmap->surface;
1375 new_bitmap->surface = swap_bitmap.surface;
1377 swap_bitmap.drawable = old_bitmap->drawable;
1378 old_bitmap->drawable = new_bitmap->drawable;
1379 new_bitmap->drawable = swap_bitmap.drawable;
1382 old_bitmap->width = new_bitmap->width;
1383 old_bitmap->height = new_bitmap->height;
1386 /* this replaces all blit masks created when loading -- maybe optimize this */
1388 #if defined(TARGET_X11)
1389 if (old_bitmap->clip_mask)
1390 XFreePixmap(display, old_bitmap->clip_mask);
1392 old_bitmap->clip_mask =
1393 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1395 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1397 SDL_Surface *old_surface = old_bitmap->surface;
1399 if (old_bitmap->surface_masked)
1400 SDL_FreeSurface(old_bitmap->surface_masked);
1402 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1403 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1404 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1405 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1406 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1411 UPDATE_BUSY_STATE();
1413 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1416 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1418 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1421 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1423 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1427 /* ------------------------------------------------------------------------- */
1428 /* mouse pointer functions */
1429 /* ------------------------------------------------------------------------- */
1431 #if !defined(PLATFORM_MSDOS)
1432 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1433 /* XPM image definitions */
1434 static const char *cursor_image_none[] =
1436 /* width height num_colors chars_per_pixel */
1465 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1466 static const char *cursor_image_dot[] =
1468 /* width height num_colors chars_per_pixel */
1497 static const char **cursor_image_playfield = cursor_image_dot;
1499 /* some people complained about a "white dot" on the screen and thought it
1500 was a graphical error... OK, let's just remove the whole pointer :-) */
1501 static const char **cursor_image_playfield = cursor_image_none;
1504 #if defined(TARGET_SDL)
1505 static const int cursor_bit_order = BIT_ORDER_MSB;
1506 #elif defined(TARGET_X11_NATIVE)
1507 static const int cursor_bit_order = BIT_ORDER_LSB;
1510 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1512 struct MouseCursorInfo *cursor;
1513 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1514 int header_lines = 4;
1517 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1519 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1522 for (y = 0; y < cursor->width; y++)
1524 for (x = 0; x < cursor->height; x++)
1527 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1532 cursor->data[i] = cursor->mask[i] = 0;
1535 switch (image[header_lines + y][x])
1538 cursor->data[i] |= bit_mask;
1539 cursor->mask[i] |= bit_mask;
1543 cursor->mask[i] |= bit_mask;
1552 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1556 #endif /* !PLATFORM_MSDOS */
1558 void SetMouseCursor(int mode)
1560 #if !defined(PLATFORM_MSDOS)
1561 static struct MouseCursorInfo *cursor_none = NULL;
1562 static struct MouseCursorInfo *cursor_playfield = NULL;
1563 struct MouseCursorInfo *cursor_new;
1565 if (cursor_none == NULL)
1566 cursor_none = get_cursor_from_image(cursor_image_none);
1568 if (cursor_playfield == NULL)
1569 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1571 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1572 mode == CURSOR_NONE ? cursor_none :
1573 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1575 #if defined(TARGET_SDL)
1576 SDLSetMouseCursor(cursor_new);
1577 #elif defined(TARGET_X11_NATIVE)
1578 X11SetMouseCursor(cursor_new);
1584 /* ========================================================================= */
1585 /* audio functions */
1586 /* ========================================================================= */
1588 void OpenAudio(void)
1590 /* always start with reliable default values */
1591 audio.sound_available = FALSE;
1592 audio.music_available = FALSE;
1593 audio.loops_available = FALSE;
1595 audio.sound_enabled = FALSE;
1596 audio.sound_deactivated = FALSE;
1598 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1599 audio.mixer_pid = 0;
1600 audio.device_name = NULL;
1601 audio.device_fd = -1;
1603 audio.num_channels = 0;
1604 audio.music_channel = 0;
1605 audio.first_sound_channel = 0;
1607 #if defined(TARGET_SDL)
1609 #elif defined(PLATFORM_UNIX)
1611 #elif defined(PLATFORM_MSDOS)
1616 void CloseAudio(void)
1618 #if defined(TARGET_SDL)
1620 #elif defined(PLATFORM_UNIX)
1622 #elif defined(PLATFORM_MSDOS)
1626 audio.sound_enabled = FALSE;
1629 void SetAudioMode(boolean enabled)
1631 if (!audio.sound_available)
1634 audio.sound_enabled = enabled;
1638 /* ========================================================================= */
1639 /* event functions */
1640 /* ========================================================================= */
1642 void InitEventFilter(EventFilter filter_function)
1644 /* set event filter to filter out certain events */
1645 #if defined(TARGET_SDL)
1646 #if defined(TARGET_SDL2)
1647 SDL_SetEventFilter(filter_function, NULL);
1649 SDL_SetEventFilter(filter_function);
1654 boolean PendingEvent(void)
1656 #if defined(TARGET_SDL)
1657 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1659 return (XPending(display) ? TRUE : FALSE);
1663 void NextEvent(Event *event)
1665 #if defined(TARGET_SDL)
1666 SDLNextEvent(event);
1668 XNextEvent(display, event);
1672 void PeekEvent(Event *event)
1674 #if defined(TARGET_SDL)
1675 #if defined(TARGET_SDL2)
1676 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1678 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1681 XPeekEvent(display, event);
1685 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1687 #if defined(TARGET_SDL)
1688 #if defined(TARGET_SDL2)
1689 /* key up/down events in SDL2 do not return text characters anymore */
1690 return event->keysym.sym;
1694 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1695 (int)event->keysym.unicode,
1696 (int)event->keysym.sym,
1697 (int)SDL_GetModState());
1700 if (with_modifiers &&
1701 event->keysym.unicode > 0x0000 &&
1702 event->keysym.unicode < 0x2000)
1703 return event->keysym.unicode;
1705 return event->keysym.sym;
1711 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1712 (int)XLookupKeysym(event, event->state),
1713 (int)XLookupKeysym(event, 0));
1717 return XLookupKeysym(event, event->state);
1719 return XLookupKeysym(event, 0);
1723 KeyMod HandleKeyModState(Key key, int key_status)
1725 static KeyMod current_modifiers = KMOD_None;
1727 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1729 KeyMod new_modifier = KMOD_None;
1734 new_modifier = KMOD_Shift_L;
1737 new_modifier = KMOD_Shift_R;
1739 case KSYM_Control_L:
1740 new_modifier = KMOD_Control_L;
1742 case KSYM_Control_R:
1743 new_modifier = KMOD_Control_R;
1746 new_modifier = KMOD_Meta_L;
1749 new_modifier = KMOD_Meta_R;
1752 new_modifier = KMOD_Alt_L;
1755 new_modifier = KMOD_Alt_R;
1761 if (key_status == KEY_PRESSED)
1762 current_modifiers |= new_modifier;
1764 current_modifiers &= ~new_modifier;
1767 return current_modifiers;
1770 KeyMod GetKeyModState()
1772 #if defined(TARGET_SDL)
1773 return (KeyMod)SDL_GetModState();
1775 return HandleKeyModState(KSYM_UNDEFINED, 0);
1779 KeyMod GetKeyModStateFromEvents()
1781 /* always use key modifier state as tracked from key events (this is needed
1782 if the modifier key event was injected into the event queue, but the key
1783 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1784 query the keys as held pressed on the keyboard) -- this case is currently
1785 only used to filter out clipboard insert events from "True X-Mouse" tool */
1787 return HandleKeyModState(KSYM_UNDEFINED, 0);
1790 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1792 if (event->type != EVENT_CLIENTMESSAGE)
1795 #if defined(TARGET_SDL)
1796 return TRUE; /* the only possible message here is SDL_QUIT */
1797 #elif defined(PLATFORM_UNIX)
1798 if ((event->window == window->drawable) &&
1799 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1807 /* ========================================================================= */
1808 /* joystick functions */
1809 /* ========================================================================= */
1811 void InitJoysticks()
1815 #if defined(NO_JOYSTICK)
1816 return; /* joysticks generally deactivated by compile-time directive */
1819 /* always start with reliable default values */
1820 joystick.status = JOYSTICK_NOT_AVAILABLE;
1821 for (i = 0; i < MAX_PLAYERS; i++)
1822 joystick.fd[i] = -1; /* joystick device closed */
1824 #if defined(TARGET_SDL)
1826 #elif defined(PLATFORM_UNIX)
1827 UnixInitJoysticks();
1828 #elif defined(PLATFORM_MSDOS)
1829 MSDOSInitJoysticks();
1833 for (i = 0; i < MAX_PLAYERS; i++)
1834 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1838 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1840 #if defined(TARGET_SDL)
1841 return SDLReadJoystick(nr, x, y, b1, b2);
1842 #elif defined(PLATFORM_UNIX)
1843 return UnixReadJoystick(nr, x, y, b1, b2);
1844 #elif defined(PLATFORM_MSDOS)
1845 return MSDOSReadJoystick(nr, x, y, b1, b2);