/*********************************************************************************************
 * Copyright 2002 - Volian Enterprises, Inc. All rights reserved.
 * Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
 * ------------------------------------------------------------------------------
 * $Workfile: ctlXMLEdit.cs $     $Revision: 36 $
 * $Author: Jsj $   $Date: 7/06/06 9:32a $
 *
 * $History: ctlXMLEdit.cs $
 * 
 * *****************  Version 36  *****************
 * User: Jsj          Date: 7/06/06    Time: 9:32a
 * Updated in $/LibSource/ctlXMLEditLib
 * needed full path to read ROAPP.INI
 * 
 * *****************  Version 35  *****************
 * User: Jsj          Date: 5/03/05    Time: 11:44a
 * Updated in $/LibSource/ctlXMLEditLib
 * 
 * *****************  Version 34  *****************
 * User: Jsj          Date: 7/02/03    Time: 9:26a
 * Updated in $/LibSource/ctlXMLEditLib
 * made messagebox calls modal by removing the parent window reference
 * 
 * *****************  Version 33  *****************
 * User: Kathy        Date: 6/11/03    Time: 2:01p
 * Updated in $/LibSource/ctlXMLEditLib
 * Bug fix B2003-045 (save date as part of graphic)
 * 
 * *****************  Version 32  *****************
 * User: Kathy        Date: 5/21/03    Time: 12:41p
 * Updated in $/LibSource/ctlXMLEditLib
 * B2003-036: save of group data to ro if both have a common field
 * 
 * *****************  Version 31  *****************
 * User: Kathy        Date: 2/07/03    Time: 11:19a
 * Updated in $/LibSource/ctlXMLEditLib
 * Error on pathname compares if long filename
 * 
 * *****************  Version 30  *****************
 * User: Kathy        Date: 2/03/03    Time: 10:36a
 * Updated in $/LibSource/ctlXMLEditLib
 * UI Improve
 * 
 * *****************  Version 29  *****************
 * User: Kathy        Date: 1/22/03    Time: 12:17p
 * Updated in $/LibSource/ctlXMLEditLib
 * duplicate/save as bug
 * 
 * *****************  Version 28  *****************
 * User: Kathy        Date: 1/15/03    Time: 1:56p
 * Updated in $/LibSource/ctlXMLEditLib
 * sizing of labels & form
 * 
 * *****************  Version 27  *****************
 * User: Kathy        Date: 1/08/03    Time: 10:05a
 * Updated in $/LibSource/ctlXMLEditLib
 * Add view image
 * 
 * *****************  Version 26  *****************
 * User: Jsj          Date: 1/06/03    Time: 11:29a
 * Updated in $/LibSource/ctlXMLEditLib
 * INI file logic
 * 
 * *****************  Version 25  *****************
 * User: Jsj          Date: 1/02/03    Time: 3:47p
 * Updated in $/LibSource/ctlXMLEditLib
 * Added logic to check INI files for default graphics file extension
 * 
 * *****************  Version 24  *****************
 * User: Jsj          Date: 12/17/02   Time: 4:51p
 * Updated in $/LibSource/ctlXMLEditLib
 * fixed date/time for graphic files
 * 
 * *****************  Version 23  *****************
 * User: Kathy        Date: 12/16/02   Time: 12:11p
 * Updated in $/LibSource/ctlXMLEditLib
 * once data is saved, don't flag it as changed
 * 
 * *****************  Version 22  *****************
 * User: Kathy        Date: 12/13/02   Time: 10:05a
 * Updated in $/LibSource/ctlXMLEditLib
 * bugs with combo (& more than one field with data)
 * 
 * *****************  Version 21  *****************
 * User: Jsj          Date: 12/10/02   Time: 3:35p
 * Updated in $/LibSource/ctlXMLEditLib
 * Default Graphic file extension fix
 * 
 * *****************  Version 20  *****************
 * User: Kathy        Date: 12/10/02   Time: 2:24p
 * Updated in $/LibSource/ctlXMLEditLib
 * fieldname special chars
 * 
 * *****************  Version 19  *****************
 * User: Kathy        Date: 12/02/02   Time: 8:28a
 * Updated in $/LibSource/ctlXMLEditLib
 * fieldname replace chars
 * 
 * *****************  Version 18  *****************
 * User: Kathy        Date: 11/26/02   Time: 11:08a
 * Updated in $/LibSource/ctlXMLEditLib
 * fix required bug on combo type & fix improve sizing
 * 
 * *****************  Version 17  *****************
 * User: Kathy        Date: 11/20/02   Time: 11:36a
 * Updated in $/LibSource/ctlXMLEditLib
 * zoom button moved on main form
 * 
 * *****************  Version 16  *****************
 * User: Kathy        Date: 11/19/02   Time: 11:33a
 * Updated in $/LibSource/ctlXMLEditLib
 * zoom tool tip & tab order
 * 
 * *****************  Version 15  *****************
 * User: Kathy        Date: 10/24/02   Time: 11:15a
 * Updated in $/LibSource/ctlXMLEditLib
 * some image file date (still needs fixed)
 * 
 * *****************  Version 14  *****************
 * User: Kathy        Date: 10/15/02   Time: 2:14p
 * Updated in $/LibSource/ctlXMLEditLib
 * required fields bug
 * 
 * *****************  Version 13  *****************
 * User: Kathy        Date: 10/11/02   Time: 11:35a
 * Updated in $/LibSource/ctlXMLEditLib
 * Required fields & restore data
 * 
 * *****************  Version 12  *****************
 * User: Kathy        Date: 10/10/02   Time: 10:43a
 * Updated in $/LibSource/ctlXMLEditLib
 * console.writeline->messagebox
 * 
 * *****************  Version 11  *****************
 * User: Kathy        Date: 10/07/02   Time: 11:26a
 * Updated in $/LibSource/ctlXMLEditLib
 * graphics image file support
 * 
 * *****************  Version 10  *****************
 * User: Kathy        Date: 9/27/02    Time: 1:12p
 * Updated in $/LibSource/ctlXMLEditLib
 * fix digit as first char in fieldname
 * 
 * *****************  Version 9  *****************
 * User: Jsj          Date: 9/26/02    Time: 12:12p
 * Updated in $/LibSource/ctlXMLEditLib
 * removed reference
 * 
 * *****************  Version 8  *****************
 * User: Jsj          Date: 9/26/02    Time: 11:09a
 * Updated in $/LibSource/ctlXMLEditLib
 * added reference to VLNXML
 * 
 * *****************  Version 7  *****************
 * User: Kathy        Date: 9/25/02    Time: 9:54a
 * Updated in $/LibSource/ctlXMLEditLib
 * remove xmlvln
 * 
 * *****************  Version 6  *****************
 * User: Kathy        Date: 9/19/02    Time: 9:59a
 * Updated in $/LibSource/ctlXMLEditLib
 * fix minor bugs
 * 
 * *****************  Version 5  *****************
 * User: Kathy        Date: 9/11/02    Time: 1:13p
 * Updated in $/LibSource/ctlXMLEditLib
 * vlnxml
 * 
 * *****************  Version 4  *****************
 * User: Kathy        Date: 9/10/02    Time: 12:17p
 * Updated in $/LibSource/ctlXMLEditLib
 * modify xpath expression to find field contents
 * 
 * *****************  Version 3  *****************
 * User: Kathy        Date: 9/05/02    Time: 12:41p
 * Updated in $/LibSource/ctlXMLEditLib
 * dev
 * 
 * *****************  Version 2  *****************
 * User: Kathy        Date: 8/30/02    Time: 9:42a
 * Updated in $/LibSource/ctlXMLEditLib
 * dev
 * 
 * *****************  Version 1  *****************
 * User: Jsj          Date: 8/23/02    Time: 3:02p
 * Created in $/LibSource/ctlXMLEditLib
 *********************************************************************************************/

using System;
using System.IO;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Xml;
using System.Xml.Schema;
using System.Text;
using RODBInterface;
using Org.Mentalis.Files;
//using IniFileIO;



namespace ctlXMLEditLib
{
	/// <summary>
	/// This windows control takes an input XML Schema and displays windows controls for the
	/// schema elements.
	/// If XML is also passed in, it uses that for the data.
	/// Methods supported are:
	///    ctlXMLEdit(VlnXmlElement myelem, XmlSchema myschema)
	///			Constructor - VlnXmlElement contains data for edit and contains top
	///						- document node if creating new xml data.
	///						- XmlSchema contains field definitions
	///	   bool SaveData 
	///						- saves data in windows into passed in VlnXmlElement. 
	///						-    returns true if successful, false if failed.
	///	  
	///    
	/// </summary>
	public class ctlXMLEdit : System.Windows.Forms.UserControl
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;
		private Random random = new Random();
		private XmlSchema myXmlSchema;
		private int screenx;
		private int screeny;
		private int tabindx;
		private bool mysavexml;
		private Hashtable myHT;
		private bool dosaveflag;
		private VlnXmlElement editelem;
		private XmlDocument editdoc;
		private TextBox zoomtextbox;
		// the following is used for handling images. Note that if we want to have more
		// than one image defined in an ro, this should be become a list.
		private TextBox GraphicsFiletextbox;
		private TextBox GraphicsWdtextbox;
		private TextBox GraphicsHttextbox;
		private System.Windows.Forms.Button btnFindFile;
		private string GraphicsText;
		private ToolTip zmtooltip;
		private string DefaultGraphicFileExtension;
		int MaxWidth; // largest textbox/groupbox width to size control.
		int himage, wimage;
		int hmin, hmax;
		int wmin, wmax;
		int MAXLT = 60;  // make these defines
		int MAXWT = 84;
		int STDCPI = 12;
		int STDLPI = 6;
		int DPPL = (720/6);
		int DPPC = (720/12);
		int height, width;
		
		// use this struct to define attributes for the text box fields, storing
		// the pattern, radio button association, required field flag, etc.
		struct TextBoxAttrTag
		{

			bool required;		//whether the field is required
			string req_msg;		//message to print if required, but not set
			string pattern;		//pattern for validation
			RadioButton radio;	// if this text box has associated radio button
			bool imagechild;	//whether this field is a subchild of an image
			string imagename;	//if subchild of image, name of image parent (for save)
			string imagedate;   //if this was filename, save the date/time stamp
			public TextBoxAttrTag(bool reqd, string ptn, RadioButton rd, bool img, 
				string imgname, string imgdate) 
			{
				this.req_msg = null;
				this.required = reqd;
				this.pattern = ptn;
				this.radio = rd;
				this.imagechild = img;
				this.imagename = imgname;
				this.imagedate = imgdate;
			}
			public void SetPattern(string pattern) {this.pattern = pattern;}
			public void SetRequired(bool req) {this.required = req;}
			public void SetRequiredMessage(string ireq_msg) {this.req_msg = ireq_msg;}
			public string GetPattern { get {return pattern;}}
			public string GetRequiredMessage { get {return req_msg;}}
			public bool GetRequired { get {return required;}}
			public RadioButton GetRadio { get {return radio;}}
			public bool GetImageChild { get {return imagechild;}}
			public string GetImageName { get {return imagename;}}
			public string GetImageDate { get {return imagedate;}}
			public void SetImageDate(string imgdate) {this.imagedate = imgdate;}
		}

		public ctlXMLEdit(VlnXmlElement myelem, XmlSchema myschema, ArrayList reqfields)
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();
			zmtooltip = new ToolTip();
			myHT = new Hashtable();
			tabindx=0;
			screenx=8;
			screeny=10;
			MaxWidth = 0;
			mysavexml = false;
			dosaveflag = false;
			editelem = myelem;
			editdoc = myelem.OwnerDocument;
			myXmlSchema = myschema;
			GraphicsText = null;
			GraphicsFiletextbox = null;
//			DefaultGraphicFileExtension = ".TIF"; // default graphics file extension
			string ApplicationPath = Application.StartupPath;
			string ROINI = Directory.GetCurrentDirectory()+ "\\ROAPP.INI";

			// Get the default file extension for graphic files
//			DefaultGraphicFileExtension = TheIniFile.GetINIKeyValueStr("ROApp","Extention","",5,"ROAPP.INI");
			// Bug fix: B2006-025
			//  needed to pass the full path of ROAPP.INI
			IniReader in1 = new IniReader(ROINI);
			DefaultGraphicFileExtension = in1.ReadString("ROApp","Extention","");
			if (DefaultGraphicFileExtension.Equals(""))
			{
				string ApplPathUp = ApplicationPath.ToUpper();
				int idx = ApplPathUp.IndexOf("VE-PROMS.NET\\BIN");
				if (idx >= 0)
				{
					string PromsINI = ApplicationPath.Substring(0, idx);
					PromsINI += "VE-PROMS\\VEPROMS.INI";
					IniReader in2 = new IniReader(PromsINI);
					DefaultGraphicFileExtension = in2.ReadString("Graphics", "defaultext", ".TIF");
				}
				else
					DefaultGraphicFileExtension = ".TIF";
			}
//			if (File.Exists(PromsINI))
//				DefaultGraphicFileExtension = TheIniFile.GetINIKeyValueStr("Graphics","defaultext",".TIF",5,PromsINI);
//			if (File.Exists("ROAPP.INI"))
//				DefaultGraphicFileExtension = TheIniFile.GetINIKeyValueStr("ROApp","Extention",".TIF",5,"ROAPP.INI");
			if (!DefaultGraphicFileExtension.StartsWith("."))
				DefaultGraphicFileExtension = "." + DefaultGraphicFileExtension;

			// Put out window fields based on schema fields.
			DisplaySchemaControls(myXmlSchema);

			// Add field data to fields.
			DisplayFieldContents((XmlNode) myelem);

			// Set required fields based on list. (can add message later).
			SetRequiredFields(reqfields);
			dosaveflag=true;
		}

		// set the required fields tag on those fields which are included in the passed
		// in required fields list.
		private void DoSet(TextBox hwnd, string msg)
		{
			if (hwnd == null) return;
			if (hwnd.Tag != null)
			{
				TextBoxAttrTag tag = (TextBoxAttrTag) hwnd.Tag;
				tag.SetRequired(true);
				tag.SetRequiredMessage(msg);
				hwnd.Tag = tag;
			}
		}

		private void SetRequiredFields(ArrayList reqfields)
		{
			Object o;
			TextBox hwnd;
			string field, msg;
			int indx;
			foreach (string strfld in reqfields)
			{
				indx = strfld.IndexOf("\t");   // message is stored after field, tab delim
				field = strfld.Substring(0,indx);
				msg = strfld.Substring(indx,strfld.Length-indx);

				o = null;
				o = myHT[field];
				if (o == null)
				{
					// there may be an a,b,c,d tacked on to represent combo types.
					// try them. if we have a combo type, then set them all as required
					// because the checker will only check the one that is visible.
					o = myHT[field+"a"];
					if (o != null)   // set all combo types required, the checker
					{
						DoSet((TextBox)o,msg);
						DoSet((TextBox)myHT[field+"b"],msg);
						DoSet((TextBox)myHT[field+"c"],msg);
						DoSet((TextBox)myHT[field+"d"],msg);
					}
				}
				else if (o != null)
				{
					hwnd = (TextBox) o;
					if (hwnd.Tag != null)
					{
						TextBoxAttrTag tag = (TextBoxAttrTag) hwnd.Tag;
						tag.SetRequired(true);
						tag.SetRequiredMessage(msg);
						hwnd.Tag = tag;
					}
				}
			}
		}

		// Given a parent XmlNode, walk through the child nodes & add the text for the
		// node to the associated text box.
		private void DisplayFieldContents(XmlNode node)
		{
			Object o;
			TextBox hwnd;
			XmlNode nd;
			// if we have an image, check it for validity, i.e. file exists, etc.??
			foreach (string str in myHT.Keys)
			{
				o = myHT[str];
				hwnd = (TextBox) o;
				nd = node.SelectSingleNode(str);
				// if not found with just the string, search the tree.
				if (nd==null)nd = node.SelectSingleNode("*/"+str);
				if (nd != null)
				{	
					hwnd.Text = nd.InnerText;   // set the field's text from XML

					// check if this window has a button name as part of its tag. If
					// so it's a combo type & the radio button/visibility may need to
					// be reset. If this button is not checked (during setup), then
					// check it. By setting it's Checked property to true, an event
					// is thrown which causes the code to be run which turns off/on
					// visibility of the text boxes.
					if (hwnd.Tag != null)
					{
						TextBoxAttrTag tag = (TextBoxAttrTag) hwnd.Tag;
						RadioButton radio;
						radio = tag.GetRadio;
						
						if (radio != null )
						{
							// Use a tag on the groupbox to know that the radio button
							// was set - the first xml element in the group is the
							// active one.
							GroupBox gp = (GroupBox) radio.Parent;
							if (gp.Tag == null && radio.Checked == false)
							{
								// see if this is the first member of the group in the 
								// xml node.
								string nmgr = str.Substring(0,str.Length-1);
								XmlNode grpnd = (XmlNode) editelem.FirstChild;
								bool first = true;
								while (grpnd != null)
								{
									if (grpnd.Name.Substring(0,grpnd.Name.Length-1) == nmgr)
									{
										if (grpnd.Name == str)
										{
											if (first)
											{
												radio.Checked = true;
												radio.Parent.Tag = true;
											}
											break;
										}
										first = false;
									}
									grpnd = grpnd.NextSibling;
								}
							}
						}
						bool img;
						img = tag.GetImageChild;
						if (img==true && str == "Image_Filename")
						{
							int indx = hwnd.Text.IndexOf(" ");
							if (indx>=0)
							{
								tag.SetImageDate(hwnd.Text.Substring(0,indx));
								hwnd.Tag = tag;
								hwnd.Text = hwnd.Text.Substring(indx+1,hwnd.Text.Length-indx-1);
							}
						}
						if (img==true && str == "Image_Width")
							width = System.Convert.ToInt32(hwnd.Text);
						if (img==true && str == "Image_Height")
							height = System.Convert.ToInt32(hwnd.Text);
					}
				}
			}
			// if we're doing an image file & all data has been set, update the
			// height/width data of the image.
			if (GraphicsFiletextbox != null && GraphicsFiletextbox.Text != "") UpdateHtWd();
		}
		public TextBox GetGraphicsFiletextbox()
		{
			return GraphicsFiletextbox;
		}
		public int GetMaxWidth()
		{
			// if MaxWidth is small, a scroll bar appears below the fields
			// so make this a bit larger, so a scroll bar doesn't appear
			if (MaxWidth<30) return MaxWidth+60;
			return MaxWidth+30;
		}
		public int GetMaxLength()
		{
			return screeny+50;
		}
		public void SetNotSaved()
		{
			mysavexml = true;
		}
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			zmtooltip.RemoveAll();
			if( disposing )
			{
				if( components != null )
					components.Dispose();
			}
			base.Dispose( disposing );			
		}

		// RestoreData restores the data in the text boxes to be that which was originally 
		// sent into the control (ctlXMLEdit)
		public void RestoreData()
		{
			dosaveflag=false;
			mysavexml=false;
			TextBox hwnd;
			// first, clear out all of the text boxes.

			foreach (string str in myHT.Keys)
			{
				object o = myHT[str];
				hwnd = (TextBox) o;
				hwnd.Text = "";
				TextBoxAttrTag tag = (TextBoxAttrTag) hwnd.Tag;
				RadioButton radio;
				radio = tag.GetRadio;		
				if (radio != null )
				{
					GroupBox gp = (GroupBox) radio.Parent;
					gp.Tag = null;
				}
			}
			// Add field data to fields.
			DisplayFieldContents((XmlNode) editelem);
			dosaveflag=true;
		}

		public bool DataChanged()
		{
			if (mysavexml) return true;
			return false;
		}

		// SaveData saves the data in the element which had been sent to the control. Return
		// true if success, false if fail.
		public bool SaveData()
		{

			if (mysavexml) 
			{				
				TextBox hwnd;
				TextBoxAttrTag tag;
				string imgdate;

				//go thru the hash table to get textboxes. Find the ones that have text.
				foreach (string str in myHT.Keys)
				{
					object o = myHT[str];
					hwnd = (TextBox) o;
					imgdate = null;

					// if this is a required field and there is no text, put out an error
					// message and get out of here.
					if (hwnd.Tag != null)
					{
						tag = (TextBoxAttrTag) hwnd.Tag;
						if (tag.GetRequired == true && hwnd.Visible == true && (hwnd.Text == null || hwnd.Text == ""))
						{
							string message = CvtFldToUserFld(str) + " must be entered because it is\nused to define the " + tag.GetRequiredMessage;
							string caption = "Error on Save RO Data";
							MessageBoxButtons buttons = MessageBoxButtons.OK;
							DialogResult result;
							result = MessageBox.Show(message, caption, buttons);
							return (false);
						}
						imgdate = tag.GetImageDate;
						
					}
					
					// find the element in the current element node. 
					// if text exists and the element exists, just reset the innertext. 
					// if text exists and it's a new element, add it.
					// if the element is there and there's no text. delete it.
					XmlNode elmnode = (XmlNode) editelem;
					XmlNode nd = elmnode.SelectSingleNode(str);
					if (nd == null) nd = elmnode.SelectSingleNode("*/"+str);

					// handle, element exists - but text removed first (delete element)
					if ((hwnd.Text == null || hwnd.Text == "") && nd != null)
					{
						XmlNode parent = nd.ParentNode;
						parent.RemoveChild(nd);
					}
					else
					{
						// found the node, just set text and text exists, just modify text.
						if (nd != null)
						{
							if (str == "Image_Filename")
								nd.InnerText = imgdate + " " + hwnd.Text;
							else
								nd.InnerText = hwnd.Text;
						}
							// node not here. Make a new element
						else if (hwnd.Text != null && hwnd.Text != "")
						{	
							// if this is part of an image, then be sure that the
							// parent image node was created and if not, create it.
							bool ischldimag = false;
							if (hwnd.Tag != null)
							{
								tag = (TextBoxAttrTag) hwnd.Tag;
								if (tag.GetImageChild == true) ischldimag = true;
							}
							if (ischldimag)
							{
								tag = (TextBoxAttrTag) hwnd.Tag;   // yikes, compile errors
								string imagnm = tag.GetImageName;
								VlnXmlElement ielm;
								VlnXmlElement newelem;
								nd = elmnode.SelectSingleNode(imagnm);
								if (nd == null) // make this image node.
								{
									newelem = (VlnXmlElement) editdoc.CreateElement(imagnm);
									editelem.AppendChild((XmlNode) newelem);
									ielm = newelem;
								}
								else
									ielm = (VlnXmlElement) nd;
								newelem = (VlnXmlElement) editdoc.CreateElement(str);
								if (str == "Image_Filename")
									newelem.InnerText = imgdate + " " + hwnd.Text;
								else
									newelem.InnerText = hwnd.Text;
								ielm.AppendChild((XmlNode) newelem);
							}
							else
							{
								// just added at the current level
								VlnXmlElement newelem = (VlnXmlElement) editdoc.CreateElement(str);
								newelem.InnerText = hwnd.Text;
								editelem.AppendChild((XmlNode) newelem);
								nd = (XmlNode) newelem;
							}
						}
						// check on order of combo types if this was one. Note that the 'active'
						// type within the combo, i.e. text, variable, table or xyplot, must
						// be the first one in xml tree (before the others) in order to be the 
						// active one as presented to user. This was done since more than one can have data.
						if (hwnd.Tag != null)
						{
							tag = (TextBoxAttrTag) hwnd.Tag;
							RadioButton rb = tag.GetRadio;
							if (rb != null)
							{
								if (rb.Checked == true)
								{
									// this one needs to be before any others (of the same
									// group type) in the xml childlist - just make it 1st.
									XmlNode parent = nd.ParentNode;
									parent.RemoveChild(nd);
									parent.PrependChild(nd);										
								}
							}
						}
					}
				}
				mysavexml=false;   // data has been saved, don't allow it again.
				return(true);
			}
			return (false);
		}

		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.btnFindFile = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// btnFindFile
			// 
			this.btnFindFile.Location = new System.Drawing.Point(608, 8);
			this.btnFindFile.Name = "btnFindFile";
			this.btnFindFile.Size = new System.Drawing.Size(96, 24);
			this.btnFindFile.TabIndex = 1;
			this.btnFindFile.Text = "Find File";
			this.btnFindFile.Visible = false;
			this.btnFindFile.Click += new System.EventHandler(this.btnFindFile_click);
			this.ResumeLayout(false);

			this.Controls.Add(btnFindFile);

		}
		#endregion
	
		// Given a schema, display labels or radio buttons and their associated textboxes
		// Radio button names are derived from removing the type from the element name.
		private void DisplaySchemaControls(XmlSchema myXmlSchema)
		{
			// the first element is the group name, get past this to the data. This group
			// name is a complex type, which is processed below.
			bool first=true;						
			try
			{
				foreach(object item in myXmlSchema.Items)
				{
					if (item is XmlSchemaElement && first) 
					{
						first=false;
					}

					// in the RO schema (and any types derived from it), the fields are
					// defined within the ComplexType. 
					if (item is XmlSchemaComplexType)
						DisplayXmlSchemaComplexType((XmlSchemaComplexType)item);  //complexType
				}
			}
			catch(Exception e)
			{
				MessageBox.Show(e.ToString(),"Error displaying fields from schema");
			}
		}


		//XmlSchemaComplexType
		private void DisplayXmlSchemaComplexType(XmlSchemaComplexType complexType)
		{
			if (complexType.ContentModel == null)
			{
				if (complexType.Particle != null)
					DisplayXmlSchemaParticle(complexType.Particle);
			}
		}

		//XmlSchemaSimpleType processes a simple type schema element which contains a fields
		//  attributes such as patterns, maxLength and whether it is single (type is 
		//  'normalizedString') or a multiline text box(type is 'string'). Also, a radio 
		//  button is passed in if this was called to handle an element within a combo type.
		//  This button is saved for a given text box so that initialization of these combo types can occur.
		private string DisplayXmlSchemaSimpleType(XmlSchemaSimpleType simpleType, TextBox mytextbox, RadioButton radio, 
			bool img, string imgname)
		{
			// set up for text box tag, which stores whether field is required and
			// if a pattern exists for validation.
			string pattern = null;
			string getannot=null;
			if (simpleType.Annotation != null) 
			{
				object item = simpleType.Annotation.Items[0];
				if (item is XmlSchemaDocumentation)
				{
					XmlSchemaDocumentation doc = (XmlSchemaDocumentation) item;
					XmlNode[] node = (XmlNode[]) doc.Markup;
						
					getannot = node[0].InnerText;
					if (getannot == "VLN_FINDFILE") 
					{
						this.btnFindFile.Location = new System.Drawing.Point(mytextbox.Location.X+mytextbox.Width+50,mytextbox.Location.Y-(2*(int)mytextbox.Font.GetHeight()));
						this.btnFindFile.Visible = true;
						GraphicsFiletextbox = mytextbox;
						GraphicsFiletextbox.LostFocus += new System.EventHandler(this.GraphicText_lostfocus);
						getannot = null;
					}
					if (getannot!=null && getannot!="")
					{
						if (getannot.IndexOf("Lines")>=0)
						{
							GraphicsHttextbox = mytextbox;
							mytextbox.LostFocus += new System.EventHandler(this.GraphicsHt_lostfocus);
						}
						if (getannot.IndexOf("Character")>=0)
						{
							GraphicsWdtextbox = mytextbox;
							mytextbox.LostFocus += new System.EventHandler(this.GraphicsWd_lostfocus);
						}
					}
				}
			}
					

			if (simpleType.Content is XmlSchemaSimpleTypeRestriction) 
			{
				// A Schema Type Restriction is used to define single or multi-line boxes.
				XmlSchemaSimpleTypeRestriction myRestrictions = (XmlSchemaSimpleTypeRestriction) simpleType.Content;
				if (myRestrictions.BaseTypeName.Name == "normalizedString") 
					mytextbox.Multiline = false;
				else
				{
					mytextbox.Multiline = true;
					mytextbox.AcceptsReturn = true;
					mytextbox.Height = (int) mytextbox.Font.GetHeight() * 4;
					mytextbox.ScrollBars = ScrollBars.Vertical;
					zmtooltip.SetToolTip(mytextbox, "Press Shift F2 To Zoom");
				}

				// Schema facets were used for maxlength & patterns, process these if found.
				foreach(XmlSchemaFacet facet in myRestrictions.Facets)
				{
					if (facet is XmlSchemaMaxLengthFacet)
					{
						if (mytextbox.Multiline == false)
							mytextbox.MaxLength = System.Convert.ToInt32(facet.Value);
						// if the box is small, make the width a little bigger so maxlength text can fit. 
						int wd = System.Convert.ToInt32(facet.Value);
						if (wd<5) wd++;
						mytextbox.Width = (int) mytextbox.Font.SizeInPoints * wd;
						MaxWidth = (mytextbox.Width>MaxWidth)?mytextbox.Width:MaxWidth;
					}
					else if (facet is XmlSchemaPatternFacet)
					{
						pattern = facet.Value;
					}
				}
			}

			// Now setup a tag for the text box which will store attributes associated with it
			// for seeing if it is a required field, checking a pattern or processing a radio box
			// initialization.
			if (mytextbox.Tag == null)
			{
				TextBoxAttrTag tag = new TextBoxAttrTag(false, pattern, radio, img, (img?imgname:null), null);
				mytextbox.Tag = (object) tag;
			}
			return getannot;
		}

		//XmlSchemaParticle's contain the individual schema elements which represent
		//  fields defined for this given RO group. It may also contain a schema 'choice'
		//  which was used to handle the combo type data type fields.
		private void DisplayXmlSchemaParticle(XmlSchemaParticle particle)
		{
			if (particle is XmlSchemaElement)
				DisplayXmlSchemaElement((XmlSchemaElement)particle);
			else if (particle is XmlSchemaSequence)
			{
				foreach(XmlSchemaParticle particle1 in ((XmlSchemaSequence)particle).Items)
					DisplayXmlSchemaParticle(particle1);
			}
			else if (particle is XmlSchemaChoice)
				DisplayXmlSchemaChoice((XmlSchemaChoice) particle);
			else
				MessageBox.Show(particle.ToString(),"Not Implemented for this type");
		}
		
		// For a combo field, display the radio button & the text field. Select the first 
		// button. If data is also sent in during initialization of this control, i.e. 
		// edit versus new, the selected button will be changed during the XML file
		// data load process.
		// Return value (set as reference params): 'x' & 'y' size of the text field so that 
		//    the caller can determine the max to set the group box x, y size value and know 
		//    how far to move down on the screen.
		private void DisplayXmlSchemaRadioAndTextBox(XmlSchemaElement element, GroupBox gbox, bool first, int x, int y,
			int boxx, ref int retx, ref int rety)
		{
			int ysize;
			RadioButton radio = new RadioButton();
			radio.Location = new System.Drawing.Point(x,20);
			radio.Name = element.Name + element.SchemaTypeName.Name;
			string tmp;
			if (element.SchemaTypeName.Name.Length>1 && char.IsDigit(element.SchemaTypeName.Name,1))
				tmp = element.SchemaTypeName.Name.Substring(1,element.SchemaTypeName.Name.Length-1);
			else
				tmp = element.SchemaTypeName.Name;
			radio.Text = CvtFldToUserFld(tmp);
			//radio.Width = (int) radio.Font.SizeInPoints * radio.Text.Length + 20;  // add 20 for button
			
			radio.TabIndex = 0;
			ysize = (int) radio.Height;

			if (first) radio.Checked = true;
			radio.CheckedChanged += new System.EventHandler(this.radiocheckchg);
			gbox.Controls.Add(radio);

			TextBox tb = new TextBox();
			tb.Location = new Point(boxx+20, y+25);
			if (!first) tb.Visible = false;
			myHT.Add(element.Name,tb);
			// add the textbox to the ctlxmledit control rather than groupbox - the
			// groupbox is just to control the choices, the text box won't display if in
			// the groupbox.
			Controls.Add(tb);
			tb.TextChanged += new System.EventHandler(this.textbox_change);
			tb.GotFocus += new System.EventHandler(this.textbox_zoombtn);
			tb.KeyDown += new KeyEventHandler(MyOnKeyDown);
			gbox.Contains(tb);
			// the following will set attributes on the text boxes such as maxlength, multiline, etc.
			DisplayXmlSchemaSimpleType((XmlSchemaSimpleType)element.SchemaType, tb, radio,false,null);	
			rety = (ysize + 25 + tb.Height);
			retx = tb.Width;
		}

		//XmlSchemaChoice: processes the 'combo data type' which is represented by a
		// a schema choice element. This is handled by a group box and using radio 
		// button/textbox pairs to represent each element within the choice. 
		private void DisplayXmlSchemaChoice(XmlSchemaChoice choice)
		{
			bool first = true;
			int screenposx, screenposy;
			int maxyfortext=0,maxxfortext=0;
			GroupBox groupbox = new GroupBox();
			groupbox.SuspendLayout();
			groupbox.Location = new System.Drawing.Point(screenx,screeny);
			XmlSchemaElement elem = (XmlSchemaElement) choice.Items[0];
			groupbox.Name = elem.Name;
			groupbox.TabStop = false;

			// remove the last character of the name for the title of the group box.
			string tstr = CvtFldToUserFld(elem.Name);
			groupbox.Text = tstr.Remove((tstr.Length)-1,1);
			screenposx = screenx+20;
			screenposy = screeny+20;

			foreach (object o in choice.Items)
			{
				// put out a radio button/text box for each item in the choice.
				int xmax=0, ymax=0;
				DisplayXmlSchemaRadioAndTextBox((XmlSchemaElement) o,groupbox,first,screenposx,screenposy,screenx,ref xmax,ref ymax);
				first = false;
				maxyfortext = ymax>maxyfortext?ymax:maxyfortext;
				maxxfortext = xmax>maxxfortext?xmax:maxxfortext;
				screenposx = screenposx + 160;				
			}

			// get the widths of all children of this group box & use this to set the size 
			// of the groupbox.
			int gritms = groupbox.Controls.Count;
			screeny=screeny+maxyfortext+10;
			MaxWidth = (maxxfortext+40>MaxWidth)?maxxfortext+40:MaxWidth;
			groupbox.Size = new System.Drawing.Size(maxxfortext+40, maxyfortext+10);
			Controls.Add(groupbox);
		}

		private void DisplayXmlSchemaElement(XmlSchemaElement element)
		{
			// always add a label.
			Label mylabel;
			int sscreeny;
			mylabel =  new System.Windows.Forms.Label();
			mylabel.Location = new Point(screenx, screeny);
			mylabel.Name = element.Name;
			mylabel.Text = CvtFldToUserFld(element.Name);
			mylabel.AutoSize = true;
			Controls.Add(mylabel);
			// add 3 onto screeny so that textbox is slightly below label.
			screeny = screeny+mylabel.Height+3;
			sscreeny = screeny;   // save 'y' location in case of annotation.
			if (element.SchemaType != null && element.SchemaType is XmlSchemaComplexType)
			{
				GraphicsText = element.Name;
				DisplayXmlSchemaComplexType((XmlSchemaComplexType)element.SchemaType);
				screeny+=30;
			}
			else
			{
				TextBox mytextbox;
				mytextbox = new TextBox();
				mytextbox.Location = new Point(screenx, screeny);
				myHT.Add(element.Name,mytextbox);
				tabindx++;
				Controls.Add(mytextbox);
				screeny+=mytextbox.Height;
				mytextbox.TextChanged += new System.EventHandler(this.textbox_change);
				mytextbox.Validating += new System.ComponentModel.CancelEventHandler(this.textbox_Validating);
				mytextbox.GotFocus += new System.EventHandler(this.textbox_zoombtn);
				mytextbox.KeyDown += new KeyEventHandler(MyOnKeyDown);

				string labelAnnot;
				bool imgchld = false;
				if (element.Name == "Image_Filename" || element.Name == "Image_Height" || element.Name == "Image_Width") imgchld = true;
				// Pass the textbox in to set attributes such as maxlength, multiline and pattern
				labelAnnot = DisplayXmlSchemaSimpleType((XmlSchemaSimpleType)element.SchemaType,mytextbox, null,imgchld,GraphicsText);
				if (labelAnnot != null)
				{
					Label annot;
					annot =  new System.Windows.Forms.Label();
					annot.Location = new Point(screenx+mytextbox.Width+10, sscreeny);
					annot.Name = "annot" + screeny.ToString();
					annot.Text = labelAnnot;
					annot.AutoSize = true;
					Controls.Add(annot);
				}
				screeny+=mytextbox.Height;
			}
		}

		// the following is needed to load the control.
		private void ctlXMLEdit_Load(object sender, System.EventArgs e)
		{
		
		}
		
		// when data in a text box has changed, flag it (except for when this
		// happens during loading of original data). This flag will be used
		// later to know whether to save data.
		private void textbox_change(object sender, System.EventArgs e)
		{
			if(dosaveflag)mysavexml = true;
		}

		// radiocheckchg - called when a radio button is selected. This will set
		// visibility for associated text box. 
		private void radiocheckchg(object sender, System.EventArgs e)
		{
			RadioButton btnsel = (RadioButton) sender;
			TextBox assocbox;
			string btntext, str;

			if(dosaveflag)mysavexml = true;
			btntext = CvtUserFldToFld(btnsel.Text);
			
			// now get the actual textbox and set visibility depending
			// on whether the box is checked, i.e. turned on(if checked, it should
			// be set to visible)
		
			str = btnsel.Name.Replace(btntext,"");
			object o = myHT[str];
			if (o == null) return;
			assocbox = (TextBox) o;
			// make the text box visible if checked, otherwise, invisible
			assocbox.Visible = btnsel.Checked;
		}

		// these two methods convert user input field names from/to xml tags. (xml tags
		// cannot begin with digit, have spaces or other special chars.
		private string CvtUserFldToFld(string fldname)
		{
			if (fldname.Length < 2)
				return fldname;
			// a digit cannot start an xml fieldname, prepend a "__" to it.
			string tmp0;
			if (char.IsDigit(fldname,0))
				tmp0 = "__" + fldname;
			else
				tmp0 = fldname;
			// an xml fieldname cannot have a space, change it to a "__"
			string tmpstr = tmp0.Replace(" ","__");
			int len = tmpstr.Length;
			int cnt = 0;

			// this is also our sequence that tells us the follow 3 digits is the ascii number (base 10)
			// of the character we replaced.
			string OKpunch = "-._"; 

			string outstr = "";
			int decval;

			while (cnt < len)
			{
				char tmpchr = tmpstr[cnt];
				if(!char.IsLetterOrDigit(tmpchr)&& (OKpunch.IndexOf(tmpchr) == -1) )
				{
					decval = tmpchr;
					outstr += OKpunch + decval.ToString("D3");
				}
				else
				{
					outstr += tmpchr.ToString();
				}
				cnt++;
			}
			return outstr;
		}

		private string CvtFldToUserFld(string fldname)
		{
			string tmpstr0;
			if (fldname.Length < 2) return fldname;
			// an xml element name cannot begin with a digit. we had prepended a "__"
			if (fldname.Substring(0,2) == "__" && char.IsDigit(fldname,2))
				tmpstr0 = fldname.Substring(2,fldname.Length-2);
			else
				tmpstr0 = fldname;
			// an xml element name cannot have a space, we converted to a "__"
			string tmpstr = tmpstr0.Replace("__"," ");
			int len = tmpstr.Length;
			int cur = 0;

			// this is also our sequence that tells us the follow 3 digits is the ascii number (base 10)
			// of the character we replaced.
			string OKpunch = "-._"; 

			string outstr = "";
			int decval, indx;
			if (tmpstr.Length <6)
				indx = -1;
			else
				indx=tmpstr.IndexOf(OKpunch,cur);
			string asc_spchar;
			while (indx>=0)
			{
				outstr += tmpstr.Substring(cur,indx-cur);
				asc_spchar = tmpstr.Substring(indx+3,3);
				decval = System.Convert.ToInt16(asc_spchar,10);
				outstr += System.Convert.ToChar(decval).ToString();
				cur = indx+6;
				if (cur+6 > len)
					indx = -1;
				else
					indx = tmpstr.IndexOf(OKpunch,cur);
			}
			if (cur<len) outstr += tmpstr.Substring(cur,len-cur);	

			return outstr;
		}

		// The following can be used to validate the text, i.e. check the text against
		// the pattern. this needs written yet (5/16/02)
		private void MyValidatingCode(TextBox tb)
		{
			//get the text box's tag which contains a flag for whether this is required &
			//if it has a pattern. If it has a pattern, validate the field against the pattern.
			TextBoxAttrTag tag;
			tag = (TextBoxAttrTag) tb.Tag;
			string pattern = tag.GetPattern;
			if (pattern != null) 
			{
				//see if text in box matches pattern
				// if not throw exception.
			}

			//USE THE FOLLOWING WHEN CHECKING FOR REQUIRED FIELDS
			
			// Confirm there is text in the control.
			//if (textBox1.Text.Length == 0)
			//{
			//		throw new Exception("Email address is a required field");
			//		}
			// Confirm that there is a "." and an "@" in the e-mail address.
			//		else if(textBox1.Text.IndexOf(".") == -1 || textBox1.Text.IndexOf("@") == -1)
			//		{
			//			throw new Exception("E-mail address must be valid e-mail address format." +
			//				"\nFor example 'someone@microsoft.com'");
			//		}
		}

		// save which box we're on, for zoom processing.
		private void textbox_zoombtn(object sender, System.EventArgs e)
		{
			TextBox textbox = (TextBox) sender;
			if (textbox.Multiline == true || textbox == GraphicsFiletextbox) 
				zoomtextbox = textbox;
			else
				zoomtextbox = null;
		}

		private void textbox_Validating(object sender, System.ComponentModel.CancelEventArgs e)
		{ 
			try
			{
				MyValidatingCode((TextBox) sender);
			}

			catch(Exception ex)
			{
				// Cancel the event and select the text to be corrected by the user.
				e.Cancel = true;
				MessageBox.Show(ex.ToString(), "Error in validation");
				//textBox1.Select(0, textBox1.Text.Length);

				// Set the ErrorProvider error with the text to display. 
				//this.errorProvider1.SetError(textBox1, ex.Message);
			}
		}
		
		private void MyOnKeyDown(object objSender, KeyEventArgs kea)
		{
			if (((kea.Modifiers&Keys.Shift)==Keys.Shift) && kea.KeyCode == Keys.F2)
			{
				if (zoomtextbox == null)
				{
					MessageBox.Show("Must have cursor in text box which should be zoomed.");
					return;
				}
				btnZoom_click(null, null);
			}
		}
		
		public void btnZoom_click(object sender, System.EventArgs e)
		{
			//TextBox tb = (TextBox) sender;
			TextBoxAttrTag tag;
			bool doimage = false;
			if (zoomtextbox.Tag != null)
			{
				tag = (TextBoxAttrTag) zoomtextbox.Tag;
				if (tag.GetImageName == "Image" && zoomtextbox.Text != null && zoomtextbox.Text !="") doimage = true;
			}
			if (doimage)
			{
				string GraphicsFileName = zoomtextbox.Text;
				if (GraphicsFileName.IndexOf('.') == -1)
					GraphicsFileName += DefaultGraphicFileExtension; // default graphics file extension
				FileInfo fi = new FileInfo(GraphicsFileName);
				if (fi.Exists == false) 
				{
					MessageBox.Show("Cannot view a missing graphics file.","Error");
					return;
				}
				ImageDialog dlg = new ImageDialog(GraphicsFileName);
				dlg.ShowDialog();
			}
			else
			{
				ZoomDialog dlg = new ZoomDialog(zoomtextbox.Text);
				dlg.ShowDialog();
				// Determine the state of the DialogResult property for the form
				if (dlg.DialogResult == DialogResult.OK)
				{
					// Create an instance of the ZoomText object to store the
					// dialog data
					string zt = dlg.ZoomText;
					// Save the text in the text box.
					zoomtextbox.Text = (zt);
				}
			}

		}

		// The series of graphic file support were lifted from the old RO editor.
		// They check for file existance, check date/time stamps before moving the
		// file local & keep width/height of file proportional.
		private void GraphicText_lostfocus(object sender, System.EventArgs e)
		{
			TextBox fnamebox = (TextBox) sender;
			if (fnamebox.Text != "" && fnamebox.Modified == true)
			{
				FileInfo ifi = new FileInfo(fnamebox.Text);
				if (ifi.Exists == false) 
				{
					MessageBoxButtons buttons = MessageBoxButtons.OK;
					MessageBox.Show( "File does not exist.", 
						"File Input Error", buttons);
					return;
				}
				bool ok = ValidGraphicsFile(fnamebox.Text);
				if (ok != true)	
				{
					if (fnamebox.Text != "")fnamebox.Text.Replace(fnamebox.Text,"");
					if (GraphicsWdtextbox.Text != "")GraphicsWdtextbox.Text = "";
					if (GraphicsHttextbox.Text!= "")GraphicsHttextbox.Text = "";
				}
				else
				{
					GraphicsWdtextbox.Enabled = true;
					GraphicsHttextbox.Enabled = true;
					UpdateHtWd();
				}
			}
			if (fnamebox.Text == null || fnamebox.Text == "")
			{
				GraphicsWdtextbox.Enabled = false;
				GraphicsHttextbox.Enabled = false;
			}
		}

		string CalculatePromsDate(DateTime imgdate)
		{
			/* 
			 * do some conversion so that proms will be able to use this
			 * date/time. Proms had it in seconds since 00:00:00 1/1/1970.
			 * .NET has it in ticks since 00:00:00 1/1/1
			 */ 
			DateTime promsdt = new DateTime(1970,1,1,0,0,0); // Jan 1, 1970
			// Convert the promsdt to UTC (GMT)
			DateTime promsdtU = promsdt.ToUniversalTime();
			long promsdtU_num = promsdtU.Ticks / 10000000;

			// Convert the image file datetime to UTC
			DateTime imgdateU = imgdate.ToUniversalTime();
			long imgdateu_num = imgdateU.Ticks / 10000000;

			/**
			 * Get the time adjustment for the current Time Zone with respect
			 * to the coordinated universal time (UTC) - a.k.a. Greenwich mean time (GMT).
			 * The time gotten for the Jan 1, 1970 is in UTC time, the imgdate time is
			 * in EST.
			 * 
			 * Get the offset time between this time zone and UTC (GMT) time.
			 * Convert the offset to seconds.
			 * Subtract the offset from the UTC time gotten for Jan 1, 1970
			 */
			ThisTimeZone TZ = new ThisTimeZone();
			TimeSpan TimeZoneSpan = TZ.GetUtcOffset(promsdt); // Time Zone offset from UTC
			long TimeZoneAdj = Math.Abs(TimeZoneSpan.Ticks / 10000000); // convert to seconds

			/*
			 * The file date/time and the Jan 1, 1970 adjustment date are in UTC.
			 * Subtract the "Jan 1, 1970" date/time from the file date/time
			 * the add the Time Zone offset to place the date/time value into
			 * local time.
			 */
			long lsec = (imgdateu_num - promsdtU_num) + TimeZoneAdj;
			string imgdt = lsec.ToString();
			return imgdt;
		}
		/// Import the GetShortPathName function from the win32 kernel dll. This
		/// is not supported in .net/C#	
		[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
		public static extern void GetShortPathName(
			[MarshalAs(UnmanagedType.LPTStr)] string lpszLongPath,
			[MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszShortPath,
			[MarshalAs(UnmanagedType.U4)] int cchBuffer);

		private bool ValidGraphicsFile(string GraphicFileName)
		{
			string iname = GraphicFileName;
			if (iname == null || iname == "") return false;
			GraphicsWdtextbox.Enabled = true;
			GraphicsHttextbox.Enabled = true;
			if (iname.IndexOf('.') == -1)
				iname += DefaultGraphicFileExtension; // default graphics file extension
			FileInfo ifi = new FileInfo(iname);  // input file & info
			string ext = ifi.Extension;		 // returns '.bmp' etc
			if (ext == null)
			{
				MessageBox.Show( "Missing file extension.","Error");
				return false;
			}	
			else 
			{
				string Uext = ext.Substring(1,3).ToUpper();
				if (Uext!="BMP"&&Uext!="EMF"&&Uext!="GIF"&&Uext!="ICO"&&Uext!="JPG"&&Uext!="PNG"&&Uext!="TIF"&&Uext!="WMF")
				{
					MessageBoxButtons buttons = MessageBoxButtons.OK;
					//DialogResult result;
					MessageBox.Show( "Not a supported graphics file type.", 
						"Unsupported extension.", buttons);
					return false;
				}

				// Get the path and filename.  ptr points to just the filename
				int slindx;
				string lname;
				slindx = iname.LastIndexOf("\\");
				if (slindx >0)
					lname = iname.Substring(slindx+1,iname.Length-slindx-1);
				else
					lname = iname;
				// now check to see if this is a local file - to do this, check
				// to see if either has a "~" which may signify a short filename.
				// If so, compare the short file names (Note that comparing long
				// filenames didn't work, i.e. the kernel routine did not return
				// a long filename if a short one was sent in).

				// open an existing file, or create a new one
				
				FileInfo lfi = new FileInfo(lname);  // local file & info
				
				if (lfi.Exists == false)    // !exist, copy it & move on
				{
					// Copy the file to the local directory
					ifi.CopyTo(lname);
					// update fields on window....
					GraphicsFiletextbox.Text = lfi.Name;
					TextBoxAttrTag tag = (TextBoxAttrTag) GraphicsFiletextbox.Tag;
					tag.SetImageDate(CalculatePromsDate(ifi.LastWriteTime));
					GraphicsFiletextbox.Tag = tag;
					UpdateHtWd();
					return true;
				}
				else  // A local file exists by the same name
				{ 
					if (ifi.Exists == false)
					{
						MessageBox.Show("Input file doesn't exist.","Error");
						return false;
					}
					else
					{
						// first just check if these are really the same, just the
						// user put a path in.
						int same = 0;
						if (ifi.DirectoryName.IndexOf("~")>=0 || lfi.DirectoryName.IndexOf("~")>=0)
						{
						
							StringBuilder shortlname = new StringBuilder(257);
							StringBuilder shortiname = new StringBuilder(257);
							GetShortPathName(ifi.DirectoryName,shortiname,257);
							GetShortPathName(lfi.DirectoryName,shortlname,257);
							same = String.Compare(shortlname.ToString(),shortlname.ToString());
						}
						if (same == 0)
						{
							TextBoxAttrTag tag = (TextBoxAttrTag) GraphicsFiletextbox.Tag;
							tag.SetImageDate(CalculatePromsDate(lfi.LastWriteTime));
							GraphicsFiletextbox.Tag = tag;
							return true;
						}
						else
						{
							// Is the file the same - size, date, time
							// old code checked for both findfirst failures??
							string msg=null;
							if (lfi.LastWriteTime > ifi.LastWriteTime)
								msg = "A newer copy of t";
							else if (lfi.LastWriteTime < ifi.LastWriteTime)
								msg = "An older copy of t";
							else if (lfi.Length != ifi.Length)
								msg = "A different copy of t";
							msg = msg + "he selected file\nexists in the RO directory\n";
							msg = msg + "Do you want to replace it\n";
							msg = msg + "with the selected file?";
							MessageBoxButtons buttons = MessageBoxButtons.YesNoCancel;
							DialogResult result;
							result = MessageBox.Show( msg, "Graphics File Copy", buttons);
							if (result == DialogResult.Yes)
							{
								lfi.Delete();
								ifi.CopyTo(lname,true);
								// update dialog data & ht/wd
								GraphicsFiletextbox.Text = lfi.Name;
								TextBoxAttrTag tag = (TextBoxAttrTag) GraphicsFiletextbox.Tag;
								tag.SetImageDate(CalculatePromsDate(lfi.LastWriteTime));
								GraphicsFiletextbox.Tag = tag;
								UpdateHtWd();
								return true;
							}
							else if (result != DialogResult.No)   // not yes or no. Cancel out.
								return false;
						}
					}
				}
			}
			return false;
		}
		
		// if changed height, calculate associated width
		private void GraphicsHt_lostfocus(object sender, System.EventArgs e)
		{
			TextBox ht = (TextBox) sender;
			if (ht.Modified == true)
			{
				try
				{
					int newht= System.Convert.ToInt32(ht.Text);
					setHtWdBasedUponHeight(newht);
				}
				catch (Exception ee)
				{
					MessageBox.Show("Invalid Height Input",ee.ToString());
				}
			}
		}
		// if changed width, calculate associated height
		private void GraphicsWd_lostfocus(object sender, System.EventArgs e)
		{
			TextBox wd = (TextBox) sender;
			if (wd.Modified == true)
			{
				try
				{
					int newwd= System.Convert.ToInt32(wd.Text);
					setHtWdBasedUponWidth(newwd);
				}
				catch (Exception ee)
				{
					MessageBox.Show("Invalid Width Input", ee.ToString());
				}
			}
		}					

		private void setHtWdBasedUponHeight(int nuval)
		{
			int w,h;
			if(himage!=0)
			{
				if(nuval==0)nuval=(himage+DPPL-1)/DPPL;
				if(nuval > hmax)nuval=hmax;
				else if(nuval < hmin)nuval=hmin;
				h=nuval;
				// The <<1, +1, and >>1 efectively round the result
				// by multiplying by 2 performing the division adding
				// 1 and dividing by 2
				w=(((h*STDCPI*wimage)<<1)/(himage*STDLPI)+1)>>1;
			} 
			else 
			{
				w=h=0;
			}
			GraphicsWdtextbox.Text = w.ToString();
			GraphicsHttextbox.Text = h.ToString();
		}

		private void setHtWdBasedUponWidth(int nuval)
		{
			int w,h;
			if(himage!=0)
			{
				if(nuval==0)nuval=(wimage+DPPC-1)/DPPC;
				if(nuval > wmax)nuval=wmax;
				else if(nuval < wmin)nuval=wmin;
				w=nuval;
				//
				// The <<1, +1, and >>1 efectively round the result
				// by multiplying by 2 performing the division adding
				// 1 and dividing by 2
				h=(((w*STDLPI*himage)<<1)/(wimage*STDCPI)+1)>>1;
			} 
			else 
			{
				w=h=0;
			}
			GraphicsWdtextbox.Text = w.ToString();
			GraphicsHttextbox.Text = h.ToString();
		}

		private void UpdateHtWd()
		{
			// copy the file local and also get it's width/height by reading the file.
			Bitmap image;

			try 
			{
				string dir = Directory.GetCurrentDirectory();
				string GraphicsFileName = GraphicsFiletextbox.Text;
//				FileInfo fi = new FileInfo(GraphicsFiletextbox.Text);
				if (GraphicsFileName.IndexOf('.') == -1)
					GraphicsFileName += DefaultGraphicFileExtension; // default graphics file extension
				FileInfo fi = new FileInfo(GraphicsFileName);
				if (fi.Exists == false) 
				{
					MessageBox.Show("Graphics File is missing","Error");
					wimage=himage=height=width=0;
					return;
				}
				
				image = new Bitmap(GraphicsFileName);
				himage = image.Height;
				wimage = image.Width;
				hmax=MAXLT; // 60 Lines
				int hmxw=STDLPI*MAXWT*himage/(wimage*STDCPI);
				if(hmxw < hmax)
				{// Size is limited to the width of the paper
					hmax=hmxw;
					wmax=MAXWT;
				} 
				else 
				{
					wmax=STDCPI*hmax*wimage/(himage*STDLPI);
				}
				hmin=1;
				int hmnw=STDLPI*6*himage/(wimage*STDCPI);
				if(hmnw > hmin)
				{// Size is limited by the width of the graphic
					hmin=hmnw;
					wmin=6;
				} 
				else 
				{
					wmin=STDCPI*1*wimage/(himage*STDLPI);
				}
				setHtWdBasedUponHeight(height);
			}
			catch (Exception exx)
			{
				MessageBox.Show(exx.Message.ToString(),"error on processing of graphics file");
			}
		}

		private void btnFindFile_click(object sender, System.EventArgs e)
		{
			bool done = false;
			while (done == false)
			{
				OpenFileDialog openFileDialog1 = new OpenFileDialog();
				openFileDialog1.InitialDirectory = Directory.GetCurrentDirectory();
				openFileDialog1.Filter = 
					"Bitmap files (*.bmp)|*.bmp|Enhanced Windows metafiles (*.emf)|*.emf|Graphics Interchange Format (*.gif)|*.gif|Icons (*.ico)|*.ico|JPEG (*.jpg)|*.jpg|Portable Network Graphics (*.png)|*.png|TIFF (*.tif)|*.tif|Windows Metafile (*.wmf)|*.wmf" ;
				openFileDialog1.FilterIndex = 7 ;
				openFileDialog1.RestoreDirectory = true ;
				openFileDialog1.CheckFileExists = true;
//				try
//				{
					if(openFileDialog1.ShowDialog() != DialogResult.OK)
						done = true;
					else
					{
						string iname = openFileDialog1.FileName;
						done = ValidGraphicsFile(iname);
						if (done == true)
						{
							FileInfo fi = new FileInfo(iname);
							GraphicsFiletextbox.Text = fi.Name;
							UpdateHtWd();
						}
					}
//				}
//				catch (Exception j)
//				{
//					MessageBox.Show(j.Message,"debug");
//				}
			}

		}
	}			

	/*
	 * TimeZone is an Abstract Class.  You need to inherit the TimeZone Class
	 * and overload a couple of it's functions in order to use it.
	 * - called in CalculatePromsDate() above.
	 */ 
		public class ThisTimeZone : TimeZone
	{
		private TimeZone curTZ;
		public TimeSpan SpanTZ;

		public ThisTimeZone()
		{
			curTZ = CurrentTimeZone;  // local timezone
		}

		// get the UTC (GMT) value for the given date/time
		public override TimeSpan GetUtcOffset(DateTime ForThisDate)
		{
			SpanTZ = curTZ.GetUtcOffset(ForThisDate); 
			return SpanTZ;
		}

		// Name of the local Daylight savings time zone
		public override string DaylightName
		{
			get
			{
				return curTZ.DaylightName;
			}
		}

		// Name of the local standard time zone
		public override string StandardName
		{
			get
			{
				return curTZ.StandardName;
			}
		}

		// Get the start and end dates for daylight savings
		public override System.Globalization.DaylightTime GetDaylightChanges(int year)
		{
			return curTZ.GetDaylightChanges(year);
		}
	}
}

