+ if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
+ {
+ max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
+ font_nr = FONT_TEXT_1;
+ }
+#else
+ int max_word_len = 0;
+ char *text_ptr;
+ char *text_copy = getStringCopy(text);
+
+ font_nr = FONT_TEXT_2;
+
+ for (text_ptr = text; *text_ptr; text_ptr++)
+ {
+ max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
+
+ if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
+ {
+ max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
+ font_nr = FONT_TEXT_1;
+
+ break;
+ }
+ }
+#endif
+#endif
+
+#if 1
+ for (text_ptr = text_copy; *text_ptr; text_ptr++)
+ if (*text_ptr == ' ')
+ *text_ptr = '\n';
+#endif
+
+#if 1
+ dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
+ dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
+#else
+ dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
+ dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
+#endif
+
+ for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
+ {
+ int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
+ int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
+ int sx = SX + (SXSIZE - xsize * font_width) / 2;
+ // int sy = SX + (SYSIZE - ysize * font_height) / 2;
+ int sy = SY + (SYSIZE - ysize * (font_height + line_spacing)) / 2;
+ int xx, yy;
+
+#if 1
+ BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+#else
+ SetDrawtoField(DRAW_BUFFERED);
+
+#if 1
+ BlitScreenToBitmap(backbuffer);
+#else
+ BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+#endif
+
+ SetDrawtoField(DRAW_BACKBUFFER);
+#endif
+
+ for (yy = 0; yy < ysize; yy++)
+ for (xx = 0; xx < xsize; xx++)
+ DrawEnvelopeBackgroundTiles(graphic, sx, sy, xx, yy, xsize, ysize,
+ getFontWidth(font_nr),
+ getFontHeight(font_nr) + line_spacing);
+
+#if 1
+
+#if 1
+ DrawTextBuffer(sx + font_width, sy + font_height + 8,
+ text_copy, font_nr, max_xsize,
+ xsize - 2, ysize - 2, line_spacing, mask_mode,
+ FALSE, TRUE, FALSE);
+#else
+ DrawTextBuffer(sx + font_width, sy + font_height,
+ level.envelope[envelope_nr].text, font_nr, max_xsize,
+ xsize - 2, ysize - 2, 0, mask_mode,
+ level.envelope[envelope_nr].autowrap,
+ level.envelope[envelope_nr].centered, FALSE);
+#endif
+
+#else
+ DrawTextToTextArea(sx + font_width, sy + font_height,
+ level.envelope[envelope_nr].text, font_nr, max_xsize,
+ xsize - 2, ysize - 2, mask_mode);
+#endif
+
+ /* copy request gadgets to door backbuffer */
+#if 1
+ /*
+ if ((ysize - 2) > 13)
+ BlitBitmap(bitmap_db_door, drawto,
+ DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
+ DOOR_GFX_PAGEY1 + 13 * font_height,
+ (xsize - 2) * font_width,
+ (ysize - 2 - 13) * font_height,
+ sx + font_width,
+ sy + font_height * (1 + 13));
+ */
+ if ((ysize - 2) > 13)
+ BlitBitmap(bitmap_db_door, drawto,
+ DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
+ DOOR_GFX_PAGEY1 + 11 * (font_height + line_spacing * 0),
+ (xsize - 2) * font_width,
+ (ysize - 2 - 13) * (font_height + line_spacing),
+ sx + font_width,
+ sy + (font_height + line_spacing) * (1 + 13));
+#else
+ if ((ysize - 2) > 13)
+ BlitBitmap(bitmap_db_door, drawto,
+ DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
+ DOOR_GFX_PAGEY1 + 13 * font_height,
+ (xsize - 2) * font_width,
+ (ysize - 2 - 13) * font_height,
+ sx + font_width,
+ sy + font_height * (1 + 13));
+#endif
+
+#if 1
+ redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+ // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
+#else
+ redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+#endif
+
+#if 1
+ DoAnimation();
+ BackToFront();
+#else
+ BackToFront();
+#endif
+
+ WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
+ }
+
+#if 1
+ free(text_copy);
+#endif
+}
+
+#endif
+
+void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
+{
+#if 1
+ int last_game_status = game_status; /* save current game status */
+ // int last_draw_background_mask = gfx.draw_background_mask;
+#endif
+#if 1
+ int graphic = IMG_BACKGROUND_REQUEST;
+ int sound_opening = SND_REQUEST_OPENING;
+ int sound_closing = SND_REQUEST_CLOSING;
+#else
+ int envelope_nr = 0;
+ int element = EL_ENVELOPE_1 + envelope_nr;
+ int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
+ int sound_opening = element_info[element].sound[ACTION_OPENING];
+ int sound_closing = element_info[element].sound[ACTION_CLOSING];
+#endif
+#if 0
+ boolean ffwd_delay = (tape.playing && tape.fast_forward);
+ boolean no_delay = (tape.warp_forward);
+ int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
+ int wait_delay_value = (no_delay ? 0 : normal_delay_value);
+#endif
+ int anim_mode = graphic_info[graphic].anim_mode;
+ int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
+ anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
+#if 0
+ char *text_copy = getStringCopy(text);
+ char *text_ptr;
+
+ for (text_ptr = text_copy; *text_ptr; text_ptr++)
+ if (*text_ptr == ' ')
+ *text_ptr = '\n';
+#endif
+
+#if 1
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ BlitScreenToBitmap_EM(backbuffer);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ BlitScreenToBitmap_SP(backbuffer);
+ else
+ {
+ BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+ }
+ }
+
+ SetDrawtoField(DRAW_BACKBUFFER);
+
+ // SetDrawBackgroundMask(REDRAW_NONE);
+
+ if (action == ACTION_OPENING)
+ {
+ BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+#if 1
+ if (req_state & REQ_ASK)
+ {
+ MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
+ }
+ else if (req_state & REQ_CONFIRM)
+ {
+ MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
+ }
+ else if (req_state & REQ_PLAYER)
+ {
+ MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
+ }
+#endif
+
+#if 1
+ DrawEnvelopeRequest(text);
+#else
+ DrawEnvelopeRequest(text_copy);
+#endif
+
+ if (game_status != GAME_MODE_MAIN)
+ InitAnimation();
+ }
+
+ /* force DOOR font inside door area */
+ game_status = GAME_MODE_PSEUDO_DOOR;
+#endif
+
+ 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);
+
+#if 0
+ if (tape.playing)
+ Delay(wait_delay_value);
+ else
+ WaitForEventToContinue();
+#endif
+ }
+ 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;
+
+#if 1
+ // game_status = last_game_status; /* restore current game status */
+
+ if (action == ACTION_CLOSING)
+ {
+ if (game_status != GAME_MODE_MAIN)
+ StopAnimation();
+
+ BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ }
+#else
+ SetDrawtoField(DRAW_BUFFERED);
+#endif
+
+ // SetDrawBackgroundMask(last_draw_background_mask);
+
+#if 1
+ redraw_mask = REDRAW_FIELD;
+ // redraw_mask |= REDRAW_ALL;
+#else
+ redraw_mask |= REDRAW_FIELD;
+#endif
+
+#if 1
+ if (game_status == GAME_MODE_MAIN)
+ DoAnimation();
+
+ BackToFront();
+
+ /* (important: after "BackToFront()", but before "SetDrawtoField()") */
+ game_status = last_game_status; /* restore current game status */
+
+#if 1
+ if (action == ACTION_CLOSING &&
+ game_status == GAME_MODE_PLAYING &&
+ level.game_engine_type == GAME_ENGINE_TYPE_RND)
+ SetDrawtoField(DRAW_BUFFERED);
+#else
+ if (game_status == GAME_MODE_PLAYING &&
+ level.game_engine_type == GAME_ENGINE_TYPE_RND)
+ SetDrawtoField(DRAW_BUFFERED);
+#endif
+
+#else
+ BackToFront();
+#endif
+
+#if 0
+ free(text_copy);
+#endif
+}
+
+void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
+{
+ 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 x,y;
+
+#if 1
+ SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
+ SetDrawBackgroundMask(REDRAW_FIELD);
+#else
+ SetDrawBackgroundMask(REDRAW_NONE);
+#endif
+
+ ClearField();
+
+ for (x = BX1; x <= BX2; x++)
+ for (y = BY1; y <= BY2; y++)
+ DrawScreenField(x, y);
+
+ 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 DrawPreviewLevelPlayfieldExt(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 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;
+
+ DrawBackground(dst_x, dst_y, preview_width, preview_height);
+
+ dst_x += (preview_width - real_preview_xsize * tile_size) / 2;
+ dst_y += (preview_height - real_preview_ysize * tile_size) / 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_MICROLEVEL;
+}
+
+#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
+
+static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
+{
+ int max_text_width = SXSIZE;
+ int font_width = getFontWidth(font_nr);
+
+ if (pos->align == ALIGN_CENTER)
+ max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
+ else if (pos->align == ALIGN_RIGHT)
+ max_text_width = pos->x;
+ else
+ max_text_width = SXSIZE - pos->x;
+
+ return max_text_width / font_width;
+}
+
+static void DrawPreviewLevelLabelExt(int mode)
+{
+ struct TextPosInfo *pos = &menu.main.text.level_info_2;
+ char label_text[MAX_OUTPUT_LINESIZE + 1];
+ int max_len_label_text;
+#if 1
+ int font_nr = pos->font;
+ int i;
+
+ if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
+ mode == MICROLABEL_IMPORTED_FROM_HEAD ||
+ mode == MICROLABEL_IMPORTED_BY_HEAD)
+ font_nr = pos->font_alt;
+#else
+ int font_nr = FONT_TEXT_2;
+ int i;
+
+ if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
+ mode == MICROLABEL_IMPORTED_FROM_HEAD ||
+ mode == MICROLABEL_IMPORTED_BY_HEAD)
+ font_nr = FONT_TEXT_3;
+#endif
+
+#if 1
+ max_len_label_text = getMaxTextLength(pos, font_nr);
+#else
+ max_len_label_text = SXSIZE / getFontWidth(font_nr);
+#endif
+
+#if 1
+ if (pos->size != -1)
+ max_len_label_text = pos->size;
+#endif
+
+ for (i = 0; i < max_len_label_text; i++)
+ label_text[i] = ' ';
+ label_text[max_len_label_text] = '\0';
+
+ if (strlen(label_text) > 0)
+ {
+#if 1
+ DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
+#else
+ int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
+ int lypos = MICROLABEL2_YPOS;
+
+ DrawText(lxpos, lypos, label_text, font_nr);
+#endif
+ }
+
+ strncpy(label_text,
+ (mode == MICROLABEL_LEVEL_NAME ? level.name :
+ mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
+ mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
+ mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
+ mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
+ mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
+ mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
+ max_len_label_text);
+ label_text[max_len_label_text] = '\0';
+
+ if (strlen(label_text) > 0)
+ {
+#if 1
+ DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
+#else
+ int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
+ int lypos = MICROLABEL2_YPOS;
+
+ DrawText(lxpos, lypos, label_text, font_nr);
+#endif
+ }
+
+ redraw_mask |= REDRAW_MICROLEVEL;
+}
+
+static void DrawPreviewLevelExt(boolean restart)
+{
+ static unsigned int scroll_delay = 0;
+ static unsigned int label_delay = 0;
+ static int from_x, from_y, scroll_direction;
+ static int label_state, label_counter;
+ unsigned int scroll_delay_value = preview.step_delay;
+ 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 last_game_status = game_status; /* save current game status */
+
+#if 0
+ /* force PREVIEW font on preview level */
+ game_status = GAME_MODE_PSEUDO_PREVIEW;
+#endif
+
+ if (restart)
+ {
+ from_x = 0;
+ from_y = 0;
+
+ if (preview.anim_mode == ANIM_CENTERED)
+ {
+ if (level_xsize > preview.xsize)
+ from_x = (level_xsize - preview.xsize) / 2;
+ if (level_ysize > preview.ysize)
+ from_y = (level_ysize - preview.ysize) / 2;
+ }
+
+ from_x += preview.xoffset;
+ from_y += preview.yoffset;
+
+ scroll_direction = MV_RIGHT;
+ label_state = 1;
+ label_counter = 0;
+
+ DrawPreviewLevelPlayfieldExt(from_x, from_y);
+ DrawPreviewLevelLabelExt(label_state);
+
+ /* initialize delay counters */
+ DelayReached(&scroll_delay, 0);
+ DelayReached(&label_delay, 0);
+
+ if (leveldir_current->name)
+ {
+ struct TextPosInfo *pos = &menu.main.text.level_info_1;
+ char label_text[MAX_OUTPUT_LINESIZE + 1];
+#if 1
+ int font_nr = pos->font;
+#else
+ int font_nr = FONT_TEXT_1;
+#endif
+#if 1
+ int max_len_label_text = getMaxTextLength(pos, font_nr);
+#else
+ int max_len_label_text = SXSIZE / getFontWidth(font_nr);
+#endif
+#if 0
+ int text_width;
+ int lxpos, lypos;
+#endif
+
+#if 1
+ if (pos->size != -1)
+ max_len_label_text = pos->size;
+#endif
+
+ strncpy(label_text, leveldir_current->name, max_len_label_text);
+ label_text[max_len_label_text] = '\0';
+
+#if 1
+ DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
+#else
+ lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
+ lypos = SY + MICROLABEL1_YPOS;
+
+ DrawText(lxpos, lypos, label_text, font_nr);
+#endif
+ }
+
+ game_status = last_game_status; /* restore current game status */
+
+ return;
+ }
+
+ /* scroll preview level, if needed */
+ if (preview.anim_mode != ANIM_NONE &&
+ (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
+ DelayReached(&scroll_delay, scroll_delay_value))
+ {
+ switch (scroll_direction)
+ {
+ case MV_LEFT:
+ if (from_x > 0)
+ {
+ from_x -= preview.step_offset;
+ from_x = (from_x < 0 ? 0 : from_x);
+ }
+ else
+ scroll_direction = MV_UP;
+ break;
+
+ case MV_RIGHT:
+ if (from_x < level_xsize - preview.xsize)
+ {
+ from_x += preview.step_offset;
+ from_x = (from_x > level_xsize - preview.xsize ?
+ level_xsize - preview.xsize : from_x);
+ }
+ else
+ scroll_direction = MV_DOWN;
+ break;
+
+ case MV_UP:
+ if (from_y > 0)
+ {
+ from_y -= preview.step_offset;
+ from_y = (from_y < 0 ? 0 : from_y);
+ }
+ else
+ scroll_direction = MV_RIGHT;
+ break;
+
+ case MV_DOWN:
+ if (from_y < level_ysize - preview.ysize)
+ {
+ from_y += preview.step_offset;
+ from_y = (from_y > level_ysize - preview.ysize ?
+ level_ysize - preview.ysize : from_y);
+ }
+ else
+ scroll_direction = MV_LEFT;
+ break;
+
+ default:
+ break;
+ }
+
+ DrawPreviewLevelPlayfieldExt(from_x, from_y);
+ }
+
+ /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
+ /* redraw micro level label, if needed */
+ if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
+ !strEqual(level.author, ANONYMOUS_NAME) &&
+ !strEqual(level.author, leveldir_current->name) &&
+ DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
+ {
+ int max_label_counter = 23;
+
+ if (leveldir_current->imported_from != NULL &&
+ strlen(leveldir_current->imported_from) > 0)
+ max_label_counter += 14;
+ if (leveldir_current->imported_by != NULL &&
+ strlen(leveldir_current->imported_by) > 0)
+ max_label_counter += 14;
+
+ label_counter = (label_counter + 1) % max_label_counter;
+ label_state = (label_counter >= 0 && label_counter <= 7 ?
+ MICROLABEL_LEVEL_NAME :
+ label_counter >= 9 && label_counter <= 12 ?
+ MICROLABEL_LEVEL_AUTHOR_HEAD :
+ label_counter >= 14 && label_counter <= 21 ?
+ MICROLABEL_LEVEL_AUTHOR :
+ label_counter >= 23 && label_counter <= 26 ?
+ MICROLABEL_IMPORTED_FROM_HEAD :
+ label_counter >= 28 && label_counter <= 35 ?
+ MICROLABEL_IMPORTED_FROM :
+ label_counter >= 37 && label_counter <= 40 ?
+ MICROLABEL_IMPORTED_BY_HEAD :
+ label_counter >= 42 && label_counter <= 49 ?
+ MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
+
+ if (leveldir_current->imported_from == NULL &&
+ (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
+ label_state == MICROLABEL_IMPORTED_FROM))
+ label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
+ MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
+
+ DrawPreviewLevelLabelExt(label_state);
+ }
+
+ game_status = last_game_status; /* restore current game status */
+}
+
+void DrawPreviewLevelInitial()
+{
+ DrawPreviewLevelExt(TRUE);
+}
+
+void DrawPreviewLevelAnimation()
+{
+ DrawPreviewLevelExt(FALSE);
+}
+
+inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+ int graphic, int sync_frame, int mask_mode)
+{
+ int frame = getGraphicAnimationFrame(graphic, sync_frame);
+
+ if (mask_mode == USE_MASKING)
+ DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
+ else
+ DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
+}
+
+inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+ int graphic, int sync_frame,
+ int mask_mode)
+{
+ int frame = getGraphicAnimationFrame(graphic, sync_frame);
+
+ if (mask_mode == USE_MASKING)
+ DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
+ else
+ DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
+}
+
+inline void DrawGraphicAnimation(int x, int y, int graphic)
+{
+ int lx = LEVELX(x), ly = LEVELY(y);
+
+ if (!IN_SCR_FIELD(x, y))
+ return;
+
+#if NEW_TILESIZE
+ DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
+ graphic, GfxFrame[lx][ly], NO_MASKING);
+#else
+ DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
+ graphic, GfxFrame[lx][ly], NO_MASKING);
+#endif
+ MarkTileDirty(x, y);
+}
+
+inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
+{
+ int lx = LEVELX(x), ly = LEVELY(y);
+
+ if (!IN_SCR_FIELD(x, y))
+ return;
+
+ DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
+ graphic, GfxFrame[lx][ly], NO_MASKING);
+ MarkTileDirty(x, y);
+}
+
+void DrawLevelGraphicAnimation(int x, int y, int graphic)
+{
+ DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
+}
+
+void DrawLevelElementAnimation(int x, int y, int element)
+{
+ int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+
+ DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
+}
+
+inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
+{
+ int sx = SCREENX(x), sy = SCREENY(y);
+
+ if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
+ return;
+
+ if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
+ return;
+
+ DrawGraphicAnimation(sx, sy, graphic);
+
+#if 1
+ if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
+ DrawLevelFieldCrumbled(x, y);
+#else
+ if (GFX_CRUMBLED(Feld[x][y]))
+ DrawLevelFieldCrumbled(x, y);
+#endif
+}
+
+void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
+{
+ int sx = SCREENX(x), sy = SCREENY(y);
+ int graphic;
+
+ if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
+ return;
+
+ graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+
+ if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
+ return;
+
+ DrawGraphicAnimation(sx, sy, graphic);
+
+ if (GFX_CRUMBLED(element))
+ DrawLevelFieldCrumbled(x, y);
+}
+
+static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
+{
+ if (player->use_murphy)
+ {
+ /* this works only because currently only one player can be "murphy" ... */
+ static int last_horizontal_dir = MV_LEFT;
+ int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
+
+ if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+ last_horizontal_dir = move_dir;
+
+ if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
+ {
+ int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
+
+ graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
+ }
+
+ return graphic;
+ }
+ else
+ return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
+}
+
+static boolean equalGraphics(int graphic1, int graphic2)
+{
+ struct GraphicInfo *g1 = &graphic_info[graphic1];
+ struct GraphicInfo *g2 = &graphic_info[graphic2];
+
+ return (g1->bitmap == g2->bitmap &&
+ g1->src_x == g2->src_x &&
+ g1->src_y == g2->src_y &&
+ g1->anim_frames == g2->anim_frames &&
+ g1->anim_delay == g2->anim_delay &&
+ g1->anim_mode == g2->anim_mode);
+}
+
+void DrawAllPlayers()
+{
+ int i;
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ if (stored_player[i].active)
+ DrawPlayer(&stored_player[i]);
+}
+
+void DrawPlayerField(int x, int y)
+{
+ if (!IS_PLAYER(x, y))
+ return;
+
+ DrawPlayer(PLAYERINFO(x, y));
+}
+
+#define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
+
+void DrawPlayer(struct PlayerInfo *player)
+{
+ int jx = player->jx;
+ int jy = player->jy;
+ int move_dir = player->MovDir;
+ int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
+ int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
+ int last_jx = (player->is_moving ? jx - dx : jx);
+ int last_jy = (player->is_moving ? jy - dy : jy);
+ int next_jx = jx + dx;
+ int next_jy = jy + dy;
+ boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
+ boolean player_is_opaque = FALSE;
+ int sx = SCREENX(jx), sy = SCREENY(jy);
+ int sxx = 0, syy = 0;
+ int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
+ int graphic;
+ int action = ACTION_DEFAULT;
+ int last_player_graphic = getPlayerGraphic(player, move_dir);
+ int last_player_frame = player->Frame;
+ int frame = 0;
+
+ /* GfxElement[][] is set to the element the player is digging or collecting;
+ remove also for off-screen player if the player is not moving anymore */
+ if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
+ GfxElement[jx][jy] = EL_UNDEFINED;
+
+ if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
+ return;
+
+#if DEBUG
+ if (!IN_LEV_FIELD(jx, jy))
+ {
+ printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
+ printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
+ printf("DrawPlayerField(): This should never happen!\n");
+ return;
+ }
+#endif
+
+ if (element == EL_EXPLOSION)
+ return;
+
+ action = (player->is_pushing ? ACTION_PUSHING :
+ player->is_digging ? ACTION_DIGGING :
+ player->is_collecting ? ACTION_COLLECTING :
+ player->is_moving ? ACTION_MOVING :
+ player->is_snapping ? ACTION_SNAPPING :
+ player->is_dropping ? ACTION_DROPPING :
+ player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
+
+ if (player->is_waiting)
+ move_dir = player->dir_waiting;
+
+ InitPlayerGfxAnimation(player, action, move_dir);
+
+ /* ----------------------------------------------------------------------- */
+ /* draw things in the field the player is leaving, if needed */
+ /* ----------------------------------------------------------------------- */
+
+ if (player->is_moving)
+ {
+ if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
+ {
+ DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
+
+ if (last_element == EL_DYNAMITE_ACTIVE ||
+ last_element == EL_EM_DYNAMITE_ACTIVE ||
+ last_element == EL_SP_DISK_RED_ACTIVE)
+ DrawDynamite(last_jx, last_jy);
+ else
+ DrawLevelFieldThruMask(last_jx, last_jy);
+ }
+ else if (last_element == EL_DYNAMITE_ACTIVE ||
+ last_element == EL_EM_DYNAMITE_ACTIVE ||
+ last_element == EL_SP_DISK_RED_ACTIVE)
+ DrawDynamite(last_jx, last_jy);
+#if 0
+ /* !!! this is not enough to prevent flickering of players which are
+ moving next to each others without a free tile between them -- this
+ can only be solved by drawing all players layer by layer (first the
+ background, then the foreground etc.) !!! => TODO */
+ else if (!IS_PLAYER(last_jx, last_jy))
+ DrawLevelField(last_jx, last_jy);
+#else
+ else
+ DrawLevelField(last_jx, last_jy);
+#endif
+
+ if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
+ DrawLevelElement(next_jx, next_jy, EL_EMPTY);
+ }
+
+ if (!IN_SCR_FIELD(sx, sy))
+ return;
+
+ /* ----------------------------------------------------------------------- */
+ /* draw things behind the player, if needed */
+ /* ----------------------------------------------------------------------- */
+
+ if (Back[jx][jy])
+ DrawLevelElement(jx, jy, Back[jx][jy]);
+ else if (IS_ACTIVE_BOMB(element))
+ DrawLevelElement(jx, jy, EL_EMPTY);
+ else
+ {
+ if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
+ {
+ int old_element = GfxElement[jx][jy];
+ int old_graphic = el_act_dir2img(old_element, action, move_dir);
+ int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
+
+ if (GFX_CRUMBLED(old_element))
+ DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
+ else
+ DrawGraphic(sx, sy, old_graphic, frame);
+
+ if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
+ player_is_opaque = TRUE;
+ }
+ else
+ {
+ GfxElement[jx][jy] = EL_UNDEFINED;
+
+ /* make sure that pushed elements are drawn with correct frame rate */
+#if 1
+ graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+
+ if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
+ GfxFrame[jx][jy] = player->StepFrame;
+#else
+ if (player->is_pushing && player->is_moving)
+ GfxFrame[jx][jy] = player->StepFrame;
+#endif
+
+ DrawLevelField(jx, jy);
+ }
+ }
+
+#if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
+ /* ----------------------------------------------------------------------- */
+ /* draw player himself */
+ /* ----------------------------------------------------------------------- */
+
+ graphic = getPlayerGraphic(player, move_dir);
+
+ /* in the case of changed player action or direction, prevent the current
+ animation frame from being restarted for identical animations */
+ if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
+ player->Frame = last_player_frame;
+
+ frame = getGraphicAnimationFrame(graphic, player->Frame);
+
+ if (player->GfxPos)
+ {
+ if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+ sxx = player->GfxPos;
+ else
+ syy = player->GfxPos;
+ }
+
+ if (!setup.soft_scrolling && ScreenMovPos)
+ sxx = syy = 0;
+
+ if (player_is_opaque)
+ DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
+ else
+ DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+
+ if (SHIELD_ON(player))
+ {
+ int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
+ IMG_SHIELD_NORMAL_ACTIVE);
+ int frame = getGraphicAnimationFrame(graphic, -1);
+
+ DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+ }