diff --git a/Source/Core/Editing/CopyPasteManager.cs b/Source/Core/Editing/CopyPasteManager.cs index 8e72b86..618f0cc 100644 --- a/Source/Core/Editing/CopyPasteManager.cs +++ b/Source/Core/Editing/CopyPasteManager.cs @@ -246,7 +246,7 @@ namespace CodeImp.DoomBuilder.Editing // Write data to stream MemoryStream memstream = new MemoryStream(); ClipboardStreamWriter writer = new ClipboardStreamWriter(); //mxd - writer.Write(copyset, memstream, General.Map.Config.UseLongTextureNames); + writer.Write(copyset, memstream); // Set on clipboard Clipboard.SetData(CLIPBOARD_DATA_FORMAT, memstream); @@ -290,37 +290,31 @@ namespace CodeImp.DoomBuilder.Editing // Create undo General.MainWindow.DisplayStatus(StatusType.Action, "Pasted selected elements."); General.Map.UndoRedo.CreateUndo("Paste"); - - // Read from clipboard - Stream memstream = (Stream)Clipboard.GetData(CLIPBOARD_DATA_FORMAT); - memstream.Seek(0, SeekOrigin.Begin); // Mark all current geometry General.Map.Map.ClearAllMarks(true); - // Read data stream - ClipboardStreamReader reader = new ClipboardStreamReader(); //mxd - General.Map.Map.BeginAddRemove(); - reader.Read(General.Map.Map, memstream); - General.Map.Map.EndAddRemove(); + // Read from clipboard + using(Stream memstream = (Stream)Clipboard.GetData(CLIPBOARD_DATA_FORMAT)) + { + // Rewind before use + memstream.Seek(0, SeekOrigin.Begin); + + // Read data stream + ClipboardStreamReader reader = new ClipboardStreamReader(); //mxd + General.Map.Map.BeginAddRemove(); + bool success = reader.Read(General.Map.Map, memstream); + General.Map.Map.EndAddRemove(); + if(!success) //mxd + { + General.Map.UndoRedo.WithdrawUndo(); // This will also mess with the marks... + General.Map.Map.ClearAllMarks(true); // So re-mark all current geometry... + } + } // The new geometry is not marked, so invert the marks to get it marked General.Map.Map.InvertAllMarks(); - // Convert UDMF fields back to flags and activations, if needed - if(!(General.Map.FormatInterface is UniversalMapSetIO || General.Map.FormatInterface is SRB2MapSetIO)) General.Map.Map.TranslateFromUDMF(); - - //mxd. Translate texture names - General.Map.Map.TranslateTextureNames(General.Map.Config.UseLongTextureNames, true); - - // Modify tags and actions if preferred - if(options.ChangeTags == PasteOptions.TAGS_REMOVE) Tools.RemoveMarkedTags(); - if(options.ChangeTags == PasteOptions.TAGS_RENUMBER) Tools.RenumberMarkedTags(); - if(options.RemoveActions) Tools.RemoveMarkedActions(); - - // Clean up - memstream.Dispose(); - // Check if anything was pasted List things = General.Map.Map.GetMarkedThings(true); //mxd int totalpasted = things.Count; @@ -328,14 +322,25 @@ namespace CodeImp.DoomBuilder.Editing totalpasted += General.Map.Map.GetMarkedLinedefs(true).Count; totalpasted += General.Map.Map.GetMarkedSidedefs(true).Count; totalpasted += General.Map.Map.GetMarkedSectors(true).Count; + if(totalpasted > 0) { + // Convert UDMF fields back to flags and activations, if needed + if(!(General.Map.FormatInterface is UniversalMapSetIO || General.Map.FormatInterface is SRB2MapSetIO)) General.Map.Map.TranslateFromUDMF(); + + //mxd. Translate texture names + General.Map.Map.TranslateTextureNames(General.Map.Config.UseLongTextureNames, true); + + // Modify tags and actions if preferred + if(options.ChangeTags == PasteOptions.TAGS_REMOVE) Tools.RemoveMarkedTags(); + if(options.ChangeTags == PasteOptions.TAGS_RENUMBER) Tools.RenumberMarkedTags(); + if(options.RemoveActions) Tools.RemoveMarkedActions(); + foreach(Thing t in things) t.UpdateConfiguration(); //mxd General.Map.ThingsFilter.Update(); General.Editing.Mode.OnPasteEnd(options.Copy()); General.Plugins.OnPasteEnd(options); } - return; } } } diff --git a/Source/Core/IO/ClipboardStreamReader.cs b/Source/Core/IO/ClipboardStreamReader.cs index 22fc265..4580b84 100644 --- a/Source/Core/IO/ClipboardStreamReader.cs +++ b/Source/Core/IO/ClipboardStreamReader.cs @@ -7,6 +7,7 @@ using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Types; +using CodeImp.DoomBuilder.Windows; #endregion @@ -29,32 +30,56 @@ namespace CodeImp.DoomBuilder.IO public Dictionary Flags; } - private bool uselongtexturenames; //mxd - #endregion #region ================== Properties - public bool UseLongTextureNames { get { return uselongtexturenames; } } //mxd - #endregion #region ================== Reading // This reads from a stream - public MapSet Read(MapSet map, Stream stream) + public bool Read(MapSet map, Stream stream) { BinaryReader reader = new BinaryReader(stream); + //mxd. Sanity checks + int numverts = reader.ReadInt32(); + if(map.Vertices.Count + numverts >= General.Map.FormatInterface.MaxVertices) + { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste: resulting number of vertices (" + (map.Vertices.Count + numverts) + ") will exceed map format's maximum (" + General.Map.FormatInterface.MaxVertices + ")."); + return false; + } + + int numsectors = reader.ReadInt32(); + if(map.Sectors.Count + numsectors >= General.Map.FormatInterface.MaxSectors) + { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste: resulting number of sectors (" + (map.Sectors.Count + numsectors) + ") will exceed map format's maximum (" + General.Map.FormatInterface.MaxSectors + ")."); + return false; + } + + int numlinedefs = reader.ReadInt32(); + if(map.Linedefs.Count + numlinedefs >= General.Map.FormatInterface.MaxLinedefs) + { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste: resulting number of linedefs (" + (map.Linedefs.Count + numlinedefs) + ") will exceed map format's maximum (" + General.Map.FormatInterface.MaxLinedefs + ")."); + return false; + } + + int numthings = reader.ReadInt32(); + if(map.Things.Count + numthings >= General.Map.FormatInterface.MaxThings) + { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste: resulting number of things (" + (map.Things.Count + numthings) + ") will exceed map format's maximum (" + General.Map.FormatInterface.MaxThings + ")."); + return false; + } + // Read the map - uselongtexturenames = reader.ReadBoolean(); //mxd Dictionary vertexlink = ReadVertices(map, reader); Dictionary sectorlink = ReadSectors(map, reader); Dictionary sidedeflink = ReadSidedefs(reader); ReadLinedefs(map, reader, vertexlink, sectorlink, sidedeflink); ReadThings(map, reader); - return map; + return true; } private static Dictionary ReadVertices(MapSet map, BinaryReader reader) @@ -388,7 +413,7 @@ namespace CodeImp.DoomBuilder.IO break; default: //WOLOLO! ERRORS! - throw new Exception("Got unknown value type while reading custom fields from clipboard data! Field '" + name + "', type '" + type + "', primitive type '" + valueType + "'"); + throw new Exception("Got unknown value type while reading custom fields from clipboard data! Field \"" + name + "\", type \"" + type + "\", primitive type \"" + valueType + "\""); } } diff --git a/Source/Core/IO/ClipboardStreamWriter.cs b/Source/Core/IO/ClipboardStreamWriter.cs index 28ee6f1..7c7bce2 100644 --- a/Source/Core/IO/ClipboardStreamWriter.cs +++ b/Source/Core/IO/ClipboardStreamWriter.cs @@ -22,7 +22,7 @@ namespace CodeImp.DoomBuilder.IO #region ================== Variables - private Configuration config; + private readonly Configuration config; #endregion @@ -83,13 +83,13 @@ namespace CodeImp.DoomBuilder.IO #region ================== Writing - public void Write(MapSet map, Stream stream, bool longtexturenames) + public void Write(MapSet map, Stream stream) { - Write(map.Vertices, map.Linedefs, map.Sidedefs, map.Sectors, map.Things, stream, longtexturenames); + Write(map.Vertices, map.Linedefs, map.Sidedefs, map.Sectors, map.Things, stream); } public void Write(ICollection vertices, ICollection linedefs, ICollection sidedefs, - ICollection sectors, ICollection things, Stream stream, bool longtexturenames) + ICollection sectors, ICollection things, Stream stream) { // Create collections Dictionary vertexids = new Dictionary(); @@ -104,7 +104,10 @@ namespace CodeImp.DoomBuilder.IO BinaryWriter writer = new BinaryWriter(stream); // Write the data structures to stream - writer.Write(longtexturenames); //mxd + writer.Write(vertices.Count); //mxd + writer.Write(sectors.Count); //mxd + writer.Write(linedefs.Count); //mxd + writer.Write(things.Count); //mxd WriteVertices(vertices, writer); WriteSectors(sectors, writer); WriteSidedefs(sidedefs, writer, sectorids); @@ -292,8 +295,8 @@ namespace CodeImp.DoomBuilder.IO writer.Write(s.ToCharArray()); } else //WOLOLO! ERRORS! - { - General.ErrorLogger.Add(ErrorType.Error, "Unable to copy Universal Field '" + f.Key + "' to clipboard: unknown value type '" + f.Value.Type + "'!"); + { + General.ErrorLogger.Add(ErrorType.Error, "Unable to copy Universal Field \"" + f.Key + "\" to clipboard: unknown value type \"" + f.Value.Type + "\"!"); } } }