diff --git a/Source/Core/Builder.sln b/Source/Core/Builder.sln
index 9a59c636000acdd516a53194970da7805119c1a1..f9758a07165e0f7b065b77bf4bc691a3b68ad7ff 100644
--- a/Source/Core/Builder.sln
+++ b/Source/Core/Builder.sln
@@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 10.00
 # Visual C# Express 2008
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Builder", "Builder.csproj", "{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuilderModes", "..\Plugins\BuilderModes\BuilderModes.csproj", "{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -23,6 +25,16 @@ Global
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Mixed Platforms.Build.0 = Release|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.ActiveCfg = Release|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.Build.0 = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.ActiveCfg = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.Build.0 = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Any CPU.ActiveCfg = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.Build.0 = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.ActiveCfg = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/Source/Core/Data/ImageDataFormat.cs b/Source/Core/Data/ImageDataFormat.cs
index 1b59ee2c6abc0afa3e5ac03261ca005ea38a9cac..77a830fce222e8bf2fc2a381df2a250148919fd4 100644
--- a/Source/Core/Data/ImageDataFormat.cs
+++ b/Source/Core/Data/ImageDataFormat.cs
@@ -40,7 +40,7 @@ namespace CodeImp.DoomBuilder.Data
 		// File format signatures
 		private static readonly int[] PNG_SIGNATURE = new int[] { 137, 80, 78, 71, 13, 10, 26, 10 };
 		private static readonly int[] GIF_SIGNATURE = new int[] { 71, 73, 70 };
-		private static readonly int[] BMP_SIGNATURE = new int[] { 66, 77 };
+        //private static readonly int[] BMP_SIGNATURE = new int[] { 66, 77 }; //mxd. Not supported in (G)ZDoom
 		private static readonly int[] DDS_SIGNATURE = new int[] { 68, 68, 83, 32 };
         //mxd
         private static readonly int[] PCX_SIGNATURE = new int[] { 10, 5, 1, 8 };
@@ -83,12 +83,12 @@ namespace CodeImp.DoomBuilder.Data
                 if (CheckSignature(data, PCX_SIGNATURE)) return new FileImageReader();
 
 				// Check for BMP signature
-				data.Seek(0, SeekOrigin.Begin);
+				/*data.Seek(0, SeekOrigin.Begin);
 				if(CheckSignature(data, BMP_SIGNATURE))
 				{
 					// Check if data size matches the size specified in the data
 					if(bindata.ReadUInt32() <= data.Length) return new FileImageReader();
-				}
+				}*/
 			}
 			
 			// Could it be a doom picture?
diff --git a/Source/Plugins/BuilderModes/BuilderModes.csproj b/Source/Plugins/BuilderModes/BuilderModes.csproj
index 26cf354f79a5884dbc8ceffa601bd99e6f2c4b2d..2745ffa61ee5aa0163723460028f953093457760 100644
--- a/Source/Plugins/BuilderModes/BuilderModes.csproj
+++ b/Source/Plugins/BuilderModes/BuilderModes.csproj
@@ -39,8 +39,10 @@
     <Reference Include="System.Core">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
     </Reference>
+    <Reference Include="System.Data" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="ClassicModes\BaseClassicMode.cs" />
@@ -236,6 +238,7 @@
     <EmbeddedResource Include="Resources\HeightsMode.png" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ClassicModes\DrawRectangleMode.cs" />
     <Compile Include="ErrorChecks\CheckMissingTextures.cs" />
     <Compile Include="ErrorChecks\CheckUnknownFlats.cs" />
     <Compile Include="ErrorChecks\CheckUnknownTextures.cs" />
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs
index c0b8ddb80210429f9b9dcd1ca712150638debb74..a4923f68556344241f79018a54ee4fae311d0d40 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs
@@ -48,24 +48,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
 	{
 		#region ================== Constants
 
-		private const float LINE_THICKNESS = 0.8f;
+		protected const float LINE_THICKNESS = 0.8f;
 
 		#endregion
 
 		#region ================== Variables
 
 		// Drawing points
-		private List<DrawnVertex> points;
-		private List<LineLengthLabel> labels;
+        protected List<DrawnVertex> points;
+        protected List<LineLengthLabel> labels;
 
 		// Keep track of view changes
-		private float lastoffsetx;
-		private float lastoffsety;
-		private float lastscale;
+        protected float lastoffsetx;
+        protected float lastoffsety;
+        protected float lastscale;
 
 		// Options
-		private bool snaptogrid;		// SHIFT to toggle
-		private bool snaptonearest;		// CTRL to enable
+		protected bool snaptogrid;		// SHIFT to toggle
+		protected bool snaptonearest;		// CTRL to enable
 		
 		#endregion
 
@@ -132,9 +132,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		}
 		
 		// This updates the dragging
-		private void Update()
+		protected virtual void Update()
 		{
-			PixelColor stitchcolor = General.Colors.Highlight;
+            PixelColor stitchcolor = General.Colors.Highlight;
 			PixelColor losecolor = General.Colors.Selection;
 			PixelColor color;
 
@@ -360,19 +360,19 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		}
 		
 		// This gets the aligned and snapped draw position
-		private DrawnVertex GetCurrentPosition()
+		protected DrawnVertex GetCurrentPosition()
 		{
 			return GetCurrentPosition(mousemappos, snaptonearest, snaptogrid, renderer, points);
 		}
 		
 		// This draws a point at a specific location
-		public bool DrawPointAt(DrawnVertex p)
+        public bool DrawPointAt(DrawnVertex p)
 		{
 			return DrawPointAt(p.pos, p.stitch, p.stitchline);
 		}
 		
 		// This draws a point at a specific location
-		public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
+        public virtual bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
 		{
 			if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
 				pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
@@ -396,7 +396,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				Vector2D delta = p1 - p2;
 				if((Math.Abs(delta.x) <= 0.001f) && (Math.Abs(delta.y) <= 0.001f))
 				{
-					// Finish drawing
+                    //mxd. Seems... logical?
+                    if (points.Count == 2) {
+                        OnCancel();
+                        return true;
+                    }
+                    
+                    // Finish drawing
 					FinishDraw();
 				}
 			}
@@ -556,7 +562,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		
 		// Drawing a point
 		[BeginAction("drawpoint")]
-		public void DrawPoint()
+        public void DrawPoint()
 		{
 			// Mouse inside window?
 			if(General.Interface.MouseInDisplay)
@@ -569,7 +575,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		
 		// Remove a point
 		[BeginAction("removepoint")]
-		public void RemovePoint()
+        public virtual void RemovePoint()
 		{
 			if(points.Count > 0) points.RemoveAt(points.Count - 1);
 			if(labels.Count > 0)
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
new file mode 100644
index 0000000000000000000000000000000000000000..70f65f06107e4e32781a624c2968eba63e291d20
--- /dev/null
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
@@ -0,0 +1,169 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder.Editing;
+using CodeImp.DoomBuilder.Rendering;
+using CodeImp.DoomBuilder.Geometry;
+using CodeImp.DoomBuilder.Actions;
+using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.Map;
+
+namespace CodeImp.DoomBuilder.BuilderModes.ClassicModes
+{
+    [EditMode(DisplayName = "Draw Rectangle Mode",
+              SwitchAction = "drawrectanglemode",
+              AllowCopyPaste = false,
+              Volatile = true,
+              Optional = false)]
+
+    public class DrawRectangleMode : DrawGeometryMode
+    {
+        
+        override protected void Update() {
+            PixelColor stitchcolor = General.Colors.Highlight;
+            PixelColor losecolor = General.Colors.Selection;
+            PixelColor color;
+
+            snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
+            snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;
+
+            DrawnVertex curp = GetCurrentPosition();
+            float vsize = ((float)renderer.VertexSize + 1.0f) / renderer.Scale;
+            float vsizeborder = ((float)renderer.VertexSize + 3.0f) / renderer.Scale;
+
+            // Render drawing lines
+            if (renderer.StartOverlay(true)) {
+                color = snaptogrid ? stitchcolor : losecolor;
+                
+                if (points.Count == 1) {
+                    //points[1] = curp; // 2-nd point is opposite corner of rectangle
+
+                    //calculate positions
+                    Vector2D[] positions = new Vector2D[] { points[0].pos, new Vector2D(curp.pos.x, points[0].pos.y), curp.pos, new Vector2D(points[0].pos.x, curp.pos.y), points[0].pos };
+
+                    for (int i = 1; i < positions.Length; i++) {
+                        // Render lines
+                        renderer.RenderLine(positions[i - 1], positions[i], LINE_THICKNESS, color, true);
+                        // And labels
+                        labels[i - 1].Start = positions[i - 1];
+                        labels[i - 1].End = positions[i];
+                        renderer.RenderText(labels[i - 1].TextLabel);
+                    }
+
+                    // Render vertices
+                    for (int i = 0; i < 4; i++)
+                        renderer.RenderRectangleFilled(new RectangleF(positions[i].x - vsize, positions[i].y - vsize, vsize * 2.0f, vsize * 2.0f), color, true);
+                } else {
+                    // Render vertex at cursor
+                    renderer.RenderRectangleFilled(new RectangleF(curp.pos.x - vsize, curp.pos.y - vsize, vsize * 2.0f, vsize * 2.0f), color, true);
+                }
+
+                // Done
+                renderer.Finish();
+            }
+
+            // Done
+            renderer.Present();
+        }
+
+        // Accepted
+        override public void OnAccept() {
+            Cursor.Current = Cursors.AppStarting;
+            General.Settings.FindDefaultDrawSettings();
+
+            // When we have a rectangle
+            if (points.Count == 5) {
+                // Make undo for the draw
+                General.Map.UndoRedo.CreateUndo("Rectangle draw");
+
+                // Make an analysis and show info
+                string[] adjectives = new string[] { "gloomy", "sad", "unhappy", "lonely", "troubled", "depressed", "heartsick", "glum", "pessimistic", "bitter", "downcast" }; // aaand my english vocabulary ends here :)
+                string word = adjectives[new Random().Next(adjectives.Length - 1)];
+                string a = ((word[0] == 'a') || (word[0] == 'e') || (word[0] == 'o')) ? "an " : "a ";
+
+                General.Interface.DisplayStatus(StatusType.Action, "Created " + a + word + " rectangle.");
+
+                // Make the drawing
+                if (!Tools.DrawLines(points)) {
+                    // Drawing failed
+                    // NOTE: I have to call this twice, because the first time only cancels this volatile mode
+                    General.Map.UndoRedo.WithdrawUndo();
+                    General.Map.UndoRedo.WithdrawUndo();
+                    return;
+                }
+
+                // Snap to map format accuracy
+                General.Map.Map.SnapAllToAccuracy();
+
+                // Clear selection
+                General.Map.Map.ClearAllSelected();
+
+                // Update cached values
+                General.Map.Map.Update();
+
+                // Edit new sectors?
+                List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true);
+                if (BuilderPlug.Me.EditNewSector && (newsectors.Count > 0))
+                    General.Interface.ShowEditSectors(newsectors);
+
+                // Update the used textures
+                General.Map.Data.UpdateUsedTextures();
+
+                // Map is changed
+                General.Map.IsChanged = true;
+            }
+
+            // Done
+            Cursor.Current = Cursors.Default;
+
+            // Return to original mode
+            General.Editing.ChangeMode(General.Editing.PreviousStableMode.Name);
+        }
+
+        // This draws a point at a specific location
+        override public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline) {
+            if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
+                pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
+                return false;
+
+            DrawnVertex newpoint = new DrawnVertex();
+            newpoint.pos = pos;
+            newpoint.stitch = stitch;
+            newpoint.stitchline = stitchline;
+            points.Add(newpoint);
+
+            if (points.Count == 1) { //add point and labels
+                labels.AddRange(new LineLengthLabel[] { new LineLengthLabel(), new LineLengthLabel(), new LineLengthLabel(), new LineLengthLabel() });
+                Update();
+            } else if (points[0].pos == points[1].pos) { //nothing is drawn
+                points = new List<DrawnVertex>();
+                FinishDraw();
+            } else {
+                //recreate vertices for final shape. 
+                //I must be missing something simple here, but just adding new DrawnVertices to points 
+                //produces errors when created sector intersects with already existing ones...
+                bool stitchFirst = points[0].stitch;
+                bool stitchLineFirst = points[0].stitchline;
+
+                Vector2D[] points2D = new Vector2D[] { points[0].pos, new Vector2D(points[1].pos.x, points[0].pos.y), points[1].pos, new Vector2D(points[0].pos.x, points[1].pos.y), points[0].pos };
+                points = new List<DrawnVertex>();
+
+                base.DrawPointAt(points2D[0], stitchFirst, stitchLineFirst);
+                for (int i = 1; i < points2D.Length; i++)
+                    base.DrawPointAt(points2D[i], snaptogrid, snaptonearest);
+
+                FinishDraw();
+            }
+            return true;
+        }
+
+        override public void RemovePoint() {
+            if (points.Count > 0) points.RemoveAt(points.Count - 1);
+            if (labels.Count > 0) labels = new List<LineLengthLabel>();
+            Update();
+        }
+    }
+}
diff --git a/Source/Plugins/BuilderModes/Resources/Actions.cfg b/Source/Plugins/BuilderModes/Resources/Actions.cfg
index 003fb3e73dfea1ecb3592e047f3be80864f85b39..97a4071d61abf82939d5721fb1214c1a9d76247b 100644
--- a/Source/Plugins/BuilderModes/Resources/Actions.cfg
+++ b/Source/Plugins/BuilderModes/Resources/Actions.cfg
@@ -99,6 +99,18 @@ drawlinesmode
 	allowscroll = true;
 }
 
+//mxd
+drawrectanglemode
+{
+	title = "Start Rectangle Drawing";
+	category = "drawing";
+	description = "Starts drawing rectangle. See the Drawing category for actions available during drawing mode.";
+	allowkeys = true;
+	allowmouse = true;
+	allowscroll = true;
+	default = 196676;
+}
+
 drawpoint
 {
 	title = "Draw Vertex";