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)
441 printf("::: InitVideoBuffer\n");
444 video.height = height;
445 video.depth = GetRealDepth(depth);
447 video.fullscreen_available = FULLSCREEN_STATUS;
448 video.fullscreen_enabled = FALSE;
449 // video.fullscreen_initial = FALSE;
451 video.fullscreen_mode_current = NULL;
452 video.fullscreen_modes = NULL;
455 video.window_scaling_available = WINDOW_SCALING_STATUS;
457 #if defined(TARGET_SDL)
458 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
460 X11InitVideoBuffer(&backbuffer, &window);
466 inline static void FreeBitmapPointers(Bitmap *bitmap)
471 #if defined(TARGET_SDL)
472 SDLFreeBitmapPointers(bitmap);
474 X11FreeBitmapPointers(bitmap);
477 checked_free(bitmap->source_filename);
478 bitmap->source_filename = NULL;
481 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
484 if (src_bitmap == NULL || dst_bitmap == NULL)
487 FreeBitmapPointers(dst_bitmap);
489 *dst_bitmap = *src_bitmap;
492 void FreeBitmap(Bitmap *bitmap)
497 FreeBitmapPointers(bitmap);
502 Bitmap *CreateBitmapStruct(void)
504 #if defined(TARGET_SDL)
505 return checked_calloc(sizeof(struct SDLSurfaceInfo));
507 return checked_calloc(sizeof(struct X11DrawableInfo));
511 Bitmap *CreateBitmap(int width, int height, int depth)
513 Bitmap *new_bitmap = CreateBitmapStruct();
514 int real_width = MAX(1, width); /* prevent zero bitmap width */
515 int real_height = MAX(1, height); /* prevent zero bitmap height */
516 int real_depth = GetRealDepth(depth);
518 #if defined(TARGET_SDL)
519 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
521 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
524 new_bitmap->width = real_width;
525 new_bitmap->height = real_height;
530 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
532 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
536 *bitmap = new_bitmap;
540 TransferBitmapPointers(new_bitmap, *bitmap);
545 void CloseWindow(DrawWindow *window)
547 #if defined(TARGET_X11)
548 X11CloseWindow(window);
552 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
555 if (draw_mask == REDRAW_NONE)
558 if (draw_mask & REDRAW_ALL)
561 if ((draw_mask & REDRAW_FIELD) &&
562 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
565 if ((draw_mask & REDRAW_DOOR_1) &&
566 x >= gfx.dx && y < gfx.dy + gfx.dysize)
569 if ((draw_mask & REDRAW_DOOR_2) &&
570 x >= gfx.dx && y >= gfx.vy)
576 boolean DrawingDeactivated(int x, int y, int width, int height)
578 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
581 boolean DrawingOnBackground(int x, int y)
583 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
584 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
587 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
588 int *width, int *height, boolean is_dest)
591 int clip_x, clip_y, clip_width, clip_height;
593 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
595 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
596 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
597 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
598 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
604 clip_width = bitmap->width;
605 clip_height = bitmap->height;
608 /* skip if rectangle completely outside bitmap */
610 if (*x + *width <= clip_x ||
611 *y + *height <= clip_y ||
612 *x >= clip_x + clip_width ||
613 *y >= clip_y + clip_height)
616 /* clip if rectangle overlaps bitmap */
620 *width -= clip_x - *x;
623 else if (*x + *width > clip_x + clip_width)
625 *width = clip_x + clip_width - *x;
630 *height -= clip_y - *y;
633 else if (*y + *height > clip_y + clip_height)
635 *height = clip_y + clip_height - *y;
642 /* skip if rectangle completely outside bitmap */
644 if (*x + *width <= 0 ||
646 *x >= bitmap->width ||
647 *y >= bitmap->height)
650 /* clip if rectangle overlaps bitmap */
657 else if (*x + *width > bitmap->width)
659 *width = bitmap->width - *x;
667 else if (*y + *height > bitmap->height)
669 *height = bitmap->height - *y;
676 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
677 int src_x, int src_y, int width, int height,
678 int dst_x, int dst_y)
680 int dst_x_unclipped = dst_x;
681 int dst_y_unclipped = dst_y;
683 if (DrawingDeactivated(dst_x, dst_y, width, height))
687 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
688 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
691 /* source x/y might need adjustment if destination x/y was clipped top/left */
692 src_x += dst_x - dst_x_unclipped;
693 src_y += dst_y - dst_y_unclipped;
696 /* skip if rectangle starts outside bitmap */
697 if (src_x >= src_bitmap->width ||
698 src_y >= src_bitmap->height ||
699 dst_x >= dst_bitmap->width ||
700 dst_y >= dst_bitmap->height)
703 /* clip if rectangle overlaps bitmap */
704 if (src_x + width > src_bitmap->width)
705 width = src_bitmap->width - src_x;
706 if (src_y + height > src_bitmap->height)
707 height = src_bitmap->height - src_y;
708 if (dst_x + width > dst_bitmap->width)
709 width = dst_bitmap->width - dst_x;
710 if (dst_y + height > dst_bitmap->height)
711 height = dst_bitmap->height - dst_y;
715 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
717 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
718 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
719 but is already fixed in SVN and should therefore finally be fixed with
720 the next official SDL release, which is probably version 1.2.14.) */
722 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
723 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
724 #if defined(TARGET_SDL2)
725 if (src_bitmap == dst_bitmap)
727 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
729 /* needed when blitting directly to same bitmap -- should not be needed with
730 recent SDL libraries, but apparently does not work in 1.2.11 directly */
732 static Bitmap *tmp_bitmap = NULL;
733 static int tmp_bitmap_xsize = 0;
734 static int tmp_bitmap_ysize = 0;
736 /* start with largest static bitmaps for initial bitmap size ... */
737 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
739 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
740 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
743 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
744 if (src_bitmap->width > tmp_bitmap_xsize ||
745 src_bitmap->height > tmp_bitmap_ysize)
747 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
748 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
750 FreeBitmap(tmp_bitmap);
755 if (tmp_bitmap == NULL)
756 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
759 sysCopyArea(src_bitmap, tmp_bitmap,
760 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
761 sysCopyArea(tmp_bitmap, dst_bitmap,
762 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
772 if (dst_x < gfx.sx + gfx.sxsize)
773 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
774 FrameCounter, dst_x, dst_y, width, height);
777 sysCopyArea(src_bitmap, dst_bitmap,
778 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
781 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
782 int src_x, int src_y, int src_width, int src_height,
783 int dst_x, int dst_y, int dst_width, int dst_height)
785 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
786 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
787 int dst_xsize = dst_width;
788 int dst_ysize = dst_height;
789 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
790 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
793 for (y = 0; y < src_ysteps; y++)
795 for (x = 0; x < src_xsteps; x++)
797 int draw_x = dst_x + x * src_xsize;
798 int draw_y = dst_y + y * src_ysize;
799 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
800 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
802 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
808 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
809 int fade_mode, int fade_delay, int post_delay,
810 void (*draw_border_function)(void))
813 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
814 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
818 #if defined(TARGET_SDL)
819 SDLFadeRectangle(bitmap_cross, x, y, width, height,
820 fade_mode, fade_delay, post_delay, draw_border_function);
822 X11FadeRectangle(bitmap_cross, x, y, width, height,
823 fade_mode, fade_delay, post_delay, draw_border_function);
827 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
830 if (DrawingDeactivated(x, y, width, height))
834 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
837 /* skip if rectangle starts outside bitmap */
838 if (x >= bitmap->width ||
842 /* clip if rectangle overlaps bitmap */
843 if (x + width > bitmap->width)
844 width = bitmap->width - x;
845 if (y + height > bitmap->height)
846 height = bitmap->height - y;
849 sysFillRectangle(bitmap, x, y, width, height, color);
852 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
854 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
857 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
858 int width, int height)
860 if (DrawingOnBackground(x, y))
861 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
863 ClearRectangle(bitmap, x, y, width, height);
866 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
868 #if defined(TARGET_X11)
871 bitmap->clip_gc = clip_gc;
872 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
877 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
879 #if defined(TARGET_X11)
882 bitmap->clip_gc = clip_gc;
883 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
888 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
889 int src_x, int src_y, int width, int height,
890 int dst_x, int dst_y)
892 if (DrawingDeactivated(dst_x, dst_y, width, height))
895 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
896 dst_x, dst_y, BLIT_MASKED);
899 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
900 int src_x, int src_y, int width, int height,
901 int dst_x, int dst_y)
903 if (DrawingOnBackground(dst_x, dst_y))
905 /* draw background */
906 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
909 /* draw foreground */
910 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
911 dst_x - src_x, dst_y - src_y);
912 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
916 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
920 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
923 #if defined(TARGET_SDL)
924 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
926 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
930 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
933 #if defined(TARGET_SDL)
934 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
936 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
940 #if !defined(TARGET_X11_NATIVE)
941 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
942 int to_x, int to_y, Pixel pixel, int line_width)
946 for (x = 0; x < line_width; x++)
948 for (y = 0; y < line_width; y++)
950 int dx = x - line_width / 2;
951 int dy = y - line_width / 2;
953 if ((x == 0 && y == 0) ||
954 (x == 0 && y == line_width - 1) ||
955 (x == line_width - 1 && y == 0) ||
956 (x == line_width - 1 && y == line_width - 1))
959 #if defined(TARGET_SDL)
961 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
962 #elif defined(TARGET_ALLEGRO)
963 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
964 to_x + dx, to_y + dy, pixel);
971 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
973 #if !defined(TARGET_X11_NATIVE)
977 for (i = 0; i < num_points - 1; i++)
978 DrawLine(bitmap, points[i].x, points[i].y,
979 points[i + 1].x, points[i + 1].y, pixel, line_width);
982 SDLDrawLines(bitmap->surface, points, num_points, pixel);
985 XSetForeground(display, bitmap->line_gc[1], pixel);
986 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
987 (XPoint *)points, num_points, CoordModeOrigin);
991 Pixel GetPixel(Bitmap *bitmap, int x, int y)
993 if (x < 0 || x >= bitmap->width ||
994 y < 0 || y >= bitmap->height)
997 #if defined(TARGET_SDL)
998 return SDLGetPixel(bitmap, x, y);
999 #elif defined(TARGET_ALLEGRO)
1000 return AllegroGetPixel(bitmap->drawable, x, y);
1002 return X11GetPixel(bitmap, x, y);
1006 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
1007 unsigned int color_g, unsigned int color_b)
1009 #if defined(TARGET_SDL)
1010 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
1011 #elif defined(TARGET_ALLEGRO)
1012 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
1014 return X11GetPixelFromRGB(color_r, color_g, color_b);
1018 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
1020 unsigned int color_r = (color >> 16) & 0xff;
1021 unsigned int color_g = (color >> 8) & 0xff;
1022 unsigned int color_b = (color >> 0) & 0xff;
1024 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
1027 /* execute all pending screen drawing operations */
1028 void FlushDisplay(void)
1030 #if !defined(TARGET_SDL)
1035 /* execute and wait for all pending screen drawing operations */
1036 void SyncDisplay(void)
1038 #if !defined(TARGET_SDL)
1039 XSync(display, FALSE);
1043 void KeyboardAutoRepeatOn(void)
1045 #if defined(TARGET_SDL)
1046 #if defined(TARGET_SDL2)
1047 keyrepeat_status = TRUE;
1049 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1050 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1051 SDL_EnableUNICODE(1);
1055 XAutoRepeatOn(display);
1059 void KeyboardAutoRepeatOff(void)
1061 #if defined(TARGET_SDL)
1062 #if defined(TARGET_SDL2)
1063 keyrepeat_status = FALSE;
1065 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1066 SDL_EnableUNICODE(0);
1070 XAutoRepeatOff(display);
1074 boolean PointerInWindow(DrawWindow *window)
1076 #if defined(TARGET_SDL)
1084 /* if XQueryPointer() returns False, the pointer
1085 is not on the same screen as the specified window */
1086 return XQueryPointer(display, window->drawable, &root, &child,
1087 &root_x, &root_y, &win_x, &win_y, &mask);
1091 boolean SetVideoMode(boolean fullscreen)
1093 #if defined(TARGET_SDL)
1094 return SDLSetVideoMode(&backbuffer, fullscreen);
1096 boolean success = TRUE;
1098 if (fullscreen && video.fullscreen_available)
1100 Error(ERR_WARN, "fullscreen not available in X11 version");
1102 /* display error message only once */
1103 video.fullscreen_available = FALSE;
1112 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1114 #if defined(TARGET_SDL)
1115 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1116 (!fullscreen && video.fullscreen_enabled))
1117 fullscreen = SetVideoMode(fullscreen);
1123 Bitmap *LoadImage(char *filename)
1127 #if defined(TARGET_SDL)
1128 new_bitmap = SDLLoadImage(filename);
1130 new_bitmap = X11LoadImage(filename);
1134 new_bitmap->source_filename = getStringCopy(filename);
1139 Bitmap *LoadCustomImage(char *basename)
1141 char *filename = getCustomImageFilename(basename);
1144 if (filename == NULL)
1145 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1147 if ((new_bitmap = LoadImage(filename)) == NULL)
1148 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1153 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1155 char *filename = getCustomImageFilename(basename);
1158 if (filename == NULL) /* (should never happen) */
1160 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1164 if (strEqual(filename, bitmap->source_filename))
1166 /* The old and new image are the same (have the same filename and path).
1167 This usually means that this image does not exist in this graphic set
1168 and a fallback to the existing image is done. */
1173 if ((new_bitmap = LoadImage(filename)) == NULL)
1175 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1179 if (bitmap->width != new_bitmap->width ||
1180 bitmap->height != new_bitmap->height)
1182 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1184 FreeBitmap(new_bitmap);
1188 TransferBitmapPointers(new_bitmap, bitmap);
1192 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1194 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1196 #if defined(TARGET_SDL)
1197 SDLZoomBitmap(src_bitmap, dst_bitmap);
1199 X11ZoomBitmap(src_bitmap, dst_bitmap);
1205 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1206 boolean create_small_bitmaps)
1210 Bitmap *tmp_bitmap_1;
1211 Bitmap *tmp_bitmap_2;
1212 Bitmap *tmp_bitmap_4;
1213 Bitmap *tmp_bitmap_8;
1214 Bitmap *tmp_bitmap_16;
1215 Bitmap *tmp_bitmap_32;
1216 int width_1, height_1;
1217 int width_2, height_2;
1218 int width_4, height_4;
1219 int width_8, height_8;
1220 int width_16, height_16;
1222 int width_32, height_32;
1224 int new_width, new_height;
1226 /* calculate new image dimensions for normal sized image */
1227 width_1 = old_bitmap->width * zoom_factor;
1228 height_1 = old_bitmap->height * zoom_factor;
1230 /* get image with normal size (this might require scaling up) */
1231 if (zoom_factor != 1)
1232 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1234 tmp_bitmap_1 = old_bitmap;
1236 /* this is only needed to make compilers happy */
1237 tmp_bitmap_2 = NULL;
1238 tmp_bitmap_4 = NULL;
1239 tmp_bitmap_8 = NULL;
1240 tmp_bitmap_16 = NULL;
1241 tmp_bitmap_32 = NULL;
1243 if (create_small_bitmaps)
1245 /* calculate new image dimensions for small images */
1246 width_2 = width_1 / 2;
1247 height_2 = height_1 / 2;
1248 width_4 = width_1 / 4;
1249 height_4 = height_1 / 4;
1250 width_8 = width_1 / 8;
1251 height_8 = height_1 / 8;
1252 width_16 = width_1 / 16;
1253 height_16 = height_1 / 16;
1255 width_32 = width_1 / 32;
1256 height_32 = height_1 / 32;
1259 UPDATE_BUSY_STATE();
1261 /* get image with 1/2 of normal size (for use in the level editor) */
1262 if (zoom_factor != 2)
1263 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1265 tmp_bitmap_2 = old_bitmap;
1267 UPDATE_BUSY_STATE();
1269 /* get image with 1/4 of normal size (for use in the level editor) */
1270 if (zoom_factor != 4)
1271 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1273 tmp_bitmap_4 = old_bitmap;
1275 UPDATE_BUSY_STATE();
1277 /* get image with 1/8 of normal size (for use on the preview screen) */
1278 if (zoom_factor != 8)
1279 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1281 tmp_bitmap_8 = old_bitmap;
1283 UPDATE_BUSY_STATE();
1285 /* get image with 1/16 of normal size (for use on the preview screen) */
1286 if (zoom_factor != 16)
1287 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1289 tmp_bitmap_16 = old_bitmap;
1291 UPDATE_BUSY_STATE();
1293 /* get image with 1/32 of normal size (for use on the preview screen) */
1294 if (zoom_factor != 32)
1295 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1297 tmp_bitmap_32 = old_bitmap;
1299 UPDATE_BUSY_STATE();
1303 /* if image was scaled up, create new clipmask for normal size image */
1304 if (zoom_factor != 1)
1306 #if defined(TARGET_X11)
1307 if (old_bitmap->clip_mask)
1308 XFreePixmap(display, old_bitmap->clip_mask);
1310 old_bitmap->clip_mask =
1311 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1313 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1315 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1317 if (old_bitmap->surface_masked)
1318 SDL_FreeSurface(old_bitmap->surface_masked);
1320 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1321 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1322 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1323 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1324 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1329 if (create_small_bitmaps)
1331 new_width = width_1;
1332 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1334 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1336 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1337 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1339 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1340 width_1 / 2, height_1);
1341 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1342 3 * width_1 / 4, height_1);
1343 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1344 7 * width_1 / 8, height_1);
1345 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1346 15 * width_1 / 16, height_1);
1348 UPDATE_BUSY_STATE();
1352 new_width = width_1;
1353 new_height = height_1;
1355 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1358 if (create_small_bitmaps)
1360 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1361 if (zoom_factor != 1)
1362 FreeBitmap(tmp_bitmap_1);
1364 if (zoom_factor != 2)
1365 FreeBitmap(tmp_bitmap_2);
1367 if (zoom_factor != 4)
1368 FreeBitmap(tmp_bitmap_4);
1370 if (zoom_factor != 8)
1371 FreeBitmap(tmp_bitmap_8);
1373 if (zoom_factor != 16)
1374 FreeBitmap(tmp_bitmap_16);
1376 if (zoom_factor != 32)
1377 FreeBitmap(tmp_bitmap_32);
1380 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1381 #if defined(TARGET_SDL)
1382 swap_bitmap.surface = old_bitmap->surface;
1383 old_bitmap->surface = new_bitmap->surface;
1384 new_bitmap->surface = swap_bitmap.surface;
1386 swap_bitmap.drawable = old_bitmap->drawable;
1387 old_bitmap->drawable = new_bitmap->drawable;
1388 new_bitmap->drawable = swap_bitmap.drawable;
1391 old_bitmap->width = new_bitmap->width;
1392 old_bitmap->height = new_bitmap->height;
1395 /* this replaces all blit masks created when loading -- maybe optimize this */
1397 #if defined(TARGET_X11)
1398 if (old_bitmap->clip_mask)
1399 XFreePixmap(display, old_bitmap->clip_mask);
1401 old_bitmap->clip_mask =
1402 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1404 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1406 SDL_Surface *old_surface = old_bitmap->surface;
1408 if (old_bitmap->surface_masked)
1409 SDL_FreeSurface(old_bitmap->surface_masked);
1411 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1412 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1413 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1414 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1415 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1420 UPDATE_BUSY_STATE();
1422 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1425 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1427 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1430 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1432 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1436 /* ------------------------------------------------------------------------- */
1437 /* mouse pointer functions */
1438 /* ------------------------------------------------------------------------- */
1440 #if !defined(PLATFORM_MSDOS)
1441 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1442 /* XPM image definitions */
1443 static const char *cursor_image_none[] =
1445 /* width height num_colors chars_per_pixel */
1474 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1475 static const char *cursor_image_dot[] =
1477 /* width height num_colors chars_per_pixel */
1506 static const char **cursor_image_playfield = cursor_image_dot;
1508 /* some people complained about a "white dot" on the screen and thought it
1509 was a graphical error... OK, let's just remove the whole pointer :-) */
1510 static const char **cursor_image_playfield = cursor_image_none;
1513 #if defined(TARGET_SDL)
1514 static const int cursor_bit_order = BIT_ORDER_MSB;
1515 #elif defined(TARGET_X11_NATIVE)
1516 static const int cursor_bit_order = BIT_ORDER_LSB;
1519 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1521 struct MouseCursorInfo *cursor;
1522 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1523 int header_lines = 4;
1526 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1528 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1531 for (y = 0; y < cursor->width; y++)
1533 for (x = 0; x < cursor->height; x++)
1536 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1541 cursor->data[i] = cursor->mask[i] = 0;
1544 switch (image[header_lines + y][x])
1547 cursor->data[i] |= bit_mask;
1548 cursor->mask[i] |= bit_mask;
1552 cursor->mask[i] |= bit_mask;
1561 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1565 #endif /* !PLATFORM_MSDOS */
1567 void SetMouseCursor(int mode)
1569 #if !defined(PLATFORM_MSDOS)
1570 static struct MouseCursorInfo *cursor_none = NULL;
1571 static struct MouseCursorInfo *cursor_playfield = NULL;
1572 struct MouseCursorInfo *cursor_new;
1574 if (cursor_none == NULL)
1575 cursor_none = get_cursor_from_image(cursor_image_none);
1577 if (cursor_playfield == NULL)
1578 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1580 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1581 mode == CURSOR_NONE ? cursor_none :
1582 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1584 #if defined(TARGET_SDL)
1585 SDLSetMouseCursor(cursor_new);
1586 #elif defined(TARGET_X11_NATIVE)
1587 X11SetMouseCursor(cursor_new);
1593 /* ========================================================================= */
1594 /* audio functions */
1595 /* ========================================================================= */
1597 void OpenAudio(void)
1599 /* always start with reliable default values */
1600 audio.sound_available = FALSE;
1601 audio.music_available = FALSE;
1602 audio.loops_available = FALSE;
1604 audio.sound_enabled = FALSE;
1605 audio.sound_deactivated = FALSE;
1607 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1608 audio.mixer_pid = 0;
1609 audio.device_name = NULL;
1610 audio.device_fd = -1;
1612 audio.num_channels = 0;
1613 audio.music_channel = 0;
1614 audio.first_sound_channel = 0;
1616 #if defined(TARGET_SDL)
1618 #elif defined(PLATFORM_UNIX)
1620 #elif defined(PLATFORM_MSDOS)
1625 void CloseAudio(void)
1627 #if defined(TARGET_SDL)
1629 #elif defined(PLATFORM_UNIX)
1631 #elif defined(PLATFORM_MSDOS)
1635 audio.sound_enabled = FALSE;
1638 void SetAudioMode(boolean enabled)
1640 if (!audio.sound_available)
1643 audio.sound_enabled = enabled;
1647 /* ========================================================================= */
1648 /* event functions */
1649 /* ========================================================================= */
1651 void InitEventFilter(EventFilter filter_function)
1653 /* set event filter to filter out certain events */
1654 #if defined(TARGET_SDL)
1655 #if defined(TARGET_SDL2)
1656 SDL_SetEventFilter(filter_function, NULL);
1658 SDL_SetEventFilter(filter_function);
1663 boolean PendingEvent(void)
1665 #if defined(TARGET_SDL)
1666 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1668 return (XPending(display) ? TRUE : FALSE);
1672 void NextEvent(Event *event)
1674 #if defined(TARGET_SDL)
1675 SDLNextEvent(event);
1677 XNextEvent(display, event);
1681 void PeekEvent(Event *event)
1683 #if defined(TARGET_SDL)
1684 #if defined(TARGET_SDL2)
1685 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1687 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1690 XPeekEvent(display, event);
1694 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1696 #if defined(TARGET_SDL)
1697 #if defined(TARGET_SDL2)
1698 /* key up/down events in SDL2 do not return text characters anymore */
1699 return event->keysym.sym;
1703 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1704 (int)event->keysym.unicode,
1705 (int)event->keysym.sym,
1706 (int)SDL_GetModState());
1709 if (with_modifiers &&
1710 event->keysym.unicode > 0x0000 &&
1711 event->keysym.unicode < 0x2000)
1712 return event->keysym.unicode;
1714 return event->keysym.sym;
1720 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1721 (int)XLookupKeysym(event, event->state),
1722 (int)XLookupKeysym(event, 0));
1726 return XLookupKeysym(event, event->state);
1728 return XLookupKeysym(event, 0);
1732 KeyMod HandleKeyModState(Key key, int key_status)
1734 static KeyMod current_modifiers = KMOD_None;
1736 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1738 KeyMod new_modifier = KMOD_None;
1743 new_modifier = KMOD_Shift_L;
1746 new_modifier = KMOD_Shift_R;
1748 case KSYM_Control_L:
1749 new_modifier = KMOD_Control_L;
1751 case KSYM_Control_R:
1752 new_modifier = KMOD_Control_R;
1755 new_modifier = KMOD_Meta_L;
1758 new_modifier = KMOD_Meta_R;
1761 new_modifier = KMOD_Alt_L;
1764 new_modifier = KMOD_Alt_R;
1770 if (key_status == KEY_PRESSED)
1771 current_modifiers |= new_modifier;
1773 current_modifiers &= ~new_modifier;
1776 return current_modifiers;
1779 KeyMod GetKeyModState()
1781 #if defined(TARGET_SDL)
1782 return (KeyMod)SDL_GetModState();
1784 return HandleKeyModState(KSYM_UNDEFINED, 0);
1788 KeyMod GetKeyModStateFromEvents()
1790 /* always use key modifier state as tracked from key events (this is needed
1791 if the modifier key event was injected into the event queue, but the key
1792 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1793 query the keys as held pressed on the keyboard) -- this case is currently
1794 only used to filter out clipboard insert events from "True X-Mouse" tool */
1796 return HandleKeyModState(KSYM_UNDEFINED, 0);
1799 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1801 if (event->type != EVENT_CLIENTMESSAGE)
1804 #if defined(TARGET_SDL)
1805 return TRUE; /* the only possible message here is SDL_QUIT */
1806 #elif defined(PLATFORM_UNIX)
1807 if ((event->window == window->drawable) &&
1808 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1816 /* ========================================================================= */
1817 /* joystick functions */
1818 /* ========================================================================= */
1820 void InitJoysticks()
1824 #if defined(NO_JOYSTICK)
1825 return; /* joysticks generally deactivated by compile-time directive */
1828 /* always start with reliable default values */
1829 joystick.status = JOYSTICK_NOT_AVAILABLE;
1830 for (i = 0; i < MAX_PLAYERS; i++)
1831 joystick.fd[i] = -1; /* joystick device closed */
1833 #if defined(TARGET_SDL)
1835 #elif defined(PLATFORM_UNIX)
1836 UnixInitJoysticks();
1837 #elif defined(PLATFORM_MSDOS)
1838 MSDOSInitJoysticks();
1842 for (i = 0; i < MAX_PLAYERS; i++)
1843 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1847 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1849 #if defined(TARGET_SDL)
1850 return SDLReadJoystick(nr, x, y, b1, b2);
1851 #elif defined(PLATFORM_UNIX)
1852 return UnixReadJoystick(nr, x, y, b1, b2);
1853 #elif defined(PLATFORM_MSDOS)
1854 return MSDOSReadJoystick(nr, x, y, b1, b2);