+static void setRequestPosition(int *x, int *y, boolean add_border_size)
+{
+ setRequestPositionExt(x, y, request.width, request.height, add_border_size);
+}
+
+static void DrawEnvelopeRequestText(int sx, int sy, char *text)
+{
+ char *text_final = text;
+ char *text_door_style = NULL;
+ int graphic = IMG_BACKGROUND_REQUEST;
+ Bitmap *src_bitmap = graphic_info[graphic].bitmap;
+ int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
+ int font_nr = FONT_REQUEST;
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ int border_size = request.border_size;
+ int line_spacing = request.line_spacing;
+ int line_height = font_height + line_spacing;
+ int max_text_width = request.width - 2 * border_size;
+ int max_text_height = request.height - 2 * border_size;
+ int line_length = max_text_width / font_width;
+ int max_lines = max_text_height / line_height;
+ int text_width = line_length * font_width;
+ int sx_offset = border_size;
+ int sy_offset = border_size;
+
+ // force DOOR font inside door area
+ SetFontStatus(GAME_MODE_PSEUDO_DOOR);
+
+ if (request.centered)
+ sx_offset = (request.width - text_width) / 2;
+
+ if (request.wrap_single_words && !request.autowrap)
+ {
+ char *src_text_ptr, *dst_text_ptr;
+
+ if (maxWordLengthInRequestString(text) > line_length)
+ {
+ font_nr = FONT_REQUEST_NARROW;
+ font_width = getFontWidth(font_nr);
+ line_length = max_text_width / font_width;
+ }
+
+ text_door_style = checked_malloc(2 * strlen(text) + 1);
+
+ src_text_ptr = text;
+ dst_text_ptr = text_door_style;
+
+ while (*src_text_ptr)
+ {
+ if (*src_text_ptr == ' ' ||
+ *src_text_ptr == '?' ||
+ *src_text_ptr == '!')
+ *dst_text_ptr++ = '\n';
+
+ if (*src_text_ptr != ' ')
+ *dst_text_ptr++ = *src_text_ptr;
+
+ src_text_ptr++;
+ }
+
+ *dst_text_ptr = '\0';
+
+ text_final = text_door_style;
+ }
+
+ DrawTextBuffer(sx + sx_offset, sy + sy_offset, text_final, font_nr,
+ line_length, -1, max_lines, line_spacing, mask_mode,
+ request.autowrap, request.centered, FALSE);
+
+ if (text_door_style)
+ free(text_door_style);
+
+ ResetFontStatus();
+}
+
+static void DrawEnvelopeRequest(char *text, unsigned int req_state)
+{
+ DrawBuffer *drawto_last = drawto;
+ int graphic = IMG_BACKGROUND_REQUEST;
+ int width = request.width;
+ int height = request.height;
+ int tile_size = MAX(request.step_offset, 1);
+ int x_steps = width / tile_size;
+ int y_steps = height / tile_size;
+ int sx, sy;
+ int x, y;
+
+ setRequestPosition(&sx, &sy, FALSE);
+
+ // draw complete envelope request to temporary bitmap
+ drawto = bitmap_db_store_1;
+
+ ClearRectangle(drawto, sx, sy, width, height);
+
+ for (y = 0; y < y_steps; y++)
+ for (x = 0; x < x_steps; x++)
+ DrawEnvelopeBackgroundTiles(graphic, sx, sy,
+ x, y, x_steps, y_steps,
+ tile_size, tile_size);
+
+ // write text for request
+ DrawEnvelopeRequestText(sx, sy, text);
+
+ MapToolButtons(req_state);
+
+ // restore pointer to drawing buffer
+ drawto = drawto_last;
+
+ // prepare complete envelope request from temporary bitmap
+ PrepareEnvelopeRequestToScreen(bitmap_db_store_1, sx, sy, width, height);
+}
+
+static void AnimateEnvelopeRequest(int anim_mode, int action)
+{
+ boolean game_ended = (game_status == GAME_MODE_PLAYING && checkGameEnded());
+ int delay_value_normal = request.step_delay;
+ int delay_value_fast = delay_value_normal / 2;
+ boolean ffwd_delay = (tape.playing && tape.fast_forward);
+ boolean no_delay = (tape.warp_forward);
+ int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
+ int anim_delay_value = MAX(1, (no_delay ? 0 : delay_value) / 2);
+ DelayCounter anim_delay = { anim_delay_value };
+
+ int tile_size = MAX(request.step_offset, 1);
+ int max_xsize = request.width / tile_size;
+ int max_ysize = request.height / tile_size;
+ int max_xsize_inner = max_xsize - 2;
+ int max_ysize_inner = max_ysize - 2;
+
+ int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize_inner : 0);
+ int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize_inner : 0);
+ int xend = max_xsize_inner;
+ int yend = (anim_mode != ANIM_DEFAULT ? max_ysize_inner : 0);
+ int xstep = (xstart < xend ? 1 : 0);
+ int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
+ int start = 0;
+ int end = MAX(xend - xstart, yend - ystart);
+ int i;
+
+ if (setup.quick_doors)
+ {
+ xstart = xend;
+ ystart = yend;
+ end = 0;
+ }
+
+ for (i = start; i <= end; i++)
+ {
+ int last_frame = end; // last frame of this "for" loop
+ int x = xstart + i * xstep;
+ int y = ystart + i * ystep;
+ int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
+ int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
+ int xsize_size_left = (xsize - 1) * tile_size;
+ int ysize_size_top = (ysize - 1) * tile_size;
+ int max_xsize_pos = (max_xsize - 1) * tile_size;
+ int max_ysize_pos = (max_ysize - 1) * tile_size;
+ int width = xsize * tile_size;
+ int height = ysize * tile_size;
+ int src_x, src_y;
+ int dst_x, dst_y;
+ int xx, yy;
+
+ if (game_ended)
+ HandleGameActions();
+
+ setRequestPosition(&src_x, &src_y, FALSE);
+ setRequestPositionExt(&dst_x, &dst_y, width, height, FALSE);
+
+ for (yy = 0; yy < 2; yy++)
+ {
+ for (xx = 0; xx < 2; xx++)
+ {
+ int src_xx = src_x + xx * max_xsize_pos;
+ int src_yy = src_y + yy * max_ysize_pos;
+ int dst_xx = dst_x + xx * xsize_size_left;
+ int dst_yy = dst_y + yy * ysize_size_top;
+ int xx_size = (xx ? tile_size : xsize_size_left);
+ int yy_size = (yy ? tile_size : ysize_size_top);
+
+ // draw partial (animated) envelope request to temporary bitmap
+ BlitBitmap(bitmap_db_store_1, bitmap_db_store_2,
+ src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
+ }
+ }
+
+ // prepare partial (animated) envelope request from temporary bitmap
+ PrepareEnvelopeRequestToScreen(bitmap_db_store_2, dst_x, dst_y,
+ width, height);
+
+ redraw_mask |= REDRAW_FIELD;
+
+ BackToFront();
+
+ SkipUntilDelayReached(&anim_delay, &i, last_frame);
+ }
+
+ ClearAutoRepeatKeyEvents();
+}
+
+static void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
+{
+ int graphic = IMG_BACKGROUND_REQUEST;
+ int sound_opening = SND_REQUEST_OPENING;
+ int sound_closing = SND_REQUEST_CLOSING;
+ int anim_mode_1 = request.anim_mode; // (higher priority)
+ int anim_mode_2 = graphic_info[graphic].anim_mode; // (lower priority)
+ int anim_mode = (anim_mode_1 != ANIM_DEFAULT ? anim_mode_1 : anim_mode_2);
+ int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
+ anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
+
+ game.envelope_active = TRUE; // needed for RedrawPlayfield() events
+
+ if (action == ACTION_OPENING)
+ {
+ PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
+
+ if (anim_mode == ANIM_DEFAULT)
+ AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
+
+ AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
+ }
+ else
+ {
+ PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
+
+ if (anim_mode != ANIM_NONE)
+ AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
+
+ if (anim_mode == ANIM_DEFAULT)
+ AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
+ }
+
+ game.envelope_active = FALSE;
+}
+
+static void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
+{
+ if (IS_MM_WALL(element))
+ {
+ DrawSizedWall_MM(dst_x, dst_y, element, tilesize, el2preimg);
+ }
+ else
+ {
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int graphic = el2preimg(element);
+
+ getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
+ BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize,
+ dst_x, dst_y);
+ }
+}
+
+void DrawLevel(int draw_background_mask)
+{
+ int x, y;
+
+ SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
+ SetDrawBackgroundMask(draw_background_mask);
+
+ ClearField();
+
+ for (x = BX1; x <= BX2; x++)
+ for (y = BY1; y <= BY2; y++)
+ DrawScreenField(x, y);
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+void DrawSizedLevel(int size_x, int size_y, int scroll_x, int scroll_y,
+ int tilesize)
+{
+ int x, y;
+
+ for (x = 0; x < size_x; x++)
+ for (y = 0; y < size_y; y++)
+ DrawSizedElementOrWall(x, y, scroll_x, scroll_y, tilesize);
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
+{
+ int x, y;
+
+ for (x = 0; x < size_x; x++)
+ for (y = 0; y < size_y; y++)
+ DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+static void DrawPreviewLevelPlayfield(int from_x, int from_y)
+{
+ boolean show_level_border = (BorderElement != EL_EMPTY);
+ int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
+ int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
+ int tile_size = preview.tile_size;
+ int preview_width = preview.xsize * tile_size;
+ int preview_height = preview.ysize * tile_size;
+ int real_preview_xsize = MIN(level_xsize, preview.xsize);
+ int real_preview_ysize = MIN(level_ysize, preview.ysize);
+ int real_preview_width = real_preview_xsize * tile_size;
+ int real_preview_height = real_preview_ysize * tile_size;
+ int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
+ int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
+ int x, y;
+
+ if (!IN_GFX_FIELD_FULL(dst_x, dst_y + preview_height - 1))
+ return;
+
+ DrawBackground(dst_x, dst_y, preview_width, preview_height);
+
+ dst_x += (preview_width - real_preview_width) / 2;
+ dst_y += (preview_height - real_preview_height) / 2;
+
+ for (x = 0; x < real_preview_xsize; x++)
+ {
+ for (y = 0; y < real_preview_ysize; y++)
+ {
+ int lx = from_x + x + (show_level_border ? -1 : 0);
+ int ly = from_y + y + (show_level_border ? -1 : 0);
+ int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
+ getBorderElement(lx, ly));
+
+ DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
+ element, tile_size);
+ }
+ }
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+#define MICROLABEL_EMPTY 0
+#define MICROLABEL_LEVEL_NAME 1
+#define MICROLABEL_LEVEL_AUTHOR_HEAD 2
+#define MICROLABEL_LEVEL_AUTHOR 3
+#define MICROLABEL_IMPORTED_FROM_HEAD 4
+#define MICROLABEL_IMPORTED_FROM 5
+#define MICROLABEL_IMPORTED_BY_HEAD 6
+#define MICROLABEL_IMPORTED_BY 7
+