diff --git a/NBTExplorer.csproj b/NBTExplorer.csproj index 3008101..101a8a8 100644 --- a/NBTExplorer.csproj +++ b/NBTExplorer.csproj @@ -95,6 +95,12 @@ CancelSearchForm.cs + + UserControl + + + ExplorerBar.cs + Form @@ -226,9 +232,15 @@ ValueRuleForm.cs + + Component + CancelSearchForm.cs + + ExplorerBar.cs + FindReplace.cs diff --git a/NBTExplorer.sln b/NBTExplorer.sln index b3475a7..32c13f4 100644 --- a/NBTExplorer.sln +++ b/NBTExplorer.sln @@ -1,37 +1,31 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBTExplorer", "NBTExplorer.csproj", "{8A458245-8176-4599-95CD-3CA39F2435CE}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBTExplorerMac", "NBTExplorerMac.csproj", "{01F9A296-C477-4CBF-A0D0-41E697048257}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + AppStore|Any CPU = AppStore|Any CPU + AppStore|Mixed Platforms = AppStore|Mixed Platforms + AppStore|x86 = AppStore|x86 Debug|Any CPU = Debug|Any CPU Debug|Mixed Platforms = Debug|Mixed Platforms Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|x86 = Release|x86 - AppStore|Any CPU = AppStore|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {01F9A296-C477-4CBF-A0D0-41E697048257}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.AppStore|Any CPU.Build.0 = AppStore|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|Any CPU.Build.0 = Debug|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|x86.ActiveCfg = Debug|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|x86.Build.0 = Debug|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|Any CPU.ActiveCfg = Release|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|Any CPU.Build.0 = Release|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|x86.ActiveCfg = Release|Any CPU - {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|x86.Build.0 = Release|Any CPU {8A458245-8176-4599-95CD-3CA39F2435CE}.AppStore|Any CPU.ActiveCfg = Debug|x86 {8A458245-8176-4599-95CD-3CA39F2435CE}.AppStore|Any CPU.Build.0 = Debug|x86 + {8A458245-8176-4599-95CD-3CA39F2435CE}.AppStore|Mixed Platforms.ActiveCfg = Release|x86 + {8A458245-8176-4599-95CD-3CA39F2435CE}.AppStore|Mixed Platforms.Build.0 = Release|x86 + {8A458245-8176-4599-95CD-3CA39F2435CE}.AppStore|x86.ActiveCfg = Release|x86 + {8A458245-8176-4599-95CD-3CA39F2435CE}.AppStore|x86.Build.0 = Release|x86 {8A458245-8176-4599-95CD-3CA39F2435CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8A458245-8176-4599-95CD-3CA39F2435CE}.Debug|Any CPU.Build.0 = Debug|Any CPU {8A458245-8176-4599-95CD-3CA39F2435CE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -44,11 +38,27 @@ Global {8A458245-8176-4599-95CD-3CA39F2435CE}.Release|Mixed Platforms.Build.0 = Release|Any CPU {8A458245-8176-4599-95CD-3CA39F2435CE}.Release|x86.ActiveCfg = Release|x86 {8A458245-8176-4599-95CD-3CA39F2435CE}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = NBTExplorerMac.csproj + {01F9A296-C477-4CBF-A0D0-41E697048257}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.AppStore|Any CPU.Build.0 = AppStore|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.AppStore|Mixed Platforms.ActiveCfg = AppStore|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|x86.ActiveCfg = Debug|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Debug|x86.Build.0 = Debug|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|Any CPU.Build.0 = Release|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|x86.ActiveCfg = Release|Any CPU + {01F9A296-C477-4CBF-A0D0-41E697048257}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = NBTExplorerMac.csproj + EndGlobalSection EndGlobal diff --git a/Windows/EditHex.Designer.cs b/Windows/EditHex.Designer.cs index 1df36d4..5b51d7e 100644 --- a/Windows/EditHex.Designer.cs +++ b/Windows/EditHex.Designer.cs @@ -28,34 +28,41 @@ private void InitializeComponent () { this.statusStrip1 = new System.Windows.Forms.StatusStrip(); - this._curPositionLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this._curElementLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this._space = new System.Windows.Forms.ToolStripStatusLabel(); - this._insertStateLabel = new System.Windows.Forms.ToolStripStatusLabel(); + //this._curPositionLabel = new System.Windows.Forms.ToolStripStatusLabel(); + //this._curElementLabel = new System.Windows.Forms.ToolStripStatusLabel(); + //this._space = new System.Windows.Forms.ToolStripStatusLabel(); + //this._insertStateLabel = new System.Windows.Forms.ToolStripStatusLabel(); this._buttonCancel = new System.Windows.Forms.Button(); this._buttonOK = new System.Windows.Forms.Button(); - this.hexBox1 = new Be.Windows.Forms.HexBox(); + //this.hexBox1 = new Be.Windows.Forms.HexBox(); this._buttonImport = new System.Windows.Forms.Button(); this._buttonExport = new System.Windows.Forms.Button(); + this.viewTabs = new System.Windows.Forms.TabControl(); + //this.textView = new System.Windows.Forms.TabPage(); + //this.textBox1 = new System.Windows.Forms.TextBox(); + //this.hexView = new System.Windows.Forms.TabPage(); this.statusStrip1.SuspendLayout(); + this.viewTabs.SuspendLayout(); + //this.textView.SuspendLayout(); + //this.hexView.SuspendLayout(); this.SuspendLayout(); // // statusStrip1 // - this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + /*this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this._curPositionLabel, this._curElementLabel, this._space, - this._insertStateLabel}); + this._insertStateLabel});*/ this.statusStrip1.Location = new System.Drawing.Point(0, 333); this.statusStrip1.Name = "statusStrip1"; - this.statusStrip1.Size = new System.Drawing.Size(516, 22); + this.statusStrip1.Size = new System.Drawing.Size(532, 22); this.statusStrip1.TabIndex = 1; this.statusStrip1.Text = "statusStrip1"; // // _curPositionLabel // - this._curPositionLabel.AutoSize = false; + /*this._curPositionLabel.AutoSize = false; this._curPositionLabel.Name = "_curPositionLabel"; this._curPositionLabel.Size = new System.Drawing.Size(100, 17); this._curPositionLabel.Text = "0000"; @@ -70,20 +77,20 @@ // _space // this._space.Name = "_space"; - this._space.Size = new System.Drawing.Size(284, 17); + this._space.Size = new System.Drawing.Size(300, 17); this._space.Spring = true; // // _insertStateLabel // this._insertStateLabel.Name = "_insertStateLabel"; this._insertStateLabel.Size = new System.Drawing.Size(58, 17); - this._insertStateLabel.Text = "Overwrite"; + this._insertStateLabel.Text = "Overwrite";*/ // // _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.Location = new System.Drawing.Point(364, 307); this._buttonCancel.Name = "_buttonCancel"; this._buttonCancel.Size = new System.Drawing.Size(75, 23); this._buttonCancel.TabIndex = 13; @@ -93,7 +100,7 @@ // _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.Location = new System.Drawing.Point(445, 307); this._buttonOK.Name = "_buttonOK"; this._buttonOK.Size = new System.Drawing.Size(75, 23); this._buttonOK.TabIndex = 12; @@ -103,19 +110,19 @@ // // hexBox1 // - this.hexBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + /*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.Location = new System.Drawing.Point(0, 0); 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.Size = new System.Drawing.Size(500, 263); this.hexBox1.TabIndex = 0; - this.hexBox1.VScrollBarVisible = true; + this.hexBox1.VScrollBarVisible = true;*/ // // _buttonImport // @@ -137,22 +144,73 @@ this._buttonExport.UseVisualStyleBackColor = true; this._buttonExport.Click += new System.EventHandler(this._buttonExport_Click); // + // viewTabs + // + //this.viewTabs.Controls.Add(this.textView); + //this.viewTabs.Controls.Add(this.hexView); + this.viewTabs.Location = new System.Drawing.Point(12, 12); + this.viewTabs.Name = "viewTabs"; + this.viewTabs.SelectedIndex = 0; + this.viewTabs.Size = new System.Drawing.Size(508, 289); + this.viewTabs.TabIndex = 16; + // + // textView + // + /*this.textView.Controls.Add(this.textBox1); + this.textView.Location = new System.Drawing.Point(4, 22); + this.textView.Name = "textView"; + this.textView.Padding = new System.Windows.Forms.Padding(3); + this.textView.Size = new System.Drawing.Size(500, 263); + this.textView.TabIndex = 1; + this.textView.Text = "Text View"; + this.textView.UseVisualStyleBackColor = true;*/ + // + // textBox1 + // + /*this.textBox1.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.textBox1.Location = new System.Drawing.Point(0, 0); + this.textBox1.Margin = new System.Windows.Forms.Padding(0); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.textBox1.Size = new System.Drawing.Size(500, 263); + this.textBox1.TabIndex = 0;*/ + // + // hexView + // + /*this.hexView.Controls.Add(this.hexBox1); + this.hexView.Location = new System.Drawing.Point(4, 22); + this.hexView.Name = "hexView"; + this.hexView.Padding = new System.Windows.Forms.Padding(3); + this.hexView.Size = new System.Drawing.Size(500, 263); + this.hexView.TabIndex = 0; + this.hexView.Text = "Hex View"; + this.hexView.UseVisualStyleBackColor = true;*/ + // // 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.ClientSize = new System.Drawing.Size(532, 355); + this.Controls.Add(this.viewTabs); this.Controls.Add(this._buttonExport); this.Controls.Add(this._buttonImport); this.Controls.Add(this._buttonCancel); this.Controls.Add(this._buttonOK); this.Controls.Add(this.statusStrip1); - this.Controls.Add(this.hexBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.Name = "HexEditor"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.Text = "HexEditor"; this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); + this.viewTabs.ResumeLayout(false); + //this.textView.ResumeLayout(false); + //this.textView.PerformLayout(); + //this.hexView.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -160,15 +218,19 @@ #endregion - private Be.Windows.Forms.HexBox hexBox1; + //private Be.Windows.Forms.HexBox hexBox1; private System.Windows.Forms.StatusStrip statusStrip1; - private System.Windows.Forms.ToolStripStatusLabel _curPositionLabel; + //private System.Windows.Forms.ToolStripStatusLabel _curPositionLabel; private System.Windows.Forms.Button _buttonCancel; private System.Windows.Forms.Button _buttonOK; - private System.Windows.Forms.ToolStripStatusLabel _curElementLabel; - private System.Windows.Forms.ToolStripStatusLabel _space; - private System.Windows.Forms.ToolStripStatusLabel _insertStateLabel; + //private System.Windows.Forms.ToolStripStatusLabel _curElementLabel; + //private System.Windows.Forms.ToolStripStatusLabel _space; + //private System.Windows.Forms.ToolStripStatusLabel _insertStateLabel; private System.Windows.Forms.Button _buttonImport; private System.Windows.Forms.Button _buttonExport; + private System.Windows.Forms.TabControl viewTabs; + //private System.Windows.Forms.TabPage textView; + //private System.Windows.Forms.TextBox textBox1; + //private System.Windows.Forms.TabPage hexView; } } \ No newline at end of file diff --git a/Windows/EditHex.cs b/Windows/EditHex.cs index 9adce63..981939a 100644 --- a/Windows/EditHex.cs +++ b/Windows/EditHex.cs @@ -5,15 +5,238 @@ using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Text; +using System.Drawing; namespace NBTExplorer.Windows { public partial class HexEditor : Form { - private int _bytesPerElem; - private byte[] _data; - private bool _modified; - DynamicByteProvider _byteProvider; + private abstract class EditView + { + protected EditView (StatusStrip statusBar, int bytesPerElem) + { + BytesPerElem = bytesPerElem; + StatusBar = statusBar; + } + + public event EventHandler Modified; + + public int BytesPerElem { get; set; } + public StatusStrip StatusBar { get; set; } + + public abstract TabPage TabPage { get; } + + public abstract void Initialize (); + public abstract void Activate (); + public abstract byte[] GetRawData (); + public abstract void SetRawData (byte[] data); + + protected virtual void OnModified () + { + var ev = Modified; + if (ev != null) + ev(this, EventArgs.Empty); + } + } + + private class TextView : EditView + { + private TabPage _tabPage; + private TextBox _textBox; + + private ToolStripStatusLabel _elementLabel; + private ToolStripStatusLabel _spaceLabel; + + public TextView (StatusStrip statusBar, int bytesPerElem) + : base(statusBar, bytesPerElem) + { } + + public override void Initialize () + { + _textBox = new TextBox() { + Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right, + Font = new Font("Courier New", 9F, FontStyle.Regular, GraphicsUnit.Point, 0), + Location = new Point(0, 0), + Margin = new Padding(0), + Multiline = true, + ScrollBars = ScrollBars.Vertical, + Size = new Size(500, 263), + TabIndex = 0, + }; + + _tabPage = new TabPage() { + Location = new Point(4, 22), + Padding = new Padding(3), + Size = new Size(500, 263), + TabIndex = 1, + Text = "Text View", + UseVisualStyleBackColor = true, + }; + + _tabPage.Controls.Add(_textBox); + + _textBox.TextChanged += (s, e) => { OnModified(); }; + + InitializeStatusBar(); + } + + private void InitializeStatusBar () + { + _elementLabel = new ToolStripStatusLabel() { + Size = new Size(100, 17), + Text = "Element 0", + TextAlign = ContentAlignment.MiddleLeft, + }; + + _spaceLabel = new ToolStripStatusLabel() { + Spring = true, + }; + } + + public override void Activate () + { + StatusBar.Items.Clear(); + StatusBar.Items.AddRange(new ToolStripItem[] { + _elementLabel, _spaceLabel, + }); + } + + public override TabPage TabPage + { + get { return _tabPage; } + } + + public override byte[] GetRawData () + { + return HexEditor.TextToRaw(_textBox.Text, BytesPerElem); + } + + public override void SetRawData (byte[] data) + { + _textBox.Text = HexEditor.RawToText(data, BytesPerElem); + } + } + + private class HexView : EditView + { + private TabPage _tabPage; + private HexBox _hexBox; + + private ToolStripStatusLabel _positionLabel; + private ToolStripStatusLabel _elementLabel; + private ToolStripStatusLabel _spaceLabel; + private ToolStripStatusLabel _insertLabel; + + private DynamicByteProvider _byteProvider; + + public HexView (StatusStrip statusBar, int bytesPerElem) + : base(statusBar, bytesPerElem) + { } + + public override void Initialize () + { + _byteProvider = new DynamicByteProvider(new byte[0]); + _byteProvider.Changed += (o, e) => { OnModified(); }; + + _hexBox = new HexBox() { + Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right, + Font = new Font("Courier New", 9F, FontStyle.Regular, GraphicsUnit.Point, 0), + LineInfoForeColor = Color.Empty, + LineInfoVisible = true, + Location = new Point(0, 0), + ShadowSelectionColor = Color.FromArgb(100, 60, 188, 255), + Size = new Size(500, 263), + TabIndex = 0, + VScrollBarVisible = true, + ByteProvider = _byteProvider, + }; + + _tabPage = new TabPage() { + Location = new Point(4, 22), + Padding = new Padding(3), + Size = new Size(500, 263), + TabIndex = 0, + Text = "Hex View", + UseVisualStyleBackColor = true, + }; + + _tabPage.Controls.Add(_hexBox); + + _hexBox.HorizontalByteCountChanged += (s, e) => { UpdatePosition(); }; + _hexBox.CurrentLineChanged += (s, e) => { UpdatePosition(); }; + _hexBox.CurrentPositionInLineChanged += (s, e) => { UpdatePosition(); }; + + _hexBox.InsertActiveChanged += (s, e) => { _insertLabel.Text = (_hexBox.InsertActive) ? "Insert" : "Overwrite"; }; + + InitializeStatusBar(); + } + + private void InitializeStatusBar () + { + _positionLabel = new ToolStripStatusLabel() { + AutoSize = false, + Size = new Size(100, 17), + Text = "0000", + }; + + _elementLabel = new ToolStripStatusLabel() { + Size = new Size(59, 17), + Text = "Element 0", + TextAlign = ContentAlignment.MiddleLeft, + }; + + _spaceLabel = new ToolStripStatusLabel() { + Size = new Size(300, 17), + Spring = true, + }; + + _insertLabel = new ToolStripStatusLabel() { + Size = new Size(58, 17), + Text = (_hexBox.InsertActive) ? "Insert" : "Overwrite", + }; + } + + public override void Activate () + { + StatusBar.Items.Clear(); + StatusBar.Items.AddRange(new ToolStripItem[] { + _positionLabel, _elementLabel, _spaceLabel, _insertLabel, + }); + + UpdatePosition(); + } + + public override TabPage TabPage + { + get { return _tabPage; } + } + + public override byte[] GetRawData () + { + byte[] data = new byte[_byteProvider.Length]; + for (int i = 0; i < data.Length; i++) { + data[i] = _byteProvider.Bytes[i]; + } + + return data; + } + + public override void SetRawData (byte[] data) + { + _byteProvider = new DynamicByteProvider(data); + _byteProvider.Changed += (o, e2) => { OnModified(); }; + + _hexBox.ByteProvider = _byteProvider; + } + + private void UpdatePosition () + { + long pos = (_hexBox.CurrentLine - 1) * _hexBox.HorizontalByteCount + _hexBox.CurrentPositionInLine - 1; + + _positionLabel.Text = "0x" + pos.ToString("X4"); + _elementLabel.Text = "Element " + pos / BytesPerElem; + } + } private class FixedByteProvider : DynamicByteProvider { @@ -27,30 +250,61 @@ namespace NBTExplorer.Windows } } + private TabPage _previousPage; + private int _bytesPerElem; + private byte[] _data; + private bool _modified; + //DynamicByteProvider _byteProvider; + + private Dictionary _views = new Dictionary(); + public HexEditor (string tagName, byte[] data, int bytesPerElem) { InitializeComponent(); + TextView textView = new TextView(statusStrip1, bytesPerElem); + textView.Initialize(); + _views.Add(textView.TabPage, textView); + viewTabs.TabPages.Add(textView.TabPage); + + if (!IsMono()) { + HexView hexView = new HexView(statusStrip1, bytesPerElem); + hexView.Initialize(); + _views.Add(hexView.TabPage, hexView); + viewTabs.TabPages.Add(hexView.TabPage); + } + + viewTabs.Deselected += (o, e) => { _previousPage = e.TabPage; }; + viewTabs.Selecting += HandleTabChanged; + //textBox1.TextChanged += (o, e) => { _modified = true; }; + this.Text = "Editing: " + tagName; _bytesPerElem = bytesPerElem; - _curPositionLabel.Text = "0x0000"; - _curElementLabel.Text = "Element 0"; + //_curPositionLabel.Text = "0x0000"; + //_curElementLabel.Text = "Element 0"; _data = new byte[data.Length]; Array.Copy(data, _data, data.Length); - _byteProvider = new DynamicByteProvider(_data); - _byteProvider.Changed += (o, e) => { _modified = true; }; + //_byteProvider = new DynamicByteProvider(_data); + //_byteProvider.Changed += (o, e) => { _modified = true; }; - hexBox1.ByteProvider = _byteProvider; + //hexBox1.ByteProvider = _byteProvider; - hexBox1.HorizontalByteCountChanged += HexBox_HorizontalByteCountChanged; - hexBox1.CurrentLineChanged += HexBox_CurrentLineChanged; - hexBox1.CurrentPositionInLineChanged += HexBox_CurrentPositionInLineChanged; - hexBox1.InsertActiveChanged += HexBox_InsertActiveChanged; + //hexBox1.HorizontalByteCountChanged += HexBox_HorizontalByteCountChanged; + //hexBox1.CurrentLineChanged += HexBox_CurrentLineChanged; + //hexBox1.CurrentPositionInLineChanged += HexBox_CurrentPositionInLineChanged; + //hexBox1.InsertActiveChanged += HexBox_InsertActiveChanged; - hexBox1.ReadOnly = false; + //hexBox1.ReadOnly = false; + + //textBox1.Text = RawToText(data); + } + + private bool IsMono () + { + return Type.GetType("Mono.Runtime") != null; } public byte[] Data @@ -63,7 +317,49 @@ namespace NBTExplorer.Windows get { return _modified; } } - private void HexBox_HorizontalByteCountChanged (object sender, EventArgs e) + private void HandleTabChanged (object sender, TabControlCancelEventArgs e) + { + if (e.Action != TabControlAction.Selecting) + return; + + if (e.TabPage == _previousPage) + return; + + EditView oldView = _views[_previousPage]; + EditView newView = _views[e.TabPage]; + + byte[] data = oldView.GetRawData(); + newView.SetRawData(data); + + newView.Activate(); + + /*if (e.TabPage == textView) { + if (_previousPage == textView) + return; + + byte[] data = DataFromHexBox(); + textBox1.Text = RawToText(data); + + _insertStateLabel.Text = "Insert"; + } + else if (e.TabPage == hexView) { + if (_previousPage == hexView) + return; + + byte[] data = TextToRaw(textBox1.Text); + _byteProvider = new DynamicByteProvider(data); + _byteProvider.Changed += (o, e2) => { _modified = true; }; + + hexBox1.ByteProvider = _byteProvider; + + if (hexBox1.InsertActive) + _insertStateLabel.Text = "Insert"; + else + _insertStateLabel.Text = "Overwrite"; + }*/ + } + + /*private void HexBox_HorizontalByteCountChanged (object sender, EventArgs e) { UpdatePosition(); } @@ -92,9 +388,18 @@ namespace NBTExplorer.Windows _curPositionLabel.Text = "0x" + pos.ToString("X4"); _curElementLabel.Text = "Element " + pos / _bytesPerElem; - } + }*/ private void Apply () + { + EditView view = _views[viewTabs.SelectedTab]; + _data = view.GetRawData(); + + DialogResult = DialogResult.OK; + Close(); + } + + /*private void ApplyHex () { if (_data.Length != _byteProvider.Length) _data = new byte[_byteProvider.Length]; @@ -107,45 +412,94 @@ namespace NBTExplorer.Windows Close(); } + private void ApplyText () + { + _data = TextToRaw(textBox1.Text); + + DialogResult = DialogResult.OK; + Close(); + }*/ + + /*private byte[] DataFromHexBox () + { + byte[] data = new byte[_byteProvider.Length]; + for (int i = 0; i < data.Length; i++) { + data[i] = _byteProvider.Bytes[i]; + } + + return data; + }*/ + private String RawToText (byte[] data) + { + return RawToText(data, _bytesPerElem); + } + + private static String RawToText (byte[] data, int bytesPerElem) + { + switch (bytesPerElem) { + case 1: return RawToText(data, bytesPerElem, 16); + case 2: return RawToText(data, bytesPerElem, 8); + case 4: return RawToText(data, bytesPerElem, 4); + case 8: return RawToText(data, bytesPerElem, 2); + default: return RawToText(data, bytesPerElem, 1); + } + } + + //private String RawToText (byte[] data, int elementsPerLine) + //{ + // return RawToText(data, _bytesPerElem, elementsPerLine); + //} + + private static String RawToText (byte[] data, int bytesPerElem, int elementsPerLine) { StringBuilder builder = new StringBuilder(); - for (int i = 0; i < data.Length; i += _bytesPerElem) { - if (data.Length - i < _bytesPerElem) + for (int i = 0; i < data.Length; i += bytesPerElem) { + if (data.Length - i < bytesPerElem) break; - switch (_bytesPerElem) { + switch (bytesPerElem) { case 1: - builder.AppendLine(((sbyte)data[i]).ToString()); + builder.Append(((sbyte)data[i]).ToString()); break; case 2: - builder.AppendLine(BitConverter.ToInt16(data, i).ToString()); + builder.Append(BitConverter.ToInt16(data, i).ToString()); break; case 4: - builder.AppendLine(BitConverter.ToInt32(data, i).ToString()); + builder.Append(BitConverter.ToInt32(data, i).ToString()); break; case 8: - builder.AppendLine(BitConverter.ToInt64(data, i).ToString()); + builder.Append(BitConverter.ToInt64(data, i).ToString()); break; } + + if ((i / bytesPerElem) % elementsPerLine == elementsPerLine - 1) + builder.AppendLine(); + else + builder.Append(" "); } return builder.ToString(); } private byte[] TextToRaw (string text) + { + return TextToRaw(text, _bytesPerElem); + } + + private static byte[] TextToRaw (string text, int bytesPerElem) { string[] items = text.Split(null as char[], StringSplitOptions.RemoveEmptyEntries); - byte[] data = new byte[_bytesPerElem * items.Length]; + byte[] data = new byte[bytesPerElem * items.Length]; for (int i = 0; i < items.Length; i++) { - int index = i * _bytesPerElem; + int index = i * bytesPerElem; - switch (_bytesPerElem) { + switch (bytesPerElem) { case 1: sbyte val1; if (sbyte.TryParse(items[i], out val1)) diff --git a/Windows/FindReplace.Designer.cs b/Windows/FindReplace.Designer.cs index 0cdba2d..3557096 100644 --- a/Windows/FindReplace.Designer.cs +++ b/Windows/FindReplace.Designer.cs @@ -70,6 +70,8 @@ this._buttonReplace = new System.Windows.Forms.Button(); this._buttonReplaceAll = new System.Windows.Forms.Button(); this._buttonCancel = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this._explorerStrip = new System.Windows.Forms.ToolStrip(); this.groupBox1.SuspendLayout(); this.panel1.SuspendLayout(); this.toolStrip1.SuspendLayout(); @@ -83,9 +85,9 @@ this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.groupBox1.Controls.Add(this.panel1); - this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Location = new System.Drawing.Point(12, 46); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(439, 180); + this.groupBox1.Size = new System.Drawing.Size(450, 146); this.groupBox1.TabIndex = 0; this.groupBox1.TabStop = false; this.groupBox1.Text = "Find"; @@ -98,7 +100,7 @@ this.panel1.Controls.Add(this.toolStrip1); this.panel1.Location = new System.Drawing.Point(6, 19); this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(427, 155); + this.panel1.Size = new System.Drawing.Size(438, 155); this.panel1.TabIndex = 0; // // treeView1 @@ -112,7 +114,7 @@ this.treeView1.SelectedImageIndex = 0; this.treeView1.ShowPlusMinus = false; this.treeView1.ShowRootLines = false; - this.treeView1.Size = new System.Drawing.Size(427, 130); + this.treeView1.Size = new System.Drawing.Size(438, 130); this.treeView1.TabIndex = 1; // // imageList1 @@ -160,7 +162,7 @@ this._tbFindString}); this.toolStrip1.Location = new System.Drawing.Point(0, 0); this.toolStrip1.Name = "toolStrip1"; - this.toolStrip1.Size = new System.Drawing.Size(427, 25); + this.toolStrip1.Size = new System.Drawing.Size(438, 25); this.toolStrip1.TabIndex = 0; this.toolStrip1.Text = "toolStrip1"; // @@ -302,7 +304,7 @@ this.groupBox2.Controls.Add(this.panel2); this.groupBox2.Location = new System.Drawing.Point(12, 198); this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(439, 182); + this.groupBox2.Size = new System.Drawing.Size(450, 184); this.groupBox2.TabIndex = 1; this.groupBox2.TabStop = false; this.groupBox2.Text = "Replace"; @@ -316,7 +318,7 @@ this.panel2.Controls.Add(this.toolStrip2); this.panel2.Location = new System.Drawing.Point(6, 19); this.panel2.Name = "panel2"; - this.panel2.Size = new System.Drawing.Size(427, 157); + this.panel2.Size = new System.Drawing.Size(438, 159); this.panel2.TabIndex = 0; // // treeView2 @@ -330,7 +332,7 @@ this.treeView2.SelectedImageIndex = 0; this.treeView2.ShowPlusMinus = false; this.treeView2.ShowRootLines = false; - this.treeView2.Size = new System.Drawing.Size(427, 132); + this.treeView2.Size = new System.Drawing.Size(438, 134); this.treeView2.TabIndex = 1; // // toolStrip2 @@ -353,7 +355,7 @@ this._tbReplaceCompound}); this.toolStrip2.Location = new System.Drawing.Point(0, 0); this.toolStrip2.Name = "toolStrip2"; - this.toolStrip2.Size = new System.Drawing.Size(427, 25); + this.toolStrip2.Size = new System.Drawing.Size(438, 25); this.toolStrip2.TabIndex = 0; this.toolStrip2.Text = "toolStrip2"; // @@ -495,7 +497,7 @@ // _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(295, 386); + this._buttonFind.Location = new System.Drawing.Point(306, 388); this._buttonFind.Name = "_buttonFind"; this._buttonFind.Size = new System.Drawing.Size(75, 23); this._buttonFind.TabIndex = 2; @@ -506,7 +508,7 @@ // _buttonReplace // this._buttonReplace.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this._buttonReplace.Location = new System.Drawing.Point(376, 386); + this._buttonReplace.Location = new System.Drawing.Point(387, 388); this._buttonReplace.Name = "_buttonReplace"; this._buttonReplace.Size = new System.Drawing.Size(75, 23); this._buttonReplace.TabIndex = 3; @@ -518,7 +520,7 @@ // this._buttonReplaceAll.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this._buttonReplaceAll.Enabled = false; - this._buttonReplaceAll.Location = new System.Drawing.Point(376, 415); + this._buttonReplaceAll.Location = new System.Drawing.Point(387, 417); this._buttonReplaceAll.Name = "_buttonReplaceAll"; this._buttonReplaceAll.Size = new System.Drawing.Size(75, 23); this._buttonReplaceAll.TabIndex = 4; @@ -529,7 +531,7 @@ // _buttonCancel // this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this._buttonCancel.Location = new System.Drawing.Point(12, 386); + this._buttonCancel.Location = new System.Drawing.Point(12, 388); this._buttonCancel.Name = "_buttonCancel"; this._buttonCancel.Size = new System.Drawing.Size(75, 23); this._buttonCancel.TabIndex = 5; @@ -537,11 +539,29 @@ this._buttonCancel.UseVisualStyleBackColor = true; this._buttonCancel.Click += new System.EventHandler(this._buttonCancel_Click); // + // label1 + // + this.label1.Location = new System.Drawing.Point(12, 420); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(358, 18); + this.label1.TabIndex = 6; + this.label1.Text = "Search Root: blahblahbnl/blf"; + // + // _explorerStrip + // + this._explorerStrip.Location = new System.Drawing.Point(0, 0); + this._explorerStrip.Name = "_explorerStrip"; + this._explorerStrip.Size = new System.Drawing.Size(474, 25); + this._explorerStrip.TabIndex = 7; + this._explorerStrip.Text = "toolStrip3"; + // // FindReplace // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(463, 449); + this.ClientSize = new System.Drawing.Size(474, 451); + this.Controls.Add(this._explorerStrip); + this.Controls.Add(this.label1); this.Controls.Add(this._buttonCancel); this.Controls.Add(this._buttonReplaceAll); this.Controls.Add(this._buttonReplace); @@ -561,6 +581,7 @@ this.toolStrip2.ResumeLayout(false); this.toolStrip2.PerformLayout(); this.ResumeLayout(false); + this.PerformLayout(); } @@ -607,5 +628,7 @@ private System.Windows.Forms.ToolStripButton _tbFindGroupOr; private System.Windows.Forms.ToolStripButton _tbFindEdit; private System.Windows.Forms.ToolStripButton _tbReplaceEdit; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ToolStrip _explorerStrip; } } \ No newline at end of file diff --git a/Windows/FindReplace.cs b/Windows/FindReplace.cs index 22264ee..6a96dc1 100644 --- a/Windows/FindReplace.cs +++ b/Windows/FindReplace.cs @@ -36,6 +36,8 @@ namespace NBTExplorer.Windows _replaceController = new NodeTreeController(treeView2); _replaceController.VirtualRootDisplay = "Replacement Tags"; + + _explorerStrip.Renderer = new ToolStripExplorerRenderer(); } #region Find Toolbar Buttons diff --git a/Windows/FindReplace.resx b/Windows/FindReplace.resx index b475523..deae6d5 100644 --- a/Windows/FindReplace.resx +++ b/Windows/FindReplace.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABA - QgAAAk1TRnQBSQFMAgEBFAEAAZABAQGQAQEBEAEAARABAAT/ARkBAAj/AUIBTQE2BwABNgMAASgDAAFA + QgAAAk1TRnQBSQFMAgEBFAEAAaABAQGgAQEBEAEAARABAAT/ARkBAAj/AUIBTQE2BwABNgMAASgDAAFA AwABYAMAAQEBAAEYBgABSP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AOEAA/8D/AP6GPgD+QP6A/wMAAP9 A/oS+AP5A/0D/2kAA/4D+QPxAboBogGKAbYBhgFWAbYBhgFWAbYBhgFWAbYBhgFWAbYBhgFWAbYBhgFW AbYBhgFWAbYBhgFWAbwBpAGNA/cMAAP8A/YD8wG8AcoBzQFVAZUBowFVAZUBowHQAdcB2QPzA/UD+wP/ @@ -443,48 +443,48 @@ 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 - BPSUqbbrmUHrAAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAI9SURBVDhPzZHda1JxHMYPdddFFLRgXUaEsCC6ChYRvSBR + xEA3WuuN0S4CBxFLR8rYcmrl3OiixjB1ZmcnVEJSN5uzbS4tFouj5ZytTI94XuZxaLv0qvOYEf0F9YMP + 5+H5Pp+rQ/w/77pRlPUYRMeNYTHXMcjW8O0xlF3g7050YNvQfr2Ld3OKLi3Da60l/qm//M375kfhvkuk + L+vzSYCMDjdssIVTl+W9K7ILt2jeTJWyVHgrQ0YqaedsZbXbnPXZg9UUQEaHGzbYwoFLtHYtOlSGDE/O + VdLPw9UUFams9VuZeQPJxdEBZHS4YYMODlyi5bw/N0px687X1U+AjGx96TSsBWyvyvSjl2LMSJXmLG5h + qV2/6h9xb8zrXcKMiSyFhyeZBFyiWe6tTQY3v9qmyzRwhSrpc9qEb9QjRnV2zg9GPOIiOov7T/eA4mNw + if2nvTmTk8mM+zY/Wjxi7CElRpVDn6eNlBDtt7EBgFzvpjYWfnd9j3PLcImDZ2ccV3RJzvyi9FZtZYMD + Dn725th65PaT7ILWXgwBZHS4aSbYALoOdSIPlzikiMuOKJeFXgtDa6zFUN9EIaB3ckttA8nQPScXB8jo + cNPYiiFsD7fFeLj1X9ly5pni2NWMcEnHMHfGix9MU+x71dj3lVOqVAYgo1NLN2ywhVOXpbddYk/TAaX8 + qPKd90Q3w5xsZ2vHrxXyrZ20ByCjww0bbOE0XGKbxI5GsU+iWaJJYpfEzga7JfZK4IYNtnDg/tNHED8B + 40iprvh5KYkAAAAASUVORK5CYII= iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIHSURBVDhPY6AZ2LWY2XnXYsa9ILxzMVM8VBg/2DKfQQLK - ZNg2j3Hf+9f9398/7P6zbQHjLqgwihoUsHEOU8KmuYz7Ns1lXr5xNrMHiP373cz/L67n/EWIMS8HiYPU - QrUhwIaZjPu/v5r8//3D9u8HN+ieB/G/vej///JU9I91MxlXH1yjc/7tpYbvX551/QfJQbUhwOrJTAfu + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIGSURBVDhPY6AZ2LWY2XnXYsa9ILxzMVM8VBg/2DKfQQLK + ZNg2j3Hf+9f939/e7/yzbQHjLqgwihoUsHEOU8KmuYz7Ns1lXr5xNrMHiP373cz/z65m/UWIMS8HiYPU + QrUhwIaZjPu/v5r8//3D9u8HN+ieB/G/vej///JE9I91MxlXH1yjc/7thYbvX551/QfJQbUhwOrJTAfu nwj/8fRK4v9Xt4r/71+lceH9w+b/t08GftoHZL+8WfAfJAdSA1IL1YYAyycyWC3vZ1y5Z4XyzZPbLF48 upT6H4TvnA7+//Bi8n+QGEgOpAakFqoNEyzsYnZZ0M106PAmqw/Xjnr8B2EQGyQGkoMqwwSzWxms57Qx - rt6x0ujmyc32L68cdvkPwjdO+IPpY5utX+5YonUTpAakFqoNAabWMx25eyL6x62T3v+vH3P5v3SS8OWT - W0w/3zsXBmaDxG6c8Ph/8qjPD5BaqDYE6KtgOnrntMv/E4fMfizqFrrSX8m44cRhsx/3zwf+B8mBxEBy - IDUgPlQbArQXMKS05DCeaMllXA9ke4Poy4fs/z694vMfJA4Tg7JToNpQgZUhgxSUyVCZzHjsxnH7v3f3 - 2/+sTGI8BRVGUYMN8AKxIhCr+9kzVNRlclwAYXsThkSQGBArA7EAEDMCMVbAAcRiQAyyBRsWB2IuIMZp - AImAgQEA1wkcgSmiF0cAAAAASUVORK5CYII= + rt6x0ujmyc32L68cdvkPwjdO+IPpY5utX+5YonUTpAakFqoNAabWMx25CwywWye9/18/5vJ/6SThyye3 + mH6+dy4MzAaJ3Tjh8f/EUZ8fILVQbQjQV8F09M5pl/8nDpn9WNQtdKW/knHDicNmP+6fD/wPkgOJgeRA + akB8qDYEaC9gSGnJYTzRksu4Hsj2BtEXD9j/fXrF5z9IHCYGZadAtaECK0MGKSiToTKZ8di1o/Z/7+63 + /1mZxHgKKoyiBhvgBWJFIFb3s2eoqMvkuADC9iYMiSAxIFYGYgEgZgRirIADiMWAGGQLNiwOxFxAjNMA + EgEDAwCaIRxoqFFNlQAAAABJRU5ErkJggg== @@ -733,13 +733,16 @@ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFySURBVDhPrdE/SAJhHMbx33FCY2PQ0NLUHK1SIFRE0VAR - Ev2DQoiGKBCSUBvKKIhAoxByyE5QEkEF0cIIgwpxaGsQDSoowv5B0BBvPvLey912UgdfDt73+dxy9C9P - 1kmm7LTJdjYlb6o5zZTXpr3DFoZzotPxhtZrR9vR68kGq2Q8tfy2Dl3qOTbYwnBOlJ6Uu2+9fTntB0JL - XaLggln3AWxhOCdKTZjmS8pc+THuYmoJ94Ao6ugR5whbGM6JkmOy770Q+mHFMFMrhu2i/P6sOEfYwnBO - FLfKe983AfZ56RNlPMOiuKtfd4ctDOdEMavs/yr42VtuRwQYtltqb2WxU3eHLQznRJFROfBxtcteslsi - YO1bG7YwnBOFRuTDyvk2e0qvGwpbGM6JgkOS8lz9RQ/JVUNhC8M5UWBQitwn3OwutmIobGE4J/L2Sqly - 1MFKx8uGwhaGc2qZaZcO1izSRT3BwOIDjdWaqjXXGQzsXx6iXy8F3Ygxdd78AAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFySURBVDhPrdFPRINxHMfx7+M3OnaMDl06dU7XKUYlpUMl + k/5RRjqkGE22dailSGwpox1aG5tmbGO2smRRmQ7dOswWFSVbiuiQX/vM7/l5ntuTenh7+P0+r+fy0L88 + OSeZctMm29kU21RzmqmgTXuHLYzgRKfjDa3Xjraj6skGr2Q99fy2Dl3qOTbYwghOlJlk3Xfevrz2A+Gl + Lllwwaz7ALYwghOlJ0zzpdBc+Snh4mpJ94As5uiR5whbGMGJUmPMVy2Ev3kxwtWKEbussD8rzxG2MIIT + Jaxs7+s2wD8ufbKsZ1iWcPXr7rCFEZwobmX+zxs/f8vvyAAjdkv9HVrs1N1hCyM4UXSUBd6vdvlrbksG + rH1rwxZGcKLwCDusnG/z58y6obCFEZwoOKSEXmq/6DG1aihsYQQnCgwq0Yekm9/HVwyFLYzgRN5eJV2O + OXjpeNlQ2MIITi0z7crBmkW5+E0wsPhAY62mWs2/DAb2Lw/RDxmp3YCQ0WllAAAAAElFTkSuQmCC + + 345, 17 + \ No newline at end of file