+ 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