diff --git a/Build/Scripting/ZDoom_DECORATE.cfg b/Build/Scripting/ZDoom_DECORATE.cfg
index 909eaf5b738df00b10e323c266ce6bad0d147f12..a1f8a5e502edb7afa3c41d45091a61469b222d09 100644
--- a/Build/Scripting/ZDoom_DECORATE.cfg
+++ b/Build/Scripting/ZDoom_DECORATE.cfg
@@ -368,7 +368,7 @@ keywords
 	A_BarrelDestroy = "A_BarrelDestroy";
 //Miscellaneous functions not listed in the "Action functions" wiki article
 	A_Bang4Cloud = "A_Bang4Cloud";
-	A_Blast = "A_Blast[(int flags = 0[, int strength = 255[, int radius = 255[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, str blastsound = \"BlastRadius\"]]]]])]\nA_Blast[(int flags = 0[, int strength = 255[, float radius = 255.0[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, str blastsound = \"BlastRadius\"]]]]])]";
+	A_Blast = "A_Blast[(int flags = 0[, float strength = 255.0[, float radius = 255.0[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, str blastsound = \"BlastRadius\"]]]]])]";
 	A_BishopMissileWeave = "A_BishopMissileWeave";
 	A_DropWeaponPieces = "A_DropWeaponPieces(str actorclass1, str actorclass2, str actorclass3)";
 	A_Feathers = "A_Feathers";
diff --git a/Help/gzdb/features/classic_modes/draw_grid_tri.jpg b/Help/gzdb/features/classic_modes/draw_grid_tri.jpg
index 68817542e7ea8886f6e1ebe0d98f2b6b3847954c..6cd5d922c829ba816bf75b1c578aeaa2e3d3db5c 100644
Binary files a/Help/gzdb/features/classic_modes/draw_grid_tri.jpg and b/Help/gzdb/features/classic_modes/draw_grid_tri.jpg differ
diff --git a/Help/gzdb/features/classic_modes/mode_drawcurve.html b/Help/gzdb/features/classic_modes/mode_drawcurve.html
index 472288a2ecebeb4dfcee2aa0e9a210bce8c435fe..3db4b83a15a7f0752665fea3fe9974986be6c76e 100644
--- a/Help/gzdb/features/classic_modes/mode_drawcurve.html
+++ b/Help/gzdb/features/classic_modes/mode_drawcurve.html
@@ -25,7 +25,9 @@ This mode lets you draw various curve shapes. <br>
 <b>Default key:</b> Ctrl-Alt-D.<br>
 <b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level.<br><br>
 You can activate this mode by pressing <strong>Ctrl-Alt-D</strong> (default key).<br>
-You can use the side panel or &quot;<strong>Increase Subdivision Level</strong>&quot; and &quot;<strong>Decrease Subdivision Level</strong>&quot; actions to control how detailed the curve is:
+Press "<strong>Continuous drawing</strong>" button on the mode panel to disable automatic switching to previous editing mode after finishing drawing.<br>
+Press "<strong>Auto-finish drawing</strong>" button on the mode panel to automatically finish drawing when currently drawn lines and already existing level geometry form a closed shape.<br>
+You can use the mode panel or &quot;<strong>Increase Subdivision Level</strong>&quot; and &quot;<strong>Decrease Subdivision Level</strong>&quot; actions to control how detailed the curve is:
 <br>
 <img src="draw_curve.jpg" /></div>
 </body>
diff --git a/Help/gzdb/features/classic_modes/mode_drawellipse.html b/Help/gzdb/features/classic_modes/mode_drawellipse.html
index 1ed952a5575999c13294eba471fa75a36b8c36a1..772aa198d44c4cc150e133eb6fc6667ce73f17e8 100644
--- a/Help/gzdb/features/classic_modes/mode_drawellipse.html
+++ b/Help/gzdb/features/classic_modes/mode_drawellipse.html
@@ -21,14 +21,15 @@ This mode lets you draw various ellipsoid shapes.<br>
 	<b>Menu path:</b> Mode -&gt; Draw Ellipse.<br>
       <b>Action category:</b> Drawing.<br>
       <b>Default key:</b> Ctrl-Alt-D.<br>
-      <b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase  Corners Bevel, Decrease Corners Bevel.<br>
+      <b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase  Corners Bevel, Decrease Corners Bevel, Rotate Clockwise, Rotate Counterclockwise.<br>
       <br>
       You can activate this mode by pressing <strong>Alt-Shift-D</strong> (default key).<br>
-      You can use the side panel or &quot;<strong>Increase Subdivision Level</strong>&quot; and &quot;<strong>Decrease Subdivision Level</strong>&quot; actions to  control the number of sides ellipse has:
-      <br>
+	  Press "<strong>Continuous drawing</strong>" button on the mode panel to disable automatic switching to previous editing mode after finishing drawing.<br>
+	  You can use the mode panel or &quot;<strong>Rotate Clockwise</strong>&quot; and &quot;<strong>Rotate Counterclockwise</strong>&quot; actions to rotate the shape.<br>
+      You can use the mode panel or &quot;<strong>Increase Subdivision Level</strong>&quot; and &quot;<strong>Decrease Subdivision Level</strong>&quot; actions to  control the number of sides ellipse has.<br>
       <img src="draw_ellipse1.jpg" />
       <br>
-      You can use side panel or &quot;<strong>Increase Corners Bevel</strong>&quot; and &quot;<strong>Decrease Corners Bevel</strong>&quot; actions to bevel the ellipse: <br>
+      You can use mode panel or &quot;<strong>Increase Corners Bevel</strong>&quot; and &quot;<strong>Decrease Corners Bevel</strong>&quot; actions to bevel the ellipse: <br>
       <img src="draw_ellipse2.jpg" />
       <br>
       When using &quot;<strong>Increase/Decrease Corners Bevel</strong>&quot; actions, the bevel  increment is based on the current grid size.</p>
diff --git a/Help/gzdb/features/classic_modes/mode_drawgrid.html b/Help/gzdb/features/classic_modes/mode_drawgrid.html
index 2512b7840fc659429ad0018466a740832d78e5dc..659e7dd8b477edeeb97872efc039ec53c2078e9b 100644
--- a/Help/gzdb/features/classic_modes/mode_drawgrid.html
+++ b/Help/gzdb/features/classic_modes/mode_drawgrid.html
@@ -24,8 +24,9 @@
       <b>Default key:</b> none.<br />
       <b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase  Corners Bevel, Decrease Corners Bevel.</p>
     <p>You can use the side panel or &quot;<strong>Increase/Decrease Subdivision Level</strong>&quot; and &quot;<strong>Increase/Decrease Corners Bevel</strong>&quot; actions to change the number of horizontal and vertical slices.<br />
-    Check "<strong>Lock slices to grid</strong>" to match slices number to current grid size.<br />
-    Check &quot;<strong>Triangulate</strong>&quot; if you want to create triangles instead of quads:</p>
+    Change "<strong>Lock slices to grid</strong>" setting  to match slices number to current grid size horizontally, vertically or in both directions.<br />
+    Check &quot;<strong>Triangulate</strong>&quot; if you want to create triangles instead of quads.<br />
+	Check "<strong>Continuous drawing</strong>"	to disable automatic switching to previous editing mode after finishing drawing.</p>
     <p><img src="draw_grid_tri.jpg" alt="" /></p>
 </div>
 </body>
diff --git a/Help/gzdb/features/classic_modes/mode_drawrect.html b/Help/gzdb/features/classic_modes/mode_drawrect.html
index 29aaccf0f04160eb7a3320309ee6190465e21486..8328c48b7bb2c30164d4bd46c6ad0c1a36a34d93 100644
--- a/Help/gzdb/features/classic_modes/mode_drawrect.html
+++ b/Help/gzdb/features/classic_modes/mode_drawrect.html
@@ -21,9 +21,11 @@ This mode lets you draw various rectangle shapes.<br>
 <b>Menu path:</b> Mode -&gt; Draw Rectangle.<br />
 <b>Action category:</b> Drawing.<br>
 <b>Default key:</b> Ctrl-Shift-D.<br>
-<b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase  Corners Bevel, Decrease Corners Bevel.<br><br>
+<b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase  Corners Bevel, Decrease Corners Bevel.<br>
+<br>
 You can activate this mode by pressing <strong>Ctrl-Shift-D</strong> (default key).<br>
-You can use the side panel or &quot;<strong>Increase/Decrease Subdivision Level</strong>&quot; and &quot;<strong>Increase/Decrease Corners Bevel</strong>&quot; actions to change corner bevel amount and detail level:
+Press "<strong>Continuous drawing</strong>" button on the mode panel to disable automatic switching to previous editing mode after finishing drawing.<br>
+You can use the mode panel or &quot;<strong>Increase/Decrease Subdivision Level</strong>&quot; and &quot;<strong>Increase/Decrease Corners Bevel</strong>&quot; actions to change corner bevel amount and detail level:
 <br>
 <img src="draw_rectangle1.jpg" />
 <br>
diff --git a/Source/Core/Data/WADReader.cs b/Source/Core/Data/WADReader.cs
index e29ae59d73c331c84f1795dee41df122d25dd6f0..dec6464a403a73753850cf219a1046028a6c13cc 100644
--- a/Source/Core/Data/WADReader.cs
+++ b/Source/Core/Data/WADReader.cs
@@ -83,7 +83,7 @@ namespace CodeImp.DoomBuilder.Data
 			
 			// Initialize
 			file = new WAD(location.location, true);
-			is_iwad = (file.Type == WAD.TYPE_IWAD);
+			is_iwad = file.IsIWAD;
 			strictpatches = dl.option1;
 			patchranges = new List<LumpRange>();
 			spriteranges = new List<LumpRange>();
@@ -175,7 +175,7 @@ namespace CodeImp.DoomBuilder.Data
 		public override void Resume()
 		{
 			file = new WAD(location.location, true);
-			is_iwad = (file.Type == WAD.TYPE_IWAD);
+			is_iwad = file.IsIWAD;
 			base.Resume();
 		}
 
@@ -219,23 +219,27 @@ namespace CodeImp.DoomBuilder.Data
 				}
 			}
 
-			//mxd. Display warnings for unclosed ranges
-			foreach(KeyValuePair<LumpRange, KeyValuePair<string, string>> group in failedranges)
+			// Don't check official IWADs
+			if(!file.IsOfficialIWAD)
 			{
-				if(successfulrangestarts.ContainsKey(group.Key.start)) continue;
-				General.ErrorLogger.Add(ErrorType.Warning, "\"" + group.Value.Key + "\" range at index " + group.Key.start + " is not closed in resource \"" + location.location + "\" (\"" + group.Value.Value + "\" marker is missing).");
-			}
+				//mxd. Display warnings for unclosed ranges
+				foreach(KeyValuePair<LumpRange, KeyValuePair<string, string>> group in failedranges)
+				{
+					if(successfulrangestarts.ContainsKey(group.Key.start)) continue;
+					General.ErrorLogger.Add(ErrorType.Warning, "\"" + group.Value.Key + "\" range at index " + group.Key.start + " is not closed in resource \"" + location.location + "\" (\"" + group.Value.Value + "\" marker is missing).");
+				}
 
-			//mxd. Check duplicates
-			foreach(LumpRange range in ranges)
-			{
-				HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
-				for(int i = range.start + 1; i < range.end; i++)
+				//mxd. Check duplicates
+				foreach(LumpRange range in ranges)
 				{
-					if(names.Contains(file.Lumps[i].Name))
-						General.ErrorLogger.Add(ErrorType.Warning, elementname + " \"" + file.Lumps[i].Name + "\", index " + i + " is double defined in resource \"" + location.location + "\".");
-					else
-						names.Add(file.Lumps[i].Name);
+					HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
+					for(int i = range.start + 1; i < range.end; i++)
+					{
+						if(names.Contains(file.Lumps[i].Name))
+							General.ErrorLogger.Add(ErrorType.Warning, elementname + " \"" + file.Lumps[i].Name + "\", index " + i + " is double defined in resource \"" + location.location + "\".");
+						else
+							names.Add(file.Lumps[i].Name);
+					}
 				}
 			}
 		}
diff --git a/Source/Core/Editing/ClassicMode.cs b/Source/Core/Editing/ClassicMode.cs
index 8558a3e6410e55ed0a8c881527852b0723e996ad..9ff5be126a9e2c52d784733581764666281ef317 100644
--- a/Source/Core/Editing/ClassicMode.cs
+++ b/Source/Core/Editing/ClassicMode.cs
@@ -461,7 +461,6 @@ namespace CodeImp.DoomBuilder.Editing
 		#region ================== Processing
 
 		// Processing
-		public override void OnProcess(float deltatime) { OnProcess((long)deltatime); } //mxd. DB2 compatibility
 		public override void OnProcess(long deltatime)
 		{
 			base.OnProcess(deltatime);
diff --git a/Source/Core/Editing/EditMode.cs b/Source/Core/Editing/EditMode.cs
index 3f4a5c9d6c214f6d1b972231f9bebe5633134338..4920e23c3e0a9d95c945400b0ac83078d6be409e 100644
--- a/Source/Core/Editing/EditMode.cs
+++ b/Source/Core/Editing/EditMode.cs
@@ -246,7 +246,6 @@ namespace CodeImp.DoomBuilder.Editing
 
 		// Processing events
 		public virtual void OnProcess(long deltatime) { }
-		public virtual void OnProcess(float deltatime) { OnProcess((long)deltatime); } //mxd. DB2 compatibility
 		
 		// Generic events
 		public virtual void OnReloadResources() { }
diff --git a/Source/Core/General/General.cs b/Source/Core/General/General.cs
index d100cc2f10ddc50a3469164e9ce7cb4fc381991a..e9e9d308cf79867078651b2a72dc154bd3ebf65b 100644
--- a/Source/Core/General/General.cs
+++ b/Source/Core/General/General.cs
@@ -231,6 +231,7 @@ namespace CodeImp.DoomBuilder
 		public static bool NoSettings { get { return nosettings; } }
 		public static EditingManager Editing { get { return editing; } }
 		public static ErrorLogger ErrorLogger { get { return errorlogger; } }
+		internal static int PendingUpdateRev; //mxd
 
 		#endregion
 
@@ -993,7 +994,7 @@ namespace CodeImp.DoomBuilder
 			// Terminate properly?
 			if(properexit)
 			{
-				General.WriteLogLine("Termination requested");
+				General.WriteLogLine(PendingUpdateRev != 0 ? "Program update requested" : "Termination requested");
 				
 				// Unbind static methods from actions
 				General.Actions.UnbindMethods(typeof(General));
@@ -1018,7 +1019,14 @@ namespace CodeImp.DoomBuilder
 				if(mainwindow != null) { mainwindow.Dispose(); mainwindow = null; }
 				if(actions != null) { actions.Dispose(); actions = null; }
 				if(types != null) { types.Dispose(); types = null; }
-				try { D3DDevice.Terminate(); } catch(Exception) { }
+				try { D3DDevice.Terminate(); } catch { }
+
+				//mxd. Launch the updater?
+				if(PendingUpdateRev != 0)
+				{
+					General.WriteLogLine("Initiating update to R" + PendingUpdateRev + "...");
+					Process.Start(Path.Combine(apppath, "Updater.exe"), "-rev " + PendingUpdateRev);
+				}
 
 				// Application ends here and now
 				General.WriteLogLine("Termination done");
@@ -1181,7 +1189,10 @@ namespace CodeImp.DoomBuilder
 			openfile.Filter = "Doom WAD Files (*.wad)|*.wad";
 			openfile.Title = "Open Map";
 			if(!string.IsNullOrEmpty(settings.LastUsedMapFolder) && Directory.Exists(settings.LastUsedMapFolder)) //mxd
-				openfile.InitialDirectory = settings.LastUsedMapFolder; //mxd
+			{
+				openfile.RestoreDirectory = true;
+				openfile.InitialDirectory = settings.LastUsedMapFolder;
+			} 
 			openfile.AddExtension = false;
 			openfile.CheckFileExists = true;
 			openfile.Multiselect = false;
@@ -1468,6 +1479,12 @@ namespace CodeImp.DoomBuilder
 			savefile.OverwritePrompt = true;
 			savefile.ValidateNames = true;
 			savefile.FileName = map.FileTitle; //mxd
+			if(map.FilePathName.Length > 0) //mxd
+			{
+				savefile.RestoreDirectory = true;
+				savefile.InitialDirectory = Path.GetDirectoryName(map.FilePathName);
+			}
+
 			if(savefile.ShowDialog(mainwindow) == DialogResult.OK)
 			{
 				// Check if we're saving to the same file as the original.
diff --git a/Source/Core/General/MapManager.cs b/Source/Core/General/MapManager.cs
index c56e02697afc88d02b036a4bc598ad576151f916..7d21db5d4148d777b00887fcf8a5911aa4b0f831 100644
--- a/Source/Core/General/MapManager.cs
+++ b/Source/Core/General/MapManager.cs
@@ -664,7 +664,7 @@ namespace CodeImp.DoomBuilder
 				General.MainWindow.DisplayStatus(StatusType.Busy, "Compressing sidedefs...");
 				outputset.CompressSidedefs();
 
-				// Check if it still doesnt fit
+				// Check if it still doesnt
 				if(outputset.Sidedefs.Count > io.MaxSidedefs)
 				{
 					// Problem! Can't save the map like this!
@@ -727,6 +727,20 @@ namespace CodeImp.DoomBuilder
 
 			General.WriteLogLine("Saving map to file: " + newfilepathname);
 
+			//mxd. Official IWAD check...
+			WAD hashtest = new WAD(newfilepathname, true);
+			if(hashtest.IsOfficialIWAD)
+			{
+				General.WriteLogLine("Map saving aborted: attempt to modify official IWAD");
+				General.ShowErrorMessage("Official IWADs should not be modified.\nConsider making a PWAD instead", MessageBoxButtons.OK);
+				return false;
+			}
+			else
+			{
+				hashtest.Dispose();
+				hashtest = null;
+			}
+
 			// Scripts changed?
 			bool localscriptschanged = CheckScriptChanged();
 
@@ -907,7 +921,7 @@ namespace CodeImp.DoomBuilder
 					WAD origwad = new WAD(origwadfile, true);
 
 					// Create new target file
-					targetwad = new WAD(newfilepathname);
+					targetwad = new WAD(newfilepathname) { IsIWAD = origwad.IsIWAD }; //mxd. Let's preserve wad type
 
 					// Copy all lumps, except the original map
 					GameConfiguration origcfg; //mxd
diff --git a/Source/Core/Geometry/Tools.cs b/Source/Core/Geometry/Tools.cs
index afafdd009a3e6d7d257348ea9a97757fc28ce626..fd2e41b5dcceb03989c7282d4989a57f2324df9f 100644
--- a/Source/Core/Geometry/Tools.cs
+++ b/Source/Core/Geometry/Tools.cs
@@ -359,7 +359,6 @@ namespace CodeImp.DoomBuilder.Geometry
 			{
 				// Add line to path
 				path.Add(new LinedefSide(nextline, nextfront));
-				if(!tracecount.ContainsKey(nextline)) tracecount.Add(nextline, 1); else tracecount[nextline]++;
 
 				// Determine next vertex to use
 				Vertex v = nextfront ? nextline.End : nextline.Start;
@@ -390,6 +389,21 @@ namespace CodeImp.DoomBuilder.Geometry
 					Linedef prevline = nextline;
 					nextline = (lines[0] == nextline ? lines[1] : lines[0]);
 
+					//mxd. Try to pick a line with lower tracecount...
+					// Otherwise we will just walk the same path trise
+					int curcount = (!tracecount.ContainsKey(nextline) ? 0 : tracecount[nextline]);
+					if(curcount > 0)
+					{
+						foreach(Linedef l in lines)
+						{
+							if(l != nextline && l != prevline && (!tracecount.ContainsKey(l) || tracecount[l] < curcount))
+							{
+								nextline = l;
+								break;
+							}
+						}
+					}
+
 					// Are we allowed to trace this line again?
 					if(!tracecount.ContainsKey(nextline) || (tracecount[nextline] < 3))
 					{
@@ -403,6 +417,9 @@ namespace CodeImp.DoomBuilder.Geometry
 						path = null;
 					}
 				}
+
+				//mxd. Increase trace count
+				if(!tracecount.ContainsKey(nextline)) tracecount.Add(nextline, 1); else tracecount[nextline]++;
 			}
 			// Continue as long as we have not reached the start yet
 			// or we have no next line to trace
diff --git a/Source/Core/IO/WAD.cs b/Source/Core/IO/WAD.cs
index ea4eefc872c0c88725e9468c737d816fe02ed260..4827fe9b0e3e23b7bd9dd8eb4b61a2237baeb003 100644
--- a/Source/Core/IO/WAD.cs
+++ b/Source/Core/IO/WAD.cs
@@ -18,6 +18,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Security.Cryptography;
 using System.Text;
 using System.IO;
 
@@ -30,11 +31,58 @@ namespace CodeImp.DoomBuilder.IO
 		#region ================== Constants
 
 		// WAD types
-		public const string TYPE_IWAD = "IWAD";
-		public const string TYPE_PWAD = "PWAD";
+		private const string TYPE_IWAD = "IWAD";
+		private const string TYPE_PWAD = "PWAD";
 		
 		// Encoder
 		public static readonly Encoding ENCODING = Encoding.ASCII;
+
+		//mxd. Official IWAD MD5 hashes
+		private static readonly HashSet<string> IWAD_HASHES = new HashSet<string>
+		{
+			////// DOOM IWADS //////
+			"d9153ced9fd5b898b36cc5844e35b520",			// DOOM2 1.666g MD5
+			"30e3c2d0350b67bfbf47271970b74b2f",			// DOOM2 1.666 MD5
+			"ea74a47a791fdef2e9f2ea8b8a9da13b",			// DOOM2 1.7 MD5
+			"d7a07e5d3f4625074312bc299d7ed33f",			// DOOM2 1.7a MD5
+			"c236745bb01d89bbb866c8fed81b6f8c",			// DOOM2 1.8 MD5
+			"25e1459ca71d321525f84628f45ca8cd",			// DOOM2 1.9 MD5
+			"3cb02349b3df649c86290907eed64e7b",			// DOOM2 French MD5
+			"c3bea40570c23e511a7ed3ebcd9865f7",			// BFG DOOM2 MD5
+
+			"981b03e6d1dc033301aa3095acc437ce",			// DOOM 1.1 MD5
+			"792fd1fea023d61210857089a7c1e351",			// DOOM 1.2 MD5
+			"464e3723a7e7f97039ac9fd057096adb",			// DOOM 1.6b MD5
+			"54978d12de87f162b9bcc011676cb3c0",			// DOOM 1.666 MD5
+			"11e1cd216801ea2657723abc86ecb01f",			// DOOM 1.8 MD5
+			"1cd63c5ddff1bf8ce844237f580e9cf3",			// DOOM 1.9 MD5
+			"fb35c4a5a9fd49ec29ab6e900572c524",			// BFG DOOM MD5
+
+			"c4fe9fd920207691a9f493668e0a2083",			// ULTIMATE DOOM MD5
+
+			"75c8cf89566741fa9d22447604053bd7",			// PLUTONIA MD5
+			"3493be7e1e2588bc9c8b31eab2587a04",			// PLUTONIA RARE MD5
+
+			"4e158d9953c79ccf97bd0663244cc6b6",			// TNT MD5
+			"1d39e405bf6ee3df69a8d2646c8d5c49",			// TNT Fixed MD5
+			"be626c12b7c9d94b1dfb9c327566b4ff",			// PSN TNT MD5
+
+			////// HERETIC IWADS //////
+			"3117e399cdb4298eaa3941625f4b2923",			// HERETIC 1.0 MD5
+			"1e4cb4ef075ad344dd63971637307e04",			// HERETIC 1.2 MD5
+			"66d686b1ed6d35ff103f15dbd30e0341",			// HERETIC 1.3 MD5
+
+			////// HEXEN IWADS //////
+			"c88a2bb3d783e2ad7b599a8e301e099e",			// HEXEN Beta MD5
+			"b2543a03521365261d0a0f74d5dd90f0",			// HEXEN 1.0 MD5
+			"abb033caf81e26f12a2103e1fa25453f",			// HEXEN 1.1 MD5
+			"1077432e2690d390c256ac908b5f4efa",			// HEXEN DK 1.0 MD5
+			"78d5898e99e220e4de64edaa0e479593",			// HEXEN DK 1.1 MD5
+
+			////// STRIFE IWADS //////
+			"8f2d3a6a289f5d2f2f9c1eec02b47299",			// STRIFE 1.0 MD5
+			"2fed2031a5b03892106e0f117f17901f",			// STRIFE 1.2 MD5
+		};                                                      
 		
 		#endregion
 
@@ -47,15 +95,16 @@ namespace CodeImp.DoomBuilder.IO
 		private BinaryWriter writer;
 		
 		// Header
-		private string type;
 		private int numlumps;
 		private int lumpsoffset;
+		private bool isiwad; //mxd
+		private bool isofficialiwad; //mxd
 		
 		// Lumps
 		private List<Lump> lumps;
 		
 		// Status
-		private readonly bool isreadonly;
+		private bool isreadonly;
 		private bool isdisposed;
 
 		#endregion
@@ -63,10 +112,11 @@ namespace CodeImp.DoomBuilder.IO
 		#region ================== Properties
 
 		public string Filename { get { return filename; } }
-		public string Type { get { return type; } }
 		public Encoding Encoding { get { return ENCODING; } }
 		public bool IsReadOnly { get { return isreadonly; } }
 		public bool IsDisposed { get { return isdisposed; } }
+		public bool IsIWAD { get { return isiwad; } set { isiwad = value; } } //mxd
+		public bool IsOfficialIWAD { get { return isofficialiwad; } } //mxd
 		public List<Lump> Lumps { get { return lumps; } }
 
 		#endregion
@@ -131,6 +181,12 @@ namespace CodeImp.DoomBuilder.IO
 		{
 			FileAccess access;
 			FileShare share;
+
+			// Keep filename
+			filename = pathfilename;
+
+			//mxd
+			CheckHash();
 			
 			// Determine if opening for read only
 			if(isreadonly)
@@ -146,9 +202,6 @@ namespace CodeImp.DoomBuilder.IO
 				share = FileShare.Read;
 			}
 			
-			// Keep filename
-			filename = pathfilename;
-			
 			// Open the file stream
 			file = File.Open(pathfilename, FileMode.OpenOrCreate, access, share);
 
@@ -157,7 +210,7 @@ namespace CodeImp.DoomBuilder.IO
 			if(!isreadonly) writer = new BinaryWriter(file, ENCODING);
 
 			// Is the WAD file zero length?
-			if(file.Length == 0)
+			if(file.Length < 4)
 			{
 				// Create the headers in file
 				CreateHeaders();
@@ -173,14 +226,15 @@ namespace CodeImp.DoomBuilder.IO
 		private void CreateHeaders()
 		{
 			// Default settings
-			type = TYPE_PWAD;
+			isiwad = false; //mxd
+			isofficialiwad = false; //mxd
 			lumpsoffset = 12;
 
 			// New lumps array
 			lumps = new List<Lump>(numlumps);
 			
 			// Write the headers
-			WriteHeaders();
+			if(!isreadonly) WriteHeaders();
 		}
 		
 		// This reads the WAD header and lumps table
@@ -193,7 +247,7 @@ namespace CodeImp.DoomBuilder.IO
 			file.Seek(0, SeekOrigin.Begin);
 
 			// Read WAD type
-			type = ENCODING.GetString(reader.ReadBytes(4));
+			isiwad = (ENCODING.GetString(reader.ReadBytes(4)) == TYPE_IWAD); //mxd
 			
 			// Number of lumps
 			numlumps = reader.ReadInt32();
@@ -223,14 +277,14 @@ namespace CodeImp.DoomBuilder.IO
 			}
 		}
 
-		// This reads the WAD header and lumps table
+		// This writes the WAD header and lumps table
 		public void WriteHeaders()
 		{
 			// Seek to beginning
 			file.Seek(0, SeekOrigin.Begin);
 
 			// Write WAD type
-			writer.Write(ENCODING.GetBytes(type));
+			writer.Write(ENCODING.GetBytes(isiwad ? TYPE_IWAD : TYPE_PWAD));
 
 			// Number of lumps
 			writer.Write(numlumps);
@@ -250,6 +304,48 @@ namespace CodeImp.DoomBuilder.IO
 				writer.Write(lumps[i].FixedName);
 			}
 		}
+
+		//mxd
+		private void CheckHash()
+		{
+			// Open the file stream
+			FileStream fs = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
+			
+			// Empty file can't be official iwad
+			if(fs.Length > 4)
+			{
+				BinaryReader r = new BinaryReader(fs, ENCODING);
+
+				// Read WAD type
+				if(ENCODING.GetString(r.ReadBytes(4)) == TYPE_IWAD)
+				{
+					// Rewind
+					r.BaseStream.Position = 0;
+					
+					// Check hash
+					MD5 hasher = MD5.Create();
+					byte[] data = hasher.ComputeHash(r.BaseStream);
+
+					// Create a new Stringbuilder to collect the bytes and create a string.
+					StringBuilder hash = new StringBuilder();
+
+					// Loop through each byte of the hashed data and format each one as a hexadecimal string.
+					for(int i = 0; i < data.Length; i++)
+					{
+						hash.Append(data[i].ToString("x2"));
+					}
+
+					isofficialiwad = IWAD_HASHES.Contains(hash.ToString());
+					if(!isreadonly && isofficialiwad) isreadonly = true;
+				}
+
+				// Close the reader
+				r.Close();
+			}
+
+			// Close the file
+			fs.Dispose();
+		}
 		
 		// This flushes writing changes
 		/*public void Flush()
diff --git a/Source/Core/VisualModes/VisualMode.cs b/Source/Core/VisualModes/VisualMode.cs
index d1425d1bf8898b841a9b549beda4e54c04bee8ca..7fc1aaf2502ef4b76990993711f533650ef7e7be 100644
--- a/Source/Core/VisualModes/VisualMode.cs
+++ b/Source/Core/VisualModes/VisualMode.cs
@@ -1099,7 +1099,6 @@ namespace CodeImp.DoomBuilder.VisualModes
 		/// <summary>
 		/// While this mode is active, this is called continuously to process whatever needs processing.
 		/// </summary>
-		public override void OnProcess(float deltatime) { OnProcess((long)deltatime); } //mxd. DB2 compatibility
 		public override void OnProcess(long deltatime)
 		{
 			base.OnProcess(deltatime);
diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs
index 4fa53e370b7350ff5f6d7daeeda2a61396a93543..c7f4204da741860b598235054a4f78ca93eb7e62 100644
--- a/Source/Core/Windows/MainForm.cs
+++ b/Source/Core/Windows/MainForm.cs
@@ -4182,12 +4182,13 @@ namespace CodeImp.DoomBuilder.Windows
 				// Update ignored revision number
 				General.Settings.IgnoredRemoteRevision = (form.IgnoreThisUpdate ? remoterev : 0);
 
-				if(result == DialogResult.OK && General.AskSaveMap())
+				if(result == DialogResult.OK)
 				{
-					// Launch the updater
-					Process.Start(Path.Combine(General.AppPath, "Updater.exe"), "-rev " + remoterev);
+					// Updater will be launched from General.Terminate
+					General.PendingUpdateRev = remoterev;
 
 					// Close
+					General.WriteLogLine("Initiating shutdown due to update request...");
 					General.Exit(true);
 				}
 			}
diff --git a/Source/Core/Windows/OpenMapOptionsForm.cs b/Source/Core/Windows/OpenMapOptionsForm.cs
index 48139db147b3db8a2805b876d8465778600becca..8d90ed296b74e888ca74d8546708beadffcffa85 100644
--- a/Source/Core/Windows/OpenMapOptionsForm.cs
+++ b/Source/Core/Windows/OpenMapOptionsForm.cs
@@ -446,7 +446,7 @@ namespace CodeImp.DoomBuilder.Windows
 			}
 			
 			// Check if we should warn the user for missing resources
-			if((wadfile.Type != WAD.TYPE_IWAD) && (locations.Count == 0) && (configinfo.Resources.Count == 0))
+			if((!wadfile.IsIWAD) && (locations.Count == 0) && (configinfo.Resources.Count == 0))
 			{
 				if(MessageBox.Show(this, "You are about to load a map without selecting any resources. Textures, flats and " +
 										 "sprites may not be shown correctly or may not show up at all. Do you want to continue?", Application.ProductName,
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs
index 55dca5660f7f4fd3f9042932a8ee48102cfa9c97..330e1276ad83470140fedfc2ddb172545f8c4367 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs
@@ -183,7 +183,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				General.Map.UndoRedo.CreateUndo("Curve draw");
 
 				// Make an analysis and show info
-				string[] adjectives = new[] 
+				string[] adjectives =
 				{
 				  "beautiful", "lovely", "romantic", "stylish", "cheerful", "comical",
 				  "awesome", "accurate", "adorable", "adventurous", "attractive", "cute",
@@ -197,27 +197,23 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 				List<DrawnVertex> verts = new List<DrawnVertex>();
 				
-				//if we have a curve...
+				// If we have a curve...
 				if(points.Count > 2)
 				{
-					//is it a closed curve?
-					int lastPoint;
-					if(points[0].pos == points[points.Count - 1].pos) 
-					{
-						lastPoint = curve.Segments.Count;
-					}
+					// Is it an (auto)closed curve?
+					int lastpoint;
+					if(drawingautoclosed || points[0].pos == points[points.Count - 1].pos) 
+						lastpoint = curve.Segments.Count;
 					else 
-					{
-						lastPoint = curve.Segments.Count - 1;
-					}
+						lastpoint = curve.Segments.Count - 1;
 
-					for(int i = 0; i < lastPoint; i++) 
+					for(int i = 0; i < lastpoint; i++) 
 					{
 						int next = (i == curve.Segments.Count - 1 ? 0 : i + 1);
 						bool stitch = points[i].stitch && points[next].stitch;
 						bool stitchline = points[i].stitchline && points[next].stitchline;
 
-						//add segment points except the last one
+						// Add segment points except the last one
 						for(int c = 0; c < curve.Segments[i].Points.Length - 1; c++) 
 						{
 							DrawnVertex dv = new DrawnVertex();
@@ -228,9 +224,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 						}
 					}
 
-					//add last point
+					// Add the last point
 					DrawnVertex end = new DrawnVertex();
-					end.pos = curve.Segments[lastPoint - 1].End;
+					end.pos = curve.Segments[lastpoint - 1].End;
 					end.stitch = verts[verts.Count - 1].stitch;
 					end.stitchline = verts[verts.Count - 1].stitchline;
 					verts.Add(end);
@@ -283,6 +279,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Reset settings
 				points.Clear();
 				labels.Clear();
+				drawingautoclosed = false;
 
 				// Redraw display
 				General.Interface.RedrawDisplay();
@@ -319,9 +316,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			panel.SegmentLength = segmentlength;
 			panel.OnValueChanged += OptionsPanelOnValueChanged;
 			panel.OnContinuousDrawingChanged += OnContinuousDrawingChanged;
+			panel.OnAutoCloseDrawingChanged += OnAutoCloseDrawingChanged;
 
-			// Needs to be set after adding the OnContinuousDrawingChanged event...
+			// Needs to be set after adding the events...
 			panel.ContinuousDrawing = General.Settings.ReadPluginSetting("drawcurvemode.continuousdrawing", false);
+			panel.AutoCloseDrawing = General.Settings.ReadPluginSetting("drawlinesmode.autoclosedrawing", false);
 		}
 
 		protected override void AddInterface()
@@ -334,6 +333,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			// Store settings
 			General.Settings.WritePluginSetting("drawcurvemode.segmentlength", segmentlength);
 			General.Settings.WritePluginSetting("drawcurvemode.continuousdrawing", panel.ContinuousDrawing);
+			General.Settings.WritePluginSetting("drawlinesmode.autoclosedrawing", panel.AutoCloseDrawing);
 
 			// Remove the buttons
 			panel.Unregister();
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawEllipseMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawEllipseMode.cs
index b704ab8269ef760d65f7d37b89b626addc836ca9..2e836bd9ac16f4e19d37efc49f5309adaec25adb 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawEllipseMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawEllipseMode.cs
@@ -1,6 +1,8 @@
 #region ================== Namespaces
 
 using System;
+using System.Collections.Generic;
+using CodeImp.DoomBuilder.Actions;
 using CodeImp.DoomBuilder.Editing;
 using CodeImp.DoomBuilder.Geometry;
 
@@ -20,17 +22,22 @@ namespace CodeImp.DoomBuilder.BuilderModes
 	public class DrawEllipseMode : DrawRectangleMode
 	{
 		#region ================== Variables
-
-		// Drawing
-		private float angle; // in radians
 		
 		// Interface
 		private DrawEllipseOptionsPanel panel;
 
+		// Drawing
+		private float angle; // in radians
+
 		#endregion
 
 		#region ================== Constructor
 
+		public DrawEllipseMode()
+		{
+			autoclosedrawing = false;
+		}
+
 		#endregion
 
 		#region ================== Settings panel
@@ -135,9 +142,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return shape;
 		}
 
-		protected override string GetHintText() 
+		protected override string GetHintText()
 		{
-			return "BVL: " + bevelwidth + "; VERTS: " + subdivisions;
+			List<string> result = new List<string>();
+			if(bevelwidth != 0) result.Add("BVL: " + bevelwidth);
+			if(subdivisions != 0) result.Add("VERTS: " + subdivisions);
+			if(panel.Angle != 0) result.Add("ANGLE: " + panel.Angle);
+			
+			return string.Join("; ", result.ToArray());
 		}
 
 		#endregion
@@ -229,6 +241,22 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			}
 		}
 
+		[BeginAction("rotateclockwise")]
+		private void IncreaseAngle()
+		{
+			panel.Angle = General.ClampAngle(panel.Angle + 5);
+			angle = Angle2D.DegToRad(panel.Angle);
+			Update();
+		}
+
+		[BeginAction("rotatecounterclockwise")]
+		private void DecreaseAngle()
+		{
+			panel.Angle = General.ClampAngle(panel.Angle - 5);
+			angle = Angle2D.DegToRad(panel.Angle);
+			Update();
+		}
+
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs
index fb3498bcc5eec5bebc1d981589bd9f9074ed4920..a4f81918ae2620fb2bb4b5ff4b891d0282e9a612 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs
@@ -66,6 +66,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		protected bool snaptocardinaldirection; //mxd. ALT-SHIFT to enable
 		protected static bool usefourcardinaldirections;
 		protected bool continuousdrawing; //mxd. Restart after finishing drawing?
+		protected bool autoclosedrawing;  //mxd. Finish drawing when new points and existing geometry form a closed shape
+		protected bool drawingautoclosed; //mxd
 
 		//mxd. Labels display style
 		protected bool labelshowangle = true;
@@ -428,28 +430,125 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			labels.Add(new LineLengthLabel(labelshowangle, labeluseoffset));
 			Update();
 
-			// Check if point stitches with the first
-			if((points.Count > 1) && points[points.Count - 1].stitch)
+			if(points.Count > 1)
 			{
-				Vector2D p1 = points[0].pos;
-				Vector2D p2 = points[points.Count - 1].pos;
-				Vector2D delta = p1 - p2;
-				if((Math.Abs(delta.x) <= 0.001f) && (Math.Abs(delta.y) <= 0.001f))
+				// Check if point stitches with the first
+				if(points[points.Count - 1].stitch)
 				{
-					//mxd. Seems... logical?
-					if(points.Count == 2) 
+					Vector2D p1 = points[0].pos;
+					Vector2D p2 = points[points.Count - 1].pos;
+					Vector2D delta = p1 - p2;
+					if((Math.Abs(delta.x) <= 0.001f) && (Math.Abs(delta.y) <= 0.001f))
 					{
-						OnCancel();
+						//mxd. Seems... logical?
+						if(points.Count == 2)
+						{
+							OnCancel();
+							return true;
+						}
+
+						// Finish drawing
+						FinishDraw();
 						return true;
 					}
+				}
+				
+				//mxd. Points and existing geometry form a closed shape?
+				if(continuousdrawing && autoclosedrawing)
+				{
+					// Determive center point
+					float minx = float.MaxValue;
+					float maxx = float.MinValue;
+					float miny = float.MaxValue;
+					float maxy = float.MinValue;
+
+					foreach(DrawnVertex v in points)
+					{
+						if(v.pos.x < minx) minx = v.pos.x;
+						if(v.pos.x > maxx) maxx = v.pos.x;
+						if(v.pos.y < miny) miny = v.pos.y;
+						if(v.pos.y > maxy) maxy = v.pos.y;
+					}
+
+					Vector2D shapecenter = new Vector2D(minx + (maxx - minx) / 2, miny + (maxy - miny) / 2);
 					
-					// Finish drawing
-					FinishDraw();
+					// Determine center point between start and end points
+					minx = Math.Min(points[0].pos.x, points[points.Count - 1].pos.x);
+					maxx = Math.Max(points[0].pos.x, points[points.Count - 1].pos.x);
+					miny = Math.Min(points[0].pos.y, points[points.Count - 1].pos.y);
+					maxy = Math.Max(points[0].pos.y, points[points.Count - 1].pos.y);
+
+					Vector2D startendcenter = new Vector2D(minx + (maxx - minx) / 2, miny + (maxy - miny) / 2);
+
+					// Offset the center perpendicular to the start -> end line direction...
+					if(shapecenter == startendcenter)
+					{
+						shapecenter -= new Line2D(points[0].pos, points[points.Count - 1].pos).GetPerpendicular().GetNormal();
+					}
+
+					// Do the check
+					if(CanFinishDrawing(points[0].pos, points[points.Count - 1].pos, shapecenter))
+					{
+						drawingautoclosed = true;
+						FinishDraw();
+					}
 				}
 			}
 
 			return true;
 		}
+
+		//mxd
+		private static bool CanFinishDrawing(Vector2D start, Vector2D end, Vector2D center)
+		{
+			Linedef startline = FindPotentialLine(start, center);
+			if(startline == null) return false;
+
+			Linedef endline = FindPotentialLine(end, center);
+			if(endline == null) return false;
+
+			// Can finish drawing if a path between startline and endline exists
+			return Tools.FindClosestPath(startline, startline.SideOfLine(center) < 0.0f, endline, endline.SideOfLine(center) < 0.0f, true) != null;
+		}
+
+		//mxd
+		private static Linedef FindPotentialLine(Vector2D target, Vector2D center)
+		{
+			// Target position on top of existing vertex?
+			Vertex v = General.Map.Map.NearestVertex(target);
+			if(v == null) return null;
+
+			Linedef result = null;
+			if(v.Position == target)
+			{
+				float mindistance = float.MaxValue;
+				foreach(Linedef l in v.Linedefs)
+				{
+					if(result == null)
+					{
+						result = l;
+						mindistance = Vector2D.DistanceSq(l.GetCenterPoint(), center);
+					}
+					else
+					{
+						float curdistance = Vector2D.DistanceSq(l.GetCenterPoint(), center);
+						if(curdistance < mindistance)
+						{
+							mindistance = curdistance;
+							result = l;
+						}
+					}
+				}
+			}
+			else
+			{
+				// Result position will split a line?
+				result = General.Map.Map.NearestLinedef(target);
+				if(result.DistanceTo(target, true) > BuilderPlug.Me.StitchRange) return null;
+			}
+
+			return result;
+		}
 		
 		#endregion
 
@@ -460,9 +559,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			//Add options docker
 			panel = new DrawLineOptionsPanel();
 			panel.OnContinuousDrawingChanged += OnContinuousDrawingChanged;
+			panel.OnAutoCloseDrawingChanged += OnAutoCloseDrawingChanged;
 
-			// Needs to be set after adding the OnContinuousDrawingChanged event...
+			// Needs to be set after adding the events...
 			panel.ContinuousDrawing = General.Settings.ReadPluginSetting("drawlinesmode.continuousdrawing", false);
+			panel.AutoCloseDrawing = General.Settings.ReadPluginSetting("drawlinesmode.autoclosedrawing", false);
 		}
 
 		protected virtual void AddInterface()
@@ -473,6 +574,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		protected virtual void RemoveInterface()
 		{
 			General.Settings.WritePluginSetting("drawlinesmode.continuousdrawing", panel.ContinuousDrawing);
+			General.Settings.WritePluginSetting("drawlinesmode.autoclosedrawing", panel.AutoCloseDrawing);
 			panel.Unregister();
 		}
 
@@ -509,7 +611,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public override void OnCancel()
 		{
 			//mxd. Cannot leave this way when continuous drawing is enabled
-			if(continuousdrawing) return;
+			if(continuousdrawing)
+			{
+				drawingautoclosed = false;
+				return;
+			}
 			
 			// Cancel base class
 			base.OnCancel();
@@ -584,6 +690,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				//mxd. Reset settings
 				points.Clear();
 				labels.Clear();
+				drawingautoclosed = false;
 
 				//mxd. Redraw display
 				General.Interface.RedrawDisplay();
@@ -650,6 +757,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			continuousdrawing = (bool)value;
 		}
+
+		//mxd
+		protected void OnAutoCloseDrawingChanged(object value, EventArgs e)
+		{
+			autoclosedrawing = (bool)value;
+		}
 		
 		#endregion
 		
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs
index aef069b89c015282ba8d3705e2dc8192b5812d0b..c12b33cf1df13d8d298992a949baaffb8dbcf858 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs
@@ -72,6 +72,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			snaptogrid = true;
 			usefourcardinaldirections = true;
+			autoclosedrawing = false;
 			gridpoints = new List<DrawnVertex[]>();
 		}
 
@@ -144,6 +145,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Reset settings
 				points.Clear();
 				labels.Clear();
+				drawingautoclosed = false;
 
 				// Redraw display
 				General.Interface.RedrawDisplay();
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
index df3a0125fc55a609623f62b502673c94d9543a85..9ac19f3868af64818bed4af7be8d196b72e5d013 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
@@ -58,6 +58,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			snaptogrid = true;
 			usefourcardinaldirections = true;
+			autoclosedrawing = false;
 		}
 
 		public override void Dispose() 
@@ -263,9 +264,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return points;
 		}
 
-		protected virtual string GetHintText() 
+		protected virtual string GetHintText()
 		{
-			return "BVL: " + bevelwidth + "; SUB: " + subdivisions;
+			List<string> result = new List<string>();
+			if(bevelwidth != 0) result.Add("BVL: " + bevelwidth);
+			if(subdivisions != 0) result.Add("SUB: " + subdivisions);
+
+			return string.Join("; ", result.ToArray());
 		}
 
 		// Update top-left and bottom-right points, which define drawing shape
@@ -362,7 +367,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				General.Map.UndoRedo.CreateUndo(undoname);
 
 				// Make an analysis and show info
-				string[] adjectives = new[] { "gloomy", "sad", "unhappy", "lonely", "troubled", "depressed", "heartsick", "glum", "pessimistic", "bitter", "downcast" }; // aaand my english vocabulary ends here :)
+				string[] adjectives = { "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] == 'u' ? "an " : "a ");
 
@@ -411,6 +416,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Reset settings
 				points.Clear();
 				labels.Clear();
+				drawingautoclosed = false;
 
 				// Redraw display
 				General.Interface.RedrawDisplay();
diff --git a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
index 2d3906423dac15249349310ed8b1413b59bff900..2f09d0437b7d6219ba2000a3ca2dc63683a66886 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
@@ -1290,63 +1290,122 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			}
 
 			// Any selected lines?
-			if(selected.Count > 0)
+			if(selected.Count == 0)
 			{
-				// Make undo
-				if(selected.Count > 1)
-				{
-					General.Map.UndoRedo.CreateUndo("Flip " + selected.Count + " linedefs");
-					General.Interface.DisplayStatus(StatusType.Action, "Flipped " + selected.Count + " linedefs.");
-				}
-				else
-				{
-					General.Map.UndoRedo.CreateUndo("Flip linedef");
-					General.Interface.DisplayStatus(StatusType.Action, "Flipped a linedef.");
-				}
+				General.Interface.DisplayStatus(StatusType.Warning, "This action requires a selection!");
+				return;
+			}
 
-				//mxd. Do it sector-wise
-				Dictionary<Sector, int> sectors = new Dictionary<Sector, int>();
+			// Make undo
+			if(selected.Count > 1)
+			{
+				General.Map.UndoRedo.CreateUndo("Flip " + selected.Count + " linedefs");
+				General.Interface.DisplayStatus(StatusType.Action, "Flipped " + selected.Count + " linedefs.");
+			}
+			else
+			{
+				General.Map.UndoRedo.CreateUndo("Flip linedef");
+				General.Interface.DisplayStatus(StatusType.Action, "Flipped a linedef.");
+			}
 
-				foreach(Linedef l in selected) 
+			// Flip all selected linedefs
+			foreach(Linedef l in selected)
+			{
+				l.FlipVertices();
+				l.FlipSidedefs();
+			}
+
+			// Remove selection if only one linedef was selected
+			if(selected.Count == 1)
+			{
+				foreach(Linedef ld in selected) ld.Selected = false;
+				selected.Clear();
+			}
+
+			// Redraw
+			General.Map.Map.Update();
+			General.Map.IsChanged = true;
+			General.Interface.RefreshInfo();
+			General.Interface.RedrawDisplay();
+		}
+
+		[BeginAction("alignlinedefs")]
+		public void AlignLinedefs() //mxd
+		{
+			// No selected lines?
+			ICollection<Linedef> selected = General.Map.Map.GetSelectedLinedefs(true);
+			if(selected.Count == 0)
+			{
+				// Anything highlighted?
+				if(highlighted != null)
 				{
-					if(l.Front != null && l.Front.Sector != null)
-					{
-						if(!sectors.ContainsKey(l.Front.Sector)) sectors.Add(l.Front.Sector, 0);
-						sectors[l.Front.Sector]++;
-					}
-						
-					if(l.Back != null && l.Back.Sector != null)
-					{
-						if(!sectors.ContainsKey(l.Back.Sector)) sectors.Add(l.Back.Sector, 0);
-						sectors[l.Back.Sector]++;
-					}
+					// Select the highlighted item
+					highlighted.Selected = true;
+					selected.Add(highlighted);
 				}
+			}
 
-				//mxd. Sort the collection so sectors with the most selected linedefs go first
-				List<KeyValuePair<Sector, int>> sortedlist = sectors.ToList();
-				sortedlist.Sort((firstPair, nextPair) => firstPair.Value.CompareTo(nextPair.Value));
-				sortedlist.Reverse();
+			// Any selected lines?
+			if(selected.Count == 0)
+			{
+				General.Interface.DisplayStatus(StatusType.Warning, "This action requires a selection!");
+				return;
+			}
 
-				//mxd. Gather our ordered sectors
-				List<Sector> sectorslist = new List<Sector>(sortedlist.Count());
-				sectorslist.AddRange(sortedlist.Select(pair => pair.Key));
+			// Make undo
+			if(selected.Count > 1)
+			{
+				General.Map.UndoRedo.CreateUndo("Align " + selected.Count + " linedefs");
+				General.Interface.DisplayStatus(StatusType.Action, "Aligned " + selected.Count + " linedefs.");
+			}
+			else
+			{
+				General.Map.UndoRedo.CreateUndo("Align linedef");
+				General.Interface.DisplayStatus(StatusType.Action, "Aligned a linedef.");
+			}
 
-				//mxd. Flip the lines
-				Tools.FlipSectorLinedefs(sectorslist, true);
+			//mxd. Do it sector-wise
+			Dictionary<Sector, int> sectors = new Dictionary<Sector, int>();
 
-				// Remove selection if only one linedef was selected
-				if(selected.Count == 1)
+			foreach(Linedef l in selected) 
+			{
+				if(l.Front != null && l.Front.Sector != null)
 				{
-					foreach(Linedef ld in selected) ld.Selected = false;
-					selected.Clear();
+					if(!sectors.ContainsKey(l.Front.Sector)) sectors.Add(l.Front.Sector, 0);
+					sectors[l.Front.Sector]++;
 				}
+						
+				if(l.Back != null && l.Back.Sector != null)
+				{
+					if(!sectors.ContainsKey(l.Back.Sector)) sectors.Add(l.Back.Sector, 0);
+					sectors[l.Back.Sector]++;
+				}
+			}
 
-				// Redraw
-				General.Map.Map.Update();
-				General.Map.IsChanged = true;
-				General.Interface.RefreshInfo();
-				General.Interface.RedrawDisplay();
+			//mxd. Sort the collection so sectors with the most selected linedefs go first
+			List<KeyValuePair<Sector, int>> sortedlist = sectors.ToList();
+			sortedlist.Sort((firstPair, nextPair) => firstPair.Value.CompareTo(nextPair.Value));
+			sortedlist.Reverse();
+
+			//mxd. Gather our ordered sectors
+			List<Sector> sectorslist = new List<Sector>(sortedlist.Count());
+			sectorslist.AddRange(sortedlist.Select(pair => pair.Key));
+
+			//mxd. Flip the lines
+			Tools.FlipSectorLinedefs(sectorslist, true);
+
+			// Remove selection if only one linedef was selected
+			if(selected.Count == 1)
+			{
+				foreach(Linedef ld in selected) ld.Selected = false;
+				selected.Clear();
 			}
+
+			// Redraw
+			General.Map.Map.Update();
+			General.Map.IsChanged = true;
+			General.Interface.RefreshInfo();
+			General.Interface.RedrawDisplay();
 		}
 
 		[BeginAction("flipsidedefs")]
@@ -1363,6 +1422,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				}
 			}
 
+			//mxd. Any selected lines?
+			if(selected.Count == 0)
+			{
+				General.Interface.DisplayStatus(StatusType.Warning, "This action requires a selection!");
+				return;
+			}
+
 			//mxd. Do this only with double-sided linedefs
 			List<Linedef> validlines = new List<Linedef>();
 			foreach(Linedef l in selected) 
@@ -1370,39 +1436,38 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				if(l.Front != null && l.Back != null) validlines.Add(l);
 			}
 
-			// Any selected lines?
-			if(validlines.Count > 0) 
+			//mxd. Any double-sided lines selected?
+			if(validlines.Count == 0)
 			{
-				// Make undo
-				if(validlines.Count > 1) 
-				{
-					General.Map.UndoRedo.CreateUndo("Flip " + validlines.Count + " sidedefs");
-					General.Interface.DisplayStatus(StatusType.Action, "Flipped " + validlines.Count + " sidedefs.");
-				}
-				else
-				{
-					General.Map.UndoRedo.CreateUndo("Flip sidedef");
-					General.Interface.DisplayStatus(StatusType.Action, "Flipped a sidedef.");
-				}
+				General.Interface.DisplayStatus(StatusType.Warning, "No sidedefs to flip! Only 2-sided linedefs can be flipped.");
+				return;
+			}
 
-				// Flip sidedefs in all selected linedefs
-				foreach(Linedef l in validlines) 
-				{
-					l.FlipSidedefs();
-					l.Front.Sector.UpdateNeeded = true;
-					l.Back.Sector.UpdateNeeded = true;
-				}
+			// Make undo
+			if(validlines.Count > 1) 
+			{
+				General.Map.UndoRedo.CreateUndo("Flip " + validlines.Count + " sidedefs");
+				General.Interface.DisplayStatus(StatusType.Action, "Flipped " + validlines.Count + " sidedefs.");
+			}
+			else
+			{
+				General.Map.UndoRedo.CreateUndo("Flip sidedef");
+				General.Interface.DisplayStatus(StatusType.Action, "Flipped a sidedef.");
+			}
 
-				// Redraw
-				General.Map.Map.Update();
-				General.Map.IsChanged = true;
-				General.Interface.RefreshInfo();
-				General.Interface.RedrawDisplay();
-			} 
-			else 
+			// Flip sidedefs in all selected linedefs
+			foreach(Linedef l in validlines) 
 			{
-				General.Interface.DisplayStatus(StatusType.Warning, "No sidedefs to flip (only 2-sided linedefs can be flipped)!");
+				l.FlipSidedefs();
+				l.Front.Sector.UpdateNeeded = true;
+				l.Back.Sector.UpdateNeeded = true;
 			}
+
+			// Redraw
+			General.Map.Map.Update();
+			General.Map.IsChanged = true;
+			General.Interface.RefreshInfo();
+			General.Interface.RedrawDisplay();
 		}
 
 		//mxd. Make gradient brightness
diff --git a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
index 03e6a3ccc739a943ded664fbdc1e79f47c5be706..776cd1da81460a6c0ccec511cb10a6b8acf33d01 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
@@ -2411,6 +2411,57 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		//mxd
 		[BeginAction("fliplinedefs")]
 		public void FlipLinedefs() 
+		{
+			// Get selection
+			ICollection<Sector> selected = General.Map.Map.GetSelectedSectors(true);
+
+			if(selected.Count == 0 && highlighted != null && !highlighted.IsDisposed)
+				selected.Add(highlighted);
+
+			if(selected.Count == 0)
+			{
+				General.Interface.DisplayStatus(StatusType.Warning, "This action requires a selection!");
+				return;
+			}
+
+			// Make undo
+			if(selected.Count > 1)
+			{
+				General.Map.UndoRedo.CreateUndo("Align linedefs of " + selected.Count + " sectors");
+				General.Interface.DisplayStatus(StatusType.Action, "Aligned linedefs of " + selected.Count + "sectors.");
+			}
+			else
+			{
+				General.Map.UndoRedo.CreateUndo("Align sector linedefs");
+				General.Interface.DisplayStatus(StatusType.Action, "Aligned sector linedefs.");
+			}
+
+			HashSet<Linedef> selectedlines = new HashSet<Linedef>();
+			foreach(Sector s in selected)
+			{
+				foreach(Sidedef side in s.Sidedefs)
+				{
+					if(!selectedlines.Contains(side.Line)) selectedlines.Add(side.Line);
+				}
+			}
+
+			// Flip all selected linedefs
+			foreach(Linedef l in selectedlines)
+			{
+				l.FlipVertices();
+				l.FlipSidedefs();
+			}
+
+			// Redraw
+			General.Map.Map.Update();
+			General.Map.IsChanged = true;
+			General.Interface.RefreshInfo();
+			General.Interface.RedrawDisplay();
+		}
+		
+		//mxd
+		[BeginAction("alignlinedefs")]
+		public void AlignLinedefs() 
 		{
 			// Get selection
 			ICollection<Sector> selection = General.Map.Map.GetSelectedSectors(true);
@@ -2427,13 +2478,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			// Make undo
 			if(selection.Count > 1) 
 			{
-				General.Map.UndoRedo.CreateUndo("Flip linedefs of " + selection.Count + " sectors");
-				General.Interface.DisplayStatus(StatusType.Action, "Flipped linedefs of " + selection.Count + "sectors.");
+				General.Map.UndoRedo.CreateUndo("Align linedefs of " + selection.Count + " sectors");
+				General.Interface.DisplayStatus(StatusType.Action, "Aligned linedefs of " + selection.Count + "sectors.");
 			} 
 			else 
 			{
-				General.Map.UndoRedo.CreateUndo("Flip sector linedefs");
-				General.Interface.DisplayStatus(StatusType.Action, "Flipped sector linedefs.");
+				General.Map.UndoRedo.CreateUndo("Align sector linedefs");
+				General.Interface.DisplayStatus(StatusType.Action, "Aligned sector linedefs.");
 			}
 
 			// Flip lines
diff --git a/Source/Plugins/BuilderModes/Interface/DrawCurveOptionsPanel.Designer.cs b/Source/Plugins/BuilderModes/Interface/DrawCurveOptionsPanel.Designer.cs
index 901edbb781f5a107c5286278cb19e261d2b47367..853cf270d22a1304350d3f9671b676e78f1ce685 100644
--- a/Source/Plugins/BuilderModes/Interface/DrawCurveOptionsPanel.Designer.cs
+++ b/Source/Plugins/BuilderModes/Interface/DrawCurveOptionsPanel.Designer.cs
@@ -29,11 +29,12 @@
 		private void InitializeComponent() 
 		{
 			this.toolstrip = new System.Windows.Forms.ToolStrip();
+			this.continuousdrawing = new System.Windows.Forms.ToolStripButton();
+			this.autoclosedrawing = new System.Windows.Forms.ToolStripButton();
+			this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
 			this.seglabel = new System.Windows.Forms.ToolStripLabel();
 			this.seglen = new CodeImp.DoomBuilder.Controls.ToolStripNumericUpDown();
 			this.reset = new System.Windows.Forms.ToolStripButton();
-			this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
-			this.continuousdrawing = new System.Windows.Forms.ToolStripButton();
 			this.toolstrip.SuspendLayout();
 			this.SuspendLayout();
 			// 
@@ -41,16 +42,43 @@
 			// 
 			this.toolstrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.continuousdrawing,
+            this.autoclosedrawing,
             this.toolStripSeparator1,
             this.seglabel,
             this.seglen,
             this.reset});
 			this.toolstrip.Location = new System.Drawing.Point(0, 0);
 			this.toolstrip.Name = "toolstrip";
-			this.toolstrip.Size = new System.Drawing.Size(320, 25);
+			this.toolstrip.Size = new System.Drawing.Size(562, 25);
 			this.toolstrip.TabIndex = 7;
 			this.toolstrip.Text = "toolStrip1";
 			// 
+			// continuousdrawing
+			// 
+			this.continuousdrawing.CheckOnClick = true;
+			this.continuousdrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Repeat;
+			this.continuousdrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
+			this.continuousdrawing.Name = "continuousdrawing";
+			this.continuousdrawing.Size = new System.Drawing.Size(135, 22);
+			this.continuousdrawing.Text = "Continuous drawing";
+			this.continuousdrawing.CheckedChanged += new System.EventHandler(this.continuousdrawing_CheckedChanged);
+			// 
+			// autoclosedrawing
+			// 
+			this.autoclosedrawing.CheckOnClick = true;
+			this.autoclosedrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.NewSector2;
+			this.autoclosedrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
+			this.autoclosedrawing.Margin = new System.Windows.Forms.Padding(2, 1, 0, 2);
+			this.autoclosedrawing.Name = "autoclosedrawing";
+			this.autoclosedrawing.Size = new System.Drawing.Size(131, 22);
+			this.autoclosedrawing.Text = "Auto-close drawing";
+			this.autoclosedrawing.CheckedChanged += new System.EventHandler(this.autoclosedrawing_CheckedChanged);
+			// 
+			// toolStripSeparator1
+			// 
+			this.toolStripSeparator1.Name = "toolStripSeparator1";
+			this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
+			// 
 			// seglabel
 			// 
 			this.seglabel.Name = "seglabel";
@@ -87,32 +115,17 @@
 			this.reset.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Reset;
 			this.reset.ImageTransparentColor = System.Drawing.Color.Magenta;
 			this.reset.Name = "reset";
-			this.reset.Size = new System.Drawing.Size(23, 20);
+			this.reset.Size = new System.Drawing.Size(23, 22);
 			this.reset.Text = "Reset";
 			this.reset.Click += new System.EventHandler(this.reset_Click);
 			// 
-			// toolStripSeparator1
-			// 
-			this.toolStripSeparator1.Name = "toolStripSeparator1";
-			this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
-			// 
-			// continuousdrawing
-			// 
-			this.continuousdrawing.CheckOnClick = true;
-			this.continuousdrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Repeat;
-			this.continuousdrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
-			this.continuousdrawing.Name = "continuousdrawing";
-			this.continuousdrawing.Size = new System.Drawing.Size(135, 22);
-			this.continuousdrawing.Text = "Continuous drawing";
-			this.continuousdrawing.CheckedChanged += new System.EventHandler(this.continuousdrawing_CheckedChanged);
-			// 
 			// DrawCurveOptionsPanel
 			// 
 			this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
 			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
 			this.Controls.Add(this.toolstrip);
 			this.Name = "DrawCurveOptionsPanel";
-			this.Size = new System.Drawing.Size(320, 60);
+			this.Size = new System.Drawing.Size(562, 60);
 			this.toolstrip.ResumeLayout(false);
 			this.toolstrip.PerformLayout();
 			this.ResumeLayout(false);
@@ -128,6 +141,7 @@
 		private System.Windows.Forms.ToolStripButton reset;
 		private System.Windows.Forms.ToolStripButton continuousdrawing;
 		private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+		private System.Windows.Forms.ToolStripButton autoclosedrawing;
 
 	}
 }
diff --git a/Source/Plugins/BuilderModes/Interface/DrawCurveOptionsPanel.cs b/Source/Plugins/BuilderModes/Interface/DrawCurveOptionsPanel.cs
index 4d751f231baac81a49dddab54ec6b5aa0fe04a1f..5dd68f10e8cb8c079fa18c9a2b6fcfd25992808f 100644
--- a/Source/Plugins/BuilderModes/Interface/DrawCurveOptionsPanel.cs
+++ b/Source/Plugins/BuilderModes/Interface/DrawCurveOptionsPanel.cs
@@ -7,10 +7,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 	{
 		public event EventHandler OnValueChanged;
 		public event EventHandler OnContinuousDrawingChanged;
+		public event EventHandler OnAutoCloseDrawingChanged;
 		private bool blockevents;
 
 		public int SegmentLength { get { return (int)seglen.Value; } set { blockevents = true; seglen.Value = value; blockevents = false; } }
 		public bool ContinuousDrawing { get { return continuousdrawing.Checked; } set { continuousdrawing.Checked = value; } }
+		public bool AutoCloseDrawing { get { return autoclosedrawing.Checked; } set { autoclosedrawing.Checked = value; } }
 
 		public DrawCurveOptionsPanel(int minLength, int maxLength) 
 		{
@@ -25,6 +27,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public void Register() 
 		{
 			General.Interface.AddButton(continuousdrawing);
+			General.Interface.AddButton(autoclosedrawing);
 			General.Interface.AddButton(toolStripSeparator1);
 			General.Interface.AddButton(seglabel);
 			General.Interface.AddButton(seglen);
@@ -37,6 +40,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.RemoveButton(seglen);
 			General.Interface.RemoveButton(seglabel);
 			General.Interface.RemoveButton(toolStripSeparator1);
+			General.Interface.RemoveButton(autoclosedrawing);
 			General.Interface.RemoveButton(continuousdrawing);
 		}
 
@@ -54,5 +58,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			if(OnContinuousDrawingChanged != null) OnContinuousDrawingChanged(continuousdrawing.Checked, EventArgs.Empty);
 		}
+
+		private void autoclosedrawing_CheckedChanged(object sender, EventArgs e)
+		{
+			if(OnAutoCloseDrawingChanged != null) OnAutoCloseDrawingChanged(autoclosedrawing.Checked, EventArgs.Empty);
+		}
 	}
 }
diff --git a/Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.Designer.cs b/Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.Designer.cs
index af61aca311e5b07ea8b810d3f9afb9df4a254465..88f1ada0ca54ac0da0ed232837d468eb28441ad4 100644
--- a/Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.Designer.cs
+++ b/Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.Designer.cs
@@ -30,16 +30,18 @@
 		{
 			this.toolStrip1 = new System.Windows.Forms.ToolStrip();
 			this.continuousdrawing = new System.Windows.Forms.ToolStripButton();
+			this.autoclosedrawing = new System.Windows.Forms.ToolStripButton();
 			this.toolStrip1.SuspendLayout();
 			this.SuspendLayout();
 			// 
 			// toolStrip1
 			// 
 			this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.continuousdrawing});
+            this.continuousdrawing,
+            this.autoclosedrawing});
 			this.toolStrip1.Location = new System.Drawing.Point(0, 0);
 			this.toolStrip1.Name = "toolStrip1";
-			this.toolStrip1.Size = new System.Drawing.Size(200, 25);
+			this.toolStrip1.Size = new System.Drawing.Size(406, 25);
 			this.toolStrip1.TabIndex = 8;
 			this.toolStrip1.Text = "toolStrip1";
 			// 
@@ -53,13 +55,24 @@
 			this.continuousdrawing.Text = "Continuous drawing";
 			this.continuousdrawing.CheckedChanged += new System.EventHandler(this.continuousdrawing_CheckedChanged);
 			// 
+			// autoclosedrawing
+			// 
+			this.autoclosedrawing.CheckOnClick = true;
+			this.autoclosedrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.NewSector2;
+			this.autoclosedrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
+			this.autoclosedrawing.Margin = new System.Windows.Forms.Padding(2, 1, 0, 2);
+			this.autoclosedrawing.Name = "autoclosedrawing";
+			this.autoclosedrawing.Size = new System.Drawing.Size(133, 22);
+			this.autoclosedrawing.Text = "Auto-finish drawing";
+			this.autoclosedrawing.CheckedChanged += new System.EventHandler(this.autoclosedrawing_CheckedChanged);
+			// 
 			// DrawLineOptionsPanel
 			// 
 			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
 			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
 			this.Controls.Add(this.toolStrip1);
 			this.Name = "DrawLineOptionsPanel";
-			this.Size = new System.Drawing.Size(200, 60);
+			this.Size = new System.Drawing.Size(406, 60);
 			this.toolStrip1.ResumeLayout(false);
 			this.toolStrip1.PerformLayout();
 			this.ResumeLayout(false);
@@ -71,5 +84,6 @@
 
 		private System.Windows.Forms.ToolStrip toolStrip1;
 		private System.Windows.Forms.ToolStripButton continuousdrawing;
+		private System.Windows.Forms.ToolStripButton autoclosedrawing;
 	}
 }
diff --git a/Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.cs b/Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.cs
index fbc34259572874728f491ffcfb9bb3564282c11f..776e26e4cc22b2faea1d97216fd8d3341a1bb6cf 100644
--- a/Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.cs
+++ b/Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.cs
@@ -6,8 +6,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 	internal partial class DrawLineOptionsPanel : UserControl
 	{
 		public event EventHandler OnContinuousDrawingChanged;
+		public event EventHandler OnAutoCloseDrawingChanged;
 
 		public bool ContinuousDrawing { get { return continuousdrawing.Checked; } set { continuousdrawing.Checked = value; } }
+		public bool AutoCloseDrawing { get { return autoclosedrawing.Checked; } set { autoclosedrawing.Checked = value; } }
 		
 		public DrawLineOptionsPanel()
 		{
@@ -17,10 +19,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public void Register()
 		{
 			General.Interface.AddButton(continuousdrawing);
+			General.Interface.AddButton(autoclosedrawing);
 		}
 
 		public void Unregister()
 		{
+			General.Interface.RemoveButton(autoclosedrawing);
 			General.Interface.RemoveButton(continuousdrawing);
 		}
 
@@ -28,5 +32,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			if(OnContinuousDrawingChanged != null) OnContinuousDrawingChanged(continuousdrawing.Checked, EventArgs.Empty);
 		}
+
+		private void autoclosedrawing_CheckedChanged(object sender, EventArgs e)
+		{
+			if(OnAutoCloseDrawingChanged != null) OnAutoCloseDrawingChanged(autoclosedrawing.Checked, EventArgs.Empty);
+		}
 	}
 }
diff --git a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs
index aee62a101e19f37dfb73e2b69c4e62d20e5ce215..77d70a54eb0b537a538688b5fe1a16ecb4f9c12d 100644
--- a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs
+++ b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs
@@ -88,7 +88,6 @@
             0,
             0,
             0});
-			this.radius.ValueChanged += new System.EventHandler(this.ValueChanged);
 			// 
 			// subdivslabel
 			// 
@@ -118,7 +117,6 @@
             0,
             0,
             0});
-			this.subdivs.ValueChanged += new System.EventHandler(this.ValueChanged);
 			// 
 			// continuousdrawing
 			// 
diff --git a/Source/Plugins/BuilderModes/Interface/MenusForm.Designer.cs b/Source/Plugins/BuilderModes/Interface/MenusForm.Designer.cs
index 9e99436971432969b1e27cc65efe477a23663650..07d52c057509cd41f1a361dd263d1dbda3619cb2 100644
--- a/Source/Plugins/BuilderModes/Interface/MenusForm.Designer.cs
+++ b/Source/Plugins/BuilderModes/Interface/MenusForm.Designer.cs
@@ -107,6 +107,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.itemcopyprops = new System.Windows.Forms.ToolStripMenuItem();
 			this.itempasteprops = new System.Windows.Forms.ToolStripMenuItem();
 			this.itempastepropsoptions = new System.Windows.Forms.ToolStripMenuItem();
+			this.alignsectorlinedefsitem = new System.Windows.Forms.ToolStripMenuItem();
+			this.alignlinedefsitem = new System.Windows.Forms.ToolStripMenuItem();
 			this.menustrip.SuspendLayout();
 			this.manualstrip.SuspendLayout();
 			this.fileMenuStrip.SuspendLayout();
@@ -135,6 +137,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
             this.selectdoublesideditem,
             this.toolStripMenuItem4,
             this.fliplinedefsitem,
+            this.alignlinedefsitem,
             this.flipsidedefsitem,
             this.toolStripMenuItem1,
             this.curvelinedefsitem,
@@ -318,6 +321,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
             this.mergesectorsitem,
             this.toolStripMenuItem2,
             this.flipsectorlinedefsitem,
+            this.alignsectorlinedefsitem,
             this.toolStripSeparator8,
             this.makedooritem,
             this.toolStripSeparator4,
@@ -847,6 +851,23 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.itempastepropsoptions.Text = "Paste Properties Special...";
 			this.itempastepropsoptions.Click += new System.EventHandler(this.InvokeTaggedAction);
 			// 
+			// alignsectorlinedefsitem
+			// 
+			this.alignsectorlinedefsitem.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Flip;
+			this.alignsectorlinedefsitem.Name = "alignsectorlinedefsitem";
+			this.alignsectorlinedefsitem.Size = new System.Drawing.Size(224, 22);
+			this.alignsectorlinedefsitem.Tag = "alignlinedefs";
+			this.alignsectorlinedefsitem.Text = "Align &Linedefs";
+			this.alignsectorlinedefsitem.Click += new System.EventHandler(this.InvokeTaggedAction);
+			// 
+			// alignlinedefsitem
+			// 
+			this.alignlinedefsitem.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Flip;
+			this.alignlinedefsitem.Name = "alignlinedefsitem";
+			this.alignlinedefsitem.Size = new System.Drawing.Size(224, 22);
+			this.alignlinedefsitem.Tag = "alignlinedefs";
+			this.alignlinedefsitem.Text = "Align &Linedefs";
+			// 
 			// MenusForm
 			// 
 			this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -955,5 +976,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		private System.Windows.Forms.ToolStripMenuItem itempasteprops;
 		private System.Windows.Forms.ToolStripMenuItem itempastepropsoptions;
 		private System.Windows.Forms.ToolStripSeparator separatorcopyprops;
+		private System.Windows.Forms.ToolStripMenuItem alignsectorlinedefsitem;
+		private System.Windows.Forms.ToolStripMenuItem alignlinedefsitem;
 	}
 }
\ No newline at end of file
diff --git a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
index a4739659012e9cf6f2ac1ab6e0b075884952de81..3a36fac33c6a60c8a577ca17dbb494271c6d020d 100644
--- a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
+++ b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
@@ -1,7 +1,7 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:2.0.50727.5485
+//     Runtime Version:2.0.50727.5466
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
@@ -256,6 +256,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties {
             }
         }
         
+        internal static System.Drawing.Bitmap NewSector2 {
+            get {
+                object obj = ResourceManager.GetObject("NewSector2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
         internal static System.Drawing.Bitmap PasteProperties {
             get {
                 object obj = ResourceManager.GetObject("PasteProperties", resourceCulture);
diff --git a/Source/Plugins/BuilderModes/Properties/Resources.resx b/Source/Plugins/BuilderModes/Properties/Resources.resx
index f6dd0729e20d388f55f5c65e7b6e860c3e88e302..6992badfbfe7eaaccd723f30cd93c0d12bf83c2a 100644
--- a/Source/Plugins/BuilderModes/Properties/Resources.resx
+++ b/Source/Plugins/BuilderModes/Properties/Resources.resx
@@ -118,6 +118,9 @@
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="Join" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Join.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
   <data name="FloorAlign" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\FloorAlign.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
@@ -136,6 +139,9 @@
   <data name="ViewSelectionEffects" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\ViewSelectionEffects.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="Flip" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Flip.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
   <data name="HideAll" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\HideAll.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
@@ -193,9 +199,6 @@
   <data name="Text" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\Text.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
-  <data name="Show" type="System.Resources.ResXFileRef, System.Windows.Forms">
-    <value>..\Resources\Show.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
-  </data>
   <data name="BrightnessGradient" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\BrightnessGradient.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
@@ -211,8 +214,8 @@
   <data name="Reset" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\Reset.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
-  <data name="Join" type="System.Resources.ResXFileRef, System.Windows.Forms">
-    <value>..\Resources\Join.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  <data name="Show" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Show.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
   <data name="ViewSelectionIndex" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\ViewSelectionIndex.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
@@ -229,8 +232,8 @@
   <data name="ColorPick" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\ColorPick.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
-  <data name="Flip" type="System.Resources.ResXFileRef, System.Windows.Forms">
-    <value>..\Resources\Flip.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  <data name="Repeat" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Repeat.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
   <data name="FlipSelectionH" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\FlipSelectionH.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
@@ -256,7 +259,7 @@
   <data name="Show3" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\Show3.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
-  <data name="Repeat" type="System.Resources.ResXFileRef, System.Windows.Forms">
-    <value>..\Resources\Repeat.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  <data name="NewSector2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\NewSector2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
 </root>
\ No newline at end of file
diff --git a/Source/Plugins/BuilderModes/Resources/Actions.cfg b/Source/Plugins/BuilderModes/Resources/Actions.cfg
index 444923fcd039f2e8397109122c0b1182e2c68c8a..04ca2188506a19e327ebf75627ff5174ebd3c162 100644
--- a/Source/Plugins/BuilderModes/Resources/Actions.cfg
+++ b/Source/Plugins/BuilderModes/Resources/Actions.cfg
@@ -298,6 +298,16 @@ fliplinedefs
 	allowscroll = true;
 }
 
+alignlinedefs //mxd
+{
+	title = "Align Linedefs";
+	category = "linedefs";
+	description = "This aligns the selected linedefs, so their front (or back) point towards (or away from) the same sector.";
+	allowkeys = true;
+	allowmouse = true;
+	allowscroll = true;
+}
+
 flipsidedefs
 {
 	title = "Flip Sidedefs";
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySector.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySector.cs
index 096d6d0b473a6a90581c82cb98403963b66fd367..9eccf262f10ec063fdaf648b77367dd7fbc0544a 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySector.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySector.cs
@@ -580,7 +580,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		}
 		
 		// Processing
-		public virtual void OnProcess(float deltatime)
+		public virtual void OnProcess(long deltatime)
 		{
 			// If the texture was not loaded, but is loaded now, then re-setup geometry
 			if(setuponloadedtexture != 0)
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs
index d0623eeda069c612a939df40d2a70e361e7fbf62..8af4ca056e43dcdfc1d4ae07091f1413212a390f 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs
@@ -795,7 +795,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		}
 		
 		// Processing
-		public virtual void OnProcess(float deltatime)
+		public virtual void OnProcess(long deltatime)
 		{
 			// If the texture was not loaded, but is loaded now, then re-setup geometry
 			if(setuponloadedtexture != 0)
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
index f8db38f344e423be26c2d4518fd36b6ef28f6afb..1a8434886ca8e41def7db20caa0c4da5728c638a 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
@@ -606,7 +606,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public void OnTextureAlign(bool alignx, bool aligny) { }
 		public void OnToggleUpperUnpegged() { }
 		public void OnToggleLowerUnpegged() { }
-		public void OnProcess(float deltatime) { }
+		public void OnProcess(long deltatime) { }
 		public void OnTextureFloodfill() { }
 		public void OnInsert() { }
 		public void OnTextureFit(FitTextureOptions options) { } //mxd
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualVertex.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualVertex.cs
index a0b9e5c5510cfa2cd1e1f08f16ada1bbfa38dcee..214dc9343bb5dc9522a281f00a8002d7006d108c 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualVertex.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualVertex.cs
@@ -254,7 +254,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public void OnToggleLowerUnpegged() { }
 		public void OnResetTextureOffset() { }
 		public void OnResetLocalTextureOffset() { } //mxd
-		public void OnProcess(float deltatime) { }
+		public void OnProcess(long deltatime) { }
 		public void OnTextureFloodfill() { }
 		public void OnInsert() { }
 		public void ApplyTexture(string texture) { }
diff --git a/Source/Plugins/BuilderModes/VisualModes/IVisualEventReceiver.cs b/Source/Plugins/BuilderModes/VisualModes/IVisualEventReceiver.cs
index c7e4467e6dd8a25c849964ac22d09803bc8e47a3..4582d5915910b1b5aa18a35258ae5c4a4ae64355 100644
--- a/Source/Plugins/BuilderModes/VisualModes/IVisualEventReceiver.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/IVisualEventReceiver.cs
@@ -48,7 +48,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		void OnTextureFloodfill();
 		void OnToggleUpperUnpegged();
 		void OnToggleLowerUnpegged();
-		void OnProcess(float deltatime);
+		void OnProcess(long deltatime);
 		void OnInsert();
 		void OnDelete();
 
diff --git a/Source/Plugins/BuilderModes/VisualModes/NullVisualEventReceiver.cs b/Source/Plugins/BuilderModes/VisualModes/NullVisualEventReceiver.cs
index 596d19d1fd1d81c86ef42865a83c1576f38c0302..32f8f54694c3c70ed2ed50a85f3e7d1763cf5c26 100644
--- a/Source/Plugins/BuilderModes/VisualModes/NullVisualEventReceiver.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/NullVisualEventReceiver.cs
@@ -48,7 +48,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public void OnTextureFloodfill() { }
 		public void OnToggleUpperUnpegged()	{ }
 		public void OnToggleLowerUnpegged()	{ }
-		public void OnProcess(float deltatime) { }
+		public void OnProcess(long deltatime) { }
 		public void OnInsert() { }
 		public void OnDelete() { }
 		public void ApplyTexture(string texture) { }