+ if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) &&
+ IS_IN_GROUP_EL(IntelliDrawBuffer[last_x][last_y], new_element))
+ connected_drawing = TRUE;
+ }
+
+ if (!connected_drawing)
+ ResolveGroupElement(new_element);
+
+ new_element = GetElementFromGroupElement(new_element);
+ }
+ else if (IS_BELT_SWITCH(old_element))
+ {
+ int belt_nr = getBeltNrFromBeltSwitchElement(old_element);
+ int belt_dir = getBeltDirFromBeltSwitchElement(old_element);
+
+ belt_dir = (belt_dir == MV_LEFT ? MV_NONE :
+ belt_dir == MV_NONE ? MV_RIGHT : MV_LEFT);
+
+ new_element = getBeltSwitchElementFromBeltNrAndBeltDir(belt_nr, belt_dir);
+ }
+ else
+ {
+ static int swappable_elements[][2] =
+ {
+ { EL_EXIT_CLOSED, EL_EXIT_OPEN },
+ { EL_DYNAMITE, EL_DYNAMITE_ACTIVE },
+ { EL_EM_DYNAMITE, EL_EM_DYNAMITE_ACTIVE },
+ { EL_QUICKSAND_EMPTY, EL_QUICKSAND_FULL },
+ { EL_EMERALD, EL_WALL_EMERALD },
+ { EL_EMERALD_YELLOW, EL_WALL_EMERALD_YELLOW },
+ { EL_EMERALD_RED, EL_WALL_EMERALD_RED },
+ { EL_EMERALD_PURPLE, EL_WALL_EMERALD_PURPLE },
+ { EL_DIAMOND, EL_WALL_DIAMOND },
+ { EL_BD_DIAMOND, EL_WALL_BD_DIAMOND },
+ { EL_GATE_1, EL_GATE_1_GRAY },
+ { EL_GATE_2, EL_GATE_2_GRAY },
+ { EL_GATE_3, EL_GATE_3_GRAY },
+ { EL_GATE_4, EL_GATE_4_GRAY },
+ { EL_EM_GATE_1, EL_EM_GATE_1_GRAY },
+ { EL_EM_GATE_2, EL_EM_GATE_2_GRAY },
+ { EL_EM_GATE_3, EL_EM_GATE_3_GRAY },
+ { EL_EM_GATE_4, EL_EM_GATE_4_GRAY },
+ { EL_EMC_GATE_5, EL_EMC_GATE_5_GRAY },
+ { EL_EMC_GATE_6, EL_EMC_GATE_6_GRAY },
+ { EL_EMC_GATE_7, EL_EMC_GATE_7_GRAY },
+ { EL_EMC_GATE_8, EL_EMC_GATE_8_GRAY },
+ { EL_DC_GATE_WHITE, EL_DC_GATE_WHITE_GRAY },
+ { EL_TIME_ORB_EMPTY, EL_TIME_ORB_FULL },
+ { EL_LAMP, EL_LAMP_ACTIVE },
+ { EL_SOKOBAN_FIELD_EMPTY, EL_SOKOBAN_FIELD_FULL },
+ { EL_SP_BASE, EL_SP_BUGGY_BASE },
+ { EL_PEARL, EL_WALL_PEARL },
+ { EL_CRYSTAL, EL_WALL_CRYSTAL },
+ { EL_TIMEGATE_CLOSED, EL_TIMEGATE_OPEN },
+ { EL_SWITCHGATE_CLOSED, EL_SWITCHGATE_OPEN },
+ { EL_SWITCHGATE_SWITCH_UP, EL_SWITCHGATE_SWITCH_DOWN },
+ { EL_DC_SWITCHGATE_SWITCH_UP, EL_DC_SWITCHGATE_SWITCH_DOWN },
+ { EL_LIGHT_SWITCH, EL_LIGHT_SWITCH_ACTIVE },
+ { EL_LANDMINE, EL_DC_LANDMINE },
+ { EL_SHIELD_NORMAL, EL_SHIELD_DEADLY },
+ { EL_STEEL_EXIT_CLOSED, EL_STEEL_EXIT_OPEN },
+ { EL_EM_EXIT_CLOSED, EL_EM_EXIT_OPEN },
+ { EL_EM_STEEL_EXIT_CLOSED, EL_EM_STEEL_EXIT_OPEN },
+ { EL_QUICKSAND_FAST_EMPTY, EL_QUICKSAND_FAST_FULL },
+ { EL_MM_EXIT_CLOSED, EL_MM_EXIT_OPEN },
+ { EL_MM_FUSE, EL_MM_FUSE_ACTIVE },
+ { EL_MM_LIGHTBULB, EL_MM_LIGHTBULB_ACTIVE },
+ { EL_MM_FUEL_EMPTY, EL_MM_FUEL_FULL },
+
+ { -1, -1 },
+ };
+ static int rotatable_elements_4[][4] =
+ {
+ {
+ EL_BUG_UP,
+ EL_BUG_RIGHT,
+ EL_BUG_DOWN,
+ EL_BUG_LEFT
+ },
+ {
+ EL_SPACESHIP_UP,
+ EL_SPACESHIP_RIGHT,
+ EL_SPACESHIP_DOWN,
+ EL_SPACESHIP_LEFT
+ },
+ {
+ EL_BD_BUTTERFLY_UP,
+ EL_BD_BUTTERFLY_RIGHT,
+ EL_BD_BUTTERFLY_DOWN,
+ EL_BD_BUTTERFLY_LEFT
+ },
+ {
+ EL_BD_FIREFLY_UP,
+ EL_BD_FIREFLY_RIGHT,
+ EL_BD_FIREFLY_DOWN,
+ EL_BD_FIREFLY_LEFT
+ },
+ {
+ EL_PACMAN_UP,
+ EL_PACMAN_RIGHT,
+ EL_PACMAN_DOWN,
+ EL_PACMAN_LEFT
+ },
+ {
+ EL_YAMYAM_UP,
+ EL_YAMYAM_RIGHT,
+ EL_YAMYAM_DOWN,
+ EL_YAMYAM_LEFT
+ },
+ {
+ EL_ARROW_UP,
+ EL_ARROW_RIGHT,
+ EL_ARROW_DOWN,
+ EL_ARROW_LEFT
+ },
+ {
+ EL_SP_PORT_UP,
+ EL_SP_PORT_RIGHT,
+ EL_SP_PORT_DOWN,
+ EL_SP_PORT_LEFT
+ },
+ {
+ EL_SP_GRAVITY_PORT_UP,
+ EL_SP_GRAVITY_PORT_RIGHT,
+ EL_SP_GRAVITY_PORT_DOWN,
+ EL_SP_GRAVITY_PORT_LEFT
+ },
+ {
+ EL_SP_GRAVITY_ON_PORT_UP,
+ EL_SP_GRAVITY_ON_PORT_RIGHT,
+ EL_SP_GRAVITY_ON_PORT_DOWN,
+ EL_SP_GRAVITY_ON_PORT_LEFT
+ },
+ {
+ EL_SP_GRAVITY_OFF_PORT_UP,
+ EL_SP_GRAVITY_OFF_PORT_RIGHT,
+ EL_SP_GRAVITY_OFF_PORT_DOWN,
+ EL_SP_GRAVITY_OFF_PORT_LEFT
+ },
+ {
+ EL_MOLE_UP,
+ EL_MOLE_RIGHT,
+ EL_MOLE_DOWN,
+ EL_MOLE_LEFT
+ },
+ {
+ EL_BALLOON_SWITCH_UP,
+ EL_BALLOON_SWITCH_RIGHT,
+ EL_BALLOON_SWITCH_DOWN,
+ EL_BALLOON_SWITCH_LEFT
+ },
+ {
+ EL_MM_MCDUFFIN_UP,
+ EL_MM_MCDUFFIN_RIGHT,
+ EL_MM_MCDUFFIN_DOWN,
+ EL_MM_MCDUFFIN_LEFT
+ },
+ {
+ EL_MM_MIRROR_FIXED_1,
+ EL_MM_MIRROR_FIXED_4,
+ EL_MM_MIRROR_FIXED_3,
+ EL_MM_MIRROR_FIXED_2
+ },
+ {
+ EL_MM_STEEL_GRID_FIXED_1,
+ EL_MM_STEEL_GRID_FIXED_4,
+ EL_MM_STEEL_GRID_FIXED_2,
+ EL_MM_STEEL_GRID_FIXED_3
+ },
+ {
+ EL_MM_WOODEN_GRID_FIXED_1,
+ EL_MM_WOODEN_GRID_FIXED_4,
+ EL_MM_WOODEN_GRID_FIXED_2,
+ EL_MM_WOODEN_GRID_FIXED_3
+ },
+ {
+ EL_MM_POLARISATOR_CROSS_1,
+ EL_MM_POLARISATOR_CROSS_4,
+ EL_MM_POLARISATOR_CROSS_3,
+ EL_MM_POLARISATOR_CROSS_2
+ },
+ {
+ EL_MM_PACMAN_UP,
+ EL_MM_PACMAN_RIGHT,
+ EL_MM_PACMAN_DOWN,
+ EL_MM_PACMAN_LEFT
+ },
+ {
+ EL_DF_LASER_UP,
+ EL_DF_LASER_RIGHT,
+ EL_DF_LASER_DOWN,
+ EL_DF_LASER_LEFT
+ },
+ {
+ EL_DF_RECEIVER_UP,
+ EL_DF_RECEIVER_RIGHT,
+ EL_DF_RECEIVER_DOWN,
+ EL_DF_RECEIVER_LEFT
+ },
+
+ {
+ -1,
+ },
+ };
+ static int rotatable_elements_8[][8] =
+ {
+ {
+ EL_DF_STEEL_GRID_FIXED_1,
+ EL_DF_STEEL_GRID_FIXED_8,
+ EL_DF_STEEL_GRID_FIXED_7,
+ EL_DF_STEEL_GRID_FIXED_6,
+ EL_DF_STEEL_GRID_FIXED_5,
+ EL_DF_STEEL_GRID_FIXED_4,
+ EL_DF_STEEL_GRID_FIXED_3,
+ EL_DF_STEEL_GRID_FIXED_2
+ },
+ {
+ EL_DF_WOODEN_GRID_FIXED_1,
+ EL_DF_WOODEN_GRID_FIXED_8,
+ EL_DF_WOODEN_GRID_FIXED_7,
+ EL_DF_WOODEN_GRID_FIXED_6,
+ EL_DF_WOODEN_GRID_FIXED_5,
+ EL_DF_WOODEN_GRID_FIXED_4,
+ EL_DF_WOODEN_GRID_FIXED_3,
+ EL_DF_WOODEN_GRID_FIXED_2
+ },
+ {
+ EL_DF_STEEL_GRID_ROTATING_1,
+ EL_DF_STEEL_GRID_ROTATING_8,
+ EL_DF_STEEL_GRID_ROTATING_7,
+ EL_DF_STEEL_GRID_ROTATING_6,
+ EL_DF_STEEL_GRID_ROTATING_5,
+ EL_DF_STEEL_GRID_ROTATING_4,
+ EL_DF_STEEL_GRID_ROTATING_3,
+ EL_DF_STEEL_GRID_ROTATING_2
+ },
+ {
+ EL_DF_WOODEN_GRID_ROTATING_1,
+ EL_DF_WOODEN_GRID_ROTATING_8,
+ EL_DF_WOODEN_GRID_ROTATING_7,
+ EL_DF_WOODEN_GRID_ROTATING_6,
+ EL_DF_WOODEN_GRID_ROTATING_5,
+ EL_DF_WOODEN_GRID_ROTATING_4,
+ EL_DF_WOODEN_GRID_ROTATING_3,
+ EL_DF_WOODEN_GRID_ROTATING_2
+ },
+
+ {
+ -1,
+ },
+ };
+ static int rotatable_elements_16[][16] =
+ {
+ {
+ EL_MM_MIRROR_1,
+ EL_MM_MIRROR_16,
+ EL_MM_MIRROR_15,
+ EL_MM_MIRROR_14,
+ EL_MM_MIRROR_13,
+ EL_MM_MIRROR_12,
+ EL_MM_MIRROR_11,
+ EL_MM_MIRROR_10,
+ EL_MM_MIRROR_9,
+ EL_MM_MIRROR_8,
+ EL_MM_MIRROR_7,
+ EL_MM_MIRROR_6,
+ EL_MM_MIRROR_5,
+ EL_MM_MIRROR_4,
+ EL_MM_MIRROR_3,
+ EL_MM_MIRROR_2
+ },
+ {
+ EL_MM_BEAMER_5,
+ EL_MM_BEAMER_4,
+ EL_MM_BEAMER_3,
+ EL_MM_BEAMER_2,
+ EL_MM_BEAMER_1,
+ EL_MM_BEAMER_16,
+ EL_MM_BEAMER_15,
+ EL_MM_BEAMER_14,
+ EL_MM_BEAMER_13,
+ EL_MM_BEAMER_12,
+ EL_MM_BEAMER_11,
+ EL_MM_BEAMER_10,
+ EL_MM_BEAMER_9,
+ EL_MM_BEAMER_8,
+ EL_MM_BEAMER_7,
+ EL_MM_BEAMER_6
+ },
+ {
+ EL_MM_BEAMER_RED_5,
+ EL_MM_BEAMER_RED_4,
+ EL_MM_BEAMER_RED_3,
+ EL_MM_BEAMER_RED_2,
+ EL_MM_BEAMER_RED_1,
+ EL_MM_BEAMER_RED_16,
+ EL_MM_BEAMER_RED_15,
+ EL_MM_BEAMER_RED_14,
+ EL_MM_BEAMER_RED_13,
+ EL_MM_BEAMER_RED_12,
+ EL_MM_BEAMER_RED_11,
+ EL_MM_BEAMER_RED_10,
+ EL_MM_BEAMER_RED_9,
+ EL_MM_BEAMER_RED_8,
+ EL_MM_BEAMER_RED_7,
+ EL_MM_BEAMER_RED_6
+ },
+ {
+ EL_MM_BEAMER_YELLOW_5,
+ EL_MM_BEAMER_YELLOW_4,
+ EL_MM_BEAMER_YELLOW_3,
+ EL_MM_BEAMER_YELLOW_2,
+ EL_MM_BEAMER_YELLOW_1,
+ EL_MM_BEAMER_YELLOW_16,
+ EL_MM_BEAMER_YELLOW_15,
+ EL_MM_BEAMER_YELLOW_14,
+ EL_MM_BEAMER_YELLOW_13,
+ EL_MM_BEAMER_YELLOW_12,
+ EL_MM_BEAMER_YELLOW_11,
+ EL_MM_BEAMER_YELLOW_10,
+ EL_MM_BEAMER_YELLOW_9,
+ EL_MM_BEAMER_YELLOW_8,
+ EL_MM_BEAMER_YELLOW_7,
+ EL_MM_BEAMER_YELLOW_6
+ },
+ {
+ EL_MM_BEAMER_GREEN_5,
+ EL_MM_BEAMER_GREEN_4,
+ EL_MM_BEAMER_GREEN_3,
+ EL_MM_BEAMER_GREEN_2,
+ EL_MM_BEAMER_GREEN_1,
+ EL_MM_BEAMER_GREEN_16,
+ EL_MM_BEAMER_GREEN_15,
+ EL_MM_BEAMER_GREEN_14,
+ EL_MM_BEAMER_GREEN_13,
+ EL_MM_BEAMER_GREEN_12,
+ EL_MM_BEAMER_GREEN_11,
+ EL_MM_BEAMER_GREEN_10,
+ EL_MM_BEAMER_GREEN_9,
+ EL_MM_BEAMER_GREEN_8,
+ EL_MM_BEAMER_GREEN_7,
+ EL_MM_BEAMER_GREEN_6
+ },
+ {
+ EL_MM_BEAMER_BLUE_5,
+ EL_MM_BEAMER_BLUE_4,
+ EL_MM_BEAMER_BLUE_3,
+ EL_MM_BEAMER_BLUE_2,
+ EL_MM_BEAMER_BLUE_1,
+ EL_MM_BEAMER_BLUE_16,
+ EL_MM_BEAMER_BLUE_15,
+ EL_MM_BEAMER_BLUE_14,
+ EL_MM_BEAMER_BLUE_13,
+ EL_MM_BEAMER_BLUE_12,
+ EL_MM_BEAMER_BLUE_11,
+ EL_MM_BEAMER_BLUE_10,
+ EL_MM_BEAMER_BLUE_9,
+ EL_MM_BEAMER_BLUE_8,
+ EL_MM_BEAMER_BLUE_7,
+ EL_MM_BEAMER_BLUE_6
+ },
+ {
+ EL_MM_POLARISATOR_1,
+ EL_MM_POLARISATOR_16,
+ EL_MM_POLARISATOR_15,
+ EL_MM_POLARISATOR_14,
+ EL_MM_POLARISATOR_13,
+ EL_MM_POLARISATOR_12,
+ EL_MM_POLARISATOR_11,
+ EL_MM_POLARISATOR_10,
+ EL_MM_POLARISATOR_9,
+ EL_MM_POLARISATOR_8,
+ EL_MM_POLARISATOR_7,
+ EL_MM_POLARISATOR_6,
+ EL_MM_POLARISATOR_5,
+ EL_MM_POLARISATOR_4,
+ EL_MM_POLARISATOR_3,
+ EL_MM_POLARISATOR_2
+ },
+ {
+ EL_DF_MIRROR_1,
+ EL_DF_MIRROR_16,
+ EL_DF_MIRROR_15,
+ EL_DF_MIRROR_14,
+ EL_DF_MIRROR_13,
+ EL_DF_MIRROR_12,
+ EL_DF_MIRROR_11,
+ EL_DF_MIRROR_10,
+ EL_DF_MIRROR_9,
+ EL_DF_MIRROR_8,
+ EL_DF_MIRROR_7,
+ EL_DF_MIRROR_6,
+ EL_DF_MIRROR_5,
+ EL_DF_MIRROR_4,
+ EL_DF_MIRROR_3,
+ EL_DF_MIRROR_2
+ },
+ {
+ EL_DF_MIRROR_ROTATING_1,
+ EL_DF_MIRROR_ROTATING_16,
+ EL_DF_MIRROR_ROTATING_15,
+ EL_DF_MIRROR_ROTATING_14,
+ EL_DF_MIRROR_ROTATING_13,
+ EL_DF_MIRROR_ROTATING_12,
+ EL_DF_MIRROR_ROTATING_11,
+ EL_DF_MIRROR_ROTATING_10,
+ EL_DF_MIRROR_ROTATING_9,
+ EL_DF_MIRROR_ROTATING_8,
+ EL_DF_MIRROR_ROTATING_7,
+ EL_DF_MIRROR_ROTATING_6,
+ EL_DF_MIRROR_ROTATING_5,
+ EL_DF_MIRROR_ROTATING_4,
+ EL_DF_MIRROR_ROTATING_3,
+ EL_DF_MIRROR_ROTATING_2
+ },
+
+ {
+ -1,
+ },
+ };
+ int i, j;
+
+ for (i = 0; swappable_elements[i][0] != -1; i++)
+ {
+ int element1 = swappable_elements[i][0];
+ int element2 = swappable_elements[i][1];
+
+ if (old_element == element1 || old_element == element2)
+ new_element = (old_element == element1 ? element2 : element1);
+ }
+
+ for (i = 0; rotatable_elements_4[i][0] != -1; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ int element = rotatable_elements_4[i][j];
+
+ if (old_element == element)
+ new_element = (button == 1 ? rotatable_elements_4[i][(j + 3) % 4] :
+ button == 2 ? rotatable_elements_4[i][0] :
+ button == 3 ? rotatable_elements_4[i][(j + 1) % 4] :
+ old_element);
+ }
+ }
+
+ for (i = 0; rotatable_elements_8[i][0] != -1; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ int element = rotatable_elements_8[i][j];
+
+ if (old_element == element)
+ new_element = (button == 1 ? rotatable_elements_8[i][(j + 7) % 8] :
+ button == 2 ? rotatable_elements_8[i][0] :
+ button == 3 ? rotatable_elements_8[i][(j + 1) % 8] :
+ old_element);
+ }
+ }
+
+ for (i = 0; rotatable_elements_16[i][0] != -1; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+ int element = rotatable_elements_16[i][j];
+
+ if (old_element == element)
+ new_element = (button == 1 ? rotatable_elements_16[i][(j + 15) % 16] :
+ button == 2 ? rotatable_elements_16[i][0] :
+ button == 3 ? rotatable_elements_16[i][(j + 1) % 16] :
+ old_element);
+ }
+ }
+
+ if (old_element != new_element)
+ {
+ int max_infotext_len = getMaxInfoTextLength();
+ char infotext[MAX_OUTPUT_LINESIZE + 1];
+
+ strncpy(infotext, getElementInfoText(new_element), max_infotext_len);
+ infotext[max_infotext_len] = '\0';
+
+ ClearEditorGadgetInfoText();
+
+ DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, INFOTEXT_FONT,
+ infotext);
+ }
+ }
+
+ SetElementSimple(x, y, new_element, change_level);
+
+ last_x = x;
+ last_y = y;
+}
+
+static void ResetIntelliDraw()
+{
+ int x, y;
+
+ for (x = 0; x < lev_fieldx; x++)
+ for (y = 0; y < lev_fieldy; y++)
+ IntelliDrawBuffer[x][y] = Feld[x][y];
+
+ SetElementIntelliDraw(-1, -1, EL_UNDEFINED, FALSE, -1);
+}
+
+static boolean draw_mode_hires = FALSE;
+
+static void SetDrawModeHiRes(int element)
+{
+ draw_mode_hires =
+ (level.game_engine_type == GAME_ENGINE_TYPE_MM &&
+ (IS_MM_WALL_EDITOR(element) || element == EL_EMPTY));
+}
+
+static boolean getDrawModeHiRes()
+{
+ return draw_mode_hires;
+}
+
+static int getLoResScreenPos(int pos)
+{
+ return (getDrawModeHiRes() ? pos / 2 : pos);
+}
+
+static int getLoResScreenMod(int pos)
+{
+ return (getDrawModeHiRes() ? pos % 2 : 0);
+}
+
+static void SetElementExt(int x, int y, int dx, int dy, int element,
+ boolean change_level, int button)
+{
+ if (element < 0)
+ SetElementSimple(x, y, Feld[x][y], change_level);
+ else if (GetKeyModState() & KMOD_Shift && !IS_MM_WALL_EDITOR(element))
+ SetElementIntelliDraw(x, y, element, change_level, button);
+ else
+ SetElementSimpleExt(x, y, dx, dy, element, change_level);
+}
+
+static void SetElement(int x, int y, int element)
+{
+ SetElementExt(x, y, 0, 0, element, TRUE, -1);
+}
+
+static void SetElementButton(int x, int y, int dx, int dy, int element,
+ int button)
+{
+ SetElementExt(x, y, dx, dy, element, TRUE, button);
+}
+
+static void SetElementHiRes(int sx2, int sy2, int element, boolean change_level)
+{
+ int lx = getLoResScreenPos(sx2) + level_xpos;
+ int ly = getLoResScreenPos(sy2) + level_ypos;
+ int dx = getLoResScreenMod(sx2);
+ int dy = getLoResScreenMod(sy2);
+
+ SetElementExt(lx, ly, dx, dy, element, change_level, -1);
+}
+
+static void SetLevelElementHiRes(int lx2, int ly2, int element)
+{
+ int lx = lx2 / 2;
+ int ly = ly2 / 2;
+ int dx = lx2 % 2;
+ int dy = ly2 % 2;
+
+ SetElementExt(lx, ly, dx, dy, element, TRUE, -1);
+}
+
+static int getLevelElementHiRes(int lx2, int ly2)
+{
+ int lx = lx2 / 2;
+ int ly = ly2 / 2;
+ int dx = lx2 % 2;
+ int dy = ly2 % 2;
+ int element = Feld[lx][ly];
+ unsigned int bitmask = (dx + 1) << (dy * 2);
+
+ if (IS_MM_WALL(element))
+ {
+ if (element & bitmask)
+ return map_mm_wall_element(element);
+ else
+ return EL_EMPTY;
+ }
+
+ return element;
+}
+
+static void DrawLineElement(int x, int y, int element, boolean change_level)
+{
+ SetElementHiRes(x, y, element, change_level);
+}
+
+static void DrawLine(int from_x, int from_y, int to_x, int to_y,
+ int element, boolean change_level)
+{
+ int xsize = ABS(to_x - from_x);
+ int ysize = ABS(to_y - from_y);
+ int dx = (to_x < from_x ? -1 : +1);
+ int dy = (to_y < from_y ? -1 : +1);
+ int i;
+
+ if (from_y == to_y) /* horizontal line */
+ {
+ for (i = 0; i <= xsize; i++)
+ DrawLineElement(from_x + i * dx, from_y, element, change_level);
+ }
+ else if (from_x == to_x) /* vertical line */
+ {
+ for (i = 0; i <= ysize; i++)
+ DrawLineElement(from_x, from_y + i * dy, element, change_level);
+ }
+ else /* diagonal line */
+ {
+ if (ysize < xsize) /* a < 1 */
+ {
+ float a = (float)ysize / (float)xsize;
+
+ for (i = 0; i <= xsize; i++)
+ {
+ int x = dx * i;
+ int y = dy * (int)(a * i + 0.5);
+
+ DrawLineElement(from_x + x, from_y + y, element, change_level);
+ }
+ }
+ else /* a >= 1 */
+ {
+ float a = (float)xsize / (float)ysize;
+
+ for (i = 0; i <= ysize; i++)
+ {
+ int x = dx * (int)(a * i + 0.5);
+ int y = dy * i;
+
+ DrawLineElement(from_x + x, from_y + y, element, change_level);
+ }
+ }
+ }
+}
+
+static void DrawBox(int from_x, int from_y, int to_x, int to_y,
+ int element, boolean change_level)
+{
+ DrawLine(from_x, from_y, from_x, to_y, element, change_level);
+ DrawLine(from_x, to_y, to_x, to_y, element, change_level);
+ DrawLine(to_x, to_y, to_x, from_y, element, change_level);
+ DrawLine(to_x, from_y, from_x, from_y, element, change_level);
+}
+
+static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
+ int element, boolean change_level)
+{
+ int y;
+
+ if (from_y > to_y)
+ swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
+
+ for (y = from_y; y <= to_y; y++)
+ DrawLine(from_x, y, to_x, y, element, change_level);
+}
+
+static void DrawArcExt(int from_x, int from_y, int to_x2, int to_y2,
+ int element, boolean change_level)
+{
+ int to_x = to_x2 - (to_x2 > from_x ? +1 : -1);
+ int to_y = to_y2 - (to_y2 > from_y ? +1 : -1);
+ int len_x = ABS(to_x - from_x);
+ int len_y = ABS(to_y - from_y);
+ int radius, x, y;
+
+ radius = (int)(sqrt((float)(len_x * len_x + len_y * len_y)) + 0.5);
+
+ /* not optimal (some points get drawn twice) but simple,
+ and fast enough for the few points we are drawing */
+
+ for (x = 0; x <= radius; x++)
+ {
+ int sx, sy, sx2, sy2, lx, ly;
+
+ y = (int)(sqrt((float)(radius * radius - x * x)) + 0.5);
+
+ sx2 = from_x + x * (from_x < to_x2 ? +1 : -1);
+ sy2 = from_y + y * (from_y < to_y2 ? +1 : -1);
+ sx = getLoResScreenPos(sx2);
+ sy = getLoResScreenPos(sy2);
+ lx = sx + level_xpos;
+ ly = sy + level_ypos;
+
+ if (IN_ED_FIELD(sx, sy) && IN_LEV_FIELD(lx, ly))
+ DrawLineElement(sx2, sy2, element, change_level);
+ }
+
+ for (y = 0; y <= radius; y++)
+ {
+ int sx, sy, sx2, sy2, lx, ly;
+
+ x = (int)(sqrt((float)(radius * radius - y * y)) + 0.5);
+
+ sx2 = from_x + x * (from_x < to_x2 ? +1 : -1);
+ sy2 = from_y + y * (from_y < to_y2 ? +1 : -1);
+ sx = getLoResScreenPos(sx2);
+ sy = getLoResScreenPos(sy2);
+ lx = sx + level_xpos;
+ ly = sy + level_ypos;
+
+ if (IN_ED_FIELD(sx, sy) && IN_LEV_FIELD(lx, ly))
+ DrawLineElement(sx2, sy2, element, change_level);
+ }
+}
+
+static void DrawArc(int from_x, int from_y, int to_x, int to_y,
+ int element, boolean change_level)
+{
+ int to_x2 = to_x + (to_x < from_x ? -1 : +1);
+ int to_y2 = to_y + (to_y > from_y ? +1 : -1);
+
+ DrawArcExt(from_x, from_y, to_x2, to_y2, element, change_level);
+}
+
+#define DRAW_CIRCLES_BUTTON_AVAILABLE 0
+
+#if DRAW_CIRCLES_BUTTON_AVAILABLE
+static void DrawCircle(int from_x, int from_y, int to_x, int to_y,
+ int element, boolean change_level)
+{
+ int to_x2 = to_x + (to_x < from_x ? -1 : +1);
+ int to_y2 = to_y + (to_y > from_y ? +1 : -1);
+ int mirror_to_x2 = from_x - (to_x2 - from_x);
+ int mirror_to_y2 = from_y - (to_y2 - from_y);
+
+ DrawArcExt(from_x, from_y, to_x2, to_y2, element, change_level);
+ DrawArcExt(from_x, from_y, mirror_to_x2, to_y2, element, change_level);
+ DrawArcExt(from_x, from_y, to_x2, mirror_to_y2, element, change_level);
+ DrawArcExt(from_x, from_y, mirror_to_x2, mirror_to_y2, element,change_level);
+}
+#endif
+
+static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
+{
+ int from_sx, from_sy;
+ int to_sx, to_sy;
+
+ if (from_x > to_x)
+ swap_numbers(&from_x, &to_x);
+
+ if (from_y > to_y)
+ swap_numbers(&from_y, &to_y);
+
+ from_sx = SX + from_x * ed_tilesize;
+ from_sy = SY + from_y * ed_tilesize;
+ to_sx = SX + (to_x + 1) * ed_tilesize - 1;
+ to_sy = SY + (to_y + 1) * ed_tilesize - 1;
+
+ DrawSimpleWhiteLine(drawto, from_sx, from_sy, to_sx, from_sy);
+ DrawSimpleWhiteLine(drawto, to_sx, from_sy, to_sx, to_sy);
+ DrawSimpleWhiteLine(drawto, to_sx, to_sy, from_sx, to_sy);
+ DrawSimpleWhiteLine(drawto, from_sx, to_sy, from_sx, from_sy);
+
+ if (from_x == to_x && from_y == to_y)
+ MarkTileDirty(from_x/2, from_y/2);
+ else
+ redraw_mask |= REDRAW_FIELD;
+}
+
+static void DrawAreaBox(int from_x, int from_y, int to_x, int to_y,
+ int element, boolean change_level)
+{
+ DrawBox(from_x, from_y, to_x, to_y, element, change_level);
+}
+
+static void SelectArea(int from_x, int from_y, int to_x, int to_y,
+ int element, boolean change_level)
+{
+ if (element == -1 || change_level)
+ DrawAreaBox(from_x, from_y, to_x, to_y, -1, FALSE);
+ else
+ DrawAreaBorder(from_x, from_y, to_x, to_y);
+}
+
+/* values for CopyBrushExt() */
+#define CB_AREA_TO_BRUSH 0
+#define CB_BRUSH_TO_CURSOR 1
+#define CB_BRUSH_TO_LEVEL 2
+#define CB_DELETE_OLD_CURSOR 3
+#define CB_DUMP_BRUSH 4
+#define CB_DUMP_BRUSH_SMALL 5
+
+static void DrawBrushElement(int sx, int sy, int element, boolean change_level)
+{
+ DrawLineElement(sx, sy, element, change_level);
+}
+
+static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
+ int button, int mode)
+{
+ static short brush_buffer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+ static int brush_width, brush_height;
+ static int last_cursor_x = -1, last_cursor_y = -1;
+ static boolean delete_old_brush;
+ int new_element = BUTTON_ELEMENT(button);
+ int x, y;
+
+ if (mode == CB_DUMP_BRUSH ||
+ mode == CB_DUMP_BRUSH_SMALL)
+ {
+ if (!draw_with_brush)
+ {
+ Error(ERR_WARN, "no brush selected");
+
+ return;
+ }
+
+ for (y = 0; y < brush_height; y++)
+ {
+ for (x = 0; x < brush_width; x++)
+ {
+ int element = brush_buffer[x][y];
+ int element_mapped = element;
+
+ if (IS_CUSTOM_ELEMENT(element))
+ element_mapped = EL_CUSTOM_START;
+ else if (IS_GROUP_ELEMENT(element))
+ element_mapped = EL_GROUP_START;
+ else if (element >= NUM_FILE_ELEMENTS)
+ element_mapped = EL_UNKNOWN;
+
+ // dump brush as level sketch text for the R'n'D forum:
+ // - large tiles: `xxx (0x60 ASCII)
+ // - small tiles: ¸xxx (0xb8 ISO-8859-1, 0xc2b8 UTF-8)
+ printf("%s%03d", (mode == CB_DUMP_BRUSH ? "`" : "¸"), element_mapped);