From 2db332c8ad3dff265ab209a1ff727f30be4dbd20 Mon Sep 17 00:00:00 2001
From: Ian C <ianc@noddybox.co.uk>
Date: Mon, 1 Aug 2005 23:46:42 +0000
Subject: Initial working version

---
 BitmapSpriteEd.GfxEditor.resources | Bin 14416 -> 14806 bytes
 BitmapSpriteEd.MainForm.resources  | Bin 12638 -> 16803 bytes
 BitmapSpriteEd.prjx                |   1 +
 GfxEditor.cs                       | 696 ++++++++++++++++-------------
 MainForm.cs                        | 868 +++++++++++++++++++++++++++++--------
 ManipulationMenu.cs                | 104 +++++
 Sprite.cs                          |  33 +-
 7 files changed, 1219 insertions(+), 483 deletions(-)
 create mode 100644 ManipulationMenu.cs

diff --git a/BitmapSpriteEd.GfxEditor.resources b/BitmapSpriteEd.GfxEditor.resources
index 32fce11..d5c1526 100644
Binary files a/BitmapSpriteEd.GfxEditor.resources and b/BitmapSpriteEd.GfxEditor.resources differ
diff --git a/BitmapSpriteEd.MainForm.resources b/BitmapSpriteEd.MainForm.resources
index 19aa4b4..fff1e6f 100644
Binary files a/BitmapSpriteEd.MainForm.resources and b/BitmapSpriteEd.MainForm.resources differ
diff --git a/BitmapSpriteEd.prjx b/BitmapSpriteEd.prjx
index d4db08c..76fc817 100644
--- a/BitmapSpriteEd.prjx
+++ b/BitmapSpriteEd.prjx
@@ -9,6 +9,7 @@
     <File name=".\GfxEditor.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
     <File name=".\AlphaColourDialog.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
     <File name=".\BitmapSpriteEd.GfxEditor.resources" subtype="Code" buildaction="EmbedAsResource" dependson="" data="" />
+    <File name=".\ManipulationMenu.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
   </Contents>
   <References />
   <DeploymentInformation target="" script="" strategy="File" />
diff --git a/GfxEditor.cs b/GfxEditor.cs
index c564a52..604f00e 100644
--- a/GfxEditor.cs
+++ b/GfxEditor.cs
@@ -33,41 +33,69 @@ namespace BitmapSpriteEd
 	[ToolboxItem(true)]
 	public class GfxEditor : System.Windows.Forms.UserControl
 	{
+		private System.Windows.Forms.Label m_backCol;
+		private System.Windows.Forms.Label label5;
 		private System.Windows.Forms.Label m_fgPreview;
-		private System.Windows.Forms.ComboBox m_modeList;
-		private System.Windows.Forms.Label m_recent8;
-		private System.Windows.Forms.Label m_recent1;
-		private System.Windows.Forms.Label label11;
-		private System.Windows.Forms.Label m_recent3;
-		private System.Windows.Forms.Label m_recent5;
-		private System.Windows.Forms.Label m_recent6;
-		private System.Windows.Forms.Label m_recent7;
-		private System.Windows.Forms.Label m_bgPreview;
-		private System.Windows.Forms.Label m_recent2;
 		private System.Windows.Forms.ComboBox m_sizeY;
-		private System.Windows.Forms.CheckBox m_mark;
-		private System.Windows.Forms.PictureBox m_preview;
-		private System.Windows.Forms.Label m_gridCol;
-		private System.Windows.Forms.PictureBox m_edit;
-		private System.Windows.Forms.Label label12;
-		private System.Windows.Forms.Label label13;
-		private System.Windows.Forms.Label m_pos;
-		private System.Windows.Forms.Label m_recent4;
-		private System.Windows.Forms.Label label14;
-		private System.Windows.Forms.Label label15;
-		private System.Windows.Forms.Button m_undoButton;
+		private System.Windows.Forms.ComboBox m_sizeX;
+		private System.Windows.Forms.Button m_manipButton;
 		private System.Windows.Forms.Label label3;
 		private System.Windows.Forms.Label label2;
 		private System.Windows.Forms.Label label1;
-		private System.Windows.Forms.ComboBox m_sizeX;
 		private System.Windows.Forms.Label label7;
 		private System.Windows.Forms.Label label6;
-		private System.Windows.Forms.Label label5;
+		private System.Windows.Forms.PictureBox m_edit;
 		private System.Windows.Forms.Label label4;
-		private System.Windows.Forms.Label m_backCol;
+		private System.Windows.Forms.Label m_recent8;
+		private System.Windows.Forms.Label m_recent7;
+		private System.Windows.Forms.Label m_recent4;
+		private System.Windows.Forms.Label m_recent5;
+		private System.Windows.Forms.Label m_recent6;
+		private System.Windows.Forms.Label label11;
+		private System.Windows.Forms.CheckBox m_mark;
+		private System.Windows.Forms.Label m_recent1;
+		private System.Windows.Forms.Label m_recent2;
+		private System.Windows.Forms.Label m_recent3;
+		private System.Windows.Forms.Label label13;
+		private System.Windows.Forms.Label label14;
+		private System.Windows.Forms.Label label12;
+		private System.Windows.Forms.Button m_undoButton;
+		private System.Windows.Forms.Label label15;
+		private System.Windows.Forms.Label m_gridCol;
+		private System.Windows.Forms.PictureBox m_preview;
+		private System.Windows.Forms.Label m_bgPreview;
+		private System.Windows.Forms.ComboBox m_modeList;
+		private System.Windows.Forms.Label m_pos;
 		
 		public const int	MAX_SIZE=32;
 		
+		public class FrameResizeEventArgs : EventArgs
+		{
+			public FrameResizeEventArgs(int width, int height)
+			{
+				m_width=width;
+				m_height=height;
+			}
+			
+			public int Width	{get {return m_width;}}
+			public int Height	{get {return m_height;}}
+			
+			private int	m_width;
+			private int m_height;
+		}
+		
+		public delegate void FrameResizeEventHandler(object sender, FrameResizeEventArgs e);
+		
+		public event FrameResizeEventHandler FrameResize;
+		
+		protected virtual void OnFrameResize(FrameResizeEventArgs e)
+		{
+			if (FrameResize!=null)
+			{
+				FrameResize(this,e);
+			}
+		}
+		
 		private const int	SIZE=256;
 		private Color		TRANS=Color.Empty;
 
@@ -89,35 +117,37 @@ namespace BitmapSpriteEd
 
 		//private bool		m_inEditor;
 		
-		private Frame		m_char;
-		private Frame		m_undo;
-		private int			m_width;
-		private int			m_height;
+		private Frame				m_char;
+		private Frame				m_undo;
+		private int					m_width;
+		private int					m_height;
+		
+		private Rectangle			m_editRect;
+		private Bitmap				m_editBmp;
+		private Rectangle			m_prevRect;
+		private Bitmap				m_prevBmp;
 		
-		private Rectangle	m_editRect;
-		private Bitmap		m_editBmp;
-		private Rectangle	m_prevRect;
-		private Bitmap		m_prevBmp;
+		private int					m_grid;
+		private int					m_mx;
+		private int					m_my;
 		
-		private int			m_grid;
-		private int			m_mx;
-		private int			m_my;
+		private bool				m_drawing;
+		private Mode				m_mode;
+		private Color[,]			m_overlay;
+		private int					m_ox;
+		private int					m_oy;
+		private Color				m_pen;
 		
-		private bool		m_drawing;
-		private Mode		m_mode;
-		private Color[,]	m_overlay;
-		private int			m_ox;
-		private int			m_oy;
-		private Color		m_pen;
+		private CopyMenu			m_cpMenu;
+		private int					m_cpX;
+		private int					m_cpY;
+		private int					m_cpWidth;
+		private int					m_cpHeight;
+		private Color[,]			m_cpBuff;
 		
-		private CopyMenu	m_cpMenu;
-		private int			m_cpX;
-		private int			m_cpY;
-		private int			m_cpWidth;
-		private int			m_cpHeight;
-		private Color[,]	m_cpBuff;
+		private ManipulationMenu	m_manipMenu;
 		
-		private Label[]		m_recent;
+		private Label[]				m_recent;
 		
 		public GfxEditor()
 		{
@@ -155,6 +185,7 @@ namespace BitmapSpriteEd
 			m_modeList.SelectedIndex=0;
 			
 			m_cpMenu=new CopyMenu();
+			m_manipMenu=new ManipulationMenu();
 			
 			m_recent=new Label[]
 				{m_recent1,m_recent2,m_recent3,m_recent4,
@@ -168,126 +199,104 @@ namespace BitmapSpriteEd
 		/// not be able to load this method if it was changed manually.
 		/// </summary>
 		private void InitializeComponent() {
-			this.m_backCol = new System.Windows.Forms.Label();
-			this.label4 = new System.Windows.Forms.Label();
-			this.label5 = new System.Windows.Forms.Label();
-			this.label6 = new System.Windows.Forms.Label();
-			this.label7 = new System.Windows.Forms.Label();
-			this.m_sizeX = new System.Windows.Forms.ComboBox();
-			this.label1 = new System.Windows.Forms.Label();
-			this.label2 = new System.Windows.Forms.Label();
-			this.label3 = new System.Windows.Forms.Label();
-			this.m_undoButton = new System.Windows.Forms.Button();
+			this.m_pos = new System.Windows.Forms.Label();
+			this.m_modeList = new System.Windows.Forms.ComboBox();
+			this.m_bgPreview = new System.Windows.Forms.Label();
+			this.m_preview = new System.Windows.Forms.PictureBox();
+			this.m_gridCol = new System.Windows.Forms.Label();
 			this.label15 = new System.Windows.Forms.Label();
+			this.m_undoButton = new System.Windows.Forms.Button();
+			this.label12 = new System.Windows.Forms.Label();
 			this.label14 = new System.Windows.Forms.Label();
-			this.m_recent4 = new System.Windows.Forms.Label();
-			this.m_pos = new System.Windows.Forms.Label();
 			this.label13 = new System.Windows.Forms.Label();
-			this.label12 = new System.Windows.Forms.Label();
-			this.m_edit = new System.Windows.Forms.PictureBox();
-			this.m_gridCol = new System.Windows.Forms.Label();
-			this.m_preview = new System.Windows.Forms.PictureBox();
-			this.m_mark = new System.Windows.Forms.CheckBox();
-			this.m_sizeY = new System.Windows.Forms.ComboBox();
+			this.m_recent3 = new System.Windows.Forms.Label();
 			this.m_recent2 = new System.Windows.Forms.Label();
-			this.m_bgPreview = new System.Windows.Forms.Label();
-			this.m_recent7 = new System.Windows.Forms.Label();
+			this.m_recent1 = new System.Windows.Forms.Label();
+			this.m_mark = new System.Windows.Forms.CheckBox();
+			this.label11 = new System.Windows.Forms.Label();
 			this.m_recent6 = new System.Windows.Forms.Label();
 			this.m_recent5 = new System.Windows.Forms.Label();
-			this.m_recent3 = new System.Windows.Forms.Label();
-			this.label11 = new System.Windows.Forms.Label();
-			this.m_recent1 = new System.Windows.Forms.Label();
+			this.m_recent4 = new System.Windows.Forms.Label();
+			this.m_recent7 = new System.Windows.Forms.Label();
 			this.m_recent8 = new System.Windows.Forms.Label();
-			this.m_modeList = new System.Windows.Forms.ComboBox();
+			this.label4 = new System.Windows.Forms.Label();
+			this.m_edit = new System.Windows.Forms.PictureBox();
+			this.label6 = new System.Windows.Forms.Label();
+			this.label7 = new System.Windows.Forms.Label();
+			this.label1 = new System.Windows.Forms.Label();
+			this.label2 = new System.Windows.Forms.Label();
+			this.label3 = new System.Windows.Forms.Label();
+			this.m_manipButton = new System.Windows.Forms.Button();
+			this.m_sizeX = new System.Windows.Forms.ComboBox();
+			this.m_sizeY = new System.Windows.Forms.ComboBox();
 			this.m_fgPreview = new System.Windows.Forms.Label();
+			this.label5 = new System.Windows.Forms.Label();
+			this.m_backCol = new System.Windows.Forms.Label();
 			this.SuspendLayout();
 			// 
-			// m_backCol
-			// 
-			this.m_backCol.BackColor = System.Drawing.Color.Black;
-			this.m_backCol.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
-			this.m_backCol.Location = new System.Drawing.Point(168, 272);
-			this.m_backCol.Name = "m_backCol";
-			this.m_backCol.Size = new System.Drawing.Size(24, 24);
-			this.m_backCol.TabIndex = 34;
-			this.m_backCol.Click += new System.EventHandler(this.OnPaper);
-			// 
-			// label4
-			// 
-			this.label4.Location = new System.Drawing.Point(280, 88);
-			this.label4.Name = "label4";
-			this.label4.Size = new System.Drawing.Size(32, 16);
-			this.label4.TabIndex = 10;
-			this.label4.Text = "Left";
-			this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
-			// 
-			// label5
-			// 
-			this.label5.Location = new System.Drawing.Point(336, 88);
-			this.label5.Name = "label5";
-			this.label5.Size = new System.Drawing.Size(40, 16);
-			this.label5.TabIndex = 12;
-			this.label5.Text = "Right";
-			this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
-			// 
-			// label6
+			// m_pos
 			// 
-			this.label6.Location = new System.Drawing.Point(336, 8);
-			this.label6.Name = "label6";
-			this.label6.Size = new System.Drawing.Size(48, 16);
-			this.label6.TabIndex = 22;
-			this.label6.Text = "Height";
-			this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			this.m_pos.Location = new System.Drawing.Point(208, 272);
+			this.m_pos.Name = "m_pos";
+			this.m_pos.Size = new System.Drawing.Size(56, 24);
+			this.m_pos.TabIndex = 23;
+			this.m_pos.TextAlign = System.Drawing.ContentAlignment.TopRight;
 			// 
-			// label7
+			// m_modeList
 			// 
-			this.label7.Location = new System.Drawing.Point(280, 232);
-			this.label7.Name = "label7";
-			this.label7.Size = new System.Drawing.Size(88, 16);
-			this.label7.TabIndex = 24;
-			this.label7.Text = "Recent Colours";
-			this.label7.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			this.m_modeList.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.m_modeList.Items.AddRange(new object[] {
+						"Plot",
+						"Line",
+						"Rectangle",
+						"Filled Rect",
+						"Circle",
+						"Filled Circle",
+						"Ellipse",
+						"Filled Ellipse",
+						"Flood Fill",
+						"Copy/Paste"});
+			this.m_modeList.Location = new System.Drawing.Point(280, 64);
+			this.m_modeList.MaxDropDownItems = 16;
+			this.m_modeList.Name = "m_modeList";
+			this.m_modeList.Size = new System.Drawing.Size(104, 21);
+			this.m_modeList.TabIndex = 15;
+			this.m_modeList.SelectedIndexChanged += new System.EventHandler(this.OnModeSelect);
 			// 
-			// m_sizeX
+			// m_bgPreview
 			// 
-			this.m_sizeX.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-			this.m_sizeX.Enabled = false;
-			this.m_sizeX.Items.AddRange(new object[] {
-						"8",
-						"16",
-						"32"});
-			this.m_sizeX.Location = new System.Drawing.Point(280, 24);
-			this.m_sizeX.Name = "m_sizeX";
-			this.m_sizeX.Size = new System.Drawing.Size(48, 21);
-			this.m_sizeX.TabIndex = 36;
-			this.m_sizeX.SelectedIndexChanged += new System.EventHandler(this.OnSizeWidth);
+			this.m_bgPreview.BackColor = System.Drawing.Color.Transparent;
+			this.m_bgPreview.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+			this.m_bgPreview.Location = new System.Drawing.Point(336, 104);
+			this.m_bgPreview.Name = "m_bgPreview";
+			this.m_bgPreview.Size = new System.Drawing.Size(40, 32);
+			this.m_bgPreview.TabIndex = 18;
+			this.m_bgPreview.Click += new System.EventHandler(this.OnBackground);
 			// 
-			// label1
+			// m_preview
 			// 
-			this.label1.Location = new System.Drawing.Point(280, 48);
-			this.label1.Name = "label1";
-			this.label1.Size = new System.Drawing.Size(64, 16);
-			this.label1.TabIndex = 3;
-			this.label1.Text = "Draw Mode";
-			this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			this.m_preview.BackColor = System.Drawing.SystemColors.Control;
+			this.m_preview.Location = new System.Drawing.Point(288, 192);
+			this.m_preview.Name = "m_preview";
+			this.m_preview.Size = new System.Drawing.Size(34, 34);
+			this.m_preview.TabIndex = 1;
+			this.m_preview.TabStop = false;
 			// 
-			// label2
+			// m_gridCol
 			// 
-			this.label2.Location = new System.Drawing.Point(280, 168);
-			this.label2.Name = "label2";
-			this.label2.Size = new System.Drawing.Size(56, 16);
-			this.label2.TabIndex = 21;
-			this.label2.Text = "Preview";
-			this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			this.m_gridCol.BackColor = System.Drawing.Color.Lime;
+			this.m_gridCol.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+			this.m_gridCol.Location = new System.Drawing.Point(136, 272);
+			this.m_gridCol.Name = "m_gridCol";
+			this.m_gridCol.Size = new System.Drawing.Size(24, 24);
+			this.m_gridCol.TabIndex = 33;
+			this.m_gridCol.Click += new System.EventHandler(this.OnGrid);
 			// 
-			// label3
+			// label15
 			// 
-			this.label3.Location = new System.Drawing.Point(280, 8);
-			this.label3.Name = "label3";
-			this.label3.Size = new System.Drawing.Size(48, 16);
-			this.label3.TabIndex = 8;
-			this.label3.Text = "Width";
-			this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			this.label15.Location = new System.Drawing.Point(0, 0);
+			this.label15.Name = "label15";
+			this.label15.TabIndex = 0;
 			// 
 			// m_undoButton
 			// 
@@ -298,11 +307,13 @@ namespace BitmapSpriteEd
 			this.m_undoButton.Text = "Undo";
 			this.m_undoButton.Click += new System.EventHandler(this.OnUndo);
 			// 
-			// label15
+			// label12
 			// 
-			this.label15.Location = new System.Drawing.Point(0, 0);
-			this.label15.Name = "label15";
-			this.label15.TabIndex = 0;
+			this.label12.BackColor = System.Drawing.Color.White;
+			this.label12.Location = new System.Drawing.Point(200, 144);
+			this.label12.Name = "label12";
+			this.label12.Size = new System.Drawing.Size(16, 16);
+			this.label12.TabIndex = 31;
 			// 
 			// label14
 			// 
@@ -312,97 +323,23 @@ namespace BitmapSpriteEd
 			this.label14.Size = new System.Drawing.Size(16, 16);
 			this.label14.TabIndex = 29;
 			// 
-			// m_recent4
-			// 
-			this.m_recent4.BackColor = System.Drawing.Color.Black;
-			this.m_recent4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
-			this.m_recent4.Location = new System.Drawing.Point(352, 248);
-			this.m_recent4.Name = "m_recent4";
-			this.m_recent4.Size = new System.Drawing.Size(16, 16);
-			this.m_recent4.TabIndex = 28;
-			this.m_recent4.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
-			// 
-			// m_pos
-			// 
-			this.m_pos.Location = new System.Drawing.Point(208, 272);
-			this.m_pos.Name = "m_pos";
-			this.m_pos.Size = new System.Drawing.Size(56, 24);
-			this.m_pos.TabIndex = 23;
-			this.m_pos.TextAlign = System.Drawing.ContentAlignment.TopRight;
-			// 
 			// label13
 			// 
 			this.label13.BackColor = System.Drawing.Color.White;
 			this.label13.Location = new System.Drawing.Point(176, 144);
 			this.label13.Name = "label13";
 			this.label13.Size = new System.Drawing.Size(16, 16);
-			this.label13.TabIndex = 30;
-			// 
-			// label12
-			// 
-			this.label12.BackColor = System.Drawing.Color.White;
-			this.label12.Location = new System.Drawing.Point(200, 144);
-			this.label12.Name = "label12";
-			this.label12.Size = new System.Drawing.Size(16, 16);
-			this.label12.TabIndex = 31;
-			// 
-			// m_edit
-			// 
-			this.m_edit.BackColor = System.Drawing.SystemColors.Control;
-			this.m_edit.Location = new System.Drawing.Point(8, 8);
-			this.m_edit.Name = "m_edit";
-			this.m_edit.Size = new System.Drawing.Size(256, 256);
-			this.m_edit.TabIndex = 0;
-			this.m_edit.TabStop = false;
-			this.m_edit.MouseEnter += new System.EventHandler(this.OnEnterEditor);
-			this.m_edit.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnMouseMove);
-			this.m_edit.MouseMove += new System.Windows.Forms.MouseEventHandler(this.OnMouseMove);
-			this.m_edit.MouseLeave += new System.EventHandler(this.OnLeaveEditor);
-			this.m_edit.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnMouseMove);
-			// 
-			// m_gridCol
-			// 
-			this.m_gridCol.BackColor = System.Drawing.Color.Lime;
-			this.m_gridCol.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
-			this.m_gridCol.Location = new System.Drawing.Point(136, 272);
-			this.m_gridCol.Name = "m_gridCol";
-			this.m_gridCol.Size = new System.Drawing.Size(24, 24);
-			this.m_gridCol.TabIndex = 33;
-			this.m_gridCol.Click += new System.EventHandler(this.OnGrid);
-			// 
-			// m_preview
-			// 
-			this.m_preview.BackColor = System.Drawing.SystemColors.Control;
-			this.m_preview.Location = new System.Drawing.Point(288, 192);
-			this.m_preview.Name = "m_preview";
-			this.m_preview.Size = new System.Drawing.Size(34, 34);
-			this.m_preview.TabIndex = 1;
-			this.m_preview.TabStop = false;
-			// 
-			// m_mark
-			// 
-			this.m_mark.Checked = true;
-			this.m_mark.CheckState = System.Windows.Forms.CheckState.Checked;
-			this.m_mark.Location = new System.Drawing.Point(280, 136);
-			this.m_mark.Name = "m_mark";
-			this.m_mark.Size = new System.Drawing.Size(96, 32);
-			this.m_mark.TabIndex = 35;
-			this.m_mark.Text = "Highlight Dark Colours";
-			this.m_mark.CheckedChanged += new System.EventHandler(this.OnMark);
-			// 
-			// m_sizeY
-			// 
-			this.m_sizeY.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-			this.m_sizeY.Enabled = false;
-			this.m_sizeY.Items.AddRange(new object[] {
-						"8",
-						"16",
-						"32"});
-			this.m_sizeY.Location = new System.Drawing.Point(336, 24);
-			this.m_sizeY.Name = "m_sizeY";
-			this.m_sizeY.Size = new System.Drawing.Size(48, 21);
-			this.m_sizeY.TabIndex = 37;
-			this.m_sizeY.SelectedIndexChanged += new System.EventHandler(this.OnSizeHeight);
+			this.label13.TabIndex = 30;
+			// 
+			// m_recent3
+			// 
+			this.m_recent3.BackColor = System.Drawing.Color.Black;
+			this.m_recent3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+			this.m_recent3.Location = new System.Drawing.Point(328, 248);
+			this.m_recent3.Name = "m_recent3";
+			this.m_recent3.Size = new System.Drawing.Size(16, 16);
+			this.m_recent3.TabIndex = 27;
+			this.m_recent3.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
 			// 
 			// m_recent2
 			// 
@@ -414,25 +351,34 @@ namespace BitmapSpriteEd
 			this.m_recent2.TabIndex = 26;
 			this.m_recent2.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
 			// 
-			// m_bgPreview
+			// m_recent1
 			// 
-			this.m_bgPreview.BackColor = System.Drawing.Color.Transparent;
-			this.m_bgPreview.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
-			this.m_bgPreview.Location = new System.Drawing.Point(336, 104);
-			this.m_bgPreview.Name = "m_bgPreview";
-			this.m_bgPreview.Size = new System.Drawing.Size(40, 32);
-			this.m_bgPreview.TabIndex = 18;
-			this.m_bgPreview.Click += new System.EventHandler(this.OnBackground);
+			this.m_recent1.BackColor = System.Drawing.Color.White;
+			this.m_recent1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+			this.m_recent1.Location = new System.Drawing.Point(280, 248);
+			this.m_recent1.Name = "m_recent1";
+			this.m_recent1.Size = new System.Drawing.Size(16, 16);
+			this.m_recent1.TabIndex = 25;
+			this.m_recent1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
 			// 
-			// m_recent7
+			// m_mark
 			// 
-			this.m_recent7.BackColor = System.Drawing.Color.Black;
-			this.m_recent7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
-			this.m_recent7.Location = new System.Drawing.Point(328, 272);
-			this.m_recent7.Name = "m_recent7";
-			this.m_recent7.Size = new System.Drawing.Size(16, 16);
-			this.m_recent7.TabIndex = 31;
-			this.m_recent7.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
+			this.m_mark.Checked = true;
+			this.m_mark.CheckState = System.Windows.Forms.CheckState.Checked;
+			this.m_mark.Location = new System.Drawing.Point(280, 136);
+			this.m_mark.Name = "m_mark";
+			this.m_mark.Size = new System.Drawing.Size(96, 32);
+			this.m_mark.TabIndex = 35;
+			this.m_mark.Text = "Highlight Dark Colours";
+			this.m_mark.CheckedChanged += new System.EventHandler(this.OnMark);
+			// 
+			// label11
+			// 
+			this.label11.BackColor = System.Drawing.Color.White;
+			this.label11.Location = new System.Drawing.Point(224, 144);
+			this.label11.Name = "label11";
+			this.label11.Size = new System.Drawing.Size(16, 16);
+			this.label11.TabIndex = 32;
 			// 
 			// m_recent6
 			// 
@@ -454,33 +400,25 @@ namespace BitmapSpriteEd
 			this.m_recent5.TabIndex = 29;
 			this.m_recent5.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
 			// 
-			// m_recent3
-			// 
-			this.m_recent3.BackColor = System.Drawing.Color.Black;
-			this.m_recent3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
-			this.m_recent3.Location = new System.Drawing.Point(328, 248);
-			this.m_recent3.Name = "m_recent3";
-			this.m_recent3.Size = new System.Drawing.Size(16, 16);
-			this.m_recent3.TabIndex = 27;
-			this.m_recent3.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
-			// 
-			// label11
+			// m_recent4
 			// 
-			this.label11.BackColor = System.Drawing.Color.White;
-			this.label11.Location = new System.Drawing.Point(224, 144);
-			this.label11.Name = "label11";
-			this.label11.Size = new System.Drawing.Size(16, 16);
-			this.label11.TabIndex = 32;
+			this.m_recent4.BackColor = System.Drawing.Color.Black;
+			this.m_recent4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+			this.m_recent4.Location = new System.Drawing.Point(352, 248);
+			this.m_recent4.Name = "m_recent4";
+			this.m_recent4.Size = new System.Drawing.Size(16, 16);
+			this.m_recent4.TabIndex = 28;
+			this.m_recent4.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
 			// 
-			// m_recent1
+			// m_recent7
 			// 
-			this.m_recent1.BackColor = System.Drawing.Color.White;
-			this.m_recent1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
-			this.m_recent1.Location = new System.Drawing.Point(280, 248);
-			this.m_recent1.Name = "m_recent1";
-			this.m_recent1.Size = new System.Drawing.Size(16, 16);
-			this.m_recent1.TabIndex = 25;
-			this.m_recent1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
+			this.m_recent7.BackColor = System.Drawing.Color.Black;
+			this.m_recent7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+			this.m_recent7.Location = new System.Drawing.Point(328, 272);
+			this.m_recent7.Name = "m_recent7";
+			this.m_recent7.Size = new System.Drawing.Size(16, 16);
+			this.m_recent7.TabIndex = 31;
+			this.m_recent7.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
 			// 
 			// m_recent8
 			// 
@@ -492,26 +430,111 @@ namespace BitmapSpriteEd
 			this.m_recent8.TabIndex = 32;
 			this.m_recent8.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnRecent);
 			// 
-			// m_modeList
+			// label4
 			// 
-			this.m_modeList.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-			this.m_modeList.Items.AddRange(new object[] {
-						"Plot",
-						"Line",
-						"Rectangle",
-						"Filled Rect",
-						"Circle",
-						"Filled Circle",
-						"Ellipse",
-						"Filled Ellipse",
-						"Flood Fill",
-						"Copy/Paste"});
-			this.m_modeList.Location = new System.Drawing.Point(280, 64);
-			this.m_modeList.MaxDropDownItems = 16;
-			this.m_modeList.Name = "m_modeList";
-			this.m_modeList.Size = new System.Drawing.Size(104, 21);
-			this.m_modeList.TabIndex = 15;
-			this.m_modeList.SelectedIndexChanged += new System.EventHandler(this.OnModeSelect);
+			this.label4.Location = new System.Drawing.Point(280, 88);
+			this.label4.Name = "label4";
+			this.label4.Size = new System.Drawing.Size(32, 16);
+			this.label4.TabIndex = 10;
+			this.label4.Text = "Left";
+			this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			// 
+			// m_edit
+			// 
+			this.m_edit.BackColor = System.Drawing.SystemColors.Control;
+			this.m_edit.Location = new System.Drawing.Point(8, 8);
+			this.m_edit.Name = "m_edit";
+			this.m_edit.Size = new System.Drawing.Size(256, 256);
+			this.m_edit.TabIndex = 0;
+			this.m_edit.TabStop = false;
+			this.m_edit.MouseEnter += new System.EventHandler(this.OnEnterEditor);
+			this.m_edit.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnMouseMove);
+			this.m_edit.MouseMove += new System.Windows.Forms.MouseEventHandler(this.OnMouseMove);
+			this.m_edit.MouseLeave += new System.EventHandler(this.OnLeaveEditor);
+			this.m_edit.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnMouseMove);
+			// 
+			// label6
+			// 
+			this.label6.Location = new System.Drawing.Point(336, 8);
+			this.label6.Name = "label6";
+			this.label6.Size = new System.Drawing.Size(48, 16);
+			this.label6.TabIndex = 22;
+			this.label6.Text = "Height";
+			this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			// 
+			// label7
+			// 
+			this.label7.Location = new System.Drawing.Point(280, 232);
+			this.label7.Name = "label7";
+			this.label7.Size = new System.Drawing.Size(88, 16);
+			this.label7.TabIndex = 24;
+			this.label7.Text = "Recent Colours";
+			this.label7.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			// 
+			// label1
+			// 
+			this.label1.Location = new System.Drawing.Point(280, 48);
+			this.label1.Name = "label1";
+			this.label1.Size = new System.Drawing.Size(64, 16);
+			this.label1.TabIndex = 3;
+			this.label1.Text = "Draw Mode";
+			this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			// 
+			// label2
+			// 
+			this.label2.Location = new System.Drawing.Point(280, 168);
+			this.label2.Name = "label2";
+			this.label2.Size = new System.Drawing.Size(56, 16);
+			this.label2.TabIndex = 21;
+			this.label2.Text = "Preview";
+			this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			// 
+			// label3
+			// 
+			this.label3.Location = new System.Drawing.Point(280, 8);
+			this.label3.Name = "label3";
+			this.label3.Size = new System.Drawing.Size(48, 16);
+			this.label3.TabIndex = 8;
+			this.label3.Text = "Width";
+			this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			// 
+			// m_manipButton
+			// 
+			this.m_manipButton.Enabled = false;
+			this.m_manipButton.Location = new System.Drawing.Point(336, 184);
+			this.m_manipButton.Name = "m_manipButton";
+			this.m_manipButton.Size = new System.Drawing.Size(48, 24);
+			this.m_manipButton.TabIndex = 38;
+			this.m_manipButton.Text = "Manip";
+			this.m_manipButton.Click += new System.EventHandler(this.OnManip);
+			// 
+			// m_sizeX
+			// 
+			this.m_sizeX.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.m_sizeX.Enabled = false;
+			this.m_sizeX.Items.AddRange(new object[] {
+						"8",
+						"16",
+						"32"});
+			this.m_sizeX.Location = new System.Drawing.Point(280, 24);
+			this.m_sizeX.Name = "m_sizeX";
+			this.m_sizeX.Size = new System.Drawing.Size(48, 21);
+			this.m_sizeX.TabIndex = 36;
+			this.m_sizeX.SelectedIndexChanged += new System.EventHandler(this.OnSizeWidth);
+			// 
+			// m_sizeY
+			// 
+			this.m_sizeY.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.m_sizeY.Enabled = false;
+			this.m_sizeY.Items.AddRange(new object[] {
+						"8",
+						"16",
+						"32"});
+			this.m_sizeY.Location = new System.Drawing.Point(336, 24);
+			this.m_sizeY.Name = "m_sizeY";
+			this.m_sizeY.Size = new System.Drawing.Size(48, 21);
+			this.m_sizeY.TabIndex = 37;
+			this.m_sizeY.SelectedIndexChanged += new System.EventHandler(this.OnSizeHeight);
 			// 
 			// m_fgPreview
 			// 
@@ -523,8 +546,28 @@ namespace BitmapSpriteEd
 			this.m_fgPreview.TabIndex = 17;
 			this.m_fgPreview.Click += new System.EventHandler(this.OnForeground);
 			// 
+			// label5
+			// 
+			this.label5.Location = new System.Drawing.Point(336, 88);
+			this.label5.Name = "label5";
+			this.label5.Size = new System.Drawing.Size(40, 16);
+			this.label5.TabIndex = 12;
+			this.label5.Text = "Right";
+			this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			// 
+			// m_backCol
+			// 
+			this.m_backCol.BackColor = System.Drawing.Color.Black;
+			this.m_backCol.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+			this.m_backCol.Location = new System.Drawing.Point(168, 272);
+			this.m_backCol.Name = "m_backCol";
+			this.m_backCol.Size = new System.Drawing.Size(24, 24);
+			this.m_backCol.TabIndex = 34;
+			this.m_backCol.Click += new System.EventHandler(this.OnPaper);
+			// 
 			// GfxEditor
 			// 
+			this.Controls.Add(this.m_manipButton);
 			this.Controls.Add(this.m_sizeY);
 			this.Controls.Add(this.m_sizeX);
 			this.Controls.Add(this.m_mark);
@@ -580,6 +623,7 @@ namespace BitmapSpriteEd
 			{
 				m_char=value;
 				SetUndo(null);
+				m_manipButton.Enabled=true;
 				m_width=m_char.Width;
 				m_height=m_char.Height;
 				m_sizeX.Enabled=true;
@@ -1078,6 +1122,8 @@ namespace BitmapSpriteEd
 			
 			DrawGrid();
 			DrawChar();
+			
+			OnFrameResize(new FrameResizeEventArgs(m_width,m_height));
 		}
 		
 		void OnSizeHeight(object sender, System.EventArgs e)
@@ -1098,6 +1144,8 @@ namespace BitmapSpriteEd
 			
 			DrawGrid();
 			DrawChar();
+			
+			OnFrameResize(new FrameResizeEventArgs(m_width,m_height));
 		}
 		
 		void OnEnterEditor(object sender, System.EventArgs e)
@@ -1132,9 +1180,9 @@ namespace BitmapSpriteEd
 		{
 			if (m_undo!=null)
 			{
-				Frame s=m_char;
-				m_char=m_undo;
-				m_undo=s;
+				Frame u=new Frame(m_char);
+				m_char.CopyFrom(m_undo);
+				m_undo=u;
 				DrawChar();
 			}
 		}
@@ -1393,6 +1441,58 @@ namespace BitmapSpriteEd
 			RedrawChar();
 		}
 		
+		void OnManip(object sender, System.EventArgs e)
+		{
+			Control c=(Control)sender;
+			bool redraw=true;
+			
+			m_manipMenu.Show(c,c.Width,c.Height/2);
+			
+			switch(m_manipMenu.Mode)
+			{
+				case ManipulationMenu.EMode.eMirrorHorizontal:
+					m_char.MirrorHorizontal();
+					break;
+
+				case ManipulationMenu.EMode.eMirrorVertical:
+					m_char.MirrorVertical();
+					break;
+
+				case ManipulationMenu.EMode.eRotateLeft:
+					m_char.RotateLeft();
+					break;
+
+				case ManipulationMenu.EMode.eRotateRight:
+					m_char.RotateRight();
+					break;
+
+				case ManipulationMenu.EMode.eScrollUp:
+					m_char.Scroll(0,-1);
+					break;
+
+				case ManipulationMenu.EMode.eScrollDown:
+					m_char.Scroll(0,1);
+					break;
+
+				case ManipulationMenu.EMode.eScrollLeft:
+					m_char.Scroll(-1,0);
+					break;
+
+				case ManipulationMenu.EMode.eScrollRight:
+					m_char.Scroll(1,0);
+					break;
+
+				case ManipulationMenu.EMode.eNothing:
+					redraw=false;
+					break;
+			}
+			
+			if (redraw)
+			{
+				RedrawChar();
+			}
+		}
+		
 		#endregion
 	}
 }
diff --git a/MainForm.cs b/MainForm.cs
index 13da6d8..18ffb97 100644
--- a/MainForm.cs
+++ b/MainForm.cs
@@ -19,7 +19,9 @@
 //
 using System;
 using System.Drawing;
+using System.Drawing.Imaging;
 using System.Windows.Forms;
+using System.IO;
 
 namespace BitmapSpriteEd
 {
@@ -28,34 +30,50 @@ namespace BitmapSpriteEd
 	/// </summary>
 	public class MainForm : System.Windows.Forms.Form
 	{
-		private System.Windows.Forms.MainMenu m_menu;
-		private System.Windows.Forms.NumericUpDown m_frameNum;
-		private System.Windows.Forms.MenuItem m_new;
-		private System.Windows.Forms.Button m_addFrame;
-		private System.Windows.Forms.MenuItem m_about;
-		private System.Windows.Forms.NumericUpDown m_spriteNum;
-		private System.Windows.Forms.TextBox m_spriteName;
-		private System.Windows.Forms.MenuItem m_saveAs;
+		private System.ComponentModel.IContainer components;
+		private System.Windows.Forms.Label label1;
+		private System.Windows.Forms.MenuItem m_helpMenu;
 		private System.Windows.Forms.Button m_removeFrame;
-		private System.Windows.Forms.MenuItem m_open;
+		private System.Windows.Forms.Button m_addFrame;
+		private System.Windows.Forms.MenuItem m_break1;
 		private System.Windows.Forms.MenuItem m_fileMenu;
+		private System.Windows.Forms.Button m_addSprite;
+		private System.Windows.Forms.MenuItem m_exportSinglePNG;
+		private System.Windows.Forms.Label m_spriteCount;
+		private System.Windows.Forms.Button m_removeSprite;
+		private System.Windows.Forms.TextBox m_spriteName;
 		private System.Windows.Forms.MenuItem m_exportMenu;
-		private System.Windows.Forms.MenuItem m_quit;
-		private System.Windows.Forms.MenuItem m_exportPNG;
-		private System.Windows.Forms.GroupBox m_animGroup;
+		private System.Windows.Forms.CheckBox m_addFrameAsCopy;
+		private System.Windows.Forms.MenuItem m_about;
 		private System.Windows.Forms.Label label3;
 		private System.Windows.Forms.Label label2;
-		private System.Windows.Forms.Label label1;
-		private System.Windows.Forms.MenuItem m_break1;
-		private System.Windows.Forms.GroupBox m_editGroup;
-		private System.Windows.Forms.Button m_addSprite;
+		private System.Windows.Forms.CheckBox m_animStretch;
+		private System.Windows.Forms.Label label4;
+		private System.Windows.Forms.Timer m_timer;
+		private System.Windows.Forms.MainMenu m_menu;
+		private System.Windows.Forms.GroupBox m_animGroup;
+		private System.Windows.Forms.CheckBox m_animEnable;
+		private System.Windows.Forms.NumericUpDown m_animSpeed;
+		private System.Windows.Forms.MenuItem m_quit;
 		private System.Windows.Forms.MenuItem m_save;
+		private System.Windows.Forms.MenuItem m_exportPNG;
+		private System.Windows.Forms.MenuItem m_saveAs;
+		private System.Windows.Forms.CheckBox m_animPong;
+		private System.Windows.Forms.NumericUpDown m_spriteNum;
+		private System.Windows.Forms.GroupBox m_editGroup;
+		private System.Windows.Forms.MenuItem m_new;
+		private System.Windows.Forms.MenuItem m_open;
+		private System.Windows.Forms.PictureBox m_preview;
+		private System.Windows.Forms.Label m_frameCount;
 		private System.Windows.Forms.GroupBox m_spriteGroup;
-		private System.Windows.Forms.Button m_removeSprite;
-		private System.Windows.Forms.MenuItem m_helpMenu;
+		private System.Windows.Forms.NumericUpDown m_frameNum;
 
 		private GfxEditor			m_edit;
 		private SpriteList			m_sprites;
+		private string				m_path;
+		private string				m_exportPath;
+		private int					m_animIndex;
+		private int					m_animIndexInc=1;
 		
 		public MainForm()
 		{
@@ -64,10 +82,16 @@ namespace BitmapSpriteEd
 			//
 			InitializeComponent();
 			
+			m_path="";
+			m_exportPath="";
+			m_sprites=new SpriteList();
+			
 			m_edit=new GfxEditor();
 			m_edit.Location=new Point(4,16);
 			m_editGroup.Controls.Add(m_edit);
 			
+			m_edit.FrameResize+=new GfxEditor.FrameResizeEventHandler(OnFrameResize);
+			
 			OnNew(null,null);
 		}
 		
@@ -84,54 +108,75 @@ namespace BitmapSpriteEd
 		/// not be able to load this method if it was changed manually.
 		/// </summary>
 		private void InitializeComponent() {
-			this.m_helpMenu = new System.Windows.Forms.MenuItem();
-			this.m_removeSprite = new System.Windows.Forms.Button();
+			this.components = new System.ComponentModel.Container();
+			this.m_frameNum = new System.Windows.Forms.NumericUpDown();
 			this.m_spriteGroup = new System.Windows.Forms.GroupBox();
-			this.m_save = new System.Windows.Forms.MenuItem();
-			this.m_addSprite = new System.Windows.Forms.Button();
+			this.m_frameCount = new System.Windows.Forms.Label();
+			this.m_preview = new System.Windows.Forms.PictureBox();
+			this.m_open = new System.Windows.Forms.MenuItem();
+			this.m_new = new System.Windows.Forms.MenuItem();
 			this.m_editGroup = new System.Windows.Forms.GroupBox();
-			this.m_break1 = new System.Windows.Forms.MenuItem();
-			this.label1 = new System.Windows.Forms.Label();
-			this.label2 = new System.Windows.Forms.Label();
-			this.label3 = new System.Windows.Forms.Label();
-			this.m_animGroup = new System.Windows.Forms.GroupBox();
+			this.m_spriteNum = new System.Windows.Forms.NumericUpDown();
+			this.m_animPong = new System.Windows.Forms.CheckBox();
+			this.m_saveAs = new System.Windows.Forms.MenuItem();
 			this.m_exportPNG = new System.Windows.Forms.MenuItem();
+			this.m_save = new System.Windows.Forms.MenuItem();
 			this.m_quit = new System.Windows.Forms.MenuItem();
+			this.m_animSpeed = new System.Windows.Forms.NumericUpDown();
+			this.m_animEnable = new System.Windows.Forms.CheckBox();
+			this.m_animGroup = new System.Windows.Forms.GroupBox();
+			this.m_menu = new System.Windows.Forms.MainMenu();
+			this.m_timer = new System.Windows.Forms.Timer(this.components);
+			this.label4 = new System.Windows.Forms.Label();
+			this.m_animStretch = new System.Windows.Forms.CheckBox();
+			this.label2 = new System.Windows.Forms.Label();
+			this.label3 = new System.Windows.Forms.Label();
+			this.m_about = new System.Windows.Forms.MenuItem();
+			this.m_addFrameAsCopy = new System.Windows.Forms.CheckBox();
 			this.m_exportMenu = new System.Windows.Forms.MenuItem();
-			this.m_fileMenu = new System.Windows.Forms.MenuItem();
-			this.m_open = new System.Windows.Forms.MenuItem();
-			this.m_removeFrame = new System.Windows.Forms.Button();
-			this.m_saveAs = new System.Windows.Forms.MenuItem();
 			this.m_spriteName = new System.Windows.Forms.TextBox();
-			this.m_spriteNum = new System.Windows.Forms.NumericUpDown();
-			this.m_about = new System.Windows.Forms.MenuItem();
+			this.m_removeSprite = new System.Windows.Forms.Button();
+			this.m_spriteCount = new System.Windows.Forms.Label();
+			this.m_exportSinglePNG = new System.Windows.Forms.MenuItem();
+			this.m_addSprite = new System.Windows.Forms.Button();
+			this.m_fileMenu = new System.Windows.Forms.MenuItem();
+			this.m_break1 = new System.Windows.Forms.MenuItem();
 			this.m_addFrame = new System.Windows.Forms.Button();
-			this.m_new = new System.Windows.Forms.MenuItem();
-			this.m_frameNum = new System.Windows.Forms.NumericUpDown();
-			this.m_menu = new System.Windows.Forms.MainMenu();
+			this.m_removeFrame = new System.Windows.Forms.Button();
+			this.m_helpMenu = new System.Windows.Forms.MenuItem();
+			this.label1 = new System.Windows.Forms.Label();
+			((System.ComponentModel.ISupportInitialize)(this.m_frameNum)).BeginInit();
 			this.m_spriteGroup.SuspendLayout();
 			((System.ComponentModel.ISupportInitialize)(this.m_spriteNum)).BeginInit();
-			((System.ComponentModel.ISupportInitialize)(this.m_frameNum)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.m_animSpeed)).BeginInit();
+			this.m_animGroup.SuspendLayout();
 			this.SuspendLayout();
 			// 
-			// m_helpMenu
-			// 
-			this.m_helpMenu.Index = 2;
-			this.m_helpMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
-						this.m_about});
-			this.m_helpMenu.Text = "Help";
-			// 
-			// m_removeSprite
+			// m_frameNum
 			// 
-			this.m_removeSprite.Location = new System.Drawing.Point(224, 32);
-			this.m_removeSprite.Name = "m_removeSprite";
-			this.m_removeSprite.Size = new System.Drawing.Size(64, 24);
-			this.m_removeSprite.TabIndex = 5;
-			this.m_removeSprite.Text = "Remove";
-			this.m_removeSprite.Click += new System.EventHandler(this.OnRemoveSprite);
+			this.m_frameNum.Location = new System.Drawing.Point(64, 96);
+			this.m_frameNum.Minimum = new System.Decimal(new int[] {
+						1,
+						0,
+						0,
+						0});
+			this.m_frameNum.Name = "m_frameNum";
+			this.m_frameNum.ReadOnly = true;
+			this.m_frameNum.Size = new System.Drawing.Size(64, 20);
+			this.m_frameNum.TabIndex = 2;
+			this.m_frameNum.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+			this.m_frameNum.Value = new System.Decimal(new int[] {
+						1,
+						0,
+						0,
+						0});
+			this.m_frameNum.ValueChanged += new System.EventHandler(this.OnFrameSelected);
 			// 
 			// m_spriteGroup
 			// 
+			this.m_spriteGroup.Controls.Add(this.m_addFrameAsCopy);
+			this.m_spriteGroup.Controls.Add(this.m_frameCount);
+			this.m_spriteGroup.Controls.Add(this.m_spriteCount);
 			this.m_spriteGroup.Controls.Add(this.m_spriteName);
 			this.m_spriteGroup.Controls.Add(this.label3);
 			this.m_spriteGroup.Controls.Add(this.m_removeFrame);
@@ -144,27 +189,43 @@ namespace BitmapSpriteEd
 			this.m_spriteGroup.Controls.Add(this.m_spriteNum);
 			this.m_spriteGroup.Location = new System.Drawing.Point(424, 8);
 			this.m_spriteGroup.Name = "m_spriteGroup";
-			this.m_spriteGroup.Size = new System.Drawing.Size(304, 152);
+			this.m_spriteGroup.Size = new System.Drawing.Size(288, 192);
 			this.m_spriteGroup.TabIndex = 1;
 			this.m_spriteGroup.TabStop = false;
 			this.m_spriteGroup.Text = "Sprite Frames";
 			// 
-			// m_save
+			// m_frameCount
 			// 
-			this.m_save.Enabled = false;
-			this.m_save.Index = 2;
-			this.m_save.Shortcut = System.Windows.Forms.Shortcut.CtrlS;
-			this.m_save.Text = "Save";
-			this.m_save.Click += new System.EventHandler(this.OnSave);
+			this.m_frameCount.Location = new System.Drawing.Point(136, 104);
+			this.m_frameCount.Name = "m_frameCount";
+			this.m_frameCount.Size = new System.Drawing.Size(56, 16);
+			this.m_frameCount.TabIndex = 11;
+			this.m_frameCount.Text = "label5";
 			// 
-			// m_addSprite
+			// m_preview
 			// 
-			this.m_addSprite.Location = new System.Drawing.Point(144, 32);
-			this.m_addSprite.Name = "m_addSprite";
-			this.m_addSprite.Size = new System.Drawing.Size(64, 24);
-			this.m_addSprite.TabIndex = 4;
-			this.m_addSprite.Text = "Add";
-			this.m_addSprite.Click += new System.EventHandler(this.OnAddSprite);
+			this.m_preview.BackColor = System.Drawing.Color.Black;
+			this.m_preview.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+			this.m_preview.Location = new System.Drawing.Point(176, 24);
+			this.m_preview.Name = "m_preview";
+			this.m_preview.Size = new System.Drawing.Size(64, 64);
+			this.m_preview.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
+			this.m_preview.TabIndex = 3;
+			this.m_preview.TabStop = false;
+			// 
+			// m_open
+			// 
+			this.m_open.Index = 1;
+			this.m_open.Shortcut = System.Windows.Forms.Shortcut.CtrlO;
+			this.m_open.Text = "Open";
+			this.m_open.Click += new System.EventHandler(this.OnOpen);
+			// 
+			// m_new
+			// 
+			this.m_new.Index = 0;
+			this.m_new.Shortcut = System.Windows.Forms.Shortcut.CtrlN;
+			this.m_new.Text = "New";
+			this.m_new.Click += new System.EventHandler(this.OnNew);
 			// 
 			// m_editGroup
 			// 
@@ -175,23 +236,142 @@ namespace BitmapSpriteEd
 			this.m_editGroup.TabStop = false;
 			this.m_editGroup.Text = "Editor";
 			// 
-			// m_break1
+			// m_spriteNum
 			// 
-			this.m_break1.Index = 4;
-			this.m_break1.Text = "-";
+			this.m_spriteNum.Location = new System.Drawing.Point(64, 32);
+			this.m_spriteNum.Minimum = new System.Decimal(new int[] {
+						1,
+						0,
+						0,
+						0});
+			this.m_spriteNum.Name = "m_spriteNum";
+			this.m_spriteNum.ReadOnly = true;
+			this.m_spriteNum.Size = new System.Drawing.Size(64, 20);
+			this.m_spriteNum.TabIndex = 0;
+			this.m_spriteNum.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+			this.m_spriteNum.Value = new System.Decimal(new int[] {
+						1,
+						0,
+						0,
+						0});
+			this.m_spriteNum.ValueChanged += new System.EventHandler(this.OnSpriteSelected);
 			// 
-			// label1
+			// m_animPong
 			// 
-			this.label1.Location = new System.Drawing.Point(8, 32);
-			this.label1.Name = "label1";
-			this.label1.Size = new System.Drawing.Size(56, 24);
-			this.label1.TabIndex = 1;
-			this.label1.Text = "Sprite:";
-			this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+			this.m_animPong.Location = new System.Drawing.Point(8, 48);
+			this.m_animPong.Name = "m_animPong";
+			this.m_animPong.Size = new System.Drawing.Size(120, 16);
+			this.m_animPong.TabIndex = 4;
+			this.m_animPong.Text = "Ping/Pong";
+			this.m_animPong.CheckedChanged += new System.EventHandler(this.OnAnimPingPong);
+			// 
+			// m_saveAs
+			// 
+			this.m_saveAs.Index = 3;
+			this.m_saveAs.Shortcut = System.Windows.Forms.Shortcut.F12;
+			this.m_saveAs.Text = "Save as...";
+			this.m_saveAs.Click += new System.EventHandler(this.OnSaveAs);
+			// 
+			// m_exportPNG
+			// 
+			this.m_exportPNG.Index = 0;
+			this.m_exportPNG.Text = "Export to PNG";
+			this.m_exportPNG.Click += new System.EventHandler(this.OnExportPNG);
+			// 
+			// m_save
+			// 
+			this.m_save.Enabled = false;
+			this.m_save.Index = 2;
+			this.m_save.Shortcut = System.Windows.Forms.Shortcut.CtrlS;
+			this.m_save.Text = "Save";
+			this.m_save.Click += new System.EventHandler(this.OnSave);
+			// 
+			// m_quit
+			// 
+			this.m_quit.Index = 5;
+			this.m_quit.Shortcut = System.Windows.Forms.Shortcut.CtrlQ;
+			this.m_quit.Text = "Quit";
+			this.m_quit.Click += new System.EventHandler(this.OnQuit);
+			// 
+			// m_animSpeed
+			// 
+			this.m_animSpeed.Location = new System.Drawing.Point(8, 96);
+			this.m_animSpeed.Maximum = new System.Decimal(new int[] {
+						50,
+						0,
+						0,
+						0});
+			this.m_animSpeed.Minimum = new System.Decimal(new int[] {
+						1,
+						0,
+						0,
+						0});
+			this.m_animSpeed.Name = "m_animSpeed";
+			this.m_animSpeed.ReadOnly = true;
+			this.m_animSpeed.Size = new System.Drawing.Size(48, 20);
+			this.m_animSpeed.TabIndex = 1;
+			this.m_animSpeed.Value = new System.Decimal(new int[] {
+						5,
+						0,
+						0,
+						0});
+			this.m_animSpeed.ValueChanged += new System.EventHandler(this.OnAnimSpeed);
+			// 
+			// m_animEnable
+			// 
+			this.m_animEnable.Location = new System.Drawing.Point(8, 24);
+			this.m_animEnable.Name = "m_animEnable";
+			this.m_animEnable.Size = new System.Drawing.Size(120, 16);
+			this.m_animEnable.TabIndex = 0;
+			this.m_animEnable.Text = "Preview Animation";
+			this.m_animEnable.CheckedChanged += new System.EventHandler(this.OnAnimEnable);
+			// 
+			// m_animGroup
+			// 
+			this.m_animGroup.Controls.Add(this.m_animStretch);
+			this.m_animGroup.Controls.Add(this.m_animPong);
+			this.m_animGroup.Controls.Add(this.m_preview);
+			this.m_animGroup.Controls.Add(this.label4);
+			this.m_animGroup.Controls.Add(this.m_animSpeed);
+			this.m_animGroup.Controls.Add(this.m_animEnable);
+			this.m_animGroup.Location = new System.Drawing.Point(424, 208);
+			this.m_animGroup.Name = "m_animGroup";
+			this.m_animGroup.Size = new System.Drawing.Size(288, 128);
+			this.m_animGroup.TabIndex = 2;
+			this.m_animGroup.TabStop = false;
+			this.m_animGroup.Text = "Animation Preview";
+			// 
+			// m_menu
+			// 
+			this.m_menu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+						this.m_fileMenu,
+						this.m_exportMenu,
+						this.m_helpMenu});
+			// 
+			// m_timer
+			// 
+			this.m_timer.Tick += new System.EventHandler(this.OnTimer);
+			// 
+			// label4
+			// 
+			this.label4.Location = new System.Drawing.Point(64, 104);
+			this.label4.Name = "label4";
+			this.label4.Size = new System.Drawing.Size(104, 16);
+			this.label4.TabIndex = 2;
+			this.label4.Text = "/50 secs per frame";
+			// 
+			// m_animStretch
+			// 
+			this.m_animStretch.Location = new System.Drawing.Point(8, 72);
+			this.m_animStretch.Name = "m_animStretch";
+			this.m_animStretch.Size = new System.Drawing.Size(120, 16);
+			this.m_animStretch.TabIndex = 5;
+			this.m_animStretch.Text = "Stretch";
+			this.m_animStretch.CheckedChanged += new System.EventHandler(this.OnAnimStretch);
 			// 
 			// label2
 			// 
-			this.label2.Location = new System.Drawing.Point(8, 72);
+			this.label2.Location = new System.Drawing.Point(8, 96);
 			this.label2.Name = "label2";
 			this.label2.Size = new System.Drawing.Size(56, 24);
 			this.label2.TabIndex = 3;
@@ -200,141 +380,133 @@ namespace BitmapSpriteEd
 			// 
 			// label3
 			// 
-			this.label3.Location = new System.Drawing.Point(8, 112);
+			this.label3.Location = new System.Drawing.Point(8, 160);
 			this.label3.Name = "label3";
 			this.label3.Size = new System.Drawing.Size(56, 24);
 			this.label3.TabIndex = 8;
 			this.label3.Text = "Name:";
 			this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
 			// 
-			// m_animGroup
-			// 
-			this.m_animGroup.Location = new System.Drawing.Point(424, 176);
-			this.m_animGroup.Name = "m_animGroup";
-			this.m_animGroup.Size = new System.Drawing.Size(304, 160);
-			this.m_animGroup.TabIndex = 2;
-			this.m_animGroup.TabStop = false;
-			this.m_animGroup.Text = "Animation Preview";
-			// 
-			// m_exportPNG
+			// m_about
 			// 
-			this.m_exportPNG.Index = 0;
-			this.m_exportPNG.Text = "Export to PNG";
-			this.m_exportPNG.Click += new System.EventHandler(this.OnExportPNG);
+			this.m_about.Index = 0;
+			this.m_about.Text = "About";
+			this.m_about.Click += new System.EventHandler(this.OnAbout);
 			// 
-			// m_quit
+			// m_addFrameAsCopy
 			// 
-			this.m_quit.Index = 5;
-			this.m_quit.Shortcut = System.Windows.Forms.Shortcut.CtrlQ;
-			this.m_quit.Text = "Quit";
-			this.m_quit.Click += new System.EventHandler(this.OnQuit);
+			this.m_addFrameAsCopy.Location = new System.Drawing.Point(64, 128);
+			this.m_addFrameAsCopy.Name = "m_addFrameAsCopy";
+			this.m_addFrameAsCopy.Size = new System.Drawing.Size(128, 16);
+			this.m_addFrameAsCopy.TabIndex = 12;
+			this.m_addFrameAsCopy.Text = "New Frame as Copy";
 			// 
 			// m_exportMenu
 			// 
 			this.m_exportMenu.Index = 1;
 			this.m_exportMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
-						this.m_exportPNG});
+						this.m_exportPNG,
+						this.m_exportSinglePNG});
 			this.m_exportMenu.Text = "Export";
 			// 
-			// m_fileMenu
+			// m_spriteName
 			// 
-			this.m_fileMenu.Index = 0;
-			this.m_fileMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
-						this.m_new,
-						this.m_open,
-						this.m_save,
-						this.m_saveAs,
-						this.m_break1,
-						this.m_quit});
-			this.m_fileMenu.Text = "File";
+			this.m_spriteName.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper;
+			this.m_spriteName.Location = new System.Drawing.Point(64, 160);
+			this.m_spriteName.Name = "m_spriteName";
+			this.m_spriteName.Size = new System.Drawing.Size(208, 20);
+			this.m_spriteName.TabIndex = 9;
+			this.m_spriteName.Text = "";
+			this.m_spriteName.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.OnSpriteNameKey);
+			this.m_spriteName.TextChanged += new System.EventHandler(this.OnSpriteName);
 			// 
-			// m_open
+			// m_removeSprite
 			// 
-			this.m_open.Index = 1;
-			this.m_open.Shortcut = System.Windows.Forms.Shortcut.CtrlO;
-			this.m_open.Text = "Open";
-			this.m_open.Click += new System.EventHandler(this.OnOpen);
+			this.m_removeSprite.Location = new System.Drawing.Point(200, 48);
+			this.m_removeSprite.Name = "m_removeSprite";
+			this.m_removeSprite.Size = new System.Drawing.Size(72, 24);
+			this.m_removeSprite.TabIndex = 5;
+			this.m_removeSprite.Text = "Remove";
+			this.m_removeSprite.Click += new System.EventHandler(this.OnRemoveSprite);
 			// 
-			// m_removeFrame
+			// m_spriteCount
 			// 
-			this.m_removeFrame.Location = new System.Drawing.Point(224, 72);
-			this.m_removeFrame.Name = "m_removeFrame";
-			this.m_removeFrame.Size = new System.Drawing.Size(64, 24);
-			this.m_removeFrame.TabIndex = 7;
-			this.m_removeFrame.Text = "Remove";
-			this.m_removeFrame.Click += new System.EventHandler(this.OnRemoveFrame);
+			this.m_spriteCount.Location = new System.Drawing.Point(136, 40);
+			this.m_spriteCount.Name = "m_spriteCount";
+			this.m_spriteCount.Size = new System.Drawing.Size(56, 16);
+			this.m_spriteCount.TabIndex = 10;
+			this.m_spriteCount.Text = "label5";
 			// 
-			// m_saveAs
+			// m_exportSinglePNG
 			// 
-			this.m_saveAs.Index = 3;
-			this.m_saveAs.Shortcut = System.Windows.Forms.Shortcut.F12;
-			this.m_saveAs.Text = "Save as...";
-			this.m_saveAs.Click += new System.EventHandler(this.OnSaveAs);
+			this.m_exportSinglePNG.Index = 1;
+			this.m_exportSinglePNG.Text = "Export to Single PNG";
+			this.m_exportSinglePNG.Click += new System.EventHandler(this.OnExportSinglePNG);
 			// 
-			// m_spriteName
+			// m_addSprite
 			// 
-			this.m_spriteName.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper;
-			this.m_spriteName.Location = new System.Drawing.Point(64, 112);
-			this.m_spriteName.Name = "m_spriteName";
-			this.m_spriteName.Size = new System.Drawing.Size(224, 21);
-			this.m_spriteName.TabIndex = 9;
-			this.m_spriteName.Text = "";
-			this.m_spriteName.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.OnSpriteNameKey);
-			this.m_spriteName.TextChanged += new System.EventHandler(this.OnSpriteName);
+			this.m_addSprite.Location = new System.Drawing.Point(200, 16);
+			this.m_addSprite.Name = "m_addSprite";
+			this.m_addSprite.Size = new System.Drawing.Size(72, 24);
+			this.m_addSprite.TabIndex = 4;
+			this.m_addSprite.Text = "Add";
+			this.m_addSprite.Click += new System.EventHandler(this.OnAddSprite);
 			// 
-			// m_spriteNum
+			// m_fileMenu
 			// 
-			this.m_spriteNum.Location = new System.Drawing.Point(64, 32);
-			this.m_spriteNum.Name = "m_spriteNum";
-			this.m_spriteNum.ReadOnly = true;
-			this.m_spriteNum.Size = new System.Drawing.Size(64, 21);
-			this.m_spriteNum.TabIndex = 0;
-			this.m_spriteNum.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
-			this.m_spriteNum.ValueChanged += new System.EventHandler(this.OnSpriteSelected);
+			this.m_fileMenu.Index = 0;
+			this.m_fileMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+						this.m_new,
+						this.m_open,
+						this.m_save,
+						this.m_saveAs,
+						this.m_break1,
+						this.m_quit});
+			this.m_fileMenu.Text = "File";
 			// 
-			// m_about
+			// m_break1
 			// 
-			this.m_about.Index = 0;
-			this.m_about.Text = "About";
-			this.m_about.Click += new System.EventHandler(this.OnAbout);
+			this.m_break1.Index = 4;
+			this.m_break1.Text = "-";
 			// 
 			// m_addFrame
 			// 
-			this.m_addFrame.Location = new System.Drawing.Point(144, 72);
+			this.m_addFrame.Location = new System.Drawing.Point(200, 80);
 			this.m_addFrame.Name = "m_addFrame";
-			this.m_addFrame.Size = new System.Drawing.Size(64, 24);
+			this.m_addFrame.Size = new System.Drawing.Size(72, 24);
 			this.m_addFrame.TabIndex = 6;
 			this.m_addFrame.Text = "Add";
 			this.m_addFrame.Click += new System.EventHandler(this.OnAddFrame);
 			// 
-			// m_new
+			// m_removeFrame
 			// 
-			this.m_new.Index = 0;
-			this.m_new.Shortcut = System.Windows.Forms.Shortcut.CtrlN;
-			this.m_new.Text = "New";
-			this.m_new.Click += new System.EventHandler(this.OnNew);
+			this.m_removeFrame.Location = new System.Drawing.Point(200, 112);
+			this.m_removeFrame.Name = "m_removeFrame";
+			this.m_removeFrame.Size = new System.Drawing.Size(72, 24);
+			this.m_removeFrame.TabIndex = 7;
+			this.m_removeFrame.Text = "Remove";
+			this.m_removeFrame.Click += new System.EventHandler(this.OnRemoveFrame);
 			// 
-			// m_frameNum
+			// m_helpMenu
 			// 
-			this.m_frameNum.Location = new System.Drawing.Point(64, 72);
-			this.m_frameNum.Name = "m_frameNum";
-			this.m_frameNum.ReadOnly = true;
-			this.m_frameNum.Size = new System.Drawing.Size(64, 21);
-			this.m_frameNum.TabIndex = 2;
-			this.m_frameNum.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
-			this.m_frameNum.ValueChanged += new System.EventHandler(this.OnFrameSelected);
+			this.m_helpMenu.Index = 2;
+			this.m_helpMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+						this.m_about});
+			this.m_helpMenu.Text = "Help";
 			// 
-			// m_menu
+			// label1
 			// 
-			this.m_menu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
-						this.m_fileMenu,
-						this.m_exportMenu,
-						this.m_helpMenu});
+			this.label1.Location = new System.Drawing.Point(8, 32);
+			this.label1.Name = "label1";
+			this.label1.Size = new System.Drawing.Size(56, 24);
+			this.label1.TabIndex = 1;
+			this.label1.Text = "Sprite:";
+			this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
 			// 
 			// MainForm
 			// 
-			this.AutoScaleBaseSize = new System.Drawing.Size(5, 14);
-			this.ClientSize = new System.Drawing.Size(738, 351);
+			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+			this.ClientSize = new System.Drawing.Size(722, 351);
 			this.Controls.Add(this.m_animGroup);
 			this.Controls.Add(this.m_spriteGroup);
 			this.Controls.Add(this.m_editGroup);
@@ -343,9 +515,12 @@ namespace BitmapSpriteEd
 			this.Menu = this.m_menu;
 			this.Name = "MainForm";
 			this.Text = "Bitmap Sprite Editor";
+			this.Closing += new System.ComponentModel.CancelEventHandler(this.OnClosing);
+			((System.ComponentModel.ISupportInitialize)(this.m_frameNum)).EndInit();
 			this.m_spriteGroup.ResumeLayout(false);
 			((System.ComponentModel.ISupportInitialize)(this.m_spriteNum)).EndInit();
-			((System.ComponentModel.ISupportInitialize)(this.m_frameNum)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.m_animSpeed)).EndInit();
+			this.m_animGroup.ResumeLayout(false);
 			this.ResumeLayout(false);
 		}
 		#endregion
@@ -354,7 +529,7 @@ namespace BitmapSpriteEd
 		{
 			get
 			{
-				int spr=Convert.ToInt32(m_spriteNum.Value);
+				int spr=Convert.ToInt32(m_spriteNum.Value)-1;
 				
 				return m_sprites[spr];
 			}
@@ -364,37 +539,137 @@ namespace BitmapSpriteEd
 		{
 			get
 			{
-				int frame=Convert.ToInt32(m_frameNum.Value);
+				int frame=Convert.ToInt32(m_frameNum.Value)-1;
 				
 				return SelectedSprite[frame];
 			}
 		}
 		
+		private bool EditChanged
+		{
+			get {return m_edit.Frame!=null && m_edit.Frame.Changed;}
+		}
+		
+		private bool ChangesAllowed
+		{
+			get {return (!m_sprites.Changed && !EditChanged) || Util.YesNo("Abandon changes?");}
+		}
+
+		private void UpdateInfo()
+		{
+			m_spriteCount.Text="of "+m_sprites.Count;
+			m_frameCount.Text="of "+SelectedSprite.Count;
+			m_removeSprite.Enabled=(m_sprites.Count>1);
+			m_removeFrame.Enabled=(SelectedSprite.Count>1);
+		}
+		
+		private void OnFrameResize(object sender, GfxEditor.FrameResizeEventArgs e)
+		{
+			foreach (Frame f in SelectedSprite)
+			{
+				if (f!=m_edit.Frame)
+				{
+					f.Resize(e.Width,e.Height);
+				}
+			}
+		}
+		
 		void OnNew(object sender, System.EventArgs e)
 		{
-			m_sprites=new SpriteList();
-			m_sprites.Add(new Sprite());
-			
-			m_spriteNum.Maximum=0;
-			m_frameNum.Maximum=0;
-			m_spriteNum.Value=0;
-			OnSpriteSelected(null,null);
+			if (ChangesAllowed)
+			{
+				m_sprites=new SpriteList();
+				m_sprites.Add(new Sprite());
+				m_sprites.Changed=false;
+				m_save.Enabled=false;
+				
+				m_animIndex=0;
+				m_animIndexInc=1;
+				
+				m_spriteNum.Maximum=1;
+				m_frameNum.Maximum=1;
+				m_spriteNum.Value=1;
+				OnSpriteSelected(null,null);
+			}
 		}
 		
 		void OnOpen(object sender, System.EventArgs e)
 		{
+			if (ChangesAllowed)
+			{
+				OpenFileDialog fsel=new OpenFileDialog();
+				
+				fsel.FileName=m_path;
+				fsel.Filter="Bitmap Sprite Files (*.bms)|*.bms|All files (*.*)|*.*";
+				
+				if (fsel.ShowDialog()==DialogResult.OK)
+				{
+					using(FileStream str=File.Open(fsel.FileName,FileMode.Open))
+					{
+						try
+						{
+							m_sprites=SpriteList.Input(str);
+							str.Close();
+							m_spriteNum.Value=1;
+							m_spriteNum.Maximum=m_sprites.Count;
+							OnSpriteSelected(null,null);
+							m_path=fsel.FileName;
+							m_save.Enabled=true;
+						}
+						catch (Exception ex)
+						{
+							Util.Error("Error opening " + fsel.FileName + ":\n" + ex.Message);
+						}
+					}
+				}
+			}
 		}
 		
 		void OnSave(object sender, System.EventArgs e)
 		{
+			using(FileStream str=File.Open(m_path,FileMode.Create))
+			{
+				try
+				{
+					m_sprites.Output(str);
+					str.Close();
+				}
+				catch (Exception ex)
+				{
+					Util.Error("Error writing " + m_path + ":\n" + ex.Message);
+				}
+			}
 		}
 		
 		void OnSaveAs(object sender, System.EventArgs e)
 		{
+			SaveFileDialog fsel=new SaveFileDialog();
+			
+			fsel.FileName=m_path;
+			fsel.Filter="Bitmap Sprite Files (*.bms)|*.bms|All files (*.*)|*.*";
+			
+			if (fsel.ShowDialog()==DialogResult.OK)
+			{
+				using(FileStream str=File.Open(fsel.FileName,FileMode.Create))
+				{
+					try
+					{
+						m_sprites.Output(str);
+						str.Close();
+						m_path=fsel.FileName;
+						m_save.Enabled=true;
+					}
+					catch (Exception ex)
+					{
+						Util.Error("Error writing " + fsel.FileName + ":\n" + ex.Message);
+					}
+				}
+			}
 		}
 		
 		void OnQuit(object sender, System.EventArgs e)
 		{
+			Close();
 		}
 		
 		void OnAbout(object sender, System.EventArgs e)
@@ -404,26 +679,180 @@ namespace BitmapSpriteEd
 		
 		void OnExportPNG(object sender, System.EventArgs e)
 		{
+			try
+			{
+				m_sprites.Validate();
+			}
+			catch (ApplicationException ex)
+			{
+				Util.Error(ex.Message);
+				return;
+			}
+			
+			FolderBrowserDialog fsel=new FolderBrowserDialog();
+			
+			fsel.ShowNewFolderButton=true;
+			fsel.Description="Select folder to ouput PNG files to";
+			fsel.SelectedPath=m_exportPath;
+			
+			if (fsel.ShowDialog()==DialogResult.OK)
+			{
+				try
+				{
+					foreach(Sprite s in m_sprites)
+					{
+						using (Bitmap bmp=new Bitmap(s[0].Width*s.Count,s[0].Height,PixelFormat.Format32bppArgb))
+						{
+							using (Graphics g=Graphics.FromImage(bmp))
+							{
+								string fname=fsel.SelectedPath +
+												Path.DirectorySeparatorChar +
+													s.Name + ".png";
+
+								int x=0;
+								
+								foreach (Frame f in s)
+								{
+									g.DrawImageUnscaled(f.Bitmap,x,0);
+									x+=f.Width;
+								}
+								
+							
+								bmp.Save(fname,ImageFormat.Png);
+							}
+						}
+					}
+					
+					m_exportPath=fsel.SelectedPath;
+				}
+				catch (Exception ex)
+				{
+					Util.Error("Error writing to " + fsel.SelectedPath + ":\n" + ex.Message);
+				}
+			}
 		}
 
+		void OnExportSinglePNG(object sender, System.EventArgs e)
+		{
+			SaveFileDialog fsel=new SaveFileDialog();
+			
+			fsel.Filter="PNG Files (*.png)|*.png|All files (*.*)|*.*";
+			
+			if (fsel.ShowDialog()==DialogResult.OK)
+			{
+				int height=0;
+				int width=0;
+				
+				foreach (Sprite s in m_sprites)
+				{
+					height+=s[0].Height;
+					width=Math.Max(width,s[0].Width*s.Count);
+				}
+				
+				try
+				{
+					using (Bitmap bmp=new Bitmap(width,height,PixelFormat.Format32bppArgb))
+					{
+						using (Graphics g=Graphics.FromImage(bmp))
+						{
+							int y=0;
+							
+							foreach(Sprite s in m_sprites)
+							{
+								int x=0;
+								
+								foreach (Frame f in s)
+								{
+									g.DrawImageUnscaled(f.Bitmap,x,y);
+									x+=f.Width;
+								}
+								
+								y+=s[0].Height;
+							}
+							
+							bmp.Save(fsel.FileName,ImageFormat.Png);
+						}
+					}
+				}
+				catch (Exception ex)
+				{
+					Util.Error("Error writing " + fsel.FileName + ":\n" + ex.Message);
+				}
+			}
+		}
+		
 		void OnAddSprite(object sender, System.EventArgs e)
 		{
+			m_timer.Enabled=false;
+			
 			m_sprites.Add(new Sprite());
-			m_spriteNum.Maximum=m_sprites.Count-1;
+			m_spriteNum.Maximum=m_sprites.Count;
+			UpdateInfo();
+
+			m_animIndex=0;
+			m_animIndexInc=1;
+			m_timer.Enabled=m_animEnable.Checked;
 		}
 		
 		void OnRemoveSprite(object sender, System.EventArgs e)
 		{
+			m_timer.Enabled=false;
+			
+			m_sprites.Remove(SelectedSprite);
+			
+			if (m_spriteNum.Value==m_sprites.Count+1)
+			{
+				m_spriteNum.Value--;
+			}
+
+			m_spriteNum.Maximum=m_sprites.Count;
+			OnSpriteSelected(null,null);
+			UpdateInfo();
+
+			m_animIndex=0;
+			m_animIndexInc=1;
+			m_timer.Enabled=m_animEnable.Checked;
 		}
 		
 		void OnAddFrame(object sender, System.EventArgs e)
 		{
-			SelectedSprite.Add(new Frame(SelectedFrame));
-			m_frameNum.Maximum=SelectedSprite.Count-1;
+			m_timer.Enabled=false;
+
+			if (m_addFrameAsCopy.Checked)
+			{
+				SelectedSprite.Add(new Frame(SelectedFrame));
+			}
+			else
+			{
+				SelectedSprite.Add(new Frame(SelectedFrame.Width,SelectedFrame.Height));
+			}
+			
+			m_frameNum.Maximum=SelectedSprite.Count;
+			UpdateInfo();
+
+			m_animIndex=0;
+			m_animIndexInc=1;
+			m_timer.Enabled=m_animEnable.Checked;
 		}
 		
 		void OnRemoveFrame(object sender, System.EventArgs e)
 		{
+			m_timer.Enabled=false;
+			
+			SelectedSprite.Remove(SelectedFrame);
+			
+			if (m_frameNum.Value==SelectedSprite.Count+1)
+			{
+				m_frameNum.Value--;
+			}
+
+			m_frameNum.Maximum=SelectedSprite.Count;
+			OnFrameSelected(null,null);
+			UpdateInfo();
+
+			m_animIndex=0;
+			m_animIndexInc=1;
+			m_timer.Enabled=m_animEnable.Checked;
 		}
 
 		void OnSpriteNameKey(object sender, System.Windows.Forms.KeyPressEventArgs e)
@@ -442,9 +871,12 @@ namespace BitmapSpriteEd
 		
 		void OnSpriteSelected(object sender, System.EventArgs e)
 		{
+			m_animIndex=0;
+			m_animIndexInc=1;
 			m_spriteName.Text=SelectedSprite.Name;
-			m_frameNum.Value=0;
-			m_frameNum.Maximum=SelectedSprite.Count-1;
+			m_frameNum.Value=1;
+			m_frameNum.Maximum=SelectedSprite.Count;
+			UpdateInfo();
 			OnFrameSelected(null,null);
 		}
 		
@@ -452,5 +884,79 @@ namespace BitmapSpriteEd
 		{
 			m_edit.Frame=SelectedFrame;
 		}
+
+		void OnTimer(object sender, System.EventArgs e)
+		{
+			if (m_animPong.Checked)
+			{
+				if (m_animIndex<=0)
+				{
+					m_animIndex=0;
+					m_animIndexInc=1;
+				}
+				
+				if (m_animIndex>=SelectedSprite.Count-1)
+				{
+					m_animIndex=SelectedSprite.Count-1;
+					m_animIndexInc=-1;
+				}
+			}
+			else
+			{
+				if (m_animIndex==SelectedSprite.Count)
+				{
+					m_animIndex=0;
+				}
+			}
+
+			m_preview.Image=SelectedSprite[m_animIndex].Bitmap;
+
+			if (m_animPong.Checked)
+			{
+				m_animIndex+=m_animIndexInc;
+			}
+			else
+			{
+				m_animIndex++;
+			}
+		}
+
+		void OnAnimEnable(object sender, System.EventArgs e)
+		{
+			m_animIndex=0;
+			m_animIndexInc=1;
+			m_timer.Enabled=m_animEnable.Checked;
+		}
+
+		void OnAnimPingPong(object sender, System.EventArgs e)
+		{
+			m_animIndex=0;
+			m_animIndexInc=1;
+		}
+
+		void OnAnimSpeed(object sender, System.EventArgs e)
+		{
+			m_timer.Interval=20*Convert.ToInt32(m_animSpeed.Value);
+		}
+		
+		void OnAnimStretch(object sender, System.EventArgs e)
+		{
+			if (m_animStretch.Checked)
+			{
+				m_preview.SizeMode=PictureBoxSizeMode.StretchImage;
+			}
+			else
+			{
+				m_preview.SizeMode=PictureBoxSizeMode.CenterImage;
+			}
+		}
+		
+		void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
+		{
+			if (!ChangesAllowed)
+			{
+				e.Cancel=true;
+			}
+		}
 	}
 }
diff --git a/ManipulationMenu.cs b/ManipulationMenu.cs
new file mode 100644
index 0000000..f71cbd3
--- /dev/null
+++ b/ManipulationMenu.cs
@@ -0,0 +1,104 @@
+// BitmapSpriteEd - Bitmap Sprite Editor
+// Copyright (C) 2005  Ian Cowburn
+// 
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//
+// $Id$
+//
+using System;
+using System.Collections;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace BitmapSpriteEd
+{
+	/// <summary>
+	/// Implements the Manipulation menu
+	/// </summary>
+	public class ManipulationMenu
+	{
+		public enum EMode
+		{
+			eNothing,
+			eMirrorHorizontal,
+			eMirrorVertical,
+			eRotateLeft,
+			eRotateRight,
+			eScrollUp,
+			eScrollDown,
+			eScrollLeft,
+			eScrollRight
+		};
+		
+		public ManipulationMenu()
+		{
+			m_mode=EMode.eNothing;
+			
+			CreateMenus();
+		}
+		
+		public EMode Mode
+		{
+			get {return m_mode;}
+		}
+
+		public void Show(Control c, int x, int y)
+		{
+			m_mode=EMode.eNothing;
+			m_menu.Show(c, new Point(x,y));
+			
+			// Kludge warning!
+			//
+			Application.DoEvents();
+		}
+
+
+		// ------------------------------------------------
+		// PRIVATE
+		//
+		private EMode		m_mode;
+		
+		private Hashtable	m_modeMap;
+
+		private ContextMenu	m_menu;
+		
+		private void CreateItem(string text, EMode mode)
+		{
+			MenuItem i=new MenuItem(text,new EventHandler(OnMenu));
+			m_modeMap[i]=mode;
+			m_menu.MenuItems.Add(i);
+		}
+
+		private void CreateMenus()
+		{
+			m_menu=new ContextMenu();
+			m_modeMap=new Hashtable();
+			
+			CreateItem("Mirror Horizontal",EMode.eMirrorHorizontal);
+			CreateItem("Mirror Vertical",EMode.eMirrorVertical);
+			CreateItem("Rotate Left",EMode.eRotateLeft);
+			CreateItem("Rotate Right",EMode.eRotateRight);
+			CreateItem("Scroll Up",EMode.eScrollUp);
+			CreateItem("Scroll Down",EMode.eScrollDown);
+			CreateItem("Scroll Left",EMode.eScrollLeft);
+			CreateItem("Scroll Right",EMode.eScrollRight);
+		}
+		
+		private void OnMenu(object sender, System.EventArgs e)
+		{
+			m_mode=(EMode)m_modeMap[sender];
+		}
+	}
+}
diff --git a/Sprite.cs b/Sprite.cs
index 47678e9..290f582 100644
--- a/Sprite.cs
+++ b/Sprite.cs
@@ -19,6 +19,7 @@
 //
 using System;
 using System.Drawing;
+using System.Drawing.Imaging;
 using System.IO;
 using System.Collections;
 
@@ -44,6 +45,11 @@ namespace BitmapSpriteEd
 		}
 		
 		public Frame(Frame old)
+		{
+			CopyFrom(old);
+		}
+		
+		public void CopyFrom(Frame old)
 		{
 			m_width=old.m_width;
 			m_height=old.m_height;
@@ -59,7 +65,7 @@ namespace BitmapSpriteEd
 			
 			m_changed=old.m_changed;
 		}
-		
+			
 		public int Width
 		{
 			get {return m_width;}
@@ -256,6 +262,24 @@ namespace BitmapSpriteEd
 			return s;
 		}
 		
+		public Bitmap Bitmap
+		{
+			get
+			{
+				Bitmap bmp=new Bitmap(m_width,m_height,PixelFormat.Format32bppArgb);
+				
+				for(int x=0;x<m_width;x++)
+				{
+					for(int y=0;y<m_height;y++)
+					{
+						bmp.SetPixel(x,y,m_data[x,y]);
+					}
+				}
+				
+				return bmp;
+			}
+		}
+		
 		// ------------------------------------------------
 		// PRIVATE
 		//
@@ -294,7 +318,7 @@ namespace BitmapSpriteEd
 		public Sprite()
 		{
 			m_changed=false;
-			m_name="Untitled";
+			m_name="";
 			m_frames=new ArrayList();
 			m_frames.Add(new Frame(16,16));
 		}
@@ -382,6 +406,7 @@ namespace BitmapSpriteEd
 		{
 			Sprite fr=new Sprite();
 			
+			fr.m_frames.Clear();
 			fr.Name=Util.ReadString(stream);
 			
 			int num=Util.ReadInt(stream);
@@ -483,10 +508,10 @@ namespace BitmapSpriteEd
 			{
 				if (this[i].Name.Length==0)
 				{
-					throw new ApplicationException("Empty sprite name found");
+					throw new ApplicationException("Empty sprite name found (sprite number " + (i+1).ToString() + ")");
 				}
 				
-				for(int j=0;j<num;i++)
+				for(int j=0;j<num;j++)
 				{
 					if (i!=j)
 					{
-- 
cgit v1.2.3