Index: src/terraform_gui.h
===================================================================
--- src/terraform_gui.h	(revision 18715)
+++ src/terraform_gui.h	(working copy)
@@ -16,6 +16,8 @@
 
 void CcTerraform(bool success, TileIndex tile, uint32 p1, uint32 p2);
 
+bool DraggingDiagonal();
+
 Window *ShowTerraformToolbar(Window *link = NULL);
 void ShowTerraformToolbarWithTool(uint16 key, uint16 keycode);
 Window *ShowEditorTerraformToolbar();
Index: src/terraform_cmd.cpp
===================================================================
--- src/terraform_cmd.cpp	(revision 18715)
+++ src/terraform_cmd.cpp	(working copy)
@@ -353,12 +353,43 @@
 	return total_cost;
 }
 
+/** raises or lowers a single tile to the given height
+ * @param tile2 the tile to be leveled
+ * @param h the height to be leveled to
+ * @param flags DC_EXEC for simulation or real action and other flags for DoCommand
+ * @param money pile of money the cost is subtracted from
+ * @param cost cumulative cost of possibly many level actions. The cost for this action is added to it.
+ * @return false if cash is missing for the level action, true otherwise
+ */
+bool LevelSingleTile(TileIndex tile2, uint h, DoCommandFlag flags, Money &money, CommandCost &cost)
+{
+	uint curh = TileHeight(tile2);
+	while (curh != h) {
+		CommandCost ret = DoCommand(tile2, SLOPE_N, (curh > h) ? 0 : 1,
+			flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
+		if (CmdFailed(ret)) break;
 
+		if (flags & DC_EXEC) {
+			money -= ret.GetCost();
+			if (money < 0) {
+				_additional_cash_required = ret.GetCost();
+				return false;
+			}
+			DoCommand(tile2, SLOPE_N, (curh > h) ? 0 : 1, flags,
+				CMD_TERRAFORM_LAND);
+		}
+
+		cost.AddCost(ret);
+		curh += (curh > h) ? -1 : 1;
+	}
+	return true;
+}
+
 /** Levels a selected (rectangle) area of land
  * @param tile end tile of area-drag
  * @param flags for this command type
  * @param p1 start tile of area drag
- * @param p2 height difference; eg raise (+1), lower (-1) or level (0)
+ * @param p2 flags for the mode of levelling; @LevelMode at bit 0 and @Orientation at bit 2
  * @param text unused
  * @return the cost of this operation or an error
  */
@@ -372,45 +403,37 @@
 	uint oldh = TileHeight(p1);
 
 	/* compute new height */
-	uint h = oldh + p2;
+	uint h = oldh;
+	LevelMode mode = (LevelMode)GB(p2, 0, 2);
+	switch (mode) {
+	case LEVEL_LEVEL:
+		break;
+	case LEVEL_RAISE:
+		h++;
+		break;
+	case LEVEL_LOWER:
+		h--;
+		break;
+	default:
+		return CMD_ERROR;
+	}
 
 	/* Check range of destination height */
 	if (h > MAX_TILE_HEIGHT) return_cmd_error((oldh == 0) ? STR_ERROR_ALREADY_AT_SEA_LEVEL : STR_ERROR_TOO_HIGH);
 	if (p2 == 0) _error_message = STR_ERROR_ALREADY_LEVELLED;
 
-	/* make sure sx,sy are smaller than ex,ey */
-	int ex = TileX(tile);
-	int ey = TileY(tile);
-	int sx = TileX(p1);
-	int sy = TileY(p1);
-	if (ex < sx) Swap(ex, sx);
-	if (ey < sy) Swap(ey, sy);
-	tile = TileXY(sx, sy);
-
-	int size_x = ex - sx + 1;
-	int size_y = ey - sy + 1;
-
 	Money money = GetAvailableMoneyForCommand();
 	CommandCost cost(EXPENSES_CONSTRUCTION);
 
-	TILE_LOOP(tile2, size_x, size_y, tile) {
-		uint curh = TileHeight(tile2);
-		while (curh != h) {
-			CommandCost ret = DoCommand(tile2, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
-			if (CmdFailed(ret)) break;
-
-			if (flags & DC_EXEC) {
-				money -= ret.GetCost();
-				if (money < 0) {
-					_additional_cash_required = ret.GetCost();
-					return cost;
-				}
-				DoCommand(tile2, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
-			}
-
-			cost.AddCost(ret);
-			curh += (curh > h) ? -1 : 1;
+	Orientation orient = (Orientation)GB(p2, 2, 1);
+	if (orient == ORIENTATION_DIAG) {
+		for (DiagonalIterator iter(tile, p1); iter.IsValid(); ++iter) {
+			if (!LevelSingleTile(*iter, h, flags, money, cost)) return cost;
 		}
+	} else {
+		for (OrthogonalIterator iter(tile, p1); iter.IsValid(); ++iter) {
+			if (!LevelSingleTile(*iter, h, flags, money, cost)) return cost;
+		}
 	}
 
 	return (cost.GetCost() == 0) ? CMD_ERROR : cost;
Index: src/map_func.h
===================================================================
--- src/map_func.h	(revision 18715)
+++ src/map_func.h	(working copy)
@@ -347,7 +347,166 @@
 	for (uint var = tile, cur_h = (h); cur_h > 0; --cur_h, var += TileDiffXY(0, 1) - (w)) \
 		for (uint cur_w = (w); cur_w > 0; --cur_w, var++)
 
+
+class InvalidIterator;
+
 /**
+ * A common base class for tile iterators.
+ */
+class TileIterator {
+public:
+	virtual TileIterator &operator++() = 0;
+	virtual TileIndex operator*() const = 0;
+	virtual bool IsValid() const = 0;
+};
+
+/**
+ * An iterator that lists all the tiles in an orthogonally arranged rectangle.
+ * Use operator++ to advance it and operator* to get the current tile.
+ */
+class OrthogonalIterator : public TileIterator {
+public:
+
+	OrthogonalIterator(TileIndex corner1, TileIndex corner2);
+
+	OrthogonalIterator(TileIndex corner, int width, int height);
+
+	/**
+	 * increments the iterator
+	 */
+	inline OrthogonalIterator &operator++()
+	{
+		++this->current;
+		/* If TileX(current) == 0 here, the left edge of the map has been reached.
+		 * In this case TileX(current) > x_max doesn't work
+		 */
+		if(TileX(this->current) > this->x_max || (TileX(this->current) == 0)) {
+			this->current += TileDiffXY(0, 1) - this->w;
+			/* there is no wrap-around for y components, so this one always works */
+			if (TileY(this->current) > this->y_max) {
+				this->current = INVALID_TILE;
+			}
+		}
+		return *this;
+	}
+
+	/**
+	 * returns the tile associated with the iterator
+	 */
+	inline TileIndex operator*() const {return this->current;}
+
+	/**
+	 * compare two iterators for equality.
+	 * They are equal if all their members are.
+	 */
+	inline bool operator==(const OrthogonalIterator &other) const
+	{
+		return this->current == other.current && this->x_max == other.x_max &&
+				this->y_max == other.y_max && this->w == other.w;
+	}
+
+	/**
+	 * compare two iterators for inequality.
+	 */
+	inline bool operator!=(const OrthogonalIterator &other) const
+	{
+		return !(*this == other);
+	}
+
+	/** check if an orthogonal iterator is still iterating. */
+	inline bool IsValid() const
+	{
+		return this->current != INVALID_TILE;
+	}
+
+private:
+	void Init(uint x_min, uint y_min);
+	TileIndex current;
+	uint x_max, y_max;
+	uint w;
+};
+
+/**
+ * an iterator that lists all the tiles in an diagonally arranged rectangle.
+ * Use operator++ to advance it and operator* to get the current tile.
+ */
+class DiagonalIterator : public TileIterator {
+public:
+	/* a and b are coordinates in a rotated coordinate system.
+	 * base, a_max and b_max form a rectangle in a diagonal coordinate system.
+	 * a_max counts the number of diagonals in one direction, b_max in the other.
+	 * However with this method you only count half the squares. Compare with a
+	 * check board with alternating black and white squares. You only count one
+	 * color. That is why we count double the amount of rows and columns and
+	 * divide by 2 when translating the coordinates back.
+	 */
+
+	DiagonalIterator(TileIndex corner1, TileIndex corner2);
+
+	/** advances the iterator by one tile */
+	inline DiagonalIterator &operator++()
+	{
+		do {
+			if (this->a_max > 0) {
+				++this->a_cur;
+			} else {
+				--this->a_cur;
+			}
+			if (this->a_cur == this->a_max) {
+				this->a_cur = 0;
+				if (this->b_max > 0) {
+					++this->b_cur;
+				} else {
+					--this->b_cur;
+				}
+			}
+		} while (OutsideMap() && this->b_max != this->b_cur);
+		return *this;
+	}
+
+	/** returns the tile associated with the iterator. */
+	inline TileIndex operator*() const
+	{
+		return this->base +
+			TileDiffXY((this->a_cur - this->b_cur) / 2, (this->b_cur + this->a_cur) / 2);
+	}
+
+	/**
+	 * compare two iterators.
+	 * They are equal if all their members are.
+	 */
+	inline bool operator==(const DiagonalIterator &other) const
+	{
+		return this->base == other.base && this->b_cur == other.b_cur &&
+				this->b_max == other.b_max && this->a_cur == other.a_cur &&
+				this->a_max == other.a_max;
+	}
+
+	/** compare two iterators for inequality */
+	inline bool operator!=(const DiagonalIterator &other) const
+	{
+		return !(*this == other);
+	}
+
+	/** check if a diagonal iterator is still iterating.*/
+	inline bool IsValid() const
+	{
+		return this->b_cur != this->b_max;
+	}
+
+private:
+	/** check if the iterator refers to an invalid tile */
+	inline bool OutsideMap() const
+	{
+		return *(*this) >= MapSize();
+	}
+
+	TileIndex base;
+	int a_cur, b_cur;
+	int a_max, b_max;
+};
+
+/**
  * Convert a DiagDirection to a TileIndexDiff
  *
  * @param dir The DiagDirection
Index: src/terraform_gui.cpp
===================================================================
--- src/terraform_gui.cpp	(revision 18715)
+++ src/terraform_gui.cpp	(working copy)
@@ -125,18 +125,28 @@
 		if (TileY(end_tile) == MapMaxY()) end_tile += TileDiffXY(0, -1);
 	}
 
+	int32 lvl_demolish_flags = 0;
+	if (_ctrl_pressed) {
+		SB(lvl_demolish_flags, 2, 1, ORIENTATION_DIAG);
+	} else {
+		SB(lvl_demolish_flags, 2, 1, ORIENTATION_ORTH);
+	}
+
 	switch (proc) {
 		case DDSP_DEMOLISH_AREA:
-			DoCommandP(end_tile, start_tile, 0, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA), CcPlaySound10);
+			DoCommandP(end_tile, start_tile, lvl_demolish_flags, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA), CcPlaySound10);
 			break;
 		case DDSP_RAISE_AND_LEVEL_AREA:
-			DoCommandP(end_tile, start_tile, 1, CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_RAISE_LAND_HERE), CcTerraform);
+			SB(lvl_demolish_flags, 0, 2, LEVEL_RAISE);
+			DoCommandP(end_tile, start_tile, lvl_demolish_flags, CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_RAISE_LAND_HERE), CcTerraform);
 			break;
 		case DDSP_LOWER_AND_LEVEL_AREA:
-			DoCommandP(end_tile, start_tile, (uint32)-1, CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LOWER_LAND_HERE), CcTerraform);
+			SB(lvl_demolish_flags, 0, 2, LEVEL_LOWER);
+			DoCommandP(end_tile, start_tile, lvl_demolish_flags, CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LOWER_LAND_HERE), CcTerraform);
 			break;
 		case DDSP_LEVEL_AREA:
-			DoCommandP(end_tile, start_tile, 0, CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LEVEL_LAND_HERE), CcTerraform);
+			SB(lvl_demolish_flags, 0, 2, LEVEL_LEVEL);
+			DoCommandP(end_tile, start_tile, lvl_demolish_flags, CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LEVEL_LAND_HERE), CcTerraform);
 			break;
 		case DDSP_CREATE_ROCKS:
 			GenerateRockyArea(end_tile, start_tile);
@@ -651,6 +661,14 @@
 	}
 }
 
+/** returns true if we are selecting a diagonal rectangle for an action that supports it, otherwise false */
+bool DraggingDiagonal()
+{
+	return _ctrl_pressed && _left_button_down && (_place_proc == PlaceProc_DemolishArea ||
+			_place_proc == PlaceProc_LevelLand || _place_proc == PlaceProc_RaiseLand ||
+			_place_proc == PlaceProc_LowerLand);
+}
+
 struct ScenarioEditorLandscapeGenerationWindow : Window {
 	ScenarioEditorLandscapeGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
 	{
Index: src/core/math_func.cpp
===================================================================
--- src/core/math_func.cpp	(revision 18715)
+++ src/core/math_func.cpp	(working copy)
@@ -46,3 +46,12 @@
 	return a;
 
 }
+
+/**
+ * check if the parameter "check" is inside the interval between begin an end,
+ * including both begin and end.
+ */
+bool IsInRangeInclusive(int begin, int end, int check) {
+	if (begin > end) Swap(begin, end);
+	return begin <= check && check <= end;
+}
Index: src/core/math_func.hpp
===================================================================
--- src/core/math_func.hpp	(revision 18715)
+++ src/core/math_func.hpp	(working copy)
@@ -317,5 +317,6 @@
 
 int LeastCommonMultiple(int a, int b);
 int GreatestCommonDivisor(int a, int b);
+bool IsInRangeInclusive(int begin, int end, int check);
 
 #endif /* MATH_FUNC_HPP */
Index: src/map_type.h
===================================================================
--- src/map_type.h	(revision 18715)
+++ src/map_type.h	(working copy)
@@ -77,4 +77,21 @@
  */
 #define STRAIGHT_TRACK_LENGTH 7071/10000
 
+/**
+ * argument for CmdLevelLand describing what to do
+ */
+enum LevelMode {
+	LEVEL_LEVEL,
+	LEVEL_LOWER,
+	LEVEL_RAISE,
+};
+
+/**
+ * argument for CmdLevelLand describing the orientation of the level action
+ */
+enum Orientation {
+	ORIENTATION_DIAG,
+	ORIENTATION_ORTH,
+};
+
 #endif /* MAP_TYPE_H */
Index: src/map.cpp
===================================================================
--- src/map.cpp	(revision 18715)
+++ src/map.cpp	(working copy)
@@ -310,6 +310,82 @@
 	return false;
 }
 
+/** Create an orthogonal tile iterator
+ * @param corner1 one corner of the rectange to be iterated over
+ * @param corner2 the opposite corner of the rectangle to be iterated over
+ */
+OrthogonalIterator::OrthogonalIterator(TileIndex corner1, TileIndex corner2)
+{
+	/* coordinates of end and start points */
+	this->x_max = TileX(corner2);
+	this->y_max = TileY(corner2);
+	Init(TileX(corner1), TileY(corner1));
+}
+
+/** Initialize the orthogonal tile iterator; only called from constructor
+ * @param x_min x dimension of a vertical edge of the rectangle
+ * @param y_min y dimension of a horizontal edge of the rectangle
+ */
+void OrthogonalIterator::Init(uint x_min, uint y_min)
+{
+	/* make sure x_min, y_min are smaller than x_max, y_max
+	 */
+	if (this->x_max < x_min) Swap(this->x_max, x_min);
+	if (this->y_max < y_min) Swap(this->y_max, y_min);
+
+	this->current = TileXY(x_min, y_min);
+	this->w = this->x_max - x_min + 1;
+}
+
+/** Create an orthogonal tile iterator
+ * @param corner a corner of the rectangle to be iterated over
+ * @param width x dimension of the rectangle to be iterated over
+ * @param height y dimension of the rectangle to be iterated over
+ */
+OrthogonalIterator::OrthogonalIterator(TileIndex corner, int width, int height)
+{
+	uint x_min = TileX(corner);
+	uint y_min = TileY(corner);
+	this->x_max = x_min + width;
+	this->y_max = y_min + height;
+	Init(x_min, y_min);
+}
+
+/** Create a diagonal tile iterator
+ * @param corner1 a corner of the rectangle to be iterated over
+ * @param corner2 the opposite corner of the rectangle to be iterated over
+ */
+DiagonalIterator::DiagonalIterator(TileIndex corner1, TileIndex corner2)
+{
+	int dist_x = TileX(corner1) - TileX(corner2);
+	int dist_y = TileY(corner1) - TileY(corner2);
+	this->a_max = dist_x + dist_y;
+	this->b_max = dist_y - dist_x;
+	this->base = corner2;
+	/* Unfortunately we can't find a new base and make all a and b positive because
+	 * the new base might be a "flattened" corner where there actually is no single
+	 * tile. If we try anyway the result is either inaccurate ("one off" half of the
+	 * time) or the code gets much more complex;
+	 *
+	 * We also need to increment here to have equality as marker for the end of a row or
+	 * column. Like that it's shorter than having another if/else in operator++
+	 */
+	if (this->a_max > 0) {
+		this->a_max++;
+	} else {
+		this->a_max--;
+	}
+
+	if (this->b_max > 0) {
+		this->b_max++;
+	} else {
+		this->b_max--;
+	}
+	this->b_cur = 0;
+	this->a_cur = 0;
+	if (OutsideMap()) operator++();
+}
+
 /*!
  * Finds the distance for the closest tile with water/land given a tile
  * @param tile  the tile to find the distance too
Index: src/landscape.cpp
===================================================================
--- src/landscape.cpp	(revision 18715)
+++ src/landscape.cpp	(working copy)
@@ -605,7 +605,7 @@
  * @param tile end tile of area dragging
  * @param p1 start tile of area dragging
  * @param flags of operation to conduct
- * @param p2 unused
+ * @param p2 orientation of clearing rectangle encoded in bit 2, see @Orientation
  * @param text unused
  * @return the cost of this operation or an error
  */
@@ -613,43 +613,44 @@
 {
 	if (p1 >= MapSize()) return CMD_ERROR;
 
-	/* make sure sx,sy are smaller than ex,ey */
-	int ex = TileX(tile);
-	int ey = TileY(tile);
-	int sx = TileX(p1);
-	int sy = TileY(p1);
-	if (ex < sx) Swap(ex, sx);
-	if (ey < sy) Swap(ey, sy);
-
 	Money money = GetAvailableMoneyForCommand();
 	CommandCost cost(EXPENSES_CONSTRUCTION);
+
 	bool success = false;
 
-	for (int x = sx; x <= ex; ++x) {
-		for (int y = sy; y <= ey; ++y) {
-			CommandCost ret = DoCommand(TileXY(x, y), 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
-			if (CmdFailed(ret)) continue;
-			success = true;
+	TileIterator *iter;
+	if (p2 == ORIENTATION_DIAG) {
+		iter = new DiagonalIterator(tile, p1);
+	} else {
+		iter = new OrthogonalIterator(tile, p1);
+	}
+	for (;iter->IsValid(); ++(*iter)) {
+		TileIndex clear_tile = **iter;
+		CommandCost ret = DoCommand(clear_tile, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
+		if (CmdFailed(ret)) continue;
+		success = true;
 
-			if (flags & DC_EXEC) {
-				money -= ret.GetCost();
-				if (ret.GetCost() > 0 && money < 0) {
-					_additional_cash_required = ret.GetCost();
-					return cost;
-				}
-				DoCommand(TileXY(x, y), 0, 0, flags, CMD_LANDSCAPE_CLEAR);
+		if (flags & DC_EXEC) {
+			money -= ret.GetCost();
+			if (ret.GetCost() > 0 && money < 0) {
+				_additional_cash_required = ret.GetCost();
+				delete iter;
+				return cost;
+			}
+			DoCommand(clear_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
-				/* draw explosion animation... */
-				if ((x == sx || x == ex) && (y == sy || y == ey)) {
-					/* big explosion in each corner, or small explosion for single tiles */
-					CreateEffectVehicleAbove(x * TILE_SIZE + TILE_SIZE / 2, y * TILE_SIZE + TILE_SIZE / 2, 2,
-						sy == ey && sx == ex ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
-					);
-				}
+			/* draw explosion animation... */
+			if (clear_tile == tile || clear_tile == p1) {
+				/* big explosion in 2 corners, or small explosion for single tiles */
+				CreateEffectVehicleAbove(TileX(clear_tile) * TILE_SIZE + TILE_SIZE / 2,
+					TileY(clear_tile) * TILE_SIZE + TILE_SIZE / 2, 2,
+					tile == p1 ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
+				);
 			}
-			cost.AddCost(ret);
 		}
+		cost.AddCost(ret);
 	}
+	delete iter;
 
 	return (success) ? cost : CMD_ERROR;
 }
Index: src/viewport.cpp
===================================================================
--- src/viewport.cpp	(revision 18715)
+++ src/viewport.cpp	(working copy)
@@ -47,6 +47,7 @@
 #include "window_func.h"
 #include "tilehighlight_func.h"
 #include "window_gui.h"
+#include "terraform_gui.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -752,6 +753,23 @@
 }
 
 /**
+ * checks if a point is inside the selected a diagonal rectangle given by _thd.size and _thd.pos
+ * @param x x coordinate of the point to be checked
+ * @param y y coordinate of the point to be checked
+ * @return true if the point is inside the rectangle, else false
+ */
+bool IsInsideRotatedRectangle(int x, int y)
+{
+	int dist_a = (_thd.size.x + _thd.size.y); // Rotated coordinate system for selected rectangle
+	int dist_b = (_thd.size.x - _thd.size.y); // We don't have to divide by 2. It's all relative!
+	int a = ((x - _thd.pos.x) + (y - _thd.pos.y)); // Rotated coordinate system for the point under scrutiny
+	int b = ((x - _thd.pos.x) - (y - _thd.pos.y));
+
+	/* check if a and b are between 0 and dist_a or dist_b respectively */
+	return IsInRangeInclusive(dist_a, 0, a) && IsInRangeInclusive(dist_b, 0, b);
+}
+
+/**
  * Add a child sprite to a parent sprite.
  *
  * @param image the image to draw.
@@ -938,6 +956,29 @@
 	/* no selection active? */
 	if (_thd.drawstyle == 0) return;
 
+	if (_thd.diagonal) { // We're drawing a 45 degrees rotated (diagonal) rectangle
+		if (IsInsideRotatedRectangle((int)ti->x, (int)ti->y)) {
+			if (_thd.drawstyle & HT_RECT) { // highlighting a square (clear land)
+
+				// don't mark tiles outside the map
+				if (TileX(ti->tile) == MapMaxX() || TileY(ti->tile) == MapMaxY()) return;
+				SpriteID image = SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh];
+				DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : PAL_NONE, ti, 7, FOUNDATION_PART_NORMAL);
+			} else { // highlighting a dot (level land)
+				/* Figure out the Z coordinate for the single dot. */
+				byte z = ti->z;
+				if (ti->tileh & SLOPE_N) {
+					z += TILE_HEIGHT;
+					if (!(ti->tileh & SLOPE_S) && (ti->tileh & SLOPE_STEEP)) {
+						z += TILE_HEIGHT;
+					}
+				}
+				DrawGroundSpriteAt(_cur_dpi->zoom != 2 ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti->x, ti->y, z);
+			}
+		}
+		return;
+	}
+
 	/* Inside the inner area? */
 	if (IsInsideBS(ti->x, _thd.pos.x, _thd.size.x) &&
 			IsInsideBS(ti->y, _thd.pos.y, _thd.size.y)) {
@@ -1619,88 +1660,107 @@
  */
 static void SetSelectionTilesDirty()
 {
-	int x_start = _thd.pos.x;
-	int y_start = _thd.pos.y;
-
 	int x_size = _thd.size.x;
 	int y_size = _thd.size.y;
 
-	if (_thd.outersize.x != 0) {
-		x_size  += _thd.outersize.x;
-		x_start += _thd.offs.x;
-		y_size  += _thd.outersize.y;
-		y_start += _thd.offs.y;
-	}
+	if (!_thd.diagonal) { // Selecting in a straigth rectangle (or a single square)
+		int x_start = _thd.pos.x;
+		int y_start = _thd.pos.y;
 
-	x_size -= TILE_SIZE;
-	y_size -= TILE_SIZE;
+		if (_thd.outersize.x != 0) {
+			x_size  += _thd.outersize.x;
+			x_start += _thd.offs.x;
+			y_size  += _thd.outersize.y;
+			y_start += _thd.offs.y;
+		}
 
-	assert(x_size >= 0);
-	assert(y_size >= 0);
+		x_size -= TILE_SIZE;
+		y_size -= TILE_SIZE;
 
-	int x_end = Clamp(x_start + x_size, 0, MapSizeX() * TILE_SIZE - TILE_SIZE);
-	int y_end = Clamp(y_start + y_size, 0, MapSizeY() * TILE_SIZE - TILE_SIZE);
+		assert(x_size >= 0);
+		assert(y_size >= 0);
 
-	x_start = Clamp(x_start, 0, MapSizeX() * TILE_SIZE - TILE_SIZE);
-	y_start = Clamp(y_start, 0, MapSizeY() * TILE_SIZE - TILE_SIZE);
+		int x_end = Clamp(x_start + x_size, 0, MapSizeX() * TILE_SIZE - TILE_SIZE);
+		int y_end = Clamp(y_start + y_size, 0, MapSizeY() * TILE_SIZE - TILE_SIZE);
 
-	/* make sure everything is multiple of TILE_SIZE */
-	assert((x_end | y_end | x_start | y_start) % TILE_SIZE == 0);
+		x_start = Clamp(x_start, 0, MapSizeX() * TILE_SIZE - TILE_SIZE);
+		y_start = Clamp(y_start, 0, MapSizeY() * TILE_SIZE - TILE_SIZE);
 
-	/* How it works:
-	 * Suppose we have to mark dirty rectangle of 3x4 tiles:
-	 *   x
-	 *  xxx
-	 * xxxxx
-	 *  xxxxx
-	 *   xxx
-	 *    x
-	 * This algorithm marks dirty columns of tiles, so it is done in 3+4-1 steps:
-	 * 1)  x     2)  x
-	 *    xxx       Oxx
-	 *   Oxxxx     xOxxx
-	 *    xxxxx     Oxxxx
-	 *     xxx       xxx
-	 *      x         x
-	 * And so forth...
-	 */
+		/* make sure everything is multiple of TILE_SIZE */
+		assert((x_end | y_end | x_start | y_start) % TILE_SIZE == 0);
 
-	int top_x = x_end; // coordinates of top dirty tile
-	int top_y = y_start;
-	int bot_x = top_x; // coordinates of bottom dirty tile
-	int bot_y = top_y;
+		/* How it works:
+		 * Suppose we have to mark dirty rectangle of 3x4 tiles:
+		 *   x
+		 *  xxx
+		 * xxxxx
+		 *  xxxxx
+		 *   xxx
+		 *    x
+		 * This algorithm marks dirty columns of tiles, so it is done in 3+4-1 steps:
+		 * 1)  x     2)  x
+		 *    xxx       Oxx
+		 *   Oxxxx     xOxxx
+		 *    xxxxx     Oxxxx
+		 *     xxx       xxx
+		 *      x         x
+		 * And so forth...
+		 */
 
-	do {
-		Point top = RemapCoords2(top_x, top_y); // topmost dirty point
-		Point bot = RemapCoords2(bot_x + TILE_SIZE - 1, bot_y + TILE_SIZE - 1); // bottommost point
+		int top_x = x_end; // coordinates of top dirty tile
+		int top_y = y_start;
+		int bot_x = top_x; // coordinates of bottom dirty tile
+		int bot_y = top_y;
 
-		/* the 'x' coordinate of 'top' and 'bot' is the same (and always in the same distance from tile middle),
-		 * tile height/slope affects only the 'y' on-screen coordinate! */
+		do {
+			Point top = RemapCoords2(top_x, top_y); // topmost dirty point
+			Point bot = RemapCoords2(bot_x + TILE_SIZE - 1, bot_y + TILE_SIZE - 1); // bottommost point
 
-		int l = top.x - (TILE_PIXELS - 2); // 'x' coordinate of left side of dirty rectangle
-		int t = top.y;                     // 'y' coordinate of top side -//-
-		int r = top.x + (TILE_PIXELS - 2); // right side of dirty rectangle
-		int b = bot.y;                     // bottom -//-
+			/* the 'x' coordinate of 'top' and 'bot' is the same (and always in the same distance from tile middle),
+			 * tile height/slope affects only the 'y' on-screen coordinate! */
 
-		static const int OVERLAY_WIDTH = 4; // part of selection sprites is drawn outside the selected area
+			int l = top.x - (TILE_PIXELS - 2); // 'x' coordinate of left side of dirty rectangle
+			int t = top.y;                     // 'y' coordinate of top side -//-
+			int r = top.x + (TILE_PIXELS - 2); // right side of dirty rectangle
+			int b = bot.y;                     // bottom -//-
 
-		/* For halftile foundations on SLOPE_STEEP_S the sprite extents some more towards the top */
-		MarkAllViewportsDirty(l - OVERLAY_WIDTH, t - OVERLAY_WIDTH - TILE_HEIGHT, r + OVERLAY_WIDTH, b + OVERLAY_WIDTH);
+			static const int OVERLAY_WIDTH = 4; // part of selection sprites is drawn outside the selected area
 
-		/* haven't we reached the topmost tile yet? */
-		if (top_x != x_start) {
-			top_x -= TILE_SIZE;
-		} else {
-			top_y += TILE_SIZE;
-		}
+			/* For halftile foundations on SLOPE_STEEP_S the sprite extents some more towards the top */
+			MarkAllViewportsDirty(l - OVERLAY_WIDTH, t - OVERLAY_WIDTH - TILE_HEIGHT, r + OVERLAY_WIDTH, b + OVERLAY_WIDTH);
 
-		/* the way the bottom tile changes is different when we reach the bottommost tile */
-		if (bot_y != y_end) {
-			bot_y += TILE_SIZE;
-		} else {
-			bot_x -= TILE_SIZE;
+			/* haven't we reached the topmost tile yet? */
+			if (top_x != x_start) {
+				top_x -= TILE_SIZE;
+			} else {
+				top_y += TILE_SIZE;
+			}
+
+			/* the way the bottom tile changes is different when we reach the bottommost tile */
+			if (bot_y != y_end) {
+				bot_y += TILE_SIZE;
+			} else {
+				bot_x -= TILE_SIZE;
+			}
+		} while (bot_x >= top_x);
+	} else { // Selecting in a 45 degrees rotated (diagonal) rectangle.
+		/* a_size, b_size describe a rectangle with rotated coordinates */
+		int a_size = x_size + y_size, b_size = x_size - y_size;
+
+		int interval_a = a_size < 0 ? -TILE_SIZE : TILE_SIZE;
+		int interval_b = b_size < 0 ? -TILE_SIZE : TILE_SIZE;
+
+		for (int a = -interval_a; a != a_size + interval_a; a += interval_a) {
+			for (int b = -interval_b; b != b_size + interval_b; b += interval_b) {
+				uint x = (_thd.pos.x + (a + b) / 2) / TILE_SIZE;
+				uint y = (_thd.pos.y + (a - b) / 2) / TILE_SIZE;
+
+				if (x < MapMaxX() && y < MapMaxY()) {
+					MarkTileDirtyByTile(TileXY(x, y));
+				}
+			}
 		}
-	} while (bot_x >= top_x);
+	}
 }
 
 
@@ -1943,6 +2003,7 @@
 	int y1;
 
 	_thd.new_drawstyle = HT_NONE;
+	_thd.new_diagonal = false;
 
 	if (_thd.place_mode == HT_SPECIAL) {
 		x1 = _thd.selend.x;
@@ -1953,12 +2014,20 @@
 			x1 &= ~TILE_UNIT_MASK;
 			y1 &= ~TILE_UNIT_MASK;
 
-			if (x1 >= x2) Swap(x1, x2);
-			if (y1 >= y2) Swap(y1, y2);
+			if (DraggingDiagonal()) {
+				_thd.new_diagonal = true;
+			} else {
+				if (x1 >= x2) Swap(x1, x2);
+				if (y1 >= y2) Swap(y1, y2);
+			}
 			_thd.new_pos.x = x1;
 			_thd.new_pos.y = y1;
-			_thd.new_size.x = x2 - x1 + TILE_SIZE;
-			_thd.new_size.y = y2 - y1 + TILE_SIZE;
+			_thd.new_size.x = x2 - x1;
+			_thd.new_size.y = y2 - y1;
+			if (!_thd.new_diagonal) {
+				_thd.new_size.x += TILE_SIZE;
+				_thd.new_size.y += TILE_SIZE;
+			}
 			_thd.new_drawstyle = _thd.next_drawstyle;
 		}
 	} else if (_thd.place_mode != HT_NONE) {
@@ -2013,7 +2082,8 @@
 			_thd.pos.x != _thd.new_pos.x || _thd.pos.y != _thd.new_pos.y ||
 			_thd.size.x != _thd.new_size.x || _thd.size.y != _thd.new_size.y ||
 			_thd.outersize.x != _thd.new_outersize.x ||
-			_thd.outersize.y != _thd.new_outersize.y) {
+			_thd.outersize.y != _thd.new_outersize.y ||
+			_thd.diagonal    != _thd.new_diagonal) {
 		/* clear the old selection? */
 		if (_thd.drawstyle) SetSelectionTilesDirty();
 
@@ -2021,6 +2091,7 @@
 		_thd.pos = _thd.new_pos;
 		_thd.size = _thd.new_size;
 		_thd.outersize = _thd.new_outersize;
+		_thd.diagonal = _thd.new_diagonal;
 		_thd.dirty = 0xff;
 
 		/* draw the new selection? */
Index: src/tilehighlight_type.h
===================================================================
--- src/tilehighlight_type.h	(revision 18715)
+++ src/tilehighlight_type.h	(working copy)
@@ -70,6 +70,8 @@
 	ViewportDragDropSelectionProcess select_proc;
 
 	TileIndex redsq;
+	bool diagonal;     ///< true if dragging a 45 degrees rotated rectangle
+	bool new_diagonal;
 };
 
 #endif /* TILEHIGHLIGHT_TYPE_H */
