From e8d60d96f4d3584522931bb9850ea0df5c882a9f Mon Sep 17 00:00:00 2001 From: Justin Aquadro Date: Sat, 3 Nov 2012 21:36:12 -0400 Subject: [PATCH] Experimental monomac-based version of project --- NBTExplorerMac/DataNode.cs | 121 + NBTExplorerMac/IconRegistry.cs | 30 + NBTExplorerMac/Info.plist | 18 + NBTExplorerMac/LICENSE.txt | 19 + NBTExplorerMac/Mac/AppDelegate.cs | 24 + NBTExplorerMac/Mac/AppDelegate.designer.cs | 10 + NBTExplorerMac/Mac/MainMenu.xib | 4074 +++++++++++++++++ NBTExplorerMac/Mac/MainWindow.cs | 35 + NBTExplorerMac/Mac/MainWindow.designer.cs | 17 + NBTExplorerMac/Mac/MainWindow.xib | 189 + NBTExplorerMac/Mac/MainWindowController.cs | 48 + NBTExplorerMac/Mac/TreeDataNode.cs | 12 + NBTExplorerMac/Mac/TreeDataSource.cs | 12 + NBTExplorerMac/MainForm.Designer.cs | 718 +++ NBTExplorerMac/MainForm.cs | 983 ++++ NBTExplorerMac/MainForm.resources | Bin 0 -> 60582 bytes NBTExplorerMac/MainForm.resx | 1146 +++++ NBTExplorerMac/Model/CompoundTagContainer.cs | 65 + NBTExplorerMac/Model/CubicRegionDataNode.cs | 75 + NBTExplorerMac/Model/CubicRegionFile.cs | 24 + NBTExplorerMac/Model/DataNode.cs | 215 + NBTExplorerMac/Model/DataNodeCollection.cs | 121 + NBTExplorerMac/Model/DirectoryDataNode.cs | 55 + NBTExplorerMac/Model/FileTypeRegistry.cs | 69 + NBTExplorerMac/Model/ListTagContainer.cs | 38 + NBTExplorerMac/Model/NbtFileDataNode.cs | 141 + NBTExplorerMac/Model/NodeCapabilities.cs | 19 + NBTExplorerMac/Model/RegionChunkDataNode.cs | 104 + NBTExplorerMac/Model/RegionFileDataNode.cs | 76 + NBTExplorerMac/Model/TagByteArrayDataNode.cs | 37 + NBTExplorerMac/Model/TagByteDataNode.cs | 26 + NBTExplorerMac/Model/TagCompoundDataNode.cs | 130 + NBTExplorerMac/Model/TagContainerInterface.cs | 36 + NBTExplorerMac/Model/TagDataNode.cs | 344 ++ NBTExplorerMac/Model/TagDoubleDataNode.cs | 16 + NBTExplorerMac/Model/TagFloatDataNode.cs | 16 + NBTExplorerMac/Model/TagIntArrayDataNode.cs | 37 + NBTExplorerMac/Model/TagIntDataNode.cs | 16 + NBTExplorerMac/Model/TagListDataNode.cs | 111 + NBTExplorerMac/Model/TagLongDataNode.cs | 16 + NBTExplorerMac/Model/TagShortDataNode.cs | 16 + NBTExplorerMac/Model/TagStringDataNode.cs | 21 + NBTExplorerMac/NBTExplorerMac.csproj | 72 + NBTExplorerMac/NbtClipboardData.cs | 62 + NBTExplorerMac/Program.cs | 35 + NBTExplorerMac/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 77 + NBTExplorerMac/Properties/Resources.resources | Bin 0 -> 1557 bytes NBTExplorerMac/Properties/Resources.resx | 127 + .../Properties/Settings.Designer.cs | 48 + NBTExplorerMac/Properties/Settings.settings | 12 + NBTExplorerMac/Resources/24/box-24.png | Bin 0 -> 654 bytes NBTExplorerMac/Resources/24/cross.png | Bin 0 -> 1081 bytes NBTExplorerMac/Resources/24/document-b.png | Bin 0 -> 3486 bytes NBTExplorerMac/Resources/24/document-d.png | Bin 0 -> 3467 bytes NBTExplorerMac/Resources/24/document-f.png | Bin 0 -> 3413 bytes NBTExplorerMac/Resources/24/document-i.png | Bin 0 -> 3417 bytes NBTExplorerMac/Resources/24/document-l.png | Bin 0 -> 3376 bytes NBTExplorerMac/Resources/24/document-s.png | Bin 0 -> 3508 bytes NBTExplorerMac/Resources/24/document.png | Bin 0 -> 624 bytes NBTExplorerMac/Resources/24/edit-code-i.png | Bin 0 -> 3263 bytes NBTExplorerMac/Resources/24/edit-code.png | Bin 0 -> 3135 bytes NBTExplorerMac/Resources/24/edit-list.png | Bin 0 -> 3026 bytes .../Resources/24/edit-smallcaps.png | Bin 0 -> 3188 bytes NBTExplorerMac/Resources/24/pencil.png | Bin 0 -> 603 bytes NBTExplorerMac/Resources/24/scissors.png | Bin 0 -> 1125 bytes .../Resources/24/selection-input.png | Bin 0 -> 3561 bytes NBTExplorerMac/Resources/Dead_Bush.png | Bin 0 -> 693 bytes NBTExplorerMac/Resources/arrow-090.png | Bin 0 -> 618 bytes NBTExplorerMac/Resources/arrow-270.png | Bin 0 -> 622 bytes NBTExplorerMac/Resources/binocular--arrow.png | Bin 0 -> 733 bytes NBTExplorerMac/Resources/binocular.png | Bin 0 -> 621 bytes NBTExplorerMac/Resources/clipboard-paste.png | Bin 0 -> 685 bytes NBTExplorerMac/Resources/cross.png | Bin 0 -> 544 bytes NBTExplorerMac/Resources/disk--pencil.png | Bin 0 -> 677 bytes NBTExplorerMac/Resources/disk-24.png | Bin 0 -> 691 bytes NBTExplorerMac/Resources/disk.png | Bin 0 -> 507 bytes .../Resources/document-attribute-b.png | Bin 0 -> 612 bytes .../Resources/document-attribute-i.png | Bin 0 -> 587 bytes NBTExplorerMac/Resources/document-copy.png | Bin 0 -> 606 bytes NBTExplorerMac/Resources/door.png | Bin 0 -> 503 bytes NBTExplorerMac/Resources/edit-code-b.png | Bin 0 -> 388 bytes NBTExplorerMac/Resources/edit-code-i.png | Bin 0 -> 380 bytes NBTExplorerMac/Resources/edit-code.png | Bin 0 -> 308 bytes NBTExplorerMac/Resources/folder-open-24.png | Bin 0 -> 886 bytes .../Resources/folder-open-document.png | Bin 0 -> 677 bytes NBTExplorerMac/Resources/folder-open.png | Bin 0 -> 647 bytes .../Resources/information-frame.png | Bin 0 -> 898 bytes NBTExplorerMac/Resources/pencil.png | Bin 0 -> 1529 bytes NBTExplorerMac/Resources/question-frame.png | Bin 0 -> 925 bytes NBTExplorerMac/Resources/question-white.png | Bin 0 -> 761 bytes NBTExplorerMac/Resources/scissors.png | Bin 0 -> 690 bytes NBTExplorerMac/Resources/selection-input.png | Bin 0 -> 265 bytes NBTExplorerMac/SearchWorker.cs | 121 + NBTExplorerMac/TagKey.cs | 39 + .../Be.Windows.Forms.HexBox/AssemblyInfo.cs | 70 + .../BuiltInContextMenu.cs | 220 + .../ByteCharConverters.cs | 104 + .../Be.Windows.Forms.HexBox/ByteCollection.cs | 127 + .../BytePositionInfo.cs | 28 + .../Be.Windows.Forms.HexBox/DataBlock.cs | 42 + .../Vendor/Be.Windows.Forms.HexBox/DataMap.cs | 318 ++ .../DynamicByteProvider.cs | 177 + .../DynamicFileByteProvider.cs | 569 +++ .../FileByteProvider.cs | 271 ++ .../Be.Windows.Forms.HexBox/FileDataBlock.cs | 96 + .../Vendor/Be.Windows.Forms.HexBox/HexBox.bmp | Bin 0 -> 246 bytes .../Vendor/Be.Windows.Forms.HexBox/HexBox.cs | 3701 +++++++++++++++ .../Be.Windows.Forms.HexBox/HexBox.resources | Bin 0 -> 180 bytes .../Be.Windows.Forms.HexBox/HexBox.resx | 126 + .../Be.Windows.Forms.HexBox/HexCasing.cs | 21 + .../Be.Windows.Forms.HexBox/IByteProvider.cs | 75 + .../MemoryDataBlock.cs | 87 + .../Be.Windows.Forms.HexBox/NativeMethods.cs | 27 + .../Properties/Resources.Designer.cs | 63 + .../Properties/Resources.resx | 120 + .../Vendor/Be.Windows.Forms.HexBox/Util.cs | 38 + NBTExplorerMac/app.config | 9 + NBTExplorerMac/dead_bush.icns | Bin 0 -> 9100 bytes NBTExplorerMac/dead_bush.ico | Bin 0 -> 17542 bytes NBTExplorerMac/forms/About.Designer.cs | 85 + NBTExplorerMac/forms/About.cs | 22 + NBTExplorerMac/forms/About.resources | Bin 0 -> 1270 bytes NBTExplorerMac/forms/About.resx | 156 + .../forms/CancelSearchForm.Designer.cs | 63 + NBTExplorerMac/forms/CancelSearchForm.cs | 18 + .../forms/CancelSearchForm.resources | Bin 0 -> 180 bytes NBTExplorerMac/forms/CancelSearchForm.resx | 120 + NBTExplorerMac/forms/CreateNode.Designer.cs | 126 + NBTExplorerMac/forms/CreateNode.cs | 182 + NBTExplorerMac/forms/CreateNode.resources | Bin 0 -> 180 bytes NBTExplorerMac/forms/CreateNode.resx | 120 + NBTExplorerMac/forms/EditHex.Designer.cs | 130 + NBTExplorerMac/forms/EditHex.cs | 106 + NBTExplorerMac/forms/EditHex.resources | Bin 0 -> 180 bytes NBTExplorerMac/forms/EditHex.resx | 123 + NBTExplorerMac/forms/EditName.Designer.cs | 91 + NBTExplorerMac/forms/EditName.cs | 78 + NBTExplorerMac/forms/EditName.resources | Bin 0 -> 180 bytes NBTExplorerMac/forms/EditName.resx | 120 + NBTExplorerMac/forms/EditString.Designer.cs | 92 + NBTExplorerMac/forms/EditString.cs | 55 + NBTExplorerMac/forms/EditString.resources | Bin 0 -> 180 bytes NBTExplorerMac/forms/EditString.resx | 120 + NBTExplorerMac/forms/EditValue.Designer.cs | 91 + NBTExplorerMac/forms/EditValue.cs | 101 + NBTExplorerMac/forms/EditValue.resources | Bin 0 -> 180 bytes NBTExplorerMac/forms/EditValue.resx | 120 + NBTExplorerMac/forms/Find.Designer.cs | 133 + NBTExplorerMac/forms/Find.cs | 49 + NBTExplorerMac/forms/Find.resources | Bin 0 -> 180 bytes NBTExplorerMac/forms/Find.resx | 120 + Test/AppDelegate.cs | 24 + Test/AppDelegate.designer.cs | 10 + Test/Info.plist | 18 + Test/Main.cs | 18 + Test/MainMenu.xib | 4074 +++++++++++++++++ Test/MainWindow.cs | 35 + Test/MainWindow.designer.cs | 17 + Test/MainWindow.xib | 189 + Test/MainWindowController.cs | 48 + Test/Resources/scissors.png | Bin 0 -> 690 bytes Test/Test.csproj | 88 + 163 files changed, 23140 insertions(+) create mode 100644 NBTExplorerMac/DataNode.cs create mode 100644 NBTExplorerMac/IconRegistry.cs create mode 100644 NBTExplorerMac/Info.plist create mode 100644 NBTExplorerMac/LICENSE.txt create mode 100644 NBTExplorerMac/Mac/AppDelegate.cs create mode 100644 NBTExplorerMac/Mac/AppDelegate.designer.cs create mode 100644 NBTExplorerMac/Mac/MainMenu.xib create mode 100644 NBTExplorerMac/Mac/MainWindow.cs create mode 100644 NBTExplorerMac/Mac/MainWindow.designer.cs create mode 100644 NBTExplorerMac/Mac/MainWindow.xib create mode 100644 NBTExplorerMac/Mac/MainWindowController.cs create mode 100644 NBTExplorerMac/Mac/TreeDataNode.cs create mode 100644 NBTExplorerMac/Mac/TreeDataSource.cs create mode 100644 NBTExplorerMac/MainForm.Designer.cs create mode 100644 NBTExplorerMac/MainForm.cs create mode 100644 NBTExplorerMac/MainForm.resources create mode 100644 NBTExplorerMac/MainForm.resx create mode 100644 NBTExplorerMac/Model/CompoundTagContainer.cs create mode 100644 NBTExplorerMac/Model/CubicRegionDataNode.cs create mode 100644 NBTExplorerMac/Model/CubicRegionFile.cs create mode 100644 NBTExplorerMac/Model/DataNode.cs create mode 100644 NBTExplorerMac/Model/DataNodeCollection.cs create mode 100644 NBTExplorerMac/Model/DirectoryDataNode.cs create mode 100644 NBTExplorerMac/Model/FileTypeRegistry.cs create mode 100644 NBTExplorerMac/Model/ListTagContainer.cs create mode 100644 NBTExplorerMac/Model/NbtFileDataNode.cs create mode 100644 NBTExplorerMac/Model/NodeCapabilities.cs create mode 100644 NBTExplorerMac/Model/RegionChunkDataNode.cs create mode 100644 NBTExplorerMac/Model/RegionFileDataNode.cs create mode 100644 NBTExplorerMac/Model/TagByteArrayDataNode.cs create mode 100644 NBTExplorerMac/Model/TagByteDataNode.cs create mode 100644 NBTExplorerMac/Model/TagCompoundDataNode.cs create mode 100644 NBTExplorerMac/Model/TagContainerInterface.cs create mode 100644 NBTExplorerMac/Model/TagDataNode.cs create mode 100644 NBTExplorerMac/Model/TagDoubleDataNode.cs create mode 100644 NBTExplorerMac/Model/TagFloatDataNode.cs create mode 100644 NBTExplorerMac/Model/TagIntArrayDataNode.cs create mode 100644 NBTExplorerMac/Model/TagIntDataNode.cs create mode 100644 NBTExplorerMac/Model/TagListDataNode.cs create mode 100644 NBTExplorerMac/Model/TagLongDataNode.cs create mode 100644 NBTExplorerMac/Model/TagShortDataNode.cs create mode 100644 NBTExplorerMac/Model/TagStringDataNode.cs create mode 100644 NBTExplorerMac/NBTExplorerMac.csproj create mode 100644 NBTExplorerMac/NbtClipboardData.cs create mode 100644 NBTExplorerMac/Program.cs create mode 100644 NBTExplorerMac/Properties/AssemblyInfo.cs create mode 100644 NBTExplorerMac/Properties/Resources.Designer.cs create mode 100644 NBTExplorerMac/Properties/Resources.resources create mode 100644 NBTExplorerMac/Properties/Resources.resx create mode 100644 NBTExplorerMac/Properties/Settings.Designer.cs create mode 100644 NBTExplorerMac/Properties/Settings.settings create mode 100644 NBTExplorerMac/Resources/24/box-24.png create mode 100644 NBTExplorerMac/Resources/24/cross.png create mode 100644 NBTExplorerMac/Resources/24/document-b.png create mode 100644 NBTExplorerMac/Resources/24/document-d.png create mode 100644 NBTExplorerMac/Resources/24/document-f.png create mode 100644 NBTExplorerMac/Resources/24/document-i.png create mode 100644 NBTExplorerMac/Resources/24/document-l.png create mode 100644 NBTExplorerMac/Resources/24/document-s.png create mode 100644 NBTExplorerMac/Resources/24/document.png create mode 100644 NBTExplorerMac/Resources/24/edit-code-i.png create mode 100644 NBTExplorerMac/Resources/24/edit-code.png create mode 100644 NBTExplorerMac/Resources/24/edit-list.png create mode 100644 NBTExplorerMac/Resources/24/edit-smallcaps.png create mode 100644 NBTExplorerMac/Resources/24/pencil.png create mode 100644 NBTExplorerMac/Resources/24/scissors.png create mode 100644 NBTExplorerMac/Resources/24/selection-input.png create mode 100644 NBTExplorerMac/Resources/Dead_Bush.png create mode 100644 NBTExplorerMac/Resources/arrow-090.png create mode 100644 NBTExplorerMac/Resources/arrow-270.png create mode 100644 NBTExplorerMac/Resources/binocular--arrow.png create mode 100644 NBTExplorerMac/Resources/binocular.png create mode 100644 NBTExplorerMac/Resources/clipboard-paste.png create mode 100644 NBTExplorerMac/Resources/cross.png create mode 100644 NBTExplorerMac/Resources/disk--pencil.png create mode 100644 NBTExplorerMac/Resources/disk-24.png create mode 100644 NBTExplorerMac/Resources/disk.png create mode 100644 NBTExplorerMac/Resources/document-attribute-b.png create mode 100644 NBTExplorerMac/Resources/document-attribute-i.png create mode 100644 NBTExplorerMac/Resources/document-copy.png create mode 100644 NBTExplorerMac/Resources/door.png create mode 100644 NBTExplorerMac/Resources/edit-code-b.png create mode 100644 NBTExplorerMac/Resources/edit-code-i.png create mode 100644 NBTExplorerMac/Resources/edit-code.png create mode 100644 NBTExplorerMac/Resources/folder-open-24.png create mode 100644 NBTExplorerMac/Resources/folder-open-document.png create mode 100644 NBTExplorerMac/Resources/folder-open.png create mode 100644 NBTExplorerMac/Resources/information-frame.png create mode 100644 NBTExplorerMac/Resources/pencil.png create mode 100644 NBTExplorerMac/Resources/question-frame.png create mode 100644 NBTExplorerMac/Resources/question-white.png create mode 100644 NBTExplorerMac/Resources/scissors.png create mode 100644 NBTExplorerMac/Resources/selection-input.png create mode 100644 NBTExplorerMac/SearchWorker.cs create mode 100644 NBTExplorerMac/TagKey.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/AssemblyInfo.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/BuiltInContextMenu.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/ByteCharConverters.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/ByteCollection.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/BytePositionInfo.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DataBlock.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DataMap.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DynamicByteProvider.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DynamicFileByteProvider.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/FileByteProvider.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/FileDataBlock.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.bmp create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.resources create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.resx create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexCasing.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/IByteProvider.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/MemoryDataBlock.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/NativeMethods.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Properties/Resources.Designer.cs create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Properties/Resources.resx create mode 100644 NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Util.cs create mode 100644 NBTExplorerMac/app.config create mode 100644 NBTExplorerMac/dead_bush.icns create mode 100644 NBTExplorerMac/dead_bush.ico create mode 100644 NBTExplorerMac/forms/About.Designer.cs create mode 100644 NBTExplorerMac/forms/About.cs create mode 100644 NBTExplorerMac/forms/About.resources create mode 100644 NBTExplorerMac/forms/About.resx create mode 100644 NBTExplorerMac/forms/CancelSearchForm.Designer.cs create mode 100644 NBTExplorerMac/forms/CancelSearchForm.cs create mode 100644 NBTExplorerMac/forms/CancelSearchForm.resources create mode 100644 NBTExplorerMac/forms/CancelSearchForm.resx create mode 100644 NBTExplorerMac/forms/CreateNode.Designer.cs create mode 100644 NBTExplorerMac/forms/CreateNode.cs create mode 100644 NBTExplorerMac/forms/CreateNode.resources create mode 100644 NBTExplorerMac/forms/CreateNode.resx create mode 100644 NBTExplorerMac/forms/EditHex.Designer.cs create mode 100644 NBTExplorerMac/forms/EditHex.cs create mode 100644 NBTExplorerMac/forms/EditHex.resources create mode 100644 NBTExplorerMac/forms/EditHex.resx create mode 100644 NBTExplorerMac/forms/EditName.Designer.cs create mode 100644 NBTExplorerMac/forms/EditName.cs create mode 100644 NBTExplorerMac/forms/EditName.resources create mode 100644 NBTExplorerMac/forms/EditName.resx create mode 100644 NBTExplorerMac/forms/EditString.Designer.cs create mode 100644 NBTExplorerMac/forms/EditString.cs create mode 100644 NBTExplorerMac/forms/EditString.resources create mode 100644 NBTExplorerMac/forms/EditString.resx create mode 100644 NBTExplorerMac/forms/EditValue.Designer.cs create mode 100644 NBTExplorerMac/forms/EditValue.cs create mode 100644 NBTExplorerMac/forms/EditValue.resources create mode 100644 NBTExplorerMac/forms/EditValue.resx create mode 100644 NBTExplorerMac/forms/Find.Designer.cs create mode 100644 NBTExplorerMac/forms/Find.cs create mode 100644 NBTExplorerMac/forms/Find.resources create mode 100644 NBTExplorerMac/forms/Find.resx create mode 100644 Test/AppDelegate.cs create mode 100644 Test/AppDelegate.designer.cs create mode 100644 Test/Info.plist create mode 100644 Test/Main.cs create mode 100644 Test/MainMenu.xib create mode 100644 Test/MainWindow.cs create mode 100644 Test/MainWindow.designer.cs create mode 100644 Test/MainWindow.xib create mode 100644 Test/MainWindowController.cs create mode 100644 Test/Resources/scissors.png create mode 100644 Test/Test.csproj diff --git a/NBTExplorerMac/DataNode.cs b/NBTExplorerMac/DataNode.cs new file mode 100644 index 0000000..ef3248d --- /dev/null +++ b/NBTExplorerMac/DataNode.cs @@ -0,0 +1,121 @@ +using Substrate.Core; +using Substrate.Nbt; +using System.Collections.Generic; +using System; +using System.Windows.Forms; + +namespace NBTExplorer +{ + public class DataNodeOld + { + public DataNodeOld () + { + } + + public DataNodeOld (DataNodeOld parent) + { + Parent = parent; + } + + public DataNodeOld Parent { get; set; } + + private bool _modified; + public bool Modified + { + get { return _modified; } + set + { + if (value && Parent != null) { + Parent.Modified = value; + } + _modified = value; + } + } + + public bool Expanded { get; set; } + } + + public class NbtDataNode : DataNodeOld + { + public NbtDataNode () + { + } + + public NbtDataNode (DataNodeOld parent) + : base(parent) + { + } + + public NbtTree Tree { get; set; } + } + + public class RegionChunkData : NbtDataNode + { + public RegionChunkData (RegionFile file, int x, int z) + : this(null, file, x, z) + { + } + + public RegionChunkData (DataNodeOld parent, RegionFile file, int x, int z) + : base(parent) + { + Region = file; + X = x; + Z = z; + } + + public RegionFile Region { get; private set; } + public int X { get; private set; } + public int Z { get; private set; } + } + + public class RegionData : DataNodeOld + { + public RegionData (string path) + : this(null, path) + { + } + + public RegionData (DataNodeOld parent, string path) + : base(parent) + { + Path = path; + } + + public string Path { get; private set; } + } + + public class NbtFileData : NbtDataNode + { + public NbtFileData (string path, CompressionType cztype) + : this(null, path, cztype) + { + } + + public NbtFileData (DataNodeOld parent, string path, CompressionType cztype) + : base(parent) + { + Path = path; + CompressionType = cztype; + } + + public string Path { get; private set; } + public CompressionType CompressionType { get; private set; } + } + + public class DirectoryData : DataNodeOld + { + public DirectoryData (string path) + : this(null, path) + { + } + + public DirectoryData (DataNodeOld parent, string path) + : base(parent) + { + Path = path; + } + + public string Path { get; private set; } + } +} diff --git a/NBTExplorerMac/IconRegistry.cs b/NBTExplorerMac/IconRegistry.cs new file mode 100644 index 0000000..14ec075 --- /dev/null +++ b/NBTExplorerMac/IconRegistry.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace NBTExplorer +{ + public class IconRegistry + { + private Dictionary _iconRegistry; + + public IconRegistry () + { + _iconRegistry = new Dictionary(); + } + + public int DefaultIcon { get; set; } + + public int Lookup (Type type) + { + if (_iconRegistry.ContainsKey(type)) + return _iconRegistry[type]; + else + return DefaultIcon; + } + + public void Register (Type type, int iconIndex) + { + _iconRegistry[type] = iconIndex; + } + } +} diff --git a/NBTExplorerMac/Info.plist b/NBTExplorerMac/Info.plist new file mode 100644 index 0000000..b123471 --- /dev/null +++ b/NBTExplorerMac/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.NBTExplorerMac + CFBundleName + NBTExplorerMac + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.6 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/NBTExplorerMac/LICENSE.txt b/NBTExplorerMac/LICENSE.txt new file mode 100644 index 0000000..27a2f7e --- /dev/null +++ b/NBTExplorerMac/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (C) 2011 by Justin Aquadro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/NBTExplorerMac/Mac/AppDelegate.cs b/NBTExplorerMac/Mac/AppDelegate.cs new file mode 100644 index 0000000..32579a8 --- /dev/null +++ b/NBTExplorerMac/Mac/AppDelegate.cs @@ -0,0 +1,24 @@ +using System; +using System.Drawing; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +namespace Test +{ + public partial class AppDelegate : NSApplicationDelegate + { + MainWindowController mainWindowController; + + public AppDelegate () + { + } + + public override void FinishedLaunching (NSObject notification) + { + mainWindowController = new MainWindowController (); + mainWindowController.Window.MakeKeyAndOrderFront (this); + } + } +} + diff --git a/NBTExplorerMac/Mac/AppDelegate.designer.cs b/NBTExplorerMac/Mac/AppDelegate.designer.cs new file mode 100644 index 0000000..e0d6166 --- /dev/null +++ b/NBTExplorerMac/Mac/AppDelegate.designer.cs @@ -0,0 +1,10 @@ + +namespace Test +{ + // Should subclass MonoMac.AppKit.NSResponder + [MonoMac.Foundation.Register("AppDelegate")] + public partial class AppDelegate + { + } +} + diff --git a/NBTExplorerMac/Mac/MainMenu.xib b/NBTExplorerMac/Mac/MainMenu.xib new file mode 100644 index 0000000..52d0fd5 --- /dev/null +++ b/NBTExplorerMac/Mac/MainMenu.xib @@ -0,0 +1,4074 @@ + + + + 1060 + 10D573 + 762 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 762 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + Test + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + MacCocoaApp + + YES + + + About Test + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide Test + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit Test + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + YES + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + YES + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + Test Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + NSFontManager + + + AppDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + terminate: + + + + 449 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + delegate + + + + 534 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + YES + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + + 377 + + + YES + + + + + + 388 + + + YES + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + YES + + + + + + 398 + + + YES + + + + + + 399 + + + YES + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + YES + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + YES + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + YES + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + YES + + + + + + 451 + + + YES + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + YES + + + + + + 491 + + + YES + + + + + + 492 + + + + + 496 + + + YES + + + + + + 497 + + + YES + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + YES + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + YES + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 533 + + + + + + + YES + + YES + -3.IBPluginDependency + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 375.IBPluginDependency + 376.IBEditorWindowLastContentRect + 376.IBPluginDependency + 377.IBPluginDependency + 388.IBEditorWindowLastContentRect + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 418.IBPluginDependency + 419.IBPluginDependency + 450.IBPluginDependency + 451.IBEditorWindowLastContentRect + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 457.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 462.IBPluginDependency + 465.IBPluginDependency + 466.IBPluginDependency + 485.IBPluginDependency + 490.IBPluginDependency + 491.IBEditorWindowLastContentRect + 491.IBPluginDependency + 492.IBPluginDependency + 496.IBPluginDependency + 497.IBEditorWindowLastContentRect + 497.IBPluginDependency + 498.IBPluginDependency + 499.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 500.IBPluginDependency + 501.IBPluginDependency + 502.IBPluginDependency + 503.IBPluginDependency + 504.IBPluginDependency + 505.IBPluginDependency + 506.IBPluginDependency + 507.IBPluginDependency + 508.IBEditorWindowLastContentRect + 508.IBPluginDependency + 509.IBPluginDependency + 510.IBPluginDependency + 511.IBPluginDependency + 512.IBPluginDependency + 513.IBPluginDependency + 514.IBPluginDependency + 515.IBPluginDependency + 516.IBPluginDependency + 517.IBPluginDependency + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 187}, {275, 113}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{453, 408}, {254, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{187, 434}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 217}, {238, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{613, 618}, {194, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{346, 722}, {402, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 978}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{563, 648}, {231, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{746, 287}, {220, 133}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{497, 648}, {83, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{580, 408}, {175, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{753, 197}, {170, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{684, 668}, {142, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{674, 260}, {204, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{878, 180}, {164, 173}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{355, 508}, {183, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{411, 488}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{145, 474}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 534 + + + + YES + + AppDelegate + NSResponder + + IBUserSource + + + + + + YES + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFontManager + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../MacCocoaApp.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/NBTExplorerMac/Mac/MainWindow.cs b/NBTExplorerMac/Mac/MainWindow.cs new file mode 100644 index 0000000..c744580 --- /dev/null +++ b/NBTExplorerMac/Mac/MainWindow.cs @@ -0,0 +1,35 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace NBTExplorer +{ + public partial class MainWindow : MonoMac.AppKit.NSWindow + { + #region Constructors + + // Called when created from unmanaged code + public MainWindow (IntPtr handle) : base (handle) + { + Initialize (); + } + + // Called when created directly from a XIB file + [Export ("initWithCoder:")] + public MainWindow (NSCoder coder) : base (coder) + { + Initialize (); + } + + // Shared initialization code + void Initialize () + { + } + + #endregion + } +} + diff --git a/NBTExplorerMac/Mac/MainWindow.designer.cs b/NBTExplorerMac/Mac/MainWindow.designer.cs new file mode 100644 index 0000000..e620e76 --- /dev/null +++ b/NBTExplorerMac/Mac/MainWindow.designer.cs @@ -0,0 +1,17 @@ + +namespace NBTExplorer +{ + + // Should subclass MonoMac.AppKit.NSWindow + [MonoMac.Foundation.Register("MainWindow")] + public partial class MainWindow + { + } + + // Should subclass MonoMac.AppKit.NSWindowController + [MonoMac.Foundation.Register("MainWindowController")] + public partial class MainWindowController + { + } +} + diff --git a/NBTExplorerMac/Mac/MainWindow.xib b/NBTExplorerMac/Mac/MainWindow.xib new file mode 100644 index 0000000..060535b --- /dev/null +++ b/NBTExplorerMac/Mac/MainWindow.xib @@ -0,0 +1,189 @@ + + + + 1060 + 10D573 + 762 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 762 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + MainWindowController + + + FirstResponder + + + NSApplication + + + 15 + 2 + {{131, 74}, {606, 354}} + 611844096 + Window + MainWindow + + {1.79769e+308, 1.79769e+308} + + + 256 + {606, 354} + + + {{0, 0}, {1280, 778}} + {1.79769e+308, 1.79769e+308} + + + + + YES + + + window + + + + 6 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 2 + + + YES + + + + + + 3 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 2.IBEditorWindowLastContentRect + 2.IBPluginDependency + 2.IBWindowTemplateEditedContentRect + 2.NSWindowTemplate.visibleAtLaunch + 3.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{319, 371}, {606, 354}} + com.apple.InterfaceBuilder.CocoaPlugin + {{319, 371}, {606, 354}} + + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 6 + + + + YES + + MainWindow + NSWindow + + IBUserSource + + + + + MainWindowController + NSWindowController + + IBUserSource + + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + + 3 + + diff --git a/NBTExplorerMac/Mac/MainWindowController.cs b/NBTExplorerMac/Mac/MainWindowController.cs new file mode 100644 index 0000000..c39fd21 --- /dev/null +++ b/NBTExplorerMac/Mac/MainWindowController.cs @@ -0,0 +1,48 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace NBTExplorer +{ + public partial class MainWindowController : MonoMac.AppKit.NSWindowController + { + #region Constructors + + // Called when created from unmanaged code + public MainWindowController (IntPtr handle) : base (handle) + { + Initialize (); + } + + // Called when created directly from a XIB file + [Export ("initWithCoder:")] + public MainWindowController (NSCoder coder) : base (coder) + { + Initialize (); + } + + // Call to load from the XIB/NIB file + public MainWindowController () : base ("MainWindow") + { + Initialize (); + } + + // Shared initialization code + void Initialize () + { + } + + #endregion + + //strongly typed window accessor + public new MainWindow Window { + get { + return (MainWindow)base.Window; + } + } + } +} + diff --git a/NBTExplorerMac/Mac/TreeDataNode.cs b/NBTExplorerMac/Mac/TreeDataNode.cs new file mode 100644 index 0000000..9cc1777 --- /dev/null +++ b/NBTExplorerMac/Mac/TreeDataNode.cs @@ -0,0 +1,12 @@ +using System; + +namespace NBTExplorer +{ + public class TreeDataNode + { + public TreeDataNode () + { + } + } +} + diff --git a/NBTExplorerMac/Mac/TreeDataSource.cs b/NBTExplorerMac/Mac/TreeDataSource.cs new file mode 100644 index 0000000..b43d782 --- /dev/null +++ b/NBTExplorerMac/Mac/TreeDataSource.cs @@ -0,0 +1,12 @@ +using System; + +namespace NBTExplorer.Mac +{ + public class TreeDataSource + { + public TreeDataSource () + { + } + } +} + diff --git a/NBTExplorerMac/MainForm.Designer.cs b/NBTExplorerMac/MainForm.Designer.cs new file mode 100644 index 0000000..1d3fd1d --- /dev/null +++ b/NBTExplorerMac/MainForm.Designer.cs @@ -0,0 +1,718 @@ +namespace NBTExplorer +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemOpen = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemOpenFolder = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemOpenMinecraftSaveFolder = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this._menuItemSave = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this._menuItemExit = new System.Windows.Forms.ToolStripMenuItem(); + this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemCut = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemCopy = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemPaste = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); + this._menuItemRename = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemEditValue = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemDelete = new System.Windows.Forms.ToolStripMenuItem(); + this.searchToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemFind = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemFindNext = new System.Windows.Forms.ToolStripMenuItem(); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemAbout = new System.Windows.Forms.ToolStripMenuItem(); + this._nodeTree = new System.Windows.Forms.TreeView(); + this.imageList1 = new System.Windows.Forms.ImageList(this.components); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this._buttonOpen = new System.Windows.Forms.ToolStripButton(); + this._buttonOpenFolder = new System.Windows.Forms.ToolStripButton(); + this._buttonSave = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this._buttonCut = new System.Windows.Forms.ToolStripButton(); + this._buttonCopy = new System.Windows.Forms.ToolStripButton(); + this._buttonPaste = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this._buttonRename = new System.Windows.Forms.ToolStripButton(); + this._buttonEdit = new System.Windows.Forms.ToolStripButton(); + this._buttonDelete = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this._buttonAddTagByte = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagShort = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagInt = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagLong = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagFloat = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagDouble = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagByteArray = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagIntArray = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagString = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagList = new System.Windows.Forms.ToolStripButton(); + this._buttonAddTagCompound = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); + this._buttonFindNext = new System.Windows.Forms.ToolStripButton(); + this.BottomToolStripPanel = new System.Windows.Forms.ToolStripPanel(); + this.TopToolStripPanel = new System.Windows.Forms.ToolStripPanel(); + this.RightToolStripPanel = new System.Windows.Forms.ToolStripPanel(); + this.LeftToolStripPanel = new System.Windows.Forms.ToolStripPanel(); + this.ContentPanel = new System.Windows.Forms.ToolStripContentPanel(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.testToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemRecentFiles = new System.Windows.Forms.ToolStripMenuItem(); + this._menuItemRecentFolders = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); + this.menuStrip1.SuspendLayout(); + this.toolStrip1.SuspendLayout(); + this.contextMenuStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.editToolStripMenuItem, + this.searchToolStripMenuItem, + this.helpToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(619, 24); + this.menuStrip1.TabIndex = 0; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this._menuItemOpen, + this._menuItemOpenFolder, + this._menuItemOpenMinecraftSaveFolder, + this.toolStripSeparator3, + this._menuItemSave, + this.toolStripSeparator4, + this._menuItemRecentFiles, + this._menuItemRecentFolders, + this.toolStripSeparator8, + this._menuItemExit}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Text = "&File"; + // + // _menuItemOpen + // + this._menuItemOpen.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemOpen.Image"))); + this._menuItemOpen.Name = "_menuItemOpen"; + this._menuItemOpen.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this._menuItemOpen.Size = new System.Drawing.Size(223, 22); + this._menuItemOpen.Text = "&Open..."; + // + // _menuItemOpenFolder + // + this._menuItemOpenFolder.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemOpenFolder.Image"))); + this._menuItemOpenFolder.Name = "_menuItemOpenFolder"; + this._menuItemOpenFolder.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.O))); + this._menuItemOpenFolder.Size = new System.Drawing.Size(223, 22); + this._menuItemOpenFolder.Text = "Open &Folder..."; + // + // _menuItemOpenMinecraftSaveFolder + // + this._menuItemOpenMinecraftSaveFolder.Name = "_menuItemOpenMinecraftSaveFolder"; + this._menuItemOpenMinecraftSaveFolder.Size = new System.Drawing.Size(223, 22); + this._menuItemOpenMinecraftSaveFolder.Text = "Open &Minecraft Save Folder"; + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(220, 6); + // + // _menuItemSave + // + this._menuItemSave.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemSave.Image"))); + this._menuItemSave.Name = "_menuItemSave"; + this._menuItemSave.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this._menuItemSave.Size = new System.Drawing.Size(223, 22); + this._menuItemSave.Text = "&Save"; + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(220, 6); + // + // _menuItemExit + // + this._menuItemExit.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemExit.Image"))); + this._menuItemExit.Name = "_menuItemExit"; + this._menuItemExit.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); + this._menuItemExit.Size = new System.Drawing.Size(223, 22); + this._menuItemExit.Text = "E&xit"; + // + // editToolStripMenuItem + // + this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this._menuItemCut, + this._menuItemCopy, + this._menuItemPaste, + this.toolStripSeparator7, + this._menuItemRename, + this._menuItemEditValue, + this._menuItemDelete}); + this.editToolStripMenuItem.Name = "editToolStripMenuItem"; + this.editToolStripMenuItem.Size = new System.Drawing.Size(39, 20); + this.editToolStripMenuItem.Text = "&Edit"; + // + // _menuItemCut + // + this._menuItemCut.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemCut.Image"))); + this._menuItemCut.Name = "_menuItemCut"; + this._menuItemCut.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X))); + this._menuItemCut.Size = new System.Drawing.Size(166, 22); + this._menuItemCut.Text = "Cu&t"; + // + // _menuItemCopy + // + this._menuItemCopy.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemCopy.Image"))); + this._menuItemCopy.Name = "_menuItemCopy"; + this._menuItemCopy.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C))); + this._menuItemCopy.Size = new System.Drawing.Size(166, 22); + this._menuItemCopy.Text = "&Copy"; + // + // _menuItemPaste + // + this._menuItemPaste.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemPaste.Image"))); + this._menuItemPaste.Name = "_menuItemPaste"; + this._menuItemPaste.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V))); + this._menuItemPaste.Size = new System.Drawing.Size(166, 22); + this._menuItemPaste.Text = "&Paste"; + // + // toolStripSeparator7 + // + this.toolStripSeparator7.Name = "toolStripSeparator7"; + this.toolStripSeparator7.Size = new System.Drawing.Size(163, 6); + // + // _menuItemRename + // + this._menuItemRename.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemRename.Image"))); + this._menuItemRename.Name = "_menuItemRename"; + this._menuItemRename.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.R))); + this._menuItemRename.Size = new System.Drawing.Size(166, 22); + this._menuItemRename.Text = "&Rename"; + // + // _menuItemEditValue + // + this._menuItemEditValue.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemEditValue.Image"))); + this._menuItemEditValue.Name = "_menuItemEditValue"; + this._menuItemEditValue.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); + this._menuItemEditValue.Size = new System.Drawing.Size(166, 22); + this._menuItemEditValue.Text = "&Edit Value"; + // + // _menuItemDelete + // + this._menuItemDelete.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemDelete.Image"))); + this._menuItemDelete.Name = "_menuItemDelete"; + this._menuItemDelete.ShortcutKeys = System.Windows.Forms.Keys.Delete; + this._menuItemDelete.Size = new System.Drawing.Size(166, 22); + this._menuItemDelete.Text = "&Delete"; + // + // searchToolStripMenuItem + // + this.searchToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this._menuItemFind, + this._menuItemFindNext}); + this.searchToolStripMenuItem.Name = "searchToolStripMenuItem"; + this.searchToolStripMenuItem.Size = new System.Drawing.Size(54, 20); + this.searchToolStripMenuItem.Text = "&Search"; + // + // _menuItemFind + // + this._menuItemFind.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemFind.Image"))); + this._menuItemFind.Name = "_menuItemFind"; + this._menuItemFind.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F))); + this._menuItemFind.Size = new System.Drawing.Size(146, 22); + this._menuItemFind.Text = "Find..."; + // + // _menuItemFindNext + // + this._menuItemFindNext.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemFindNext.Image"))); + this._menuItemFindNext.Name = "_menuItemFindNext"; + this._menuItemFindNext.ShortcutKeys = System.Windows.Forms.Keys.F3; + this._menuItemFindNext.Size = new System.Drawing.Size(146, 22); + this._menuItemFindNext.Text = "Find Next"; + // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this._menuItemAbout}); + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20); + this.helpToolStripMenuItem.Text = "&Help"; + // + // _menuItemAbout + // + this._menuItemAbout.Image = ((System.Drawing.Image)(resources.GetObject("_menuItemAbout.Image"))); + this._menuItemAbout.Name = "_menuItemAbout"; + this._menuItemAbout.ShortcutKeys = System.Windows.Forms.Keys.F1; + this._menuItemAbout.Size = new System.Drawing.Size(126, 22); + this._menuItemAbout.Text = "&About"; + // + // _nodeTree + // + this._nodeTree.AllowDrop = true; + this._nodeTree.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this._nodeTree.ImageIndex = 0; + this._nodeTree.ImageList = this.imageList1; + this._nodeTree.ItemHeight = 18; + this._nodeTree.Location = new System.Drawing.Point(0, 49); + this._nodeTree.Margin = new System.Windows.Forms.Padding(0); + this._nodeTree.Name = "_nodeTree"; + this._nodeTree.SelectedImageIndex = 0; + this._nodeTree.Size = new System.Drawing.Size(619, 374); + this._nodeTree.TabIndex = 0; + // + // imageList1 + // + this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream"))); + this.imageList1.TransparentColor = System.Drawing.Color.Transparent; + this.imageList1.Images.SetKeyName(0, "document-attribute-b.png"); + this.imageList1.Images.SetKeyName(1, "document-attribute-s.png"); + this.imageList1.Images.SetKeyName(2, "document-attribute-i.png"); + this.imageList1.Images.SetKeyName(3, "document-attribute-l.png"); + this.imageList1.Images.SetKeyName(4, "document-attribute-f.png"); + this.imageList1.Images.SetKeyName(5, "document-attribute-d.png"); + this.imageList1.Images.SetKeyName(6, "edit-code.png"); + this.imageList1.Images.SetKeyName(7, "edit-small-caps.png"); + this.imageList1.Images.SetKeyName(8, "edit-list.png"); + this.imageList1.Images.SetKeyName(9, "box.png"); + this.imageList1.Images.SetKeyName(10, "folder.png"); + this.imageList1.Images.SetKeyName(11, "block.png"); + this.imageList1.Images.SetKeyName(12, "wooden-box.png"); + this.imageList1.Images.SetKeyName(13, "map.png"); + this.imageList1.Images.SetKeyName(14, "edit-code-i.png"); + this.imageList1.Images.SetKeyName(15, "question-white.png"); + // + // toolStrip1 + // + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this._buttonOpen, + this._buttonOpenFolder, + this._buttonSave, + this.toolStripSeparator1, + this._buttonCut, + this._buttonCopy, + this._buttonPaste, + this.toolStripSeparator6, + this._buttonRename, + this._buttonEdit, + this._buttonDelete, + this.toolStripSeparator2, + this._buttonAddTagByte, + this._buttonAddTagShort, + this._buttonAddTagInt, + this._buttonAddTagLong, + this._buttonAddTagFloat, + this._buttonAddTagDouble, + this._buttonAddTagByteArray, + this._buttonAddTagIntArray, + this._buttonAddTagString, + this._buttonAddTagList, + this._buttonAddTagCompound, + this.toolStripSeparator5, + this._buttonFindNext}); + this.toolStrip1.Location = new System.Drawing.Point(0, 24); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(619, 25); + this.toolStrip1.Stretch = true; + this.toolStrip1.TabIndex = 0; + // + // _buttonOpen + // + this._buttonOpen.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonOpen.Image = ((System.Drawing.Image)(resources.GetObject("_buttonOpen.Image"))); + this._buttonOpen.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonOpen.Name = "_buttonOpen"; + this._buttonOpen.Size = new System.Drawing.Size(23, 22); + this._buttonOpen.Text = "Open NBT Data Source"; + // + // _buttonOpenFolder + // + this._buttonOpenFolder.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonOpenFolder.Image = ((System.Drawing.Image)(resources.GetObject("_buttonOpenFolder.Image"))); + this._buttonOpenFolder.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonOpenFolder.Name = "_buttonOpenFolder"; + this._buttonOpenFolder.Size = new System.Drawing.Size(23, 22); + this._buttonOpenFolder.Text = "Open Folder"; + // + // _buttonSave + // + this._buttonSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonSave.Image = ((System.Drawing.Image)(resources.GetObject("_buttonSave.Image"))); + this._buttonSave.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonSave.Name = "_buttonSave"; + this._buttonSave.Size = new System.Drawing.Size(23, 22); + this._buttonSave.Text = "Save All Modified Tags"; + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25); + // + // _buttonCut + // + this._buttonCut.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonCut.Image = ((System.Drawing.Image)(resources.GetObject("_buttonCut.Image"))); + this._buttonCut.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonCut.Name = "_buttonCut"; + this._buttonCut.Size = new System.Drawing.Size(23, 22); + this._buttonCut.Text = "Cut"; + // + // _buttonCopy + // + this._buttonCopy.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonCopy.Image = ((System.Drawing.Image)(resources.GetObject("_buttonCopy.Image"))); + this._buttonCopy.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonCopy.Name = "_buttonCopy"; + this._buttonCopy.Size = new System.Drawing.Size(23, 22); + this._buttonCopy.Text = "Copy"; + // + // _buttonPaste + // + this._buttonPaste.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonPaste.Image = ((System.Drawing.Image)(resources.GetObject("_buttonPaste.Image"))); + this._buttonPaste.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonPaste.Name = "_buttonPaste"; + this._buttonPaste.Size = new System.Drawing.Size(23, 22); + this._buttonPaste.Text = "Paste"; + // + // toolStripSeparator6 + // + this.toolStripSeparator6.Name = "toolStripSeparator6"; + this.toolStripSeparator6.Size = new System.Drawing.Size(6, 25); + // + // _buttonRename + // + this._buttonRename.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonRename.Image = ((System.Drawing.Image)(resources.GetObject("_buttonRename.Image"))); + this._buttonRename.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonRename.Name = "_buttonRename"; + this._buttonRename.Size = new System.Drawing.Size(23, 22); + this._buttonRename.Text = "Rename Tag"; + // + // _buttonEdit + // + this._buttonEdit.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonEdit.Image = ((System.Drawing.Image)(resources.GetObject("_buttonEdit.Image"))); + this._buttonEdit.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonEdit.Name = "_buttonEdit"; + this._buttonEdit.Size = new System.Drawing.Size(23, 22); + this._buttonEdit.Text = "Edit Tag Value"; + // + // _buttonDelete + // + this._buttonDelete.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonDelete.Image = ((System.Drawing.Image)(resources.GetObject("_buttonDelete.Image"))); + this._buttonDelete.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonDelete.Name = "_buttonDelete"; + this._buttonDelete.Size = new System.Drawing.Size(23, 22); + this._buttonDelete.Text = "Delete Tag"; + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25); + // + // _buttonAddTagByte + // + this._buttonAddTagByte.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagByte.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagByte.Image"))); + this._buttonAddTagByte.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagByte.Name = "_buttonAddTagByte"; + this._buttonAddTagByte.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagByte.Text = "Add Byte Tag"; + // + // _buttonAddTagShort + // + this._buttonAddTagShort.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagShort.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagShort.Image"))); + this._buttonAddTagShort.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagShort.Name = "_buttonAddTagShort"; + this._buttonAddTagShort.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagShort.Text = "Add Short Tag"; + // + // _buttonAddTagInt + // + this._buttonAddTagInt.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagInt.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagInt.Image"))); + this._buttonAddTagInt.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagInt.Name = "_buttonAddTagInt"; + this._buttonAddTagInt.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagInt.Text = "Add Int Tag"; + // + // _buttonAddTagLong + // + this._buttonAddTagLong.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagLong.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagLong.Image"))); + this._buttonAddTagLong.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagLong.Name = "_buttonAddTagLong"; + this._buttonAddTagLong.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagLong.Text = "Add Long Tag"; + // + // _buttonAddTagFloat + // + this._buttonAddTagFloat.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagFloat.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagFloat.Image"))); + this._buttonAddTagFloat.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagFloat.Name = "_buttonAddTagFloat"; + this._buttonAddTagFloat.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagFloat.Text = "Add Float Tag"; + // + // _buttonAddTagDouble + // + this._buttonAddTagDouble.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagDouble.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagDouble.Image"))); + this._buttonAddTagDouble.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagDouble.Name = "_buttonAddTagDouble"; + this._buttonAddTagDouble.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagDouble.Text = "Add Double Tag"; + // + // _buttonAddTagByteArray + // + this._buttonAddTagByteArray.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagByteArray.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagByteArray.Image"))); + this._buttonAddTagByteArray.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagByteArray.Name = "_buttonAddTagByteArray"; + this._buttonAddTagByteArray.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagByteArray.Text = "Add Byte Array Tag"; + // + // _buttonAddTagIntArray + // + this._buttonAddTagIntArray.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagIntArray.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagIntArray.Image"))); + this._buttonAddTagIntArray.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this._buttonAddTagIntArray.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagIntArray.Name = "_buttonAddTagIntArray"; + this._buttonAddTagIntArray.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagIntArray.Text = "Add Int Array Tag"; + // + // _buttonAddTagString + // + this._buttonAddTagString.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagString.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagString.Image"))); + this._buttonAddTagString.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagString.Name = "_buttonAddTagString"; + this._buttonAddTagString.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagString.Text = "Add String Tag"; + // + // _buttonAddTagList + // + this._buttonAddTagList.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagList.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagList.Image"))); + this._buttonAddTagList.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagList.Name = "_buttonAddTagList"; + this._buttonAddTagList.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagList.Text = "Add List Tag"; + // + // _buttonAddTagCompound + // + this._buttonAddTagCompound.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonAddTagCompound.Image = ((System.Drawing.Image)(resources.GetObject("_buttonAddTagCompound.Image"))); + this._buttonAddTagCompound.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonAddTagCompound.Name = "_buttonAddTagCompound"; + this._buttonAddTagCompound.Size = new System.Drawing.Size(23, 22); + this._buttonAddTagCompound.Text = "Add Compound Tag"; + // + // toolStripSeparator5 + // + this.toolStripSeparator5.Name = "toolStripSeparator5"; + this.toolStripSeparator5.Size = new System.Drawing.Size(6, 25); + // + // _buttonFindNext + // + this._buttonFindNext.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this._buttonFindNext.Image = ((System.Drawing.Image)(resources.GetObject("_buttonFindNext.Image"))); + this._buttonFindNext.ImageTransparentColor = System.Drawing.Color.Magenta; + this._buttonFindNext.Name = "_buttonFindNext"; + this._buttonFindNext.Size = new System.Drawing.Size(23, 22); + this._buttonFindNext.Text = "Find / Find Next"; + // + // BottomToolStripPanel + // + this.BottomToolStripPanel.Location = new System.Drawing.Point(0, 0); + this.BottomToolStripPanel.Name = "BottomToolStripPanel"; + this.BottomToolStripPanel.Orientation = System.Windows.Forms.Orientation.Horizontal; + this.BottomToolStripPanel.RowMargin = new System.Windows.Forms.Padding(3, 0, 0, 0); + this.BottomToolStripPanel.Size = new System.Drawing.Size(0, 0); + // + // TopToolStripPanel + // + this.TopToolStripPanel.Location = new System.Drawing.Point(0, 0); + this.TopToolStripPanel.Name = "TopToolStripPanel"; + this.TopToolStripPanel.Orientation = System.Windows.Forms.Orientation.Horizontal; + this.TopToolStripPanel.RowMargin = new System.Windows.Forms.Padding(3, 0, 0, 0); + this.TopToolStripPanel.Size = new System.Drawing.Size(0, 0); + // + // RightToolStripPanel + // + this.RightToolStripPanel.Location = new System.Drawing.Point(0, 0); + this.RightToolStripPanel.Name = "RightToolStripPanel"; + this.RightToolStripPanel.Orientation = System.Windows.Forms.Orientation.Horizontal; + this.RightToolStripPanel.RowMargin = new System.Windows.Forms.Padding(3, 0, 0, 0); + this.RightToolStripPanel.Size = new System.Drawing.Size(0, 0); + // + // LeftToolStripPanel + // + this.LeftToolStripPanel.Location = new System.Drawing.Point(0, 0); + this.LeftToolStripPanel.Name = "LeftToolStripPanel"; + this.LeftToolStripPanel.Orientation = System.Windows.Forms.Orientation.Horizontal; + this.LeftToolStripPanel.RowMargin = new System.Windows.Forms.Padding(3, 0, 0, 0); + this.LeftToolStripPanel.Size = new System.Drawing.Size(0, 0); + // + // ContentPanel + // + this.ContentPanel.Size = new System.Drawing.Size(562, 376); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.testToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(97, 26); + // + // testToolStripMenuItem + // + this.testToolStripMenuItem.Name = "testToolStripMenuItem"; + this.testToolStripMenuItem.Size = new System.Drawing.Size(96, 22); + this.testToolStripMenuItem.Text = "Test"; + // + // _menuItemRecentFiles + // + this._menuItemRecentFiles.Name = "_menuItemRecentFiles"; + this._menuItemRecentFiles.Size = new System.Drawing.Size(223, 22); + this._menuItemRecentFiles.Text = "Recent Files"; + // + // _menuItemRecentFolders + // + this._menuItemRecentFolders.Name = "_menuItemRecentFolders"; + this._menuItemRecentFolders.Size = new System.Drawing.Size(223, 22); + this._menuItemRecentFolders.Text = "Recent Folders"; + // + // toolStripSeparator8 + // + this.toolStripSeparator8.Name = "toolStripSeparator8"; + this.toolStripSeparator8.Size = new System.Drawing.Size(220, 6); + // + // MainForm + // + this.AllowDrop = true; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(619, 423); + this.Controls.Add(this.toolStrip1); + this.Controls.Add(this._nodeTree); + this.Controls.Add(this.menuStrip1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.menuStrip1; + this.Name = "MainForm"; + this.Text = "NBTExplorer"; + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.contextMenuStrip1.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem searchToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.TreeView _nodeTree; + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripButton _buttonOpen; + private System.Windows.Forms.ToolStripButton _buttonSave; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripButton _buttonRename; + private System.Windows.Forms.ToolStripButton _buttonEdit; + private System.Windows.Forms.ToolStripButton _buttonDelete; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripButton _buttonAddTagByte; + private System.Windows.Forms.ToolStripButton _buttonAddTagShort; + private System.Windows.Forms.ToolStripButton _buttonAddTagInt; + private System.Windows.Forms.ToolStripButton _buttonAddTagLong; + private System.Windows.Forms.ToolStripButton _buttonAddTagFloat; + private System.Windows.Forms.ToolStripButton _buttonAddTagDouble; + private System.Windows.Forms.ToolStripButton _buttonAddTagByteArray; + private System.Windows.Forms.ToolStripButton _buttonAddTagList; + private System.Windows.Forms.ToolStripButton _buttonAddTagCompound; + private System.Windows.Forms.ImageList imageList1; + private System.Windows.Forms.ToolStripButton _buttonAddTagString; + private System.Windows.Forms.ToolStripMenuItem _menuItemAbout; + private System.Windows.Forms.ToolStripMenuItem _menuItemOpen; + private System.Windows.Forms.ToolStripMenuItem _menuItemOpenFolder; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.ToolStripMenuItem _menuItemSave; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripMenuItem _menuItemExit; + private System.Windows.Forms.ToolStripMenuItem _menuItemFind; + private System.Windows.Forms.ToolStripMenuItem _menuItemFindNext; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; + private System.Windows.Forms.ToolStripButton _buttonFindNext; + private System.Windows.Forms.ToolStripButton _buttonOpenFolder; + private System.Windows.Forms.ToolStripMenuItem _menuItemOpenMinecraftSaveFolder; + private System.Windows.Forms.ToolStripPanel BottomToolStripPanel; + private System.Windows.Forms.ToolStripPanel TopToolStripPanel; + private System.Windows.Forms.ToolStripPanel RightToolStripPanel; + private System.Windows.Forms.ToolStripPanel LeftToolStripPanel; + private System.Windows.Forms.ToolStripContentPanel ContentPanel; + private System.Windows.Forms.ToolStripButton _buttonAddTagIntArray; + private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem _menuItemCut; + private System.Windows.Forms.ToolStripMenuItem _menuItemCopy; + private System.Windows.Forms.ToolStripMenuItem _menuItemPaste; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; + private System.Windows.Forms.ToolStripMenuItem _menuItemRename; + private System.Windows.Forms.ToolStripMenuItem _menuItemEditValue; + private System.Windows.Forms.ToolStripMenuItem _menuItemDelete; + private System.Windows.Forms.ToolStripButton _buttonCut; + private System.Windows.Forms.ToolStripButton _buttonCopy; + private System.Windows.Forms.ToolStripButton _buttonPaste; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem testToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem _menuItemRecentFiles; + private System.Windows.Forms.ToolStripMenuItem _menuItemRecentFolders; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator8; + } +} + diff --git a/NBTExplorerMac/MainForm.cs b/NBTExplorerMac/MainForm.cs new file mode 100644 index 0000000..bfa726a --- /dev/null +++ b/NBTExplorerMac/MainForm.cs @@ -0,0 +1,983 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Threading; +using System.Windows.Forms; +using NBTExplorer.Forms; +using NBTExplorer.Model; +using Substrate.Nbt; +using NBTExplorer.Properties; +using System.Collections.Specialized; + +namespace NBTExplorer +{ + public partial class MainForm : Form + { + private static Dictionary _tagIconIndex; + + private IconRegistry _iconRegistry; + + private string _openFolderPath = null; + + static MainForm () + { + try { + _tagIconIndex = new Dictionary(); + _tagIconIndex[TagType.TAG_BYTE] = 0; + _tagIconIndex[TagType.TAG_SHORT] = 1; + _tagIconIndex[TagType.TAG_INT] = 2; + _tagIconIndex[TagType.TAG_LONG] = 3; + _tagIconIndex[TagType.TAG_FLOAT] = 4; + _tagIconIndex[TagType.TAG_DOUBLE] = 5; + _tagIconIndex[TagType.TAG_BYTE_ARRAY] = 6; + _tagIconIndex[TagType.TAG_STRING] = 7; + _tagIconIndex[TagType.TAG_LIST] = 8; + _tagIconIndex[TagType.TAG_COMPOUND] = 9; + _tagIconIndex[TagType.TAG_INT_ARRAY] = 14; + } + catch (Exception e) { + Program.StaticInitFailure(e); + } + } + + public MainForm () + { + InitializeComponent(); + InitializeIconRegistry(); + + FormClosing += MainForm_Closing; + + _nodeTree.BeforeExpand += _nodeTree_BeforeExpand; + _nodeTree.AfterCollapse += _nodeTree_AfterCollapse; + _nodeTree.AfterSelect += _nodeTree_AfterSelect; + _nodeTree.NodeMouseDoubleClick += _nodeTree_NodeMouseDoubleClick; + _nodeTree.NodeMouseClick += _nodeTree_NodeMouseClick; + _nodeTree.DragEnter += _nodeTree_DragEnter; + _nodeTree.DragDrop += _nodeTree_DragDrop; + + _buttonOpen.Click += _buttonOpen_Click; + _buttonOpenFolder.Click += _buttonOpenFolder_Click; + _buttonSave.Click += _buttonSave_Click; + _buttonEdit.Click += _buttonEdit_Click; + _buttonRename.Click += _buttonRename_Click; + _buttonDelete.Click += _buttonDelete_Click; + _buttonCopy.Click += _buttonCopy_Click; + _buttonCut.Click += _buttonCut_Click; + _buttonPaste.Click += _buttonPaste_Click; + _buttonAddTagByte.Click += _buttonAddTagByte_Click; + _buttonAddTagByteArray.Click += _buttonAddTagByteArray_Click; + _buttonAddTagCompound.Click += _buttonAddTagCompound_Click; + _buttonAddTagDouble.Click += _buttonAddTagDouble_Click; + _buttonAddTagFloat.Click += _buttonAddTagFloat_Click; + _buttonAddTagInt.Click += _buttonAddTagInt_Click; + _buttonAddTagIntArray.Click += _buttonAddTagIntArray_Click; + _buttonAddTagList.Click += _buttonAddTagList_Click; + _buttonAddTagLong.Click += _buttonAddTagLong_Click; + _buttonAddTagShort.Click += _buttonAddTagShort_Click; + _buttonAddTagString.Click += _buttonAddTagString_Click; + _buttonFindNext.Click += _buttonFindNext_Click; + + _menuItemOpen.Click += _menuItemOpen_Click; + _menuItemOpenFolder.Click += _menuItemOpenFolder_Click; + _menuItemOpenMinecraftSaveFolder.Click += _menuItemOpenMinecraftSaveFolder_Click; + _menuItemSave.Click += _menuItemSave_Click; + _menuItemExit.Click += _menuItemExit_Click; + _menuItemEditValue.Click += _menuItemEditValue_Click; + _menuItemRename.Click += _menuItemRename_Click; + _menuItemDelete.Click += _menuItemDelete_Click; + _menuItemCopy.Click += _menuItemCopy_Click; + _menuItemCut.Click += _menuItemCut_Click; + _menuItemPaste.Click += _menuItemPaste_Click; + _menuItemFind.Click += _menuItemFind_Click; + _menuItemFindNext.Click += _menuItemFindNext_Click; + _menuItemAbout.Click += _menuItemAbout_Click; + + string[] args = Environment.GetCommandLineArgs(); + if (args.Length > 1) { + string[] paths = new string[args.Length - 1]; + Array.Copy(args, 1, paths, 0, paths.Length); + OpenPaths(paths); + } + else { + OpenMinecraftDirectory(); + } + + UpdateOpenMenu(); + } + + private void InitializeIconRegistry () + { + _iconRegistry = new IconRegistry(); + _iconRegistry.DefaultIcon = 15; + + _iconRegistry.Register(typeof(TagByteDataNode), 0); + _iconRegistry.Register(typeof(TagShortDataNode), 1); + _iconRegistry.Register(typeof(TagIntDataNode), 2); + _iconRegistry.Register(typeof(TagLongDataNode), 3); + _iconRegistry.Register(typeof(TagFloatDataNode), 4); + _iconRegistry.Register(typeof(TagDoubleDataNode), 5); + _iconRegistry.Register(typeof(TagByteArrayDataNode), 6); + _iconRegistry.Register(typeof(TagStringDataNode), 7); + _iconRegistry.Register(typeof(TagListDataNode), 8); + _iconRegistry.Register(typeof(TagCompoundDataNode), 9); + _iconRegistry.Register(typeof(RegionChunkDataNode), 9); + _iconRegistry.Register(typeof(DirectoryDataNode), 10); + _iconRegistry.Register(typeof(RegionFileDataNode), 11); + _iconRegistry.Register(typeof(CubicRegionDataNode), 11); + _iconRegistry.Register(typeof(NbtFileDataNode), 12); + _iconRegistry.Register(typeof(TagIntArrayDataNode), 14); + } + + private void OpenFile () + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.RestoreDirectory = true; + ofd.Multiselect = true; + + if (ofd.ShowDialog() == DialogResult.OK) { + OpenPaths(ofd.FileNames); + } + + UpdateUI(); + } + + private void OpenFolder () + { + FolderBrowserDialog ofd = new FolderBrowserDialog(); + if (_openFolderPath != null) + ofd.SelectedPath = _openFolderPath; + + if (ofd.ShowDialog() == DialogResult.OK) { + _openFolderPath = ofd.SelectedPath; + OpenPaths(new string[] { ofd.SelectedPath }); + } + + UpdateUI(); + } + + private void OpenPaths (string[] paths) + { + _nodeTree.Nodes.Clear(); + + foreach (string path in paths) { + if (Directory.Exists(path)) { + DirectoryDataNode node = new DirectoryDataNode(path); + _nodeTree.Nodes.Add(CreateUnexpandedNode(node)); + + AddPathToHistory(Settings.Default.RecentDirectories, path); + } + else if (File.Exists(path)) { + DataNode node = null; + foreach (var item in FileTypeRegistry.RegisteredTypes) { + if (item.Value.NamePatternTest(path)) + node = item.Value.NodeCreate(path); + } + + if (node != null) { + _nodeTree.Nodes.Add(CreateUnexpandedNode(node)); + AddPathToHistory(Settings.Default.RecentFiles, path); + } + } + } + + if (_nodeTree.Nodes.Count > 0) { + _nodeTree.Nodes[0].Expand(); + } + + UpdateUI(); + UpdateOpenMenu(); + } + + private void OpenMinecraftDirectory () + { + try { + string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + path = Path.Combine(path, ".minecraft"); + path = Path.Combine(path, "saves"); + + if (!Directory.Exists(path)) { + path = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); + } + + OpenPaths(new string[] { path }); + } + catch (Exception e) { + MessageBox.Show("Could not open default Minecraft save directory"); + Console.WriteLine(e.Message); + + try { + OpenPaths(new string[] { Directory.GetCurrentDirectory() }); + } + catch (Exception) { + MessageBox.Show("Could not open current directory, this tool is probably not compatible with your platform."); + Console.WriteLine(e.Message); + Application.Exit(); + } + } + + UpdateUI(); + } + + private TreeNode CreateUnexpandedNode (DataNode node) + { + TreeNode frontNode = new TreeNode(node.NodeDisplay); + frontNode.ImageIndex = _iconRegistry.Lookup(node.GetType()); + frontNode.SelectedImageIndex = frontNode.ImageIndex; + frontNode.Tag = node; + frontNode.ContextMenuStrip = BuildNodeContextMenu(node); + + if (node.HasUnexpandedChildren || node.Nodes.Count > 0) + frontNode.Nodes.Add(new TreeNode()); + + return frontNode; + } + + private ContextMenuStrip BuildNodeContextMenu (DataNode node) + { + if (node == null) + return null; + + ContextMenuStrip menu = new ContextMenuStrip(); + + if (node.CanReoderNode) { + ToolStripMenuItem itemUp = new ToolStripMenuItem("Move &Up", Properties.Resources.ArrowUp, _contextMoveUp_Click); + ToolStripMenuItem itemDn = new ToolStripMenuItem("Move &Down", Properties.Resources.ArrowDown, _contextMoveDown_Click); + + itemUp.Enabled = node.CanMoveNodeUp; + itemDn.Enabled = node.CanMoveNodeDown; + + menu.Items.Add(itemUp); + menu.Items.Add(itemDn); + } + + return (menu.Items.Count > 0) ? menu : null; + } + + private void _contextMoveUp_Click (object sender, EventArgs e) + { + TreeNode frontNode = _nodeTree.SelectedNode; + if (frontNode == null) + return; + + DataNode node = frontNode.Tag as DataNode; + if (node == null || !node.CanMoveNodeUp) + return; + + node.ChangeRelativePosition(-1); + RefreshChildNodes(frontNode.Parent, node.Parent); + } + + private void _contextMoveDown_Click (object sender, EventArgs e) + { + TreeNode frontNode = _nodeTree.SelectedNode; + if (frontNode == null) + return; + + DataNode node = frontNode.Tag as DataNode; + if (node == null || !node.CanMoveNodeDown) + return; + + node.ChangeRelativePosition(1); + RefreshChildNodes(frontNode.Parent, node.Parent); + } + + private void ExpandNode (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + if (node.IsExpanded) + return; + + node.Nodes.Clear(); + + DataNode backNode = node.Tag as DataNode; + if (!backNode.IsExpanded) + backNode.Expand(); + + foreach (DataNode child in backNode.Nodes) + node.Nodes.Add(CreateUnexpandedNode(child)); + } + + private void CollapseNode (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode backNode = node.Tag as DataNode; + if (backNode.IsModified) + return; + + backNode.Collapse(); + + node.Nodes.Clear(); + if (backNode.HasUnexpandedChildren) + node.Nodes.Add(new TreeNode()); + } + + private void CreateNode (TreeNode node, TagType type) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode dataNode = node.Tag as DataNode; + if (!dataNode.CanCreateTag(type)) + return; + + if (dataNode.CreateNode(type)) { + node.Text = dataNode.NodeDisplay; + RefreshChildNodes(node, dataNode); + UpdateUI(dataNode); + } + } + + private void RefreshChildNodes (TreeNode node, DataNode dataNode) + { + Dictionary currentNodes = new Dictionary(); + foreach (TreeNode child in node.Nodes) { + if (child.Tag is DataNode) + currentNodes.Add(child.Tag as DataNode, child); + } + + node.Nodes.Clear(); + foreach (DataNode child in dataNode.Nodes) { + if (!currentNodes.ContainsKey(child)) + node.Nodes.Add(CreateUnexpandedNode(child)); + else + node.Nodes.Add(currentNodes[child]); + } + + foreach (TreeNode child in node.Nodes) + child.ContextMenuStrip = BuildNodeContextMenu(child.Tag as DataNode); + + if (node.Nodes.Count == 0 && dataNode.HasUnexpandedChildren) { + ExpandNode(node); + node.Expand(); + } + } + + private void EditNode (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode dataNode = node.Tag as DataNode; + if (!dataNode.CanEditNode) + return; + + if (dataNode.EditNode()) { + node.Text = dataNode.NodeDisplay; + UpdateUI(dataNode); + } + } + + private void RenameNode (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode dataNode = node.Tag as DataNode; + if (!dataNode.CanRenameNode) + return; + + if (dataNode.RenameNode()) { + node.Text = dataNode.NodeDisplay; + UpdateUI(dataNode); + } + } + + private void DeleteNode (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode dataNode = node.Tag as DataNode; + if (!dataNode.CanDeleteNode) + return; + + if (dataNode.DeleteNode()) { + UpdateUI(node.Parent.Tag as DataNode); + UpdateNodeText(node.Parent); + node.Remove(); + } + } + + private void CopyNode (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode dataNode = node.Tag as DataNode; + if (!dataNode.CanCopyNode) + return; + + dataNode.CopyNode(); + } + + private void CutNode (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode dataNode = node.Tag as DataNode; + if (!dataNode.CanCutNode) + return; + + if (dataNode.CutNode()) { + UpdateUI(node.Parent.Tag as DataNode); + UpdateNodeText(node.Parent); + node.Remove(); + } + } + + private void PasteNode (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode dataNode = node.Tag as DataNode; + if (!dataNode.CanPasteIntoNode) + return; + + if (dataNode.PasteNode()) { + node.Text = dataNode.NodeDisplay; + RefreshChildNodes(node, dataNode); + UpdateUI(dataNode); + } + } + + private void Save () + { + foreach (TreeNode node in _nodeTree.Nodes) { + DataNode dataNode = node.Tag as DataNode; + if (dataNode != null) + dataNode.Save(); + } + + UpdateUI(); + } + + private bool ConfirmExit () + { + if (CheckModifications()) { + if (MessageBox.Show("You currently have unsaved changes. Close anyway?", "Unsaved Changes", MessageBoxButtons.OKCancel) != DialogResult.OK) + return false; + } + + return true; + } + + private CancelSearchForm _searchForm; + private SearchState _searchState; + + private void SearchNode (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode dataNode = node.Tag as DataNode; + if (!dataNode.CanSearchNode) + return; + + Find form = new Find(); + if (form.ShowDialog() != DialogResult.OK) + return; + + _searchState = new SearchState() { + RootNode = dataNode, + SearchName = form.NameToken, + SearchValue = form.ValueToken, + DiscoverCallback = SearchDiscoveryCallback, + CollapseCallback = SearchCollapseCallback, + EndCallback = SearchEndCallback, + }; + + SearchNextNode(); + } + + private void SearchNextNode () + { + if (_searchState == null) + return; + + SearchWorker worker = new SearchWorker(_searchState, this); + + Thread t = new Thread(new ThreadStart(worker.Run)); + t.IsBackground = true; + t.Start(); + + _searchForm = new CancelSearchForm(); + if (_searchForm.ShowDialog(this) == DialogResult.Cancel) { + worker.Cancel(); + _searchState = null; + } + + t.Join(); + } + + private void SearchDiscoveryCallback (DataNode node) + { + _nodeTree.SelectedNode = FindFrontNode(node); + + if (_searchForm != null) { + _searchForm.DialogResult = DialogResult.OK; + _searchForm = null; + } + } + + private void SearchCollapseCallback (DataNode node) + { + CollapseBelow(node); + } + + private void SearchEndCallback (DataNode node) + { + _searchForm.DialogResult = DialogResult.OK; + _searchForm = null; + + MessageBox.Show("End of results"); + } + + private TreeNode GetRootFromDataNodePath (DataNode node, out Stack hierarchy) + { + hierarchy = new Stack(); + while (node != null) { + hierarchy.Push(node); + node = node.Parent; + } + + DataNode rootDataNode = hierarchy.Pop(); + TreeNode frontNode = null; + foreach (TreeNode child in _nodeTree.Nodes) { + if (child.Tag == rootDataNode) + frontNode = child; + } + + return frontNode; + } + + private TreeNode FindFrontNode (DataNode node) + { + Stack hierarchy; + TreeNode frontNode = GetRootFromDataNodePath(node, out hierarchy); + + if (frontNode == null) + return null; + + while (hierarchy.Count > 0) { + if (!frontNode.IsExpanded) { + frontNode.Nodes.Add(new TreeNode()); + frontNode.Expand(); + } + + DataNode childData = hierarchy.Pop(); + foreach (TreeNode childFront in frontNode.Nodes) { + if (childFront.Tag == childData) { + frontNode = childFront; + break; + } + } + } + + return frontNode; + } + + private void CollapseBelow (DataNode node) + { + Stack hierarchy; + TreeNode frontNode = GetRootFromDataNodePath(node, out hierarchy); + + if (frontNode == null) + return; + + while (hierarchy.Count > 0) { + if (!frontNode.IsExpanded) + return; + + DataNode childData = hierarchy.Pop(); + foreach (TreeNode childFront in frontNode.Nodes) { + if (childFront.Tag == childData) { + frontNode = childFront; + break; + } + } + } + + if (frontNode.IsExpanded) + frontNode.Collapse(); + } + + private void UpdateNodeText (TreeNode node) + { + if (node == null || !(node.Tag is DataNode)) + return; + + DataNode dataNode = node.Tag as DataNode; + node.Text = dataNode.NodeDisplay; + } + + private bool CheckModifications () + { + foreach (TreeNode node in _nodeTree.Nodes) { + DataNode dataNode = node.Tag as DataNode; + if (dataNode != null && dataNode.IsModified) + return true; + } + + return false; + } + + private void UpdateUI () + { + TreeNode selected = _nodeTree.SelectedNode; + if (selected != null && selected.Tag is DataNode) { + UpdateUI(selected.Tag as DataNode); + } + else { + _buttonSave.Enabled = CheckModifications(); + _buttonFindNext.Enabled = false; + + _menuItemSave.Enabled = _buttonSave.Enabled; + _menuItemFind.Enabled = false; + _menuItemFindNext.Enabled = _searchState != null; + } + } + + private void UpdateUI (DataNode node) + { + if (node == null) + return; + + _buttonAddTagByte.Enabled = node.CanCreateTag(TagType.TAG_BYTE); + _buttonAddTagByteArray.Enabled = node.CanCreateTag(TagType.TAG_BYTE_ARRAY); + _buttonAddTagCompound.Enabled = node.CanCreateTag(TagType.TAG_COMPOUND); + _buttonAddTagDouble.Enabled = node.CanCreateTag(TagType.TAG_DOUBLE); + _buttonAddTagFloat.Enabled = node.CanCreateTag(TagType.TAG_FLOAT); + _buttonAddTagInt.Enabled = node.CanCreateTag(TagType.TAG_INT); + _buttonAddTagIntArray.Enabled = node.CanCreateTag(TagType.TAG_INT_ARRAY); + _buttonAddTagList.Enabled = node.CanCreateTag(TagType.TAG_LIST); + _buttonAddTagLong.Enabled = node.CanCreateTag(TagType.TAG_LONG); + _buttonAddTagShort.Enabled = node.CanCreateTag(TagType.TAG_SHORT); + _buttonAddTagString.Enabled = node.CanCreateTag(TagType.TAG_STRING); + + _buttonSave.Enabled = CheckModifications(); + _buttonCopy.Enabled = node.CanCopyNode; + _buttonCut.Enabled = node.CanCutNode; + _buttonDelete.Enabled = node.CanDeleteNode; + _buttonEdit.Enabled = node.CanEditNode; + _buttonFindNext.Enabled = node.CanSearchNode || _searchState != null; + _buttonPaste.Enabled = node.CanPasteIntoNode; + _buttonRename.Enabled = node.CanRenameNode; + + _menuItemSave.Enabled = _buttonSave.Enabled; + _menuItemCopy.Enabled = node.CanCopyNode; + _menuItemCut.Enabled = node.CanCutNode; + _menuItemDelete.Enabled = node.CanDeleteNode; + _menuItemEditValue.Enabled = node.CanEditNode; + _menuItemFind.Enabled = node.CanSearchNode; + _menuItemPaste.Enabled = node.CanPasteIntoNode; + _menuItemRename.Enabled = node.CanRenameNode; + _menuItemFind.Enabled = node.CanSearchNode; + _menuItemFindNext.Enabled = _searchState != null; + } + + private void UpdateOpenMenu () + { + try { + if (Settings.Default.RecentDirectories == null) + Settings.Default.RecentDirectories = new StringCollection(); + if (Settings.Default.RecentFiles == null) + Settings.Default.RecentFiles = new StringCollection(); + } + catch { + return; + } + + _menuItemRecentFolders.DropDown = BuildRecentEntriesDropDown(Settings.Default.RecentDirectories); + _menuItemRecentFiles.DropDown = BuildRecentEntriesDropDown(Settings.Default.RecentFiles); + } + + private ToolStripDropDown BuildRecentEntriesDropDown (StringCollection list) + { + if (list == null || list.Count == 0) + return new ToolStripDropDown(); + + ToolStripDropDown menu = new ToolStripDropDown(); + foreach (string entry in list) { + ToolStripMenuItem item = new ToolStripMenuItem("&" + (menu.Items.Count + 1) + " " + entry); + item.Tag = entry; + item.Click += _menuItemRecentPaths_Click; + + menu.Items.Add(item); + } + + return menu; + } + + private void AddPathToHistory (StringCollection list, string entry) + { + foreach (string item in list) { + if (item == entry) { + list.Remove(item); + break; + } + } + + while (list.Count >= 5) + list.RemoveAt(list.Count - 1); + + list.Insert(0, entry); + } + + #region Event Handlers + + private void MainForm_Closing (object sender, CancelEventArgs e) + { + Settings.Default.RecentFiles = Settings.Default.RecentFiles; + Settings.Default.Save(); + if (!ConfirmExit()) + e.Cancel = true; + } + + #region TreeView Event Handlers + + private void _nodeTree_BeforeExpand (object sender, TreeViewCancelEventArgs e) + { + ExpandNode(e.Node); + } + + private void _nodeTree_AfterCollapse (object sender, TreeViewEventArgs e) + { + CollapseNode(e.Node); + } + + private void _nodeTree_AfterSelect (object sender, TreeViewEventArgs e) + { + if (e.Node != null) + UpdateUI(e.Node.Tag as DataNode); + } + + private void _nodeTree_NodeMouseDoubleClick (object sender, TreeNodeMouseClickEventArgs e) + { + EditNode(e.Node); + } + + private void _nodeTree_NodeMouseClick (object sender, TreeNodeMouseClickEventArgs e) + { + if (e.Button == MouseButtons.Right) + _nodeTree.SelectedNode = e.Node; + } + + private void _nodeTree_DragDrop (object sender, DragEventArgs e) + { + OpenPaths((string[])e.Data.GetData(DataFormats.FileDrop)); + } + + private void _nodeTree_DragEnter (object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + e.Effect = DragDropEffects.Copy; + } + + #endregion + + #region Toolstrip Event Handlers + + private void _buttonOpen_Click (object sender, EventArgs e) + { + OpenFile(); + } + + private void _buttonOpenFolder_Click (object sender, EventArgs e) + { + OpenFolder(); + } + + private void _buttonSave_Click (object sender, EventArgs e) + { + Save(); + } + + private void _buttonEdit_Click (object sender, EventArgs e) + { + EditNode(_nodeTree.SelectedNode); + } + + private void _buttonRename_Click (object sender, EventArgs e) + { + RenameNode(_nodeTree.SelectedNode); + } + + private void _buttonDelete_Click (object sender, EventArgs e) + { + DeleteNode(_nodeTree.SelectedNode); + } + + private void _buttonCopy_Click (object sernder, EventArgs e) + { + CopyNode(_nodeTree.SelectedNode); + } + + private void _buttonCut_Click (object sernder, EventArgs e) + { + CutNode(_nodeTree.SelectedNode); + } + + private void _buttonPaste_Click (object sernder, EventArgs e) + { + PasteNode(_nodeTree.SelectedNode); + } + + private void _buttonAddTagByteArray_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_BYTE_ARRAY); + } + + private void _buttonAddTagByte_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_BYTE); + } + + private void _buttonAddTagCompound_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_COMPOUND); + } + + private void _buttonAddTagDouble_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_DOUBLE); + } + + private void _buttonAddTagFloat_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_FLOAT); + } + + private void _buttonAddTagInt_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_INT); + } + + private void _buttonAddTagIntArray_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_INT_ARRAY); + } + + private void _buttonAddTagList_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_LIST); + } + + private void _buttonAddTagLong_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_LONG); + } + + private void _buttonAddTagShort_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_SHORT); + } + + private void _buttonAddTagString_Click (object sender, EventArgs e) + { + CreateNode(_nodeTree.SelectedNode, TagType.TAG_STRING); + } + + private void _buttonFindNext_Click (object sender, EventArgs e) + { + if (_searchState != null) + SearchNextNode(); + else + SearchNode(_nodeTree.SelectedNode); + } + + #endregion + + #region Menu Event Handlers + + private void _menuItemOpen_Click (object sender, EventArgs e) + { + OpenFile(); + } + + private void _menuItemOpenFolder_Click (object sender, EventArgs e) + { + OpenFolder(); + } + + private void _menuItemOpenMinecraftSaveFolder_Click (object sender, EventArgs e) + { + OpenMinecraftDirectory(); + } + + private void _menuItemSave_Click (object sender, EventArgs e) + { + Save(); + } + + private void _menuItemExit_Click (object sender, EventArgs e) + { + Settings.Default.Save(); + Close(); + } + + private void _menuItemEditValue_Click (object sender, EventArgs e) + { + EditNode(_nodeTree.SelectedNode); + } + + private void _menuItemRename_Click (object sender, EventArgs e) + { + RenameNode(_nodeTree.SelectedNode); + } + + private void _menuItemDelete_Click (object sender, EventArgs e) + { + DeleteNode(_nodeTree.SelectedNode); + } + + private void _menuItemCopy_Click (object sender, EventArgs e) + { + CopyNode(_nodeTree.SelectedNode); + } + + private void _menuItemCut_Click (object sender, EventArgs e) + { + CutNode(_nodeTree.SelectedNode); + } + + private void _menuItemPaste_Click (object sender, EventArgs e) + { + PasteNode(_nodeTree.SelectedNode); + } + + private void _menuItemFind_Click (object sender, EventArgs e) + { + SearchNode(_nodeTree.SelectedNode); + } + + private void _menuItemFindNext_Click (object sender, EventArgs e) + { + SearchNextNode(); + } + + private void _menuItemAbout_Click (object sender, EventArgs e) + { + new About().ShowDialog(); + } + + private void _menuItemRecentPaths_Click (object sender, EventArgs e) + { + ToolStripMenuItem item = sender as ToolStripMenuItem; + if (item == null || !(item.Tag is string)) + return; + + OpenPaths(new string[] { item.Tag as string }); + } + + #endregion + + #endregion + } +} diff --git a/NBTExplorerMac/MainForm.resources b/NBTExplorerMac/MainForm.resources new file mode 100644 index 0000000000000000000000000000000000000000..9c8c28e83b5e0d08c5d269ba68c996d6ea5455c4 GIT binary patch literal 60582 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 Z18e|mK`4(uvjFl5su;q42>m0e{{vSrUMv6r literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/MainForm.resx b/NBTExplorerMac/MainForm.resx new file mode 100644 index 0000000..f77388b --- /dev/null +++ b/NBTExplorerMac/MainForm.resx @@ -0,0 +1,1146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAACkklEQVQ4T43SX0hTURzA8d9b + 9O/BHjPowfZkRgTRgxVFJgrBRKT2kJWjEsUsKyprtZyumdoSZ86hGdU0LUOTsJXGahCYthIUs6au/fPf + nJvzOvfXX+ccusINgg584Hfhni/ncC8MqACoL+WQQ5T8pxx+H/STzX+UcpZynPl4CmeNJ5Ebuo0xRyPi + 5BOh2RYk75fy+6BPCTwlLrzEFe8LDNpr0dNXiG+1h/DdG7VAT68GO8vi69Ql+6FKvg/gU9kqVWy+DaMz + eibmfY7mjnPo9HhwiuPQQdj8fnxlMqFSnmrIlMlEGcXFACbFqoqouwUjk48ZOn9uleKwxYLfRkdx3O3G + kakpbO7uRrrI5jxCBEY58O5Fpp9iyPGQobPpkQS/j42xyKTPxyIavX6VKD1dBj03gVcdcjVhwFrP0NnY + eBR/TEywyBy5Ah+hJ6HXSSsqKgDDDeDVLtsakLPUMnTu1WWixWplEe/SkiDiWFzElIKCQnh9DXjawIQW + /aPVDJ0NdWIct9lYZGF5WRCZDgTwQG7uBei8ArwG7mcN+oYrGTp31xxBKwnQCBcMCiLz5HmvVHoRFMcA + 2i8xTf4RNXoGVQydu+6noc1uZ5FAOCyI+Mnznuzsy0DXrSyAZ+dB7xuqQLdZwdC5ozIV7Q4HiwQjEUGE + I4FdEgk5P8BaYpPuLHR5B8mv3C9nvOQU7XdT0Ol0skgkGhVElkhwu1hMviFAHLEtPxXq31fv9o8b8sJz + Awqc/6rE1jsH0eVyoZOIraxglAjHYhgisRCZ45OTy9kV6Dq8A0B3BjK0p0HXdn3LB3Nz5q+rWWvs60Qi + zYbExIqNSUmqv61PSMgXBMhm0EgB1CdgZ9VxkJVJ4AF5YSux+R/ifgP/44T3ShVnvwAAAABJRU5ErkJg + gg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADrwAAA68AZW8ckkAAAI/SURBVDhPjdJPSJNxGAfw5xYd6+hZJIhCkm5d8hBeIq/9 + AftDgRcPHQzEqVPn5sRcNptjuVjZYlkUFZZpusQIFf+h2Zwuc0NJl5vatub+fXufB1e8DKTBhz1s3+f7 + vr+Xl2jvM2GgK+MG0v4Pzmb3/n6PNVFDZMmAdfdlbAyVITJbh3TgPrD2UG3DCc7mFHxuJB22nyMT7kHc + 34HN0QosuEqQWepUwaoDnM0pGGkkfTrkQmq9W6TDTzHjKMb2jAlJ7z2kFy0iE3gAzuYUDGvJmAo6kVxz + CJ6nuk7BP6IXKaWEpf12cDanYKiGWpM/HmE30CV4/mQ+iZVhnUh4zCK1bANncwr6NWTaXbUjttwpeHab + TmDZ3SDi8+0i4bOCs30aKlKVvKsi8+8VGyKLZsHzQGshfINaEZsziV1+FpkMOK8qeFNJltg3C3Y8JsHz + 2+ZjWPpQJ6KzbSK+0IFQNArOqwpeVpIt4m3H1lyL4Pm17ii8A7Xi10yriH29C18wCM6rCp7dJPvO/G1s + TusFzy/qj8DzXiO2p1pE9MsdnB7NgPOqAmcFdW/NGhGcqBc899QUwNNXLbYmjSKiHON4bwSczxYcVIbD + 1uv0KjytvMpjtSKs3IVLU4BF5fZZ9ghR5UFy9loxnVX2eJcOKfLLz1Bnv6lox9dbnvg5Xo/QpA7NFyh8 + 6xyNsJZLNJjFWd7Z2/13EusNKrVcJeuTqjz3+OPS780X6aPyb15JPh3IeXH2+6GtjAqVq1U3nad2Jbfv + 8h/ayQIkRwIF8QAAAABJRU5ErkJggg== + + + + + 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 + gsnRJ2HiAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAACc0lEQVQ4T43SW0hUURQG4PWS + 0JsIFUQ9lWMTFo63RqXRLKoRDMbMcbyMWtqY5qBOjsEEFmlRJAaTlJRdTLtn+ZBBL4EE9rBDu0AlIURZ + D4VQjo3j7W+v0+xT+tSBj7M5Z6+ftdc5dC6diLVn/HXIaozIzc3NkVxhOfzs3z2qTisOB3TIDYKdMNFw + 12H3l5GRD2C85mfqvbx36AF+GRAm3rfvRV9NKgYHX2Fo6B1GRz9reM3P+N1bfynkfqHq6OxmUsTrtiJc + L4nFRftaXCtej5v74nC7Ih7dpRtwuSAGPWUb8bK1ALJGqDpqTSVFDJ9x4NnRbDz2ZGguNNjQ1ujQnW8q + Q2eLC83bl72pLbSQ25FGdNqsEy9O5eGpb6fO7yvGr7k5/JyexvepKYwFAugbGECtPeWjzeeLzvZ6iU4m + 6cTzZhueeLfqWr35mJyZwfjkJL5NTODT+Dh6+vvBlyyukgx0PIEUwe0/qrNoeGDHqrIRnJ3Fj2BQD/F3 + d0OJtlqPUFMcKYLbv38gWRvkpfxoNJRkIiSPEAiFFoRwJ2Oyq23V1W7yxZIi+uvTcaVwHTodBo3HmYkZ + GRCUM1gcwjOxVFTUUaORFPGg2oyrRUZdXfEWzM3PIySPsTiEB2t2Oj1UbyBF9MqALtm+4i7MwLwc2Kzs + YnFIQAbE2+1e2r2SyL1GI3qrNmk/i1KZl6ZNnEO4Ez4Oz4QHOyXvMVlZPuJr1woi1+o/AbfKTboaWzzy + raYFHFkmJBlXfY00mVqiEhPLuX6ptHxPJImHB1O0r3CvMgl3XYm6O/sTwPi3ZryXa8K1FCUXsclL6MaO + CBL/g/dyjRT1G7y5F+bDPK+HAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAt0lEQVQ4T6VSSwoCMQxNTzBL + wYX3cu9F5j7iQhAFQXAxC8/gATxGzQuNhEdHM1h4NOn7tBlGaq3yD6SUAoyKfauxZ2p4xAMOzex9ZjdP + RvhV4+QxvAD1VhHPeiHGO3GiEbjvBZhm7nmX7DfxgCsZuO9dZBonbhTAfS/ANHMj3JeOMJGB+95FpnHi + EQJQ7xTxTLDoEuN//kjmDItHc+rJwkT/8WxUfFa8mgl7poYHXhkUK8V6IeAZ3llKVtf+E8JOAAAAAElF + TkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAADaWlUWHRYTUw6Y29tLmFkb2Jl + LnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQi + Pz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENv + cmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJE + RiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8 + cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBSaWdodHM9Imh0dHA6Ly9ucy5hZG9i + ZS5jb20veGFwLzEuMC9yaWdodHMvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAv + MS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNv + dXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wUmlnaHRz + Ok1hcmtlZD0iRmFsc2UiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzA0RUI0NjQwMzg3MTFFMUFE + RTJDQkMzMDBBQjU2MjYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzA0RUI0NjMwMzg3MTFFMUFE + RTJDQkMzMDBBQjU2MjYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTMyBXaW5kb3dz + Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InV1aWQ6QUMxRjJFODMzMjRBREYx + MUFBQjhDNTM5MEQ4NUI1QjMiIHN0UmVmOmRvY3VtZW50SUQ9InV1aWQ6QzlEMzQ5NjY0QTNDREQxMUIw + OEFCQkJDRkYxNzIxNTYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ + IDw/eHBhY2tldCBlbmQ9InIiPz4xPsWJAAACIElEQVQ4T4WSXUhTYRiA3/dbG7omFjZGFyFBJBkW9nMR + SD/o2kUF5+aElZo0LyYG9oOh5aIakxlpKAxrQ1jUZEWRRT/EvBiKFLEslW6CmeWwCyFJangRvL3fwcmx + OnrguTgcnuf7zve9ACs8JUUIbU0IqqpqpBG3TiL2jiHue4FobGfFp2EEyUKgcMBu76VAgIYRXz1DLP+n + 8LeoC2xSFKU+k8nQvMdDc1VVFAN4shgwErVACPcHffa7Uk4mk5RKpchnsTyPAOyA4kIAbw1o2/wvLD8K + 4kv6HqD4g52a7HA4fKW5uVtUsxkg2grQ5zUI6OTfMz6aeHeUblzM6bfZbNutVitIjAM6ef7bZZp8f5we + Bk2J/pCpPCsbB3Tyz6lmmhqrpnsdYvB+t6h4fNukrWy8A508O3GW0uO1FPaLoTvXhTPWJWD5gE6e+VSv + yd2tYvjWNeGMtAvQB8zyAOWzeIg6efqjm+WT1H4eX99sQWfPVQHZQOURsXR2ZIApinVgn7yqr6PV9OXD + CbrSgG/azuDBzmYEGVCcBmMbbgJLzzk4/SOdmE3GK+jzSCW1uPGt14MufyOCq2yZeZd76WzAPfHoqcTc + 9CClRiK/Go/h0IVacO3dtYKY/ZFLNeiXcrRLHa07jKEDpajwNztTwKxl8pk8hqcGchgLs4oxMdoqVHcI + Q2Xb0J1nxd38XsIUM5uZjcwGZj2zjlnDrF4IyWsQfwCLISjKZ5nx7AAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABfUlEQVQ4T6WTu0vDUBTGz1+g + VBtB1KBgdSsUNFvHQoZChw4upWoRupYO7a6giw66KCj4wgciuAiKg5M4XcFBUHAVBxdXcfD4fTGJqaZT + hx+353yPezNUVFU6oaMwL/YKDkXkCJyIuMDw5LzvE6cx87eAIaPNpvIEbqTA0z5qtVBrKfCN5qvR0Id8 + Xj/rdcXOAJYQ81apeNpLqRRovy/YxXOAuwPje7Wq146jr+WyciaPhYK3u8vlvB29zISfwAGCbEHYhOG5 + WNSLdFpvs1m9ymR027L02LaVGj30xhbAIBswrMN4nkrpXiLhcZBMKnfU6PlXsIjlElgBqzCtwXyGW08R + DuCOGj30MhN+QlCw/GMwlwjGQY2edgUUzA3CAZzb7NyWF8zjOcDcIxzAeQG3kTiNmfATbAxTMNYRekIJ + T87D2JM4jZmwAL8HwdiEyNw0wpMis5hHwRAYACOOyAw1ejCPMxMt6MKiF/T79OHsAd2AWgJYET3JfVjQ + yd/5G8s+qAWdGU8YAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAACDElEQVQ4T42SzWoaURTHRxER + QUVBCqVv4aZxIX7MBNMQJn7G6ERNFRTRGT8riCAluMob5BmSTQjNRkogkEWg4LJQUgiE0NCH+PecYabc + BhcVftzjPef8Zu49IzkcDkngM8XnBK/iPscbc6+LLqbTKXw+3yoQCEihUMiEY97jHIkuRLkoOAmHw99k + WQavxBkhWXD8N0eCE1siCi6XyyVGoxEMY8SStQjnptNP0PU+v8XlJsHVYrHA0ZGGXK6CSCSCfr9vwjHn + Go0GstkiC642Ca7n8znK5UNEo1GzSURRFNTrdahqjgXXrwWnwWDwO5/fblJVFZ1Ox4Rj3pfllLlyLQlO + WWLfwWo2m9HZdeTzeWxtRUE3/0OkUCig1+uh2WwSbX6LlSi4GY/HqFY1eoqM3d0Cj/Kn3+9/z3A8mUzo + Dj5iZyeNdHqfBTei4HYwGKBSOUQikaCCLLxe7yMhWTwOh0O6gxq2txUoyh4LbkXBna7rKJWKiMViVKDC + 4/E8EZLFk2EY5oRSqSSSyQ8suBMF991uF8fHdfMODg40uN3uZ0KyeOY8j7FYLBJlFtyLgnU8Hjft9hRc + LtcLIVm88NF4lHaemtemwPo9tFotaJpGI9unD6kEp9P52541x+12G7ValT6kDDKZAqjvwW5+R8EX4pcI + NX+l/xHGiv/JWz3cK/mJEPGGePufcC33+P8AbaoESlToQpYAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAACZElEQVQ4T4WSXWhSYRjHj8Ns + GDrmJutjd0LrJroQYjoQzWO4BiluTt3OlkvXlqhH50xaizWWrNhdEWNdBEFBFxvBGI3AaiR1EQV2EQxG + weiDotsuol38e56D2mEMEn68f9/nfX6e87wKGo1GUDFLeZngVb3Pec/a7kMrhUIBBoOh1NTUJJhMJgXO + vMc1Eq2o5WrBnNlsfieKIngl7hJCFc71GgnmahK1YLVYLCKXy0GWcyypqOFaoXAJ6XSGn2J1L8HazMwM + hoYk9PYOwmq1IpPJKHDmWiwWQyDQz4K1vQTr09PTGBiIwG63K01qPB4PotEofL5eFqzvFiw0Nzdv8vvX + mnw+HxKJhAJn3hdFt7LyWRIssKQ2g9LU1BS9exp9fX2w2eygyW+pCQaDSKVSiMfjxDg/RUkt2JicnMTw + sES/IqKnJ8hX+cloNHYynPP5PM3gPLq7vfB6/SzYUAvK2WwWg4MRuFwuOhCAXq/fJoQq2xMTEzSDc3Bf + eQT36DwLymrB63Q6jXC4Hw6HAx6PD42NjV8I4Yg3JXCWZVm5Ifv1DeIl2roiWwfFRH0Gb5LJJEZGosoM + QiEJOp3u2yFPQjherCx1yMt/umafwXathJNXn2LxK9CRffyLalJtiBWn0wm3+1T9FrRa7Y9WR1ywXC6/ + vfUZSHwAht7/I7cJcE2ofj6OjY1BkiS6Mj/9kcJoaGj4ub/9hNDiv7nU0n9759jFhzg6/gCW0fvofAW0 + hu78pprE/e3EE+K7GhrQc/puZapZqR84c2OH0VmcL6q9gpGCiWgjDv8P3dnFe/tOz1+o9hj/AtmlLdLj + WupUAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAC5klEQVQ4T12OX0iTURjGD4kM + 8y4JCYqQbJZkLhWElStG08lybm5q/k/TajCM/ANOlmmBaEQEqeGFDBd4ITNNIRC0LaXc0vmp6edQYzrN + C0WvvH/63tOM6MDv4/ne9/kdDsvNzWUGg4Hl5eUxk8nEzGbz6fz8fJUEnfthKKtoRx3qkkMu/4QvkEnL + jPr6+iav17u0t7eH3d1dDuWZmZmlurq6JupIF8j+v0BmNBpzHA5HPwnvR1bR+GoBOqufQ9k5LGJnZxt9 + fX391JUukPEX6PV64qa0cAaDQZTbZnG3eR21bw7R0HOE+u4jWF8foKBpje82NtbR29vrJIdcptPpYq1W + q31zM4jiRi8qX4Tw6OU+ch6v4PhQftCxh9KWP51AIACLxWInl2m1WrXb/Xm52+lDXsMKKtpCMNQFoHno + /3sBZZoV24O4U7uIrv4ZjI2NLpPLNBpNKT2rxu5BeWsQWRaBo67+Drn2Ay5oXEjIHkF85hBHdW+ad+fm + ZkEuU6vVVkEQcL1kAiVPf+JWlQ8K0yQuZo9KpTn4/X7Eaz9K/2OclPxJ3p2enga5TKVS1VIxvXAcOU9W + kGhwI0E/CblunMuiKPJMM+Kq+QvvejwekMuUSmWlICygrGEcqmoBiWYf55JhisuhUIjn4/kV81fe9Xim + QC5LT0/PGhx0rXa+8+BagRupFQEkFUsvMc9y+eDggGeaEZdzJ9DR7YbD4Vwll6WlpZ0xGk3t8/PLuF0x + huRCH1Iqt5BU9IPLh4eHPCsqtpBo8vKOz7cAg8HYTi5TKBQsOTlZ29Ly3LW4uI4bhS6cz/yExCIRiqpf + HMo0o50grMFub3ORQy6LjY1lcXFxUXK5vNRmax0WxR109nyDvnoIp1K7OJRpJorbsNmeDVOXHHLpnJA4 + KZPJzsbExJQplRlvBwZGN9bW9vEvNKMddaTuOXLCLouQQoyEXCIlMjJSHRUVVRMdHd0s0RGmmWa0o45E + QtiJ+A2+oxJO8d3MEAAAAABJRU5ErkJggg== + + + + 237, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADQ + MwAAAk1TRnQBSQFMAgEBEAEAARgBAQEYAQEBEAEAARABAAT/ARkBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABUAMAAQEBAAEYBgABPP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AB4AA/wD+SH4A/kD/AMAA/0D+SH4 + A/kD/TkAA/8D/AP5EvgD+QP7A/4GAAGWAakBvAFcAYQBrgFcAYQBrgFcAYQBrgFcAYQBrgFcAYQBrgFc + AYQBrgFcAYQBrgFcAYQBrgFcAYQBrgFcAYQBrgFcAYQBrgFcAYQBrgFcAYQBrgGWAakBvAMAAs8BywK5 + AbACuQGwArkBsAK5AbACuQGwArkBsAK5AbACuQGwArkBsAK5AbACuQGwArkBsAK5AbACzwHLOQAD/gP4 + AegC5QHZAbQBqwHqAY4BdwHuAXABUAHuAXABUAHqAY4BdwHZAbQBqwHoAeUB5AP2A/4GAAFsAZMBugFV + AYgBuwFwAaMB1gFnAZoBzQFnAZoBzQFnAZoBzQFnAZoBzQFnAZoBzQFnAZoBzQFnAZoBzQFnAZoBzQFn + AZoBzQFwAaMB1gFVAYgBuwFsAZMBugMAAsEBuQL5AekC8wHiAvMB4gLzAeIC8wHiAvMB4gLzAeIC8wHi + AvMB4gLzAeIC8wHiAvMB4gL5AekCwQG5PAAB6gHcAdgB7gGCAWcB9QGiAY8B+gHRAcoB/AHnAeUB/AHm + AeUB+QHRAckB9AGhAY4B7gGBAWYB6gHcAdgJAAF+AaIBxwFxAaQB1wFVAYgBuwFxAaQB1wFxAaQB1wFx + AaQB1wFxAaQB1wFxAaQB1wFxAaQB1wFxAaQB1wFxAaQB1wFxAaQB1wFVAYgBuwFxAaQB1wF+AaIBxwMA + AssBwwL0AeQBegGnAZsBhwG3AacBhwG1AaMBiQGzAaIBaAGgAYYBVwGXAXgBWAGTAXkBaAGQAX4BkgGk + AZMBhgGXAYACqAGOAvQB5ALLAcMJAAP+A/wG+QP6BvwD+wb5A/wD/gwAAfMB3wHaAe4BewFgAfcB1AHO + AfcC6QH3AugB/AL0AfwC9AH3AugB9wLpAfYB0QHKAe4BewFfAfMB3wHaBgABhgGqAc0BcwGmAdkBagGd + AdABSAF7Aa4BXwGSAcUBTAF/AbIBXwGSAcUBTAF/AbIBXwGSAcUBTAF/AbIBXwGSAcUBSAF7Aa4BagGd + AdABcwGmAdkBhgGqAc0DAALPAccC9QHmAYQBtQGrAZgB1wHHAZAB0QG+AXMBsAGZAZcBywG2AacBzgG9 + AZcBvQGsAZQBugGoAakBvwGvAY4BrQGhAbcBrQGLAvUB5gLPAccJAAP+A/wD+QOzA1wG/ANcA7QD+QP8 + A/4JAAH6AfgB9wHnAX4BYgHzAdMBzQHwAuUB7wLkAe8C5AHlAWEBPwHlAWEBPwHvAuQB7wLkAe8C5AHv + Ac0BxwHnAX4BYgH6AfgB9wMAAYsBrQHPAXUBqAHbAWwBnwHSAUoBfQGwAWwBnwHSAVIBhQG4AWwBnwHS + AVIBhQG4AWwBnwHSAVIBhQG4AWwBnwHSAUoBfQGwAWwBnwHSAXUBqAHbAYsBrQHPAwAC0QHJAvYB6QGQ + AbwBtQG5AeUB2wGmAd0B0AGIAcABsgGHAckBtQF+Ab4BpAGIAbkBowGuAdABvwGpAccBtQGUAboBqAG2 + AbUBkQL2AekC0QHJDwADywN1A/gGAAP4A3UDyw8AAegBxQG8AeUBnQGKAeoC4gHnAt8B5wLfAecC3wHW + AVkBNwHWAVkBNwHnAt8B5wLfAecC3wHoAuAB4QGXAYQB6AHFAbwDAAGPAbEB0gF3AaoB3QFuAaEB1AFH + AXoBrQFuAaEB1AFPAYIBtQFuAaEB1AFPAYIBtQFuAaEB1AFPAYIBtQFuAaEB1AFHAXoBrQFuAaEB1AF3 + AaoB3QGPAbEB0gMAAtMBzAL3AesBxQG4AYcB/wHeAYwB+AHnAa0B1QHRAbABygHrAeIBvQHlAdkBoAHK + AbsBqgHOAa8BggHBAaQBfgG2ApgBrAGEAvcB6wLTAcwMAAPOA38D+QHdAbMBuQHAAUkBWgHAAUkBWgHd + AbMBuQP5A38DzgwAAdIBhAFuAeoB0AHIAeEC2gHgAtkB4ALZAeAC2QHxAu0B8QLtAeAC2QHgAtkB4ALZ + AeAC2QHhAcQBvQHSAYQBbgMAAZMBtAHUAXgBqwHeAW8BogHVAUQBdwGqAW8BogHVAUwBfwGyAW8BogHV + AUwBfwGyAW8BogHVAUwBfwGyAW8BogHVAUQBdwGqAW8BogHVAXgBqwHeAZMBtAHUAwAC1QHNAvgB7gHR + Aa4BaQHbAboBcQHeAb4BdAHpAckBfAG/Ac0BqAGVAcwBwgGhAc8BvgGRAcQBrwF/Ab0BpgF3AbcBnQGo + AaoBdwL4Ae4C1QHNCQAD0AOGA/kGAAHgAbYBvAHRAXsBhwYAA/kDhgPQCQABuwFUATUB9AHuAe0B5wLl + AdoC1gHYAtQB2ALUAbcBSAEmAbcBSAEmAeMC3wHYAtQB2ALUAdgC1AHhAdgB1gG7AVQBNQMAAZgBuAHX + AXoBrQHgAXEBpAHXAUEBdAGnAXEBpAHXAUkBfAGvAXEBpAHXAUkBfAGvAXEBpAHXAUkBfAGvAXEBpAHX + AUEBdAGnAXEBpAHXAXoBrQHgAZgBuAHXAwAC1wHPAvkB8QHTAawBZgH/AdMBfgH/AdYBggHgAb4BdAH2 + AeEBmQGwAe0B5AGvAdEBvwGiAeAB0wGYAdgBxgGOAdABugG4AbIBgAL5AfEC1wHPBgAD7wNsA+8JAAHj + AbgBvwHXAYEBjQkAA+8DbAPvBgABsQFQATEB9AHvAe0D7gPqAdwC2wHTAtEBxwGmAZwBrgFHASUBwQFz + AVoB3gLcAdIC0AHSAtAB3wHYAdcBsQFQATEDAAGbAboB2QF8Aa8B4gFzAaYB2QE/AXIBpQFzAaYB2QFH + AXoBrQFzAaYB2QFHAXoBrQFzAaYB2QFHAXoBrQFzAaYB2QE/AXIBpQFzAaYB2QF8Aa8B4gGbAboB2QMA + AtkB0QL7AfQB1QGpAWIB/wHOAXkB/wHSAX0B3wG6AW8B/wHYAYMB5gHqAb0BpgHYAc0BswHsAeIBuQHk + AdABtgHcAcQBqwG+AZcC+wH0AtkB0QkAA9QDkQP5BgAB5gG7AcEB3QGHAZMGAAP5A5ED1AkAAcABfQFm + AeoB1QHNCfAD6wPgAcgBnAGNAasBRgEkAb0BigF5A84B0gLRAdwBxwLAAX0BZgMAAZ0BvQHbAX4BsQHk + AXUBqAHbATgBawGeAVEBhAG3ATgBawGeAVEBhAG3ATgBawGeAVEBhAG3ATgBawGeAVEBhAG3ATgBawGe + AXUBqAHbAX4BsQHkAZ0BvQHbAwAC2gHTAvwB9wHXAacBXwHaAawBZAHcAbABZwHnAbwBcAHgAboBbwHj + Ab4BcwHfAdEBmAHbAc8BlgHVAdEBnAHEAc0BpAGdAdEBwwL8AfcC2gHTDAAD1QOWA/kB6AG9AcMB3QFm + AXcB3QFmAXcB6AG9AcMD+QOWA9UMAAHfAcMBuQHUAZ0BigP1BvMB2gGpAZgB2gGpAZgBzwGOAXgBswFP + AS0B0wGhAZAD8wP1AdQBnAGJAd8BwwG5AwABoAG+AdwBfwGyAeUBZgGZAcwBdgGpAdwBdgGpAdwBdgGp + AdwBdgGpAdwBdgGpAdwBdgGpAdwBdgGpAdwBdgGpAdwBdgGpAdwBZgGZAcwBfwGyAeUBoAG+AdwDAALb + AdQC/QH5AdkBpAFcAf8BxAFvAf8ByAFzAd4BsAFnAf8BzgF5Af8B0gF9AeQBvgFyAf8B2AGDAe0B5AGo + AeIB5gG2AdAB1wGtAv0B+QLbAdQPAAPXA5kD+gYAA/oDmQPXDwAB+QH4AfcBywF7AWAB8gHfAdkD+AP3 + AcEBXQE7AcEBXQE7AcEBXQE7AcEBXQE7AekB0AHIA/gB8gHfAdkBywF7AWAB+QH4AfcDAAGjAcAB3gFr + AZ4B0QF3AaoB3QF3AaoB3QF3AaoB3QF3AaoB3QF3AaoB3QF3AaoB3QF3AaoB3QF3AaoB3QF3AaoB3QF3 + AaoB3QF3AaoB3QFrAZ4B0QGjAcAB3gMAAt0B1QL+AfwB2gGjAVoB/wG/AWsB/wHCAW4B3gGsAWIB/wHJ + AXQB/wHNAXgB4wG5AW4B/wHTAX4B/wHXAYMB/AHeAZUB7AHKAXwC/gH8At0B1RIAA9gDnQYAA50D2BUA + Ae4B4AHbAdgBhAFoAfYB4wHcA/wM+wP8AfYB4wHcAdgBhAFoAe4B4AHbBgABpgHDAeABoAHTAfoBmAHL + AfUBkwHGAfMBkwHGAfMBkwHGAfMBkwHGAfMBkwHGAfMBkwHGAfMBkwHGAfMBkwHGAfMBkwHGAfMBmAHL + AfUBoAHTAfoBpgHDAeADAALeAdcC/wH+AdsBoQFYAdsBogFZAdsBpAFbAdsBpQFdAdsBqQFgAdsBrAFj + AdsBrwFmAdsBsQFoAdsBtAFrAdsBtwFuAdsBuQFxAv8B/gLeAdc8AAHwAeIB3QHkAZQBeAHvAbcBpAH6 + AeQB3QH+AfkB9wH+AfkB9wH6AeQB3QHvAbcBpAHkAZQBeAHwAeIB3QkAAegB7QHzAagBxAHhAZcBygH1 + AZIBxQHzAZIBxQHzAZIBxQHzAZIBxQHzAZIBxQHzAZIBxQHzAZIBxQHzAZIBxQHzAZIBxQHzAZcBygH1 + AagBxAHhAegB7QHzAwAC3wHZJ/8C3wHZPwAB+gL4Ae8B0gHIAewBqAGSAewBjgFuAewBjgFuAewBqAGS + Ae8B0gHIAfoC+A8AAegB7QHzAakBxQHiAakBxQHiAakBxQHiAakBxQHiAakBxQHiAakBxQHiAakBxQHi + AakBxQHiAakBxQHiAakBxQHiAakBxQHiAegB7QHzBgAC6gHmAuAB2QLgAdkC4AHZAuAB2QLgAdkC4AHZ + AuAB2QLgAdkC4AHZAuAB2QLgAdkC4AHZAuAB2QLqAebDAAP7A/EBlQGvAbwBaAGbAbYBaAGbAbYBaAGb + AbYBaAGbAbYBaAGbAbYBaAGbAbYBaAGbAbYBaAGbAbYBaAGbAbYBaAGbAbYBlQGvAbwD8QP7FQAS+AP5 + A/0zAAP8A/kk+AP5A/wD/QP6AXcBqAHBAYYBzwHwAYEBywHtAYEBywHtAYEBywHtAYEBywHtAYEBywHt + AYEBywHtAYYBzwHwAUsBjwGxAYYBzwHwAXcBqAHBAdwB4gHlBv0D+Qz4A/MBiQGlAY8BVQGLAV8BVQGL + AV8BVQGLAV8BVQGLAV8BVQGLAV8BVQGLAV8BlAGtAZkGAAPAAywDwAMAA/sb+AP7A/cBkwGmAboBYAGI + Aa8BYAGIAa8BYAGIAa8BYAGIAa8BYAGIAa8BYAGIAa8BYAGIAa8BYAGIAa8BYAGIAa8BYAGIAa8BYAGI + Aa8BYAGIAa8BkwGmAboD9wYAAYYBtQHNAYQBzgHuAXwBxwHoAXwBxwHoAXwBxwHoAXwBxwHoAXwBxwHo + AXwBxwHoAYQBzgHuAVcBmwG9AYQBzgHuAfQBtgEuAYYBtQHNAwAClAG4AlUBowJVAaMCVQGjAlUBowJV + AaMCVQGjAVUBegGJATUBvQF5AUMBywGHAT4BxgGCAT4BxgGCAT4BxgGCAUMBywGHAVUBoAFwBgADQAFn + AlYDQAMAA/sDYQNeA1wDWQNUA0kDPAMvA2wD+wMAAXIBmAG/AXsBrgHgAXoBrQHfAXoBrQHfAXoBrQHf + AXoBrQHfAXoBrQHfAXoBrQHfAXoBrQHfAXoBrQHfAXoBrQHfAXoBrQHfAXsBrgHgAXIBmAG/CQABkQG+ + AdQBhwHQAe8BfwHKAekBfwHKAekBfwHKAekBfwHKAekBfwHKAekBfwHKAekBhwHQAe8BXwGjAcUBhwHQ + Ae8B/gHJAUEBkQG+AdQDAAJVAbQBLwEeAdwBJQETAdgBJQETAdgBJQETAdgBJQETAdgBJQETAdgBVQF+ + AZUBNwG/AXsBQgHKAYYBNwG/AXsBNwG/AXsBNwG/AXsBQgHKAYYBVQGnAXYGAAPLA1UDyycAAYQBpwHL + AYEBtAHkAX0BsAHhAX0BsAHhAX0BsAHhAX0BsAHhAX0BsAHhAX0BsAHhAX0BsAHhAX0BsAHhAX0BsAHh + AX0BsAHhAYEBtAHkAYQBpwHLCQABlAHAAdYBigHTAfABggHNAesBggHNAesBggHNAesBggHNAesBggHN + AesBggHNAesBigHTAfABYgGmAcgBigHTAfAC6QHbAZQBwAHWAwACVQG5AS0BHAHeARUBAAHVARUBAAHV + ARUBAAHVARUBAAHVARUBAAHVAVUBgQGaATsBwwF/AUgBzwGMATsBwwF/ATsBwwF/ATsBwwF/AUgBzwGM + AVUBrQF7NgABigGtAc8BiAG7AeoBggG1AeUBggG1AeUBggG1AeUBggG1AeUBggG1AeUBggG1AeUBggG1 + AeUBggG1AeUBggG1AeUBggG1AeUBiAG7AeoBigGtAc8JAAGYAcMB2AGOAdYB8gGHAdAB7QGHAdAB7QGH + AdAB7QGHAdAB7QGHAdAB7QGHAdAB7QGOAdYB8gFmAaoBzAGOAdYB8gLwAeYBmAHDAdgDAAJVAb8BNgEl + AeQBGQEAAdsBGQEAAdsBGQEAAdsBGQEAAdsBGQEAAdsBVQGEAaABPgHGAYIBTQHVAZEBPgHGAYIBPgHG + AYIBPgHGAYIBTQHVAZEBVQGzAYA2AAGOAbAB0QGPAcIB7gGHAboB6QGHAboB6QGHAboB6QGHAboB6QGH + AboB6QGHAboB6QGHAboB6QGHAboB6QGHAboB6QGHAboB6QGPAcIB7gGOAbAB0QkAAZsBxgHaAZIB2gH0 + AYsB1AHwAYsB1AHwAYsB1AHwAYsB1AHwAYsB1AHwAYsB1AHwAZIB2gH0AWkBrQHPAZIB2gH0AvgB8wGb + AcYB2gMAAlUBxAE+AS0B7AEcAQAB4wEcAQAB4wEcAQAB4wEcAQAB4wEcAQAB4wFVAYYBpAFCAcoBhgFR + AdkBlQFCAcoBhgFCAcoBhgFCAcoBhgFRAdkBlQFVAbkBhAYAA9ADZwPQJwABkwG0AdQBlgHJAfIBjAG/ + AewBjAG/AewBjAG/AewBRAF3AaoBjAG/AewBRAF3AaoBjAG/AewBjAG/AewBjAG/AewBjAG/AewBlgHJ + AfIBkwG0AdQJAAGfAcgB3QGXAd4B9gGQAdgB8gGQAdgB8gGQAdgB8gGQAdgB8gGQAdgB8gGQAdgB8gGX + Ad4B9gF5Ab0B3AF4Ab0B3AL+Af0BnwHIAd0DAAJVAcgBRgE1AfIBIAEAAekBIAEAAekBIAEAAekBIAEA + AekBIAEAAekBVQGJAagBRAHMAYgBZQHtAakBZQHtAakBZQHtAakBZQHtAakBWAHWAZYBfwHLAaQGAANs + AW8CaQNsBgADdQN0A3EDbgNsA2gDZQNjA2AGAAGYAbgB1wGbAc4B9gGRAcQB8AGRAcQB8AGRAcQB8AFV + AYgBuwFEAXcBqgFVAYgBuwFAAXMBpgGRAcQB8AGRAcQB8AGRAcQB8AGbAc4B9gGYAbgB1wkAAaIBygHe + AZsB4QH3AZQB2wH0AZQB2wH0AZQB2wH0AZQB2wH0AZQB2wH0AZQB2wH0AZQB2wH0AZ4B5AH5AXwBwAHe + AaIBygHeAe4B8wH1AwACfwHVAWIBYQHnAXYBdQH+AXYBdQH+AXkBYgGjAXsBUAFVAXsBUAFVAWoBWQE/ + AWoBbgEyAWoBbgEyAWEBiwFRAVUBwQGKAVUBwQGKAVUBwQGKAeIB7wHoBgAD0wNxA9MnAAGbAboB2QGf + AdIB+QGVAcgB8wGVAcgB8wGVAcgB8wFVAYgBuwFVAYgBuwFVAYgBuwFNAYABswGVAcgB8wGVAcgB8wGV + AcgB8wGfAdIB+QGbAboB2QkAAaUBzQHgAZ4B5QH5AZgB3wH2AZgB3wH2AZgB3wH2AZgB3wH2AZgB3wH2 + AZgB3wH2AZgB3wH2AZgB3wH2AaEB6AH6AaUBzQHgBgAC4gHxAlUBzgJVAc4CVQHOAW0BUwF1AdwBqQEy + AdcBpAEtAdcBpAEtAdcBpAEtAdwBqQEyAbABhgFIQgABnwG9AdsBqQHbAf4BqgHdAf8BqgHdAf8BqgHd + Af8BdwGqAd0BdwGqAd0BdwGqAd0BZgGZAcwBqgHdAf8BqgHdAf8BqgHdAf8BqQHbAf4BnwG9AdsJAAGo + Ac4B4gGjAegB+wGdAeMB+QGdAeMB+QGdAeMB+QGdAeMB+QGdAeMB+QGdAeMB+QGdAeMB+QGdAeMB+QGj + AegB+wGoAc4B4hIAAbYBiwFFAdwBqQEyAdEBngEnAdEBngEnAdEBngEnAdwBqQEyAbYBiwFFQgABxwHX + AecBiAG2AeIBgAGzAeYBgAGzAeYBgAGzAeYBTgGBAbQBTgGBAbQBTgGBAbQBSAF7Aa4BgAGzAeYBgAGz + AeYBgAGzAeYBiAG2AeIBxwHXAecJAAGrAdAB4wGmAesB/AGhAeYB+wGhAeYB+wGhAeYB+wGhAeYB+wGh + AeYB+wGhAeYB+wGhAeYB+wGhAeYB+wGmAesB/AGrAdAB4xIAAbsBkAFBAeEBrgE4AdYBowEsAdYBowEs + AdYBowEsAeEBrgE4AbsBkAFBEgAD1wN9A9cnAAHjAeoB8QGOAbgB4QGJAbwB7wGIAbsB7gGIAbsB7gFB + AXQBpwFBAXQBpwFBAXQBpwE+AXEBpAGIAbsB7gGIAbsB7gGJAbwB7wGOAbgB4QHjAeoB8QkAAa4B0gHk + AakB7gH9AaQB6QH8AaQB6QH8AaQB6QH8AaQB6QH8AaQB6QH8AaQB6QH8AaQB6QH8AaQB6QH8AakB7gH9 + Aa4B0gHkEgABwAGVAT8B5wG0AT0B2gGnATAB2gGnATAB2gGnATAB5wG0AT0BwAGVAT8SAAN/A3cDfwYA + A4IDgQN/A34DfAN6A3kDdgOrBgAB9QH3AfkBmwG+Ad8BiQG8Ae8BiAG7Ae4BiAG7Ae4BNQFoAZsBNQFo + AZsBNQFoAZsBNQFoAZsBiAG7Ae4BiAG7Ae4BiQG8Ae8BmwG+Ad8B9QH3AfkJAAGwAdQB5gGsAfEB/wGn + AewB/gGnAewB/gGnAewB/gGnAewB/gGnAewB/gGnAewB/gGnAewB/gGnAewB/gGsAfEB/wGwAdQB5hIA + AcYBmgE9AesBuAFBAd0BqgEzAd0BqgEzAd0BqgEzAesBuAFBAcYBmgE9EgAD2AOCA9gnAAP+AcsB2gHq + AakBxQHiAakBxQHiAakBxQHiAVUBfQGmAVUBfQGmAVUBfQGmAVUBfQGmAakBxQHiAakBxQHiAakBxQHi + AcsB2gHqA/4JAAGyAdUB5gGxAfUB/wGuAfIB/wGuAfIB/wGuAfIB/wGuAfIB/wGuAfIB/wGuAfIB/wGu + AfIB/wGuAfIB/wGxAfUB/wGyAdUB5hIAAdQBswFsAecBuAFGAf4BywFUAf4BywFUAf4BywFUAecBuAFG + AdQBswFsdQAB0AHkAe4BswHWAecBswHWAecBswHWAecBswHWAecBswHWAecBswHWAecBswHWAecBswHW + AecBswHWAecBswHWAecB0AHkAe4SAAHwAesB3gHNAaABOQHNAaABOQHNAaABOQHNAaABOQHNAaABOQHw + AesB3g8AA/sD8QLIAcMCuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwAsgBwwPx + BvsD8QLIAcMCuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwAsgBwwPxA/tgAAP9 + A/oCwAG4C/8D/gH9Av4B/AL9AfsC/QH6AvwB+AL+AfkCwAG4A/oG/QP6AsABuAv/A/4B/QL+AfwC/QH7 + Av0B+gL8AfgC/gH5AsABuAP6A/1mAALJAcEG/wP+Av0B/AL9AfsC/AH5AvsB+AL6AfYC+AH0AvsB9gLJ + AcEMAALJAcEG/wP+Av0B/AL9AfsC/AH5AvsB+AL6AfYC+AH0AvsB9gLJAcFsAALPAccD/wP+Av0B/AL9 + AfsC/AH5AvsB+AL6AfYC+AH0AvcB8gL7AfUCzwHHDAACzwHHA/8D/gL9AfwC/QH7AvwB+QL7AfgC+gH2 + AvgB9AL3AfIC+wH1As8BxwwAA/4D/Ab5A/oG/AP7BvkD/AP+BgAD/QP8A/oe+AP6A/wD/QYAAtAByAL/ + Af4C/QH8Av0B+wG/AUgBrgHsAc4B5QL6AfYC+AH0AvcB8gL2AfAC+gHzAtAByAwAAtAByAL/Af4C/QH8 + AekBzwHrAa4BSAG/Aa4BSAG/Aa4BSAG/AdMBoQHaAvcB8gL2AfAC+gHzAtAByAwAA/4D/AP5A7MDXAb8 + A1wDtAP5A/wD/gYAA/0DhAM0A4QD+APiBjQDhAPiA3UDpAP4A4QDNAPpBgAC0gHLAv4D/QH7AvwB+QHG + AU8BtQHsAc8B5QL4AfQC9wHyAvYB8AL1Ae4C+gHyAtIBywwAAtIBywL+A/0B+wHqAdEB7QG1AU8BxgL6 + AfYB5wHOAegBtQFPAcYB7gHhAesC9QHuAvoB8gLSAcsSAAPLA3UD+AYAA/gDdQPLEgADeQP1BgADqgN5 + BgADywO+A+4DqgPCCQAC1QHNAv4D/AH5AvsB+AHOAVcBvQHOAVcBvQHOAVcBvQHiAaYB1gL1Ae4C9AHs + AvkB7wLVAc0MAALVAc0C/gP8AfkB6wHSAe0BvQFXAc4C+AH0AvcB8gG9AVcBzgHnAc0B5QL0AewC+QHv + AtUBzQ8AA84DfwP5DAAD+QN/A84PAAPGDGADxgYAA/UJYAPpCQAC1gHOAv0D+wH4AvoB9gHWAV8BxQHv + AdEB5gL2AfAC9QHuAvQB7ALxAecC9wHqAtYBzgwAAtYBzgL9A/sB+AHsAdMB7gHFAV8B1gL3AfIB6gHR + AeoBxQFfAdYB7QHhAekC8QHnAvcB6gLWAc4MAAPQA4YD+RIAA/kDhgPQDAAD9QOUA+8D0QNoA/UJAAOT + A+8DaAwAAtgB0AL9A/oB9gL4AfQB3AFlAcsB3AFlAcsB3AFlAcsB4gGJAdMC8QHnAuwB3wL0AeUC2AHQ + DAAC2AHQAv0D+gH2Ae0B0wHuAcsBZQHcAcsBZQHcAcsBZQHcAd8BrAHjAvEB5wLsAd8C9AHlAtgB0AkA + A+8DbAPvGAAD7wNsA+8MAAOPA/YDtwOPDAADzAN9A8wMAALaAdIC/AP4AfQC9wHyAvYB8AL1Ae4C9AHs + AvEB5wLsAd8C6AHZAvMB4gLaAdIMAALaAdIC/AP4AfQC9wHyAvYB8AL1Ae4C9AHsAvEB5wLsAd8C6AHZ + AvMB4gLaAdIMAAPUA5ED+RIAA/kDkQPUDwADzgPVA3cDzgwAA+wDdwPsDAAC2wHTAvwD9wHyAvYB8AL1 + Ae4C9AHsAvEB5wLsAd8C6AHZAuYB1QLyAeEC2wHTDAAC2wHTAvwD9wHyAvYB8AL1Ae4C9AHsAvEB5wLs + Ad8C6AHZAuYB1QLyAeEC2wHTDwAD1QOWA/kMAAP5A5YD1RIAA/YDogN+A/YhAALcAdUC+wP2AfAC9QHu + AvQB7ALxAecC7AHfAugB2QLmAdUC5QHUAvIB4QLcAdUMAALcAdUC+wP2AfAC9QHuAvQB7ALxAecC7AHf + AugB2QLmAdUC5QHUAvIB4QLcAdUSAAPXA5kD+gYAA/oDmQPXGAAGnCQAAt0B1gL6AfQC9QHuAvQB7ALx + AecC7AHfAugB2QLmAdUCpAGTAqQBkwKkAZMCyQHADAAC3QHWAvoB9AL1Ae4C9AHsAvEB5wLsAd8C6AHZ + AuYB1QKkAZMCpAGTAqQBkwLJAcAVAAPYA50GAAOdA9hFAALeAdcC+gHzAvQB7ALxAecC7AHfAugB2QLm + AdUC5QHUArYBpQP/At4B1wL3AfYMAALeAdcC+gHzAvQB7ALxAecC7AHfAugB2QLmAdUC5QHUArYBpQP/ + At4B1wL3AfZsAALfAdkC/AH1AvkB7wL2AeoC9AHlAvMB4gLyAeEC8gHhAsIBsQLfAdkC9wH2DwAC3wHZ + AvwB9QL5Ae8C9gHqAvQB5QLzAeIC8gHhAvIB4QLCAbEC3wHZAvcB9m8AAuoB5gLgAdkC4AHZAuAB2QLg + AdkC4AHZAuAB2QLgAdkC4AHZAvcB9hIAAuoB5gLgAdkC4AHZAuAB2QLgAdkC4AHZAuAB2QLgAdkC4AHZ + AvcB9mwAA/sD8QLIAcMCuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwAsgBwwPx + BvsD8QLIAcMCuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwAsgBwwPxBvsD8QLI + AcMCuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwAsgBwwPxBvsD8QLIAcMCuAGw + ArgBsAK4AbACuAGwArgBsAK4AbACuAGwArgBsAK4AbACuAGwAsgBwwPxA/sD/QP6AsABuAv/A/4B/QL+ + AfwC/QH7Av0B+gL8AfgC/gH5AsABuAP6Bv0D+gLAAbgL/wP+Af0C/gH8Av0B+wL9AfoC/AH4Av4B+QLA + AbgD+gb9A/oCwAG4C/8D/gH9Av4B/AL9AfsC/QH6AvwB+AL+AfkCwAG4A/oG/QP6AsABuAv/A/4B/QL+ + AfwC/QH7Av0B+gL8AfgC/gH5AsABuAP6A/0GAALJAcEG/wP+Av0B/AL9AfsC/AH5AvsB+AL6AfYC+AH0 + AvsB9gLJAcEMAALJAcEG/wP+Av0B/AL9AfsC/AH5AvsB+AL6AfYC+AH0AvsB9gLJAcEMAALJAcEG/wP+ + Av0B/AL9AfsC/AH5AvsB+AL6AfYC+AH0AvsB9gLJAcEMAALJAcEG/wP+Av0B/AL9AfsC/AH5AvsB+AL6 + AfYC+AH0AvsB9gLJAcEMAALPAccD/wP+Av0B/AL9AfsC/AH5AvsB+AL6AfYC+AH0AvcB8gL7AfUCzwHH + DAACzwHHA/8D/gL9AfwC/QH7AvwB+QL7AfgC+gH2AvgB9AL3AfIC+wH1As8BxwwAAs8BxwP/A/4C/QH8 + Av0B+wL8AfkC+wH4AvoB9gL4AfQC9wHyAvsB9QLPAccMAALPAccD/wP+Av0B/AL9AfsC/AH5AvsB+AL6 + AfYC+AH0AvcB8gL7AfUCzwHHDAAC0AHIAv8B/gL9AfwB3AHPAesBewFIAb8BewFIAb8BewFIAb8BiwFe + AcYB6AHhAesC9gHwAvoB8wLQAcgMAALQAcgC/wH+Av0B/AL9AfsBggHCAbQBWQGuAZ0BWQGuAZ0BqQHT + AcgC9wHyAvYB8AL6AfMC0AHIDAAC0AHIAv8B/gL9AfwC/QH7Ad4BogGpAb8BSAFZAb8BSAFZAdwBoAGm + AvcB8gL2AfAC+gHzAtAByAwAAtAByAL/Af4C/QH8Av0B+wG/AXsBSAG/AXsBSAG/AXsBSAHcAboBngL3 + AfIC9gHwAvoB8wLQAcgMAALSAcsC/gP9AfsB3QHRAe0BggFPAcYC+gH2AvgB9AGCAU8BxgHZAcwB5QL1 + Ae4C+gHyAtIBywwAAtIBywL+A/0B+wL8AfkC+wH4AvoB9gHSAegB4AFgAbUBpAL2AfAC9QHuAvoB8gLS + AcsMAALSAcsC/gP9AfsC/AH5AvsB+AHgAaUBqwHTAXoBhQL3AfIC9gHwAvUB7gL6AfIC0gHLDAAC0gHL + Av4D/QH7AvwB+QHGAYIBTwHsAdsBzAL4AfQC9wHyAvYB8AL1Ae4C+gHyAtIBywwAAtUBzQL+A/wB+QHf + AdIB7QGKAVcBzgGYAWwB0wGKAVcBzgGlAX8B1wHnAeEB6QL0AewC+QHvAtUBzQwAAtUBzQL+A/wB+QL7 + AfgBsgHcAdIBaAG9AawBaAG9AawBrgHZAc0C9QHuAvQB7AL5Ae8C1QHNDAAC1QHNAv4D/AH5AvsB+AL6 + AfYB4wGoAa4B2QF/AYsC9gHwAvUB7gL0AewC+QHvAtUBzQwAAtUBzQL+A/wB+QL7AfgBzgGKAVcB7gHd + AcwC9wHyAvYB8AL1Ae4C9AHsAvkB7wLVAc0MAALWAc4C/QP7AfgB4AHTAe4BkgFfAdYC9wHyAd0B0AHp + AZIBXwHWAvQB7ALxAecC9wHqAtYBzgwAAtYBzgL9A/sB+AL6AfYBcAHFAbQB1QHrAeIC9gHwAvUB7gL0 + AewC8QHnAvcB6gLWAc4MAALWAc4C/QP7AfgC+gH2AvgB9AHnAasBsQHeAYUBkAL1Ae4C9AHsAvEB5wL3 + AeoC1gHODAAC1gHOAv0D+wH4AvoB9gHWAZIBXwHvAd4BzQL2AfAC9QHuAvQB7ALxAecC9wHqAtYBzgwA + AtgB0AL9A/oB9gHgAdMB7gGYAWUB3AGYAWUB3AGYAWUB3AHFAawB4wLxAecC7AHfAvQB5QLYAdAMAALY + AdAC/QP6AfYC+AH0AbcB4QHVAXYBywG6AXYBywG6AZUB1QHGAvEB5wLsAd8C9AHlAtgB0AwAAtgB0AL9 + A/oB9gL4AfQB6gGvAbQB3AFlAXYB3AFlAXYB6AGsAbEC8QHnAuwB3wL0AeUC2AHQDAAC2AHQAv0D+gH2 + AvgB9AHcAZgBZQHvAd4BzQL1Ae4C9AHsAvEB5wLsAd8C9AHlAtgB0AwAAtoB0gL8A/gB9AL3AfIC9gHw + AvUB7gL0AewC8QHnAuwB3wLoAdkC8wHiAtoB0gwAAtoB0gL8A/gB9AL3AfIC9gHwAvUB7gL0AewC8QHn + AuwB3wLoAdkC8wHiAtoB0gwAAtoB0gL8A/gB9AL3AfIC9gHwAvUB7gL0AewC8QHnAuwB3wLoAdkC8wHi + AtoB0gwAAtoB0gL8A/gB9AL3AfIC9gHwAvUB7gL0AewC8QHnAuwB3wLoAdkC8wHiAtoB0gwAAtsB0wL8 + A/cB8gL2AfAC9QHuAvQB7ALxAecC7AHfAugB2QLmAdUC8gHhAtsB0wwAAtsB0wL8A/cB8gL2AfAC9QHu + AvQB7ALxAecC7AHfAugB2QLmAdUC8gHhAtsB0wwAAtsB0wL8A/cB8gL2AfAC9QHuAvQB7ALxAecC7AHf + AugB2QLmAdUC8gHhAtsB0wwAAtsB0wL8A/cB8gL2AfAC9QHuAvQB7ALxAecC7AHfAugB2QLmAdUC8gHh + AtsB0wwAAtwB1QL7A/YB8AL1Ae4C9AHsAvEB5wLsAd8C6AHZAuYB1QLlAdQC8gHhAtwB1QwAAtwB1QL7 + A/YB8AL1Ae4C9AHsAvEB5wLsAd8C6AHZAuYB1QLlAdQC8gHhAtwB1QwAAtwB1QL7A/YB8AL1Ae4C9AHs + AvEB5wLsAd8C6AHZAuYB1QLlAdQC8gHhAtwB1QwAAtwB1QL7A/YB8AL1Ae4C9AHsAvEB5wLsAd8C6AHZ + AuYB1QLlAdQC8gHhAtwB1QwAAt0B1gL6AfQC9QHuAvQB7ALxAecC7AHfAugB2QLmAdUCpAGTAqQBkwKk + AZMCyQHADAAC3QHWAvoB9AL1Ae4C9AHsAvEB5wLsAd8C6AHZAuYB1QKkAZMCpAGTAqQBkwLJAcAMAALd + AdYC+gH0AvUB7gL0AewC8QHnAuwB3wLoAdkC5gHVAqQBkwKkAZMCpAGTAskBwAwAAt0B1gL6AfQC9QHu + AvQB7ALxAecC7AHfAugB2QLmAdUCpAGTAqQBkwKkAZMCyQHADAAC3gHXAvoB8wL0AewC8QHnAuwB3wLo + AdkC5gHVAuUB1AK2AaUD/wLeAdcC9wH2DAAC3gHXAvoB8wL0AewC8QHnAuwB3wLoAdkC5gHVAuUB1AK2 + AaUD/wLeAdcC9wH2DAAC3gHXAvoB8wL0AewC8QHnAuwB3wLoAdkC5gHVAuUB1AK2AaUD/wLeAdcC9wH2 + DAAC3gHXAvoB8wL0AewC8QHnAuwB3wLoAdkC5gHVAuUB1AK2AaUD/wLeAdcC9wH2DAAC3wHZAvwB9QL5 + Ae8C9gHqAvQB5QLzAeIC8gHhAvIB4QLCAbEC3wHZAvcB9g8AAt8B2QL8AfUC+QHvAvYB6gL0AeUC8wHi + AvIB4QLyAeECwgGxAt8B2QL3AfYPAALfAdkC/AH1AvkB7wL2AeoC9AHlAvMB4gLyAeEC8gHhAsIBsQLf + AdkC9wH2DwAC3wHZAvwB9QL5Ae8C9gHqAvQB5QLzAeIC8gHhAvIB4QLCAbEC3wHZAvcB9g8AAuoB5gLg + AdkC4AHZAuAB2QLgAdkC4AHZAuAB2QLgAdkC4AHZAvcB9hIAAuoB5gLgAdkC4AHZAuAB2QLgAdkC4AHZ + AuAB2QLgAdkC4AHZAvcB9hIAAuoB5gLgAdkC4AHZAuAB2QLgAdkC4AHZAuAB2QLgAdkC4AHZAvcB9hIA + AuoB5gLgAdkC4AHZAuAB2QLgAdkC4AHZAuAB2QLgAdkC4AHZAvcB9gwAAUIBTQE+BwABPgMAASgDAAFA + AwABUAMAAQEBAAEBBQABgAECFgAD/4IAAQEBAAEBAv8BwAEDAQABAQEAAQEC/wHAAQMBAAEBAQABAQL/ + AeABBwEAAQEBAAEBAcABAwHAAQMBAAEBAQABAQHAAQMBgAEBAQABAQEAAQEB8QGPAYABAQEAAQEBAAEB + AeABBwGAAQEBAAEBAQABAQHGAWMBgAEBAQABAQEAAQEBjgFxAYABAQEAAQEBAAEBAcYBYwGAAQEBAAEB + AQABAQHgAQcBgAEBAQABAQEAAQEB8QGPAYABAQEAAQEBAAEBAfkBnwHAAQMBAAEBAQABAQL/AeABBwEA + AQEBAAEBAv8B8AEPAYABAwEAAQEI/wIAAf4BAQL/BQABAQGIAwABwAEBAQABAQGIAQABgAEBAcABAQEA + AQEBjwH/AYABAQHAAQEBAAEBAv8BgAEBAcABAQEAAQEC/wGAAQEBwAEBAQABAQGPAf8BgAEBAcABAQEA + AQEBjAEBAYABAQHAAQEBAAEBAY8B/wGAAQEBwAEDAQABHwL/AYABAQHAAQMB8AEfAv8BgAEBAcABAwHw + AR8BjwH/AYABAQHAAQMB8AEfAYwBAQGAAQEBwAEDAfABHwGPAf8BgAEBAcABAwHwAR8E/wHAAQMB8AEf + BAAE/wQABP8BwAEDAcABAwT/AcABAwHAAQMBwAEDAgABwAEDAcABAwHAAQMCAAHAAQMBwAEDAfEBjwHM + AcEBwAEDAcABAwHjAccBwAHBAcABAwHAAQMBxwHjAcAB4wHAAQMBwAEDAY8B8QHhAeMBwAEDAcABAwHH + AeMB4QHjAcABAwHAAQMB4wHHAeEB/wHAAQMBwAEDAfEBjwHzAf8BwAEDAcABAwH5AZ8C/wHAAQMBwAED + BP8BwAEHAcABBwT/AcABDwHAAQ8E/xAAAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAED + AcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAED + AcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAED + AcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABBwHAAQcBwAEHAcABBwHAAQ8BwAEP + AcABDwHAAQ8L + + + + 132, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJ5SURBVDhPjdNdSFNhHMfx56Kb3i7scl10M28kIW+6kCDC + mF1EikF5IViDBMMkJQbKzHyZLiUVXc6hGdU0K0OTMFPBGkGpWIJiqznX3nybc3Oezb3663ke8sBJgg58 + Of/ncM6H58A5hPw5ZrTk+rSWVP1P7N6958TzVB2pESxarH28hvWJfAhz95BwdgHLT6Wt94Lduw/4XEs0 + 2HqNXd8rhB06eL8U470+A6PvmiSNjbdhsPZ4+z7gUy2pT2y+QHzNyEv4XmJm4BZcXi9WBAFOmj0QwBuT + CZpKxUiOWp0sQUxVpCHu6UVs+QmPzZN9SsxbLPhmNsPq8WBhZQU9w8NgR3ZZWaEEmbhLHsRWnyHifMRj + s+lxLr4vLnJk2e/nSJvRKJacmakWdzFWQVoi7m6EbB08Nk90XcGPpSWObNBX2EPYTtjrKEpKikRgpJzo + duydECw6HpvHDTmw2Gwc8QWDEsS5vY2MoqJiEXirIvrQkh4BcwuPzSPtWbDa7RzZ2tmRIKuhEM4WFNwW + gUEV6RR+tsI/38hj83DrRdgowBAhHJYgm3R9RqksFYH+UtIdWGiCd7aex+ah5guwOxwcCUWjEiRA16fz + 8u6IQG8xMfrnGuCZqeaxeaBRAYfTyZFwLCZBBAqk5eaqGHCQdsxwgwz5ZumnPFXJ89Fd9N8/D5fLxZFY + PC5BghQ8mZVVwYAkmrxQQTpGW9IC1qHC6MZ0NTa/atBXdw5utxsuWmJ3F3FaNJFAhGIROsvS07WSr9FQ + QLL1SmJ4Xi77MNlz6Zfq8gHHIbm87XBKSsPR1NT6vzsil9/c90+wC8355FRjHlHXXCUP6fIETfaPkn4D + qvVdCMceSq0AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJASURBVDhPjdJPSJNxGAfw5xYd6+hZJIjCim5d8hBe+nOL + KLA/FHjx0GEHcf6f04m51mwb5mJlhlkUFpVmusSIKf5Dszk3zYmSLjdn29rmtm/v8+CKl4E0+LCH7ft8 + 3/f38hLtfsYb6dpYI9X8D85m9/5+jzZQXcTbiHXnVWwMlSAyU430ygNg7ZHaRhc4m1PwpZ50CL9AJtSD + uL8Nm64yzHcXI+O1qmDVAc7mFIzUkz4d7EZqvVOkQ88w7ShCeNqIHc99pBcsIrPyEJzNKRiuIUMq0IWd + NYfgebLjFPwjepFSSljabwdncwqGKqll58djJFY6BM+fzSexPKwTSbdZpJbawdmcgg9aMiZW7YgtWQXP + TuNxLDnrRHzOJJI+Gzjbp6UTqpL35WT+vdyOyIJZ8DzQUgjfYI2IzRpFgp9FJgPOqwreaMgSW7Rg220U + PL9rOgLvx2oRnWkV8fk2BKNRcF5V8EpD7RGPCVuzzYLn17rD8AxUiV/TLSL27R58gQA4ryp4fpvs23N3 + sDmlFzy/rD0Ed79WhCebRfTrXZx2ZcB5VUFXGXVuzRgQGK8VPPdUFsDdVyG2Jgwiohzj6NsIOJ8t2K8M + B203qTc0pbzKo1UipNxFt7YAC8rts+wRosqD5OyNIjqr7PEuHVDkl54ha7/x2LavtzT5c6wWwQkd9Bcp + pDlPI6z5Cg1mcZZ3dnf/ncR2iy5YrpPtaXme0/Xk3Pemy/RJ+TevOJ/25bw4e/3QWkKFytUqGi6RScnt + ufwHz8wCEl4W+tkAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGqSURBVDhPrY3dK0NxHIfPcf4Al8qFK9du1K65kt0oGi0v + GSMX3Kml1NTENntT06TMCBtSthI2MptMygVDyLxERCsvodVqX+dzar8oHZRTT+f0+32e53DcfzxNOY42 + jWAfUOn1rb8BWzjs3xrBZj2ZfiE8mR/ABls4LNAoWOxxT5LSmQyl0mlZsMEWDgvUC5bBPfcDvYny0/u7 + LNhgC4cFGgSTc3fklh5TKbp7fpYFG2zhsEAt3+/acV3Tvfj3i2RSFmywhcMCar53JOa8pPPEE928vsqC + DbZwPgUMo1HHGQX7478CWzVvGGWBGl7vCVtPyFQ9QUbV+LfgLsv20BXBYQEV3z25ajoki3qKYrFtikSi + X8AZ7mZ1UbLX+WhzMEFwWKCK7/Kt9O2To36GQqEwdZcPSQQCSxI4wx0CLu0CbdhOCQ4LVPC6+ZDxgJya + efL7g9Ib+Hx+iewZAmPty7RuOSY4LKDgKkuVfEewp8z1ODe3QsMtfgmvd1Eie4aAtzNMa+Yjwj4bKBA/ + igo5RXMJp90SBMH8Hbj7TDGndIseXC5XJE8k/4/Ayf0AQu4lRh6dpg8AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHBSURBVDhPrVI9SAJhGH5vlygi+jFIBBGHOCdBAkFwEWlQ + WsImaxYpMLlFMALnGowiaIsapJaIhHAQghAu4pak5aCQuMUloSC/3ufDCxWThoSH93ufv/tOJfqPTyKR + WI7H4+pfuuCDv8+bSqU0IBaLjSyBbnv7Cjwej6brukgmk1o4HB5aAh46fPAP3lYFaRiG4Ctqfr+/rwQ7 + eOjd8NCHqF6vV2s0GiIajWpslCZM7OChMzXyNWWJaZoiFAppTqdzBRP7X8LytZb4CT6fT2s2myISidxU + q1WBHfyvv9IbkeOVaPVFUfYY52VFqey4XIZlWaLmcBgPvIOHDh/8P2UGL8+KsmsFg/V2Ot1q5/MdUSyK + x0xG3BK94wyAhw4f/MjJEp1ozQwEdJgu3O6nfaL6V6EgrnheE5UwsYOHDh/8yMmCmqIc94Y/sllxyWaG + NGBiB99bgpwsKBNVWtlsB+JnLidOeZ7Z7d0XxQ4eOnzwIyflA6LDe1Vt4hYnLG4PhO0vCzx0+OBHTmpe + onCJ6IiJu3WiLaYW8f9hLDCcjHmGm+HbINqED37k7PI5PtiY5fM0Y5IxzhjrYoLnFGOmx4sMfQPwk+w3 + ZtRzYgAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAG4SURBVDhPlZNNS0JREIbdR2DLIghCF0Eu2rQKI4IuSIFE + hQtXLsRCIiMjQ7m7+gHhL+iTEKmFIoj5tXfZrkUIGRhpeq/fOs0IczmYCR4YOHDOfZjnnXN1Olx7gcDW + riw7h9WOLBvozshlDQRcaqcD340GfNZqkK9W4b1SgedMBuhs2+83jgb4fPtKqwVfigIf5TK8FYvwWijA + bTQKtKx4PhKy6fUeqO02lFS1D4nncnCfSsF5MKjVmsv1RIpDlTY8HncdFX7q9T4knM3CWErrbvdhEwEK + ZkCQMLqPpbTqdB61ul2oYQ4ECaXTICpxLlc3N8BllCS/FuyKw3Hc6fWggTkQJJRMgqg0GC5NiLQ1wLLd + ftJFQBs1CPKYSICoxOFyJ3kMmrQ1wJLNdtrDcXVQgyAP8TiIShwud0JvhbQ1wKLVekbz7mEXBLmLxUBU + 4nC5k1KzCaStAWbNZrn/YgiCdR2JgKjE4XInFcyJtBkwN2EweCZNpksugyS9iEocLndCIyZtBuhxM401 + w7VgsVyIShwud1LDoEn7v/9DP6hEOpQJBUvTaeKe7iBgahjkj5Kox3vSxo/nfwHKBlL+USi6VgAAAABJ + RU5ErkJggg== + + + + + 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 + RpkLgwRoAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAG9SURBVDhPjZLNSwJRFMVdFu1a1DrIhRC0CCKiVUG5KIi0 + KGjRxkpKwpAJ1BgIpEWboH8gwqIoCiHaBv4L1UIQ+8ISkcpxZvz2ds/QRPLMenB4PDj3x73nXYvl68xs + bk5My/JiMzlludv0C7czEFjSKhV6LxYpreuUVFV6yuXoUVEMRaJRgmcqGLQ2hEz6/cu5UokyXPiazdJ9 + JkOxVIruXl7oNpmkw6srwoGvIWRCktwqA940rSFkLxwmU9axsaDQxbjPt6KXy/TB7f8GQScYB14BMOr1 + ruY5AyWfbwoBAF4BMOLxeAoMUAuFphAEC68AGHa710rVKumcAyCXF2mSXHFDkbPUd7D4HXgFwJDL5S0z + oMA5mJDI6SvthhJ1maR5RHgFwODCwnqlVqMij2FCzo+faUeO1WWCPYFXAPTPz/uqDEAXJuT08IFC/pu6 + TBQeEV4B0Dc7K9V4USoMAOTkIEFz9mtDR/vxbwiWDV4B0OtwbGDTatyFCfk5jvk7GmcErwCw2u0BY1f/ + gGDZ4P0JaOVHR+fAwJYJMCAsZIJgMRK+GHtS5De8qGGh1tLO6mnp6lpvs9m2/yN4UYPaT6iBRnEAJMyK + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGzSURBVDhPjZK9S4JRFMYdi7aGmoUchKAhCImmgnRIiuzD + QcjFSkpCEQM/EFyCxlqamuwPaHFoCRyarKmCyIoCTUQ0X/X1+z2dR3olumZdeLhceM6Pc557NJqvsxYK + mVfD4c1+WgmHx1S/cK8EAluVVosK9TplZZlS5TK9lUr0KkkdncfjBM9yMKjrCVny+7dLjQbluPC9WKSX + XI4eMhm6S6fpNpWis1iMcODrCTH7fM4yA/KVSk/IcTRKqnRGY1DoYsHr3ZGbTfrg9n+DoBOMA68AmHe7 + d6ucgVSt9oUAAK8AmHO5XDUGlGu1vhAEC68AmHU69xrtNsmcAyCOkyRdPxeEcfA78AqAGYfD3WRAjXMA + ZOPovgP4mUmWR4RXAEzb7Z6WolCdxwBk/fCGEk95YRzsCbwCYMpm87YZgC4AWYxcUeIxJ2QicXfwCoBJ + q9Wn8KK0GACIKXDZ1elFstsJlg1eATBhsexj0xTuQoWo46jB4osrPB68AkBnMgU6u/oHBMsG73fAID9G + Rg2GiAroQFjIBMFiJHwx9qTOb3hRw0KtZpg1PqDVeob0+oP/CF7UoPYTXb5IoCRPHYoAAAAASUVORK5C + YII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAG1SURBVDhPjZK9S4JRFMYdi7aGmoUchKAhCImmgnRIirRy + EHKxkpJQxMAPhJZo7l+oxqAhtwiEWgIjKiEIIuE1kZfM1+/P03mk9yW4Zl14uFx4zo9znnt0uu+zGo1a + V2KxjX6yx2Jjql+47eHwZrnVony9TrlKhaRSidLFIr0pSlfniQTBsxyJGHpClkKhrWKjQTIXvhcK9CrL + 9JzN0lMmQ4+SRCfxOOHA1xNiDQY9JQZ8lMs9IUfHx6TKYDZHhC4WAoHtSrNJn9z+bxB0gnHgFQDzPt9O + lTNQqtW+EADgFQBzXq+3xoBSrdYXgmDhFQCzHs9uo92mCucAyK37RdPDYVoLFr8DrwCYcbt9TQbUOAdA + rtdTlLnPC+PkeER4BcC0y+VvdTpU5zEAuVxLakqdprVgsSfwCoAppzPQZgC6AORi8YakO1nIROHu4BUA + kw5HsMOL0mIAIGeWK5KSspaJ+jtYNngFwITNtodN63AXKkQdRw0WkDKPB68AMFgs4e6u/gHBssH7EzDI + j5FRk2lfBXQhLGSCYDESvhh7Uuc3vKhhoVY3zBof0Ov9Q0bjwX8EL2pQ+wUVkUjMVKxfkgAAAABJRU5E + rkJggg== + + + + + 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 + + + + 347, 17 + + + + AAABAAQAMDAAAAEAIACoJQAARgAAACAgAAABACAAqBAAAO4lAAAYGAAAAQAgAIgJAACWNgAAEBAAAAEA + IABoBAAAHkAAACgAAAAwAAAAYAAAAAEAIAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAABjRbAAY0WwsGNFvIBTNa/wo5Yf8jXo3/KGSU/yZhkf8NPmf/BTNa/wY0W+AGNFscBjRbAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAABTNaAAUzWgsFM1rIBDJZ/wk4YP8iXYz/KGSU/yZhkf8NPmf/BTNa/wY0 + W+AGNFscBjRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzVdAAc1XQsHNV3IBjRc/ws6Yv8jXo3/KGSU/yZh + kf8NPmf/BTNa/wY0W+AGNFscBjRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFiGACBYhgsgWIbIH1iG/yFa + iP8mYpL/KGSU/yZhkf8NPmf/BTNa/wY0W+AGNFscBjRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKGSUAChk + lAsoZJTIKGSU/yhklP8oZJT/KGSU/yZhkf8NPmf/BTNa/wY0W+AGNFscBjRbAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAKGSUAChklAsoZJTIKGSU/yhklP8oZJT/KGSU/yZhkf8NPmf/BTNa/wY0W+AGNFscBjRbAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKGSUAChklAsoZJTIKGSU/yhklP8oZJT/KGSU/yZhkf8NPmf/BTNa/wY0 + W+AGNFscBjRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChk + lAAoZJQAKGSUAChklAAoZJQAKGSUAAAAAAAAAAAAKGSUAChklAsoZJTIKGSU/yhklP8oZJT/KGSU/yZh + kf8NPmf/BTNa/wY0W+AGNFscBjRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAChklAAoZJQGKGSUCihklAkoZJQCKGSUAAAAAAAAAAAAJmKRACZikQsmYpHIJmKR/yZi + kv8nY5P/KGSU/yZhkf8NPmf/BTNa/wY0W+AGNFscBjRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + lAAoZJQAKGSUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKGSUAChklAgoZJSuKGSU4CNejeAjXo30I16N/yRejf8nYpL/KGSU/yNe + jf8KOWH/BTNa/wY0W/QGNFtOBjRbHgY0WxoGNFsDBjRbAAY0WwoGNFuxBjRb4AY0W8QGNFsYBjRbAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKGSUAChklAEoZJQXKGSUHgo5YR4KOWGxCThg/wo7 + Y/8gWoj/KGSU/yNejf8KOWH/BTNa/wY0W/0GNFvmBjRb4AY0W8UGNFsYBjRbAAY0WwEGNFsYBjRbHgY0 + WxoGNFsDBjRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEURuABFEbgARRG4AEURuAAUz + WgAFM1mkBDFY/wY0W/8gWYf/KGWV/yNejf8JOGD/BDJZ/wUzWv8FM1r/BjRb/wY0W+EGNFsYBjRbAAY0 + WwAGNFsABjRbAAY0WwAGNFsABjRbAAY0WwAGNFsABjRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjRbAAY0 + WwIGNFsqBjRbNgY0WzYKOmK5DD1m/w0/aP8bU4D/IFqI/x1Wg/8PQGr/DD1m/ww9Zv8HNl3/BTNa/wY0 + W+YGNFtMBjRbNgY0WzMGNFsLBjRbAAY0WwYGNFswBjRbNgY0WyoGNFsCBjRbAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAABjRbAAY0WwkGNFu9BjRb9AY0W/QbUX77JmKS/yRfjv8NP2j/BjRb/ws6Yv8hXIv/JmGR/yRf + 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 + AAAAAAAAAAAAAAAAAAAAAAAAKGSUAChklBMoZJSRKGSUpChklH4oZJQGKGSUAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKGSUAChklAAoZJQAKGSUACdjkx4nY5PgJ2OT/ydj + k/MnY5M2J2OTAAAAAAAAAAAAAAAAAAAAAAAAAAAAKGSUAChklAAoZJQAKGSUAChklAAoZJQAKGSUAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKGSUAChk + lB4oZJTgKGSU/yhklPMoZJQ2KGSUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAKGSUAChklB4oZJTgKGSU/yhklPMoZJQ2KGSUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKGSUAChklB4oZJTgKGSU/yhklPMoZJQ2KGSUAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + AADmBwAA/nMAAP53AAD/fwAA/38AAA== + + + \ No newline at end of file diff --git a/NBTExplorerMac/Model/CompoundTagContainer.cs b/NBTExplorerMac/Model/CompoundTagContainer.cs new file mode 100644 index 0000000..7df9f75 --- /dev/null +++ b/NBTExplorerMac/Model/CompoundTagContainer.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class CompoundTagContainer : INamedTagContainer + { + private TagNodeCompound _tag; + + public CompoundTagContainer (TagNodeCompound tag) + { + _tag = tag; + } + + public int TagCount + { + get { return _tag.Count; } + } + + public IEnumerable TagNamesInUse + { + get { return _tag.Keys; } + } + + public string GetTagName (TagNode tag) + { + foreach (String name in _tag.Keys) + if (_tag[name] == tag) + return name; + + return null; + } + + public bool AddTag (TagNode tag, string name) + { + if (_tag.ContainsKey(name)) + return false; + + _tag.Add(name, tag); + return true; + } + + public bool RenameTag (TagNode tag, string name) + { + if (_tag.ContainsKey(name)) + return false; + + string oldName = GetTagName(tag); + _tag.Remove(oldName); + _tag.Add(name, tag); + + return true; + } + + public bool DeleteTag (TagNode tag) + { + foreach (String name in _tag.Keys) + if (_tag[name] == tag) + return _tag.Remove(name); + + return false; + } + } +} diff --git a/NBTExplorerMac/Model/CubicRegionDataNode.cs b/NBTExplorerMac/Model/CubicRegionDataNode.cs new file mode 100644 index 0000000..51de6f5 --- /dev/null +++ b/NBTExplorerMac/Model/CubicRegionDataNode.cs @@ -0,0 +1,75 @@ +using System.IO; +using System.Text.RegularExpressions; +using System.Windows.Forms; + +namespace NBTExplorer.Model +{ + public class CubicRegionDataNode : DataNode + { + private string _path; + private CubicRegionFile _region; + + private static Regex _namePattern = new Regex(@"^r2(\.-?\d+){3}\.(mcr|mca)$"); + + private CubicRegionDataNode (string path) + { + _path = path; + } + + public static CubicRegionDataNode TryCreateFrom (string path) + { + return new CubicRegionDataNode(path); + } + + public static bool SupportedNamePattern (string path) + { + path = Path.GetFileName(path); + return _namePattern.IsMatch(path); + } + + protected override NodeCapabilities Capabilities + { + get + { + return NodeCapabilities.Search; + } + } + + public override bool HasUnexpandedChildren + { + get { return !IsExpanded; } + } + + public override string NodeDisplay + { + get { return Path.GetFileName(_path); } + } + + protected override void ExpandCore () + { + try { + if (_region == null) + _region = new CubicRegionFile(_path); + + for (int x = 0; x < 32; x++) { + for (int z = 0; z < 32; z++) { + if (_region.HasChunk(x, z)) { + Nodes.Add(new RegionChunkDataNode(_region, x, z)); + } + } + } + } + catch { + MessageBox.Show("Not a valid cubic region file.", "Read Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + } + + protected override void ReleaseCore () + { + if (_region != null) + _region.Close(); + _region = null; + Nodes.Clear(); + } + } +} diff --git a/NBTExplorerMac/Model/CubicRegionFile.cs b/NBTExplorerMac/Model/CubicRegionFile.cs new file mode 100644 index 0000000..c54cf7a --- /dev/null +++ b/NBTExplorerMac/Model/CubicRegionFile.cs @@ -0,0 +1,24 @@ +using Substrate.Core; + +namespace NBTExplorer.Model +{ + public class CubicRegionFile : RegionFile + { + private const int _sectorBytes = 256; + private static byte[] _emptySector = new byte[_sectorBytes]; + + public CubicRegionFile (string path) + : base(path) + { } + + protected override int SectorBytes + { + get { return _sectorBytes; } + } + + protected override byte[] EmptySector + { + get { return _emptySector; } + } + } +} diff --git a/NBTExplorerMac/Model/DataNode.cs b/NBTExplorerMac/Model/DataNode.cs new file mode 100644 index 0000000..bfe356e --- /dev/null +++ b/NBTExplorerMac/Model/DataNode.cs @@ -0,0 +1,215 @@ +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class DataNode + { + private DataNode _parent; + private DataNodeCollection _children; + + private bool _expanded; + private bool _modified; + + public DataNode () + { + _children = new DataNodeCollection(this); + } + + public DataNode Parent + { + get { return _parent; } + internal set { _parent = value; } + } + + public DataNodeCollection Nodes + { + get { return _children; } + } + + public bool IsModified + { + get { return _modified; } + set + { + if (value && Parent != null) + Parent.IsModified = value; + _modified = value; + } + } + + public bool IsExpanded + { + get { return _expanded; } + private set { _expanded = value; } + } + + public void Expand () + { + if (!IsExpanded) { + ExpandCore(); + IsExpanded = true; + } + } + + protected virtual void ExpandCore () { } + + public void Collapse () + { + if (IsExpanded && !IsModified) { + Release(); + IsExpanded = false; + } + } + + public void Release () + { + foreach (DataNode node in Nodes) + node.Release(); + + ReleaseCore(); + IsExpanded = false; + } + + protected virtual void ReleaseCore () + { + Nodes.Clear(); + } + + public void Save () + { + foreach (DataNode node in Nodes) + if (node.IsModified) + node.Save(); + + SaveCore(); + IsModified = false; + } + + protected virtual void SaveCore () + { + } + + public virtual string NodeName + { + get { return ""; } + } + + public virtual string NodeDisplay + { + get { return ""; } + } + + public virtual bool HasUnexpandedChildren + { + get { return false; } + } + + #region Capabilities + + protected virtual NodeCapabilities Capabilities + { + get { return NodeCapabilities.None; } + } + + public virtual bool CanRenameNode + { + get { return (Capabilities & NodeCapabilities.Rename) != NodeCapabilities.None; } + } + + public virtual bool CanEditNode + { + get { return (Capabilities & NodeCapabilities.Edit) != NodeCapabilities.None; } + } + + public virtual bool CanDeleteNode + { + get { return (Capabilities & NodeCapabilities.Delete) != NodeCapabilities.None; } + } + + public virtual bool CanCopyNode + { + get { return (Capabilities & NodeCapabilities.Copy) != NodeCapabilities.None; } + } + + public virtual bool CanCutNode + { + get { return (Capabilities & NodeCapabilities.Cut) != NodeCapabilities.None; } + } + + public virtual bool CanPasteIntoNode + { + get { return (Capabilities & NodeCapabilities.PasteInto) != NodeCapabilities.None; } + } + + public virtual bool CanSearchNode + { + get { return (Capabilities & NodeCapabilities.Search) != NodeCapabilities.None; } + } + + public virtual bool CanReoderNode + { + get { return (Capabilities & NodeCapabilities.Reorder) != NodeCapabilities.None; } + } + + public virtual bool CanMoveNodeUp + { + get { return false; } + } + + public virtual bool CanMoveNodeDown + { + get { return false; } + } + + public virtual bool CanCreateTag (TagType type) + { + return false; + } + + #endregion + + #region Operations + + public virtual bool CreateNode (TagType type) + { + return false; + } + + public virtual bool RenameNode () + { + return false; + } + + public virtual bool EditNode () + { + return false; + } + + public virtual bool DeleteNode () + { + return false; + } + + public virtual bool CopyNode () + { + return false; + } + + public virtual bool CutNode () + { + return false; + } + + public virtual bool PasteNode () + { + return false; + } + + public virtual bool ChangeRelativePosition (int offset) + { + return false; + } + + #endregion + } +} diff --git a/NBTExplorerMac/Model/DataNodeCollection.cs b/NBTExplorerMac/Model/DataNodeCollection.cs new file mode 100644 index 0000000..52ffbcf --- /dev/null +++ b/NBTExplorerMac/Model/DataNodeCollection.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; + +namespace NBTExplorer.Model +{ + public class DataNodeCollection : IList + { + private List _nodes; + private DataNode _parent; + + internal DataNodeCollection (DataNode parent) + { + _parent = parent; + _nodes = new List(); + } + + public int IndexOf (DataNode item) + { + return _nodes.IndexOf(item); + } + + public void Insert (int index, DataNode item) + { + if (item == null) + throw new ArgumentNullException("item"); + if (item.Parent != null) + throw new ArgumentException("The item is already assigned to another DataNode."); + + item.Parent = _parent; + + _nodes.Insert(index, item); + } + + public void RemoveAt (int index) + { + if (index < 0 || index >= _nodes.Count) + throw new ArgumentOutOfRangeException("index"); + + DataNode node = _nodes[index]; + node.Parent = null; + + _nodes.RemoveAt(index); + } + + DataNode IList.this[int index] + { + get { return _nodes[index]; } + set + { + if (index < 0 || index > _nodes.Count) + throw new ArgumentOutOfRangeException("index"); + if (value == null) + throw new ArgumentNullException("item"); + if (value.Parent != null) + throw new ArgumentException("The item is already assigned to another DataNode."); + + _nodes[index].Parent = null; + _nodes[index] = value; + _nodes[index].Parent = _parent; + } + } + + public void Add (DataNode item) + { + if (item == null) + throw new ArgumentNullException("item"); + if (item.Parent != null) + throw new ArgumentException("The item is already assigned to another DataNode."); + + item.Parent = _parent; + + _nodes.Add(item); + } + + public void Clear () + { + foreach (DataNode node in _nodes) + node.Parent = null; + + _nodes.Clear(); + } + + public bool Contains (DataNode item) + { + return _nodes.Contains(item); + } + + public void CopyTo (DataNode[] array, int arrayIndex) + { + _nodes.CopyTo(array, arrayIndex); + } + + public int Count + { + get { return _nodes.Count; } + } + + bool ICollection.IsReadOnly + { + get { return (_nodes as IList).IsReadOnly; } + } + + public bool Remove (DataNode item) + { + if (_nodes.Contains(item)) + item.Parent = null; + + return _nodes.Remove(item); + } + + public IEnumerator GetEnumerator () + { + return _nodes.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () + { + return _nodes.GetEnumerator(); + } + } +} diff --git a/NBTExplorerMac/Model/DirectoryDataNode.cs b/NBTExplorerMac/Model/DirectoryDataNode.cs new file mode 100644 index 0000000..8d2d272 --- /dev/null +++ b/NBTExplorerMac/Model/DirectoryDataNode.cs @@ -0,0 +1,55 @@ +using System.IO; + +namespace NBTExplorer.Model +{ + public class DirectoryDataNode : DataNode + { + private string _path; + + public DirectoryDataNode (string path) + { + _path = path; + } + + protected override NodeCapabilities Capabilities + { + get + { + return NodeCapabilities.Search; + } + } + + public override string NodeDisplay + { + get { return Path.GetFileName(_path); } + } + + public override bool HasUnexpandedChildren + { + get { return !IsExpanded; } + } + + protected override void ExpandCore () + { + foreach (string dirpath in Directory.GetDirectories(_path)) { + Nodes.Add(new DirectoryDataNode(dirpath)); + } + + foreach (string filepath in Directory.GetFiles(_path)) { + DataNode node = null; + foreach (var item in FileTypeRegistry.RegisteredTypes) { + if (item.Value.NamePatternTest(filepath)) + node = item.Value.NodeCreate(filepath); + } + + if (node != null) + Nodes.Add(node); + } + } + + protected override void ReleaseCore () + { + Nodes.Clear(); + } + } +} diff --git a/NBTExplorerMac/Model/FileTypeRegistry.cs b/NBTExplorerMac/Model/FileTypeRegistry.cs new file mode 100644 index 0000000..64e746b --- /dev/null +++ b/NBTExplorerMac/Model/FileTypeRegistry.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; + +namespace NBTExplorer.Model +{ + public delegate bool NamePatternTestFunc (string path); + public delegate DataNode NodeCreateFunc (string path); + + public class FileTypeRecord + { + public NamePatternTestFunc NamePatternTest { get; set; } + public NodeCreateFunc NodeCreate { get; set; } + } + + public class FileTypeRegistry + { + private static Dictionary _registry = new Dictionary(); + + public static FileTypeRecord Lookup (Type type) + { + if (_registry.ContainsKey(type)) + return _registry[type]; + else + return null; + } + + public static void Register (Type type, FileTypeRecord record) + { + _registry[type] = record; + } + + public static void Register (FileTypeRecord record) + { + Register(typeof(T), record); + } + + public static IEnumerable> RegisteredTypes + { + get + { + foreach (var item in _registry) + yield return item; + } + } + + static FileTypeRegistry () + { + try { + Register(new FileTypeRecord() { + NamePatternTest = NbtFileDataNode.SupportedNamePattern, + NodeCreate = NbtFileDataNode.TryCreateFrom, + }); + + Register(new FileTypeRecord() { + NamePatternTest = RegionFileDataNode.SupportedNamePattern, + NodeCreate = RegionFileDataNode.TryCreateFrom, + }); + + Register(new FileTypeRecord() { + NamePatternTest = CubicRegionDataNode.SupportedNamePattern, + NodeCreate = CubicRegionDataNode.TryCreateFrom, + }); + } + catch (Exception e) { + Program.StaticInitFailure(e); + } + } + } +} diff --git a/NBTExplorerMac/Model/ListTagContainer.cs b/NBTExplorerMac/Model/ListTagContainer.cs new file mode 100644 index 0000000..1f4f3cd --- /dev/null +++ b/NBTExplorerMac/Model/ListTagContainer.cs @@ -0,0 +1,38 @@ +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class ListTagContainer : IOrderedTagContainer + { + private TagNodeList _tag; + + public ListTagContainer (TagNodeList tag) + { + _tag = tag; + } + + public int TagCount + { + get { return _tag.Count; } + } + + public bool DeleteTag (TagNode tag) + { + return _tag.Remove(tag); + } + + public int GetTagIndex (TagNode tag) + { + return _tag.IndexOf(tag); + } + + public bool InsertTag (TagNode tag, int index) + { + if (index < 0 || index > _tag.Count) + return false; + + _tag.Insert(index, tag); + return true; + } + } +} diff --git a/NBTExplorerMac/Model/NbtFileDataNode.cs b/NBTExplorerMac/Model/NbtFileDataNode.cs new file mode 100644 index 0000000..6d4681f --- /dev/null +++ b/NBTExplorerMac/Model/NbtFileDataNode.cs @@ -0,0 +1,141 @@ +using System.IO; +using Substrate.Core; +using Substrate.Nbt; +using System.Text.RegularExpressions; + +namespace NBTExplorer.Model +{ + public class NbtFileDataNode : DataNode, IMetaTagContainer + { + private NbtTree _tree; + private string _path; + private CompressionType _compressionType; + + private CompoundTagContainer _container; + + private static Regex _namePattern = new Regex(@"\.(dat|nbt|schematic)$"); + + private NbtFileDataNode (string path, CompressionType compressionType) + { + _path = path; + _compressionType = compressionType; + _container = new CompoundTagContainer(new TagNodeCompound()); + } + + public static NbtFileDataNode TryCreateFrom (string path) + { + return TryCreateFrom(path, CompressionType.GZip) + ?? TryCreateFrom(path, CompressionType.None); + } + + private static NbtFileDataNode TryCreateFrom (string path, CompressionType compressionType) + { + try { + NBTFile file = new NBTFile(path); + NbtTree tree = new NbtTree(); + tree.ReadFrom(file.GetDataInputStream(compressionType)); + + if (tree.Root == null) + return null; + + return new NbtFileDataNode(path, compressionType); + } + catch { + return null; + } + } + + public static bool SupportedNamePattern (string path) + { + path = Path.GetFileName(path); + return _namePattern.IsMatch(path); + } + + protected override NodeCapabilities Capabilities + { + get + { + return NodeCapabilities.CreateTag + | NodeCapabilities.PasteInto + | NodeCapabilities.Search; + } + } + + public override string NodeName + { + get { return Path.GetFileName(_path); } + } + + public override string NodeDisplay + { + get { return NodeName; } + } + + public override bool HasUnexpandedChildren + { + get { return !IsExpanded; } + } + + protected override void ExpandCore () + { + if (_tree == null) { + NBTFile file = new NBTFile(_path); + _tree = new NbtTree(); + _tree.ReadFrom(file.GetDataInputStream(_compressionType)); + + if (_tree.Root != null) + _container = new CompoundTagContainer(_tree.Root); + } + + foreach (TagNode tag in _tree.Root.Values) { + TagDataNode node = TagDataNode.CreateFromTag(tag); + if (node != null) + Nodes.Add(node); + } + } + + protected override void ReleaseCore () + { + _tree = null; + Nodes.Clear(); + } + + protected override void SaveCore () + { + NBTFile file = new NBTFile(_path); + using (Stream str = file.GetDataOutputStream(_compressionType)) { + _tree.WriteTo(str); + } + } + + public bool IsNamedContainer + { + get { return true; } + } + + public bool IsOrderedContainer + { + get { return false; } + } + + public INamedTagContainer NamedTagContainer + { + get { return _container; } + } + + public IOrderedTagContainer OrderedTagContainer + { + get { return null; } + } + + public int TagCount + { + get { return _container.TagCount; } + } + + public bool DeleteTag (TagNode tag) + { + return _container.DeleteTag(tag); + } + } +} diff --git a/NBTExplorerMac/Model/NodeCapabilities.cs b/NBTExplorerMac/Model/NodeCapabilities.cs new file mode 100644 index 0000000..9588730 --- /dev/null +++ b/NBTExplorerMac/Model/NodeCapabilities.cs @@ -0,0 +1,19 @@ +using System; + +namespace NBTExplorer.Model +{ + [Flags] + public enum NodeCapabilities + { + None = 0, + Cut = 0x1, + Copy = 0x2, + PasteInto = 0x4, + Rename = 0x8, + Edit = 0x10, + Delete = 0x20, + CreateTag = 0x40, + Search = 0x80, + Reorder = 0x100, + } +} diff --git a/NBTExplorerMac/Model/RegionChunkDataNode.cs b/NBTExplorerMac/Model/RegionChunkDataNode.cs new file mode 100644 index 0000000..02be164 --- /dev/null +++ b/NBTExplorerMac/Model/RegionChunkDataNode.cs @@ -0,0 +1,104 @@ +using Substrate.Core; +using Substrate.Nbt; +using System.IO; + +namespace NBTExplorer.Model +{ + public class RegionChunkDataNode : DataNode, IMetaTagContainer + { + private RegionFile _regionFile; + private NbtTree _tree; + private int _x; + private int _z; + + private CompoundTagContainer _container; + + public RegionChunkDataNode (RegionFile regionFile, int x, int z) + { + _regionFile = regionFile; + _x = x; + _z = z; + _container = new CompoundTagContainer(new TagNodeCompound()); + } + + protected override NodeCapabilities Capabilities + { + get + { + return NodeCapabilities.CreateTag + | NodeCapabilities.PasteInto + | NodeCapabilities.Search; + } + } + + public override bool HasUnexpandedChildren + { + get { return !IsExpanded; } + } + + public override string NodeDisplay + { + get { return "Chunk [" + _x + ", " + _z + "]"; } + } + + protected override void ExpandCore () + { + if (_tree == null) { + _tree = new NbtTree(); + _tree.ReadFrom(_regionFile.GetChunkDataInputStream(_x, _z)); + + if (_tree.Root != null) + _container = new CompoundTagContainer(_tree.Root); + } + + foreach (TagNode tag in _tree.Root.Values) { + TagDataNode node = TagDataNode.CreateFromTag(tag); + if (node != null) + Nodes.Add(node); + } + } + + protected override void ReleaseCore () + { + _tree = null; + Nodes.Clear(); + } + + protected override void SaveCore () + { + using (Stream str = _regionFile.GetChunkDataOutputStream(_x, _z)) { + _tree.WriteTo(str); + } + } + + public bool IsNamedContainer + { + get { return true; } + } + + public bool IsOrderedContainer + { + get { return false; } + } + + public INamedTagContainer NamedTagContainer + { + get { return _container; } + } + + public IOrderedTagContainer OrderedTagContainer + { + get { return null; } + } + + public int TagCount + { + get { return _container.TagCount; } + } + + public bool DeleteTag (TagNode tag) + { + return _container.DeleteTag(tag); + } + } +} diff --git a/NBTExplorerMac/Model/RegionFileDataNode.cs b/NBTExplorerMac/Model/RegionFileDataNode.cs new file mode 100644 index 0000000..4fb1a2d --- /dev/null +++ b/NBTExplorerMac/Model/RegionFileDataNode.cs @@ -0,0 +1,76 @@ +using System.IO; +using System.Windows.Forms; +using Substrate.Core; +using System.Text.RegularExpressions; + +namespace NBTExplorer.Model +{ + public class RegionFileDataNode : DataNode + { + private string _path; + private RegionFile _region; + + private static Regex _namePattern = new Regex(@"^r(\.-?\d+){2}\.(mcr|mca)$"); + + private RegionFileDataNode (string path) + { + _path = path; + } + + public static RegionFileDataNode TryCreateFrom (string path) + { + return new RegionFileDataNode(path); + } + + public static bool SupportedNamePattern (string path) + { + path = Path.GetFileName(path); + return _namePattern.IsMatch(path); + } + + protected override NodeCapabilities Capabilities + { + get + { + return NodeCapabilities.Search; + } + } + + public override bool HasUnexpandedChildren + { + get { return !IsExpanded; } + } + + public override string NodeDisplay + { + get { return Path.GetFileName(_path); } + } + + protected override void ExpandCore () + { + try { + if (_region == null) + _region = new RegionFile(_path); + + for (int x = 0; x < 32; x++) { + for (int z = 0; z < 32; z++) { + if (_region.HasChunk(x, z)) { + Nodes.Add(new RegionChunkDataNode(_region, x, z)); + } + } + } + } + catch { + MessageBox.Show("Not a valid region file.", "Read Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + } + + protected override void ReleaseCore () + { + if (_region != null) + _region.Close(); + _region = null; + Nodes.Clear(); + } + } +} diff --git a/NBTExplorerMac/Model/TagByteArrayDataNode.cs b/NBTExplorerMac/Model/TagByteArrayDataNode.cs new file mode 100644 index 0000000..0ed183b --- /dev/null +++ b/NBTExplorerMac/Model/TagByteArrayDataNode.cs @@ -0,0 +1,37 @@ +using System; +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagByteArrayDataNode : TagDataNode + { + public TagByteArrayDataNode (TagNodeByteArray tag) + : base(tag) + { } + + protected new TagNodeByteArray Tag + { + get { return base.Tag as TagNodeByteArray; } + } + + public override bool CanEditNode + { + get { return !IsMono(); } + } + + public override bool EditNode () + { + return EditByteHexValue(Tag); + } + + public override string NodeDisplay + { + get { return NodeDisplayPrefix + Tag.Data.Length + " bytes"; } + } + + private bool IsMono () + { + return Type.GetType("Mono.Runtime") != null; + } + } +} diff --git a/NBTExplorerMac/Model/TagByteDataNode.cs b/NBTExplorerMac/Model/TagByteDataNode.cs new file mode 100644 index 0000000..cfc803a --- /dev/null +++ b/NBTExplorerMac/Model/TagByteDataNode.cs @@ -0,0 +1,26 @@ +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagByteDataNode : TagDataNode + { + public TagByteDataNode (TagNodeByte tag) + : base(tag) + { } + + protected new TagNodeByte Tag + { + get { return base.Tag as TagNodeByte; } + } + + public override bool EditNode () + { + return EditScalarValue(Tag); + } + + public override string NodeDisplay + { + get { return NodeDisplayPrefix + unchecked((sbyte)Tag.Data).ToString(); } + } + } +} diff --git a/NBTExplorerMac/Model/TagCompoundDataNode.cs b/NBTExplorerMac/Model/TagCompoundDataNode.cs new file mode 100644 index 0000000..d4810ae --- /dev/null +++ b/NBTExplorerMac/Model/TagCompoundDataNode.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagCompoundDataNode : TagDataNode.Container + { + private CompoundTagContainer _container; + + public TagCompoundDataNode (TagNodeCompound tag) + : base(tag) + { + _container = new CompoundTagContainer(tag); + } + + protected new TagNodeCompound Tag + { + get { return base.Tag as TagNodeCompound; } + } + + protected override void ExpandCore () + { + var list = new SortedList(); + foreach (var item in Tag) { + list.Add(new TagKey(item.Key, item.Value.GetTagType()), item.Value); + } + + foreach (var item in list) { + TagDataNode node = TagDataNode.CreateFromTag(item.Value); + if (node != null) + Nodes.Add(node); + } + } + + public override bool CanCreateTag (TagType type) + { + return Enum.IsDefined(typeof(TagType), type) && type != TagType.TAG_END; + } + + public override bool CanPasteIntoNode + { + get { return NbtClipboardData.ContainsData; } + } + + public override bool CreateNode (TagType type) + { + if (!CanCreateTag(type)) + return false; + + CreateNodeForm form = new CreateNodeForm(type, true); + form.InvalidNames.AddRange(_container.TagNamesInUse); + + if (form.ShowDialog() == DialogResult.OK) { + AddTag(form.TagNode, form.TagName); + return true; + } + + return false; + } + + public override bool PasteNode () + { + if (!CanPasteIntoNode) + return false; + + NbtClipboardData clipboard = NbtClipboardData.CopyFromClipboard(); + if (clipboard.Node == null) + return false; + + string name = clipboard.Name; + if (String.IsNullOrEmpty(name)) + name = "UNNAMED"; + + AddTag(clipboard.Node, MakeUniqueName(name)); + return true; + } + + public override bool IsNamedContainer + { + get { return true; } + } + + public override INamedTagContainer NamedTagContainer + { + get { return _container; } + } + + public override int TagCount + { + get { return _container.TagCount; } + } + + public override bool DeleteTag (TagNode tag) + { + return _container.DeleteTag(tag); + } + + private void AddTag (TagNode tag, string name) + { + _container.AddTag(tag, name); + IsModified = true; + + if (IsExpanded) { + TagDataNode node = TagDataNode.CreateFromTag(tag); + if (node != null) + Nodes.Add(node); + } + } + + private string MakeUniqueName (string name) + { + List names = new List(_container.TagNamesInUse); + if (!names.Contains(name)) + return name; + + int index = 1; + while (names.Contains(MakeCandidateName(name, index))) + index++; + + return MakeCandidateName(name, index); + } + + private string MakeCandidateName (string name, int index) + { + return name + " (Copy " + index + ")"; + } + } +} diff --git a/NBTExplorerMac/Model/TagContainerInterface.cs b/NBTExplorerMac/Model/TagContainerInterface.cs new file mode 100644 index 0000000..35c56b2 --- /dev/null +++ b/NBTExplorerMac/Model/TagContainerInterface.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public interface ITagContainer + { + int TagCount { get; } + + bool DeleteTag (TagNode tag); + } + + public interface IMetaTagContainer : ITagContainer + { + bool IsNamedContainer { get; } + bool IsOrderedContainer { get; } + + INamedTagContainer NamedTagContainer { get; } + IOrderedTagContainer OrderedTagContainer { get; } + } + + public interface INamedTagContainer : ITagContainer + { + IEnumerable TagNamesInUse { get; } + + string GetTagName (TagNode tag); + bool AddTag (TagNode tag, string name); + bool RenameTag (TagNode tag, string name); + } + + public interface IOrderedTagContainer : ITagContainer + { + int GetTagIndex (TagNode tag); + bool InsertTag (TagNode tag, int index); + } +} diff --git a/NBTExplorerMac/Model/TagDataNode.cs b/NBTExplorerMac/Model/TagDataNode.cs new file mode 100644 index 0000000..9ddc61f --- /dev/null +++ b/NBTExplorerMac/Model/TagDataNode.cs @@ -0,0 +1,344 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public abstract class TagDataNode : DataNode + { + public abstract class Container : TagDataNode, IMetaTagContainer + { + protected Container (TagNode tag) + : base(tag) + { } + + #region ITagContainer + + public virtual int TagCount + { + get { return 0; } + } + + public virtual bool IsNamedContainer + { + get { return false; } + } + + public virtual bool IsOrderedContainer + { + get { return false; } + } + + public virtual INamedTagContainer NamedTagContainer + { + get { return null; } + } + + public virtual IOrderedTagContainer OrderedTagContainer + { + get { return null; } + } + + public virtual bool DeleteTag (TagNode tag) + { + return false; + } + + #endregion + + protected override NodeCapabilities Capabilities + { + get + { + return NodeCapabilities.Copy + | NodeCapabilities.CreateTag + | NodeCapabilities.Cut + | NodeCapabilities.Delete + | NodeCapabilities.PasteInto + | (TagParent.IsNamedContainer ? NodeCapabilities.Rename : NodeCapabilities.None) + | (TagParent.IsOrderedContainer ? NodeCapabilities.Reorder : NodeCapabilities.None) + | NodeCapabilities.Search; + } + } + + public override bool HasUnexpandedChildren + { + get { return !IsExpanded && TagCount > 0; } + } + + public override string NodeDisplay + { + get { return NodeDisplayPrefix + TagCount + ((TagCount == 1) ? " entry" : " entries"); } + } + } + + private static Dictionary _tagRegistry; + + static TagDataNode () + { + _tagRegistry = new Dictionary(); + _tagRegistry[TagType.TAG_BYTE] = typeof(TagByteDataNode); + _tagRegistry[TagType.TAG_BYTE_ARRAY] = typeof(TagByteArrayDataNode); + _tagRegistry[TagType.TAG_COMPOUND] = typeof(TagCompoundDataNode); + _tagRegistry[TagType.TAG_DOUBLE] = typeof(TagDoubleDataNode); + _tagRegistry[TagType.TAG_FLOAT] = typeof(TagFloatDataNode); + _tagRegistry[TagType.TAG_INT] = typeof(TagIntDataNode); + _tagRegistry[TagType.TAG_INT_ARRAY] = typeof(TagIntArrayDataNode); + _tagRegistry[TagType.TAG_LIST] = typeof(TagListDataNode); + _tagRegistry[TagType.TAG_LONG] = typeof(TagLongDataNode); + _tagRegistry[TagType.TAG_SHORT] = typeof(TagShortDataNode); + _tagRegistry[TagType.TAG_STRING] = typeof(TagStringDataNode); + } + + static public TagDataNode CreateFromTag (TagNode tag) + { + if (tag == null || !_tagRegistry.ContainsKey(tag.GetTagType())) + return null; + + return Activator.CreateInstance(_tagRegistry[tag.GetTagType()], tag) as TagDataNode; + } + + static public TagNode DefaultTag (TagType type) + { + switch (type) { + case TagType.TAG_BYTE: + return new TagNodeByte(0); + case TagType.TAG_BYTE_ARRAY: + return new TagNodeByteArray(new byte[0]); + case TagType.TAG_COMPOUND: + return new TagNodeCompound(); + case TagType.TAG_DOUBLE: + return new TagNodeDouble(0); + case TagType.TAG_FLOAT: + return new TagNodeFloat(0); + case TagType.TAG_INT: + return new TagNodeInt(0); + case TagType.TAG_INT_ARRAY: + return new TagNodeIntArray(new int[0]); + case TagType.TAG_LIST: + return new TagNodeList(TagType.TAG_BYTE); + case TagType.TAG_LONG: + return new TagNodeLong(0); + case TagType.TAG_SHORT: + return new TagNodeShort(0); + case TagType.TAG_STRING: + return new TagNodeString(""); + default: + return new TagNodeByte(0); + } + } + + private TagNode _tag; + + protected TagDataNode (TagNode tag) + { + _tag = tag; + } + + protected IMetaTagContainer TagParent + { + get { return base.Parent as IMetaTagContainer; } + } + + protected TagNode Tag + { + get { return _tag; } + set + { + if (_tag.GetTagType() == value.GetTagType()) + _tag = value; + } + } + + protected override NodeCapabilities Capabilities + { + get + { + return NodeCapabilities.Copy + | NodeCapabilities.Cut + | NodeCapabilities.Delete + | NodeCapabilities.Edit + | (TagParent.IsNamedContainer ? NodeCapabilities.Rename : NodeCapabilities.None) + | (TagParent.IsOrderedContainer ? NodeCapabilities.Reorder : NodeCapabilities.None); + } + } + + public override bool CanMoveNodeUp + { + get + { + if (TagParent.IsOrderedContainer) + return TagParent.OrderedTagContainer.GetTagIndex(Tag) > 0; + return false; + } + } + + public override bool CanMoveNodeDown + { + get + { + if (TagParent.IsOrderedContainer) + return TagParent.OrderedTagContainer.GetTagIndex(Tag) < (TagParent.TagCount - 1); + return false; + } + } + + public override string NodeName + { + get + { + if (TagParent == null || !TagParent.IsNamedContainer) + return null; + + return TagParent.NamedTagContainer.GetTagName(Tag); + } + } + + protected string NodeDisplayPrefix + { + get + { + string name = NodeName; + return String.IsNullOrEmpty(name) ? "" : name + ": "; + } + } + + public override string NodeDisplay + { + get { return NodeDisplayPrefix + Tag.ToString(); } + } + + public override bool DeleteNode () + { + if (CanDeleteNode) { + TagParent.DeleteTag(Tag); + return Parent.Nodes.Remove(this); + } + + return false; + } + + public override bool RenameNode () + { + if (CanRenameNode && TagParent.IsNamedContainer) { + EditName form = new EditName(TagParent.NamedTagContainer.GetTagName(Tag)); + form.InvalidNames.AddRange(TagParent.NamedTagContainer.TagNamesInUse); + if (form.ShowDialog() == DialogResult.OK && form.IsModified) { + if (TagParent.NamedTagContainer.RenameTag(Tag, form.TagName)) { + IsModified = true; + return true; + } + } + } + + return false; + } + + public override bool CopyNode () + { + if (CanCopyNode) { + NbtClipboardData clip = new NbtClipboardData(NodeName, Tag); + clip.CopyToClipboard(); + return true; + } + + return false; + } + + public override bool CutNode () + { + if (CanCutNode) { + NbtClipboardData clip = new NbtClipboardData(NodeName, Tag); + clip.CopyToClipboard(); + + TagParent.DeleteTag(Tag); + Parent.Nodes.Remove(this); + return true; + } + + return false; + } + + public override bool ChangeRelativePosition (int offset) + { + if (CanReoderNode) { + int curIndex = TagParent.OrderedTagContainer.GetTagIndex(Tag); + int newIndex = curIndex + offset; + + if (newIndex < 0 || newIndex >= TagParent.OrderedTagContainer.TagCount) + return false; + + TagParent.OrderedTagContainer.DeleteTag(Tag); + TagParent.OrderedTagContainer.InsertTag(Tag, newIndex); + + DataNode parent = Parent; + parent.Nodes.Remove(this); + parent.Nodes.Insert(newIndex, this); + parent.IsModified = true; + return true; + } + + return false; + } + + protected bool EditScalarValue (TagNode tag) + { + EditValue form = new EditValue(tag); + if (form.ShowDialog() == DialogResult.OK) { + IsModified = true; + return true; + } + else + return false; + } + + protected bool EditStringValue (TagNode tag) + { + EditString form = new EditString(tag.ToTagString().Data); + if (form.ShowDialog() == DialogResult.OK) { + tag.ToTagString().Data = form.StringValue; + + IsModified = true; + return true; + } + else + return false; + } + + protected bool EditByteHexValue (TagNode tag) + { + HexEditor form = new HexEditor(NodeName, tag.ToTagByteArray().Data, 1); + if (form.ShowDialog() == DialogResult.OK && form.Modified) { + Array.Copy(form.Data, tag.ToTagByteArray().Data, tag.ToTagByteArray().Length); + + IsModified = true; + return true; + } + else + return false; + } + + protected bool EditIntHexValue (TagNode tag) + { + TagNodeIntArray iatag = tag.ToTagIntArray(); + byte[] data = new byte[iatag.Length * 4]; + for (int i = 0; i < iatag.Length; i++) { + byte[] buf = BitConverter.GetBytes(iatag.Data[i]); + Array.Copy(buf, 0, data, 4 * i, 4); + } + + HexEditor form = new HexEditor(NodeName, data, 4); + if (form.ShowDialog() == DialogResult.OK && form.Modified) { + for (int i = 0; i < iatag.Length; i++) { + iatag.Data[i] = BitConverter.ToInt32(form.Data, i * 4); + } + + IsModified = true; + return true; + } + else + return false; + } + } +} diff --git a/NBTExplorerMac/Model/TagDoubleDataNode.cs b/NBTExplorerMac/Model/TagDoubleDataNode.cs new file mode 100644 index 0000000..e1fd990 --- /dev/null +++ b/NBTExplorerMac/Model/TagDoubleDataNode.cs @@ -0,0 +1,16 @@ +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagDoubleDataNode : TagDataNode + { + public TagDoubleDataNode (TagNodeDouble tag) + : base(tag) + { } + + public override bool EditNode () + { + return EditScalarValue(Tag); + } + } +} diff --git a/NBTExplorerMac/Model/TagFloatDataNode.cs b/NBTExplorerMac/Model/TagFloatDataNode.cs new file mode 100644 index 0000000..30c8946 --- /dev/null +++ b/NBTExplorerMac/Model/TagFloatDataNode.cs @@ -0,0 +1,16 @@ +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagFloatDataNode : TagDataNode + { + public TagFloatDataNode (TagNodeFloat tag) + : base(tag) + { } + + public override bool EditNode () + { + return EditScalarValue(Tag); + } + } +} diff --git a/NBTExplorerMac/Model/TagIntArrayDataNode.cs b/NBTExplorerMac/Model/TagIntArrayDataNode.cs new file mode 100644 index 0000000..a11bb98 --- /dev/null +++ b/NBTExplorerMac/Model/TagIntArrayDataNode.cs @@ -0,0 +1,37 @@ +using System; +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagIntArrayDataNode : TagDataNode + { + public TagIntArrayDataNode (TagNodeIntArray tag) + : base(tag) + { } + + protected new TagNodeIntArray Tag + { + get { return base.Tag as TagNodeIntArray; } + } + + public override bool CanEditNode + { + get { return !IsMono(); } + } + + public override bool EditNode () + { + return EditIntHexValue(Tag); + } + + public override string NodeDisplay + { + get { return NodeDisplayPrefix + Tag.Data.Length + " integers"; } + } + + private bool IsMono () + { + return Type.GetType("Mono.Runtime") != null; + } + } +} diff --git a/NBTExplorerMac/Model/TagIntDataNode.cs b/NBTExplorerMac/Model/TagIntDataNode.cs new file mode 100644 index 0000000..2cda6c3 --- /dev/null +++ b/NBTExplorerMac/Model/TagIntDataNode.cs @@ -0,0 +1,16 @@ +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagIntDataNode : TagDataNode + { + public TagIntDataNode (TagNodeInt tag) + : base(tag) + { } + + public override bool EditNode () + { + return EditScalarValue(Tag); + } + } +} diff --git a/NBTExplorerMac/Model/TagListDataNode.cs b/NBTExplorerMac/Model/TagListDataNode.cs new file mode 100644 index 0000000..ecc630b --- /dev/null +++ b/NBTExplorerMac/Model/TagListDataNode.cs @@ -0,0 +1,111 @@ +using System; +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagListDataNode : TagDataNode.Container + { + private ListTagContainer _container; + + public TagListDataNode (TagNodeList tag) + : base(tag) + { + _container = new ListTagContainer(tag); + } + + protected new TagNodeList Tag + { + get { return base.Tag as TagNodeList; } + set { base.Tag = value; } + } + + protected override void ExpandCore () + { + foreach (TagNode tag in Tag) { + TagDataNode node = TagDataNode.CreateFromTag(tag); + if (node != null) + Nodes.Add(node); + } + } + + public override bool CanCreateTag (TagType type) + { + if (Tag.Count > 0) + return Tag.ValueType == type; + else + return Enum.IsDefined(typeof(TagType), type) && type != TagType.TAG_END; + } + + public override bool CanPasteIntoNode + { + get + { + if (NbtClipboardData.ContainsData) { + TagNode node = NbtClipboardData.CopyFromClipboard().Node; + if (node != null && node.GetTagType() == Tag.ValueType) + return true; + } + + return false; + } + } + + public override bool CreateNode (TagType type) + { + if (!CanCreateTag(type)) + return false; + + if (Tag.Count == 0) { + Tag.ChangeValueType(type); + } + + AppendTag(TagDataNode.DefaultTag(type)); + return true; + } + + public override bool PasteNode () + { + if (!CanPasteIntoNode) + return false; + + NbtClipboardData clipboard = NbtClipboardData.CopyFromClipboard(); + if (clipboard.Node == null) + return false; + + AppendTag(clipboard.Node); + return true; + } + + public override bool IsOrderedContainer + { + get { return true; } + } + + public override IOrderedTagContainer OrderedTagContainer + { + get { return _container; } + } + + public override int TagCount + { + get { return _container.TagCount; } + } + + public override bool DeleteTag (TagNode tag) + { + return _container.DeleteTag(tag); + } + + private void AppendTag (TagNode tag) + { + _container.InsertTag(tag, _container.TagCount); + IsModified = true; + + if (IsExpanded) { + TagDataNode node = TagDataNode.CreateFromTag(tag); + if (node != null) + Nodes.Add(node); + } + } + } +} diff --git a/NBTExplorerMac/Model/TagLongDataNode.cs b/NBTExplorerMac/Model/TagLongDataNode.cs new file mode 100644 index 0000000..3051802 --- /dev/null +++ b/NBTExplorerMac/Model/TagLongDataNode.cs @@ -0,0 +1,16 @@ +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagLongDataNode : TagDataNode + { + public TagLongDataNode (TagNodeLong tag) + : base(tag) + { } + + public override bool EditNode () + { + return EditScalarValue(Tag); + } + } +} diff --git a/NBTExplorerMac/Model/TagShortDataNode.cs b/NBTExplorerMac/Model/TagShortDataNode.cs new file mode 100644 index 0000000..beff379 --- /dev/null +++ b/NBTExplorerMac/Model/TagShortDataNode.cs @@ -0,0 +1,16 @@ +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagShortDataNode : TagDataNode + { + public TagShortDataNode (TagNodeShort tag) + : base(tag) + { } + + public override bool EditNode () + { + return EditScalarValue(Tag); + } + } +} diff --git a/NBTExplorerMac/Model/TagStringDataNode.cs b/NBTExplorerMac/Model/TagStringDataNode.cs new file mode 100644 index 0000000..1624073 --- /dev/null +++ b/NBTExplorerMac/Model/TagStringDataNode.cs @@ -0,0 +1,21 @@ +using Substrate.Nbt; + +namespace NBTExplorer.Model +{ + public class TagStringDataNode : TagDataNode + { + public TagStringDataNode (TagNodeString tag) + : base(tag) + { } + + public override bool EditNode () + { + return EditStringValue(Tag); + } + + public override string NodeDisplay + { + get { return NodeDisplayPrefix + Tag.ToString().Replace('\n', (char)0x00B6); } + } + } +} diff --git a/NBTExplorerMac/NBTExplorerMac.csproj b/NBTExplorerMac/NBTExplorerMac.csproj new file mode 100644 index 0000000..9ddb9f2 --- /dev/null +++ b/NBTExplorerMac/NBTExplorerMac.csproj @@ -0,0 +1,72 @@ + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {01F9A296-C477-4CBF-A0D0-41E697048257} + {948B3504-5B70-4649-8FE4-BDE1FB46EC69};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + NBTExplorerMac + Resources + NBTExplorerMac + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + False + False + False + False + False + Mac Developer + + + none + True + bin\Release + prompt + 4 + False + False + Full + False + False + False + Mac Developer + + + none + True + bin\AppStore + prompt + 4 + 3rd Party Mac Developer Installer + True + Full + True + False + True + True + 3rd Party Mac Developer Application + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NBTExplorerMac/NbtClipboardData.cs b/NBTExplorerMac/NbtClipboardData.cs new file mode 100644 index 0000000..02ea8bf --- /dev/null +++ b/NBTExplorerMac/NbtClipboardData.cs @@ -0,0 +1,62 @@ +using System; +using System.IO; +using System.Windows.Forms; +using Substrate.Nbt; + +namespace NBTExplorer +{ + [Serializable] + public class NbtClipboardData + { + public string Name; + + private byte[] _data; + + [NonSerialized] + public TagNode Node; + + public NbtClipboardData (String name, TagNode node) + { + Name = name; + + TagNodeCompound root = new TagNodeCompound(); + root.Add("root", node); + NbtTree tree = new NbtTree(root); + + using (MemoryStream ms = new MemoryStream()) { + tree.WriteTo(ms); + _data = new byte[ms.Length]; + Array.Copy(ms.GetBuffer(), _data, ms.Length); + } + } + + public static bool ContainsData + { + get { return Clipboard.ContainsData(typeof(NbtClipboardData).FullName); } + } + + public void CopyToClipboard () + { + Clipboard.SetData(typeof(NbtClipboardData).FullName, this); + } + + public static NbtClipboardData CopyFromClipboard () + { + NbtClipboardData clip = Clipboard.GetData(typeof(NbtClipboardData).FullName) as NbtClipboardData; + if (clip == null) + return null; + + NbtTree tree = new NbtTree(); + using (MemoryStream ms = new MemoryStream(clip._data)) { + tree.ReadFrom(ms); + } + + TagNodeCompound root = tree.Root; + if (root == null || !root.ContainsKey("root")) + return null; + + clip.Node = root["root"]; + return clip; + } + } +} diff --git a/NBTExplorerMac/Program.cs b/NBTExplorerMac/Program.cs new file mode 100644 index 0000000..d2f1547 --- /dev/null +++ b/NBTExplorerMac/Program.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace NBTExplorer +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main () + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + public static void StaticInitFailure (Exception e) + { + Console.WriteLine("Static Initialization Failure:"); + + Exception original = e; + while (e != null) { + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + e = e.InnerException; + } + + MessageBox.Show("Application failed during static initialization: " + original.Message); + Application.Exit(); + } + } +} diff --git a/NBTExplorerMac/Properties/AssemblyInfo.cs b/NBTExplorerMac/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..66baf9f --- /dev/null +++ b/NBTExplorerMac/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("NBTExplorer")] +[assembly: AssemblyDescription("Graphical editor for most NBT data sources. NBT is used by Minecraft.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NBTExplorer")] +[assembly: AssemblyCopyright("Copyright © Justin Aquadro 2011-2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("11f3587a-6155-499e-b7b5-ebd48fdca479")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2.0.2.0")] +[assembly: AssemblyFileVersion("2.0.2.0")] diff --git a/NBTExplorerMac/Properties/Resources.Designer.cs b/NBTExplorerMac/Properties/Resources.Designer.cs new file mode 100644 index 0000000..0d3bc07 --- /dev/null +++ b/NBTExplorerMac/Properties/Resources.Designer.cs @@ -0,0 +1,77 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.269 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace NBTExplorer.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NBTExplorer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Bitmap ArrowDown { + get { + object obj = ResourceManager.GetObject("ArrowDown", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap ArrowUp { + get { + object obj = ResourceManager.GetObject("ArrowUp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/NBTExplorerMac/Properties/Resources.resources b/NBTExplorerMac/Properties/Resources.resources new file mode 100644 index 0000000000000000000000000000000000000000..b0ac4701a7e6d24c7811b9a392bc9cf544c6c657 GIT binary patch literal 1557 zcmcgsdrVVT7(ZBT0n1|y(QdllO(q&TEMi4ArNSzY@Ei}3O@!Nesf~R|9|M6<9?L8< zDxyY8h~h{DGIiO=M1@(+iVTAkqZ@^85@80{MynMp0{5PsOPrh8e@nJ=&i9@3Jx;#g zm-D-K;D+;x2LRv*5_#r6jh0Y^We^&bPAwrcFHac+zKc-vFoi~9;YI;|R)^RRTCST2(!5&N=KdkE!babzSekO($}M@6hB_#2~E z{JJ2EgyLPiPzrKUX*^oaZEi-a(yyq-OH&Z<81)P4&7)T^I!UUW?e4QcfrjXe&_`jg}nVev#OoN6^e)|13_ zTiz?aZ?uo+!&XJ9+hn&6K`c6vxw?=Sm09|D96s)G!&X&=i)#+)1HjOw~-62s|$Z4jeNWiO%b znXeAmMj@-O=FYuI@2|d0VRz=(I9&`Oe0q-Z?)|*0Vvbc?^P3kF>*&sA@82`dIY>e( zLNVvgmsw1xpM<97!es@4x4*!P+M-r|Hw*RtK4Y)99A07|s;r)dgB-IqX_+F_Qn{PY ztv+7az-V<;HE<2@R&DoY1uYZ@?MeZGGecI}+^K8mkwD_sRMGj^g6hTp9m7b(z5kbC zWiJ`F#J`hW8-CuVV~UQR&F$Z``g(KetkIYTA?p?veXDV6GDEBlz0hQ&rXjSC3#qiS zNhmb<1%$Na{%Bnr*HJR?D5O}0cgMWxv$eHq1h zvs2t)zl{B-jcJyMxNu3Ik+SKjoE5V(Cf9=@IBXlG{PN48e$rJ2j}8f^xu%&%(DlRD z^E7E;HcE$+X-d`=jg54{yj4xlxm~USy*8?@v>Si>wTSU#v%L&HJhNktd)f6!?|-TQ zyu&y$SS#)RIhs`Q9RvE#>@>vTU=HR#sJUJ~-UZbM@~Oz3@Y($L^2<(zG^?`$S~_PO z`ktGkkWRgNZ=@tn-fM!%Z$fhE2<4nl<@pMv=1)mz>39hB*H%E3YJMPLiG8pQg;`S{ wU*G-7KIWmS^16-wj_Pv5Z7~+)Azrg-`*Oo@oxlU|i$+egRk+bl;BVym1A!lWj{pDw literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Properties/Resources.resx b/NBTExplorerMac/Properties/Resources.resx new file mode 100644 index 0000000..2ef62d6 --- /dev/null +++ b/NBTExplorerMac/Properties/Resources.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\arrow-270.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\arrow-090.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/NBTExplorerMac/Properties/Settings.Designer.cs b/NBTExplorerMac/Properties/Settings.Designer.cs new file mode 100644 index 0000000..029c8a1 --- /dev/null +++ b/NBTExplorerMac/Properties/Settings.Designer.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.269 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace NBTExplorer.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Collections.Specialized.StringCollection RecentFiles { + get { + return ((global::System.Collections.Specialized.StringCollection)(this["RecentFiles"])); + } + set { + this["RecentFiles"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Collections.Specialized.StringCollection RecentDirectories { + get { + return ((global::System.Collections.Specialized.StringCollection)(this["RecentDirectories"])); + } + set { + this["RecentDirectories"] = value; + } + } + } +} diff --git a/NBTExplorerMac/Properties/Settings.settings b/NBTExplorerMac/Properties/Settings.settings new file mode 100644 index 0000000..86f5808 --- /dev/null +++ b/NBTExplorerMac/Properties/Settings.settings @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/NBTExplorerMac/Resources/24/box-24.png b/NBTExplorerMac/Resources/24/box-24.png new file mode 100644 index 0000000000000000000000000000000000000000..b10ed76d13a55606aeff3fca3235e87074da36ee GIT binary patch literal 654 zcmV;90&)F`P)6LIANK z98hT$L?u+{!h|ZIqC*#?egeJ&pMimig>S%C#K4Za0Rv)gtGWXt!a<2d9qhZ~{a2miy#Ms^rKR<|<)#7MNfw!W3BQT?lWl2Io5$T@STdtvN>!mw^Emm|!c-2V-fabMeia5&`R@JJ~oEgaH;b^P)DvP`m>RB68( zu7sYaoFMJUY%mzm^|dv37S@E!?dJg`g36MyN>5Il4@6Nk*Ow#-{fcAvJha=2x$?Gt zzRr|oDd3A()p%i9QqvNtLhnVaYP_(@0SxPGDypb5K*e}r(`hi_iLI9KQ2#PLr$IEty` o;e!Q<^46<~k7~i*KmH@Y057u8*GpabegFUf07*qoM6N<$f)p)0mjD0& literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/24/cross.png b/NBTExplorerMac/Resources/24/cross.png new file mode 100644 index 0000000000000000000000000000000000000000..87b63731ebd7329548b0516355b6612606d969be GIT binary patch literal 1081 zcmV-91jhS`P)H&aBB*Y(9T+pPcI|+ zhdgzw_wA~YU3!affTHQ?R@?TmCB#)v~* zU2JA%23A*BA)QV`E6&Gau{9##BJaF>}1o^ z)518FN}3m^n&l%&XLJkEk`Z7i8giX+p} z54N_l#Ml^zaM2MFkL74f)Vd)Y-EOE2pf7XFE88Vnx?^UELIk|^8~*2-W+lwk-pyE z$l+j+f1jU+rKKf1p>&e@Y}Sr^-B!^rl`0*mkjhHE!s~?$R+JhZc?AVI|0(}pMXWeL zx1k+!IJo+Yc>P zKEFnMKy0RjqcfGJj$|z^5fY8!It8Zfu#Bg0q2U;AsAS)fmwNpZk1wtND(i`}7rL4E~Ph5DqU>J%O; zHKLpg5=FVDek^E?uA+Wilw`+PmffQ8OMn3Yo^A=-4;_-e00000NkvXXu0mjfyleX< literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/24/document-b.png b/NBTExplorerMac/Resources/24/document-b.png new file mode 100644 index 0000000000000000000000000000000000000000..9fde514b575130636afeba0afe2678f076ccbf25 GIT binary patch literal 3486 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 M07*qoM6N<$g2L#7>;M1& literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/24/document-d.png b/NBTExplorerMac/Resources/24/document-d.png new file mode 100644 index 0000000000000000000000000000000000000000..1d31f1b3376abdb421660f04697362b9801d90e8 GIT binary patch literal 3467 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 literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/24/document-i.png b/NBTExplorerMac/Resources/24/document-i.png new file mode 100644 index 0000000000000000000000000000000000000000..04136ef11b9e344f28fde661fc34bd9cb40cfb9e GIT binary patch literal 3417 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 KMNUMnLSTa9VGRNR literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/24/edit-code-i.png b/NBTExplorerMac/Resources/24/edit-code-i.png new file mode 100644 index 0000000000000000000000000000000000000000..f5e5526c5b36ee7671dafba782ae25e01f1d9d0c GIT binary patch literal 3263 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 literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/24/edit-code.png b/NBTExplorerMac/Resources/24/edit-code.png new file mode 100644 index 0000000000000000000000000000000000000000..726b6435e429f114c0f6f2454da8c3857dfceaea GIT binary patch literal 3135 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 literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/24/selection-input.png b/NBTExplorerMac/Resources/24/selection-input.png new file mode 100644 index 0000000000000000000000000000000000000000..f83f1dc0adce6561c47854b2f6bf78c4c2e5cc9b GIT binary patch literal 3561 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 literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/arrow-090.png b/NBTExplorerMac/Resources/arrow-090.png new file mode 100644 index 0000000000000000000000000000000000000000..4e4f5b8a445f527ea7362fa1ca0df8d01db465ca GIT binary patch literal 618 zcmV-w0+s!VP)QX~*i z6BN-(5F5uzOkv|Gf`x(@IkdDAwzaSlwG{-xLT%!|pzveBVbH_K;-(fqX*!_->VqfS4|1TF-MkA3S;arZk*TdsL^h zj@j91ym<9xOW!uD5MrLh;sAi0ujP4OrUI(`>tDHmmNp^?(>7}BF>>4t+p@OLK}mU* zA==n5`@nJ$I611qg^nVltJZ3;DwUms#FQopLdv<4g;To@R-1kkIx6uM}KI?{F%xLphZI!li>U-bm#)z zp!OME{QNGmZ>{lz#K!2^9W(Q=1ZuWGL51Tp>qnhOi^z!`$iKgz#Mjp9kNXdYmd=M& z(kt3=C?AQ#(j>TTTkT=6X=3LuUvEad&OqgF;I{w+0QQ~>MdIN|0RR9107*qoM6N<$ Eg5?1qX#fBK literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/arrow-270.png b/NBTExplorerMac/Resources/arrow-270.png new file mode 100644 index 0000000000000000000000000000000000000000..8d5209b66047e854bac75f61055f97a1b5c9330b GIT binary patch literal 622 zcmV-!0+IcRP)p64pvg+PY&vK@owIgpdIX51 z90yz1ugq9M5JT4)o~(ZTw}LPX{|I=VgzJVVm-PeV8GzGjp;)P80-T2g5TqbRAVenC zbzS<-jsTwHAn-ZN%H%Lf2npX05d<1S-ybP+9SH7c6{w+3>Fl*}s8AdLLO29w%zzjG z{9YGw>^gdSp@Q7ohoCsEOI90;dzJ|~71a=E$d_e*4xq-NBV(r-*Tjil%saqeY+;b-IeX*%zH?aG$DYl*> z`1TINH#Gj3a>q_Xzj&{1T)n?Jvl_>0R%_)?54BHOUjfmT&mcQac2p_Low=1d{>BbE_2;qUWrjs|G(baHZ1 zwpc6+R;v{_j#EG}<%pviZI51~;FiPTI3!8Z5YO{vy0Ah zaVOTl>k8-%coB=mP8N$rXtx34@yB1Z`XiA@uu|E8TCE8)Gxz2(b&B$=riN)Yn~=}v zKon*0dcDC=D5MaHL;{E_6nH3=1f^DO(hksfIvpUat^MvbswbIDg4^v@c&hC+buHYr z*=&c=qhob7qZD~O9tZ>i%9Cnxxg4}wq;MT=)H?NgeHi;*t28EAo%rDxX#is%y#!q7;;h*}>iozJfHWXOr_q25SHm#P^Fs#5u5opMA)QWR zBZE8GP!gn|)o6maDU4jZai;HE1wd$bue1Pg;>zj%XOG@TSX>b0EPlTqs?{o(&D()x zjgU&E7~$s!khy)IrmlYu4%#_Z!dkL1IB_0c-M-(D8=KSA>_NOltZRWc@D`sVgl??l z`;Xsg5e$3A=wI-V1r!J4h(7HX)>Wp)<7(VutueV?UTXbVe1fm-KLQK@;s`t!sOcpt P00000NkvXXu0mjfDcee2 literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/binocular.png b/NBTExplorerMac/Resources/binocular.png new file mode 100644 index 0000000000000000000000000000000000000000..d199572eea6098963790d538fa9ce1bf48e1cd58 GIT binary patch literal 621 zcmV-z0+RiSP)(>A_ns4fN8qJqXf^NQs+ME`ew?WLFcj zyW)@C%sh6@ix~Rg~e8YV6W&?ph0J!xD@dlwGKEmU*n4<(7z7>l_SC-}DNF)NW zSd4+rbVnS;@EVb;;IpDA?;Xc^uIqYV6vcOfARHk8&j*quy&`Tf7}%C&y}-+uIwk?GfzleL2Fb9lDpe7-2LT!PQk4EX##dDz%== znX>RDOhC+t6qx;REm?gbbCdYBPNO8#h!00000NkvXX Hu0mjf6~Gox literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/clipboard-paste.png b/NBTExplorerMac/Resources/clipboard-paste.png new file mode 100644 index 0000000000000000000000000000000000000000..0cf8887292bf3f73c89509df0011809bc06e9906 GIT binary patch literal 685 zcmV;e0#f~nP)ou|gt6 zkY-_^2w7McZnUdb5V0Uw)MYny(tHkrVb}s-#+B5EjQW| z1l?90(D0Hl#hp`oTWaCzO!m^k{c#?DUU~Yv{;~J~X^7t5uY|=g@w4f^KzVk4VX9iK zB764*bX`L_JrXV)9htCg7YDEJA)n9VQ*o6AE`|;|{=kCkx@b0=ICy*$nx=)2Wf`95 zg=@)VGHl}Nvc zo~IN#RT|v$~|&e6%lj=BL^`N{*r*A)=c0`YH-2h|I1b2C&CUS zTJzZr|5DHuZW%^GeftZzaT*xcx+Ep$AmLfKbL|4+!Dhbi9`5bvnH6%o&yOkfejlT^ zPIfaT=zs#sz_^l)j0Hn&alQWY%fI>)>KdT{AzN!L-ku(! z6_?D-?!0+#=VtbVZQGdTnZt~apI_HPK#=zVadHM((E`e*C+RoFb)Qo8-U{Lb7{`Tz zw4B8FZ|o?Wox+p=1wp47C;7ar*Xu~;a?<=sjPv>+otDjJ6FaGt!YnNyxQQhp)G1V! zk;r6ZtyV)c8pTbiRAnHRNXTxti%=+p$4aG2*+mMM&xrdiU^`VPk^N*+HX98^7!HT% zwA%;A{T)GxeQ|RcxyzV%! z$AbYD+)i1R64zB?q}NmTz}5|04~J#YG_goA*Eq(QJvp7pG14hUj1pZ^t>3S*xqHUO ze~r;}zTY_XkZ*}d@gm!;N90h8nBQenBUZ_ukZKNicn*hc_Pmc!Jn|2=s<~}>!Sb>Qm3!QP46b_JFw5YU70Tu$X}=T}ez@@t%j iG9vD)nDux55?}x$+|UyQVK_bj0000>tPvNZcrb?u3Y-g%(87__cCVTj7qmf!` zOfVW_O*6@4W}ff9n2>0(cpnF5-rRHUx%a)X1m!RQ3n+e``;IlkFfceacCbH@IFkjg zE5EmobGSI(ttn8cY@RFa8VsKIdtMI>ZA5@O;JA{!x6CNae;}WYvPdMtR8?jEwnMX{ zfKOpCNmtS|4LW1op|NV=A75ffy}XQpyeL=y zG${+~CNsbxlXZ=|Xs%qyCGqi9SdhmjV(92OjZGbgMVrJSu4FL@w8k92UgB-EQYCn4$&6 zgqXT;5Rb>fPpctt(SHXh0w3N2i|q^l{7dU z4v|dH6pYC&0(56M&nk{_irqz)rEY~ox1W5?h00000 LNkvXXu0mjfyNN4+ literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/disk-24.png b/NBTExplorerMac/Resources/disk-24.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e67afa1739cf58b423c21cfa3d358bf910fb1c GIT binary patch literal 691 zcmV;k0!;mhP)`3HhU8cQ*t7M2zP5!6C$EF^`^T3T5pDNG1hoM07VI1qvs5rn(k z&g_iy=5{x?w|hs}jdMJ9c7D9?ecyXCdrWJM|JnEoe@V}K#x7Fl?~|jwDh|&-U1-PM zePeIAhGo!xyuPw3rNrX$LZyhmUpfNk9Ba$(p3}Pn3!s@00{wm;%19=aDrK~HBiQ|7 zd@=G#z8zvY-PY?4P3A!R_3 zh_V2VgT&8BBIFrJGZ~s>mm*-2n`4lZr~(5X`^W-lm19sApl0@_09q9@P;o_+X{wL` zvJCo%0)F#cDFE7g0x*TakKkwJ`)4MDvuGIxYJx$x+r?>bSjJdxtkda?WSU^$CIF5( zEZ6S0L3h*4imBDG^XWYHW8*f- zAjtuN2!y^dINLhFHiGrvIQX#k=+zc6(MCSbJsTlya_luc8cU4ci;`Tg*DbI_IJbk3 zphBKEMjzt&4sPAPfY#C`f4^~>b8ubWy)kX>4-UV5#is`ZFh^AvKiL`mTcK*8k{kXL ZU;ux7I(XqF4?O??002ovPDHLkV1o4HGl&2H literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/disk.png b/NBTExplorerMac/Resources/disk.png new file mode 100644 index 0000000000000000000000000000000000000000..c6194618205d9cd720a3655d12f9f1212e3ee582 GIT binary patch literal 507 zcmVJNRCwB?lfO&DP!Pv2FE5e~MV;&v z#8O>d>Y|Xp!@)ti=;Gj{;NalkR7D&_5C?H_c5^D~D4m3&?IfiRqJ`F4UXz@6uW3zD z+lqn9%a8kh-uLbj0}i< zehi9-nHuaaon*BGgn(C}lmd^+@qNE9z%)(ZT+)dUp!XC(5P%|atJUfYuqZf}bRz1& z^gK@kngakR1aL0tObrN7TQ=FcBJv=Buq<6B=|Vv0fFHhB6pT#ReF2=K0UZa?5{eg3 zL(M)Gi$zL+uM+b4JpA@y8HUllc3qdY?JYsF10K=*TJqZ@EUNqVpahQNK)GDjO(dO+ zI*{x@N(uFP6LQ&mEu34O>RRS^eAu=f_P}ogeDL%pg2uy1jfR3mBB7J{T8|FR9sqv_ zq_gx?uJIh6v3R(*d3^O!d95miI++8p9i3-UfWnVBYq>KH#aI&3=}DN)68yia#JS@b*;t))0;JS1o7y^MnidYDXRf1{6UGf)c@5B&)S8SN1Fg!5=-Fc=aR}d>rP=EUj{5HNldV{I%Jy=(#k`aPH6t__FKr5ir zm5MPQkMZTf%fy4)C7i2X)Z~WtvhYA2?eF7!wR++fF5kV0#-|ok`jnL>Rl0IN8)4Ax zLhNpAz}?&9XDd@9@{>gBNp?Hgf8NU&#00flHW(R-4`7M2!yy=t>QzujQq^Z$M@y(npEBz0^KK21S>;>KS=WV zylE$!&0^biYl(s&tsq745DAr-t+d;3K?=hyq+^(bj|k>Lf?f+s0rFDiX9JZVccw7= zDud?>BW7>+2vom?6hWduNM014$i)z6$8F3Pve3~uZBZ2bg}``VeCX*x7zXe?f52E< z&Vzv#Wah&PXcb8~V$b&md@(Kfexg88L6piUh)BL|o#X4LGaMe=;QQy_h(~N0FM|Z< z++JQ{bZl&33ha0J%`+^$o;0)Pe;tjG^|*!B^)=M#?k=hq7yN9U$cW@66?+m*CqCz0 zVu)ogBj@}3ryhFHGJ0gvBZUDY$W+&lb7=ytnK4DGlV ZU;qvT4wmIEe=`68002ovPDHLkV1h+M2+jZi literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/document-copy.png b/NBTExplorerMac/Resources/document-copy.png new file mode 100644 index 0000000000000000000000000000000000000000..3836257fe907a563afae4c447e0cad2a02ce0927 GIT binary patch literal 606 zcmV-k0-^nhP)eK^(>3%7-n|AZ{BBiR=rqUgi>lAz-rIIXo?H>qsx3K@q zhZRMUtljy%w6x*{0S27=d^w6^*tU&NYin=$Tv7YR(YpTxdh!v*er`gGGo@lSMl^^9 z0}L)N;kqvR{XV`fFR$?VGxkjuqm4bJQNSjO6bdD(Vp%xqbkN${L;Ls`@0v|KsMVTh z-R=kWyr%BuO)N2BY0YM>HNYglx%>0kS=47{GNdZ=BPIf~ z=!5lj^c-hICT3S&T^J;tJ6to0m|RPG>rc0P*Eu;kzdk+v-Z0)8AAkI+(U>zxY3?kE zZ0#Ea>dZYn{E}Xdq-qlrF(-2dsc0hWMAz==X=2bzW$I?%b-fIUisfF&*~kSG6H2f< s8yln6kl*)45ouUO7Z>LoM*j*h052ROJm1I;B>(^b07*qoM6N<$f`R`H!~g&Q literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/door.png b/NBTExplorerMac/Resources/door.png new file mode 100644 index 0000000000000000000000000000000000000000..f868d020b8943c0fe569475347cc47359d44fb3d GIT binary patch literal 503 zcmVKoEWYM2U$IE)WPI zQP3cz%>gJ<&`}{#QczHE0WN`%5DgLsprT4aV~GoJfiwsTh@gNN5K&P9&feBFVx6s44? z*Xufg+qE%{V;z^J4t(+z1bA+)R5tc&0a+3dmZBkY)$wALUS7A`)yw3#nAw2@rY7li zI)%z_UkNskF7Y0xc?ZU{fS`xms0s@(F{A2?9%1`zA3pgxZu7?@ly+c7QIiffRzvJ; zZ{r{ko_EI9`iX*k3hE6{=o9V3SE33jYdQNOqEI{Z+|oz>F>&}!2*8*3;-3)VBWbchKB$E002ovPDHLkV1h1K*oy!F literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/edit-code-b.png b/NBTExplorerMac/Resources/edit-code-b.png new file mode 100644 index 0000000000000000000000000000000000000000..8b29bdeb60f91d70a3beac10d096ba276de381d7 GIT binary patch literal 388 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`>?NMQuIzW1ghgdIl36nafkK=G z9+AZi4BSE>%y{W;-5;PJOS+@4BLl<6e(pbstPBi{!k#XUAr-fh6C~y}Oq^)Q)3IFf zCvm`lb7R^JWW@fJ-dqe(pm>opa1{= z$FogNaJnSJyyT9xsZ@yUmy z3MWkWIOye@m>VldbrzJ1)JYY%E%XssL?NNMyse+~11pme#)&ljc gkL+Dk*Bs<$Sf!s}${yU11`I9+Pgg&ebxsLQ02zae=Kufz literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/edit-code-i.png b/NBTExplorerMac/Resources/edit-code-i.png new file mode 100644 index 0000000000000000000000000000000000000000..87238dd2279324af625aa05670999973e41964fe GIT binary patch literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`>?NMQuIzW1ghdr)Qw)x}0EIXU zJR*x37`TN%nDNrxx<5ccmUKs7M+SzC{oH>NSs54@xjkJRLn>}1CrHd|m^jgpr(?O| z$K{PjIh~SY$#G)1z0Lu2`RSu;SG+U7fwnOLjsY>#D?G z|Ns9t$}v06@R3PDti4lI_1+B5BjyvYbU0rgTe~DWM4fd|QTE literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/edit-code.png b/NBTExplorerMac/Resources/edit-code.png new file mode 100644 index 0000000000000000000000000000000000000000..29bac66cfc485f9cc3bc6f3957e22b527212fe5d GIT binary patch literal 308 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 GUiBZ;`8Zkt literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/question-frame.png b/NBTExplorerMac/Resources/question-frame.png new file mode 100644 index 0000000000000000000000000000000000000000..4db0f0886eb8b90d99eed95fb9dd5d30755a2de7 GIT binary patch literal 925 zcmV;O17iG%P)g7?j~uI+Ny2R zMrvq-rnbJo`ob6Sg@SDr?N2c(s2_r;`1lbK_16y(6!AwWNb}K3TKo`1@r9MdiqWD? z6Jt%#*rcXOlTGv5O}(>1sCI~2%N?Jxk)=!xSFA5)lYxz-#oTt^-@PQ>2{V?`Px?LFQ~W z8w+J)dwcsqyWM{1(w!)Lk#guN>QGy2LUnaDawR?96X(U-I1cZ#t>8FLB9RFu!ppL3 zYG`QKv~Al~$Hm)GXy=%LYyme<&z*HUJ+9o%AQ%yF`EC@Kk8W{zypPnk1IY0UgnU=Ok?x%IE>{H1OiETJX0{6jrb6dv2Jf&3*)NkQ-mP^Rz3y8)h@jVhlW1WPqU6mLO7xCcvG*p}hVy2+jX0tgkE>BOzL?B5rQeqCV z$!U-dpb~KHghh$w>b-Gr8ojcXW_Yqy$Y5M1kmfiZi|Z++$pSrkIk>;6+jI8YpE}T0 z{Yz&Fl41*}nLwI(j|2i=d`qobq*FbK{0sKy-ERFvpoj6m_vU z27|$Fvo)_ddGf;U*4FjbS*3`fp*O)>x2``L9sTSPMe%t)pJxS=V*)JcEY0%?20;+2 zsQawcG&Qr^nWCJatOtw5Vv_zdgkOZ@Zvh4Xrbm;z$GN_}00000NkvXXu0mjf_aLjw literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/question-white.png b/NBTExplorerMac/Resources/question-white.png new file mode 100644 index 0000000000000000000000000000000000000000..f806468719539405a3f76885123e4ecb09cf3d1b GIT binary patch literal 761 zcmV?7A3KEJ$%9f&PJl8eND821JVDLIihG+y!Z@4+2UMgjAcB zHZe`4oxGcwOuXNXGgxuwg)@)uJLk;(4tJPFqXGZ3jCdKp6a|Z=1#Grf5Ji)hW!X7W zo+jx1%}Wq0tEw8VRx3$K+Jj=T0FlT3rh&EyA;7|ZXnfG(I5ltxI-JdRDy#Tb<0W4t zR=GkrK~h>eumeqO;;P|=iyq$F&O>vwI_-748Su2V!02(ovG`~sEU7AJCe%QdWv{A~ zLkodpe3z5OcQ||X!+}}v-spo9eKuGKbn@44#zTY?A>|~C%|f9#H#ux`bh!*vtSAc1 zo^Pi(GiZf;J`e9c@6aA{CQjNMs6j0?s8p)clcO$5sMqThGZS{08sWid-N!y;GCPn+ zBw%gr8;taeRHKies%)>f!%Xfq`gKXlL%Cdmk6()L@I@Mi2V8LZ!V!{u5ilCJ-9R?}1XOM0h;Sqd_)KHJX7aS`&%QvhT3DMua>; zGq}}fr|CVH+Xapj^+30>O^u#`$z)%C6O-`}0nZCM&dqOA{8%pFww6eMA1f}y(7{;1$Z0ha;VV_$h^s#A_ng~Rce`Cff9{I5nkPQQ{Xe!Qbc_3 zInQHlanR{vX}DY2Iz&Io5Q)jT?e&%5_t>qa z-P8&_t<->F7%fn@(=*lIJ#cNNwQa=Du-s9ax+<^l{dgbUj6Zmp-FW?#l+pyXzYTC4 r3xQc1?H>z&kP04N{83Q*OMn3Yq{|~z654_0@Jsyvq&1RMSBs~xa`1|_$;BvXZ$eMl5$s^w|{oBOr_3HV2UPU4i zU5I`fFtTQ!^L_CjgR7c`NkLG+p={I(g@Ou&Lb}uGyvWF!ea?dhpSqSoPLfZ8O+n(f zk>BU@>BVAEg~Q>+bULkAv!5_{$uK6Z8OjK<^r!s+L_ z#@5!)A4^NY-R0#0>D>@i@J`dlz6=e$Rq?ob($lkk6L`HhJ*^fb3T`bJHT#^CM?Q6} z|KNqD-D?-url!=K#HYa6Gg-knXY|`mS~@W>eN(EtzP+tBH#W-Su~^{o%*>lzVD z;Gq~WvSy!i^2n#Ib(gn+JFA0(MY`UX4Kdkx@}F18ntjg6BcHm~E%<=ZN#L?@23`S) zyTGF4vJ`ym4SsNf!vf1V5IGH8k~}*LJjyBcoI_{(lNU4%;hvH691@s~Xli?jUw;WO Y0K{B8%8@~yF8}}l07*qoM6N<$g8HpcV*mgE literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Resources/selection-input.png b/NBTExplorerMac/Resources/selection-input.png new file mode 100644 index 0000000000000000000000000000000000000000..18e2d70bf02d6672f10cd6aab857dc2ceab387eb GIT binary patch literal 265 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XR(rZQhE&{2`t$$4J+o`W#EF6}(v20oQ}(ubn0fHuX($bt zCBk$0u*XFH84JFssTc}a3;FU$Go0S+V0p$vsLo-JXvbboi32?{9WN@_HzqQEK9sj+ z*<<$I6Aw4c1GKwe=7jAZhck{TR}`D~JN#i*IKc3vNOL#y+v!Ju&Svm* L^>bP0l+XkKAdz9> literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/SearchWorker.cs b/NBTExplorerMac/SearchWorker.cs new file mode 100644 index 0000000..b424e79 --- /dev/null +++ b/NBTExplorerMac/SearchWorker.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using NBTExplorer.Model; + +namespace NBTExplorer +{ + internal class SearchState + { + public DataNode RootNode { get; set; } + public string SearchName { get; set; } + public string SearchValue { get; set; } + + public IEnumerator State { get; set; } + + public Action DiscoverCallback { get; set; } + public Action ProgressCallback { get; set; } + public Action CollapseCallback { get; set; } + public Action EndCallback { get; set; } + } + + internal class SearchWorker + { + private ContainerControl _sender; + private SearchState _state; + private bool _cancel; + private object _lock; + + public SearchWorker (SearchState state, ContainerControl sender) + { + _state = state; + _sender = sender; + _lock = new object(); + } + + public void Cancel () + { + lock (_lock) { + _cancel = true; + } + } + + public void Run () + { + if (_state.State == null) + _state.State = FindNode(_state.RootNode).GetEnumerator(); + + if (!_state.State.MoveNext()) + InvokeEndCallback(); + } + + private IEnumerable FindNode (DataNode node) + { + lock (_lock) { + if (_cancel) + yield break; + } + + if (node == null) + yield break; + + bool searchExpanded = false; + if (!node.IsExpanded) { + node.Expand(); + searchExpanded = true; + } + + TagDataNode tagNode = node as TagDataNode; + if (tagNode != null) { + bool mName = _state.SearchName == null; + bool mValue = _state.SearchValue == null; + + if (_state.SearchName != null) { + string tagName = node.NodeName; + if (tagName != null) + mName = tagName.Contains(_state.SearchName); + } + if (_state.SearchValue != null) { + string tagValue = node.NodeDisplay; + if (tagValue != null) + mValue = tagValue.Contains(_state.SearchValue); + } + + if (mName && mValue) { + InvokeDiscoverCallback(node); + yield return node; + } + } + + foreach (DataNode sub in node.Nodes) { + foreach (DataNode s in FindNode(sub)) + yield return s; + } + + if (searchExpanded) { + if (!node.IsModified) { + node.Collapse(); + InvokeCollapseCallback(node); + } + } + } + + private void InvokeDiscoverCallback (DataNode node) + { + if (_sender != null && _state.DiscoverCallback != null) + _sender.BeginInvoke(_state.DiscoverCallback, new object[] { node }); + } + + private void InvokeCollapseCallback (DataNode node) + { + if (_sender != null && _state.CollapseCallback != null) + _sender.BeginInvoke(_state.CollapseCallback, new object[] { node }); + } + + private void InvokeEndCallback () + { + if (_sender != null && _state.EndCallback != null) + _sender.BeginInvoke(_state.EndCallback, new object[] { null }); + } + } +} diff --git a/NBTExplorerMac/TagKey.cs b/NBTExplorerMac/TagKey.cs new file mode 100644 index 0000000..d9279f1 --- /dev/null +++ b/NBTExplorerMac/TagKey.cs @@ -0,0 +1,39 @@ +using System; +using Substrate.Nbt; + +namespace NBTExplorer +{ + public class TagKey : IComparable + { + public TagKey (string name, TagType type) + { + Name = name; + TagType = type; + } + + public string Name { get; set; } + public TagType TagType { get; set; } + + #region IComparer Members + + public int Compare (TagKey x, TagKey y) + { + int typeDiff = (int)x.TagType - (int)y.TagType; + if (typeDiff != 0) + return typeDiff; + + return String.Compare(x.Name, y.Name, true); + } + + #endregion + + #region IComparable Members + + public int CompareTo (TagKey other) + { + return Compare(this, other); + } + + #endregion + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/AssemblyInfo.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/AssemblyInfo.cs new file mode 100644 index 0000000..3d83c21 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/AssemblyInfo.cs @@ -0,0 +1,70 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Security.Permissions; +using System.Runtime.InteropServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("Be.Windows.Forms.HexBox")] +[assembly: AssemblyDescription("hex edit control (C# DOTNET)")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Be")] +[assembly: AssemblyProduct("Be.Windows.Forms.HexBox")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.4.7.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] + +//[assembly: AssemblyKeyFile("../../HexBox.snk")] +//[assembly: AssemblyKeyName("")] + +//[assembly:IsolatedStorageFilePermission(SecurityAction.RequestRefuse, UserQuota=1048576)] +//[assembly:SecurityPermission(SecurityAction.RequestRefuse, UnmanagedCode=true)] +//[assembly:FileIOPermission(SecurityAction.RequestOptional, Unrestricted=true)] + +[assembly:CLSCompliant(true)] + +[assembly:ComVisible(false)] \ No newline at end of file diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/BuiltInContextMenu.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/BuiltInContextMenu.cs new file mode 100644 index 0000000..a333075 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/BuiltInContextMenu.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.ComponentModel; +using System.Windows.Forms; + +namespace Be.Windows.Forms +{ + /// + /// Defines a build-in ContextMenuStrip manager for HexBox control to show Copy, Cut, Paste menu in contextmenu of the control. + /// + [TypeConverterAttribute(typeof(ExpandableObjectConverter))] + public sealed class BuiltInContextMenu : Component + { + /// + /// Contains the HexBox control. + /// + HexBox _hexBox; + /// + /// Contains the ContextMenuStrip control. + /// + ContextMenuStrip _contextMenuStrip; + /// + /// Contains the "Cut"-ToolStripMenuItem object. + /// + ToolStripMenuItem _cutToolStripMenuItem; + /// + /// Contains the "Copy"-ToolStripMenuItem object. + /// + ToolStripMenuItem _copyToolStripMenuItem; + /// + /// Contains the "Paste"-ToolStripMenuItem object. + /// + ToolStripMenuItem _pasteToolStripMenuItem; + /// + /// Contains the "Select All"-ToolStripMenuItem object. + /// + ToolStripMenuItem _selectAllToolStripMenuItem; + /// + /// Initializes a new instance of BuildInContextMenu class. + /// + /// the HexBox control + internal BuiltInContextMenu(HexBox hexBox) + { + _hexBox = hexBox; + _hexBox.ByteProviderChanged += new EventHandler(HexBox_ByteProviderChanged); + } + /// + /// If ByteProvider + /// + /// the sender object + /// the event data + void HexBox_ByteProviderChanged(object sender, EventArgs e) + { + CheckBuiltInContextMenu(); + } + /// + /// Assigns the ContextMenuStrip control to the HexBox control. + /// + void CheckBuiltInContextMenu() + { + if (Util.DesignMode) + return; + + if (this._contextMenuStrip == null) + { + ContextMenuStrip cms = new ContextMenuStrip(); + _cutToolStripMenuItem = new ToolStripMenuItem(CutMenuItemTextInternal, CutMenuItemImage, new EventHandler(CutMenuItem_Click)); + cms.Items.Add(_cutToolStripMenuItem); + _copyToolStripMenuItem = new ToolStripMenuItem(CopyMenuItemTextInternal, CopyMenuItemImage, new EventHandler(CopyMenuItem_Click)); + cms.Items.Add(_copyToolStripMenuItem); + _pasteToolStripMenuItem = new ToolStripMenuItem(PasteMenuItemTextInternal, PasteMenuItemImage, new EventHandler(PasteMenuItem_Click)); + cms.Items.Add(_pasteToolStripMenuItem); + + cms.Items.Add(new ToolStripSeparator()); + + _selectAllToolStripMenuItem = new ToolStripMenuItem(SelectAllMenuItemTextInternal, SelectAllMenuItemImage, new EventHandler(SelectAllMenuItem_Click)); + cms.Items.Add(_selectAllToolStripMenuItem); + cms.Opening += new CancelEventHandler(BuildInContextMenuStrip_Opening); + + _contextMenuStrip = cms; + } + + if (this._hexBox.ByteProvider == null && this._hexBox.ContextMenuStrip != null) + this._hexBox.ContextMenuStrip = null; + else if (this._hexBox.ByteProvider != null && this._hexBox.ContextMenuStrip == null) + this._hexBox.ContextMenuStrip = _contextMenuStrip; + } + /// + /// Before opening the ContextMenuStrip, we manage the availability of the items. + /// + /// the sender object + /// the event data + void BuildInContextMenuStrip_Opening(object sender, CancelEventArgs e) + { + _cutToolStripMenuItem.Enabled = this._hexBox.CanCut(); + _copyToolStripMenuItem.Enabled = this._hexBox.CanCopy(); + _pasteToolStripMenuItem.Enabled = this._hexBox.CanPaste(); + _selectAllToolStripMenuItem.Enabled = this._hexBox.CanSelectAll(); + } + /// + /// The handler for the "Cut"-Click event + /// + /// the sender object + /// the event data + void CutMenuItem_Click(object sender, EventArgs e) { this._hexBox.Cut(); } + /// + /// The handler for the "Copy"-Click event + /// + /// the sender object + /// the event data + void CopyMenuItem_Click(object sender, EventArgs e) { this._hexBox.Copy(); } + /// + /// The handler for the "Paste"-Click event + /// + /// the sender object + /// the event data + void PasteMenuItem_Click(object sender, EventArgs e) { this._hexBox.Paste(); } + /// + /// The handler for the "Select All"-Click event + /// + /// the sender object + /// the event data + void SelectAllMenuItem_Click(object sender, EventArgs e) { this._hexBox.SelectAll(); } + /// + /// Gets or sets the custom text of the "Copy" ContextMenuStrip item. + /// + [Category("BuiltIn-ContextMenu"), DefaultValue(null), Localizable(true)] + public string CopyMenuItemText + { + get { return _copyMenuItemText; } + set { _copyMenuItemText = value; } + } string _copyMenuItemText; + + /// + /// Gets or sets the custom text of the "Cut" ContextMenuStrip item. + /// + [Category("BuiltIn-ContextMenu"), DefaultValue(null), Localizable(true)] + public string CutMenuItemText + { + get { return _cutMenuItemText; } + set { _cutMenuItemText = value; } + } string _cutMenuItemText; + + /// + /// Gets or sets the custom text of the "Paste" ContextMenuStrip item. + /// + [Category("BuiltIn-ContextMenu"), DefaultValue(null), Localizable(true)] + public string PasteMenuItemText + { + get { return _pasteMenuItemText; } + set { _pasteMenuItemText = value; } + } string _pasteMenuItemText; + + /// + /// Gets or sets the custom text of the "Select All" ContextMenuStrip item. + /// + [Category("BuiltIn-ContextMenu"), DefaultValue(null), Localizable(true)] + public string SelectAllMenuItemText + { + get { return _selectAllMenuItemText; } + set { _selectAllMenuItemText = value; } + } string _selectAllMenuItemText = null; + + /// + /// Gets the text of the "Cut" ContextMenuStrip item. + /// + internal string CutMenuItemTextInternal { get { return !string.IsNullOrEmpty(CutMenuItemText) ? CutMenuItemText : "Cut"; } } + /// + /// Gets the text of the "Copy" ContextMenuStrip item. + /// + internal string CopyMenuItemTextInternal { get { return !string.IsNullOrEmpty(CopyMenuItemText) ? CopyMenuItemText : "Copy"; } } + /// + /// Gets the text of the "Paste" ContextMenuStrip item. + /// + internal string PasteMenuItemTextInternal { get { return !string.IsNullOrEmpty(PasteMenuItemText) ? PasteMenuItemText : "Paste"; } } + /// + /// Gets the text of the "Select All" ContextMenuStrip item. + /// + internal string SelectAllMenuItemTextInternal { get { return !string.IsNullOrEmpty(SelectAllMenuItemText) ? SelectAllMenuItemText : "SelectAll"; } } + + /// + /// Gets or sets the image of the "Cut" ContextMenuStrip item. + /// + [Category("BuiltIn-ContextMenu"), DefaultValue(null)] + public Image CutMenuItemImage + { + get { return _cutMenuItemImage; } + set { _cutMenuItemImage = value; } + } Image _cutMenuItemImage = null; + /// + /// Gets or sets the image of the "Copy" ContextMenuStrip item. + /// + [Category("BuiltIn-ContextMenu"), DefaultValue(null)] + public Image CopyMenuItemImage + { + get { return _copyMenuItemImage; } + set { _copyMenuItemImage = value; } + } Image _copyMenuItemImage = null; + /// + /// Gets or sets the image of the "Paste" ContextMenuStrip item. + /// + [Category("BuiltIn-ContextMenu"), DefaultValue(null)] + public Image PasteMenuItemImage + { + get { return _pasteMenuItemImage; } + set { _pasteMenuItemImage = value; } + } Image _pasteMenuItemImage = null; + /// + /// Gets or sets the image of the "Select All" ContextMenuStrip item. + /// + [Category("BuiltIn-ContextMenu"), DefaultValue(null)] + public Image SelectAllMenuItemImage + { + get { return _selectAllMenuItemImage; } + set { _selectAllMenuItemImage = value; } + } Image _selectAllMenuItemImage = null; + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/ByteCharConverters.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/ByteCharConverters.cs new file mode 100644 index 0000000..072753f --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/ByteCharConverters.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Be.Windows.Forms +{ + /// + /// The interface for objects that can translate between characters and bytes. + /// + public interface IByteCharConverter + { + /// + /// Returns the character to display for the byte passed across. + /// + /// + /// + char ToChar(byte b); + + /// + /// Returns the byte to use when the character passed across is entered during editing. + /// + /// + /// + byte ToByte(char c); + } + + /// + /// The default implementation. + /// + public class DefaultByteCharConverter : IByteCharConverter + { + /// + /// Returns the character to display for the byte passed across. + /// + /// + /// + public virtual char ToChar(byte b) + { + return b > 0x1F && !(b > 0x7E && b < 0xA0) ? (char)b : '.'; + } + + /// + /// Returns the byte to use for the character passed across. + /// + /// + /// + public virtual byte ToByte(char c) + { + return (byte)c; + } + + /// + /// Returns a description of the byte char provider. + /// + /// + public override string ToString() + { + return "Default"; + } + } + + /// + /// A byte char provider that can translate bytes encoded in codepage 500 EBCDIC + /// + public class EbcdicByteCharProvider : IByteCharConverter + { + /// + /// The IBM EBCDIC code page 500 encoding. Note that this is not always supported by .NET, + /// the underlying platform has to provide support for it. + /// + private Encoding _ebcdicEncoding = Encoding.GetEncoding(500); + + /// + /// Returns the EBCDIC character corresponding to the byte passed across. + /// + /// + /// + public virtual char ToChar(byte b) + { + string encoded = _ebcdicEncoding.GetString(new byte[] { b }); + return encoded.Length > 0 ? encoded[0] : '.'; + } + + /// + /// Returns the byte corresponding to the EBCDIC character passed across. + /// + /// + /// + public virtual byte ToByte(char c) + { + byte[] decoded = _ebcdicEncoding.GetBytes(new char[] { c }); + return decoded.Length > 0 ? decoded[0] : (byte)0; + } + + /// + /// Returns a description of the byte char provider. + /// + /// + public override string ToString() + { + return "EBCDIC (Code Page 500)"; + } + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/ByteCollection.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/ByteCollection.cs new file mode 100644 index 0000000..c7d2d37 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/ByteCollection.cs @@ -0,0 +1,127 @@ +using System; + +using System.Collections; + +namespace Be.Windows.Forms +{ + /// + /// Represents a collection of bytes. + /// + public class ByteCollection : CollectionBase + { + /// + /// Initializes a new instance of ByteCollection class. + /// + public ByteCollection() { } + + /// + /// Initializes a new instance of ByteCollection class. + /// + /// an array of bytes to add to collection + public ByteCollection(byte[] bs) + { AddRange(bs); } + + /// + /// Gets or sets the value of a byte + /// + public byte this[int index] + { + get { return (byte)List[index]; } + set { List[index] = value; } + } + + /// + /// Adds a byte into the collection. + /// + /// the byte to add + public void Add(byte b) + { List.Add(b); } + + /// + /// Adds a range of bytes to the collection. + /// + /// the bytes to add + public void AddRange(byte[] bs) + { InnerList.AddRange(bs); } + + /// + /// Removes a byte from the collection. + /// + /// the byte to remove + public void Remove(byte b) + { List.Remove(b); } + + /// + /// Removes a range of bytes from the collection. + /// + /// the index of the start byte + /// the count of the bytes to remove + public void RemoveRange(int index, int count) + { InnerList.RemoveRange(index, count); } + + /// + /// Inserts a range of bytes to the collection. + /// + /// the index of start byte + /// an array of bytes to insert + public void InsertRange(int index, byte[] bs) + { InnerList.InsertRange(index, bs); } + + /// + /// Gets all bytes in the array + /// + /// an array of bytes. + public byte[] GetBytes() + { + byte[] bytes = new byte[Count]; + InnerList.CopyTo(0, bytes, 0, bytes.Length); + return bytes; + } + + /// + /// Inserts a byte to the collection. + /// + /// the index + /// a byte to insert + public void Insert(int index, byte b) + { + InnerList.Insert(index, b); + } + + /// + /// Returns the index of the given byte. + /// + public int IndexOf(byte b) + { + return InnerList.IndexOf(b); + } + + /// + /// Returns true, if the byte exists in the collection. + /// + public bool Contains(byte b) + { + return InnerList.Contains(b); + } + + /// + /// Copies the content of the collection into the given array. + /// + public void CopyTo(byte[] bs, int index) + { + InnerList.CopyTo(bs, index); + } + + /// + /// Copies the content of the collection into an array. + /// + /// the array containing all bytes. + public byte[] ToArray() + { + byte[] data = new byte[this.Count]; + this.CopyTo(data, 0); + return data; + } + + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/BytePositionInfo.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/BytePositionInfo.cs new file mode 100644 index 0000000..9302376 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/BytePositionInfo.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Be.Windows.Forms +{ + /// + /// Represents a position in the HexBox control + /// + struct BytePositionInfo + { + public BytePositionInfo(long index, int characterPosition) + { + _index = index; + _characterPosition = characterPosition; + } + + public int CharacterPosition + { + get { return _characterPosition; } + } int _characterPosition; + + public long Index + { + get { return _index; } + } long _index; + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DataBlock.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DataBlock.cs new file mode 100644 index 0000000..e5ea58f --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DataBlock.cs @@ -0,0 +1,42 @@ +using System; + +namespace Be.Windows.Forms +{ + internal abstract class DataBlock + { + internal DataMap _map; + internal DataBlock _nextBlock; + internal DataBlock _previousBlock; + + public abstract long Length + { + get; + } + + public DataMap Map + { + get + { + return _map; + } + } + + public DataBlock NextBlock + { + get + { + return _nextBlock; + } + } + + public DataBlock PreviousBlock + { + get + { + return _previousBlock; + } + } + + public abstract void RemoveBytes(long position, long count); + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DataMap.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DataMap.cs new file mode 100644 index 0000000..2876b08 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DataMap.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections; +using System.Text; + +namespace Be.Windows.Forms +{ + internal class DataMap : ICollection, IEnumerable + { + readonly object _syncRoot = new object(); + internal int _count; + internal DataBlock _firstBlock; + internal int _version; + + public DataMap() + { + } + + public DataMap(IEnumerable collection) + { + if (collection == null) + { + throw new ArgumentNullException("collection"); + } + + foreach (DataBlock item in collection) + { + AddLast(item); + } + } + + public DataBlock FirstBlock + { + get + { + return _firstBlock; + } + } + + public void AddAfter(DataBlock block, DataBlock newBlock) + { + AddAfterInternal(block, newBlock); + } + + public void AddBefore(DataBlock block, DataBlock newBlock) + { + AddBeforeInternal(block, newBlock); + } + + public void AddFirst(DataBlock block) + { + if (_firstBlock == null) + { + AddBlockToEmptyMap(block); + } + else + { + AddBeforeInternal(_firstBlock, block); + } + } + + public void AddLast(DataBlock block) + { + if (_firstBlock == null) + { + AddBlockToEmptyMap(block); + } + else + { + AddAfterInternal(GetLastBlock(), block); + } + } + + public void Remove(DataBlock block) + { + RemoveInternal(block); + } + + public void RemoveFirst() + { + if (_firstBlock == null) + { + throw new InvalidOperationException("The collection is empty."); + } + RemoveInternal(_firstBlock); + } + + public void RemoveLast() + { + if (_firstBlock == null) + { + throw new InvalidOperationException("The collection is empty."); + } + RemoveInternal(GetLastBlock()); + } + + public DataBlock Replace(DataBlock block, DataBlock newBlock) + { + AddAfterInternal(block, newBlock); + RemoveInternal(block); + return newBlock; + } + + public void Clear() + { + DataBlock block = FirstBlock; + while (block != null) + { + DataBlock nextBlock = block.NextBlock; + InvalidateBlock(block); + block = nextBlock; + } + _firstBlock = null; + _count = 0; + _version++; + } + + void AddAfterInternal(DataBlock block, DataBlock newBlock) + { + newBlock._previousBlock = block; + newBlock._nextBlock = block._nextBlock; + newBlock._map = this; + + if (block._nextBlock != null) + { + block._nextBlock._previousBlock = newBlock; + } + block._nextBlock = newBlock; + + this._version++; + this._count++; + } + + void AddBeforeInternal(DataBlock block, DataBlock newBlock) + { + newBlock._nextBlock = block; + newBlock._previousBlock = block._previousBlock; + newBlock._map = this; + + if (block._previousBlock != null) + { + block._previousBlock._nextBlock = newBlock; + } + block._previousBlock = newBlock; + + if (_firstBlock == block) + { + _firstBlock = newBlock; + } + this._version++; + this._count++; + } + + void RemoveInternal(DataBlock block) + { + DataBlock previousBlock = block._previousBlock; + DataBlock nextBlock = block._nextBlock; + + if (previousBlock != null) + { + previousBlock._nextBlock = nextBlock; + } + + if (nextBlock != null) + { + nextBlock._previousBlock = previousBlock; + } + + if (_firstBlock == block) + { + _firstBlock = nextBlock; + } + + InvalidateBlock(block); + + _count--; + _version++; + } + + DataBlock GetLastBlock() + { + DataBlock lastBlock = null; + for (DataBlock block = FirstBlock; block != null; block = block.NextBlock) + { + lastBlock = block; + } + return lastBlock; + } + + void InvalidateBlock(DataBlock block) + { + block._map = null; + block._nextBlock = null; + block._previousBlock = null; + } + + void AddBlockToEmptyMap(DataBlock block) + { + block._map = this; + block._nextBlock = null; + block._previousBlock = null; + + _firstBlock = block; + _version++; + _count++; + } + + #region ICollection Members + public void CopyTo(Array array, int index) + { + DataBlock[] blockArray = array as DataBlock[]; + for (DataBlock block = FirstBlock; block != null; block = block.NextBlock) + { + blockArray[index++] = block; + } + } + + public int Count + { + get + { + return _count; + } + } + + public bool IsSynchronized + { + get + { + return false; + } + } + + public object SyncRoot + { + get + { + return _syncRoot; + } + } + #endregion + + #region IEnumerable Members + public IEnumerator GetEnumerator() + { + return new Enumerator(this); + } + #endregion + + #region Enumerator Nested Type + internal class Enumerator : IEnumerator, IDisposable + { + DataMap _map; + DataBlock _current; + int _index; + int _version; + + internal Enumerator(DataMap map) + { + _map = map; + _version = map._version; + _current = null; + _index = -1; + } + + object IEnumerator.Current + { + get + { + if (_index < 0 || _index > _map.Count) + { + throw new InvalidOperationException("Enumerator is positioned before the first element or after the last element of the collection."); + } + return _current; + } + } + + public bool MoveNext() + { + if (this._version != _map._version) + { + throw new InvalidOperationException("Collection was modified after the enumerator was instantiated."); + } + + if (_index >= _map.Count) + { + return false; + } + + if (++_index == 0) + { + _current = _map.FirstBlock; + } + else + { + _current = _current.NextBlock; + } + + return (_index < _map.Count); + } + + void IEnumerator.Reset() + { + if (this._version != this._map._version) + { + throw new InvalidOperationException("Collection was modified after the enumerator was instantiated."); + } + + this._index = -1; + this._current = null; + } + + public void Dispose() + { + } + } + #endregion + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DynamicByteProvider.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DynamicByteProvider.cs new file mode 100644 index 0000000..83d01ee --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DynamicByteProvider.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; + +namespace Be.Windows.Forms +{ + /// + /// Byte provider for a small amount of data. + /// + public class DynamicByteProvider : IByteProvider + { + /// + /// Contains information about changes. + /// + bool _hasChanges; + /// + /// Contains a byte collection. + /// + List _bytes; + + /// + /// Initializes a new instance of the DynamicByteProvider class. + /// + /// + public DynamicByteProvider(byte[] data) : this(new List(data)) + { + } + + /// + /// Initializes a new instance of the DynamicByteProvider class. + /// + /// + public DynamicByteProvider(List bytes) + { + _bytes = bytes; + } + + /// + /// Raises the Changed event. + /// + void OnChanged(EventArgs e) + { + _hasChanges = true; + + if(Changed != null) + Changed(this, e); + } + + /// + /// Raises the LengthChanged event. + /// + void OnLengthChanged(EventArgs e) + { + if(LengthChanged != null) + LengthChanged(this, e); + } + + /// + /// Gets the byte collection. + /// + public List Bytes + { + get { return _bytes; } + } + + #region IByteProvider Members + /// + /// True, when changes are done. + /// + public bool HasChanges() + { + return _hasChanges; + } + + /// + /// Applies changes. + /// + public void ApplyChanges() + { + _hasChanges = false; + } + + /// + /// Occurs, when the write buffer contains new changes. + /// + public event EventHandler Changed; + + /// + /// Occurs, when InsertBytes or DeleteBytes method is called. + /// + public event EventHandler LengthChanged; + + + /// + /// Reads a byte from the byte collection. + /// + /// the index of the byte to read + /// the byte + public byte ReadByte(long index) + { return _bytes[(int)index]; } + + /// + /// Write a byte into the byte collection. + /// + /// the index of the byte to write. + /// the byte + public void WriteByte(long index, byte value) + { + _bytes[(int)index] = value; + OnChanged(EventArgs.Empty); + } + + /// + /// Deletes bytes from the byte collection. + /// + /// the start index of the bytes to delete. + /// the length of bytes to delete. + public void DeleteBytes(long index, long length) + { + int internal_index = (int)Math.Max(0, index); + int internal_length = (int)Math.Min((int)Length, length); + _bytes.RemoveRange(internal_index, internal_length); + + OnLengthChanged(EventArgs.Empty); + OnChanged(EventArgs.Empty); + } + + /// + /// Inserts byte into the byte collection. + /// + /// the start index of the bytes in the byte collection + /// the byte array to insert + public void InsertBytes(long index, byte[] bs) + { + _bytes.InsertRange((int)index, bs); + + OnLengthChanged(EventArgs.Empty); + OnChanged(EventArgs.Empty); + } + + /// + /// Gets the length of the bytes in the byte collection. + /// + public long Length + { + get + { + return _bytes.Count; + } + } + + /// + /// Returns true + /// + public virtual bool SupportsWriteByte() + { + return true; + } + + /// + /// Returns true + /// + public virtual bool SupportsInsertBytes() + { + return true; + } + + /// + /// Returns true + /// + public virtual bool SupportsDeleteBytes() + { + return true; + } + #endregion + + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DynamicFileByteProvider.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DynamicFileByteProvider.cs new file mode 100644 index 0000000..a68e275 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/DynamicFileByteProvider.cs @@ -0,0 +1,569 @@ +using System; +using System.Text; +using System.IO; + +namespace Be.Windows.Forms +{ + /// + /// Implements a fully editable byte provider for file data of any size. + /// + /// + /// Only changes to the file are stored in memory with reads from the + /// original data occurring as required. + /// + public sealed class DynamicFileByteProvider : IByteProvider, IDisposable + { + const int COPY_BLOCK_SIZE = 4096; + + string _fileName; + Stream _stream; + DataMap _dataMap; + long _totalLength; + bool _readOnly; + + /// + /// Constructs a new instance. + /// + /// The name of the file from which bytes should be provided. + public DynamicFileByteProvider(string fileName) : this(fileName, false) { } + + /// + /// Constructs a new instance. + /// + /// The name of the file from which bytes should be provided. + /// True, opens the file in read-only mode. + public DynamicFileByteProvider(string fileName, bool readOnly) + { + _fileName = fileName; + + if (!readOnly) + { + _stream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); + } + else + { + _stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + } + + _readOnly = readOnly; + + ReInitialize(); + } + + /// + /// Constructs a new instance. + /// + /// the stream containing the data. + /// + /// The stream must supported seek operations. + /// + public DynamicFileByteProvider(Stream stream) + { + if (stream == null) + throw new ArgumentNullException("stream"); + if (!stream.CanSeek) + throw new ArgumentException("stream must supported seek operations(CanSeek)"); + + _stream = stream; + _readOnly = !stream.CanWrite; + ReInitialize(); + } + + #region IByteProvider Members + /// + /// See for more information. + /// + public event EventHandler LengthChanged; + + /// + /// See for more information. + /// + public event EventHandler Changed; + + /// + /// See for more information. + /// + public byte ReadByte(long index) + { + long blockOffset; + DataBlock block = GetDataBlock(index, out blockOffset); + FileDataBlock fileBlock = block as FileDataBlock; + if (fileBlock != null) + { + return ReadByteFromFile(fileBlock.FileOffset + index - blockOffset); + } + else + { + MemoryDataBlock memoryBlock = (MemoryDataBlock)block; + return memoryBlock.Data[index - blockOffset]; + } + } + + /// + /// See for more information. + /// + public void WriteByte(long index, byte value) + { + try + { + // Find the block affected. + long blockOffset; + DataBlock block = GetDataBlock(index, out blockOffset); + + // If the byte is already in a memory block, modify it. + MemoryDataBlock memoryBlock = block as MemoryDataBlock; + if (memoryBlock != null) + { + memoryBlock.Data[index - blockOffset] = value; + return; + } + + FileDataBlock fileBlock = (FileDataBlock)block; + + // If the byte changing is the first byte in the block and the previous block is a memory block, extend that. + if (blockOffset == index && block.PreviousBlock != null) + { + MemoryDataBlock previousMemoryBlock = block.PreviousBlock as MemoryDataBlock; + if (previousMemoryBlock != null) + { + previousMemoryBlock.AddByteToEnd(value); + fileBlock.RemoveBytesFromStart(1); + if (fileBlock.Length == 0) + { + _dataMap.Remove(fileBlock); + } + return; + } + } + + // If the byte changing is the last byte in the block and the next block is a memory block, extend that. + if (blockOffset + fileBlock.Length - 1 == index && block.NextBlock != null) + { + MemoryDataBlock nextMemoryBlock = block.NextBlock as MemoryDataBlock; + if (nextMemoryBlock != null) + { + nextMemoryBlock.AddByteToStart(value); + fileBlock.RemoveBytesFromEnd(1); + if (fileBlock.Length == 0) + { + _dataMap.Remove(fileBlock); + } + return; + } + } + + // Split the block into a prefix and a suffix and place a memory block in-between. + FileDataBlock prefixBlock = null; + if (index > blockOffset) + { + prefixBlock = new FileDataBlock(fileBlock.FileOffset, index - blockOffset); + } + + FileDataBlock suffixBlock = null; + if (index < blockOffset + fileBlock.Length - 1) + { + suffixBlock = new FileDataBlock( + fileBlock.FileOffset + index - blockOffset + 1, + fileBlock.Length - (index - blockOffset + 1)); + } + + block = _dataMap.Replace(block, new MemoryDataBlock(value)); + + if (prefixBlock != null) + { + _dataMap.AddBefore(block, prefixBlock); + } + + if (suffixBlock != null) + { + _dataMap.AddAfter(block, suffixBlock); + } + } + finally + { + OnChanged(EventArgs.Empty); + } + } + + /// + /// See for more information. + /// + public void InsertBytes(long index, byte[] bs) + { + try + { + // Find the block affected. + long blockOffset; + DataBlock block = GetDataBlock(index, out blockOffset); + + // If the insertion point is in a memory block, just insert it. + MemoryDataBlock memoryBlock = block as MemoryDataBlock; + if (memoryBlock != null) + { + memoryBlock.InsertBytes(index - blockOffset, bs); + return; + } + + FileDataBlock fileBlock = (FileDataBlock)block; + + // If the insertion point is at the start of a file block, and the previous block is a memory block, append it to that block. + if (blockOffset == index && block.PreviousBlock != null) + { + MemoryDataBlock previousMemoryBlock = block.PreviousBlock as MemoryDataBlock; + if (previousMemoryBlock != null) + { + previousMemoryBlock.InsertBytes(previousMemoryBlock.Length, bs); + return; + } + } + + // Split the block into a prefix and a suffix and place a memory block in-between. + FileDataBlock prefixBlock = null; + if (index > blockOffset) + { + prefixBlock = new FileDataBlock(fileBlock.FileOffset, index - blockOffset); + } + + FileDataBlock suffixBlock = null; + if (index < blockOffset + fileBlock.Length) + { + suffixBlock = new FileDataBlock( + fileBlock.FileOffset + index - blockOffset, + fileBlock.Length - (index - blockOffset)); + } + + block = _dataMap.Replace(block, new MemoryDataBlock(bs)); + + if (prefixBlock != null) + { + _dataMap.AddBefore(block, prefixBlock); + } + + if (suffixBlock != null) + { + _dataMap.AddAfter(block, suffixBlock); + } + } + finally + { + _totalLength += bs.Length; + OnLengthChanged(EventArgs.Empty); + OnChanged(EventArgs.Empty); + } + } + + /// + /// See for more information. + /// + public void DeleteBytes(long index, long length) + { + try + { + long bytesToDelete = length; + + // Find the first block affected. + long blockOffset; + DataBlock block = GetDataBlock(index, out blockOffset); + + // Truncate or remove each block as necessary. + while ((bytesToDelete > 0) && (block != null)) + { + long blockLength = block.Length; + DataBlock nextBlock = block.NextBlock; + + // Delete the appropriate section from the block (this may result in two blocks or a zero length block). + long count = Math.Min(bytesToDelete, blockLength - (index - blockOffset)); + block.RemoveBytes(index - blockOffset, count); + + if (block.Length == 0) + { + _dataMap.Remove(block); + if (_dataMap.FirstBlock == null) + { + _dataMap.AddFirst(new MemoryDataBlock(new byte[0])); + } + } + + bytesToDelete -= count; + blockOffset += block.Length; + block = (bytesToDelete > 0) ? nextBlock : null; + } + } + finally + { + _totalLength -= length; + OnLengthChanged(EventArgs.Empty); + OnChanged(EventArgs.Empty); + } + } + + /// + /// See for more information. + /// + public long Length + { + get + { + return _totalLength; + } + } + + /// + /// See for more information. + /// + public bool HasChanges() + { + if (_readOnly) + return false; + + if (_totalLength != _stream.Length) + { + return true; + } + + long offset = 0; + for (DataBlock block = _dataMap.FirstBlock; block != null; block = block.NextBlock) + { + FileDataBlock fileBlock = block as FileDataBlock; + if (fileBlock == null) + { + return true; + } + + if (fileBlock.FileOffset != offset) + { + return true; + } + + offset += fileBlock.Length; + } + return (offset != _stream.Length); + } + + /// + /// See for more information. + /// + public void ApplyChanges() + { + if (_readOnly) + throw new OperationCanceledException("File is in read-only mode"); + + // This method is implemented to efficiently save the changes to the same file stream opened for reading. + // Saving to a separate file would be a much simpler implementation. + + // Firstly, extend the file length (if necessary) to ensure that there is enough disk space. + if (_totalLength > _stream.Length) + { + _stream.SetLength(_totalLength); + } + + // Secondly, shift around any file sections that have moved. + long dataOffset = 0; + for (DataBlock block = _dataMap.FirstBlock; block != null; block = block.NextBlock) + { + FileDataBlock fileBlock = block as FileDataBlock; + if (fileBlock != null && fileBlock.FileOffset != dataOffset) + { + MoveFileBlock(fileBlock, dataOffset); + } + dataOffset += block.Length; + } + + // Next, write in-memory changes. + dataOffset = 0; + for (DataBlock block = _dataMap.FirstBlock; block != null; block = block.NextBlock) + { + MemoryDataBlock memoryBlock = block as MemoryDataBlock; + if (memoryBlock != null) + { + _stream.Position = dataOffset; + for (int memoryOffset = 0; memoryOffset < memoryBlock.Length; memoryOffset += COPY_BLOCK_SIZE) + { + _stream.Write(memoryBlock.Data, memoryOffset, (int)Math.Min(COPY_BLOCK_SIZE, memoryBlock.Length - memoryOffset)); + } + } + dataOffset += block.Length; + } + + // Finally, if the file has shortened, truncate the stream. + _stream.SetLength(_totalLength); + ReInitialize(); + } + + /// + /// See for more information. + /// + public bool SupportsWriteByte() + { + return !_readOnly; + } + + /// + /// See for more information. + /// + public bool SupportsInsertBytes() + { + return !_readOnly; + } + + /// + /// See for more information. + /// + public bool SupportsDeleteBytes() + { + return !_readOnly; + } + #endregion + + #region IDisposable Members + /// + /// See for more information. + /// + ~DynamicFileByteProvider() + { + Dispose(); + } + + /// + /// See for more information. + /// + public void Dispose() + { + if (_stream != null) + { + _stream.Close(); + _stream = null; + } + _fileName = null; + _dataMap = null; + GC.SuppressFinalize(this); + } + #endregion + + /// + /// Gets a value, if the file is opened in read-only mode. + /// + public bool ReadOnly + { + get { return _readOnly; } + } + + void OnLengthChanged(EventArgs e) + { + if (LengthChanged != null) + LengthChanged(this, e); + } + + void OnChanged(EventArgs e) + { + if (Changed != null) + { + Changed(this, e); + } + } + + DataBlock GetDataBlock(long findOffset, out long blockOffset) + { + if (findOffset < 0 || findOffset > _totalLength) + { + throw new ArgumentOutOfRangeException("findOffset"); + } + + // Iterate over the blocks until the block containing the required offset is encountered. + blockOffset = 0; + for (DataBlock block = _dataMap.FirstBlock; block != null; block = block.NextBlock) + { + if ((blockOffset <= findOffset && blockOffset + block.Length > findOffset) || block.NextBlock == null) + { + return block; + } + blockOffset += block.Length; + } + return null; + } + + FileDataBlock GetNextFileDataBlock(DataBlock block, long dataOffset, out long nextDataOffset) + { + // Iterate over the remaining blocks until a file block is encountered. + nextDataOffset = dataOffset + block.Length; + block = block.NextBlock; + while (block != null) + { + FileDataBlock fileBlock = block as FileDataBlock; + if (fileBlock != null) + { + return fileBlock; + } + nextDataOffset += block.Length; + block = block.NextBlock; + } + return null; + } + + byte ReadByteFromFile(long fileOffset) + { + // Move to the correct position and read the byte. + if (_stream.Position != fileOffset) + { + _stream.Position = fileOffset; + } + return (byte)_stream.ReadByte(); + } + + void MoveFileBlock(FileDataBlock fileBlock, long dataOffset) + { + // First, determine whether the next file block needs to move before this one. + long nextDataOffset; + FileDataBlock nextFileBlock = GetNextFileDataBlock(fileBlock, dataOffset, out nextDataOffset); + if (nextFileBlock != null && dataOffset + fileBlock.Length > nextFileBlock.FileOffset) + { + // The next block needs to move first, so do that now. + MoveFileBlock(nextFileBlock, nextDataOffset); + } + + // Now, move the block. + if (fileBlock.FileOffset > dataOffset) + { + // Move the section to earlier in the file stream (done in chunks starting at the beginning of the section). + byte[] buffer = new byte[COPY_BLOCK_SIZE]; + for (long relativeOffset = 0; relativeOffset < fileBlock.Length; relativeOffset += buffer.Length) + { + long readOffset = fileBlock.FileOffset + relativeOffset; + int bytesToRead = (int)Math.Min(buffer.Length, fileBlock.Length - relativeOffset); + _stream.Position = readOffset; + _stream.Read(buffer, 0, bytesToRead); + + long writeOffset = dataOffset + relativeOffset; + _stream.Position = writeOffset; + _stream.Write(buffer, 0, bytesToRead); + } + } + else + { + // Move the section to later in the file stream (done in chunks starting at the end of the section). + byte[] buffer = new byte[COPY_BLOCK_SIZE]; + for (long relativeOffset = 0; relativeOffset < fileBlock.Length; relativeOffset += buffer.Length) + { + int bytesToRead = (int)Math.Min(buffer.Length, fileBlock.Length - relativeOffset); + long readOffset = fileBlock.FileOffset + fileBlock.Length - relativeOffset - bytesToRead; + _stream.Position = readOffset; + _stream.Read(buffer, 0, bytesToRead); + + long writeOffset = dataOffset + fileBlock.Length - relativeOffset - bytesToRead; + _stream.Position = writeOffset; + _stream.Write(buffer, 0, bytesToRead); + } + } + + // This block now points to a different position in the file. + fileBlock.SetFileOffset(dataOffset); + } + + void ReInitialize() + { + _dataMap = new DataMap(); + _dataMap.AddFirst(new FileDataBlock(0, _stream.Length)); + _totalLength = _stream.Length; + } + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/FileByteProvider.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/FileByteProvider.cs new file mode 100644 index 0000000..c3f89c5 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/FileByteProvider.cs @@ -0,0 +1,271 @@ +using System; +using System.IO; +using System.Collections; + +namespace Be.Windows.Forms +{ + /// + /// Byte provider for (big) files. + /// + public class FileByteProvider : IByteProvider, IDisposable + { + #region WriteCollection class + /// + /// Represents the write buffer class + /// + class WriteCollection : DictionaryBase + { + /// + /// Gets or sets a byte in the collection + /// + public byte this[long index] + { + get { return (byte)this.Dictionary[index]; } + set { Dictionary[index] = value; } + } + + /// + /// Adds a byte into the collection + /// + /// the index of the byte + /// the value of the byte + public void Add(long index, byte value) + { Dictionary.Add(index, value); } + + /// + /// Determines if a byte with the given index exists. + /// + /// the index of the byte + /// true, if the is in the collection + public bool Contains(long index) + { return Dictionary.Contains(index); } + + } + #endregion + + /// + /// Occurs, when the write buffer contains new changes. + /// + public event EventHandler Changed; + + /// + /// Contains all changes + /// + WriteCollection _writes = new WriteCollection(); + + /// + /// Contains the file name. + /// + string _fileName; + /// + /// Contains the file stream. + /// + FileStream _fileStream; + /// + /// Read-only access. + /// + bool _readOnly; + + /// + /// Initializes a new instance of the FileByteProvider class. + /// + /// + public FileByteProvider(string fileName) + { + _fileName = fileName; + + try + { + // try to open in write mode + _fileStream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); + } + catch + { + // write mode failed, try to open in read-only and fileshare friendly mode. + try + { + _fileStream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + _readOnly = true; + } + catch + { + throw; + } + } + } + + /// + /// Terminates the instance of the FileByteProvider class. + /// + ~FileByteProvider() + { + Dispose(); + } + + /// + /// Raises the Changed event. + /// + /// Never used. + void OnChanged(EventArgs e) + { + if(Changed != null) + Changed(this, e); + } + + /// + /// Gets the name of the file the byte provider is using. + /// + public string FileName + { + get { return _fileName; } + } + + /// + /// Returns a value if there are some changes. + /// + /// true, if there are some changes + public bool HasChanges() + { + return (_writes.Count > 0); + } + + /// + /// Updates the file with all changes the write buffer contains. + /// + public void ApplyChanges() + { + if (this._readOnly) + { + throw new Exception("File is in read-only mode."); + } + + if(!HasChanges()) + return; + + IDictionaryEnumerator en = _writes.GetEnumerator(); + while(en.MoveNext()) + { + long index = (long)en.Key; + byte value = (byte)en.Value; + if(_fileStream.Position != index) + _fileStream.Position = index; + _fileStream.Write(new byte[] { value }, 0, 1); + } + _writes.Clear(); + } + + /// + /// Clears the write buffer and reject all changes made. + /// + public void RejectChanges() + { + _writes.Clear(); + } + + #region IByteProvider Members + /// + /// Never used. + /// + public event EventHandler LengthChanged; + + /// + /// Reads a byte from the file. + /// + /// the index of the byte to read + /// the byte + public byte ReadByte(long index) + { + if(_writes.Contains(index)) + return _writes[index]; + + if(_fileStream.Position != index) + _fileStream.Position = index; + + byte res = (byte)_fileStream.ReadByte(); + return res; + } + + /// + /// Gets the length of the file. + /// + public long Length + { + get + { + return _fileStream.Length; + } + } + + /// + /// Writes a byte into write buffer + /// + public void WriteByte(long index, byte value) + { + if(_writes.Contains(index)) + _writes[index] = value; + else + _writes.Add(index, value); + + OnChanged(EventArgs.Empty); + } + + /// + /// Not supported + /// + public void DeleteBytes(long index, long length) + { + throw new NotSupportedException("FileByteProvider.DeleteBytes"); + } + + /// + /// Not supported + /// + public void InsertBytes(long index, byte[] bs) + { + throw new NotSupportedException("FileByteProvider.InsertBytes"); + } + + /// + /// Returns true + /// + public bool SupportsWriteByte() + { + return !_readOnly; + } + + /// + /// Returns false + /// + public bool SupportsInsertBytes() + { + return false; + } + + /// + /// Returns false + /// + public bool SupportsDeleteBytes() + { + return false; + } + #endregion + + #region IDisposable Members + /// + /// Releases the file handle used by the FileByteProvider. + /// + public void Dispose() + { + if(_fileStream != null) + { + _fileName = null; + + _fileStream.Close(); + _fileStream = null; + } + + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/FileDataBlock.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/FileDataBlock.cs new file mode 100644 index 0000000..40e0b0e --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/FileDataBlock.cs @@ -0,0 +1,96 @@ +using System; + +namespace Be.Windows.Forms +{ + internal sealed class FileDataBlock : DataBlock + { + long _length; + long _fileOffset; + + public FileDataBlock(long fileOffset, long length) + { + _fileOffset = fileOffset; + _length = length; + } + + public long FileOffset + { + get + { + return _fileOffset; + } + } + + public override long Length + { + get + { + return _length; + } + } + + public void SetFileOffset(long value) + { + _fileOffset = value; + } + + public void RemoveBytesFromEnd(long count) + { + if (count > _length) + { + throw new ArgumentOutOfRangeException("count"); + } + + _length -= count; + } + + public void RemoveBytesFromStart(long count) + { + if (count > _length) + { + throw new ArgumentOutOfRangeException("count"); + } + + _fileOffset += count; + _length -= count; + } + + public override void RemoveBytes(long position, long count) + { + if (position > _length) + { + throw new ArgumentOutOfRangeException("position"); + } + + if (position + count > _length) + { + throw new ArgumentOutOfRangeException("count"); + } + + long prefixLength = position; + long prefixFileOffset = _fileOffset; + + long suffixLength = _length - count - prefixLength; + long suffixFileOffset = _fileOffset + position + count; + + if (prefixLength > 0 && suffixLength > 0) + { + _fileOffset = prefixFileOffset; + _length = prefixLength; + _map.AddAfter(this, new FileDataBlock(suffixFileOffset, suffixLength)); + return; + } + + if (prefixLength > 0) + { + _fileOffset = prefixFileOffset; + _length = prefixLength; + } + else + { + _fileOffset = suffixFileOffset; + _length = suffixLength; + } + } + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.bmp b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.bmp new file mode 100644 index 0000000000000000000000000000000000000000..02699d94a9489fc28aa5aec0e54495dc5947cbe1 GIT binary patch literal 246 zcmZ9FxeX&m7OY{6=-JxK z9UUgdNU(E>IVb6cMZ(NiEQTMkT_4d72~A2LD$G;FJc^P;QJSg}_wl~3c|E_sy#W>u BSi=AS literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.cs new file mode 100644 index 0000000..5767fef --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.cs @@ -0,0 +1,3701 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using System.ComponentModel; +using System.Security.Permissions; +using System.Windows.Forms.VisualStyles; +using System.Text; +using System.Collections.Generic; + +namespace Be.Windows.Forms +{ + /// + /// Represents a hex box control. + /// + [ToolboxBitmap(typeof(HexBox), "HexBox.bmp")] + public class HexBox : Control + { + #region IKeyInterpreter interface + /// + /// Defines a user input handler such as for mouse and keyboard input + /// + interface IKeyInterpreter + { + /// + /// Activates mouse events + /// + void Activate(); + /// + /// Deactivate mouse events + /// + void Deactivate(); + /// + /// Preprocesses WM_KEYUP window message. + /// + /// the Message object to process. + /// True, if the message was processed. + bool PreProcessWmKeyUp(ref Message m); + /// + /// Preprocesses WM_CHAR window message. + /// + /// the Message object to process. + /// True, if the message was processed. + bool PreProcessWmChar(ref Message m); + /// + /// Preprocesses WM_KEYDOWN window message. + /// + /// the Message object to process. + /// True, if the message was processed. + bool PreProcessWmKeyDown(ref Message m); + /// + /// Gives some information about where to place the caret. + /// + /// the index of the byte + /// the position where the caret is to place. + PointF GetCaretPointF(long byteIndex); + } + #endregion + + #region EmptyKeyInterpreter class + /// + /// Represents an empty input handler without any functionality. + /// If is set ByteProvider to null, then this interpreter is used. + /// + class EmptyKeyInterpreter : IKeyInterpreter + { + HexBox _hexBox; + + public EmptyKeyInterpreter(HexBox hexBox) + { + _hexBox = hexBox; + } + + #region IKeyInterpreter Members + public void Activate(){} + public void Deactivate(){} + + public bool PreProcessWmKeyUp(ref Message m) + { return _hexBox.BasePreProcessMessage(ref m); } + + public bool PreProcessWmChar(ref Message m) + { return _hexBox.BasePreProcessMessage(ref m); } + + public bool PreProcessWmKeyDown(ref Message m) + { return _hexBox.BasePreProcessMessage(ref m); } + + public PointF GetCaretPointF(long byteIndex) + { return new PointF (); } + + #endregion + } + #endregion + + #region KeyInterpreter class + /// + /// Handles user input such as mouse and keyboard input during hex view edit + /// + class KeyInterpreter : IKeyInterpreter + { + /// + /// Delegate for key-down processing. + /// + /// the message object contains key data information + /// True, if the message was processed + delegate bool MessageDelegate(ref Message m); + + #region Fields + /// + /// Contains the parent HexBox control + /// + protected HexBox _hexBox; + + /// + /// Contains True, if shift key is down + /// + protected bool _shiftDown; + /// + /// Contains True, if mouse is down + /// + bool _mouseDown; + /// + /// Contains the selection start position info + /// + BytePositionInfo _bpiStart; + /// + /// Contains the current mouse selection position info + /// + BytePositionInfo _bpi; + /// + /// Contains all message handlers of key interpreter key down message + /// + Dictionary _messageHandlers; + #endregion + + #region Ctors + public KeyInterpreter(HexBox hexBox) + { + _hexBox = hexBox; + } + #endregion + + #region Activate, Deactive methods + public virtual void Activate() + { + _hexBox.MouseDown += new MouseEventHandler(BeginMouseSelection); + _hexBox.MouseMove += new MouseEventHandler(UpdateMouseSelection); + _hexBox.MouseUp += new MouseEventHandler(EndMouseSelection); + } + + public virtual void Deactivate() + { + _hexBox.MouseDown -= new MouseEventHandler(BeginMouseSelection); + _hexBox.MouseMove -= new MouseEventHandler(UpdateMouseSelection); + _hexBox.MouseUp -= new MouseEventHandler(EndMouseSelection); + } + #endregion + + #region Mouse selection methods + void BeginMouseSelection(object sender, MouseEventArgs e) + { + System.Diagnostics.Debug.WriteLine("BeginMouseSelection()", "KeyInterpreter"); + + if (e.Button != MouseButtons.Left) + return; + + _mouseDown = true; + + if(!_shiftDown) + { + _bpiStart = new BytePositionInfo(_hexBox._bytePos, _hexBox._byteCharacterPos); + _hexBox.ReleaseSelection(); + } + else + { + UpdateMouseSelection(this, e); + } + } + + void UpdateMouseSelection(object sender, MouseEventArgs e) + { + if(!_mouseDown) + return; + + _bpi = GetBytePositionInfo(new Point(e.X, e.Y)); + long selEnd = _bpi.Index; + long realselStart; + long realselLength; + + if(selEnd < _bpiStart.Index) + { + realselStart = selEnd; + realselLength = _bpiStart.Index - selEnd; + } + else if(selEnd > _bpiStart.Index) + { + realselStart = _bpiStart.Index; + realselLength = selEnd - realselStart; + } + else + { + realselStart = _hexBox._bytePos; + realselLength = 0; + } + + if(realselStart != _hexBox._bytePos || realselLength != _hexBox._selectionLength) + { + _hexBox.InternalSelect(realselStart, realselLength); + _hexBox.ScrollByteIntoView(_bpi.Index); + } + } + + void EndMouseSelection(object sender, MouseEventArgs e) + { + _mouseDown = false; + } + #endregion + + #region PrePrcessWmKeyDown methods + public virtual bool PreProcessWmKeyDown(ref Message m) + { + System.Diagnostics.Debug.WriteLine("PreProcessWmKeyDown(ref Message m)", "KeyInterpreter"); + + Keys vc = (Keys)m.WParam.ToInt32(); + + Keys keyData = vc | Control.ModifierKeys; + + // detect whether key down event should be raised + var hasMessageHandler = this.MessageHandlers.ContainsKey(keyData); + if (hasMessageHandler && RaiseKeyDown(keyData)) + return true; + + MessageDelegate messageHandler = hasMessageHandler + ? this.MessageHandlers[keyData] + : messageHandler = new MessageDelegate(PreProcessWmKeyDown_Default); + + return messageHandler(ref m); + } + + protected bool PreProcessWmKeyDown_Default(ref Message m) + { + _hexBox.ScrollByteIntoView(); + return _hexBox.BasePreProcessMessage(ref m); + } + + protected bool RaiseKeyDown(Keys keyData) + { + KeyEventArgs e = new KeyEventArgs(keyData); + _hexBox.OnKeyDown(e); + return e.Handled; + } + + protected virtual bool PreProcessWmKeyDown_Left(ref Message m) + { + return PerformPosMoveLeft(); + } + + protected virtual bool PreProcessWmKeyDown_Up(ref Message m) + { + long pos = _hexBox._bytePos; + int cp = _hexBox._byteCharacterPos; + + if( !(pos == 0 && cp == 0) ) + { + pos = Math.Max(-1, pos-_hexBox._iHexMaxHBytes); + if(pos == -1) + return true; + + _hexBox.SetPosition(pos); + + if(pos < _hexBox._startByte) + { + _hexBox.PerformScrollLineUp(); + } + + _hexBox.UpdateCaret(); + _hexBox.Invalidate(); + } + + _hexBox.ScrollByteIntoView(); + _hexBox.ReleaseSelection(); + + return true; + } + + protected virtual bool PreProcessWmKeyDown_Right(ref Message m) + { + return PerformPosMoveRight(); + } + + protected virtual bool PreProcessWmKeyDown_Down(ref Message m) + { + long pos = _hexBox._bytePos; + int cp = _hexBox._byteCharacterPos; + + if(pos == _hexBox._byteProvider.Length && cp == 0) + return true; + + pos = Math.Min(_hexBox._byteProvider.Length, pos+_hexBox._iHexMaxHBytes); + + if(pos == _hexBox._byteProvider.Length) + cp = 0; + + _hexBox.SetPosition(pos, cp); + + if(pos > _hexBox._endByte-1) + { + _hexBox.PerformScrollLineDown(); + } + + _hexBox.UpdateCaret(); + _hexBox.ScrollByteIntoView(); + _hexBox.ReleaseSelection(); + _hexBox.Invalidate(); + + return true; + } + + protected virtual bool PreProcessWmKeyDown_PageUp(ref Message m) + { + long pos = _hexBox._bytePos; + int cp = _hexBox._byteCharacterPos; + + if(pos == 0 && cp == 0) + return true; + + pos = Math.Max(0, pos-_hexBox._iHexMaxBytes); + if(pos == 0) + return true; + + _hexBox.SetPosition(pos); + + if(pos < _hexBox._startByte) + { + _hexBox.PerformScrollPageUp(); + } + + _hexBox.ReleaseSelection(); + _hexBox.UpdateCaret(); + _hexBox.Invalidate(); + return true; + } + + protected virtual bool PreProcessWmKeyDown_PageDown(ref Message m) + { + long pos = _hexBox._bytePos; + int cp = _hexBox._byteCharacterPos; + + if(pos == _hexBox._byteProvider.Length && cp == 0) + return true; + + pos = Math.Min(_hexBox._byteProvider.Length, pos+_hexBox._iHexMaxBytes); + + if(pos == _hexBox._byteProvider.Length) + cp = 0; + + _hexBox.SetPosition(pos, cp); + + if(pos > _hexBox._endByte-1) + { + _hexBox.PerformScrollPageDown(); + } + + _hexBox.ReleaseSelection(); + _hexBox.UpdateCaret(); + _hexBox.Invalidate(); + + return true; + } + + protected virtual bool PreProcessWmKeyDown_ShiftLeft(ref Message m) + { + long pos = _hexBox._bytePos; + long sel = _hexBox._selectionLength; + + if(pos + sel < 1) + return true; + + if(pos+sel <= _bpiStart.Index) + { + if(pos == 0) + return true; + + pos--; + sel++; + } + else + { + sel = Math.Max(0, sel-1); + } + + _hexBox.ScrollByteIntoView(); + _hexBox.InternalSelect(pos, sel); + + return true; + } + + protected virtual bool PreProcessWmKeyDown_ShiftUp(ref Message m) + { + long pos = _hexBox._bytePos; + long sel = _hexBox._selectionLength; + + if(pos-_hexBox._iHexMaxHBytes < 0 && pos <= _bpiStart.Index) + return true; + + if(_bpiStart.Index >= pos+sel) + { + pos = pos - _hexBox._iHexMaxHBytes; + sel += _hexBox._iHexMaxHBytes; + _hexBox.InternalSelect(pos, sel); + _hexBox.ScrollByteIntoView(); + } + else + { + sel -= _hexBox._iHexMaxHBytes; + if(sel < 0) + { + pos = _bpiStart.Index + sel; + sel = -sel; + _hexBox.InternalSelect(pos, sel); + _hexBox.ScrollByteIntoView(); + } + else + { + sel -= _hexBox._iHexMaxHBytes; + _hexBox.InternalSelect(pos, sel); + _hexBox.ScrollByteIntoView(pos+sel); + } + } + + return true; + } + + protected virtual bool PreProcessWmKeyDown_ShiftRight(ref Message m) + { + long pos = _hexBox._bytePos; + long sel = _hexBox._selectionLength; + + if(pos+sel >= _hexBox._byteProvider.Length) + return true; + + if(_bpiStart.Index <= pos) + { + sel++; + _hexBox.InternalSelect(pos, sel); + _hexBox.ScrollByteIntoView(pos+sel); + } + else + { + pos++; + sel = Math.Max(0, sel-1); + _hexBox.InternalSelect(pos, sel); + _hexBox.ScrollByteIntoView(); + } + + return true; + } + + protected virtual bool PreProcessWmKeyDown_ShiftDown(ref Message m) + { + long pos = _hexBox._bytePos; + long sel = _hexBox._selectionLength; + + long max = _hexBox._byteProvider.Length; + + if(pos+sel+_hexBox._iHexMaxHBytes > max) + return true; + + if(_bpiStart.Index <= pos) + { + sel += _hexBox._iHexMaxHBytes; + _hexBox.InternalSelect(pos, sel); + _hexBox.ScrollByteIntoView(pos+sel); + } + else + { + sel -= _hexBox._iHexMaxHBytes; + if (sel < 0) + { + pos = _bpiStart.Index; + sel = -sel; + } + else + { + pos += _hexBox._iHexMaxHBytes; + //sel -= _hexBox._iHexMaxHBytes; + } + + _hexBox.InternalSelect(pos, sel); + _hexBox.ScrollByteIntoView(); + } + + return true; + } + + protected virtual bool PreProcessWmKeyDown_Tab(ref Message m) + { + if(_hexBox._stringViewVisible && _hexBox._keyInterpreter.GetType() == typeof(KeyInterpreter)) + { + _hexBox.ActivateStringKeyInterpreter(); + _hexBox.ScrollByteIntoView(); + _hexBox.ReleaseSelection(); + _hexBox.UpdateCaret(); + _hexBox.Invalidate(); + return true; + } + + if(_hexBox.Parent == null) return true; + _hexBox.Parent.SelectNextControl(_hexBox, true, true, true, true); + return true; + } + + protected virtual bool PreProcessWmKeyDown_ShiftTab(ref Message m) + { + if(_hexBox._keyInterpreter is StringKeyInterpreter) + { + _shiftDown = false; + _hexBox.ActivateKeyInterpreter(); + _hexBox.ScrollByteIntoView(); + _hexBox.ReleaseSelection(); + _hexBox.UpdateCaret(); + _hexBox.Invalidate(); + return true; + } + + if(_hexBox.Parent == null) return true; + _hexBox.Parent.SelectNextControl(_hexBox, false, true, true, true); + return true; + } + + protected virtual bool PreProcessWmKeyDown_Back(ref Message m) + { + if(!_hexBox._byteProvider.SupportsDeleteBytes()) + return true; + + if (_hexBox.ReadOnly) + return true; + + long pos = _hexBox._bytePos; + long sel = _hexBox._selectionLength; + int cp = _hexBox._byteCharacterPos; + + long startDelete = (cp == 0 && sel == 0) ? pos-1 : pos; + if(startDelete < 0 && sel < 1) + return true; + + long bytesToDelete = (sel > 0) ? sel : 1; + _hexBox._byteProvider.DeleteBytes(Math.Max(0, startDelete), bytesToDelete); + _hexBox.UpdateScrollSize(); + + if(sel == 0) + PerformPosMoveLeftByte(); + + _hexBox.ReleaseSelection(); + _hexBox.Invalidate(); + + return true; + } + + protected virtual bool PreProcessWmKeyDown_Delete(ref Message m) + { + if(!_hexBox._byteProvider.SupportsDeleteBytes()) + return true; + + if (_hexBox.ReadOnly) + return true; + + long pos = _hexBox._bytePos; + long sel = _hexBox._selectionLength; + + if(pos >= _hexBox._byteProvider.Length) + return true; + + long bytesToDelete = (sel > 0) ? sel : 1; + _hexBox._byteProvider.DeleteBytes(pos, bytesToDelete); + + _hexBox.UpdateScrollSize(); + _hexBox.ReleaseSelection(); + _hexBox.Invalidate(); + + return true; + } + + protected virtual bool PreProcessWmKeyDown_Home(ref Message m) + { + long pos = _hexBox._bytePos; + int cp = _hexBox._byteCharacterPos; + + if(pos < 1) + return true; + + pos = 0; + cp = 0; + _hexBox.SetPosition(pos, cp); + + _hexBox.ScrollByteIntoView(); + _hexBox.UpdateCaret(); + _hexBox.ReleaseSelection(); + + return true; + } + + protected virtual bool PreProcessWmKeyDown_End(ref Message m) + { + long pos = _hexBox._bytePos; + int cp = _hexBox._byteCharacterPos; + + if(pos >= _hexBox._byteProvider.Length-1) + return true; + + pos = _hexBox._byteProvider.Length; + cp = 0; + _hexBox.SetPosition(pos, cp); + + _hexBox.ScrollByteIntoView(); + _hexBox.UpdateCaret(); + _hexBox.ReleaseSelection(); + + return true; + } + + protected virtual bool PreProcessWmKeyDown_ShiftShiftKey(ref Message m) + { + if(_mouseDown) + return true; + if(_shiftDown) + return true; + + _shiftDown = true; + + if(_hexBox._selectionLength > 0) + return true; + + _bpiStart = new BytePositionInfo(_hexBox._bytePos, _hexBox._byteCharacterPos); + + return true; + } + + protected virtual bool PreProcessWmKeyDown_ControlC(ref Message m) + { + _hexBox.Copy(); + return true; + } + + protected virtual bool PreProcessWmKeyDown_ControlX(ref Message m) + { + _hexBox.Cut(); + return true; + } + + protected virtual bool PreProcessWmKeyDown_ControlV(ref Message m) + { + _hexBox.Paste(); + return true; + } + + #endregion + + #region PreProcessWmChar methods + public virtual bool PreProcessWmChar(ref Message m) + { + if(Control.ModifierKeys == Keys.Control) + { + return _hexBox.BasePreProcessMessage(ref m); + } + + bool sw = _hexBox._byteProvider.SupportsWriteByte(); + bool si = _hexBox._byteProvider.SupportsInsertBytes(); + bool sd = _hexBox._byteProvider.SupportsDeleteBytes(); + + long pos = _hexBox._bytePos; + long sel = _hexBox._selectionLength; + int cp = _hexBox._byteCharacterPos; + + if( + (!sw && pos != _hexBox._byteProvider.Length) || + (!si && pos == _hexBox._byteProvider.Length)) + { + return _hexBox.BasePreProcessMessage(ref m); + } + + char c = (char)m.WParam.ToInt32(); + + if(Uri.IsHexDigit(c)) + { + if(RaiseKeyPress(c)) + return true; + + if(_hexBox.ReadOnly) + return true; + + bool isInsertMode = (pos == _hexBox._byteProvider.Length); + + // do insert when insertActive = true + if(!isInsertMode && si && _hexBox.InsertActive && cp == 0) + isInsertMode = true; + + if(sd && si && sel > 0) + { + _hexBox._byteProvider.DeleteBytes(pos, sel); + isInsertMode = true; + cp = 0; + _hexBox.SetPosition(pos, cp); + } + + _hexBox.ReleaseSelection(); + + byte currentByte; + if(isInsertMode) + currentByte = 0; + else + currentByte = _hexBox._byteProvider.ReadByte(pos); + + string sCb = currentByte.ToString("X", System.Threading.Thread.CurrentThread.CurrentCulture); + if(sCb.Length == 1) + sCb = "0" + sCb; + + string sNewCb = c.ToString(); + if(cp == 0) + sNewCb += sCb.Substring(1, 1); + else + sNewCb = sCb.Substring(0, 1) + sNewCb; + byte newcb = byte.Parse(sNewCb, System.Globalization.NumberStyles.AllowHexSpecifier, System.Threading.Thread.CurrentThread.CurrentCulture); + + if(isInsertMode) + _hexBox._byteProvider.InsertBytes(pos, new byte[]{newcb}); + else + _hexBox._byteProvider.WriteByte(pos, newcb); + + PerformPosMoveRight(); + + _hexBox.Invalidate(); + return true; + } + else + { + return _hexBox.BasePreProcessMessage(ref m); + } + } + + protected bool RaiseKeyPress(char keyChar) + { + KeyPressEventArgs e = new KeyPressEventArgs(keyChar); + _hexBox.OnKeyPress(e); + return e.Handled; + } + #endregion + + #region PreProcessWmKeyUp methods + public virtual bool PreProcessWmKeyUp(ref Message m) + { + System.Diagnostics.Debug.WriteLine("PreProcessWmKeyUp(ref Message m)", "KeyInterpreter"); + + Keys vc = (Keys)m.WParam.ToInt32(); + + Keys keyData = vc | Control.ModifierKeys; + + switch(keyData) + { + case Keys.ShiftKey: + case Keys.Insert: + if(RaiseKeyUp(keyData)) + return true; + break; + } + + switch(keyData) + { + case Keys.ShiftKey: + _shiftDown = false; + return true; + case Keys.Insert: + return PreProcessWmKeyUp_Insert(ref m); + default: + return _hexBox.BasePreProcessMessage(ref m); + } + } + + protected virtual bool PreProcessWmKeyUp_Insert(ref Message m) + { + _hexBox.InsertActive = !_hexBox.InsertActive; + return true; + } + + protected bool RaiseKeyUp(Keys keyData) + { + KeyEventArgs e = new KeyEventArgs(keyData); + _hexBox.OnKeyUp(e); + return e.Handled; + } + #endregion + + #region Misc + Dictionary MessageHandlers + { + get + { + if (_messageHandlers == null) + { + _messageHandlers = new Dictionary(); + _messageHandlers.Add(Keys.Left, new MessageDelegate(PreProcessWmKeyDown_Left)); // move left + _messageHandlers.Add(Keys.Up, new MessageDelegate(PreProcessWmKeyDown_Up)); // move up + _messageHandlers.Add(Keys.Right, new MessageDelegate(PreProcessWmKeyDown_Right)); // move right + _messageHandlers.Add(Keys.Down, new MessageDelegate(PreProcessWmKeyDown_Down)); // move down + _messageHandlers.Add(Keys.PageUp, new MessageDelegate(PreProcessWmKeyDown_PageUp)); // move pageup + _messageHandlers.Add(Keys.PageDown, new MessageDelegate(PreProcessWmKeyDown_PageDown)); // move page down + _messageHandlers.Add(Keys.Left | Keys.Shift, new MessageDelegate(PreProcessWmKeyDown_ShiftLeft)); // move left with selection + _messageHandlers.Add(Keys.Up | Keys.Shift, new MessageDelegate(PreProcessWmKeyDown_ShiftUp)); // move up with selection + _messageHandlers.Add(Keys.Right | Keys.Shift, new MessageDelegate(PreProcessWmKeyDown_ShiftRight)); // move right with selection + _messageHandlers.Add(Keys.Down | Keys.Shift, new MessageDelegate(PreProcessWmKeyDown_ShiftDown)); // move down with selection + _messageHandlers.Add(Keys.Tab, new MessageDelegate(PreProcessWmKeyDown_Tab)); // switch to string view + _messageHandlers.Add(Keys.Back, new MessageDelegate(PreProcessWmKeyDown_Back)); // back + _messageHandlers.Add(Keys.Delete, new MessageDelegate(PreProcessWmKeyDown_Delete)); // delete + _messageHandlers.Add(Keys.Home, new MessageDelegate(PreProcessWmKeyDown_Home)); // move to home + _messageHandlers.Add(Keys.End, new MessageDelegate(PreProcessWmKeyDown_End)); // move to end + _messageHandlers.Add(Keys.ShiftKey | Keys.Shift, new MessageDelegate(PreProcessWmKeyDown_ShiftShiftKey)); // begin selection process + _messageHandlers.Add(Keys.C | Keys.Control, new MessageDelegate(PreProcessWmKeyDown_ControlC)); // copy + _messageHandlers.Add(Keys.X | Keys.Control, new MessageDelegate(PreProcessWmKeyDown_ControlX)); // cut + _messageHandlers.Add(Keys.V | Keys.Control, new MessageDelegate(PreProcessWmKeyDown_ControlV)); // paste + } + return _messageHandlers; + } + } + + protected virtual bool PerformPosMoveLeft() + { + long pos = _hexBox._bytePos; + long sel = _hexBox._selectionLength; + int cp = _hexBox._byteCharacterPos; + + if(sel != 0) + { + cp = 0; + _hexBox.SetPosition(pos, cp); + _hexBox.ReleaseSelection(); + } + else + { + if(pos == 0 && cp == 0) + return true; + + if(cp > 0) + { + cp--; + } + else + { + pos = Math.Max(0, pos-1); + cp++; + } + + _hexBox.SetPosition(pos, cp); + + if(pos < _hexBox._startByte) + { + _hexBox.PerformScrollLineUp(); + } + _hexBox.UpdateCaret(); + _hexBox.Invalidate(); + } + + _hexBox.ScrollByteIntoView(); + return true; + } + protected virtual bool PerformPosMoveRight() + { + long pos = _hexBox._bytePos; + int cp = _hexBox._byteCharacterPos; + long sel = _hexBox._selectionLength; + + if(sel != 0) + { + pos += sel; + cp = 0; + _hexBox.SetPosition(pos, cp); + _hexBox.ReleaseSelection(); + } + else + { + if( !(pos == _hexBox._byteProvider.Length && cp == 0) ) + { + + if(cp > 0) + { + pos = Math.Min(_hexBox._byteProvider.Length, pos+1); + cp = 0; + } + else + { + cp++; + } + + _hexBox.SetPosition(pos, cp); + + if(pos > _hexBox._endByte-1) + { + _hexBox.PerformScrollLineDown(); + } + _hexBox.UpdateCaret(); + _hexBox.Invalidate(); + } + } + + _hexBox.ScrollByteIntoView(); + return true; + } + protected virtual bool PerformPosMoveLeftByte() + { + long pos = _hexBox._bytePos; + int cp = _hexBox._byteCharacterPos; + + if(pos == 0) + return true; + + pos = Math.Max(0, pos-1); + cp = 0; + + _hexBox.SetPosition(pos, cp); + + if(pos < _hexBox._startByte) + { + _hexBox.PerformScrollLineUp(); + } + _hexBox.UpdateCaret(); + _hexBox.ScrollByteIntoView(); + _hexBox.Invalidate(); + + return true; + } + + protected virtual bool PerformPosMoveRightByte() + { + long pos = _hexBox._bytePos; + int cp = _hexBox._byteCharacterPos; + + if(pos == _hexBox._byteProvider.Length) + return true; + + pos = Math.Min(_hexBox._byteProvider.Length, pos+1); + cp = 0; + + _hexBox.SetPosition(pos, cp); + + if(pos > _hexBox._endByte-1) + { + _hexBox.PerformScrollLineDown(); + } + _hexBox.UpdateCaret(); + _hexBox.ScrollByteIntoView(); + _hexBox.Invalidate(); + + return true; + } + + + public virtual PointF GetCaretPointF(long byteIndex) + { + System.Diagnostics.Debug.WriteLine("GetCaretPointF()", "KeyInterpreter"); + + return _hexBox.GetBytePointF(byteIndex); + } + + protected virtual BytePositionInfo GetBytePositionInfo(Point p) + { + return _hexBox.GetHexBytePositionInfo(p); + } + #endregion + } + #endregion + + #region StringKeyInterpreter class + /// + /// Handles user input such as mouse and keyboard input during string view edit + /// + class StringKeyInterpreter : KeyInterpreter + { + #region Ctors + public StringKeyInterpreter(HexBox hexBox) : base(hexBox) + { + _hexBox._byteCharacterPos = 0; + } + #endregion + + #region PreProcessWmKeyDown methods + public override bool PreProcessWmKeyDown(ref Message m) + { + Keys vc = (Keys)m.WParam.ToInt32(); + + Keys keyData = vc | Control.ModifierKeys; + + switch(keyData) + { + case Keys.Tab | Keys.Shift: + case Keys.Tab: + if(RaiseKeyDown(keyData)) + return true; + break; + } + + switch(keyData) + { + case Keys.Tab | Keys.Shift: + return PreProcessWmKeyDown_ShiftTab(ref m); + case Keys.Tab: + return PreProcessWmKeyDown_Tab(ref m); + default: + return base.PreProcessWmKeyDown(ref m); + } + } + + protected override bool PreProcessWmKeyDown_Left(ref Message m) + { + return PerformPosMoveLeftByte(); + } + + protected override bool PreProcessWmKeyDown_Right(ref Message m) + { + return PerformPosMoveRightByte(); + } + + #endregion + + #region PreProcessWmChar methods + public override bool PreProcessWmChar(ref Message m) + { + if(Control.ModifierKeys == Keys.Control) + { + return _hexBox.BasePreProcessMessage(ref m); + } + + bool sw = _hexBox._byteProvider.SupportsWriteByte(); + bool si = _hexBox._byteProvider.SupportsInsertBytes(); + bool sd = _hexBox._byteProvider.SupportsDeleteBytes(); + + long pos = _hexBox._bytePos; + long sel = _hexBox._selectionLength; + int cp = _hexBox._byteCharacterPos; + + if( + (!sw && pos != _hexBox._byteProvider.Length) || + (!si && pos == _hexBox._byteProvider.Length)) + { + return _hexBox.BasePreProcessMessage(ref m); + } + + char c = (char)m.WParam.ToInt32(); + + if(RaiseKeyPress(c)) + return true; + + if(_hexBox.ReadOnly) + return true; + + bool isInsertMode = (pos == _hexBox._byteProvider.Length); + + // do insert when insertActive = true + if(!isInsertMode && si && _hexBox.InsertActive) + isInsertMode = true; + + if(sd && si && sel > 0) + { + _hexBox._byteProvider.DeleteBytes(pos, sel); + isInsertMode = true; + cp = 0; + _hexBox.SetPosition(pos, cp); + } + + _hexBox.ReleaseSelection(); + + byte b = _hexBox.ByteCharConverter.ToByte(c); + if(isInsertMode) + _hexBox._byteProvider.InsertBytes(pos, new byte[]{b}); + else + _hexBox._byteProvider.WriteByte(pos, b); + + PerformPosMoveRightByte(); + _hexBox.Invalidate(); + + return true; + } + #endregion + + #region Misc + public override PointF GetCaretPointF(long byteIndex) + { + System.Diagnostics.Debug.WriteLine("GetCaretPointF()", "StringKeyInterpreter"); + + Point gp = _hexBox.GetGridBytePoint(byteIndex); + return _hexBox.GetByteStringPointF(gp); + } + + protected override BytePositionInfo GetBytePositionInfo(Point p) + { + return _hexBox.GetStringBytePositionInfo(p); + } + #endregion + } + #endregion + + #region Fields + /// + /// Contains the hole content bounds of all text + /// + Rectangle _recContent; + /// + /// Contains the line info bounds + /// + Rectangle _recLineInfo; + /// + /// Contains the hex data bounds + /// + Rectangle _recHex; + /// + /// Contains the string view bounds + /// + Rectangle _recStringView; + + /// + /// Contains string format information for text drawing + /// + StringFormat _stringFormat; + /// + /// Contains the width and height of a single char + /// + SizeF _charSize; + + /// + /// Contains the maximum of visible horizontal bytes + /// + int _iHexMaxHBytes; + /// + /// Contains the maximum of visible vertical bytes + /// + int _iHexMaxVBytes; + /// + /// Contains the maximum of visible bytes. + /// + int _iHexMaxBytes; + + /// + /// Contains the scroll bars minimum value + /// + long _scrollVmin; + /// + /// Contains the scroll bars maximum value + /// + long _scrollVmax; + /// + /// Contains the scroll bars current position + /// + long _scrollVpos; + /// + /// Contains a vertical scroll + /// + VScrollBar _vScrollBar; + /// + /// Contains a timer for thumbtrack scrolling + /// + Timer _thumbTrackTimer = new Timer(); + /// + /// Contains the thumbtrack scrolling position + /// + long _thumbTrackPosition; + /// + /// Contains the thumptrack delay for scrolling in milliseconds. + /// + const int THUMPTRACKDELAY = 50; + /// + /// Contains the Enviroment.TickCount of the last refresh + /// + int _lastThumbtrack; + /// + /// Contains the border´s left shift + /// + int _recBorderLeft = SystemInformation.Border3DSize.Width; + /// + /// Contains the border´s right shift + /// + int _recBorderRight = SystemInformation.Border3DSize.Width; + /// + /// Contains the border´s top shift + /// + int _recBorderTop = SystemInformation.Border3DSize.Height; + /// + /// Contains the border bottom shift + /// + int _recBorderBottom = SystemInformation.Border3DSize.Height; + + /// + /// Contains the index of the first visible byte + /// + long _startByte; + /// + /// Contains the index of the last visible byte + /// + long _endByte; + + /// + /// Contains the current byte position + /// + long _bytePos = -1; + /// + /// Contains the current char position in one byte + /// + /// + /// "1A" + /// "1" = char position of 0 + /// "A" = char position of 1 + /// + int _byteCharacterPos; + + /// + /// Contains string format information for hex values + /// + string _hexStringFormat = "X"; + + + /// + /// Contains the current key interpreter + /// + IKeyInterpreter _keyInterpreter; + /// + /// Contains an empty key interpreter without functionality + /// + EmptyKeyInterpreter _eki; + /// + /// Contains the default key interpreter + /// + KeyInterpreter _ki; + /// + /// Contains the string key interpreter + /// + StringKeyInterpreter _ski; + + /// + /// Contains True if caret is visible + /// + bool _caretVisible; + + /// + /// Contains true, if the find (Find method) should be aborted. + /// + bool _abortFind; + /// + /// Contains a value of the current finding position. + /// + long _findingPos; + + /// + /// Contains a state value about Insert or Write mode. When this value is true and the ByteProvider SupportsInsert is true bytes are inserted instead of overridden. + /// + bool _insertActive; + #endregion + + #region Events + /// + /// Occurs, when the value of InsertActive property has changed. + /// + [Description("Occurs, when the value of InsertActive property has changed.")] + public event EventHandler InsertActiveChanged; + /// + /// Occurs, when the value of ReadOnly property has changed. + /// + [Description("Occurs, when the value of ReadOnly property has changed.")] + public event EventHandler ReadOnlyChanged; + /// + /// Occurs, when the value of ByteProvider property has changed. + /// + [Description("Occurs, when the value of ByteProvider property has changed.")] + public event EventHandler ByteProviderChanged; + /// + /// Occurs, when the value of SelectionStart property has changed. + /// + [Description("Occurs, when the value of SelectionStart property has changed.")] + public event EventHandler SelectionStartChanged; + /// + /// Occurs, when the value of SelectionLength property has changed. + /// + [Description("Occurs, when the value of SelectionLength property has changed.")] + public event EventHandler SelectionLengthChanged; + /// + /// Occurs, when the value of LineInfoVisible property has changed. + /// + [Description("Occurs, when the value of LineInfoVisible property has changed.")] + public event EventHandler LineInfoVisibleChanged; + /// + /// Occurs, when the value of StringViewVisible property has changed. + /// + [Description("Occurs, when the value of StringViewVisible property has changed.")] + public event EventHandler StringViewVisibleChanged; + /// + /// Occurs, when the value of BorderStyle property has changed. + /// + [Description("Occurs, when the value of BorderStyle property has changed.")] + public event EventHandler BorderStyleChanged; + /// + /// Occurs, when the value of BytesPerLine property has changed. + /// + [Description("Occurs, when the value of BytesPerLine property has changed.")] + public event EventHandler BytesPerLineChanged; + /// + /// Occurs, when the value of UseFixedBytesPerLine property has changed. + /// + [Description("Occurs, when the value of UseFixedBytesPerLine property has changed.")] + public event EventHandler UseFixedBytesPerLineChanged; + /// + /// Occurs, when the value of VScrollBarVisible property has changed. + /// + [Description("Occurs, when the value of VScrollBarVisible property has changed.")] + public event EventHandler VScrollBarVisibleChanged; + /// + /// Occurs, when the value of HexCasing property has changed. + /// + [Description("Occurs, when the value of HexCasing property has changed.")] + public event EventHandler HexCasingChanged; + /// + /// Occurs, when the value of HorizontalByteCount property has changed. + /// + [Description("Occurs, when the value of HorizontalByteCount property has changed.")] + public event EventHandler HorizontalByteCountChanged; + /// + /// Occurs, when the value of VerticalByteCount property has changed. + /// + [Description("Occurs, when the value of VerticalByteCount property has changed.")] + public event EventHandler VerticalByteCountChanged; + /// + /// Occurs, when the value of CurrentLine property has changed. + /// + [Description("Occurs, when the value of CurrentLine property has changed.")] + public event EventHandler CurrentLineChanged; + /// + /// Occurs, when the value of CurrentPositionInLine property has changed. + /// + [Description("Occurs, when the value of CurrentPositionInLine property has changed.")] + public event EventHandler CurrentPositionInLineChanged; + /// + /// Occurs, when Copy method was invoked and ClipBoardData changed. + /// + [Description("Occurs, when Copy method was invoked and ClipBoardData changed.")] + public event EventHandler Copied; + /// + /// Occurs, when CopyHex method was invoked and ClipBoardData changed. + /// + [Description("Occurs, when CopyHex method was invoked and ClipBoardData changed.")] + public event EventHandler CopiedHex; + #endregion + + #region Ctors + + /// + /// Initializes a new instance of a HexBox class. + /// + public HexBox() + { + this._vScrollBar = new VScrollBar(); + this._vScrollBar.Scroll += new ScrollEventHandler(_vScrollBar_Scroll); + + this._builtInContextMenu = new BuiltInContextMenu(this); + + BackColor = Color.White; + Font = new Font("Courier New", 9F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0))); + _stringFormat = new StringFormat(StringFormat.GenericTypographic); + _stringFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces; + + ActivateEmptyKeyInterpreter(); + + SetStyle(ControlStyles.UserPaint, true); + SetStyle(ControlStyles.DoubleBuffer, true); + SetStyle(ControlStyles.AllPaintingInWmPaint, true); + SetStyle(ControlStyles.ResizeRedraw, true); + + _thumbTrackTimer.Interval = 50; + _thumbTrackTimer.Tick += new EventHandler(PerformScrollThumbTrack); + } + + #endregion + + #region Scroll methods + void _vScrollBar_Scroll(object sender, ScrollEventArgs e) + { + switch(e.Type) + { + case ScrollEventType.Last: + break; + case ScrollEventType.EndScroll: + break; + case ScrollEventType.SmallIncrement: + PerformScrollLineDown(); + break; + case ScrollEventType.SmallDecrement: + PerformScrollLineUp(); + break; + case ScrollEventType.LargeIncrement: + PerformScrollPageDown(); + break; + case ScrollEventType.LargeDecrement: + PerformScrollPageUp(); + break; + case ScrollEventType.ThumbPosition: + long lPos = FromScrollPos(e.NewValue); + PerformScrollThumpPosition(lPos); + break; + case ScrollEventType.ThumbTrack: + // to avoid performance problems use a refresh delay implemented with a timer + if (_thumbTrackTimer.Enabled) // stop old timer + _thumbTrackTimer.Enabled = false; + + // perform scroll immediately only if last refresh is very old + int currentThumbTrack = System.Environment.TickCount; + if (currentThumbTrack - _lastThumbtrack > THUMPTRACKDELAY) + { + PerformScrollThumbTrack(null, null); + _lastThumbtrack = currentThumbTrack; + break; + } + + // start thumbtrack timer + _thumbTrackPosition = FromScrollPos(e.NewValue); + _thumbTrackTimer.Enabled = true; + break; + case ScrollEventType.First: + break; + default: + break; + } + + e.NewValue = ToScrollPos(_scrollVpos); + } + + /// + /// Performs the thumbtrack scrolling after an delay. + /// + void PerformScrollThumbTrack(object sender, EventArgs e) + { + _thumbTrackTimer.Enabled = false; + PerformScrollThumpPosition(_thumbTrackPosition); + _lastThumbtrack = Environment.TickCount; + } + + void UpdateScrollSize() + { + System.Diagnostics.Debug.WriteLine("UpdateScrollSize()", "HexBox"); + + // calc scroll bar info + if (VScrollBarVisible && _byteProvider != null && _byteProvider.Length > 0 && _iHexMaxHBytes != 0) + { + long scrollmax = (long)Math.Ceiling((double)(_byteProvider.Length + 1) / (double)_iHexMaxHBytes - (double)_iHexMaxVBytes); + scrollmax = Math.Max(0, scrollmax); + + long scrollpos = _startByte / _iHexMaxHBytes; + + if (scrollmax < _scrollVmax) + { + /* Data size has been decreased. */ + if (_scrollVpos == _scrollVmax) + /* Scroll one line up if we at bottom. */ + PerformScrollLineUp(); + } + + if (scrollmax == _scrollVmax && scrollpos == _scrollVpos) + return; + + _scrollVmin = 0; + _scrollVmax = scrollmax; + _scrollVpos = Math.Min(scrollpos, scrollmax); + UpdateVScroll(); + } + else if (VScrollBarVisible) + { + // disable scroll bar + _scrollVmin = 0; + _scrollVmax = 0; + _scrollVpos = 0; + UpdateVScroll(); + } + } + + void UpdateVScroll() + { + System.Diagnostics.Debug.WriteLine("UpdateVScroll()", "HexBox"); + + int max = ToScrollMax(_scrollVmax); + + if(max > 0) + { + _vScrollBar.Minimum = 0; + _vScrollBar.Maximum = max; + _vScrollBar.Value = ToScrollPos(_scrollVpos); + _vScrollBar.Enabled = true; + } + else + { + _vScrollBar.Enabled = false; + } + } + + int ToScrollPos(long value) + { + int max = 65535; + + if(_scrollVmax < max) + return (int)value; + else + { + double valperc = (double)value / (double)_scrollVmax * (double)100; + int res = (int)Math.Floor((double)max / (double)100 * valperc); + res = (int)Math.Max(_scrollVmin, res); + res = (int)Math.Min(_scrollVmax, res); + return res; + } + } + + long FromScrollPos(int value) + { + int max = 65535; + if(_scrollVmax < max) + { + return (long)value; + } + else + { + double valperc = (double)value / (double)max * (double)100; + long res = (int)Math.Floor((double)_scrollVmax / (double)100 * valperc); + return res; + } + } + + int ToScrollMax(long value) + { + long max = 65535; + if(value > max) + return (int)max; + else + return (int)value; + } + + void PerformScrollToLine(long pos) + { + if(pos < _scrollVmin || pos > _scrollVmax || pos == _scrollVpos ) + return; + + _scrollVpos = pos; + + UpdateVScroll(); + UpdateVisibilityBytes(); + UpdateCaret(); + Invalidate(); + } + + void PerformScrollLines(int lines) + { + long pos; + if(lines > 0) + { + pos = Math.Min(_scrollVmax, _scrollVpos+lines); + } + else if(lines < 0) + { + pos = Math.Max(_scrollVmin, _scrollVpos+lines); + } + else + { + return; + } + + PerformScrollToLine(pos); + } + + void PerformScrollLineDown() + { + this.PerformScrollLines(1); + } + + void PerformScrollLineUp() + { + this.PerformScrollLines(-1); + } + + void PerformScrollPageDown() + { + this.PerformScrollLines(_iHexMaxVBytes); + } + + void PerformScrollPageUp() + { + this.PerformScrollLines(-_iHexMaxVBytes); + } + + void PerformScrollThumpPosition(long pos) + { + // Bug fix: Scroll to end, do not scroll to end + int difference = (_scrollVmax > 65535) ? 10 : 9; + + if(ToScrollPos(pos) == ToScrollMax(_scrollVmax)-difference) + pos = _scrollVmax; + // End Bug fix + + + PerformScrollToLine(pos); + } + + /// + /// Scrolls the selection start byte into view + /// + public void ScrollByteIntoView() + { + System.Diagnostics.Debug.WriteLine("ScrollByteIntoView()", "HexBox"); + + ScrollByteIntoView(_bytePos); + } + + /// + /// Scrolls the specific byte into view + /// + /// the index of the byte + public void ScrollByteIntoView(long index) + { + System.Diagnostics.Debug.WriteLine("ScrollByteIntoView(long index)", "HexBox"); + + if(_byteProvider == null || _keyInterpreter == null) + return; + + if(index < _startByte) + { + long line = (long)Math.Floor((double)index / (double)_iHexMaxHBytes); + PerformScrollThumpPosition(line); + } + else if(index > _endByte) + { + long line = (long)Math.Floor((double)index / (double)_iHexMaxHBytes); + line -= _iHexMaxVBytes-1; + PerformScrollThumpPosition(line); + } + } + #endregion + + #region Selection methods + void ReleaseSelection() + { + System.Diagnostics.Debug.WriteLine("ReleaseSelection()", "HexBox"); + + if(_selectionLength == 0) + return; + _selectionLength = 0; + OnSelectionLengthChanged(EventArgs.Empty); + + if(!_caretVisible) + CreateCaret(); + else + UpdateCaret(); + + Invalidate(); + } + + /// + /// Returns true if Select method could be invoked. + /// + public bool CanSelectAll() + { + if (!this.Enabled) + return false; + if (_byteProvider == null) + return false; + + return true; + } + + /// + /// Selects all bytes. + /// + public void SelectAll() + { + if (this.ByteProvider == null) + return; + this.Select(0, this.ByteProvider.Length); + } + + /// + /// Selects the hex box. + /// + /// the start index of the selection + /// the length of the selection + public void Select(long start, long length) + { + if (this.ByteProvider == null) + return; + if (!this.Enabled) + return; + + InternalSelect(start, length); + ScrollByteIntoView(); + } + + void InternalSelect(long start, long length) + { + long pos = start; + long sel = length; + int cp = 0; + + if(sel > 0 && _caretVisible) + DestroyCaret(); + else if(sel == 0 && !_caretVisible) + CreateCaret(); + + SetPosition(pos, cp); + SetSelectionLength(sel); + + UpdateCaret(); + Invalidate(); + } + #endregion + + #region Key interpreter methods + void ActivateEmptyKeyInterpreter() + { + if(_eki == null) + _eki = new EmptyKeyInterpreter(this); + + if(_eki == _keyInterpreter) + return; + + if(_keyInterpreter != null) + _keyInterpreter.Deactivate(); + + _keyInterpreter = _eki; + _keyInterpreter.Activate(); + } + + void ActivateKeyInterpreter() + { + if(_ki == null) + _ki = new KeyInterpreter(this); + + if(_ki == _keyInterpreter) + return; + + if(_keyInterpreter != null) + _keyInterpreter.Deactivate(); + + _keyInterpreter = _ki; + _keyInterpreter.Activate(); + } + + void ActivateStringKeyInterpreter() + { + if(_ski == null) + _ski = new StringKeyInterpreter(this); + + if(_ski == _keyInterpreter) + return; + + if(_keyInterpreter != null) + _keyInterpreter.Deactivate(); + + _keyInterpreter = _ski; + _keyInterpreter.Activate(); + } + #endregion + + #region Caret methods + void CreateCaret() + { + if(_byteProvider == null || _keyInterpreter == null || _caretVisible || !this.Focused) + return; + + System.Diagnostics.Debug.WriteLine("CreateCaret()", "HexBox"); + + // define the caret width depending on InsertActive mode + int caretWidth = (this.InsertActive) ? 1 : (int)_charSize.Width; + int caretHeight = (int)_charSize.Height; + NativeMethods.CreateCaret(Handle, IntPtr.Zero, caretWidth, caretHeight); + + UpdateCaret(); + + NativeMethods.ShowCaret(Handle); + + _caretVisible = true; + } + + void UpdateCaret() + { + if (_byteProvider == null || _keyInterpreter == null) + return; + + System.Diagnostics.Debug.WriteLine("UpdateCaret()", "HexBox"); + + long byteIndex =_bytePos - _startByte; + PointF p = _keyInterpreter.GetCaretPointF(byteIndex); + p.X += _byteCharacterPos*_charSize.Width; + NativeMethods.SetCaretPos((int)p.X, (int)p.Y); + } + + void DestroyCaret() + { + if (!_caretVisible) + return; + + System.Diagnostics.Debug.WriteLine("DestroyCaret()", "HexBox"); + + NativeMethods.DestroyCaret(); + _caretVisible = false; + } + + void SetCaretPosition(Point p) + { + System.Diagnostics.Debug.WriteLine("SetCaretPosition()", "HexBox"); + + if (_byteProvider == null || _keyInterpreter == null) + return; + + long pos = _bytePos; + int cp = _byteCharacterPos; + + if(_recHex.Contains(p)) + { + BytePositionInfo bpi = GetHexBytePositionInfo(p); + pos = bpi.Index; + cp = bpi.CharacterPosition; + + SetPosition(pos, cp); + + ActivateKeyInterpreter(); + UpdateCaret(); + Invalidate(); + } + else if(_recStringView.Contains(p)) + { + BytePositionInfo bpi = GetStringBytePositionInfo(p); + pos = bpi.Index; + cp = bpi.CharacterPosition; + + SetPosition(pos, cp); + + ActivateStringKeyInterpreter(); + UpdateCaret(); + Invalidate(); + } + } + + BytePositionInfo GetHexBytePositionInfo(Point p) + { + System.Diagnostics.Debug.WriteLine("GetHexBytePositionInfo()", "HexBox"); + + long bytePos; + int byteCharaterPos; + + float x = ((float)(p.X - _recHex.X) / _charSize.Width); + float y = ((float)(p.Y - _recHex.Y) / _charSize.Height); + int iX = (int)x; + int iY = (int)y; + + int hPos = (iX / 3 + 1); + + bytePos = Math.Min(_byteProvider.Length, + _startByte + (_iHexMaxHBytes * (iY+1) - _iHexMaxHBytes) + hPos - 1); + byteCharaterPos = (iX % 3); + if(byteCharaterPos > 1) + byteCharaterPos = 1; + + if(bytePos == _byteProvider.Length) + byteCharaterPos = 0; + + if(bytePos < 0) + return new BytePositionInfo(0, 0); + return new BytePositionInfo(bytePos, byteCharaterPos); + } + + BytePositionInfo GetStringBytePositionInfo(Point p) + { + System.Diagnostics.Debug.WriteLine("GetStringBytePositionInfo()", "HexBox"); + + long bytePos; + int byteCharacterPos; + + float x = ((float)(p.X - _recStringView.X) / _charSize.Width); + float y = ((float)(p.Y - _recStringView.Y) / _charSize.Height); + int iX = (int)x; + int iY = (int)y; + + int hPos = iX+1; + + bytePos = Math.Min(_byteProvider.Length, + _startByte + (_iHexMaxHBytes * (iY+1) - _iHexMaxHBytes) + hPos - 1); + byteCharacterPos = 0; + + if(bytePos < 0) + return new BytePositionInfo(0, 0); + return new BytePositionInfo(bytePos, byteCharacterPos); + } + #endregion + + #region PreProcessMessage methods + /// + /// Preprocesses windows messages. + /// + /// the message to process. + /// true, if the message was processed + [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=true), SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] + public override bool PreProcessMessage(ref Message m) + { + switch(m.Msg) + { + case NativeMethods.WM_KEYDOWN: + return _keyInterpreter.PreProcessWmKeyDown(ref m); + case NativeMethods.WM_CHAR: + return _keyInterpreter.PreProcessWmChar(ref m); + case NativeMethods.WM_KEYUP: + return _keyInterpreter.PreProcessWmKeyUp(ref m); + default: + return base.PreProcessMessage (ref m); + } + } + + bool BasePreProcessMessage(ref Message m) + { + return base.PreProcessMessage(ref m); + } + #endregion + + #region Find methods + /// + /// Searches the current ByteProvider + /// + /// the array of bytes to find + /// the start index + /// the SelectionStart property value if find was successfull or + /// -1 if there is no match + /// -2 if Find was aborted. + public long Find(byte[] bytes, long startIndex) + { + int match = 0; + int bytesLength = bytes.Length; + + _abortFind = false; + + for(long pos = startIndex; pos < _byteProvider.Length; pos++) + { + if(_abortFind) + return -2; + + if(pos % 1000 == 0) // for performance reasons: DoEvents only 1 times per 1000 loops + Application.DoEvents(); + + if(_byteProvider.ReadByte(pos) != bytes[match]) + { + pos -= match; + match = 0; + _findingPos = pos; + continue; + } + + match++; + + if(match == bytesLength) + { + long bytePos = pos-bytesLength+1; + Select(bytePos, bytesLength); + ScrollByteIntoView(_bytePos+_selectionLength); + ScrollByteIntoView(_bytePos); + + return bytePos; + } + } + + return -1; + } + + /// + /// Aborts a working Find method. + /// + public void AbortFind() + { + _abortFind = true; + } + + /// + /// Gets a value that indicates the current position during Find method execution. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public long CurrentFindingPosition + { + get + { + return _findingPos; + } + } + #endregion + + #region Copy, Cut and Paste methods + byte[] GetCopyData() + { + if (!CanCopy()) return new byte[0]; + + // put bytes into buffer + byte[] buffer = new byte[_selectionLength]; + int id = -1; + for (long i = _bytePos; i < _bytePos + _selectionLength; i++) + { + id++; + + buffer[id] = _byteProvider.ReadByte(i); + } + return buffer; + } + /// + /// Copies the current selection in the hex box to the Clipboard. + /// + public void Copy() + { + if(!CanCopy()) return; + + // put bytes into buffer + byte[] buffer = GetCopyData(); + + DataObject da = new DataObject(); + + // set string buffer clipbard data + string sBuffer = System.Text.Encoding.ASCII.GetString(buffer, 0, buffer.Length); + da.SetData(typeof(string), sBuffer); + + //set memorystream (BinaryData) clipboard data + System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer, 0, buffer.Length, false, true); + da.SetData("BinaryData", ms); + + Clipboard.SetDataObject(da, true); + UpdateCaret(); + ScrollByteIntoView(); + Invalidate(); + + OnCopied(EventArgs.Empty); + } + + /// + /// Return true if Copy method could be invoked. + /// + public bool CanCopy() + { + if(_selectionLength < 1 || _byteProvider == null) + return false; + + return true; + } + + /// + /// Moves the current selection in the hex box to the Clipboard. + /// + public void Cut() + { + if(!CanCut()) return; + + Copy(); + + _byteProvider.DeleteBytes(_bytePos, _selectionLength); + _byteCharacterPos = 0; + UpdateCaret(); + ScrollByteIntoView(); + ReleaseSelection(); + Invalidate(); + Refresh(); + } + + /// + /// Return true if Cut method could be invoked. + /// + public bool CanCut() + { + if (ReadOnly || !this.Enabled) + return false; + if(_byteProvider == null) + return false; + if(_selectionLength < 1 || !_byteProvider.SupportsDeleteBytes()) + return false; + + return true; + } + + /// + /// Replaces the current selection in the hex box with the contents of the Clipboard. + /// + public void Paste() + { + if(!CanPaste()) return; + + if(_selectionLength > 0) + _byteProvider.DeleteBytes(_bytePos, _selectionLength); + + byte[] buffer = null; + IDataObject da = Clipboard.GetDataObject(); + if(da.GetDataPresent("BinaryData")) + { + System.IO.MemoryStream ms = (System.IO.MemoryStream)da.GetData("BinaryData"); + buffer = new byte[ms.Length]; + ms.Read(buffer, 0, buffer.Length); + } + else if(da.GetDataPresent(typeof(string))) + { + string sBuffer = (string)da.GetData(typeof(string)); + buffer = System.Text.Encoding.ASCII.GetBytes(sBuffer); + } + else + { + return; + } + + _byteProvider.InsertBytes(_bytePos, buffer); + + SetPosition(_bytePos + buffer.Length, 0); + + ReleaseSelection(); + ScrollByteIntoView(); + UpdateCaret(); + Invalidate(); + } + + /// + /// Return true if Paste method could be invoked. + /// + public bool CanPaste() + { + if (ReadOnly || !this.Enabled) return false; + + if(_byteProvider == null || !_byteProvider.SupportsInsertBytes()) + return false; + + if(!_byteProvider.SupportsDeleteBytes() && _selectionLength > 0) + return false; + + IDataObject da = Clipboard.GetDataObject(); + if(da.GetDataPresent("BinaryData")) + return true; + else if(da.GetDataPresent(typeof(string))) + return true; + else + return false; + } + /// + /// Return true if PasteHex method could be invoked. + /// + public bool CanPasteHex() + { + if (!CanPaste()) return false; + + byte[] buffer = null; + IDataObject da = Clipboard.GetDataObject(); + if (da.GetDataPresent(typeof(string))) + { + string hexString = (string)da.GetData(typeof(string)); + buffer = ConvertHexToBytes(hexString); + return (buffer != null); + } + return false; + } + + /// + /// Replaces the current selection in the hex box with the hex string data of the Clipboard. + /// + public void PasteHex() + { + if (!CanPaste()) return; + + byte[] buffer = null; + IDataObject da = Clipboard.GetDataObject(); + if (da.GetDataPresent(typeof(string))) + { + string hexString = (string)da.GetData(typeof(string)); + buffer = ConvertHexToBytes(hexString); + if (buffer == null) + return; + } + else + { + return; + } + + if (_selectionLength > 0) + _byteProvider.DeleteBytes(_bytePos, _selectionLength); + + _byteProvider.InsertBytes(_bytePos, buffer); + + SetPosition(_bytePos + buffer.Length, 0); + + ReleaseSelection(); + ScrollByteIntoView(); + UpdateCaret(); + Invalidate(); + } + + /// + /// Copies the current selection in the hex box to the Clipboard in hex format. + /// + public void CopyHex() + { + if (!CanCopy()) return; + + // put bytes into buffer + byte[] buffer = GetCopyData(); + + DataObject da = new DataObject(); + + // set string buffer clipbard data + string hexString = ConvertBytesToHex(buffer); ; + da.SetData(typeof(string), hexString); + + //set memorystream (BinaryData) clipboard data + System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer, 0, buffer.Length, false, true); + da.SetData("BinaryData", ms); + + Clipboard.SetDataObject(da, true); + UpdateCaret(); + ScrollByteIntoView(); + Invalidate(); + + OnCopiedHex(EventArgs.Empty); + } + + + #endregion + + #region Paint methods + /// + /// Paints the background. + /// + /// A PaintEventArgs that contains the event data. + protected override void OnPaintBackground(PaintEventArgs e) + { + switch(_borderStyle) + { + case BorderStyle.Fixed3D: + { + if(TextBoxRenderer.IsSupported) + { + VisualStyleElement state = VisualStyleElement.TextBox.TextEdit.Normal; + Color backColor = this.BackColor; + + if (this.Enabled) + { + if (this.ReadOnly) + state = VisualStyleElement.TextBox.TextEdit.ReadOnly; + else if (this.Focused) + state = VisualStyleElement.TextBox.TextEdit.Focused; + } + else + { + state = VisualStyleElement.TextBox.TextEdit.Disabled; + backColor = this.BackColorDisabled; + } + + VisualStyleRenderer vsr = new VisualStyleRenderer(state); + vsr.DrawBackground(e.Graphics, this.ClientRectangle); + + Rectangle rectContent = vsr.GetBackgroundContentRectangle(e.Graphics, this.ClientRectangle); + e.Graphics.FillRectangle(new SolidBrush(backColor), rectContent); + } + else + { + // draw background + e.Graphics.FillRectangle(new SolidBrush(BackColor), ClientRectangle); + + // draw default border + ControlPaint.DrawBorder3D(e.Graphics, ClientRectangle, Border3DStyle.Sunken); + } + + break; + } + case BorderStyle.FixedSingle: + { + // draw background + e.Graphics.FillRectangle(new SolidBrush(BackColor), ClientRectangle); + + // draw fixed single border + ControlPaint.DrawBorder(e.Graphics, ClientRectangle, Color.Black, ButtonBorderStyle.Solid); + break; + } + default: + { + // draw background + e.Graphics.FillRectangle(new SolidBrush(BackColor), ClientRectangle); + break; + } + } + } + + + /// + /// Paints the hex box. + /// + /// A PaintEventArgs that contains the event data. + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + if(_byteProvider == null) + return; + + System.Diagnostics.Debug.WriteLine("OnPaint " + DateTime.Now.ToString(), "HexBox"); + + // draw only in the content rectangle, so exclude the border and the scrollbar. + Region r = new Region(ClientRectangle); + r.Exclude(_recContent); + e.Graphics.ExcludeClip(r); + + UpdateVisibilityBytes(); + + if(_lineInfoVisible) + PaintLineInfo(e.Graphics, _startByte, _endByte); + + if(!_stringViewVisible) + { + PaintHex(e.Graphics, _startByte, _endByte); + } + else + { + PaintHexAndStringView(e.Graphics, _startByte, _endByte); + if(_shadowSelectionVisible) + PaintCurrentBytesSign(e.Graphics); + } + } + + + void PaintLineInfo(Graphics g, long startByte, long endByte) + { + // Ensure endByte isn't > length of array. + endByte = Math.Min(_byteProvider.Length-1, endByte); + + Color lineInfoColor = (this.LineInfoForeColor != Color.Empty) ? this.LineInfoForeColor : this.ForeColor; + Brush brush = new SolidBrush(lineInfoColor); + + int maxLine = GetGridBytePoint(endByte-startByte).Y+1; + + for(int i = 0; i < maxLine; i++) + { + long firstLineByte = (startByte + (_iHexMaxHBytes)*i) + _lineInfoOffset; + + PointF bytePointF = GetBytePointF(new Point(0, 0+i)); + string info = firstLineByte.ToString(_hexStringFormat, System.Threading.Thread.CurrentThread.CurrentCulture); + int nulls = 8-info.Length; + string formattedInfo; + if(nulls > -1) + { + formattedInfo = new string('0', 8-info.Length) + info; + } + else + { + formattedInfo = new string('~', 8); + } + + g.DrawString(formattedInfo, Font, brush, new PointF(_recLineInfo.X, bytePointF.Y), _stringFormat); + } + } + + void PaintHex(Graphics g, long startByte, long endByte) + { + Brush brush = new SolidBrush(GetDefaultForeColor()); + Brush selBrush = new SolidBrush(_selectionForeColor); + Brush selBrushBack = new SolidBrush(_selectionBackColor); + + int counter = -1; + long intern_endByte = Math.Min(_byteProvider.Length-1, endByte+_iHexMaxHBytes); + + bool isKeyInterpreterActive = _keyInterpreter == null || _keyInterpreter.GetType() == typeof(KeyInterpreter); + + for(long i = startByte; i < intern_endByte+1; i++) + { + counter++; + Point gridPoint = GetGridBytePoint(counter); + byte b = _byteProvider.ReadByte(i); + + bool isSelectedByte = i >= _bytePos && i <= (_bytePos + _selectionLength-1) && _selectionLength != 0; + + if(isSelectedByte && isKeyInterpreterActive) + { + PaintHexStringSelected(g, b, selBrush, selBrushBack, gridPoint); + } + else + { + PaintHexString(g, b, brush, gridPoint); + } + } + } + + void PaintHexString(Graphics g, byte b, Brush brush, Point gridPoint) + { + PointF bytePointF = GetBytePointF(gridPoint); + + string sB = ConvertByteToHex(b); + + g.DrawString(sB.Substring(0,1), Font, brush, bytePointF, _stringFormat); + bytePointF.X += _charSize.Width; + g.DrawString(sB.Substring(1,1), Font, brush, bytePointF, _stringFormat); + } + + void PaintHexStringSelected(Graphics g, byte b, Brush brush, Brush brushBack, Point gridPoint) + { + string sB = b.ToString(_hexStringFormat, System.Threading.Thread.CurrentThread.CurrentCulture); + if(sB.Length == 1) + sB = "0" + sB; + + PointF bytePointF = GetBytePointF(gridPoint); + + bool isLastLineChar = (gridPoint.X+1 == _iHexMaxHBytes); + float bcWidth = (isLastLineChar) ? _charSize.Width*2 : _charSize.Width*3; + + g.FillRectangle(brushBack, bytePointF.X, bytePointF.Y, bcWidth, _charSize.Height); + g.DrawString(sB.Substring(0,1), Font, brush, bytePointF, _stringFormat); + bytePointF.X += _charSize.Width; + g.DrawString(sB.Substring(1,1), Font, brush, bytePointF, _stringFormat); + } + + void PaintHexAndStringView(Graphics g, long startByte, long endByte) + { + Brush brush = new SolidBrush(GetDefaultForeColor()); + Brush selBrush = new SolidBrush(_selectionForeColor); + Brush selBrushBack = new SolidBrush(_selectionBackColor); + + int counter = -1; + long intern_endByte = Math.Min(_byteProvider.Length-1, endByte+_iHexMaxHBytes); + + bool isKeyInterpreterActive = _keyInterpreter == null || _keyInterpreter.GetType() == typeof(KeyInterpreter); + bool isStringKeyInterpreterActive = _keyInterpreter != null && _keyInterpreter.GetType() == typeof(StringKeyInterpreter); + + for(long i = startByte; i < intern_endByte+1; i++) + { + counter++; + Point gridPoint = GetGridBytePoint(counter); + PointF byteStringPointF = GetByteStringPointF(gridPoint); + byte b = _byteProvider.ReadByte(i); + + bool isSelectedByte = i >= _bytePos && i <= (_bytePos + _selectionLength-1) && _selectionLength != 0; + + if(isSelectedByte && isKeyInterpreterActive) + { + PaintHexStringSelected(g, b, selBrush, selBrushBack, gridPoint); + } + else + { + PaintHexString(g, b, brush, gridPoint); + } + + string s = new String(ByteCharConverter.ToChar(b), 1); + + if(isSelectedByte && isStringKeyInterpreterActive) + { + g.FillRectangle(selBrushBack, byteStringPointF.X, byteStringPointF.Y, _charSize.Width, _charSize.Height); + g.DrawString(s, Font, selBrush, byteStringPointF, _stringFormat); + } + else + { + g.DrawString(s, Font, brush, byteStringPointF, _stringFormat); + } + } + } + + void PaintCurrentBytesSign(Graphics g) + { + if(_keyInterpreter != null && Focused && _bytePos != -1 && Enabled) + { + if(_keyInterpreter.GetType() == typeof(KeyInterpreter)) + { + if(_selectionLength == 0) + { + Point gp = GetGridBytePoint(_bytePos - _startByte); + PointF pf = GetByteStringPointF(gp); + Size s = new Size((int)_charSize.Width, (int)_charSize.Height); + Rectangle r = new Rectangle((int)pf.X, (int)pf.Y, s.Width, s.Height); + if(r.IntersectsWith(_recStringView)) + { + r.Intersect(_recStringView); + PaintCurrentByteSign(g, r); + } + } + else + { + int lineWidth = (int)(_recStringView.Width-_charSize.Width); + + Point startSelGridPoint = GetGridBytePoint(_bytePos-_startByte); + PointF startSelPointF = GetByteStringPointF(startSelGridPoint); + + Point endSelGridPoint = GetGridBytePoint(_bytePos-_startByte+_selectionLength-1); + PointF endSelPointF = GetByteStringPointF(endSelGridPoint); + + int multiLine = endSelGridPoint.Y - startSelGridPoint.Y; + if(multiLine == 0) + { + Rectangle singleLine = new Rectangle( + (int)startSelPointF.X, + (int)startSelPointF.Y, + (int)(endSelPointF.X-startSelPointF.X+_charSize.Width), + (int)_charSize.Height); + if(singleLine.IntersectsWith(_recStringView)) + { + singleLine.Intersect(_recStringView); + PaintCurrentByteSign(g, singleLine); + } + } + else + { + Rectangle firstLine = new Rectangle( + (int)startSelPointF.X, + (int)startSelPointF.Y, + (int)(_recStringView.X+lineWidth-startSelPointF.X+_charSize.Width), + (int)_charSize.Height); + if(firstLine.IntersectsWith(_recStringView)) + { + firstLine.Intersect(_recStringView); + PaintCurrentByteSign(g, firstLine); + } + + if(multiLine > 1) + { + Rectangle betweenLines = new Rectangle( + _recStringView.X, + (int)(startSelPointF.Y+_charSize.Height), + (int)(_recStringView.Width), + (int)(_charSize.Height*(multiLine-1))); + if(betweenLines.IntersectsWith(_recStringView)) + { + betweenLines.Intersect(_recStringView); + PaintCurrentByteSign(g, betweenLines); + } + + } + + Rectangle lastLine = new Rectangle( + _recStringView.X, + (int)endSelPointF.Y, + (int)(endSelPointF.X-_recStringView.X+_charSize.Width), + (int)_charSize.Height); + if(lastLine.IntersectsWith(_recStringView)) + { + lastLine.Intersect(_recStringView); + PaintCurrentByteSign(g, lastLine); + } + } + } + } + else + { + if(_selectionLength == 0) + { + Point gp = GetGridBytePoint(_bytePos - _startByte); + PointF pf = GetBytePointF(gp); + Size s = new Size((int)_charSize.Width * 2, (int)_charSize.Height); + Rectangle r = new Rectangle((int)pf.X, (int)pf.Y, s.Width, s.Height); + PaintCurrentByteSign(g, r); + } + else + { + int lineWidth = (int)(_recHex.Width-_charSize.Width*5); + + Point startSelGridPoint = GetGridBytePoint(_bytePos-_startByte); + PointF startSelPointF = GetBytePointF(startSelGridPoint); + + Point endSelGridPoint = GetGridBytePoint(_bytePos-_startByte+_selectionLength-1); + PointF endSelPointF = GetBytePointF(endSelGridPoint); + + int multiLine = endSelGridPoint.Y - startSelGridPoint.Y; + if(multiLine == 0) + { + Rectangle singleLine = new Rectangle( + (int)startSelPointF.X, + (int)startSelPointF.Y, + (int)(endSelPointF.X-startSelPointF.X+_charSize.Width*2), + (int)_charSize.Height); + if(singleLine.IntersectsWith(_recHex)) + { + singleLine.Intersect(_recHex); + PaintCurrentByteSign(g, singleLine); + } + } + else + { + Rectangle firstLine = new Rectangle( + (int)startSelPointF.X, + (int)startSelPointF.Y, + (int)(_recHex.X+lineWidth-startSelPointF.X+_charSize.Width*2), + (int)_charSize.Height); + if(firstLine.IntersectsWith(_recHex)) + { + firstLine.Intersect(_recHex); + PaintCurrentByteSign(g, firstLine); + } + + if(multiLine > 1) + { + Rectangle betweenLines = new Rectangle( + _recHex.X, + (int)(startSelPointF.Y+_charSize.Height), + (int)(lineWidth+_charSize.Width*2), + (int)(_charSize.Height*(multiLine-1))); + if(betweenLines.IntersectsWith(_recHex)) + { + betweenLines.Intersect(_recHex); + PaintCurrentByteSign(g, betweenLines); + } + + } + + Rectangle lastLine = new Rectangle( + _recHex.X, + (int)endSelPointF.Y, + (int)(endSelPointF.X-_recHex.X+_charSize.Width*2), + (int)_charSize.Height); + if(lastLine.IntersectsWith(_recHex)) + { + lastLine.Intersect(_recHex); + PaintCurrentByteSign(g, lastLine); + } + } + } + } + } + } + + void PaintCurrentByteSign(Graphics g, Rectangle rec) + { + // stack overflowexception on big files - workaround + if(rec.Top < 0 || rec.Left < 0 || rec.Width <= 0 || rec.Height <= 0) + return; + + Bitmap myBitmap = new Bitmap(rec.Width, rec.Height); + Graphics bitmapGraphics = Graphics.FromImage(myBitmap); + + SolidBrush greenBrush = new SolidBrush(_shadowSelectionColor); + + bitmapGraphics.FillRectangle(greenBrush, 0, + 0, rec.Width, rec.Height); + + g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.GammaCorrected; + + g.DrawImage(myBitmap, rec.Left, rec.Top); + } + + Color GetDefaultForeColor() + { + if(Enabled) + return ForeColor; + else + return Color.Gray; + } + void UpdateVisibilityBytes() + { + if(_byteProvider == null || _byteProvider.Length == 0) + return; + + _startByte = (_scrollVpos+1) * _iHexMaxHBytes - _iHexMaxHBytes; + _endByte = (long)Math.Min(_byteProvider.Length - 1, _startByte + _iHexMaxBytes); + } + #endregion + + #region Positioning methods + void UpdateRectanglePositioning() + { + // calc char size + SizeF charSize = this.CreateGraphics().MeasureString("A", Font, 100, _stringFormat); + _charSize = new SizeF((float)Math.Ceiling(charSize.Width), (float)Math.Ceiling(charSize.Height)); + + // calc content bounds + _recContent = ClientRectangle; + _recContent.X += _recBorderLeft; + _recContent.Y += _recBorderTop; + _recContent.Width -= _recBorderRight+_recBorderLeft; + _recContent.Height -= _recBorderBottom+_recBorderTop; + + if(_vScrollBarVisible) + { + _recContent.Width -= _vScrollBar.Width; + _vScrollBar.Left = _recContent.X+_recContent.Width; + _vScrollBar.Top = _recContent.Y; + _vScrollBar.Height = _recContent.Height; + } + + int marginLeft = 4; + + // calc line info bounds + if(_lineInfoVisible) + { + _recLineInfo = new Rectangle(_recContent.X+marginLeft, + _recContent.Y, + (int)(_charSize.Width*10), + _recContent.Height); + } + else + { + _recLineInfo = Rectangle.Empty; + _recLineInfo.X = marginLeft; + } + + // calc hex bounds and grid + _recHex = new Rectangle(_recLineInfo.X + _recLineInfo.Width, + _recLineInfo.Y, + _recContent.Width - _recLineInfo.Width, + _recContent.Height); + + if(UseFixedBytesPerLine) + { + SetHorizontalByteCount(_bytesPerLine); + _recHex.Width = (int)Math.Floor(((double)_iHexMaxHBytes)*_charSize.Width*3+(2*_charSize.Width)); + } + else + { + int hmax = (int)Math.Floor((double)_recHex.Width/(double)_charSize.Width); + if(hmax > 1) + SetHorizontalByteCount((int)Math.Floor((double)hmax/3)); + else + SetHorizontalByteCount(hmax); + } + + if(_stringViewVisible) + { + _recStringView = new Rectangle(_recHex.X + _recHex.Width, + _recHex.Y, + (int)(_charSize.Width*_iHexMaxHBytes), + _recHex.Height); + } + else + { + _recStringView = Rectangle.Empty; + } + + int vmax = (int)Math.Floor((double)_recHex.Height/(double)_charSize.Height); + SetVerticalByteCount(vmax); + + _iHexMaxBytes = _iHexMaxHBytes * _iHexMaxVBytes; + + UpdateScrollSize(); + } + + PointF GetBytePointF(long byteIndex) + { + Point gp = GetGridBytePoint(byteIndex); + + return GetBytePointF(gp); + } + + PointF GetBytePointF(Point gp) + { + float x = (3 * _charSize.Width) * gp.X + _recHex.X; + float y = (gp.Y+1)*_charSize.Height-_charSize.Height+_recHex.Y; + + return new PointF(x,y); + } + + PointF GetByteStringPointF(Point gp) + { + float x = (_charSize.Width) * gp.X + _recStringView.X; + float y = (gp.Y+1)*_charSize.Height-_charSize.Height+_recStringView.Y; + + return new PointF(x,y); + } + + Point GetGridBytePoint(long byteIndex) + { + int row = (int)Math.Floor((double)byteIndex/(double)_iHexMaxHBytes); + int column = (int)(byteIndex+_iHexMaxHBytes-_iHexMaxHBytes*(row+1)); + + Point res = new Point(column, row); + return res; + } + #endregion + + #region Overridden properties + /// + /// Gets or sets the background color for the control. + /// + [DefaultValue(typeof(Color), "White")] + public override Color BackColor + { + get + { + return base.BackColor; + } + set + { + base.BackColor = value; + } + } + + /// + /// The font used to display text in the hexbox. + /// + public override Font Font + { + get + { + return base.Font; + } + set + { + base.Font = value; + } + } + + /// + /// Not used. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never), Bindable(false)] + public override string Text + { + get + { + return base.Text; + } + set + { + base.Text = value; + } + } + + /// + /// Not used. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never), Bindable(false)] + public override RightToLeft RightToLeft + { + get + { + return base.RightToLeft; + } + set + { + base.RightToLeft = value; + } + } + #endregion + + #region Properties + /// + /// Gets or sets the background color for the disabled control. + /// + [Category("Appearance"), DefaultValue(typeof(Color), "WhiteSmoke")] + public Color BackColorDisabled + { + get + { + return _backColorDisabled; + } + set + { + _backColorDisabled = value; + } + } Color _backColorDisabled = Color.FromName("WhiteSmoke"); + + /// + /// Gets or sets if the count of bytes in one line is fix. + /// + /// + /// When set to True, BytesPerLine property determine the maximum count of bytes in one line. + /// + [DefaultValue(false), Category("Hex"), Description("Gets or sets if the count of bytes in one line is fix.")] + public bool ReadOnly + { + get { return _readOnly; } + set + { + if(_readOnly == value) + return; + + _readOnly = value; + OnReadOnlyChanged(EventArgs.Empty); + Invalidate(); + } + } bool _readOnly; + + /// + /// Gets or sets the maximum count of bytes in one line. + /// + /// + /// UsedFixedBytesPerLine property must set to true + /// + [DefaultValue(16), Category("Hex"), Description("Gets or sets the maximum count of bytes in one line.")] + public int BytesPerLine + { + get { return _bytesPerLine; } + set + { + if(_bytesPerLine == value) + return; + + _bytesPerLine = value; + OnBytesPerLineChanged(EventArgs.Empty); + + UpdateRectanglePositioning(); + Invalidate(); + } + } int _bytesPerLine = 16; + + /// + /// Gets or sets if the count of bytes in one line is fix. + /// + /// + /// When set to True, BytesPerLine property determine the maximum count of bytes in one line. + /// + [DefaultValue(false), Category("Hex"), Description("Gets or sets if the count of bytes in one line is fix.")] + public bool UseFixedBytesPerLine + { + get { return _useFixedBytesPerLine; } + set + { + if(_useFixedBytesPerLine == value) + return; + + _useFixedBytesPerLine = value; + OnUseFixedBytesPerLineChanged(EventArgs.Empty); + + UpdateRectanglePositioning(); + Invalidate(); + } + } bool _useFixedBytesPerLine; + + /// + /// Gets or sets the visibility of a vertical scroll bar. + /// + [DefaultValue(false), Category("Hex"), Description("Gets or sets the visibility of a vertical scroll bar.")] + public bool VScrollBarVisible + { + get { return this._vScrollBarVisible; } + set + { + if(_vScrollBarVisible == value) + return; + + _vScrollBarVisible = value; + + if(_vScrollBarVisible) + Controls.Add(_vScrollBar); + else + Controls.Remove(_vScrollBar); + + UpdateRectanglePositioning(); + UpdateScrollSize(); + + OnVScrollBarVisibleChanged(EventArgs.Empty); + } + } bool _vScrollBarVisible; + + /// + /// Gets or sets the ByteProvider. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public IByteProvider ByteProvider + { + get { return _byteProvider; } + set + { + if(_byteProvider == value) + return; + + if(value == null) + ActivateEmptyKeyInterpreter(); + else + ActivateKeyInterpreter(); + + if(_byteProvider != null) + _byteProvider.LengthChanged -= new EventHandler(_byteProvider_LengthChanged); + + _byteProvider = value; + if(_byteProvider != null) + _byteProvider.LengthChanged += new EventHandler(_byteProvider_LengthChanged); + + OnByteProviderChanged(EventArgs.Empty); + + if(value == null) // do not raise events if value is null + { + _bytePos = -1; + _byteCharacterPos = 0; + _selectionLength = 0; + + DestroyCaret(); + } + else + { + SetPosition(0, 0); + SetSelectionLength(0); + + if(_caretVisible && Focused) + UpdateCaret(); + else + CreateCaret(); + } + + CheckCurrentLineChanged(); + CheckCurrentPositionInLineChanged(); + + _scrollVpos = 0; + + UpdateVisibilityBytes(); + UpdateRectanglePositioning(); + + Invalidate(); + } + } + + IByteProvider _byteProvider; + + /// + /// Gets or sets the visibility of a line info. + /// + [DefaultValue(false), Category("Hex"), Description("Gets or sets the visibility of a line info.")] + public bool LineInfoVisible + { + get { return _lineInfoVisible; } + set + { + if(_lineInfoVisible == value) + return; + + _lineInfoVisible = value; + OnLineInfoVisibleChanged(EventArgs.Empty); + + UpdateRectanglePositioning(); + Invalidate(); + } + } bool _lineInfoVisible; + + /// + /// Gets or sets the offset of a line info. + /// + [DefaultValue((long)0), Category("Hex"), Description("Gets or sets the offset of the line info.")] + public long LineInfoOffset + { + get { return _lineInfoOffset; } + set + { + if (_lineInfoOffset == value) + return; + + _lineInfoOffset = value; + + Invalidate(); + } + } long _lineInfoOffset; + + /// + /// Gets or sets the hex box´s border style. + /// + [DefaultValue(typeof(BorderStyle), "Fixed3D"), Category("Hex"), Description("Gets or sets the hex box´s border style.")] + public BorderStyle BorderStyle + { + get { return _borderStyle;} + set + { + if(_borderStyle == value) + return; + + _borderStyle = value; + switch(_borderStyle) + { + case BorderStyle.None: + _recBorderLeft = _recBorderTop = _recBorderRight = _recBorderBottom = 0; + break; + case BorderStyle.Fixed3D: + _recBorderLeft = _recBorderRight = SystemInformation.Border3DSize.Width; + _recBorderTop = _recBorderBottom = SystemInformation.Border3DSize.Height; + break; + case BorderStyle.FixedSingle: + _recBorderLeft = _recBorderTop = _recBorderRight = _recBorderBottom = 1; + break; + } + + UpdateRectanglePositioning(); + + OnBorderStyleChanged(EventArgs.Empty); + + } + } BorderStyle _borderStyle = BorderStyle.Fixed3D; + + /// + /// Gets or sets the visibility of the string view. + /// + [DefaultValue(false), Category("Hex"), Description("Gets or sets the visibility of the string view.")] + public bool StringViewVisible + { + get { return _stringViewVisible; } + set + { + if(_stringViewVisible == value) + return; + + _stringViewVisible = value; + OnStringViewVisibleChanged(EventArgs.Empty); + + UpdateRectanglePositioning(); + Invalidate(); + } + } bool _stringViewVisible; + + /// + /// Gets or sets whether the HexBox control displays the hex characters in upper or lower case. + /// + [DefaultValue(typeof(HexCasing), "Upper"), Category("Hex"), Description("Gets or sets whether the HexBox control displays the hex characters in upper or lower case.")] + public HexCasing HexCasing + { + get + { + if(_hexStringFormat == "X") + return HexCasing.Upper; + else + return HexCasing.Lower; + } + set + { + string format; + if(value == HexCasing.Upper) + format = "X"; + else + format = "x"; + + if(_hexStringFormat == format) + return; + + _hexStringFormat = format; + OnHexCasingChanged(EventArgs.Empty); + + Invalidate(); + } + } + + /// + /// Gets and sets the starting point of the bytes selected in the hex box. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public long SelectionStart + { + get { return _bytePos; } + set + { + SetPosition(value, 0); + ScrollByteIntoView(); + Invalidate(); + } + } + + /// + /// Gets and sets the number of bytes selected in the hex box. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public long SelectionLength + { + get { return _selectionLength; } + set + { + SetSelectionLength(value); + ScrollByteIntoView(); + Invalidate(); + } + } long _selectionLength; + + + /// + /// Gets or sets the line info color. When this property is null, then ForeColor property is used. + /// + [DefaultValue(typeof(Color), "Empty"), Category("Hex"), Description("Gets or sets the line info color. When this property is null, then ForeColor property is used.")] + public Color LineInfoForeColor + { + get { return _lineInfoForeColor; } + set { _lineInfoForeColor = value; Invalidate(); } + } Color _lineInfoForeColor = Color.Empty; + + /// + /// Gets or sets the background color for the selected bytes. + /// + [DefaultValue(typeof(Color), "Blue"), Category("Hex"), Description("Gets or sets the background color for the selected bytes.")] + public Color SelectionBackColor + { + get { return _selectionBackColor; } + set { _selectionBackColor = value; Invalidate(); } + } Color _selectionBackColor = Color.Blue; + + /// + /// Gets or sets the foreground color for the selected bytes. + /// + [DefaultValue(typeof(Color), "White"), Category("Hex"), Description("Gets or sets the foreground color for the selected bytes.")] + public Color SelectionForeColor + { + get { return _selectionForeColor; } + set { _selectionForeColor = value; Invalidate(); } + } Color _selectionForeColor = Color.White; + + /// + /// Gets or sets the visibility of a shadow selection. + /// + [DefaultValue(true), Category("Hex"), Description("Gets or sets the visibility of a shadow selection.")] + public bool ShadowSelectionVisible + { + get { return _shadowSelectionVisible; } + set + { + if(_shadowSelectionVisible == value) + return; + _shadowSelectionVisible = value; + Invalidate(); + } + } bool _shadowSelectionVisible = true; + + /// + /// Gets or sets the color of the shadow selection. + /// + /// + /// A alpha component must be given! + /// Default alpha = 100 + /// + [Category("Hex"), Description("Gets or sets the color of the shadow selection.")] + public Color ShadowSelectionColor + { + get { return _shadowSelectionColor; } + set { _shadowSelectionColor = value; Invalidate(); } + } Color _shadowSelectionColor = Color.FromArgb(100, 60, 188, 255); + + /// + /// Gets the number bytes drawn horizontally. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int HorizontalByteCount + { + get { return _iHexMaxHBytes; } + } + + /// + /// Gets the number bytes drawn vertically. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int VerticalByteCount + { + get { return _iHexMaxVBytes; } + } + + /// + /// Gets the current line + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public long CurrentLine + { + get { return _currentLine; } + } long _currentLine; + + /// + /// Gets the current position in the current line + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public long CurrentPositionInLine + { + get { return _currentPositionInLine; } + } int _currentPositionInLine; + + /// + /// Gets the a value if insertion mode is active or not. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool InsertActive + { + get { return _insertActive; } + set + { + if (_insertActive == value) + return; + + _insertActive = value; + + // recreate caret + DestroyCaret(); + CreateCaret(); + + // raise change event + OnInsertActiveChanged(EventArgs.Empty); + } + } + + /// + /// Gets or sets the built-in context menu. + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public BuiltInContextMenu BuiltInContextMenu + { + get { return _builtInContextMenu; } + } BuiltInContextMenu _builtInContextMenu; + + + /// + /// Gets or sets the converter that will translate between byte and character values. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public IByteCharConverter ByteCharConverter + { + get + { + if (_byteCharConverter == null) + _byteCharConverter = new DefaultByteCharConverter(); + return _byteCharConverter; + } + set + { + if (value != null && value != _byteCharConverter) + { + _byteCharConverter = value; + Invalidate(); + } + } + } IByteCharConverter _byteCharConverter; + + #endregion + + #region Misc + /// + /// Converts a byte array to a hex string. For example: {10,11} = "0A 0B" + /// + /// the byte array + /// the hex string + string ConvertBytesToHex(byte[] data) + { + StringBuilder sb = new StringBuilder(); + foreach (byte b in data) + { + string hex = ConvertByteToHex(b); + sb.Append(hex); + sb.Append(" "); + } + if (sb.Length > 0) + sb.Remove(sb.Length - 1, 1); + string result = sb.ToString(); + return result; + } + /// + /// Converts the byte to a hex string. For example: "10" = "0A"; + /// + /// the byte to format + /// the hex string + string ConvertByteToHex(byte b) + { + string sB = b.ToString(_hexStringFormat, System.Threading.Thread.CurrentThread.CurrentCulture); + if (sB.Length == 1) + sB = "0" + sB; + return sB; + } + /// + /// Converts the hex string to an byte array. The hex string must be separated by a space char ' '. If there is any invalid hex information in the string the result will be null. + /// + /// the hex string separated by ' '. For example: "0A 0B 0C" + /// the byte array. null if hex is invalid or empty + byte[] ConvertHexToBytes(string hex) + { + if (string.IsNullOrEmpty(hex)) + return null; + hex = hex.Trim(); + var hexArray = hex.Split(' '); + var byteArray = new byte[hexArray.Length]; + + for(int i = 0; i < hexArray.Length; i++) + { + var hexValue = hexArray[i]; + + byte b; + var isByte = ConvertHexToByte(hexValue, out b); + if (!isByte) + return null; + byteArray[i] = b; + } + + return byteArray; + } + + bool ConvertHexToByte(string hex, out byte b) + { + bool isByte = byte.TryParse(hex, System.Globalization.NumberStyles.HexNumber, System.Threading.Thread.CurrentThread.CurrentCulture, out b); + return isByte; + } + + void SetPosition(long bytePos) + { + SetPosition(bytePos, _byteCharacterPos); + } + + void SetPosition(long bytePos, int byteCharacterPos) + { + if(_byteCharacterPos != byteCharacterPos) + { + _byteCharacterPos = byteCharacterPos; + } + + if(bytePos != _bytePos) + { + _bytePos = bytePos; + CheckCurrentLineChanged(); + CheckCurrentPositionInLineChanged(); + + OnSelectionStartChanged(EventArgs.Empty); + } + } + + void SetSelectionLength(long selectionLength) + { + if(selectionLength != _selectionLength) + { + _selectionLength = selectionLength; + OnSelectionLengthChanged(EventArgs.Empty); + } + } + + void SetHorizontalByteCount(int value) + { + if(_iHexMaxHBytes == value) + return; + + _iHexMaxHBytes = value; + OnHorizontalByteCountChanged(EventArgs.Empty); + } + + void SetVerticalByteCount(int value) + { + if(_iHexMaxVBytes == value) + return; + + _iHexMaxVBytes = value; + OnVerticalByteCountChanged(EventArgs.Empty); + } + + void CheckCurrentLineChanged() + { + long currentLine = (long)Math.Floor((double)_bytePos / (double)_iHexMaxHBytes) + 1; + + if(_byteProvider == null && _currentLine != 0) + { + _currentLine = 0; + OnCurrentLineChanged(EventArgs.Empty); + } + else if(currentLine != _currentLine) + { + _currentLine = currentLine; + OnCurrentLineChanged(EventArgs.Empty); + } + } + + void CheckCurrentPositionInLineChanged() + { + Point gb = GetGridBytePoint(_bytePos); + int currentPositionInLine = gb.X + 1; + + if(_byteProvider == null && _currentPositionInLine != 0) + { + _currentPositionInLine = 0; + OnCurrentPositionInLineChanged(EventArgs.Empty); + } + else if(currentPositionInLine != _currentPositionInLine) + { + _currentPositionInLine = currentPositionInLine; + OnCurrentPositionInLineChanged(EventArgs.Empty); + } + } + + /// + /// Raises the InsertActiveChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnInsertActiveChanged(EventArgs e) + { + if(InsertActiveChanged != null) + InsertActiveChanged(this, e); + } + + /// + /// Raises the ReadOnlyChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnReadOnlyChanged(EventArgs e) + { + if(ReadOnlyChanged != null) + ReadOnlyChanged(this, e); + } + + /// + /// Raises the ByteProviderChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnByteProviderChanged(EventArgs e) + { + if(ByteProviderChanged != null) + ByteProviderChanged(this, e); + } + + /// + /// Raises the SelectionStartChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnSelectionStartChanged(EventArgs e) + { + if(SelectionStartChanged != null) + SelectionStartChanged(this, e); + } + + /// + /// Raises the SelectionLengthChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnSelectionLengthChanged(EventArgs e) + { + if(SelectionLengthChanged != null) + SelectionLengthChanged(this, e); + } + + /// + /// Raises the LineInfoVisibleChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnLineInfoVisibleChanged(EventArgs e) + { + if(LineInfoVisibleChanged != null) + LineInfoVisibleChanged(this, e); + } + + /// + /// Raises the StringViewVisibleChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnStringViewVisibleChanged(EventArgs e) + { + if(StringViewVisibleChanged != null) + StringViewVisibleChanged(this, e); + } + + /// + /// Raises the BorderStyleChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnBorderStyleChanged(EventArgs e) + { + if(BorderStyleChanged != null) + BorderStyleChanged(this, e); + } + + /// + /// Raises the UseFixedBytesPerLineChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnUseFixedBytesPerLineChanged(EventArgs e) + { + if(UseFixedBytesPerLineChanged != null) + UseFixedBytesPerLineChanged(this, e); + } + + /// + /// Raises the BytesPerLineChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnBytesPerLineChanged(EventArgs e) + { + if(BytesPerLineChanged != null) + BytesPerLineChanged(this, e); + } + + /// + /// Raises the VScrollBarVisibleChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnVScrollBarVisibleChanged(EventArgs e) + { + if(VScrollBarVisibleChanged != null) + VScrollBarVisibleChanged(this, e); + } + + /// + /// Raises the HexCasingChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnHexCasingChanged(EventArgs e) + { + if(HexCasingChanged != null) + HexCasingChanged(this, e); + } + + /// + /// Raises the HorizontalByteCountChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnHorizontalByteCountChanged(EventArgs e) + { + if(HorizontalByteCountChanged != null) + HorizontalByteCountChanged(this, e); + } + + /// + /// Raises the VerticalByteCountChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnVerticalByteCountChanged(EventArgs e) + { + if(VerticalByteCountChanged != null) + VerticalByteCountChanged(this, e); + } + + /// + /// Raises the CurrentLineChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnCurrentLineChanged(EventArgs e) + { + if(CurrentLineChanged != null) + CurrentLineChanged(this, e); + } + + /// + /// Raises the CurrentPositionInLineChanged event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnCurrentPositionInLineChanged(EventArgs e) + { + if(CurrentPositionInLineChanged != null) + CurrentPositionInLineChanged(this, e); + } + + + /// + /// Raises the Copied event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnCopied(EventArgs e) + { + if (Copied != null) + Copied(this, e); + } + + /// + /// Raises the CopiedHex event. + /// + /// An EventArgs that contains the event data. + protected virtual void OnCopiedHex(EventArgs e) + { + if (CopiedHex != null) + CopiedHex(this, e); + } + + /// + /// Raises the MouseDown event. + /// + /// An EventArgs that contains the event data. + protected override void OnMouseDown(MouseEventArgs e) + { + System.Diagnostics.Debug.WriteLine("OnMouseDown()", "HexBox"); + + if(!Focused) + Focus(); + + if(e.Button == MouseButtons.Left) + SetCaretPosition(new Point(e.X, e.Y)); + + base.OnMouseDown (e); + } + + /// + /// Raises the MouseWhell event + /// + /// An EventArgs that contains the event data. + protected override void OnMouseWheel(MouseEventArgs e) + { + int linesToScroll = -(e.Delta * SystemInformation.MouseWheelScrollLines / 120); + this.PerformScrollLines(linesToScroll); + + base.OnMouseWheel (e); + } + + + /// + /// Raises the Resize event. + /// + /// An EventArgs that contains the event data. + protected override void OnResize(EventArgs e) + { + base.OnResize (e); + UpdateRectanglePositioning(); + } + + /// + /// Raises the GotFocus event. + /// + /// An EventArgs that contains the event data. + protected override void OnGotFocus(EventArgs e) + { + System.Diagnostics.Debug.WriteLine("OnGotFocus()", "HexBox"); + + base.OnGotFocus (e); + + CreateCaret(); + } + + /// + /// Raises the LostFocus event. + /// + /// An EventArgs that contains the event data. + protected override void OnLostFocus(EventArgs e) + { + System.Diagnostics.Debug.WriteLine("OnLostFocus()", "HexBox"); + + base.OnLostFocus (e); + + DestroyCaret(); + } + + void _byteProvider_LengthChanged(object sender, EventArgs e) + { + UpdateScrollSize(); + } + #endregion + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.resources b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexBox.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + False + + \ No newline at end of file diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexCasing.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexCasing.cs new file mode 100644 index 0000000..bf007ee --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/HexCasing.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Be.Windows.Forms +{ + /// + /// Specifies the case of hex characters in the HexBox control + /// + public enum HexCasing + { + /// + /// Converts all characters to uppercase. + /// + Upper = 0, + /// + /// Converts all characters to lowercase. + /// + Lower = 1 + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/IByteProvider.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/IByteProvider.cs new file mode 100644 index 0000000..7847ae5 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/IByteProvider.cs @@ -0,0 +1,75 @@ +using System; + +namespace Be.Windows.Forms +{ + /// + /// Defines a byte provider for HexBox control + /// + public interface IByteProvider + { + /// + /// Reads a byte from the provider + /// + /// the index of the byte to read + /// the byte to read + byte ReadByte(long index); + /// + /// Writes a byte into the provider + /// + /// the index of the byte to write + /// the byte to write + void WriteByte(long index, byte value); + /// + /// Inserts bytes into the provider + /// + /// + /// + /// This method must raise the LengthChanged event. + void InsertBytes(long index, byte[] bs); + /// + /// Deletes bytes from the provider + /// + /// the start index of the bytes to delete + /// the length of the bytes to delete + /// This method must raise the LengthChanged event. + void DeleteBytes(long index, long length); + + /// + /// Returns the total length of bytes the byte provider is providing. + /// + long Length { get; } + /// + /// Occurs, when the Length property changed. + /// + event EventHandler LengthChanged; + + /// + /// True, when changes are done. + /// + bool HasChanges(); + /// + /// Applies changes. + /// + void ApplyChanges(); + /// + /// Occurs, when bytes are changed. + /// + event EventHandler Changed; + + /// + /// Returns a value if the WriteByte methods is supported by the provider. + /// + /// True, when it´s supported. + bool SupportsWriteByte(); + /// + /// Returns a value if the InsertBytes methods is supported by the provider. + /// + /// True, when it´s supported. + bool SupportsInsertBytes(); + /// + /// Returns a value if the DeleteBytes methods is supported by the provider. + /// + /// True, when it´s supported. + bool SupportsDeleteBytes(); + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/MemoryDataBlock.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/MemoryDataBlock.cs new file mode 100644 index 0000000..9729267 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/MemoryDataBlock.cs @@ -0,0 +1,87 @@ +using System; + +namespace Be.Windows.Forms +{ + internal sealed class MemoryDataBlock : DataBlock + { + byte[] _data; + + public MemoryDataBlock(byte data) + { + _data = new byte[] { data }; + } + + public MemoryDataBlock(byte[] data) + { + if (data == null) + { + throw new ArgumentNullException("data"); + } + + _data = (byte[])data.Clone(); + } + + public override long Length + { + get + { + return _data.LongLength; + } + } + + public byte[] Data + { + get + { + return _data; + } + } + + public void AddByteToEnd(byte value) + { + byte[] newData = new byte[_data.LongLength + 1]; + _data.CopyTo(newData, 0); + newData[newData.LongLength - 1] = value; + _data = newData; + } + + public void AddByteToStart(byte value) + { + byte[] newData = new byte[_data.LongLength + 1]; + newData[0] = value; + _data.CopyTo(newData, 1); + _data = newData; + } + + public void InsertBytes(long position, byte[] data) + { + byte[] newData = new byte[_data.LongLength + data.LongLength]; + if (position > 0) + { + Array.Copy(_data, 0, newData, 0, position); + } + Array.Copy(data, 0, newData, position, data.LongLength); + if (position < _data.LongLength) + { + Array.Copy(_data, position, newData, position + data.LongLength, _data.LongLength - position); + } + _data = newData; + } + + public override void RemoveBytes(long position, long count) + { + byte[] newData = new byte[_data.LongLength - count]; + + if (position > 0) + { + Array.Copy(_data, 0, newData, 0, position); + } + if (position + count < _data.LongLength) + { + Array.Copy(_data, position + count, newData, position, newData.LongLength - position); + } + + _data = newData; + } + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/NativeMethods.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/NativeMethods.cs new file mode 100644 index 0000000..e678da4 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/NativeMethods.cs @@ -0,0 +1,27 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace Be.Windows.Forms +{ + internal static class NativeMethods + { + // Caret definitions + [DllImport("user32.dll", SetLastError=true)] + public static extern bool CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight); + + [DllImport("user32.dll", SetLastError=true)] + public static extern bool ShowCaret(IntPtr hWnd); + + [DllImport("user32.dll", SetLastError=true)] + public static extern bool DestroyCaret(); + + [DllImport("user32.dll", SetLastError=true)] + public static extern bool SetCaretPos(int X, int Y); + + // Key definitions + public const int WM_KEYDOWN = 0x100; + public const int WM_KEYUP = 0x101; + public const int WM_CHAR = 0x102; + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Properties/Resources.Designer.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Properties/Resources.Designer.cs new file mode 100644 index 0000000..f23b8c5 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Be.Windows.Forms.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Be.Windows.Forms.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Properties/Resources.resx b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Properties/Resources.resx new file mode 100644 index 0000000..7080a7d --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Util.cs b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Util.cs new file mode 100644 index 0000000..1408878 --- /dev/null +++ b/NBTExplorerMac/Vendor/Be.Windows.Forms.HexBox/Util.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Be.Windows.Forms +{ + static class Util + { + /// + /// Contains true, if we are in design mode of Visual Studio + /// + private static bool _designMode; + + /// + /// Initializes an instance of Util class + /// + static Util() + { + _designMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName.ToLower() == "devenv"); + } + + /// + /// Gets true, if we are in design mode of Visual Studio + /// + /// + /// In Visual Studio 2008 SP1 the designer is crashing sometimes on windows forms. + /// The DesignMode property of Control class is buggy and cannot be used, so use our own implementation instead. + /// + public static bool DesignMode + { + get + { + return _designMode; + } + } + + } +} diff --git a/NBTExplorerMac/app.config b/NBTExplorerMac/app.config new file mode 100644 index 0000000..0a7adb0 --- /dev/null +++ b/NBTExplorerMac/app.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/NBTExplorerMac/dead_bush.icns b/NBTExplorerMac/dead_bush.icns new file mode 100644 index 0000000000000000000000000000000000000000..7c08f84ea0a5538d6c472b07ef97236d4ebe0f72 GIT binary patch literal 9100 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 literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/dead_bush.ico b/NBTExplorerMac/dead_bush.ico new file mode 100644 index 0000000000000000000000000000000000000000..64aa5a007566a7df4e2bc61e4abbac0ae8d220fc GIT binary patch literal 17542 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 R-0!Ch-vGYNI7xX4{|_zLR#gB1 literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/forms/About.Designer.cs b/NBTExplorerMac/forms/About.Designer.cs new file mode 100644 index 0000000..4e30769 --- /dev/null +++ b/NBTExplorerMac/forms/About.Designer.cs @@ -0,0 +1,85 @@ +namespace NBTExplorer +{ + partial class About + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(About)); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.linkLabel1.LinkArea = new System.Windows.Forms.LinkArea(0, 0); + this.linkLabel1.Location = new System.Drawing.Point(96, 12); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(245, 120); + this.linkLabel1.TabIndex = 0; + this.linkLabel1.Text = "NBTExplorer\r\nCopyright ©2011-2012 Justin Aquadro\r\n\r\nNBTExplorer is based on NBTEd" + + "it by copyboy\r\nFugue icon set: p.yusukekamiyamane.com\r\n\r\nEmail: jaquadro@gmail.c" + + "om\r\nNBTExplorer Github Project Page"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // pictureBox1 + // + this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image"))); + this.pictureBox1.Location = new System.Drawing.Point(12, 12); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(78, 78); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox1.TabIndex = 1; + this.pictureBox1.TabStop = false; + // + // About + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(350, 144); + this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.linkLabel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "About"; + this.Text = "About NBTExplorer"; + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.PictureBox pictureBox1; + + + } +} \ No newline at end of file diff --git a/NBTExplorerMac/forms/About.cs b/NBTExplorerMac/forms/About.cs new file mode 100644 index 0000000..701e584 --- /dev/null +++ b/NBTExplorerMac/forms/About.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace NBTExplorer +{ + public partial class About : Form + { + public About () + { + InitializeComponent(); + } + + private void linkLabel1_LinkClicked (object sender, LinkLabelLinkClickedEventArgs e) + { + + } + } +} diff --git a/NBTExplorerMac/forms/About.resources b/NBTExplorerMac/forms/About.resources new file mode 100644 index 0000000000000000000000000000000000000000..874989c5b69c55117029fe5e0bc1f81abf7d0712 GIT binary patch literal 1270 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HYRpNw%QN%R^_((GauW-56i|i9 zahQQ|nrWJOnxSEesX?M~Vt}Iy5It#o84I+P!5e6|QUOCILo!1NLn%WMLn?z4Lq0uPz(ed!0!AH1R(c<01wCme5fvD1xbpcia|XCl3{U4EJL|6iwruDS5EH~H7!$_%?DhNkmtI@^zH9tZ35Skt z?N>{`eN~fB|Mcdyuid#PH?PmGnR9aUdh?$alhfn#KNYH--*@lHW1o4odruypY4f{k za=&rqx5ZlBEB5pm$66*mExi*OEjwLx4Xc%&cLaAy%(M++FLvl8>Ru>}JQTIy@urro z4#!hDvm5(P3tgLSvGYr?@!X#G?>tz4T*9J&371J#!s^qjK3ObJ`cb?5+k|~bwGOR% zuUOk1+7f!-`Ip#gj@A3xzvzYuhSl=Fj9#O(=9k>1?GdgKUu~DwyNvfuK6qgcmasdjdbR$L|6cV)f-jj{RM&7Ma%ww89O@F7wm}J0}oxJJ)@7{|a=;mSAcD&@zfpv*@ z|Mr%jF9|u$FEVX|+-%Q?v!#C=5;ZU7_EV+ox#)9&t;ucLK8OtHeJ)d literal 0 HcmV?d00001 diff --git a/NBTExplorerMac/forms/About.resx b/NBTExplorerMac/forms/About.resx new file mode 100644 index 0000000..12983ad --- /dev/null +++ b/NBTExplorerMac/forms/About.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + + + \ No newline at end of file diff --git a/NBTExplorerMac/forms/CancelSearchForm.Designer.cs b/NBTExplorerMac/forms/CancelSearchForm.Designer.cs new file mode 100644 index 0000000..8a8c5de --- /dev/null +++ b/NBTExplorerMac/forms/CancelSearchForm.Designer.cs @@ -0,0 +1,63 @@ +namespace NBTExplorer.Forms +{ + partial class CancelSearchForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + this._buttonCancel = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // _buttonCancel + // + this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this._buttonCancel.Location = new System.Drawing.Point(124, 57); + this._buttonCancel.Name = "_buttonCancel"; + this._buttonCancel.Size = new System.Drawing.Size(75, 23); + this._buttonCancel.TabIndex = 0; + this._buttonCancel.Text = "Cancel"; + this._buttonCancel.UseVisualStyleBackColor = true; + // + // CancelSearchForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this._buttonCancel; + this.ClientSize = new System.Drawing.Size(322, 92); + this.Controls.Add(this._buttonCancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CancelSearchForm"; + this.Text = "Searching..."; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button _buttonCancel; + } +} \ No newline at end of file diff --git a/NBTExplorerMac/forms/CancelSearchForm.cs b/NBTExplorerMac/forms/CancelSearchForm.cs new file mode 100644 index 0000000..8d97d5c --- /dev/null +++ b/NBTExplorerMac/forms/CancelSearchForm.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace NBTExplorer.Forms +{ + public partial class CancelSearchForm : Form + { + public CancelSearchForm () + { + InitializeComponent(); + } + } +} diff --git a/NBTExplorerMac/forms/CancelSearchForm.resources b/NBTExplorerMac/forms/CancelSearchForm.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NBTExplorerMac/forms/CreateNode.Designer.cs b/NBTExplorerMac/forms/CreateNode.Designer.cs new file mode 100644 index 0000000..4435b37 --- /dev/null +++ b/NBTExplorerMac/forms/CreateNode.Designer.cs @@ -0,0 +1,126 @@ +namespace NBTExplorer +{ + partial class CreateNodeForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + this._sizeField = new System.Windows.Forms.TextBox(); + this._sizeFieldLabel = new System.Windows.Forms.Label(); + this._nameFieldLabel = new System.Windows.Forms.Label(); + this._nameField = new System.Windows.Forms.TextBox(); + this._buttonCancel = new System.Windows.Forms.Button(); + this._buttonOK = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // _sizeField + // + this._sizeField.Location = new System.Drawing.Point(56, 26); + this._sizeField.Name = "_sizeField"; + this._sizeField.Size = new System.Drawing.Size(67, 20); + this._sizeField.TabIndex = 7; + // + // _sizeFieldLabel + // + this._sizeFieldLabel.AutoSize = true; + this._sizeFieldLabel.Location = new System.Drawing.Point(12, 29); + this._sizeFieldLabel.Name = "_sizeFieldLabel"; + this._sizeFieldLabel.Size = new System.Drawing.Size(30, 13); + this._sizeFieldLabel.TabIndex = 6; + this._sizeFieldLabel.Text = "Size:"; + // + // _nameFieldLabel + // + this._nameFieldLabel.AutoSize = true; + this._nameFieldLabel.Location = new System.Drawing.Point(12, 9); + this._nameFieldLabel.Name = "_nameFieldLabel"; + this._nameFieldLabel.Size = new System.Drawing.Size(38, 13); + this._nameFieldLabel.TabIndex = 5; + this._nameFieldLabel.Text = "Name:"; + // + // _nameField + // + this._nameField.Location = new System.Drawing.Point(56, 6); + this._nameField.Name = "_nameField"; + this._nameField.Size = new System.Drawing.Size(209, 20); + this._nameField.TabIndex = 4; + // + // _buttonCancel + // + this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this._buttonCancel.Location = new System.Drawing.Point(109, 57); + this._buttonCancel.Name = "_buttonCancel"; + this._buttonCancel.Size = new System.Drawing.Size(75, 23); + this._buttonCancel.TabIndex = 9; + this._buttonCancel.Text = "Cancel"; + this._buttonCancel.UseVisualStyleBackColor = true; + // + // _buttonOK + // + this._buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonOK.Location = new System.Drawing.Point(190, 57); + this._buttonOK.Name = "_buttonOK"; + this._buttonOK.Size = new System.Drawing.Size(75, 23); + this._buttonOK.TabIndex = 8; + this._buttonOK.Text = "OK"; + this._buttonOK.UseVisualStyleBackColor = true; + this._buttonOK.Click += new System.EventHandler(this._buttonOK_Click); + // + // CreateNode + // + this.AcceptButton = this._buttonOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this._buttonCancel; + this.ClientSize = new System.Drawing.Size(277, 92); + this.Controls.Add(this._buttonCancel); + this.Controls.Add(this._buttonOK); + this.Controls.Add(this._sizeField); + this.Controls.Add(this._sizeFieldLabel); + this.Controls.Add(this._nameFieldLabel); + this.Controls.Add(this._nameField); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CreateNode"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.Text = "Create Tag..."; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox _sizeField; + private System.Windows.Forms.Label _sizeFieldLabel; + private System.Windows.Forms.Label _nameFieldLabel; + private System.Windows.Forms.TextBox _nameField; + private System.Windows.Forms.Button _buttonCancel; + private System.Windows.Forms.Button _buttonOK; + } +} \ No newline at end of file diff --git a/NBTExplorerMac/forms/CreateNode.cs b/NBTExplorerMac/forms/CreateNode.cs new file mode 100644 index 0000000..e4418c0 --- /dev/null +++ b/NBTExplorerMac/forms/CreateNode.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using Substrate.Nbt; + +namespace NBTExplorer +{ + public partial class CreateNodeForm : Form + { + private string _name; + private int _size; + private TagType _type; + private TagNode _tag; + + private bool _hasName; + + private List _invalidNames = new List(); + + public CreateNodeForm (TagType tagType) + : this(tagType, true) + { } + + public CreateNodeForm (TagType tagType, bool hasName) + { + InitializeComponent(); + + _type = tagType; + _hasName = hasName; + + SetNameBoxState(); + SetSizeBoxState(); + } + + private void SetNameBoxState () + { + if (HasName) { + _nameFieldLabel.Enabled = true; + _nameField.Enabled = true; + } + else { + _nameFieldLabel.Enabled = false; + _nameField.Enabled = false; + } + } + + private void SetSizeBoxState () + { + if (IsTagSizedType) { + _sizeFieldLabel.Enabled = true; + _sizeField.Enabled = true; + } + else { + _sizeFieldLabel.Enabled = false; + _sizeField.Enabled = false; + } + } + + public string TagName + { + get { return _name; } + } + + public TagNode TagNode + { + get { return _tag; } + } + + public List InvalidNames + { + get { return _invalidNames; } + } + + public bool HasName + { + get { return _hasName; } + } + + private void Apply () + { + if (ValidateInput()) { + _tag = CreateTag(); + + DialogResult = DialogResult.OK; + Close(); + return; + } + } + + private TagNode CreateTag () + { + switch (_type) { + case TagType.TAG_BYTE: + return new TagNodeByte(); + case TagType.TAG_BYTE_ARRAY: + return new TagNodeByteArray(new byte[_size]); + case TagType.TAG_COMPOUND: + return new TagNodeCompound(); + case TagType.TAG_DOUBLE: + return new TagNodeDouble(); + case TagType.TAG_FLOAT: + return new TagNodeFloat(); + case TagType.TAG_INT: + return new TagNodeInt(); + case TagType.TAG_INT_ARRAY: + return new TagNodeIntArray(new int[_size]); + case TagType.TAG_LIST: + return new TagNodeList(TagType.TAG_BYTE); + case TagType.TAG_LONG: + return new TagNodeLong(); + case TagType.TAG_SHORT: + return new TagNodeShort(); + case TagType.TAG_STRING: + return new TagNodeString(); + default: + return new TagNodeByte(); + } + } + + private bool ValidateInput () + { + return ValidateNameInput() + && ValidateSizeInput(); + } + + private bool ValidateNameInput () + { + if (!HasName) + return true; + + string text = _nameField.Text.Trim(); + if (String.IsNullOrEmpty(text)) { + MessageBox.Show("You must provide a nonempty name."); + return false; + } + + if (_invalidNames.Contains(text)) { + MessageBox.Show("Duplicate name provided."); + return false; + } + + _name = _nameField.Text.Trim(); + return true; + } + + private bool ValidateSizeInput () + { + if (!IsTagSizedType) + return true; + + if (!Int32.TryParse(_sizeField.Text.Trim(), out _size)) { + MessageBox.Show("Size must be a valid integer value."); + return false; + } + + _size = Math.Max(0, _size); + return true; + } + + private bool IsTagSizedType + { + get + { + switch (_type) { + case TagType.TAG_BYTE_ARRAY: + case TagType.TAG_INT_ARRAY: + return true; + default: + return false; + } + } + } + + private void _buttonOK_Click (object sender, EventArgs e) + { + Apply(); + } + } +} diff --git a/NBTExplorerMac/forms/CreateNode.resources b/NBTExplorerMac/forms/CreateNode.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NBTExplorerMac/forms/EditHex.Designer.cs b/NBTExplorerMac/forms/EditHex.Designer.cs new file mode 100644 index 0000000..f85faf2 --- /dev/null +++ b/NBTExplorerMac/forms/EditHex.Designer.cs @@ -0,0 +1,130 @@ +namespace NBTExplorer +{ + partial class HexEditor + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + this.hexBox1 = new Be.Windows.Forms.HexBox(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this._curPositionLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this._buttonCancel = new System.Windows.Forms.Button(); + this._buttonOK = new System.Windows.Forms.Button(); + this._curElementLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.statusStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // hexBox1 + // + this.hexBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.hexBox1.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.hexBox1.LineInfoForeColor = System.Drawing.Color.Empty; + this.hexBox1.LineInfoVisible = true; + this.hexBox1.Location = new System.Drawing.Point(12, 12); + this.hexBox1.Name = "hexBox1"; + this.hexBox1.ReadOnly = true; + this.hexBox1.ShadowSelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(60)))), ((int)(((byte)(188)))), ((int)(((byte)(255))))); + this.hexBox1.Size = new System.Drawing.Size(492, 289); + this.hexBox1.TabIndex = 0; + this.hexBox1.VScrollBarVisible = true; + // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this._curPositionLabel, + this._curElementLabel}); + this.statusStrip1.Location = new System.Drawing.Point(0, 333); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Size = new System.Drawing.Size(516, 22); + this.statusStrip1.TabIndex = 1; + this.statusStrip1.Text = "statusStrip1"; + // + // _curPositionLabel + // + this._curPositionLabel.AutoSize = false; + this._curPositionLabel.Name = "_curPositionLabel"; + this._curPositionLabel.Size = new System.Drawing.Size(100, 17); + this._curPositionLabel.Text = "0000"; + // + // _buttonCancel + // + this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this._buttonCancel.Location = new System.Drawing.Point(348, 307); + this._buttonCancel.Name = "_buttonCancel"; + this._buttonCancel.Size = new System.Drawing.Size(75, 23); + this._buttonCancel.TabIndex = 13; + this._buttonCancel.Text = "Cancel"; + this._buttonCancel.UseVisualStyleBackColor = true; + // + // _buttonOK + // + this._buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonOK.Location = new System.Drawing.Point(429, 307); + this._buttonOK.Name = "_buttonOK"; + this._buttonOK.Size = new System.Drawing.Size(75, 23); + this._buttonOK.TabIndex = 12; + this._buttonOK.Text = "OK"; + this._buttonOK.UseVisualStyleBackColor = true; + this._buttonOK.Click += new System.EventHandler(this._buttonOK_Click); + // + // _curElementLabel + // + this._curElementLabel.Name = "_curElementLabel"; + this._curElementLabel.Size = new System.Drawing.Size(59, 17); + this._curElementLabel.Text = "Element 0"; + this._curElementLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // HexEditor + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this._buttonCancel; + this.ClientSize = new System.Drawing.Size(516, 355); + this.Controls.Add(this._buttonCancel); + this.Controls.Add(this._buttonOK); + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.hexBox1); + this.Name = "HexEditor"; + this.Text = "HexEditor"; + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private Be.Windows.Forms.HexBox hexBox1; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripStatusLabel _curPositionLabel; + private System.Windows.Forms.Button _buttonCancel; + private System.Windows.Forms.Button _buttonOK; + private System.Windows.Forms.ToolStripStatusLabel _curElementLabel; + } +} \ No newline at end of file diff --git a/NBTExplorerMac/forms/EditHex.cs b/NBTExplorerMac/forms/EditHex.cs new file mode 100644 index 0000000..ff922cd --- /dev/null +++ b/NBTExplorerMac/forms/EditHex.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using Be.Windows.Forms; + +namespace NBTExplorer +{ + public partial class HexEditor : Form + { + private int _bytesPerElem; + private byte[] _data; + private bool _modified; + DynamicByteProvider _byteProvider; + + private class FixedByteProvider : DynamicByteProvider + { + public FixedByteProvider (byte[] data) + : base(data) + { } + + public override bool SupportsInsertBytes () + { + return false; + } + } + + public HexEditor (string tagName, byte[] data, int bytesPerElem) + { + InitializeComponent(); + + this.Text = "Editing: " + tagName; + + _bytesPerElem = bytesPerElem; + _curPositionLabel.Text = "0x0000"; + _curElementLabel.Text = "Element 0"; + + _data = new byte[data.Length]; + Array.Copy(data, _data, data.Length); + + _byteProvider = new FixedByteProvider(_data); + _byteProvider.Changed += (o, e) => { _modified = true; }; + + hexBox1.ByteProvider = _byteProvider; + + hexBox1.HorizontalByteCountChanged += HexBox_HorizontalByteCountChanged; + hexBox1.CurrentLineChanged += HexBox_CurrentLineChanged; + hexBox1.CurrentPositionInLineChanged += HexBox_CurrentPositionInLineChanged; + + hexBox1.ReadOnly = false; + } + + public byte[] Data + { + get { return _data; } + } + + public bool Modified + { + get { return _modified; } + } + + private void HexBox_HorizontalByteCountChanged (object sender, EventArgs e) + { + UpdatePosition(); + } + + private void HexBox_CurrentLineChanged (object sender, EventArgs e) + { + UpdatePosition(); + } + + private void HexBox_CurrentPositionInLineChanged (object sender, EventArgs e) + { + UpdatePosition(); + } + + private void UpdatePosition () + { + long pos = (hexBox1.CurrentLine - 1) * hexBox1.HorizontalByteCount + hexBox1.CurrentPositionInLine - 1; + + _curPositionLabel.Text = "0x" + pos.ToString("X4"); + _curElementLabel.Text = "Element " + pos / _bytesPerElem; + } + + private void Apply () + { + long len = Math.Min(_data.Length, _byteProvider.Length); + + for (int i = 0; i < len; i++) { + _data[i] = _byteProvider.Bytes[i]; + } + + DialogResult = DialogResult.OK; + Close(); + } + + private void _buttonOK_Click (object sender, EventArgs e) + { + Apply(); + } + } +} diff --git a/NBTExplorerMac/forms/EditHex.resources b/NBTExplorerMac/forms/EditHex.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/NBTExplorerMac/forms/EditName.Designer.cs b/NBTExplorerMac/forms/EditName.Designer.cs new file mode 100644 index 0000000..b817f36 --- /dev/null +++ b/NBTExplorerMac/forms/EditName.Designer.cs @@ -0,0 +1,91 @@ +namespace NBTExplorer +{ + partial class EditName + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + this._nameField = new System.Windows.Forms.TextBox(); + this._buttonCancel = new System.Windows.Forms.Button(); + this._buttonOK = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // _nameField + // + this._nameField.Location = new System.Drawing.Point(12, 10); + this._nameField.Name = "_nameField"; + this._nameField.Size = new System.Drawing.Size(196, 20); + this._nameField.TabIndex = 0; + // + // _buttonCancel + // + this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this._buttonCancel.Location = new System.Drawing.Point(52, 37); + this._buttonCancel.Name = "_buttonCancel"; + this._buttonCancel.Size = new System.Drawing.Size(75, 23); + this._buttonCancel.TabIndex = 11; + this._buttonCancel.Text = "Cancel"; + this._buttonCancel.UseVisualStyleBackColor = true; + // + // _buttonOK + // + this._buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonOK.Location = new System.Drawing.Point(133, 37); + this._buttonOK.Name = "_buttonOK"; + this._buttonOK.Size = new System.Drawing.Size(75, 23); + this._buttonOK.TabIndex = 10; + this._buttonOK.Text = "OK"; + this._buttonOK.UseVisualStyleBackColor = true; + this._buttonOK.Click += new System.EventHandler(this._buttonOK_Click); + // + // EditName + // + this.AcceptButton = this._buttonOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this._buttonCancel; + this.ClientSize = new System.Drawing.Size(220, 72); + this.Controls.Add(this._buttonCancel); + this.Controls.Add(this._buttonOK); + this.Controls.Add(this._nameField); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.KeyPreview = true; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditName"; + this.Text = "Edit Name..."; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox _nameField; + private System.Windows.Forms.Button _buttonCancel; + private System.Windows.Forms.Button _buttonOK; + } +} \ No newline at end of file diff --git a/NBTExplorerMac/forms/EditName.cs b/NBTExplorerMac/forms/EditName.cs new file mode 100644 index 0000000..1525661 --- /dev/null +++ b/NBTExplorerMac/forms/EditName.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using Substrate.Nbt; + +namespace NBTExplorer +{ + public partial class EditName : Form + { + private string _originalName; + private string _name; + + private List _invalidNames = new List(); + + public EditName (String name) + { + InitializeComponent(); + + _originalName = name; + _name = name; + + _nameField.Text = _name; + } + + public String TagName + { + get { return _name; } + } + + public List InvalidNames + { + get { return _invalidNames; } + } + + public bool IsModified + { + get { return _name != _originalName; } + } + + private void Apply () + { + if (ValidateInput()) { + DialogResult = DialogResult.OK; + Close(); + } + } + + private bool ValidateInput () + { + return ValidateNameInput(); + } + + private bool ValidateNameInput () + { + string text = _nameField.Text.Trim(); + if (String.IsNullOrEmpty(text)) { + MessageBox.Show("You must provide a nonempty name."); + return false; + } + + if (text != _originalName && _invalidNames.Contains(text)) { + MessageBox.Show("Duplicate name provided."); + return false; + } + + _name = _nameField.Text.Trim(); + return true; + } + + private void _buttonOK_Click (object sender, EventArgs e) + { + Apply(); + } + } +} diff --git a/NBTExplorerMac/forms/EditName.resources b/NBTExplorerMac/forms/EditName.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NBTExplorerMac/forms/EditString.Designer.cs b/NBTExplorerMac/forms/EditString.Designer.cs new file mode 100644 index 0000000..62a897f --- /dev/null +++ b/NBTExplorerMac/forms/EditString.Designer.cs @@ -0,0 +1,92 @@ +namespace NBTExplorer +{ + partial class EditString + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + this._stringField = new System.Windows.Forms.TextBox(); + this._buttonCancel = new System.Windows.Forms.Button(); + this._buttonOK = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // _stringField + // + this._stringField.Location = new System.Drawing.Point(12, 12); + this._stringField.Multiline = true; + this._stringField.Name = "_stringField"; + this._stringField.Size = new System.Drawing.Size(331, 116); + this._stringField.TabIndex = 4; + // + // _buttonCancel + // + this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this._buttonCancel.Location = new System.Drawing.Point(187, 134); + this._buttonCancel.Name = "_buttonCancel"; + this._buttonCancel.Size = new System.Drawing.Size(75, 23); + this._buttonCancel.TabIndex = 9; + this._buttonCancel.Text = "Cancel"; + this._buttonCancel.UseVisualStyleBackColor = true; + // + // _buttonOK + // + this._buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonOK.Location = new System.Drawing.Point(268, 134); + this._buttonOK.Name = "_buttonOK"; + this._buttonOK.Size = new System.Drawing.Size(75, 23); + this._buttonOK.TabIndex = 8; + this._buttonOK.Text = "OK"; + this._buttonOK.UseVisualStyleBackColor = true; + this._buttonOK.Click += new System.EventHandler(this._buttonOK_Click); + // + // EditString + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this._buttonCancel; + this.ClientSize = new System.Drawing.Size(355, 169); + this.Controls.Add(this._buttonCancel); + this.Controls.Add(this._buttonOK); + this.Controls.Add(this._stringField); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditString"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.Text = "Edit String..."; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox _stringField; + private System.Windows.Forms.Button _buttonCancel; + private System.Windows.Forms.Button _buttonOK; + } +} \ No newline at end of file diff --git a/NBTExplorerMac/forms/EditString.cs b/NBTExplorerMac/forms/EditString.cs new file mode 100644 index 0000000..f61b976 --- /dev/null +++ b/NBTExplorerMac/forms/EditString.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using Substrate.Nbt; + +namespace NBTExplorer +{ + public partial class EditString : Form + { + private string _string; + + public EditString (string stringVal) + { + InitializeComponent(); + + _string = stringVal; + + _stringField.Text = _string; + } + + public string StringValue + { + get { return _string; } + } + + private void Apply () + { + if (ValidateInput()) { + DialogResult = DialogResult.OK; + Close(); + return; + } + } + + private bool ValidateInput () + { + return ValidateStringInput(); + } + + private bool ValidateStringInput () + { + _string = _stringField.Text.Trim(); + return true; + } + + private void _buttonOK_Click (object sender, EventArgs e) + { + Apply(); + } + } +} diff --git a/NBTExplorerMac/forms/EditString.resources b/NBTExplorerMac/forms/EditString.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NBTExplorerMac/forms/EditValue.Designer.cs b/NBTExplorerMac/forms/EditValue.Designer.cs new file mode 100644 index 0000000..eeb6d06 --- /dev/null +++ b/NBTExplorerMac/forms/EditValue.Designer.cs @@ -0,0 +1,91 @@ +namespace NBTExplorer +{ + partial class EditValue + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this._buttonCancel = new System.Windows.Forms.Button(); + this._buttonOK = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(12, 10); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(196, 20); + this.textBox1.TabIndex = 0; + // + // _buttonCancel + // + this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this._buttonCancel.Location = new System.Drawing.Point(52, 37); + this._buttonCancel.Name = "_buttonCancel"; + this._buttonCancel.Size = new System.Drawing.Size(75, 23); + this._buttonCancel.TabIndex = 11; + this._buttonCancel.Text = "Cancel"; + this._buttonCancel.UseVisualStyleBackColor = true; + // + // _buttonOK + // + this._buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonOK.Location = new System.Drawing.Point(133, 37); + this._buttonOK.Name = "_buttonOK"; + this._buttonOK.Size = new System.Drawing.Size(75, 23); + this._buttonOK.TabIndex = 10; + this._buttonOK.Text = "OK"; + this._buttonOK.UseVisualStyleBackColor = true; + this._buttonOK.Click += new System.EventHandler(this._buttonOK_Click); + // + // EditValue + // + this.AcceptButton = this._buttonOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this._buttonCancel; + this.ClientSize = new System.Drawing.Size(220, 72); + this.Controls.Add(this._buttonCancel); + this.Controls.Add(this._buttonOK); + this.Controls.Add(this.textBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.KeyPreview = true; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditValue"; + this.Text = "Edit Value..."; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button _buttonCancel; + private System.Windows.Forms.Button _buttonOK; + } +} \ No newline at end of file diff --git a/NBTExplorerMac/forms/EditValue.cs b/NBTExplorerMac/forms/EditValue.cs new file mode 100644 index 0000000..8d61064 --- /dev/null +++ b/NBTExplorerMac/forms/EditValue.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using Substrate.Nbt; + +namespace NBTExplorer +{ + public partial class EditValue : Form + { + private TagNode _tag; + + public EditValue (TagNode tag) + { + InitializeComponent(); + + _tag = tag; + + if (tag == null) { + DialogResult = DialogResult.Abort; + Close(); + return; + } + + textBox1.Text = _tag.ToString(); + } + + public TagNode NodeTag + { + get { return _tag; } + } + + private void Apply () + { + if (ValidateInput()) { + DialogResult = DialogResult.OK; + Close(); + } + } + + private bool ValidateInput () + { + return ValidateValueInput(); + } + + private bool ValidateValueInput () + { + try { + switch (_tag.GetTagType()) { + case TagType.TAG_BYTE: + _tag.ToTagByte().Data = unchecked((byte)sbyte.Parse(textBox1.Text)); + break; + + case TagType.TAG_SHORT: + _tag.ToTagShort().Data = short.Parse(textBox1.Text); + break; + + case TagType.TAG_INT: + _tag.ToTagInt().Data = int.Parse(textBox1.Text); + break; + + case TagType.TAG_LONG: + _tag.ToTagLong().Data = long.Parse(textBox1.Text); + break; + + case TagType.TAG_FLOAT: + _tag.ToTagFloat().Data = float.Parse(textBox1.Text); + break; + + case TagType.TAG_DOUBLE: + _tag.ToTagDouble().Data = double.Parse(textBox1.Text); + break; + + case TagType.TAG_STRING: + _tag.ToTagString().Data = textBox1.Text; + break; + } + } + catch (FormatException) { + MessageBox.Show("The value is formatted incorrectly for the given type."); + return false; + } + catch (OverflowException) { + MessageBox.Show("The value is outside the acceptable range for the given type."); + return false; + } + catch { + return false; + } + + return true; + } + + private void _buttonOK_Click (object sender, EventArgs e) + { + Apply(); + } + } +} diff --git a/NBTExplorerMac/forms/EditValue.resources b/NBTExplorerMac/forms/EditValue.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NBTExplorerMac/forms/Find.Designer.cs b/NBTExplorerMac/forms/Find.Designer.cs new file mode 100644 index 0000000..75bcd3b --- /dev/null +++ b/NBTExplorerMac/forms/Find.Designer.cs @@ -0,0 +1,133 @@ +namespace NBTExplorer +{ + partial class Find + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + this._cbName = new System.Windows.Forms.CheckBox(); + this._cbValue = new System.Windows.Forms.CheckBox(); + this._textName = new System.Windows.Forms.TextBox(); + this._textValue = new System.Windows.Forms.TextBox(); + this._buttonFind = new System.Windows.Forms.Button(); + this._buttonCancel = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // _cbName + // + this._cbName.AutoSize = true; + this._cbName.Checked = true; + this._cbName.CheckState = System.Windows.Forms.CheckState.Checked; + this._cbName.Location = new System.Drawing.Point(13, 13); + this._cbName.Name = "_cbName"; + this._cbName.Size = new System.Drawing.Size(57, 17); + this._cbName.TabIndex = 0; + this._cbName.Text = "Name:"; + this._cbName.UseVisualStyleBackColor = true; + // + // _cbValue + // + this._cbValue.AutoSize = true; + this._cbValue.Location = new System.Drawing.Point(13, 37); + this._cbValue.Name = "_cbValue"; + this._cbValue.Size = new System.Drawing.Size(56, 17); + this._cbValue.TabIndex = 1; + this._cbValue.Text = "Value:"; + this._cbValue.UseVisualStyleBackColor = true; + // + // _textName + // + this._textName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this._textName.Location = new System.Drawing.Point(76, 12); + this._textName.Name = "_textName"; + this._textName.Size = new System.Drawing.Size(273, 20); + this._textName.TabIndex = 2; + // + // _textValue + // + this._textValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this._textValue.Location = new System.Drawing.Point(76, 34); + this._textValue.Name = "_textValue"; + this._textValue.Size = new System.Drawing.Size(273, 20); + this._textValue.TabIndex = 3; + // + // _buttonFind + // + this._buttonFind.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonFind.Location = new System.Drawing.Point(274, 65); + this._buttonFind.Name = "_buttonFind"; + this._buttonFind.Size = new System.Drawing.Size(75, 23); + this._buttonFind.TabIndex = 4; + this._buttonFind.Text = "Find"; + this._buttonFind.UseVisualStyleBackColor = true; + this._buttonFind.Click += new System.EventHandler(this._buttonFind_Click); + // + // _buttonCancel + // + this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this._buttonCancel.Location = new System.Drawing.Point(193, 65); + this._buttonCancel.Name = "_buttonCancel"; + this._buttonCancel.Size = new System.Drawing.Size(75, 23); + this._buttonCancel.TabIndex = 5; + this._buttonCancel.Text = "Cancel"; + this._buttonCancel.UseVisualStyleBackColor = true; + this._buttonCancel.Click += new System.EventHandler(this._buttonCancel_Click); + // + // Find + // + this.AcceptButton = this._buttonFind; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this._buttonCancel; + this.ClientSize = new System.Drawing.Size(361, 100); + this.Controls.Add(this._buttonCancel); + this.Controls.Add(this._buttonFind); + this.Controls.Add(this._textValue); + this.Controls.Add(this._textName); + this.Controls.Add(this._cbValue); + this.Controls.Add(this._cbName); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "Find"; + this.Text = "Find"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.CheckBox _cbName; + private System.Windows.Forms.CheckBox _cbValue; + private System.Windows.Forms.TextBox _textName; + private System.Windows.Forms.TextBox _textValue; + private System.Windows.Forms.Button _buttonFind; + private System.Windows.Forms.Button _buttonCancel; + } +} \ No newline at end of file diff --git a/NBTExplorerMac/forms/Find.cs b/NBTExplorerMac/forms/Find.cs new file mode 100644 index 0000000..3226d83 --- /dev/null +++ b/NBTExplorerMac/forms/Find.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace NBTExplorer +{ + public partial class Find : Form + { + public Find () + { + InitializeComponent(); + } + + public bool MatchName + { + get { return _cbName.Checked; } + } + + public bool MatchValue + { + get { return _cbValue.Checked; } + } + + public string NameToken + { + get { return _textName.Text; } + } + + public string ValueToken + { + get { return _textValue.Text; } + } + + private void _buttonFind_Click (object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private void _buttonCancel_Click (object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/NBTExplorerMac/forms/Find.resources b/NBTExplorerMac/forms/Find.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Test/AppDelegate.cs b/Test/AppDelegate.cs new file mode 100644 index 0000000..32579a8 --- /dev/null +++ b/Test/AppDelegate.cs @@ -0,0 +1,24 @@ +using System; +using System.Drawing; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +namespace Test +{ + public partial class AppDelegate : NSApplicationDelegate + { + MainWindowController mainWindowController; + + public AppDelegate () + { + } + + public override void FinishedLaunching (NSObject notification) + { + mainWindowController = new MainWindowController (); + mainWindowController.Window.MakeKeyAndOrderFront (this); + } + } +} + diff --git a/Test/AppDelegate.designer.cs b/Test/AppDelegate.designer.cs new file mode 100644 index 0000000..e0d6166 --- /dev/null +++ b/Test/AppDelegate.designer.cs @@ -0,0 +1,10 @@ + +namespace Test +{ + // Should subclass MonoMac.AppKit.NSResponder + [MonoMac.Foundation.Register("AppDelegate")] + public partial class AppDelegate + { + } +} + diff --git a/Test/Info.plist b/Test/Info.plist new file mode 100644 index 0000000..0651d58 --- /dev/null +++ b/Test/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.Test + CFBundleName + Test + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.6 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Test/Main.cs b/Test/Main.cs new file mode 100644 index 0000000..5ed8527 --- /dev/null +++ b/Test/Main.cs @@ -0,0 +1,18 @@ +using System; +using System.Drawing; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +namespace Test +{ + class MainClass + { + static void Main (string[] args) + { + NSApplication.Init (); + NSApplication.Main (args); + } + } +} + diff --git a/Test/MainMenu.xib b/Test/MainMenu.xib new file mode 100644 index 0000000..52d0fd5 --- /dev/null +++ b/Test/MainMenu.xib @@ -0,0 +1,4074 @@ + + + + 1060 + 10D573 + 762 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 762 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + Test + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + MacCocoaApp + + YES + + + About Test + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide Test + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit Test + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + YES + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + YES + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + Test Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + NSFontManager + + + AppDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + terminate: + + + + 449 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + delegate + + + + 534 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + YES + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + + 377 + + + YES + + + + + + 388 + + + YES + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + YES + + + + + + 398 + + + YES + + + + + + 399 + + + YES + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + YES + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + YES + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + YES + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + YES + + + + + + 451 + + + YES + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + YES + + + + + + 491 + + + YES + + + + + + 492 + + + + + 496 + + + YES + + + + + + 497 + + + YES + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + YES + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + YES + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 533 + + + + + + + YES + + YES + -3.IBPluginDependency + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 375.IBPluginDependency + 376.IBEditorWindowLastContentRect + 376.IBPluginDependency + 377.IBPluginDependency + 388.IBEditorWindowLastContentRect + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 418.IBPluginDependency + 419.IBPluginDependency + 450.IBPluginDependency + 451.IBEditorWindowLastContentRect + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 457.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 462.IBPluginDependency + 465.IBPluginDependency + 466.IBPluginDependency + 485.IBPluginDependency + 490.IBPluginDependency + 491.IBEditorWindowLastContentRect + 491.IBPluginDependency + 492.IBPluginDependency + 496.IBPluginDependency + 497.IBEditorWindowLastContentRect + 497.IBPluginDependency + 498.IBPluginDependency + 499.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 500.IBPluginDependency + 501.IBPluginDependency + 502.IBPluginDependency + 503.IBPluginDependency + 504.IBPluginDependency + 505.IBPluginDependency + 506.IBPluginDependency + 507.IBPluginDependency + 508.IBEditorWindowLastContentRect + 508.IBPluginDependency + 509.IBPluginDependency + 510.IBPluginDependency + 511.IBPluginDependency + 512.IBPluginDependency + 513.IBPluginDependency + 514.IBPluginDependency + 515.IBPluginDependency + 516.IBPluginDependency + 517.IBPluginDependency + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 187}, {275, 113}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{453, 408}, {254, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{187, 434}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 217}, {238, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{613, 618}, {194, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{346, 722}, {402, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 978}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{563, 648}, {231, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{746, 287}, {220, 133}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{497, 648}, {83, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{580, 408}, {175, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{753, 197}, {170, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{684, 668}, {142, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{674, 260}, {204, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{878, 180}, {164, 173}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{355, 508}, {183, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{411, 488}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{145, 474}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 534 + + + + YES + + AppDelegate + NSResponder + + IBUserSource + + + + + + YES + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFontManager + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../MacCocoaApp.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/Test/MainWindow.cs b/Test/MainWindow.cs new file mode 100644 index 0000000..da9548f --- /dev/null +++ b/Test/MainWindow.cs @@ -0,0 +1,35 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace Test +{ + public partial class MainWindow : MonoMac.AppKit.NSWindow + { + #region Constructors + + // Called when created from unmanaged code + public MainWindow (IntPtr handle) : base (handle) + { + Initialize (); + } + + // Called when created directly from a XIB file + [Export ("initWithCoder:")] + public MainWindow (NSCoder coder) : base (coder) + { + Initialize (); + } + + // Shared initialization code + void Initialize () + { + } + + #endregion + } +} + diff --git a/Test/MainWindow.designer.cs b/Test/MainWindow.designer.cs new file mode 100644 index 0000000..3d9393d --- /dev/null +++ b/Test/MainWindow.designer.cs @@ -0,0 +1,17 @@ + +namespace Test +{ + + // Should subclass MonoMac.AppKit.NSWindow + [MonoMac.Foundation.Register("MainWindow")] + public partial class MainWindow + { + } + + // Should subclass MonoMac.AppKit.NSWindowController + [MonoMac.Foundation.Register("MainWindowController")] + public partial class MainWindowController + { + } +} + diff --git a/Test/MainWindow.xib b/Test/MainWindow.xib new file mode 100644 index 0000000..060535b --- /dev/null +++ b/Test/MainWindow.xib @@ -0,0 +1,189 @@ + + + + 1060 + 10D573 + 762 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 762 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + MainWindowController + + + FirstResponder + + + NSApplication + + + 15 + 2 + {{131, 74}, {606, 354}} + 611844096 + Window + MainWindow + + {1.79769e+308, 1.79769e+308} + + + 256 + {606, 354} + + + {{0, 0}, {1280, 778}} + {1.79769e+308, 1.79769e+308} + + + + + YES + + + window + + + + 6 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 2 + + + YES + + + + + + 3 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 2.IBEditorWindowLastContentRect + 2.IBPluginDependency + 2.IBWindowTemplateEditedContentRect + 2.NSWindowTemplate.visibleAtLaunch + 3.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{319, 371}, {606, 354}} + com.apple.InterfaceBuilder.CocoaPlugin + {{319, 371}, {606, 354}} + + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 6 + + + + YES + + MainWindow + NSWindow + + IBUserSource + + + + + MainWindowController + NSWindowController + + IBUserSource + + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + + 3 + + diff --git a/Test/MainWindowController.cs b/Test/MainWindowController.cs new file mode 100644 index 0000000..54fb420 --- /dev/null +++ b/Test/MainWindowController.cs @@ -0,0 +1,48 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace Test +{ + public partial class MainWindowController : MonoMac.AppKit.NSWindowController + { + #region Constructors + + // Called when created from unmanaged code + public MainWindowController (IntPtr handle) : base (handle) + { + Initialize (); + } + + // Called when created directly from a XIB file + [Export ("initWithCoder:")] + public MainWindowController (NSCoder coder) : base (coder) + { + Initialize (); + } + + // Call to load from the XIB/NIB file + public MainWindowController () : base ("MainWindow") + { + Initialize (); + } + + // Shared initialization code + void Initialize () + { + } + + #endregion + + //strongly typed window accessor + public new MainWindow Window { + get { + return (MainWindow)base.Window; + } + } + } +} + diff --git a/Test/Resources/scissors.png b/Test/Resources/scissors.png new file mode 100644 index 0000000000000000000000000000000000000000..85f80b593f616145c6210097351749af0faae30b GIT binary patch literal 690 zcmV;j0!{siP)_0@Jsyvq&1RMSBs~xa`1|_$;BvXZ$eMl5$s^w|{oBOr_3HV2UPU4i zU5I`fFtTQ!^L_CjgR7c`NkLG+p={I(g@Ou&Lb}uGyvWF!ea?dhpSqSoPLfZ8O+n(f zk>BU@>BVAEg~Q>+bULkAv!5_{$uK6Z8OjK<^r!s+L_ z#@5!)A4^NY-R0#0>D>@i@J`dlz6=e$Rq?ob($lkk6L`HhJ*^fb3T`bJHT#^CM?Q6} z|KNqD-D?-url!=K#HYa6Gg-knXY|`mS~@W>eN(EtzP+tBH#W-Su~^{o%*>lzVD z;Gq~WvSy!i^2n#Ib(gn+JFA0(MY`UX4Kdkx@}F18ntjg6BcHm~E%<=ZN#L?@23`S) zyTGF4vJ`ym4SsNf!vf1V5IGH8k~}*LJjyBcoI_{(lNU4%;hvH691@s~Xli?jUw;WO Y0K{B8%8@~yF8}}l07*qoM6N<$g8HpcV*mgE literal 0 HcmV?d00001 diff --git a/Test/Test.csproj b/Test/Test.csproj new file mode 100644 index 0000000..5469c1f --- /dev/null +++ b/Test/Test.csproj @@ -0,0 +1,88 @@ + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {C7203DAF-8FEF-4F66-9A6B-4657A85F0B5D} + {948B3504-5B70-4649-8FE4-BDE1FB46EC69};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + Test + Resources + Test + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + False + False + False + False + False + Mac Developer + + + none + True + bin\Release + prompt + 4 + False + False + Full + False + False + False + Mac Developer + + + none + True + bin\AppStore + prompt + 4 + 3rd Party Mac Developer Installer + True + Full + True + False + True + True + 3rd Party Mac Developer Application + + + + + + + + + + + + + + MainWindow.cs + + + + + AppDelegate.cs + + + + + + + + + + + + \ No newline at end of file