+ FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
+}
+
+void FadeSetFromType(int type)
+{
+ if (type & TYPE_ENTER_SCREEN)
+ FadeSetEnterScreen();
+ else if (type & TYPE_ENTER)
+ FadeSetEnterMenu();
+ else if (type & TYPE_LEAVE)
+ FadeSetLeaveMenu();
+}
+
+void FadeSetDisabled()
+{
+ static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
+
+ fading = fading_none;
+}
+
+void FadeSkipNextFadeIn()
+{
+ FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
+}
+
+void FadeSkipNextFadeOut()
+{
+ FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
+}
+
+Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
+{
+ boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
+
+ return (graphic == IMG_UNDEFINED ? NULL :
+ graphic_info[graphic].bitmap != NULL || redefined ?
+ graphic_info[graphic].bitmap :
+ graphic_info[default_graphic].bitmap);
+}
+
+Bitmap *getBackgroundBitmap(int graphic)
+{
+ return getBitmapFromGraphicOrDefault(graphic, IMG_BACKGROUND);
+}
+
+Bitmap *getGlobalBorderBitmap(int graphic)
+{
+ return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER);
+}
+
+Bitmap *getGlobalBorderBitmapFromGameStatus()
+{
+ int graphic =
+ (game_status == GAME_MODE_MAIN ||
+ game_status == GAME_MODE_PSEUDO_TYPENAME ? IMG_GLOBAL_BORDER_MAIN :
+ game_status == GAME_MODE_SCORES ? IMG_GLOBAL_BORDER_SCORES :
+ game_status == GAME_MODE_EDITOR ? IMG_GLOBAL_BORDER_EDITOR :
+ game_status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING :
+ IMG_GLOBAL_BORDER);
+
+ return getGlobalBorderBitmap(graphic);
+}
+
+void SetWindowBackgroundImageIfDefined(int graphic)
+{
+ if (graphic_info[graphic].bitmap)
+ SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
+}
+
+void SetMainBackgroundImageIfDefined(int graphic)
+{
+ if (graphic_info[graphic].bitmap)
+ SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
+}
+
+void SetDoorBackgroundImageIfDefined(int graphic)
+{
+ if (graphic_info[graphic].bitmap)
+ SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
+}
+
+void SetWindowBackgroundImage(int graphic)
+{
+ SetWindowBackgroundBitmap(getBackgroundBitmap(graphic));
+}
+
+void SetMainBackgroundImage(int graphic)
+{
+ SetMainBackgroundBitmap(getBackgroundBitmap(graphic));
+}
+
+void SetDoorBackgroundImage(int graphic)
+{
+ SetDoorBackgroundBitmap(getBackgroundBitmap(graphic));
+}
+
+void SetPanelBackground()
+{
+ struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
+
+ BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
+ gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
+
+ SetDoorBackgroundBitmap(bitmap_db_panel);
+}
+
+void DrawBackground(int x, int y, int width, int height)
+{
+ /* "drawto" might still point to playfield buffer here (hall of fame) */
+ ClearRectangleOnBackground(backbuffer, x, y, width, height);
+
+ if (IN_GFX_FIELD_FULL(x, y))
+ redraw_mask |= REDRAW_FIELD;
+ else if (IN_GFX_DOOR_1(x, y))
+ redraw_mask |= REDRAW_DOOR_1;
+ else if (IN_GFX_DOOR_2(x, y))
+ redraw_mask |= REDRAW_DOOR_2;
+ else if (IN_GFX_DOOR_3(x, y))
+ redraw_mask |= REDRAW_DOOR_3;
+}
+
+void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
+{
+ struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
+
+ if (font->bitmap == NULL)
+ return;
+
+ DrawBackground(x, y, width, height);
+}
+
+void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
+{
+ struct GraphicInfo *g = &graphic_info[graphic];
+
+ if (g->bitmap == NULL)
+ return;
+
+ DrawBackground(x, y, width, height);
+}
+
+static int game_status_last = -1;
+static Bitmap *global_border_bitmap_last = NULL;
+static Bitmap *global_border_bitmap = NULL;
+static int real_sx_last = -1, real_sy_last = -1;
+static int full_sxsize_last = -1, full_sysize_last = -1;
+static int dx_last = -1, dy_last = -1;
+static int dxsize_last = -1, dysize_last = -1;
+static int vx_last = -1, vy_last = -1;
+static int vxsize_last = -1, vysize_last = -1;
+
+boolean CheckIfGlobalBorderHasChanged()
+{
+ // if game status has not changed, global border has not changed either
+ if (game_status == game_status_last)
+ return FALSE;
+
+ // determine and store new global border bitmap for current game status
+ global_border_bitmap = getGlobalBorderBitmapFromGameStatus();
+
+ return (global_border_bitmap_last != global_border_bitmap);
+}
+
+boolean CheckIfGlobalBorderRedrawIsNeeded()
+{
+ // if game status has not changed, nothing has to be redrawn
+ if (game_status == game_status_last)
+ return FALSE;
+
+ // redraw if last screen was title screen
+ if (game_status_last == GAME_MODE_TITLE)
+ return TRUE;
+
+ // redraw if global screen border has changed
+ if (CheckIfGlobalBorderHasChanged())
+ return TRUE;
+
+ // redraw if position or size of playfield area has changed
+ if (real_sx_last != REAL_SX || real_sy_last != REAL_SY ||
+ full_sxsize_last != FULL_SXSIZE || full_sysize_last != FULL_SYSIZE)
+ return TRUE;
+
+ // redraw if position or size of door area has changed
+ if (dx_last != DX || dy_last != DY ||
+ dxsize_last != DXSIZE || dysize_last != DYSIZE)
+ return TRUE;
+
+ // redraw if position or size of tape area has changed
+ if (vx_last != VX || vy_last != VY ||
+ vxsize_last != VXSIZE || vysize_last != VYSIZE)
+ return TRUE;
+
+ return FALSE;
+}
+
+void RedrawGlobalBorderFromBitmap(Bitmap *bitmap)
+{
+ if (bitmap)
+ BlitBitmap(bitmap, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ else
+ ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
+}
+
+void RedrawGlobalBorder()
+{
+ Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus();
+
+ RedrawGlobalBorderFromBitmap(bitmap);
+
+ redraw_mask = REDRAW_ALL;
+}
+
+static void RedrawGlobalBorderIfNeeded()
+{
+ if (game_status == game_status_last)
+ return;
+
+ // copy current draw buffer to later copy back areas that have not changed
+ BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+ if (CheckIfGlobalBorderRedrawIsNeeded())
+ {
+ // redraw global screen border (or clear, if defined to be empty)
+ RedrawGlobalBorderFromBitmap(global_border_bitmap);
+
+ // copy previous playfield and door areas, if they are defined on both
+ // previous and current screen and if they still have the same size
+
+ if (real_sx_last != -1 && real_sy_last != -1 &&
+ REAL_SX != -1 && REAL_SY != -1 &&
+ full_sxsize_last == FULL_SXSIZE && full_sysize_last == FULL_SYSIZE)
+ BlitBitmap(bitmap_db_store, backbuffer,
+ real_sx_last, real_sy_last, FULL_SXSIZE, FULL_SYSIZE,
+ REAL_SX, REAL_SY);
+
+ if (dx_last != -1 && dy_last != -1 &&
+ DX != -1 && DY != -1 &&
+ dxsize_last == DXSIZE && dysize_last == DYSIZE)
+ BlitBitmap(bitmap_db_store, backbuffer,
+ dx_last, dy_last, DXSIZE, DYSIZE, DX, DY);
+
+ if (vx_last != -1 && vy_last != -1 &&
+ VX != -1 && VY != -1 &&
+ vxsize_last == VXSIZE && vysize_last == VYSIZE)
+ BlitBitmap(bitmap_db_store, backbuffer,
+ vx_last, vy_last, VXSIZE, VYSIZE, VX, VY);
+
+ redraw_mask = REDRAW_ALL;
+ }
+
+ game_status_last = game_status;
+
+ global_border_bitmap_last = global_border_bitmap;
+
+ real_sx_last = REAL_SX;
+ real_sy_last = REAL_SY;
+ full_sxsize_last = FULL_SXSIZE;
+ full_sysize_last = FULL_SYSIZE;
+ dx_last = DX;
+ dy_last = DY;
+ dxsize_last = DXSIZE;
+ dysize_last = DYSIZE;
+ vx_last = VX;
+ vy_last = VY;
+ vxsize_last = VXSIZE;
+ vysize_last = VYSIZE;
+}
+
+void ClearField()
+{
+ RedrawGlobalBorderIfNeeded();
+
+ /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
+ /* (when entering hall of fame after playing) */