+ 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
+#endif
+
+ ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
+
+#if 0
+ for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+ {
+ if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
+ i == TOOL_CTRL_ID_NO)) ||
+ (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
+ (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
+ i == TOOL_CTRL_ID_PLAYER_2 &&
+ i == TOOL_CTRL_ID_PLAYER_3 &&
+ i == TOOL_CTRL_ID_PLAYER_4)))
+ {
+ int x = tool_gadget[i]->x + dDX;
+ int y = tool_gadget[i]->y + dDY;
+
+ ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
+ }
+ }
+#endif
+
+ if (!(req_state & REQUEST_WAIT_FOR_INPUT))
+ {
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ SetPanelBackground();
+ SetDrawBackgroundMask(REDRAW_DOOR_1);
+ }
+ else
+ {
+ SetDrawBackgroundMask(REDRAW_FIELD);
+ }
+
+ return FALSE;
+ }
+
+#if 0
+ if (game_status != GAME_MODE_MAIN)
+ InitAnimation();
+#endif
+
+ SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
+
+ // ---------- handle request buttons ----------
+ result = RequestHandleEvents(req_state);
+
+ if (game_status != GAME_MODE_MAIN)
+ StopAnimation();
+
+ UnmapToolButtons();
+
+ ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
+
+ RemapAllGadgets();
+
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ SetPanelBackground();
+ SetDrawBackgroundMask(REDRAW_DOOR_1);
+ }
+ else
+ {
+ SetDrawBackgroundMask(REDRAW_FIELD);
+ }
+
+#if defined(NETWORK_AVALIABLE)
+ /* continue network game after request */
+ if (options.network &&
+ game_status == GAME_MODE_PLAYING &&
+ req_state & REQUEST_WAIT_FOR_INPUT)
+ SendToServer_ContinuePlaying();
+#endif
+
+ /* restore deactivated drawing when quick-loading level tape recording */
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOn();
+
+ return result;
+}
+
+boolean Request(char *text, unsigned int req_state)
+{
+ if (global.use_envelope_request)
+ return RequestEnvelope(text, req_state);
+ else
+ return RequestDoor(text, req_state);
+}
+
+#else // =====================================================================
+
+boolean Request(char *text, unsigned int req_state)
+{
+ int mx, my, ty, result = -1;
+ unsigned int old_door_state;
+ int last_game_status = game_status; /* save current game status */
+ int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
+ int font_nr = FONT_TEXT_2;
+#if 0
+ int max_word_len = 0;
+#endif
+ char *text_ptr;
+ int i;
+
+#if 0
+ global.use_envelope_request = 1;
+#endif
+
+#if 1
+ if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
+ {
+ max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
+ font_nr = FONT_TEXT_1;
+ }
+#else
+ for (text_ptr = text; *text_ptr; text_ptr++)
+ {
+ max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
+
+ if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
+ {
+ max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
+#if 1
+ font_nr = FONT_TEXT_1;
+#else
+ font_nr = FONT_LEVEL_NUMBER;
+#endif
+
+ break;
+ }
+ }
+#endif
+
+ if (game_status == GAME_MODE_PLAYING)
+ {
+#if 1
+ BlitScreenToBitmap(backbuffer);
+#else
+ 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);
+#endif
+ }
+
+ /* disable deactivated drawing when quick-loading level tape recording */
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOff(TRUE);
+
+ SetMouseCursor(CURSOR_DEFAULT);
+
+#if defined(NETWORK_AVALIABLE)
+ /* pause network game while waiting for request to answer */
+ if (options.network &&
+ game_status == GAME_MODE_PLAYING &&
+ req_state & REQUEST_WAIT_FOR_INPUT)
+ SendToServer_PausePlaying();
+#endif
+
+ old_door_state = GetDoorState();
+
+ /* simulate releasing mouse button over last gadget, if still pressed */
+ if (button_status)
+ HandleGadgets(-1, -1, 0);
+
+ UnmapAllGadgets();
+
+ /* draw released gadget before proceeding */
+ // BackToFront();
+
+#if 0
+ if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
+#else
+ if (old_door_state & DOOR_OPEN_1)
+#endif
+ {
+#if 1
+ if (!global.use_envelope_request)
+ CloseDoor(DOOR_CLOSE_1);
+#else
+ CloseDoor(DOOR_CLOSE_1);
+#endif
+
+ /* save old door content */
+ BlitBitmap(bitmap_db_door, bitmap_db_door,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
+ DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
+ }
+
+#if 1
+ SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
+#endif
+
+ SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
+
+ /* clear door drawing field */
+ DrawBackground(DX, DY, DXSIZE, DYSIZE);
+
+ /* force DOOR font inside door area */
+ game_status = GAME_MODE_PSEUDO_DOOR;
+
+ /* write text for request */
+ for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
+ {
+ char text_line[max_request_line_len + 1];
+ int tx, tl, tc = 0;
+
+ if (!*text_ptr)
+ break;
+
+ for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
+ {
+ tc = *(text_ptr + tx);
+ if (!tc || tc == ' ')
+ break;
+ }
+
+ if (!tl)
+ {
+ text_ptr++;
+ ty--;
+ continue;
+ }
+
+ strncpy(text_line, text_ptr, tl);
+ text_line[tl] = 0;
+
+ DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
+ DY + 8 + ty * (getFontHeight(font_nr) + 2),
+ text_line, font_nr);
+
+ text_ptr += tl + (tc == ' ' ? 1 : 0);
+ }
+
+ game_status = last_game_status; /* restore current game status */
+
+#if 1
+ if (global.use_envelope_request)
+ {
+ /* !!! TMP !!! */
+ FreeToolButtons();
+ CreateToolButtons();
+ }
+#endif
+
+ 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]);
+ }
+
+ /* copy request gadgets to door backbuffer */
+ BlitBitmap(drawto, bitmap_db_door,
+ DX, DY, DXSIZE, DYSIZE,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+
+#if 1
+ if (global.use_envelope_request)
+ {
+ ShowEnvelopeRequest(text, ACTION_OPENING);
+
+ for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+ {
+ if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
+ i == TOOL_CTRL_ID_NO)) ||
+ (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
+ (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
+ i == TOOL_CTRL_ID_PLAYER_2 &&
+ i == TOOL_CTRL_ID_PLAYER_3 &&
+ i == TOOL_CTRL_ID_PLAYER_4)))
+ {
+ int x = tool_gadget[i]->x + dDX;
+ int y = tool_gadget[i]->y + dDY;
+
+ ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
+ }
+ }
+ }
+#endif
+
+#if 1
+ if (!global.use_envelope_request)
+ OpenDoor(DOOR_OPEN_1);
+#else
+ OpenDoor(DOOR_OPEN_1);
+#endif
+
+ if (!(req_state & REQUEST_WAIT_FOR_INPUT))
+ {
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ SetPanelBackground();
+ SetDrawBackgroundMask(REDRAW_DOOR_1);
+ }
+ else
+ {
+ SetDrawBackgroundMask(REDRAW_FIELD);
+ }
+
+ return FALSE;
+ }
+
+#if 1
+ if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
+ InitAnimation();
+#else
+ if (game_status != GAME_MODE_MAIN)
+ InitAnimation();
+#endif
+
+ button_status = MB_RELEASED;
+
+ request_gadget_id = -1;
+
+ SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
+
+ while (result < 0)
+ {
+ if (PendingEvent())
+ {
+ Event event;
+
+ NextEvent(&event);
+
+ switch (event.type)
+ {
+ case EVENT_BUTTONPRESS:
+ case EVENT_BUTTONRELEASE:
+ case EVENT_MOTIONNOTIFY:
+ {
+ if (event.type == EVENT_MOTIONNOTIFY)
+ {
+ if (!PointerInWindow(window))
+ continue; /* window and pointer are on different screens */
+
+ if (!button_status)
+ continue;
+
+ motion_status = TRUE;
+ mx = ((MotionEvent *) &event)->x;
+ my = ((MotionEvent *) &event)->y;
+ }
+ else
+ {
+ motion_status = FALSE;
+ mx = ((ButtonEvent *) &event)->x;
+ my = ((ButtonEvent *) &event)->y;
+ if (event.type == EVENT_BUTTONPRESS)
+ button_status = ((ButtonEvent *) &event)->button;
+ else
+ button_status = MB_RELEASED;
+ }
+
+ /* this sets 'request_gadget_id' */
+ HandleGadgets(mx, my, button_status);
+
+ switch (request_gadget_id)
+ {
+ case TOOL_CTRL_ID_YES:
+ result = TRUE;
+ break;
+ case TOOL_CTRL_ID_NO:
+ result = FALSE;
+ break;
+ case TOOL_CTRL_ID_CONFIRM:
+ result = TRUE | FALSE;
+ break;
+
+ case TOOL_CTRL_ID_PLAYER_1:
+ result = 1;
+ break;
+ case TOOL_CTRL_ID_PLAYER_2:
+ result = 2;
+ break;
+ case TOOL_CTRL_ID_PLAYER_3:
+ result = 3;
+ break;
+ case TOOL_CTRL_ID_PLAYER_4:
+ result = 4;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case EVENT_KEYPRESS:
+ switch (GetEventKey((KeyEvent *)&event, TRUE))
+ {
+ case KSYM_space:
+ if (req_state & REQ_CONFIRM)
+ result = 1;
+ break;
+
+ case KSYM_Return:
+ result = 1;
+ break;
+
+ case KSYM_Escape:
+#if defined(TARGET_SDL2)
+ case KSYM_Back:
+#endif
+ result = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ if (req_state & REQ_PLAYER)
+ result = 0;
+ break;
+
+ case EVENT_KEYRELEASE:
+ ClearPlayerAction();
+ break;
+
+ default:
+ HandleOtherEvents(&event);
+ break;
+ }
+ }
+ else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
+ {
+ int joy = AnyJoystick();
+
+ if (joy & JOY_BUTTON_1)
+ result = 1;
+ else if (joy & JOY_BUTTON_2)
+ result = 0;
+ }
+
+#if 1
+
+ if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
+ {
+ HandleGameActions();
+ }
+ else
+ {
+ DoAnimation();
+
+ if (!PendingEvent()) /* delay only if no pending events */
+ Delay(10);
+ }
+
+#if 1
+ game_status = GAME_MODE_PSEUDO_DOOR;
+#endif
+
+ BackToFront();
+
+#if 1
+ game_status = last_game_status; /* restore current game status */
+#endif
+
+#else
+
+ DoAnimation();
+
+#if 1
+ if (!PendingEvent()) /* delay only if no pending events */
+ Delay(10);
+#else
+ /* don't eat all CPU time */
+ Delay(10);
+#endif
+
+#endif
+ }
+
+ if (game_status != GAME_MODE_MAIN)
+ StopAnimation();
+
+ UnmapToolButtons();
+
+#if 1
+ if (global.use_envelope_request)
+ ShowEnvelopeRequest(text, ACTION_CLOSING);
+#endif
+
+#if 1
+ if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
+#else
+ if (!(req_state & REQ_STAY_OPEN))
+#endif
+ {
+ CloseDoor(DOOR_CLOSE_1);
+
+ if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
+ (req_state & REQ_REOPEN))
+ OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+ }
+
+ RemapAllGadgets();
+
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ SetPanelBackground();
+ SetDrawBackgroundMask(REDRAW_DOOR_1);
+ }
+ else
+ {
+ SetDrawBackgroundMask(REDRAW_FIELD);
+ }
+
+#if defined(NETWORK_AVALIABLE)
+ /* continue network game after request */
+ if (options.network &&
+ game_status == GAME_MODE_PLAYING &&
+ req_state & REQUEST_WAIT_FOR_INPUT)
+ SendToServer_ContinuePlaying();
+#endif
+
+ /* restore deactivated drawing when quick-loading level tape recording */
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOn();
+
+ return result;
+}
+
+#endif
+
+static int compareDoorPartOrderInfo(const void *object1, const void *object2)
+{
+ const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
+ const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
+ int compare_result;
+
+ if (dpo1->sort_priority != dpo2->sort_priority)
+ compare_result = dpo1->sort_priority - dpo2->sort_priority;
+ else
+ compare_result = dpo1->nr - dpo2->nr;
+
+ return compare_result;
+}
+
+void InitGraphicCompatibilityInfo_Doors()
+{
+ struct
+ {
+ int door_token;
+ int part_1, part_8;
+ struct DoorInfo *door;
+ }
+ doors[] =
+ {
+ { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 },
+ { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 },
+
+ { -1, -1, -1, NULL }
+ };
+ struct Rect door_rect_list[] =
+ {
+ { DX, DY, DXSIZE, DYSIZE },
+ { VX, VY, VXSIZE, VYSIZE }
+ };
+ int i, j;
+
+ for (i = 0; doors[i].door_token != -1; i++)
+ {
+ int door_token = doors[i].door_token;
+ int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
+ int part_1 = doors[i].part_1;
+ int part_8 = doors[i].part_8;
+ int part_2 = part_1 + 1;
+ int part_3 = part_1 + 2;
+ struct DoorInfo *door = doors[i].door;
+ struct Rect *door_rect = &door_rect_list[door_index];
+ boolean door_gfx_redefined = FALSE;
+
+ /* check if any door part graphic definitions have been redefined */
+
+ for (j = 0; door_part_controls[j].door_token != -1; j++)
+ {
+ struct DoorPartControlInfo *dpc = &door_part_controls[j];
+ struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
+
+ if (dpc->door_token == door_token && fi->redefined)
+ door_gfx_redefined = TRUE;
+ }
+
+ /* check for old-style door graphic/animation modifications */
+
+ if (!door_gfx_redefined)
+ {
+ if (door->anim_mode & ANIM_STATIC_PANEL)
+ {
+ door->panel.step_xoffset = 0;
+ door->panel.step_yoffset = 0;
+ }
+
+ if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
+ {
+ struct GraphicInfo *g_part_1 = &graphic_info[part_1];
+ struct GraphicInfo *g_part_2 = &graphic_info[part_2];
+ int num_door_steps, num_panel_steps;
+
+ /* remove door part graphics other than the two default wings */
+
+ for (j = 0; door_part_controls[j].door_token != -1; j++)
+ {
+ struct DoorPartControlInfo *dpc = &door_part_controls[j];
+ struct GraphicInfo *g = &graphic_info[dpc->graphic];
+
+ if (dpc->graphic >= part_3 &&
+ dpc->graphic <= part_8)
+ g->bitmap = NULL;
+ }
+
+ /* set graphics and screen positions of the default wings */
+
+ g_part_1->width = door_rect->width;
+ g_part_1->height = door_rect->height;
+ g_part_2->width = door_rect->width;
+ g_part_2->height = door_rect->height;
+ g_part_2->src_x = door_rect->width;
+ g_part_2->src_y = g_part_1->src_y;
+
+ door->part_2.x = door->part_1.x;
+ door->part_2.y = door->part_1.y;
+
+ if (door->width != -1)
+ {
+ g_part_1->width = door->width;
+ g_part_2->width = door->width;
+
+ // special treatment for graphics and screen position of right wing
+ g_part_2->src_x += door_rect->width - door->width;
+ door->part_2.x += door_rect->width - door->width;
+ }
+
+ if (door->height != -1)
+ {
+ g_part_1->height = door->height;
+ g_part_2->height = door->height;
+
+ // special treatment for graphics and screen position of bottom wing
+ g_part_2->src_y += door_rect->height - door->height;
+ door->part_2.y += door_rect->height - door->height;
+ }
+
+ /* set animation delays for the default wings and panels */
+
+ door->part_1.step_delay = door->step_delay;
+ door->part_2.step_delay = door->step_delay;
+ door->panel.step_delay = door->step_delay;
+
+ /* set animation draw order for the default wings */
+
+ door->part_1.sort_priority = 2; /* draw left wing over ... */
+ door->part_2.sort_priority = 1; /* ... right wing */
+
+ /* set animation draw offset for the default wings */
+
+ if (door->anim_mode & ANIM_HORIZONTAL)
+ {
+ door->part_1.step_xoffset = door->step_offset;
+ door->part_1.step_yoffset = 0;
+ door->part_2.step_xoffset = door->step_offset * -1;
+ door->part_2.step_yoffset = 0;
+
+ num_door_steps = g_part_1->width / door->step_offset;
+ }
+ else // ANIM_VERTICAL
+ {
+ door->part_1.step_xoffset = 0;
+ door->part_1.step_yoffset = door->step_offset;
+ door->part_2.step_xoffset = 0;
+ door->part_2.step_yoffset = door->step_offset * -1;
+
+ num_door_steps = g_part_1->height / door->step_offset;
+ }
+
+ /* set animation draw offset for the default panels */
+
+ if (door->step_offset > 1)
+ {
+ num_panel_steps = 2 * door_rect->height / door->step_offset;
+ door->panel.start_step = num_panel_steps - num_door_steps;
+ }
+ else
+ {
+ num_panel_steps = door_rect->height / door->step_offset;
+ door->panel.start_step = num_panel_steps - num_door_steps / 2;
+ door->panel.step_delay *= 2;
+ }
+ }
+ }
+ }
+}
+
+void InitDoors()
+{
+ int i;
+
+ for (i = 0; door_part_controls[i].door_token != -1; i++)
+ {
+ struct DoorPartControlInfo *dpc = &door_part_controls[i];
+ struct DoorPartOrderInfo *dpo = &door_part_order[i];
+
+ /* initialize "start_step_opening" and "start_step_closing", if needed */
+ if (dpc->pos->start_step_opening == 0 &&
+ dpc->pos->start_step_closing == 0)
+ {
+ // dpc->pos->start_step_opening = dpc->pos->start_step;
+ dpc->pos->start_step_closing = dpc->pos->start_step;
+ }
+
+ /* fill structure for door part draw order (sorted below) */
+ dpo->nr = i;
+ dpo->sort_priority = dpc->pos->sort_priority;
+
+#if 0
+ struct DoorPartPosInfo *pos = dpc->pos;
+
+ printf(":0: step_xoffset == %d, step_yoffset == %d\n",
+ pos->step_xoffset, pos->step_yoffset);
+#endif
+ }
+
+ /* sort door part controls according to sort_priority and graphic number */
+ qsort(door_part_order, MAX_DOOR_PARTS,
+ sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
+}
+
+unsigned int OpenDoor(unsigned int door_state)
+{
+ if (door_state & DOOR_COPY_BACK)
+ {
+#if 1
+ if (door_state & DOOR_OPEN_1)
+ BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
+ 1 * DXSIZE, 0, DXSIZE, DYSIZE, 0 * DXSIZE, 0);
+
+ if (door_state & DOOR_OPEN_2)
+ BlitBitmap(bitmap_db_door_2, bitmap_db_door_2,
+ 1 * VXSIZE, 0, VXSIZE, VYSIZE, 0 * VXSIZE, 0);
+#else
+ if (door_state & DOOR_OPEN_1)
+ BlitBitmap(bitmap_db_door, bitmap_db_door,
+ DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+
+ if (door_state & DOOR_OPEN_2)
+ BlitBitmap(bitmap_db_door, bitmap_db_door,
+ DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+#endif
+
+ door_state &= ~DOOR_COPY_BACK;
+ }
+
+ return MoveDoor(door_state);
+}
+
+unsigned int CloseDoor(unsigned int door_state)
+{
+ unsigned int old_door_state = GetDoorState();
+
+ if (!(door_state & DOOR_NO_COPY_BACK))
+ {
+#if 1
+ if (old_door_state & DOOR_OPEN_1)
+ BlitBitmap(backbuffer, bitmap_db_door_1,
+ DX, DY, DXSIZE, DYSIZE, 0, 0);
+
+ if (old_door_state & DOOR_OPEN_2)
+ BlitBitmap(backbuffer, bitmap_db_door_2,
+ VX, VY, VXSIZE, VYSIZE, 0, 0);
+#else
+ if (old_door_state & DOOR_OPEN_1)
+ BlitBitmap(backbuffer, bitmap_db_door,
+ DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+
+ if (old_door_state & DOOR_OPEN_2)
+ BlitBitmap(backbuffer, bitmap_db_door,
+ VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+#endif
+
+ door_state &= ~DOOR_NO_COPY_BACK;
+ }
+
+ return MoveDoor(door_state);
+}
+
+unsigned int GetDoorState()
+{
+ return MoveDoor(DOOR_GET_STATE);
+}
+
+unsigned int SetDoorState(unsigned int door_state)
+{
+ return MoveDoor(door_state | DOOR_SET_STATE);
+}
+
+#if 1
+
+// ========== TEST 1 ===========================================================
+
+int euclid(int a, int b)
+{
+ return (b ? euclid(b, a % b) : a);
+}
+
+unsigned int MoveDoor(unsigned int door_state)
+{
+#if 0
+ struct XY panel_pos_list[] =
+ {
+ { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
+ { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
+ };
+#endif
+ struct Rect door_rect_list[] =
+ {
+ { DX, DY, DXSIZE, DYSIZE },
+ { VX, VY, VXSIZE, VYSIZE }
+ };
+ static int door1 = DOOR_OPEN_1;
+ static int door2 = DOOR_CLOSE_2;
+ unsigned int door_delay = 0;
+ unsigned int door_delay_value;
+ int i;
+
+#if 1
+ if (door_1.width < 0 || door_1.width > DXSIZE)
+ door_1.width = DXSIZE;
+ if (door_1.height < 0 || door_1.height > DYSIZE)
+ door_1.height = DYSIZE;
+ if (door_2.width < 0 || door_2.width > VXSIZE)
+ door_2.width = VXSIZE;
+ if (door_2.height < 0 || door_2.height > VYSIZE)
+ door_2.height = VYSIZE;
+#endif
+
+ if (door_state == DOOR_GET_STATE)
+ return (door1 | door2);
+
+ if (door_state & DOOR_SET_STATE)
+ {
+ if (door_state & DOOR_ACTION_1)
+ door1 = door_state & DOOR_ACTION_1;
+ if (door_state & DOOR_ACTION_2)
+ door2 = door_state & DOOR_ACTION_2;
+
+ return (door1 | door2);
+ }
+
+ if (!(door_state & DOOR_FORCE_REDRAW))
+ {
+ if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
+ door_state &= ~DOOR_OPEN_1;
+ else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
+ door_state &= ~DOOR_CLOSE_1;
+ if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
+ door_state &= ~DOOR_OPEN_2;
+ else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
+ door_state &= ~DOOR_CLOSE_2;
+ }
+
+#if 0
+ door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
+ door_2.step_delay);
+
+ if (setup.quick_doors)
+ {
+ stepsize = 20; /* must be chosen to always draw last frame */
+ door_delay_value = 0;
+ }
+#endif
+
+ if (global.autoplay_leveldir)
+ {
+ door_state |= DOOR_NO_DELAY;
+ door_state &= ~DOOR_CLOSE_ALL;
+ }
+
+#if 1
+ if (game_status == GAME_MODE_EDITOR)
+ door_state |= DOOR_NO_DELAY;
+#endif
+
+ if (door_state & DOOR_ACTION)
+ {
+ boolean door_panel_drawn[NUM_DOORS];
+ boolean panel_has_doors[NUM_DOORS];
+ boolean door_part_skip[MAX_DOOR_PARTS];
+ boolean door_part_done[MAX_DOOR_PARTS];
+ boolean door_part_done_all;
+ int num_steps[MAX_DOOR_PARTS];
+ int max_move_delay = 0; // delay for complete animations of all doors
+ int max_step_delay = 0; // delay (ms) between two animation frames
+ int num_move_steps = 0; // number of animation steps for all doors
+ int current_move_delay = 0;
+ int k;
+
+ for (i = 0; i < NUM_DOORS; i++)
+ panel_has_doors[i] = FALSE;
+
+ for (i = 0; i < MAX_DOOR_PARTS; i++)
+ {
+ struct DoorPartControlInfo *dpc = &door_part_controls[i];
+ struct GraphicInfo *g = &graphic_info[dpc->graphic];
+ int door_token = dpc->door_token;
+
+ door_part_done[i] = FALSE;
+ door_part_skip[i] = (!(door_state & door_token) ||
+ !g->bitmap);
+ }
+
+#if 0
+ for (i = 0; i < MAX_DOOR_PARTS; i++)
+ {
+ struct DoorPartControlInfo *dpc = &door_part_controls[i];
+ struct DoorPartPosInfo *pos = dpc->pos;
+ int start_step = pos->start_step;
+
+ printf("::: ---> %d: start_step == %d [%d]\n",
+ i, start_step, door_part_done[i]);
+ }
+#endif
+
+ for (i = 0; i < MAX_DOOR_PARTS; i++)
+ {
+ int nr = door_part_order[i].nr;
+ struct DoorPartControlInfo *dpc = &door_part_controls[nr];
+ struct DoorPartPosInfo *pos = dpc->pos;
+ struct GraphicInfo *g = &graphic_info[dpc->graphic];
+ int door_token = dpc->door_token;
+ int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
+ boolean is_panel = DOOR_PART_IS_PANEL(nr);
+ int step_xoffset = ABS(pos->step_xoffset);
+ int step_yoffset = ABS(pos->step_yoffset);
+ int step_delay = pos->step_delay;
+ int current_door_state = door_state & door_token;
+ boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
+ boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
+ boolean part_opening = (is_panel ? door_closing : door_opening);
+ int start_step = (part_opening ? pos->start_step_opening :
+ pos->start_step_closing);
+ float move_xsize = (step_xoffset ? g->width : 0);
+ float move_ysize = (step_yoffset ? g->height : 0);
+ int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
+ int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
+ int move_steps = (move_xsteps && move_ysteps ?
+ MIN(move_xsteps, move_ysteps) :
+ move_xsteps ? move_xsteps : move_ysteps) - start_step;
+ int move_delay = move_steps * step_delay;
+
+ if (door_part_skip[nr])
+ continue;
+
+ if (!is_panel)
+ panel_has_doors[door_index] = TRUE;
+
+ max_move_delay = MAX(max_move_delay, move_delay);
+ max_step_delay = (max_step_delay == 0 ? step_delay :
+ euclid(max_step_delay, step_delay));
+ num_steps[nr] = move_steps;
+
+#if 0
+#if 0
+ printf("::: %d: move_delay == %d, start_step == %d [%d]\n",
+ i, move_delay, start_step, door_part_order[i].nr);
+#else
+ if (DOOR_PART_IS_PANEL(i))
+ printf("::: %d: move_delay == %d, start_step == %d\n",
+ i, move_delay, start_step);
+#endif
+#endif
+ }
+
+ num_move_steps = max_move_delay / max_step_delay;
+
+ door_delay_value = max_step_delay;
+
+#if 0
+ door_delay_value *= 10;
+#endif
+
+#if 0
+ printf("::: num_move_steps == %d, max_move_delay == %d, max_step_delay == %d\n", num_move_steps, max_move_delay, max_step_delay);
+#endif
+
+ for (k = 0; k < num_move_steps; k++)
+ {
+ door_part_done_all = TRUE;
+
+ for (i = 0; i < NUM_DOORS; i++)
+ door_panel_drawn[i] = FALSE;
+
+ for (i = 0; i < MAX_DOOR_PARTS; i++)
+ {
+ int nr = door_part_order[i].nr;
+ struct DoorPartControlInfo *dpc = &door_part_controls[nr];
+ struct DoorPartPosInfo *pos = dpc->pos;
+ struct GraphicInfo *g = &graphic_info[dpc->graphic];
+ int door_token = dpc->door_token;
+ int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
+ boolean is_panel = DOOR_PART_IS_PANEL(nr);
+#if 0
+ struct XY *panel_pos = &panel_pos_list[door_index];
+#endif
+ struct Rect *door_rect = &door_rect_list[door_index];
+ Bitmap *bitmap_db_door = (door_token == DOOR_1 ? bitmap_db_door_1 :
+ bitmap_db_door_2);
+ Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
+ int current_door_state = door_state & door_token;
+ boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
+ boolean door_closing = !door_opening;
+ boolean part_opening = (is_panel ? door_closing : door_opening);
+ boolean part_closing = !part_opening;
+ int start_step = (part_opening ? pos->start_step_opening :
+ pos->start_step_closing);
+ int step_delay = pos->step_delay;
+ int step_factor = step_delay / max_step_delay;
+ int k1 = (step_factor ? k / step_factor + 1 : k);
+ int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
+ int kk = (k2 < 0 ? 0 : k2);
+ int src_x, src_y, src_xx, src_yy;
+ int dst_x, dst_y, dst_xx, dst_yy;
+ int width, height;
+
+#if 0
+ if (k == 0 && is_panel && door_token == DOOR_2)
+ printf("::: %d, %d\n", g->width, g->height);
+#endif
+
+#if 0
+ if (DOOR_PART_IS_PANEL(nr))
+ {
+ int start_step = pos->start_step;
+
+ k2 = (door_closing ? k1 : num_steps[nr] - k1);// - start_step;
+ kk = (k2 < 0 ? 0 : k2);
+ }
+#endif
+
+#if 0
+ // !!! TEST !!!
+ if (nr != 16 && nr != 0)
+ continue;
+#endif
+
+#if 0
+ // !!! TEST !!!
+ if (!is_panel)
+ continue;
+#endif
+
+#if 1
+ if (door_part_skip[nr])
+ continue;
+#endif
+
+ if (!(door_state & door_token))
+ continue;
+
+ if (!g->bitmap)
+ continue;
+
+#if 0
+ if (current_move_delay % step_delay)
+ continue;
+#endif
+
+ // draw door panel
+
+ if (!door_panel_drawn[door_index])
+ {
+#if 1
+ ClearRectangle(drawto, door_rect->x, door_rect->y,
+ door_rect->width, door_rect->height);
+#else
+ BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y,
+ door_rect->width, door_rect->height,
+ door_rect->x, door_rect->y);
+#endif
+
+ door_panel_drawn[door_index] = TRUE;
+ }
+
+ // draw opening or closing door parts
+
+ if (pos->step_xoffset < 0) // door part on right side
+ {
+ src_xx = 0;
+ dst_xx = pos->x + ABS(kk * pos->step_xoffset);
+ width = g->width;
+
+ if (dst_xx + width > door_rect->width)
+ width = door_rect->width - dst_xx;
+ }
+ else // door part on left side
+ {
+ src_xx = 0;
+ dst_xx = pos->x - kk * pos->step_xoffset;
+
+ if (dst_xx < 0)
+ {
+ src_xx = ABS(dst_xx);
+ dst_xx = 0;
+ }
+
+ width = g->width - src_xx;
+
+ // printf("::: k == %d [%d] \n", k, start_step);
+ }
+
+ if (pos->step_yoffset < 0) // door part on bottom side
+ {
+ src_yy = 0;
+ dst_yy = pos->y + ABS(kk * pos->step_yoffset);
+ height = g->height;
+
+ if (dst_yy + height > door_rect->height)
+ height = door_rect->height - dst_yy;
+ }
+ else // door part on top side
+ {
+ src_yy = 0;
+ dst_yy = pos->y - kk * pos->step_yoffset;
+
+ if (dst_yy < 0)
+ {
+ src_yy = ABS(dst_yy);
+ dst_yy = 0;
+ }
+
+ height = g->height - src_yy;
+ }
+
+ if (is_panel)
+ {
+#if 1
+ src_x = src_xx;
+ src_y = src_yy;
+#else
+ src_x = panel_pos->x + src_xx;
+ src_y = panel_pos->y + src_yy;
+#endif
+ }
+ else
+ {
+ src_x = g->src_x + src_xx;
+ src_y = g->src_y + src_yy;
+ }
+
+ dst_x = door_rect->x + dst_xx;
+ dst_y = door_rect->y + dst_yy;
+
+#if 0
+ if (DOOR_PART_IS_PANEL(nr))
+ {
+ printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
+ width, height, g->width, g->height, src_x, src_y);
+ }
+#endif
+
+ if (width >= 0 && width <= g->width &&
+ height >= 0 && height <= g->height)
+ {
+ if (is_panel || !pos->draw_masked)
+ BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
+ dst_x, dst_y);
+ else
+ BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
+ dst_x, dst_y);
+ }
+
+#if 0
+ if (DOOR_PART_IS_PANEL(nr))
+ {
+ bitmap = bitmap_db_door;
+ src_x = panel_pos->x + src_xx;
+ src_y = panel_pos->y + src_yy;
+
+ printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
+ width, height, g->width, g->height, src_x, src_y);
+
+ if (width >= 0 && width <= g->width &&
+ height >= 0 && height <= g->height)
+ BlitBitmap(bitmap, drawto, src_x, src_y,
+ width, height,
+ dst_x, dst_y);
+ }
+#endif
+
+ redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
+
+#if 1
+ if ((part_opening && (width < 0 || height < 0)) ||
+ (part_closing && (width >= g->width && height >= g->height)))
+ door_part_done[nr] = TRUE;
+#else
+ if ((door_opening && (width < 0 || height < 0)) ||
+ (door_closing && (width >= g->width && height >= g->height)))
+ door_part_done[nr] = TRUE;
+#endif
+
+#if 1
+ // continue door part animations, but not panel after door has closed
+ if (!door_part_done[nr] &&
+ !(is_panel && door_closing && panel_has_doors[door_index]))
+ door_part_done_all = FALSE;
+#else
+ // continue door part animations, but not panel after door has closed
+ if (!door_part_done[nr] && !(is_panel && door_closing))
+ door_part_done_all = FALSE;
+#endif
+
+#if 0
+ if (!door_part_done[nr])
+ printf("::: k == %d, nr == %d\n", k, nr);
+#endif
+ }
+
+ if (!(door_state & DOOR_NO_DELAY))
+ {
+ BackToFront();
+
+ if (game_status == GAME_MODE_MAIN)
+ DoAnimation();
+
+ WaitUntilDelayReached(&door_delay, door_delay_value);
+
+ current_move_delay += max_step_delay;
+ }
+
+#if 0
+ door_part_done_all = TRUE;
+
+ for (i = 0; i < MAX_DOOR_PARTS; i++)
+ if (!door_part_done[i] &&
+ !(DOOR_PART_IS_PANEL(i) && door_closing))
+ door_part_done_all = FALSE;
+#endif
+#if 1
+ if (door_part_done_all)
+ break;
+#endif
+ }
+ }
+
+ if (door_state & DOOR_ACTION_1)
+ door1 = door_state & DOOR_ACTION_1;
+ if (door_state & DOOR_ACTION_2)
+ door2 = door_state & DOOR_ACTION_2;
+
+#if 0
+ printf("::: DOORS DONE %08x\n", door_state);
+ Delay(3000);
+ printf("::: GO!\n");
+#endif
+
+ return (door1 | door2);
+}
+
+#else
+
+// ========== OLD ==============================================================
+
+unsigned int MoveDoor(unsigned int door_state)
+{
+ static int door1 = DOOR_OPEN_1;
+ static int door2 = DOOR_CLOSE_2;
+ unsigned int door_delay = 0;
+ unsigned int door_delay_value;
+ int stepsize = 1;
+
+#if 1
+ if (door_1.width < 0 || door_1.width > DXSIZE)
+ door_1.width = DXSIZE;
+ if (door_1.height < 0 || door_1.height > DYSIZE)
+ door_1.height = DYSIZE;
+ if (door_2.width < 0 || door_2.width > VXSIZE)
+ door_2.width = VXSIZE;
+ if (door_2.height < 0 || door_2.height > VYSIZE)
+ door_2.height = VYSIZE;
+#endif
+
+ if (door_state == DOOR_GET_STATE)
+ return (door1 | door2);
+
+ if (door_state & DOOR_SET_STATE)
+ {
+ if (door_state & DOOR_ACTION_1)
+ door1 = door_state & DOOR_ACTION_1;
+ if (door_state & DOOR_ACTION_2)
+ door2 = door_state & DOOR_ACTION_2;
+
+ return (door1 | door2);
+ }
+
+ if (!(door_state & DOOR_FORCE_REDRAW))
+ {
+ if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
+ door_state &= ~DOOR_OPEN_1;
+ else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
+ door_state &= ~DOOR_CLOSE_1;
+ if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
+ door_state &= ~DOOR_OPEN_2;
+ else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
+ door_state &= ~DOOR_CLOSE_2;
+ }
+
+ door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
+ door_2.step_delay);
+
+ // door_delay_value *= 4; // !!! TEST ONLY !!!
+
+ if (setup.quick_doors)
+ {
+ stepsize = 20; /* must be chosen to always draw last frame */
+ door_delay_value = 0;
+ }
+
+ if (global.autoplay_leveldir)
+ {
+ door_state |= DOOR_NO_DELAY;
+ door_state &= ~DOOR_CLOSE_ALL;
+ }
+
+#if 1
+ if (game_status == GAME_MODE_EDITOR)
+ door_state |= DOOR_NO_DELAY;
+#endif
+
+ if (door_state & DOOR_ACTION)
+ {
+#if 1
+ struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
+ struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
+ struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
+ struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
+ int door_1_left_width = g1_left->width;
+ int door_1_left_height = g1_left->height;
+ int door_1_right_width = g1_right->width;
+ int door_1_right_height = g1_right->height;
+ int door_2_left_width = g2_left->width;
+ int door_2_left_height = g2_left->height;
+ int door_2_right_width = g2_right->width;
+ int door_2_right_height = g2_right->height;
+ int door_1_width = MAX(door_1_left_width, door_1_right_width);
+ int door_1_height = MAX(door_1_left_height, door_1_right_height);
+ int door_2_width = MAX(door_2_left_width, door_2_right_width);
+ int door_2_height = MAX(door_2_left_height, door_2_right_height);
+#endif
+ boolean handle_door_1 = (door_state & DOOR_ACTION_1);
+ boolean handle_door_2 = (door_state & DOOR_ACTION_2);
+ boolean door_1_done = (!handle_door_1);
+ boolean door_2_done = (!handle_door_2);
+ boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
+ boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
+#if 1
+#if 1
+ int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
+ int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
+#else
+ int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
+ int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
+#endif
+#else
+ int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
+ int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
+#endif
+ int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
+ int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
+ // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
+ int door_size = (handle_door_2 ? door_size_2 : door_size_1);
+ int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
+ int door_skip = max_door_size - door_size;
+ int end = door_size;
+ int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
+ int k;
+
+ if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
+ {
+ /* opening door sound has priority over simultaneously closing door */
+ if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
+ PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
+ else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
+ PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
+ }
+
+ for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
+ {
+ int x = k;
+#if 0
+ Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+ GC gc = bitmap->stored_clip_gc;
+#endif
+
+ if (door_state & DOOR_ACTION_1 &&
+ x * door_1.step_offset <= door_size_1)
+ {
+ int a = MIN(x * door_1.step_offset, end);
+ int p = (door_state & DOOR_OPEN_1 ? end - a : a);
+#if 1
+ int i = p;
+#else
+ int i = p + door_skip;
+#endif
+
+#if 1
+ struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
+ struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
+ Bitmap *bm_left = g_left->bitmap;
+ Bitmap *bm_right = g_right->bitmap;
+ GC gc_left = bm_left->stored_clip_gc;
+ GC gc_right = bm_right->stored_clip_gc;
+#endif
+
+ int classic_dxsize = 100;
+ int classic_dysize = 280;
+ boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
+ DYSIZE == classic_dysize);
+
+ if (door_1.anim_mode & ANIM_STATIC_PANEL)
+ {
+ BlitBitmap(bitmap_db_door, drawto,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
+ DXSIZE, DYSIZE, DX, DY);
+ }
+ else if (x <= a)
+ {
+ BlitBitmap(bitmap_db_door, drawto,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
+ DXSIZE, DYSIZE - p / 2, DX, DY);
+
+#if 1
+ // printf("::: p == %d\n", p);
+ ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
+#endif
+ }
+
+ if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
+ {
+#if 1
+ int src1_x = g_right->src_x;
+ int src1_y = g_right->src_y;
+ int src2_x = g_left->src_x + g_left->width - i;
+ int src2_y = g_left->src_y;
+ int dst1_x = DX + DXSIZE - i;
+ int dst1_y = DY;
+ int dst2_x = DX;
+ int dst2_y = DY;
+ int width = i;
+ int height = DYSIZE;
+
+ SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
+ BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
+ dst1_x, dst1_y);
+
+ SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
+ BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
+ dst2_x, dst2_y);
+#else
+ int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
+ int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
+ int dst1_x = DX + DXSIZE - i, dst1_y = DY;
+ int dst2_x = DX, dst2_y = DY;
+ int width = i, height = DYSIZE;
+
+ SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
+ BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
+ dst1_x, dst1_y);
+
+ SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
+ BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
+ dst2_x, dst2_y);
+#endif
+ }
+ else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
+ {
+#if 1
+ int src1_x = g_right->src_x;
+ int src1_y = g_right->src_y;
+ int src2_x = g_left->src_x;
+ int src2_y = g_left->src_y + g_left->height - i;
+ int dst1_x = DX;
+ int dst1_y = DY + DYSIZE - i;
+ int dst2_x = DX;
+ int dst2_y = DY;
+ int width = DXSIZE;
+ int height = i;
+
+ SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
+ BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
+ dst1_x, dst1_y);
+
+ SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
+ BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
+ dst2_x, dst2_y);
+#else
+ int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
+ int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
+ int dst1_x = DX, dst1_y = DY + DYSIZE - i;
+ int dst2_x = DX, dst2_y = DY;
+ int width = DXSIZE, height = i;
+
+ SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
+ BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
+ dst1_x, dst1_y);
+
+ SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
+ BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
+ dst2_x, dst2_y);
+#endif
+ }
+ else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
+ {
+ int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
+
+#if 1
+ int src1_x = g_right->src_x;
+ int src1_y = g_right->src_y;
+ int src2_x = g_left->src_x + g_left->width - i;
+ int src2_y = g_left->src_y;
+ int dst1_x = DX + DXSIZE - i;
+ int dst1_y = DY;
+ int dst2_x = DX;
+ int dst2_y = DY;
+ int width = i;
+ int height1 = 63, height2 = DYSIZE / 2 - height1;
+ int ypos1 = 0, ypos2 = height2;
+ int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
+
+ SetClipOrigin(bm_right, gc_right,
+ dst1_x - src1_x, dst1_y - src1_y + j);
+ BlitBitmapMasked(bm_right, drawto,
+ src1_x, src1_y + ypos1, width, height2,
+ dst1_x, dst1_y + ypos1 + j);
+ BlitBitmapMasked(bm_right, drawto,
+ src1_x, src1_y + ypos3, width, height1,
+ dst1_x, dst1_y + ypos3 + j);
+ SetClipOrigin(bm_left, gc_left,
+ dst2_x - src2_x, dst2_y - src2_y - j);
+ BlitBitmapMasked(bm_left, drawto,
+ src2_x, src2_y + ypos1 + j, width, height2 - j,
+ dst2_x, dst2_y + ypos1);
+ BlitBitmapMasked(bm_left, drawto,
+ src2_x, src2_y + ypos3, width, height1,
+ dst2_x, dst2_y + ypos3 - j);
+
+ SetClipOrigin(bm_left, gc_left,
+ dst2_x - src2_x, dst2_y - src2_y - j);
+ BlitBitmapMasked(bm_left, drawto,
+ src2_x, src2_y + ypos2, width, height1,
+ dst2_x, dst2_y + ypos2 - j);
+ BlitBitmapMasked(bm_left, drawto,
+ src2_x, src2_y + ypos4, width, height2,
+ dst2_x, dst2_y + ypos4 - j);
+ SetClipOrigin(bm_right, gc_right,
+ dst1_x - src1_x, dst1_y - src1_y + j);
+ BlitBitmapMasked(bm_right, drawto,
+ src1_x, src1_y + ypos2, width, height1,
+ dst1_x, dst1_y + ypos2 + j);
+ BlitBitmapMasked(bm_right, drawto,
+ src1_x, src1_y + ypos4, width, height2 - j,
+ dst1_x, dst1_y + ypos4 + j);
+
+#else
+ int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
+ int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
+ int dst1_x = DX + DXSIZE - i, dst1_y = DY;
+ int dst2_x = DX, dst2_y = DY;
+ int width = i, height = DYSIZE;
+ int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
+
+ SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
+ BlitBitmapMasked(bitmap, drawto,
+ src1_x, src1_y, width, ypos2,
+ dst1_x, dst1_y + j);
+ BlitBitmapMasked(bitmap, drawto,
+ src1_x, src1_y + ypos3, width, ypos1,
+ dst1_x, dst1_y + ypos3 + j);
+ SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
+ BlitBitmapMasked(bitmap, drawto,
+ src2_x, src2_y + j, width, ypos2 - j,
+ dst2_x, dst2_y);
+ BlitBitmapMasked(bitmap, drawto,
+ src2_x, src2_y + ypos3, width, ypos1,
+ dst2_x, dst2_y + ypos3 - j);
+
+ SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
+ BlitBitmapMasked(bitmap, drawto,
+ src2_x, src2_y + ypos2, width, ypos1,
+ dst2_x, dst2_y + ypos2 - j);
+ BlitBitmapMasked(bitmap, drawto,
+ src2_x, src2_y + ypos4, width, ypos2,
+ dst2_x, dst2_y + ypos4 - j);
+ SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
+ BlitBitmapMasked(bitmap, drawto,
+ src1_x, src1_y + ypos2, width, ypos1,
+ dst1_x, dst1_y + ypos2 + j);
+ BlitBitmapMasked(bitmap, drawto,
+ src1_x, src1_y + ypos4, width, ypos2 - j,
+ dst1_x, dst1_y + ypos4 + j);
+
+ /*
+ SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
+ BlitBitmapMasked(bitmap, drawto,
+ DXSIZE, DOOR_GFX_PAGEY1, i, 77,
+ DX + DXSIZE - i, DY + j);
+ BlitBitmapMasked(bitmap, drawto,
+ DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
+ DX + DXSIZE - i, DY + 140 + j);
+ SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
+ DY - (DOOR_GFX_PAGEY1 + j));
+ BlitBitmapMasked(bitmap, drawto,
+ DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
+ DX, DY);
+ BlitBitmapMasked(bitmap, drawto,
+ DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
+ DX, DY + 140 - j);
+
+ BlitBitmapMasked(bitmap, drawto,
+ DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
+ DX, DY + 77 - j);
+ BlitBitmapMasked(bitmap, drawto,
+ DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
+ DX, DY + 203 - j);
+ SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
+ BlitBitmapMasked(bitmap, drawto,
+ DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
+ DX + DXSIZE - i, DY + 77 + j);
+ BlitBitmapMasked(bitmap, drawto,
+ DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
+ DX + DXSIZE - i, DY + 203 + j);
+ */
+#endif
+ }
+
+ redraw_mask |= REDRAW_DOOR_1;
+ door_1_done = (a == end);
+ }
+
+ if (door_state & DOOR_ACTION_2 &&
+ x * door_2.step_offset <= door_size_2)
+ {
+ int a = MIN(x * door_2.step_offset, door_size);
+ int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
+ int i = p + door_skip;
+
+#if 1
+ struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
+ struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
+ Bitmap *bm_left = g_left->bitmap;
+ Bitmap *bm_right = g_right->bitmap;
+ GC gc_left = bm_left->stored_clip_gc;
+ GC gc_right = bm_right->stored_clip_gc;
+#endif
+
+ int classic_vxsize = 100;
+ int classic_vysize = 100;
+ boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
+ VYSIZE == classic_vysize);
+
+ if (door_2.anim_mode & ANIM_STATIC_PANEL)
+ {
+ BlitBitmap(bitmap_db_door, drawto,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
+ VXSIZE, VYSIZE, VX, VY);
+ }
+ else if (x <= VYSIZE)
+ {
+ BlitBitmap(bitmap_db_door, drawto,
+ DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
+ VXSIZE, VYSIZE - p / 2, VX, VY);
+
+ ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
+ }
+
+ if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
+ {
+#if 1
+ int src1_x = g_right->src_x;
+ int src1_y = g_right->src_y;
+ int src2_x = g_left->src_x + g_left->width - i;
+ int src2_y = g_left->src_y;
+ int dst1_x = VX + VXSIZE - i;
+ int dst1_y = VY;
+ int dst2_x = VX;
+ int dst2_y = VY;
+ int width = i;
+ int height = VYSIZE;
+
+ SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
+ BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
+ dst1_x, dst1_y);
+
+ SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
+ BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
+ dst2_x, dst2_y);
+#else
+ int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
+ int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
+ int dst1_x = VX + VXSIZE - i, dst1_y = VY;
+ int dst2_x = VX, dst2_y = VY;
+ int width = i, height = VYSIZE;
+
+ SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
+ BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
+ dst1_x, dst1_y);
+
+ SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
+ BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
+ dst2_x, dst2_y);
+#endif
+ }
+ else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
+ {
+#if 1
+ int src1_x = g_right->src_x;
+ int src1_y = g_right->src_y;
+ int src2_x = g_left->src_x;
+ int src2_y = g_left->src_y + g_left->height - i;
+ int dst1_x = VX;
+ int dst1_y = VY + VYSIZE - i;
+ int dst2_x = VX;
+ int dst2_y = VY;
+ int width = VXSIZE;
+ int height = i;
+
+ SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
+ BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
+ dst1_x, dst1_y);
+
+ SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
+ BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
+ dst2_x, dst2_y);
+#else
+ int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
+ int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
+ int dst1_x = VX, dst1_y = VY + VYSIZE - i;
+ int dst2_x = VX, dst2_y = VY;
+ int width = VXSIZE, height = i;
+
+ SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
+ BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
+ dst1_x, dst1_y);
+
+ SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
+ BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
+ dst2_x, dst2_y);
+#endif
+ }
+ else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
+ {
+ int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
+
+#if 1
+ int src1_x = g_right->src_x;
+ int src1_y = g_right->src_y;
+ int src2_x = g_left->src_x + g_left->width - i;
+ int src2_y = g_left->src_y;
+ int dst1_x = VX + VXSIZE - i;
+ int dst1_y = VY;
+ int dst2_x = VX;
+ int dst2_y = VY;
+ int width = i;
+ int height = VYSIZE / 2;
+ int ypos1 = 0, ypos2 = VYSIZE / 2;
+
+ SetClipOrigin(bm_right, gc_right,
+ dst1_x - src1_x, dst1_y - src1_y + j);
+ BlitBitmapMasked(bm_right, drawto,
+ src1_x, src1_y + ypos1, width, height,
+ dst1_x, dst1_y + ypos1 + j);
+ SetClipOrigin(bm_left, gc_left,
+ dst2_x - src2_x, dst2_y - src2_y - j);
+ BlitBitmapMasked(bm_left, drawto,
+ src2_x, src2_y + ypos1 + j, width, height - j,
+ dst2_x, dst2_y + ypos1);
+
+ SetClipOrigin(bm_left, gc_left,
+ dst2_x - src2_x, dst2_y - src2_y - j);
+ BlitBitmapMasked(bm_left, drawto,
+ src2_x, src2_y + ypos2, width, height,
+ dst2_x, dst2_y + ypos2 - j);
+ SetClipOrigin(bm_right, gc_right,
+ dst1_x - src1_x, dst1_y - src1_y + j);
+ BlitBitmapMasked(bm_right, drawto,
+ src1_x, src1_y + ypos2, width, height - j,
+ dst1_x, dst1_y + ypos2 + j);
+#else
+ int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
+ int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
+ int dst1_x = VX + VXSIZE - i, dst1_y = VY;
+ int dst2_x = VX, dst2_y = VY;
+ int width = i, height = VYSIZE;
+ int ypos = VYSIZE / 2;
+
+ SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
+ BlitBitmapMasked(bitmap, drawto,
+ src1_x, src1_y, width, ypos,
+ dst1_x, dst1_y + j);
+ SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
+ BlitBitmapMasked(bitmap, drawto,
+ src2_x, src2_y + j, width, ypos - j,
+ dst2_x, dst2_y);
+
+ SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
+ BlitBitmapMasked(bitmap, drawto,
+ src2_x, src2_y + ypos, width, ypos,
+ dst2_x, dst2_y + ypos - j);
+ SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
+ BlitBitmapMasked(bitmap, drawto,
+ src1_x, src1_y + ypos, width, ypos - j,
+ dst1_x, dst1_y + ypos + j);
+
+ /*
+ SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
+ BlitBitmapMasked(bitmap, drawto,
+ VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
+ VX + VXSIZE - i, VY + j);
+ SetClipOrigin(bitmap, gc,
+ VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
+ BlitBitmapMasked(bitmap, drawto,
+ VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
+ VX, VY);
+
+ BlitBitmapMasked(bitmap, drawto,
+ VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
+ i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
+ SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
+ BlitBitmapMasked(bitmap, drawto,
+ VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
+ i, VYSIZE / 2 - j,
+ VX + VXSIZE - i, VY + VYSIZE / 2 + j);
+ */
+#endif
+ }
+
+ redraw_mask |= REDRAW_DOOR_2;
+ door_2_done = (a == VXSIZE);
+ }
+
+ if (!(door_state & DOOR_NO_DELAY))
+ {
+ BackToFront();
+
+ if (game_status == GAME_MODE_MAIN)
+ DoAnimation();
+
+ WaitUntilDelayReached(&door_delay, door_delay_value);
+ }
+ }
+ }
+
+ if (door_state & DOOR_ACTION_1)
+ door1 = door_state & DOOR_ACTION_1;
+ if (door_state & DOOR_ACTION_2)
+ door2 = door_state & DOOR_ACTION_2;
+
+ return (door1 | door2);
+}
+
+#endif
+
+void DrawSpecialEditorDoor()
+{
+#if 1
+ struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
+ int top_border_width = gfx1->width;
+ int top_border_height = gfx1->height;
+ int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
+ int ex = EX - outer_border;
+ int ey = EY - outer_border;
+ int vy = VY - outer_border;
+ int exsize = EXSIZE + 2 * outer_border;
+
+ CloseDoor(DOOR_CLOSE_2);
+
+ /* draw bigger level editor toolbox window */
+ BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
+ top_border_width, top_border_height, ex, ey - top_border_height);
+ BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
+ exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
+#else
+ /* draw bigger level editor toolbox window */
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
+ EX - 4, EY - 12);
+ BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
+ EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
+ EX - 6, EY - 4);
+#endif
+
+ redraw_mask |= REDRAW_ALL;
+}
+
+void UndrawSpecialEditorDoor()
+{
+#if 1
+ struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
+ int top_border_width = gfx1->width;
+ int top_border_height = gfx1->height;
+ int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
+ int ex = EX - outer_border;
+ int ey = EY - outer_border;
+ int ey_top = ey - top_border_height;
+ int exsize = EXSIZE + 2 * outer_border;
+ int eysize = EYSIZE + 2 * outer_border;
+
+ /* draw normal tape recorder window */
+ if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
+ {
+ BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
+ ex, ey_top, top_border_width, top_border_height,
+ ex, ey_top);
+ BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
+ ex, ey, exsize, eysize, ex, ey);
+ }
+ else
+ {
+ // if screen background is set to "[NONE]", clear editor toolbox window
+ ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
+ ClearRectangle(drawto, ex, ey, exsize, eysize);
+ }
+#else
+ /* draw normal tape recorder window */
+ BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
+ EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
+ EX - 6, EY - 12);
+#endif
+
+ redraw_mask |= REDRAW_ALL;
+}
+
+
+/* ---------- new tool button stuff ---------------------------------------- */
+
+#if 1
+
+static struct
+{
+ int graphic;
+ struct TextPosInfo *pos;
+ int gadget_id;
+ char *infotext;
+} toolbutton_info[NUM_TOOL_BUTTONS] =
+{
+ {
+ IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
+ TOOL_CTRL_ID_YES, "yes"
+ },
+ {
+ IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
+ TOOL_CTRL_ID_NO, "no"
+ },
+ {
+ IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
+ TOOL_CTRL_ID_CONFIRM, "confirm"
+ },
+ {
+ IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
+ TOOL_CTRL_ID_PLAYER_1, "player 1"
+ },
+ {
+ IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
+ TOOL_CTRL_ID_PLAYER_2, "player 2"
+ },
+ {
+ IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
+ TOOL_CTRL_ID_PLAYER_3, "player 3"
+ },
+ {
+ IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
+ TOOL_CTRL_ID_PLAYER_4, "player 4"
+ }
+};
+
+void CreateToolButtons()
+{
+ int i;
+
+ for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+ {
+ struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
+ struct TextPosInfo *pos = toolbutton_info[i].pos;
+ struct GadgetInfo *gi;
+ Bitmap *deco_bitmap = None;
+ int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
+ unsigned int event_mask = GD_EVENT_RELEASED;
+ int dx = DX;
+ int dy = DY;
+ int gd_x = gfx->src_x;
+ int gd_y = gfx->src_y;
+ int gd_xp = gfx->src_x + gfx->pressed_xoffset;
+ int gd_yp = gfx->src_y + gfx->pressed_yoffset;
+ int id = i;
+
+ if (global.use_envelope_request)
+ setRequestPosition(&dx, &dy, TRUE);
+
+ if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
+ {
+ int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
+
+ getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
+ pos->size, &deco_bitmap, &deco_x, &deco_y);
+ deco_xpos = (gfx->width - pos->size) / 2;
+ deco_ypos = (gfx->height - pos->size) / 2;
+ }
+
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_INFO_TEXT, toolbutton_info[i].infotext,
+ GDI_X, dx + GDI_ACTIVE_POS(pos->x),
+ GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
+ GDI_WIDTH, gfx->width,
+ GDI_HEIGHT, gfx->height,
+ GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
+ GDI_STATE, GD_BUTTON_UNPRESSED,
+ GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
+ GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
+ GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
+ GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
+ GDI_DECORATION_SIZE, pos->size, pos->size,
+ GDI_DECORATION_SHIFTING, 1, 1,
+ GDI_DIRECT_DRAW, FALSE,
+ GDI_EVENT_MASK, event_mask,
+ GDI_CALLBACK_ACTION, HandleToolButtons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ tool_gadget[id] = gi;
+ }
+}
+
+#else
+
+/* graphic position values for tool buttons */
+#define TOOL_BUTTON_YES_XPOS 2
+#define TOOL_BUTTON_YES_YPOS 250
+#define TOOL_BUTTON_YES_GFX_YPOS 0
+#define TOOL_BUTTON_YES_XSIZE 46
+#define TOOL_BUTTON_YES_YSIZE 28
+#define TOOL_BUTTON_NO_XPOS 52
+#define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
+#define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
+#define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
+#define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
+#define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
+#define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
+#define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
+#define TOOL_BUTTON_CONFIRM_XSIZE 96
+#define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
+#define TOOL_BUTTON_PLAYER_XSIZE 30
+#define TOOL_BUTTON_PLAYER_YSIZE 30
+#define TOOL_BUTTON_PLAYER_GFX_XPOS 5
+#define TOOL_BUTTON_PLAYER_GFX_YPOS 185
+#define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
+#define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
+#define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
+ + 0 * TOOL_BUTTON_PLAYER_XSIZE)
+#define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
+ + 1 * TOOL_BUTTON_PLAYER_XSIZE)
+#define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
+ + 0 * TOOL_BUTTON_PLAYER_XSIZE)
+#define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
+ + 1 * TOOL_BUTTON_PLAYER_XSIZE)
+#define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
+ + 0 * TOOL_BUTTON_PLAYER_YSIZE)
+#define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
+ + 0 * TOOL_BUTTON_PLAYER_YSIZE)
+#define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
+ + 1 * TOOL_BUTTON_PLAYER_YSIZE)
+#define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
+ + 1 * TOOL_BUTTON_PLAYER_YSIZE)
+
+static struct
+{
+ int xpos, ypos;
+ int x, y;
+ int width, height;
+ int gadget_id;
+ char *infotext;
+} toolbutton_info[NUM_TOOL_BUTTONS] =
+{
+ {
+ TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
+ TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
+ TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
+ TOOL_CTRL_ID_YES,
+ "yes"
+ },
+ {
+ TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
+ TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
+ TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
+ TOOL_CTRL_ID_NO,
+ "no"
+ },
+ {
+ TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
+ TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
+ TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
+ TOOL_CTRL_ID_CONFIRM,
+ "confirm"
+ },
+ {
+ TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
+ TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
+ TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
+ TOOL_CTRL_ID_PLAYER_1,
+ "player 1"
+ },
+ {
+ TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
+ TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
+ TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
+ TOOL_CTRL_ID_PLAYER_2,
+ "player 2"
+ },
+ {
+ TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
+ TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
+ TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
+ TOOL_CTRL_ID_PLAYER_3,
+ "player 3"
+ },
+ {
+ TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
+ TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
+ TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
+ TOOL_CTRL_ID_PLAYER_4,
+ "player 4"
+ }
+};
+
+void CreateToolButtons()
+{
+ int i;
+
+ for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+ {
+ Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+ Bitmap *deco_bitmap = None;
+ int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
+ struct GadgetInfo *gi;
+ unsigned int event_mask;
+ int gd_xoffset, gd_yoffset;
+ int gd_x1, gd_x2, gd_y;
+ int id = i;
+
+ event_mask = GD_EVENT_RELEASED;
+
+ gd_xoffset = toolbutton_info[i].xpos;
+ gd_yoffset = toolbutton_info[i].ypos;
+ gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
+ gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
+ gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
+
+ if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
+ {
+ int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
+
+ getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
+ &deco_bitmap, &deco_x, &deco_y);
+ deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
+ deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
+ }
+
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_INFO_TEXT, toolbutton_info[i].infotext,
+ GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
+ GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
+ GDI_WIDTH, toolbutton_info[i].width,
+ GDI_HEIGHT, toolbutton_info[i].height,
+ GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
+ GDI_STATE, GD_BUTTON_UNPRESSED,
+ GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+ GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+ GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
+ GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
+ GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
+ GDI_DECORATION_SHIFTING, 1, 1,
+ GDI_DIRECT_DRAW, FALSE,
+ GDI_EVENT_MASK, event_mask,
+ GDI_CALLBACK_ACTION, HandleToolButtons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ tool_gadget[id] = gi;
+ }
+}
+
+#endif
+
+void FreeToolButtons()
+{
+ int i;
+
+ for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+ FreeGadget(tool_gadget[i]);
+}
+
+static void UnmapToolButtons()
+{
+ int i;
+
+ for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+ UnmapGadget(tool_gadget[i]);
+}
+
+static void HandleToolButtons(struct GadgetInfo *gi)
+{
+ request_gadget_id = gi->custom_id;
+}
+
+static struct Mapping_EM_to_RND_object
+{
+ int element_em;
+ boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
+ boolean is_backside; /* backside of moving element */
+
+ int element_rnd;
+ int action;
+ int direction;
+}
+em_object_mapping_list[] =
+{
+ {
+ Xblank, TRUE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Yacid_splash_eB, FALSE, FALSE,
+ EL_ACID_SPLASH_RIGHT, -1, -1
+ },
+ {
+ Yacid_splash_wB, FALSE, FALSE,
+ EL_ACID_SPLASH_LEFT, -1, -1
+ },
+
+#ifdef EM_ENGINE_BAD_ROLL
+ {
+ Xstone_force_e, FALSE, FALSE,
+ EL_ROCK, -1, MV_BIT_RIGHT
+ },
+ {
+ Xstone_force_w, FALSE, FALSE,
+ EL_ROCK, -1, MV_BIT_LEFT
+ },
+ {
+ Xnut_force_e, FALSE, FALSE,
+ EL_NUT, -1, MV_BIT_RIGHT
+ },
+ {
+ Xnut_force_w, FALSE, FALSE,
+ EL_NUT, -1, MV_BIT_LEFT
+ },
+ {
+ Xspring_force_e, FALSE, FALSE,
+ EL_SPRING, -1, MV_BIT_RIGHT
+ },
+ {
+ Xspring_force_w, FALSE, FALSE,
+ EL_SPRING, -1, MV_BIT_LEFT
+ },
+ {
+ Xemerald_force_e, FALSE, FALSE,
+ EL_EMERALD, -1, MV_BIT_RIGHT
+ },
+ {
+ Xemerald_force_w, FALSE, FALSE,
+ EL_EMERALD, -1, MV_BIT_LEFT
+ },
+ {
+ Xdiamond_force_e, FALSE, FALSE,
+ EL_DIAMOND, -1, MV_BIT_RIGHT
+ },
+ {
+ Xdiamond_force_w, FALSE, FALSE,
+ EL_DIAMOND, -1, MV_BIT_LEFT
+ },
+ {
+ Xbomb_force_e, FALSE, FALSE,
+ EL_BOMB, -1, MV_BIT_RIGHT
+ },
+ {
+ Xbomb_force_w, FALSE, FALSE,
+ EL_BOMB, -1, MV_BIT_LEFT
+ },
+#endif /* EM_ENGINE_BAD_ROLL */
+
+ {
+ Xstone, TRUE, FALSE,
+ EL_ROCK, -1, -1
+ },
+ {
+ Xstone_pause, FALSE, FALSE,
+ EL_ROCK, -1, -1
+ },
+ {
+ Xstone_fall, FALSE, FALSE,
+ EL_ROCK, -1, -1
+ },
+ {
+ Ystone_s, FALSE, FALSE,
+ EL_ROCK, ACTION_FALLING, -1
+ },
+ {
+ Ystone_sB, FALSE, TRUE,
+ EL_ROCK, ACTION_FALLING, -1
+ },
+ {
+ Ystone_e, FALSE, FALSE,
+ EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ystone_eB, FALSE, TRUE,
+ EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ystone_w, FALSE, FALSE,