diff --git a/exeinfogui/GEM/GemColor.cs b/exeinfogui/GEM/GemColor.cs
new file mode 100644
index 0000000..fa71227
--- /dev/null
+++ b/exeinfogui/GEM/GemColor.cs
@@ -0,0 +1,32 @@
+using Eto.Drawing;
+
+namespace exeinfogui.GEM
+{
+ public static class GemColor
+ {
+ internal static Color GemToEtoColor(libexeinfo.GEM.ObjectColors color)
+ {
+ switch(color)
+ {
+ case libexeinfo.GEM.ObjectColors.White: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.White);
+ case libexeinfo.GEM.ObjectColors.Black: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.Black);
+ case libexeinfo.GEM.ObjectColors.Red: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.Red);
+ case libexeinfo.GEM.ObjectColors.Green: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.Green);
+ case libexeinfo.GEM.ObjectColors.Blue: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.Blue);
+ case libexeinfo.GEM.ObjectColors.Cyan: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.Cyan);
+ case libexeinfo.GEM.ObjectColors.Yellow: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.Yellow);
+ case libexeinfo.GEM.ObjectColors.Magenta: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.Magenta);
+ case libexeinfo.GEM.ObjectColors.LightGray: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.LightGray);
+ case libexeinfo.GEM.ObjectColors.Gray: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.Gray);
+ case libexeinfo.GEM.ObjectColors.LightRed: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.LightRed);
+ case libexeinfo.GEM.ObjectColors.LightGreen: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.LightGreen);
+ case libexeinfo.GEM.ObjectColors.LightBlue: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.LightBlue);
+ case libexeinfo.GEM.ObjectColors.LightCyan: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.LightCyan);
+ case libexeinfo.GEM.ObjectColors.LightYellow: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.LightYellow);
+ case libexeinfo.GEM.ObjectColors.LightMagenta: return Color.FromRgb((int)libexeinfo.GEM.ObjectColorsRgb.LightMagenta);
+ }
+
+ return Color.FromRgb(0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/exeinfogui/GEM/PanelGemBox.xeto b/exeinfogui/GEM/PanelGemBox.xeto
new file mode 100644
index 0000000..1e740ec
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemBox.xeto
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exeinfogui/GEM/PanelGemBox.xeto.cs b/exeinfogui/GEM/PanelGemBox.xeto.cs
new file mode 100644
index 0000000..5b29c48
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemBox.xeto.cs
@@ -0,0 +1,73 @@
+using Claunia.Encoding;
+using Eto.Forms;
+using Eto.Serialization.Xaml;
+
+namespace exeinfogui.GEM
+{
+ public class PanelGemBox : Panel
+ {
+ Label lblCharacter;
+ Label lblThickness;
+ TextBox txtBorderColor;
+ TextBox txtCharacter;
+ TextBox txtCoordinates;
+ TextBox txtFill;
+ TextBox txtFlags;
+ TextBox txtInsideColor;
+ TextBox txtSize;
+ TextBox txtState;
+ TextBox txtTextColor;
+ TextBox txtThickness;
+ TextBox txtTransparency;
+
+ public PanelGemBox()
+ {
+ XamlReader.Load(this);
+ }
+
+ public void Update(libexeinfo.GEM.TreeObjectNode node)
+ {
+ sbyte thickness = (sbyte)((node.data & 0xFF0000) >> 16);
+
+ char character = Encoding.AtariSTEncoding.GetString(new[] {(byte)((node.data & 0xFF000000) >> 24)})[0];
+
+ txtFlags.Text = node.flags == 0 ? "None" : node.flags.ToString();
+ txtState.Text = node.state == 0 ? "Normal" : node.state.ToString();
+ txtCoordinates.Text = $"{node.x},{node.y}";
+ txtSize.Text = $"{node.width}x{node.height} pixels";
+ txtBorderColor.Text =
+ ((libexeinfo.GEM.ObjectColors)((node.data & 0xFFFF & libexeinfo.GEM.BorderColorMask) >> 12)).ToString();
+ txtFill.Text =
+ ((libexeinfo.GEM.ObjectFillPattern)((node.data & 0xFFFF & libexeinfo.GEM.FillPatternMask) >> 4))
+ .ToString();
+ txtInsideColor.Text =
+ ((libexeinfo.GEM.ObjectColors)((node.data & 0xFFFF & libexeinfo.GEM.InsideColorMask) >> 8)).ToString();
+ txtTextColor.Text =
+ ((libexeinfo.GEM.ObjectColors)((node.data & 0xFFFF & libexeinfo.GEM.TextColorMask) >> 8)).ToString();
+ txtTransparency.Text = (node.data & 0xFFFF & libexeinfo.GEM.TransparentColor) != 0
+ ? "Transparent mode"
+ : "Replace mode";
+ if(thickness < 0) txtThickness.Text = $"{thickness * -1} pixels outward";
+ else if(thickness < 0)
+ txtThickness.Text = $"{thickness} pixels inward";
+ else
+ txtThickness.Text = "None";
+ txtCharacter.Text = new string(new []{character});
+
+ if(node.type == libexeinfo.GEM.ObjectTypes.G_BOXCHAR)
+ {
+ txtCharacter.Visible = true;
+ txtThickness.Visible = true;
+ lblCharacter.Visible = true;
+ lblThickness.Visible = true;
+ }
+ else
+ {
+ txtCharacter.Visible = false;
+ txtThickness.Visible = false;
+ lblCharacter.Visible = false;
+ lblThickness.Visible = false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/exeinfogui/GEM/PanelGemGeneric.xeto b/exeinfogui/GEM/PanelGemGeneric.xeto
new file mode 100644
index 0000000..7f592c7
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemGeneric.xeto
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exeinfogui/GEM/PanelGemGeneric.xeto.cs b/exeinfogui/GEM/PanelGemGeneric.xeto.cs
new file mode 100644
index 0000000..c1bffa8
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemGeneric.xeto.cs
@@ -0,0 +1,28 @@
+using Eto.Forms;
+using Eto.Serialization.Xaml;
+
+namespace exeinfogui.GEM
+{
+ public class PanelGemGeneric : Panel
+ {
+ TextBox txtCoordinates;
+ TextBox txtData;
+ TextBox txtFlags;
+ TextBox txtSize;
+ TextBox txtState;
+
+ public PanelGemGeneric()
+ {
+ XamlReader.Load(this);
+ }
+
+ public void Update(libexeinfo.GEM.TreeObjectNode node)
+ {
+ txtFlags.Text = node.flags == 0 ? "None" : node.flags.ToString();
+ txtState.Text = node.state == 0 ? "Normal" : node.state.ToString();
+ txtCoordinates.Text = $"{node.x},{node.y}";
+ txtSize.Text = $"{node.width}x{node.height} pixels";
+ txtData.Text = $"{node.data}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/exeinfogui/GEM/PanelGemIcon.xeto b/exeinfogui/GEM/PanelGemIcon.xeto
new file mode 100644
index 0000000..f078f31
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemIcon.xeto
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exeinfogui/GEM/PanelGemIcon.xeto.cs b/exeinfogui/GEM/PanelGemIcon.xeto.cs
new file mode 100644
index 0000000..3d7cdce
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemIcon.xeto.cs
@@ -0,0 +1,104 @@
+using System.Collections.Generic;
+using Eto.Drawing;
+using Eto.Forms;
+using Eto.Serialization.Xaml;
+
+namespace exeinfogui.GEM
+{
+ public class PanelGemIcon : Panel
+ {
+ ImageView imgIcon;
+ TextBox txtBgColor;
+ TextBox txtCharater;
+ TextBox txtCharCoordinates;
+ TextBox txtCoordinates;
+ TextBox txtFgColor;
+ TextBox txtFlags;
+ TextBox txtSize;
+ TextBox txtState;
+ TextBox txtText;
+ TextBox txtTextBoxSize;
+ TextBox txtTextCoordinates;
+
+ public PanelGemIcon()
+ {
+ XamlReader.Load(this);
+ }
+
+ public void Update(libexeinfo.GEM.TreeObjectNode node)
+ {
+ txtFlags.Text = node.flags == 0 ? "None" : node.flags.ToString();
+ txtState.Text = node.state == 0 ? "Normal" : node.state.ToString();
+ txtCoordinates.Text = $"{node.IconBlock.X},{node.IconBlock.Y}";
+ txtSize.Text = $"{node.IconBlock.Width}x{node.IconBlock.Height} pixels";
+ txtCharater.Text = $"{node.IconBlock.Character}";
+ txtCharCoordinates.Text = $"{node.IconBlock.CharX},{node.IconBlock.CharY}";
+ txtFgColor.Text = $"{node.IconBlock.ForegroundColor}";
+ txtBgColor.Text = $"{node.IconBlock.BackgroundColor}";
+ txtTextCoordinates.Text = $"{node.IconBlock.TextX},{node.IconBlock.TextY}";
+ txtTextBoxSize.Text = $"{node.IconBlock.TextWidth}x{node.IconBlock.TextHeight} pixels";
+ txtText.Text = node.IconBlock.Text;
+ imgIcon.Image = GemIconToEto(node);
+ }
+
+ static Bitmap GemIconToEto(libexeinfo.GEM.TreeObjectNode node)
+ {
+ const uint COLOR = 0x00000000;
+ const uint BACKGROUND = 0x00FFFFFF;
+ const uint ALPHAMASK = 0xFF000000;
+ List pixels = new List();
+
+ byte[] data = new byte[node.IconBlock.Data.Length];
+ int pos = 0;
+ int w = node.IconBlock.Width / 8;
+ // This flips the image.
+ while(pos < data.Length)
+ {
+ for(int i = 0; i < w; i++)
+ {
+ byte b = node.IconBlock.Data[pos + i];
+ data[pos + i] = (byte)(b >> 7);
+ data[pos + i] += (byte)((b >> 5) & 0x02);
+ data[pos + i] += (byte)((b >> 3) & 0x04);
+ data[pos + i] += (byte)((b >> 1) & 0x08);
+ data[pos + i] += (byte)((b << 1) & 0x10);
+ data[pos + i] += (byte)((b << 3) & 0x20);
+ data[pos + i] += (byte)((b << 5) & 0x40);
+ data[pos + i] += (byte)(b << 7);
+ }
+
+ pos += w;
+ }
+
+ byte[] mask = new byte[node.IconBlock.Mask.Length];
+ pos = 0;
+ // This flips the mask.
+ while(pos < data.Length)
+ {
+ for(int i = 0; i < w; i++)
+ {
+ byte b = node.IconBlock.Mask[pos + i];
+ mask[pos + i] = (byte)(b >> 7);
+ mask[pos + i] += (byte)((b >> 5) & 0x02);
+ mask[pos + i] += (byte)((b >> 3) & 0x04);
+ mask[pos + i] += (byte)((b >> 1) & 0x08);
+ mask[pos + i] += (byte)((b << 1) & 0x10);
+ mask[pos + i] += (byte)((b << 3) & 0x20);
+ mask[pos + i] += (byte)((b << 5) & 0x40);
+ mask[pos + i] += (byte)(b << 7);
+ }
+
+ pos += w;
+ }
+
+ for(pos = 0; pos < data.Length; pos++)
+ {
+ for(int i = 0; i < 8; i++)
+ pixels.Add((int)(((data[pos] & (1 << i)) != 0 ? COLOR : BACKGROUND) +
+ ((mask[pos] & (1 << i)) != 0 ? ALPHAMASK : 0)));
+ }
+
+ return new Bitmap(node.IconBlock.Width, node.IconBlock.Height, PixelFormat.Format32bppRgba, pixels);
+ }
+ }
+}
\ No newline at end of file
diff --git a/exeinfogui/GEM/PanelGemImage.xeto b/exeinfogui/GEM/PanelGemImage.xeto
new file mode 100644
index 0000000..aba025d
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemImage.xeto
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exeinfogui/GEM/PanelGemImage.xeto.cs b/exeinfogui/GEM/PanelGemImage.xeto.cs
new file mode 100644
index 0000000..0935977
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemImage.xeto.cs
@@ -0,0 +1,71 @@
+using System.Collections.Generic;
+using Eto.Drawing;
+using Eto.Forms;
+using Eto.Serialization.Xaml;
+
+namespace exeinfogui.GEM
+{
+ public class PanelGemImage : Panel
+ {
+ ImageView imgImage;
+ TextBox txtColor;
+ TextBox txtCoordinates;
+ TextBox txtFlags;
+ TextBox txtSize;
+ TextBox txtState;
+
+ public PanelGemImage()
+ {
+ XamlReader.Load(this);
+ }
+
+ public void Update(libexeinfo.GEM.TreeObjectNode node)
+ {
+ txtFlags.Text = node.flags == 0 ? "None" : node.flags.ToString();
+ txtState.Text = node.state == 0 ? "Normal" : node.state.ToString();
+ txtCoordinates.Text = $"{node.BitBlock.X},{node.BitBlock.Y}";
+ txtSize.Text = $"{node.BitBlock.Width}x{node.BitBlock.Height} pixels";
+ txtColor.Text = $"{node.BitBlock.Color}";
+ imgImage.Image = GemImageToEto(node);
+ }
+
+ static Bitmap GemImageToEto(libexeinfo.GEM.TreeObjectNode node)
+ {
+ Color color = GemColor.GemToEtoColor(node.BitBlock.Color);
+ Color background;
+ background = GemColor.GemToEtoColor(node.BitBlock.Color == libexeinfo.GEM.ObjectColors.White
+ ? libexeinfo.GEM.ObjectColors.Black
+ : libexeinfo.GEM.ObjectColors.White);
+
+ List pixels = new List();
+
+ byte[] data = new byte[node.BitBlock.Data.Length];
+ int pos = 0;
+ int w = node.BitBlock.Width / 8;
+ // This flips the image.
+ while(pos < data.Length)
+ {
+ for(int i = 0; i < w; i++)
+ {
+ byte b = node.BitBlock.Data[pos + i];
+ data[pos + i] = (byte)(b >> 7);
+ data[pos + i] += (byte)((b >> 5) & 0x02);
+ data[pos + i] += (byte)((b >> 3) & 0x04);
+ data[pos + i] += (byte)((b >> 1) & 0x08);
+ data[pos + i] += (byte)((b << 1) & 0x10);
+ data[pos + i] += (byte)((b << 3) & 0x20);
+ data[pos + i] += (byte)((b << 5) & 0x40);
+ data[pos + i] += (byte)(b << 7);
+ }
+
+ pos += w;
+ }
+
+ foreach(byte b in data)
+ for(int i = 0; i < 8; i++)
+ pixels.Add((b & (1 << i)) != 0 ? color : background);
+
+ return new Bitmap(node.BitBlock.Width, node.BitBlock.Height, PixelFormat.Format32bppRgb, pixels);
+ }
+ }
+}
\ No newline at end of file
diff --git a/exeinfogui/GEM/PanelGemString.xeto b/exeinfogui/GEM/PanelGemString.xeto
new file mode 100644
index 0000000..1580ddc
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemString.xeto
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exeinfogui/GEM/PanelGemString.xeto.cs b/exeinfogui/GEM/PanelGemString.xeto.cs
new file mode 100644
index 0000000..51071a4
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemString.xeto.cs
@@ -0,0 +1,28 @@
+using Eto.Forms;
+using Eto.Serialization.Xaml;
+
+namespace exeinfogui.GEM
+{
+ public class PanelGemString : Panel
+ {
+ TextBox txtCoordinates;
+ TextBox txtFlags;
+ TextBox txtSize;
+ TextBox txtState;
+ TextArea txtString;
+
+ public PanelGemString()
+ {
+ XamlReader.Load(this);
+ }
+
+ public void Update(libexeinfo.GEM.TreeObjectNode node)
+ {
+ txtFlags.Text = node.flags == 0 ? "None" : node.flags.ToString();
+ txtState.Text = node.state == 0 ? "Normal" : node.state.ToString();
+ txtCoordinates.Text = $"{node.x},{node.y}";
+ txtSize.Text = $"{node.width}x{node.height} pixels";
+ txtString.Text = node.String;
+ }
+ }
+}
\ No newline at end of file
diff --git a/exeinfogui/GEM/PanelGemText.xeto b/exeinfogui/GEM/PanelGemText.xeto
new file mode 100644
index 0000000..9068360
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemText.xeto
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exeinfogui/GEM/PanelGemText.xeto.cs b/exeinfogui/GEM/PanelGemText.xeto.cs
new file mode 100644
index 0000000..36d4fe1
--- /dev/null
+++ b/exeinfogui/GEM/PanelGemText.xeto.cs
@@ -0,0 +1,120 @@
+using Eto.Forms;
+using Eto.Serialization.Xaml;
+
+namespace exeinfogui.GEM
+{
+ public class PanelGemText : Panel
+ {
+ Label lblTemplate;
+ Label lblText;
+ Label lblValidation;
+ TextBox txtBorderColor;
+ TextBox txtCoordinates;
+ TextBox txtFill;
+ TextBox txtFlags;
+ TextBox txtFont;
+ TextBox txtInsideColor;
+ TextBox txtJustification;
+ TextBox txtPreview;
+ TextBox txtSize;
+ TextBox txtState;
+ TextBox txtTemplate;
+ TextBox txtText;
+ TextBox txtTextColor;
+ TextBox txtThickness;
+ TextBox txtTransparency;
+ TextBox txtValidation;
+
+ public PanelGemText()
+ {
+ XamlReader.Load(this);
+ }
+
+ public void Update(libexeinfo.GEM.TreeObjectNode node)
+ {
+ txtFlags.Text = node.flags == 0 ? "None" : node.flags.ToString();
+ txtState.Text = node.state == 0 ? "Normal" : node.state.ToString();
+ txtCoordinates.Text = $"{node.x},{node.y}";
+ txtSize.Text = $"{node.width}x{node.height} pixels";
+ txtBorderColor.Text = $"{node.TedInfo.BorderColor}";
+ txtFill.Text = $"{node.TedInfo.Fill}";
+ txtFont.Text = $"{node.TedInfo.Font}";
+ txtInsideColor.Text = $"{node.TedInfo.InsideColor}";
+ txtJustification.Text = $"{node.TedInfo.Justification}";
+ txtTemplate.Text = node.TedInfo.Template;
+ txtText.Text = node.TedInfo.Text;
+ txtTextColor.Text = $"{node.TedInfo.TextColor}";
+ txtTransparency.Text =
+ node.TedInfo.Transparency ? "Transparent mode" : "Replace mode";
+ txtValidation.Text = node.TedInfo.Validation;
+ if(node.TedInfo.Thickness < 0) txtThickness.Text = $"{node.TedInfo.Thickness * -1} pixels outward";
+ else if(node.TedInfo.Thickness < 0)
+ txtThickness.Text = $"{node.TedInfo.Thickness} pixels inward";
+ else
+ txtThickness.Text = "None";
+
+ if(string.IsNullOrWhiteSpace(node.TedInfo.Template))
+ {
+ txtTemplate.Visible = false;
+ lblTemplate.Visible = false;
+ }
+ else
+ {
+ txtTemplate.Visible = true;
+ lblTemplate.Visible = true;
+ }
+
+ if(string.IsNullOrWhiteSpace(node.TedInfo.Text))
+ {
+ txtText.Visible = false;
+ lblText.Visible = false;
+ }
+ else
+ {
+ txtText.Visible = true;
+ lblText.Visible = true;
+ }
+
+ if(string.IsNullOrWhiteSpace(node.TedInfo.Validation))
+ {
+ txtValidation.Visible = false;
+ lblValidation.Visible = false;
+ }
+ else
+ {
+ txtValidation.Visible = true;
+ lblValidation.Visible = true;
+ }
+
+ if(!string.IsNullOrEmpty(node.TedInfo.Template))
+ if(string.IsNullOrEmpty(node.TedInfo.Text))
+ txtPreview.Text = node.TedInfo.Template;
+ else
+ {
+ char[] preview = node.TedInfo.Template.ToCharArray();
+ char[] template = node.TedInfo.Text.ToCharArray();
+ if(template[0] == '@')
+ for(int i = 0; i < template.Length; i++)
+ template[i] = ' ';
+
+ int templatePos = 0;
+
+ for(int i = 0; i < preview.Length; i++)
+ {
+ if(preview[i] != '_') continue;
+
+ if(templatePos >= template.Length) continue;
+
+ preview[i] = template[templatePos];
+ templatePos++;
+ }
+
+ txtPreview.Text = new string(preview);
+ }
+ else txtPreview.Text = txtText.Text;
+
+ txtPreview.BackgroundColor = GemColor.GemToEtoColor(node.TedInfo.InsideColor);
+ txtPreview.TextColor = GemColor.GemToEtoColor(node.TedInfo.TextColor);
+ }
+ }
+}
\ No newline at end of file
diff --git a/exeinfogui/GEM/TabGemResources.xeto b/exeinfogui/GEM/TabGemResources.xeto
new file mode 100644
index 0000000..3bf30e4
--- /dev/null
+++ b/exeinfogui/GEM/TabGemResources.xeto
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exeinfogui/GEM/TabGemResources.xeto.cs b/exeinfogui/GEM/TabGemResources.xeto.cs
new file mode 100644
index 0000000..4fc5a7d
--- /dev/null
+++ b/exeinfogui/GEM/TabGemResources.xeto.cs
@@ -0,0 +1,118 @@
+using System;
+using Eto.Forms;
+using Eto.Serialization.Xaml;
+
+namespace exeinfogui.GEM
+{
+ public class TabGemResources : TabPage
+ {
+ PanelGemBox panelBox;
+ PanelGemGeneric panelGeneric;
+ PanelGemIcon panelIcon;
+ PanelGemImage panelImage;
+ PanelGemString panelString;
+ PanelGemText panelText;
+ Panel pnlResource;
+ TreeGridItemCollection treeData;
+ TreeGridView treeResources;
+
+ public TabGemResources()
+ {
+ XamlReader.Load(this);
+
+ treeResources.Columns.Add(new GridColumn {HeaderText = "Type", DataCell = new TextBoxCell(0)});
+
+ treeResources.AllowMultipleSelection = false;
+ treeResources.SelectionChanged += TreeResourcesOnSelectionChanged;
+
+ panelGeneric = new PanelGemGeneric();
+ panelString = new PanelGemString();
+ panelText = new PanelGemText();
+ panelBox = new PanelGemBox();
+ panelImage = new PanelGemImage();
+ panelIcon = new PanelGemIcon();
+ }
+
+ public void Update(libexeinfo.GEM.TreeObjectNode[] roots)
+ {
+ treeData = new TreeGridItemCollection();
+
+ for(int i = 0; i < roots.Length; i++)
+ {
+ TreeGridItem root = new TreeGridItem {Values = new object[] {$"Root {i}", null}};
+
+ AddObjectToTree(root, roots[i]);
+
+ treeData.Add(root);
+ }
+
+ treeResources.DataStore = treeData;
+ }
+
+ void TreeResourcesOnSelectionChanged(object sender, EventArgs eventArgs)
+ {
+ if(!(((TreeGridItem)treeResources.SelectedItem)?.Values[1] is libexeinfo.GEM.TreeObjectNode node))
+ {
+ pnlResource.Content = null;
+ return;
+ }
+
+ switch(node.type)
+ {
+ case libexeinfo.GEM.ObjectTypes.G_BUTTON:
+ case libexeinfo.GEM.ObjectTypes.G_STRING:
+ case libexeinfo.GEM.ObjectTypes.G_TITLE:
+ panelString.Update(node);
+ pnlResource.Content = panelString;
+ break;
+ case libexeinfo.GEM.ObjectTypes.G_TEXT:
+ case libexeinfo.GEM.ObjectTypes.G_BOXTEXT:
+ case libexeinfo.GEM.ObjectTypes.G_FTEXT:
+ case libexeinfo.GEM.ObjectTypes.G_FBOXTEXT:
+ panelText.Update(node);
+ pnlResource.Content = panelText;
+ break;
+ case libexeinfo.GEM.ObjectTypes.G_BOX:
+ case libexeinfo.GEM.ObjectTypes.G_IBOX:
+ case libexeinfo.GEM.ObjectTypes.G_BOXCHAR:
+ panelBox.Update(node);
+ pnlResource.Content = panelBox;
+ break;
+ case libexeinfo.GEM.ObjectTypes.G_IMAGE:
+ panelImage.Update(node);
+ pnlResource.Content = panelImage;
+ break;
+ case libexeinfo.GEM.ObjectTypes.G_ICON:
+ panelIcon.Update(node);
+ pnlResource.Content = panelIcon;
+ break;
+ /* case libexeinfo.GEM.ObjectTypes.G_USERDEF: break;
+ case libexeinfo.GEM.ObjectTypes.G_CICON: break;*/
+ default:
+ panelGeneric.Update(node);
+ pnlResource.Content = panelGeneric;
+ break;
+ }
+ }
+
+ static void AddObjectToTree(TreeGridItem parent, libexeinfo.GEM.TreeObjectNode node)
+ {
+ while(true)
+ {
+ TreeGridItem item = new TreeGridItem {Values = new object[] {$"{node.type}", node}};
+
+ if(node.child != null) AddObjectToTree(item, node.child);
+
+ parent.Children.Add(item);
+
+ if(node.sibling != null)
+ {
+ node = node.sibling;
+ continue;
+ }
+
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/exeinfogui/MainForm.xeto.cs b/exeinfogui/MainForm.xeto.cs
index 38e5d75..5ab55eb 100644
--- a/exeinfogui/MainForm.xeto.cs
+++ b/exeinfogui/MainForm.xeto.cs
@@ -25,8 +25,8 @@
// THE SOFTWARE.
using System;
-using System.IO;
using System.Linq;
+using exeinfogui.GEM;
using Eto.Forms;
using Eto.Serialization.Xaml;
using libexeinfo;
@@ -35,18 +35,25 @@ namespace exeinfogui
{
public class MainForm : Form
{
- ComboBox cmbArch;
- Label lblSubsystem;
- TextBox txtFile;
- TextArea txtInformation;
- TextBox txtOs;
- TextBox txtSubsystem;
- TextBox txtType;
- TabControl tabMain;
+ ComboBox cmbArch;
+ Label lblSubsystem;
+ TabGemResources tabGemResources;
+ TabControl tabMain;
+ TabPageStrings tabStrings;
+ TextBox txtFile;
+ TextArea txtInformation;
+ TextBox txtOs;
+ TextBox txtSubsystem;
+ TextBox txtType;
public MainForm()
{
XamlReader.Load(this);
+
+ tabStrings = new TabPageStrings {Visible = false};
+ tabGemResources = new TabGemResources {Visible = false};
+ tabMain.Pages.Add(tabStrings);
+ tabMain.Pages.Add(tabGemResources);
}
protected void OnBtnLoadClick(object sender, EventArgs e)
@@ -55,8 +62,10 @@ namespace exeinfogui
txtType.Text = "";
txtInformation.Text = "";
cmbArch.Items.Clear();
- lblSubsystem.Visible = false;
- txtSubsystem.Visible = false;
+ lblSubsystem.Visible = false;
+ txtSubsystem.Visible = false;
+ tabStrings.Visible = false;
+ tabGemResources.Visible = false;
OpenFileDialog dlgOpen = new OpenFileDialog {Title = "Choose executable file", MultiSelect = false};
@@ -72,7 +81,15 @@ namespace exeinfogui
IExecutable peExe = new PE(dlgOpen.FileName);
IExecutable recognizedExe = null;
- if(mzExe.Recognized) recognizedExe = mzExe;
+ if(mzExe.Recognized)
+ {
+ recognizedExe = mzExe;
+ if(((MZ)mzExe).ResourceObjectRoots != null && ((MZ)mzExe).ResourceObjectRoots.Any())
+ {
+ tabGemResources.Update(((MZ)mzExe).ResourceObjectRoots);
+ tabGemResources.Visible = true;
+ }
+ }
if(neExe.Recognized) recognizedExe = neExe;
else if(lxExe.Recognized)
@@ -80,7 +97,14 @@ namespace exeinfogui
else if(peExe.Recognized)
recognizedExe = peExe;
else if(stExe.Recognized)
+ {
recognizedExe = stExe;
+ if(((AtariST)stExe).ResourceObjectRoots != null && ((AtariST)stExe).ResourceObjectRoots.Any())
+ {
+ tabGemResources.Update(((AtariST)stExe).ResourceObjectRoots);
+ tabGemResources.Visible = true;
+ }
+ }
else if(coffExe.Recognized)
recognizedExe = coffExe;
else
@@ -109,8 +133,8 @@ namespace exeinfogui
if(recognizedExe.Strings != null && recognizedExe.Strings.Any())
{
- TabPageStrings tabStrings = new TabPageStrings(recognizedExe.Strings);
- tabMain.Pages.Add(tabStrings);
+ tabStrings.Update(recognizedExe.Strings);
+ tabStrings.Visible = true;
}
}
diff --git a/exeinfogui/TabPageStrings.xeto.cs b/exeinfogui/TabPageStrings.xeto.cs
index 27c5914..6561be4 100644
--- a/exeinfogui/TabPageStrings.xeto.cs
+++ b/exeinfogui/TabPageStrings.xeto.cs
@@ -1,8 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
+using System.Collections.Generic;
using Eto.Forms;
-using Eto.Drawing;
using Eto.Serialization.Xaml;
namespace exeinfogui
@@ -10,19 +7,21 @@ namespace exeinfogui
public class TabPageStrings : TabPage
{
GridView treeStrings;
-
- //IEnumerable strings;
-
- public TabPageStrings(IEnumerable strings)
+
+ public TabPageStrings()
{
XamlReader.Load(this);
- treeStrings.DataStore = strings;
treeStrings.Columns.Add(new GridColumn
{
- DataCell = new TextBoxCell {Binding = Binding.Property(r => r)},
+ DataCell = new TextBoxCell {Binding = Binding.Property(r => r)},
HeaderText = "String"
});
}
+
+ public void Update(IEnumerable strings)
+ {
+ treeStrings.DataStore = strings;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/exeinfogui/exeinfogui.csproj b/exeinfogui/exeinfogui.csproj
index b6cabde..b73926c 100644
--- a/exeinfogui/exeinfogui.csproj
+++ b/exeinfogui/exeinfogui.csproj
@@ -17,4 +17,7 @@
+
+
+
\ No newline at end of file