/*********************************************************************************************
 * Copyright 2002 - Volian Enterprises, Inc. All rights reserved.
 * Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
 * ------------------------------------------------------------------------------
 * $Workfile: ROEditor.cs $     $Revision: 54 $
 * $Author: Kathy $   $Date: 7/20/04 2:15p $
 *
 * $History: ROEditor.cs $
 * 
 * *****************  Version 54  *****************
 * User: Kathy        Date: 7/20/04    Time: 2:15p
 * Updated in $/EXE/RefObj/ROEditor
 * B2004-021 improve duplicate error message
 * 
 * *****************  Version 53  *****************
 * User: Kathy        Date: 7/15/04    Time: 11:11a
 * Updated in $/EXE/RefObj/ROEditor
 * Fix B2004-017
 * 
 * *****************  Version 52  *****************
 * User: Jsj          Date: 1/21/04    Time: 12:11p
 * Updated in $/EXE/RefObj/ROEditor
 * calls new function to get currently selected field type for multi type
 * field
 * 
 * *****************  Version 51  *****************
 * User: Jsj          Date: 1/07/04    Time: 2:19p
 * Updated in $/EXE/RefObj/ROEditor
 * allow use of SQL Server
 * 
 * *****************  Version 50  *****************
 * User: Kathy        Date: 10/15/03   Time: 10:30a
 * Updated in $/EXE/RefObj/ROEditor
 * found/fixed as part of B2003-060 - will go thru QA process for that
 * bug's fix
 * 
 * *****************  Version 49  *****************
 * User: Jsj          Date: 7/02/03    Time: 9:25a
 * Updated in $/EXE/RefObj/ROEditor
 * made messagebox calls modal by removing the parent window reference
 * 
 * *****************  Version 48  *****************
 * User: Kathy        Date: 5/30/03    Time: 12:48p
 * Updated in $/EXE/RefObj/ROEditor
 * B2003-044: sync up xml with UI tree view
 * 
 * *****************  Version 47  *****************
 * User: Kathy        Date: 5/21/03    Time: 12:52p
 * Updated in $/EXE/RefObj/ROEditor
 * B2003-034: if only one field for ro, wasn't always processing it.
 * 
 * *****************  Version 46  *****************
 * User: Kathy        Date: 5/07/03    Time: 1:59p
 * Updated in $/EXE/RefObj/ROEditor
 * B2003-033 fixed.
 * 
 * *****************  Version 45  *****************
 * User: Jsj          Date: 4/14/03    Time: 3:03p
 * Updated in $/EXE/RefObj/ROEditor
 * changes due to RO FST file creation speed up
 * 
 * *****************  Version 44  *****************
 * User: Kathy        Date: 3/26/03    Time: 2:20p
 * Updated in $/EXE/RefObj/ROEditor
 * speed up initial load
 * 
 * *****************  Version 43  *****************
 * User: Kathy        Date: 3/11/03    Time: 11:26a
 * Updated in $/EXE/RefObj/ROEditor
 * be sure tree isloaded for group def change
 * 
 * *****************  Version 42  *****************
 * User: Kathy        Date: 3/04/03    Time: 11:13a
 * Updated in $/EXE/RefObj/ROEditor
 * may be more than 1 new database for tree at a time
 * 
 * *****************  Version 41  *****************
 * User: Kathy        Date: 2/24/03    Time: 11:09a
 * Updated in $/EXE/RefObj/ROEditor
 * fixed new with implicit cancel bug (crash)
 * 
 * *****************  Version 40  *****************
 * User: Jsj          Date: 2/21/03    Time: 5:33p
 * Updated in $/EXE/RefObj/ROEditor
 * fixed RO | Save menu item enable/disable state
 * 
 * *****************  Version 39  *****************
 * User: Kathy        Date: 2/03/03    Time: 10:40a
 * Updated in $/EXE/RefObj/ROEditor
 * ui improve
 * 
 * *****************  Version 38  *****************
 * User: Kathy        Date: 1/22/03    Time: 12:18p
 * Updated in $/EXE/RefObj/ROEditor
 * duplicate/save as bug
 * 
 * *****************  Version 37  *****************
 * User: Kathy        Date: 1/15/03    Time: 1:57p
 * Updated in $/EXE/RefObj/ROEditor
 * improve UI
 * 
 * *****************  Version 36  *****************
 * User: Jsj          Date: 1/13/03    Time: 12:00p
 * Updated in $/EXE/RefObj/ROEditor
 * fixed call to data conversion
 * 
 * *****************  Version 35  *****************
 * User: Kathy        Date: 1/08/03    Time: 10:07a
 * Updated in $/EXE/RefObj/ROEditor
 * view image support
 * 
 * *****************  Version 34  *****************
 * User: Kathy        Date: 1/07/03    Time: 9:25a
 * Updated in $/EXE/RefObj/ROEditor
 * roeditor.own & specific ro (from vfw)
 * 
 * *****************  Version 33  *****************
 * User: Jsj          Date: 1/06/03    Time: 11:31a
 * Updated in $/EXE/RefObj/ROEditor
 * logic for No RO directory, Emply RO directroy, and RO directory with
 * paradox database
 * 
 * *****************  Version 32  *****************
 * User: Jsj          Date: 1/02/03    Time: 3:57p
 * Updated in $/EXE/RefObj/ROEditor
 * added INI file logic
 * 
 * *****************  Version 31  *****************
 * User: Kathy        Date: 12/17/02   Time: 9:47a
 * Updated in $/EXE/RefObj/ROEditor
 * fix some duplicate/save as bugs
 * 
 * *****************  Version 30  *****************
 * User: Kathy        Date: 12/16/02   Time: 12:12p
 * Updated in $/EXE/RefObj/ROEditor
 * added cancel button & fixed some duplicate/saveas bugs
 * 
 * *****************  Version 29  *****************
 * User: Kathy        Date: 12/13/02   Time: 10:06a
 * Updated in $/EXE/RefObj/ROEditor
 * if 'cancel' from edit, was 'stuck' on that edit control
 * 
 * *****************  Version 28  *****************
 * User: Kathy        Date: 12/10/02   Time: 2:26p
 * Updated in $/EXE/RefObj/ROEditor
 * fieldname special chars & bug fixes
 * 
 * *****************  Version 27  *****************
 * User: Jsj          Date: 12/06/02   Time: 3:28p
 * Updated in $/EXE/RefObj/ROEditor
 * fix for parameter display data (ignoring the data for now)
 * 
 * *****************  Version 26  *****************
 * User: Kathy        Date: 12/06/02   Time: 11:59a
 * Updated in $/EXE/RefObj/ROEditor
 * improve tree view & fix minor menuing things
 * 
 * *****************  Version 25  *****************
 * User: Kathy        Date: 12/02/02   Time: 8:30a
 * Updated in $/EXE/RefObj/ROEditor
 * fieldname replace chars
 * 
 * *****************  Version 24  *****************
 * User: Jsj          Date: 11/27/02   Time: 12:54p
 * Updated in $/EXE/RefObj/ROEditor
 * Modification to create the RO.FST file
 * 
 * *****************  Version 23  *****************
 * User: Kathy        Date: 11/26/02   Time: 11:10a
 * Updated in $/EXE/RefObj/ROEditor
 * add icons, list view & improve sizing
 * 
 * *****************  Version 22  *****************
 * User: Kathy        Date: 11/20/02   Time: 1:29p
 * Updated in $/EXE/RefObj/ROEditor
 * selecting 'x' doesn't close it - fixed.
 * 
 * *****************  Version 21  *****************
 * User: Kathy        Date: 11/20/02   Time: 11:37a
 * Updated in $/EXE/RefObj/ROEditor
 * zoom btn & ask about save for mod data
 * 
 * *****************  Version 20  *****************
 * User: Kathy        Date: 11/19/02   Time: 11:30a
 * Updated in $/EXE/RefObj/ROEditor
 * Fix a variety of UI bugs
 * 
 * *****************  Version 19  *****************
 * User: Kathy        Date: 10/24/02   Time: 11:17a
 * Updated in $/EXE/RefObj/ROEditor
 * save as, duplicate and delete top group
 * 
 * *****************  Version 18  *****************
 * User: Kathy        Date: 10/15/02   Time: 2:19p
 * Updated in $/EXE/RefObj/ROEditor
 * added new hi-level group
 * 
 * *****************  Version 17  *****************
 * User: Kathy        Date: 10/11/02   Time: 11:37a
 * Updated in $/EXE/RefObj/ROEditor
 * Restore Btn, bug fixes
 * 
 * *****************  Version 16  *****************
 * User: Kathy        Date: 10/10/02   Time: 10:03a
 * Updated in $/EXE/RefObj/ROEditor
 * accessory page id & try to make xml tree in sync with tree control
 * 
 * *****************  Version 15  *****************
 * User: Jsj          Date: 10/03/02   Time: 4:53p
 * Updated in $/EXE/RefObj/ROEditor
 * got the Edit menus (cut,paste,etc) working
 * 
 * *****************  Version 14  *****************
 * User: Jsj          Date: 10/03/02   Time: 1:27p
 * Updated in $/EXE/RefObj/ROEditor
 * put back missing variables for tree nodes
 * 
 * *****************  Version 13  *****************
 * User: Jsj          Date: 10/02/02   Time: 5:46p
 * Updated in $/EXE/RefObj/ROEditor
 * added an Edit menu item to the popup and RO menus.  Added logic to
 * enable or disable the Save, Expand/Collaspe, and Properties menu items,
 * added an About dialog box.  Added logic to clear the edit pane.
 * 
 * *****************  Version 12  *****************
 * User: Kathy        Date: 10/02/02   Time: 2:43p
 * Updated in $/EXE/RefObj/ROEditor
 * more tying tree to data
 * 
 * *****************  Version 11  *****************
 * User: Kathy        Date: 10/02/02   Time: 1:39p
 * Updated in $/EXE/RefObj/ROEditor
 * insert/delete group/ro tie tree to code (round 1)
 * 
 * *****************  Version 10  *****************
 * User: Jsj          Date: 10/02/02   Time: 12:11p
 * Updated in $/EXE/RefObj/ROEditor
 * added Delete to popup, and added logic to right mouse button so that it
 * selects the tree node and modifies the popup menu based on if that node
 * is colasped or expanded.
 * 
 * *****************  Version 9  *****************
 * User: Jsj          Date: 10/01/02   Time: 4:50p
 * Updated in $/EXE/RefObj/ROEditor
 * added menus and ability to pass in a database path
 * 
 * *****************  Version 8  *****************
 * User: Kathy        Date: 9/27/02    Time: 1:20p
 * Updated in $/EXE/RefObj/ROEditor
 * fix minor problems with listing groups without ros
 * 
 * *****************  Version 7  *****************
 * User: Kathy        Date: 9/25/02    Time: 9:57a
 * Updated in $/EXE/RefObj/ROEditor
 * dev
 * 
 * *****************  Version 6  *****************
 * User: Kathy        Date: 9/19/02    Time: 10:04a
 * Updated in $/EXE/RefObj/ROEditor
 * minor changes during dev
 * 
 * *****************  Version 5  *****************
 * User: Kathy        Date: 9/11/02    Time: 1:16p
 * Updated in $/EXE/RefObj/ROEditor
 * vlnxml
 * 
 * *****************  Version 4  *****************
 * User: Kathy        Date: 9/10/02    Time: 12:55p
 * Updated in $/EXE/RefObj/ROEditor
 * menutitle attribute
 * 
 * *****************  Version 3  *****************
 * User: Kathy        Date: 9/05/02    Time: 12:41p
 * Updated in $/EXE/RefObj/ROEditor
 * dev
 * 
 * *****************  Version 2  *****************
 * User: Kathy        Date: 8/28/02    Time: 10:58a
 * Updated in $/EXE/RefObj/ROEditor
 * development
 * 
 * *****************  Version 1  *****************
 * User: Jsj          Date: 8/23/02    Time: 3:35p
 * Created in $/EXE/RefObj/ROEditor
 *********************************************************************************************/

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



namespace ROEditor
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	///

	public class Form1 : System.Windows.Forms.Form
	{
		private ctlXMLEditLib.ctlXMLEdit ctlXMLEdit2;
		private RODB myrodb;
		private string DbConnectPath;
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.Splitter splitter1;
		private System.Windows.Forms.MainMenu mainMenu1;
		private System.Windows.Forms.MenuItem menuItem10;
		private System.Windows.Forms.MenuItem menuNewGroup;
		private System.Windows.Forms.MenuItem menuEdit;
		private System.Windows.Forms.MenuItem menuEditCopy;
		private System.Windows.Forms.MenuItem menuEditCut;
		private System.Windows.Forms.MenuItem menuEditPaste;
		private System.Windows.Forms.MenuItem menuTools;
		private System.Windows.Forms.MenuItem menuToolsROFST;
		private System.Windows.Forms.MenuItem menuHelp;
		private System.Windows.Forms.MenuItem menuHelpAbout;
		private System.Windows.Forms.Panel panel1;
		private System.Windows.Forms.MenuItem menuRO;
		private System.Windows.Forms.MenuItem menuRONew;
		private System.Windows.Forms.MenuItem menuNewRefObj;
		private System.Windows.Forms.MenuItem menuROEdit;		
		private System.Windows.Forms.MenuItem menuRODelete;
		private System.Windows.Forms.MenuItem menuROSave;
		private System.Windows.Forms.MenuItem menuROProperties;
		private System.Windows.Forms.MenuItem menuROExit;
		private System.Windows.Forms.MenuItem menuItem1;
		
		private XmlDocument myroXmlDoc;
		private VlnXmlElement newone;
		private TreeNode TreeNewparent;
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem menuItem5;
		private System.Windows.Forms.MenuItem menuEditUndo;
		private System.Windows.Forms.MenuItem menuEditDelete;
		private System.Windows.Forms.MenuItem menuEditSelAll;
		private TreeNode LastSelectedNode;
		private TextBox CurrentTextBox; // currently selected TextBox field
		private VlnXmlElement rootXml;
		private TreeNode rootNode;
		
		private System.Windows.Forms.ImageList imageListRoTree;
		private System.Windows.Forms.TreeView roTreeView;
		private System.Windows.Forms.ListView roListView;
		private System.Windows.Forms.ToolBar tbar;
		private bool duplicate_active;

		private const int ROGROUPIMAGE = 0;
		private System.Windows.Forms.Panel panel2;
		private const int ROIMAGE = 1;

		private ToolBarButton tbtnSave;
		private ToolBarButton tbtnRestore;
		private ToolBarButton tbtnCancel;
		private ToolBarButton tbtnSaveAs;
		private ToolBarButton tbtnDuplicate;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.ImageList imageListToolBar;
		private ToolBarButton tbtnZoom;

		public Form1(string PassedInPath, string specificro)
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();	 

			// The data path the was passed in.
			DbConnectPath = PassedInPath;
			
			// Setup the context menu
			MenuItem[] ContextMenuItemList = new MenuItem[6];
			ContextMenuItemList[0] = new MenuItem("Expand/Collaspe",new EventHandler(roTreeView_ToggleExpandCollapse));
			ContextMenuItemList[1] = menuRONew.CloneMenu();
			ContextMenuItemList[2] = menuROEdit.CloneMenu();
			ContextMenuItemList[3] = menuRODelete.CloneMenu();
			ContextMenuItemList[4] = menuROSave.CloneMenu();
			ContextMenuItemList[5] = menuROProperties.CloneMenu();

			ContextMenu treePopupMenu = new ContextMenu(ContextMenuItemList);

			// Add the root to the tree.
			myrodb = new RODB(DbConnectPath);
			myroXmlDoc = myrodb.RODB_GetRoot();
			rootXml = (VlnXmlElement) myroXmlDoc.FirstChild;
			rootNode = new TreeNode("Referenced Objects",ROGROUPIMAGE,ROGROUPIMAGE);
			rootNode.Tag = rootXml;
			roTreeView.Nodes.Add(rootNode);
			roTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.roTreeView_AfterSelect);
			roTreeView.DoubleClick += new System.EventHandler(this.roTreeView_OnDoubleClick);	
			roTreeView.BeforeExpand += new System.Windows.Forms.TreeViewCancelEventHandler(this.roTreeView_BeforeExpand);
			roTreeView.Sorted = true;
			roTreeView.ContextMenu = treePopupMenu;
			roTreeView.MouseDown += new System.Windows.Forms.MouseEventHandler(roTreeView_OnMouseDown);

			// For each group, get its subgroup.
			bool success = myrodb.RODB_GetRootGroups((VlnXmlElement)myroXmlDoc.FirstChild);
			if (success == false) this.Close();
			VlnXmlElement group = (VlnXmlElement) myroXmlDoc.FirstChild.FirstChild;
			while (group != null)
			{
				// Add the top groups to tree control as a node.
				TreeNode grnode = new TreeNode(CvtFldToUserFld(group.InnerText),ROGROUPIMAGE,ROGROUPIMAGE);
				grnode.Tag = group;
				rootNode.Nodes.Add(grnode);
				string haskids = group.GetAttribute("HasChild");

				if (haskids == "True") // add a 'dummy' node to tree if there are any
				{
					TreeNode subch = new TreeNode("VLN_DUMMY_FOR_TREE");
					subch.Tag = group;
					grnode.Nodes.Add(subch);
				}
				group = (VlnXmlElement) group.NextSibling;
			}
			newone = null;
			rootNode.Expand();
			duplicate_active = false;
			if (specificro != null) DoSpecificRO(specificro);
		}
		private void DoSpecificRO(string specificro)
		{
			// if a specific RO was passed in. Load the xml tree from it to the root & then
			// edit it through the ctlXmledit.
			// from the input tbl string, get a table name.

			ArrayList levelRecids = new ArrayList();
			int itbl = System.Convert.ToInt32(specificro.Substring(0,4),16);
			string stbl = System.Convert.ToString(itbl,10);
			string pstbl = stbl.PadLeft(6,'0');
			string tbname = "RO" + pstbl;
			string recid = specificro.Substring(4,8);

			// read in this element from the table.
			VlnXmlElement spro;
			spro = myrodb.RODB_ReadRO(tbname, recid);

			VlnXmlElement parent;
			string parentid;
			parentid = spro.GetAttribute("ParentID");
			string sproParentid = parentid;

			// walk up tree to get the path through the tree.
			VlnXmlElement child = spro;
			while (parentid != null && parentid != "00000000")
			{
				parent = myrodb.RODB_ReadRO(tbname, parentid);
				if (parent != null)
				{
					parentid = parent.GetAttribute("ParentID");
					levelRecids.Add(parent.GetAttribute("RecID"));
					if (parentid == "00000000") break;
					parent.AppendChild(child);
					child = parent;
				}
				else
					parentid = null;
			}
				
			// Now hook this into the top part of tree by loading data into
			// xml & hooking it into the tree control. 
			string attrele;
			string attrspro;
			TreeNode trnd = rootNode.FirstNode;
			VlnXmlElement ele;
			for (int i=levelRecids.Count-1; i>=0; i--)
			{
				ele = (VlnXmlElement) trnd.Tag;
				attrele = ele.GetAttribute((i==levelRecids.Count-1)?"Table":"RecID");
				if (i==levelRecids.Count-1)
					attrspro = spro.GetAttribute("Table");
				else
					attrspro = (string) levelRecids[i];
				while (attrele != attrspro)
				{
					// get next one.
					trnd = trnd.NextNode;
					ele = (VlnXmlElement) trnd.Tag;
					attrele = ele.GetAttribute((i==levelRecids.Count-1)?"Table":"RecID");
				}
				if (trnd == null) 
				{
					MessageBox.Show("Error editting RO");
					return;
				}
				LoadKids(trnd);
				trnd = trnd.FirstNode;
			}
			// lastly select the active node, this will load up everything we need.
			if (trnd == null) 
			{
				MessageBox.Show("Error editting RO");
				return;
			}
			ele = (VlnXmlElement) trnd.Tag;
			attrele = ele.GetAttribute("RecID");
			while (attrele != spro.GetAttribute("RecID"))
			{
				trnd = trnd.NextNode;
				ele = (VlnXmlElement) trnd.Tag;
				attrele = ele.GetAttribute("RecID");
			}
			if (trnd == null)
			{
				MessageBox.Show("Error editting RO");
				return;
			}
			roTreeView.SelectedNode = trnd;

		}

		protected void roTreeView_AfterSelect (object sender, 
			System.Windows.Forms.TreeViewEventArgs e)
		{
			// if the same node was selected, don't do anything.
			if (LastSelectedNode != null && LastSelectedNode.Equals(roTreeView.SelectedNode)) return;
			
			TreeNode CurrentNode = roTreeView.SelectedNode;
			if (LastSelectedNode == null)
				LastSelectedNode = CurrentNode;
			if (CurrentNode != null)
			{
				if (!LastSelectedNode.Equals(CurrentNode))
				{
					int retval = roTreeView_ClearEditDisplay(false);
					if (retval == -1)    // cancel
					{
						roTreeView.SelectedNode = LastSelectedNode;
						
						return;
					}
					LastSelectedNode = CurrentNode;
				}

				// if selected to make new, but didn't add any data, remove it.
				if (newone!=null)
				{
					XmlNode parent = newone.ParentNode;
					parent.RemoveChild(newone);
					newone=null;
				}

				/* enable/disable menu items */

				// Enable the Save item if changes were made
				// Just copy the state of the Save Button
				menuROSave.Enabled = tbtnSave.Enabled;
				roTreeView.ContextMenu.MenuItems[4].Enabled = tbtnSave.Enabled;

				// Should the properties menu item be available?
				VlnXmlElement curelem = (VlnXmlElement) CurrentNode.Tag;
				if (curelem.Name == "vlnGroup")
					menuROProperties.Enabled = true;
				else
					menuROProperties.Enabled = false;

				// Should the delete menu item be available, i.e. at top node, NO!
				if (curelem.Name == "RO_Root")
				{
					menuRODelete.Enabled = false;
					menuNewRefObj.Enabled = false;
				}
				else
				{
					menuRODelete.Enabled = true;
					menuNewRefObj.Enabled = true;
				}

				// Is there field text to edit?
				// yes if current node is either a subgroup or ro value node
				menuROEdit.Enabled = roTreeView_IsSubgroupOrRO();
				LoadKids(CurrentNode);
				if (curelem.Name != "RO_Root" && curelem.Name != "vlnGroup")
					EditRO(curelem);
				else
					updateRoListView(CurrentNode);
			}
		}

		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;
		}

		protected void roTreeView_ToggleExpandCollapse(object sender, System.EventArgs e)
		{

			TreeNode tmpCurrentNode = roTreeView.SelectedNode;
			if (tmpCurrentNode.IsExpanded)
				tmpCurrentNode.Collapse();
			else
				tmpCurrentNode.Expand();
		}

		protected void roTreeView_OnMouseDown (object sender, System.Windows.Forms.MouseEventArgs e)
		{
			// if the right mouse button was used, then selected the node that is currently
			// under the mouse pointer.
			if (e.Button == MouseButtons.Right)
			{
				// Get the tree node at the current mouse position and set it
				// to be the the currently selected node (i.e. selecti that node)
				TreeNode CurrentNode = roTreeView.GetNodeAt(e.X,e.Y);
				if (CurrentNode != null)
				{
					roTreeView.SelectedNode = CurrentNode; // select this node
					LastSelectedNode = CurrentNode;
				}
				else
					CurrentNode = roTreeView.SelectedNode; // default to last selected node

				if (CurrentNode != null)
				{
					// determine if the node can expand or collapse and change the popup
					// menu text accordingly
					if (CurrentNode.GetNodeCount(false) > 0)
					{
						if (CurrentNode.IsExpanded)
							roTreeView.ContextMenu.MenuItems[0].Text = "Collapse";
						else
							roTreeView.ContextMenu.MenuItems[0].Text = "Expand";
						roTreeView.ContextMenu.MenuItems[0].Enabled = true;
					}
					else
					{
						roTreeView.ContextMenu.MenuItems[0].Text = "Expand/Collapse";
						roTreeView.ContextMenu.MenuItems[0].Enabled = false;
					}


					// Should the save option be available?
					// Just reflect the Save button state.
					roTreeView.ContextMenu.MenuItems[4].Enabled = tbtnSave.Enabled;
					menuROSave.Enabled = tbtnSave.Enabled;

					// Should the properties menu item be available?
					VlnXmlElement curelem = (VlnXmlElement) CurrentNode.Tag;
					if (curelem.Name == "vlnGroup")
						roTreeView.ContextMenu.MenuItems[5].Enabled = true;
					else
						roTreeView.ContextMenu.MenuItems[5].Enabled = false;

					// should delete menu item be available, i.e. top node NO!
					if (curelem.Name == "RO_Root")
					{
						roTreeView.ContextMenu.MenuItems[3].Enabled = false;
						roTreeView.ContextMenu.MenuItems[1].MenuItems[1].Enabled = false;
					}
					else
					{
						roTreeView.ContextMenu.MenuItems[3].Enabled = true;
						roTreeView.ContextMenu.MenuItems[1].MenuItems[1].Enabled = true;
					}

					// Is there field text to edit?
					// yes if current node is either a subgroup or ro value node
					roTreeView.ContextMenu.MenuItems[2].Enabled = roTreeView_IsSubgroupOrRO();
				}
			}
		}

		/*
		 * return true if current tree node is a either a subgroup or a RO
		 */
		protected bool roTreeView_IsSubgroupOrRO()
		{
			bool rtnval = false;
			TreeNode CurrentNode = roTreeView.SelectedNode;
			VlnXmlElement curelem = (VlnXmlElement) CurrentNode.Tag;
			if (curelem.Name != "RO_Root")
			{
				if (curelem.Name == "vlnGroup")
				{
					TreeNode PNode = CurrentNode.Parent;
					VlnXmlElement pelem = (VlnXmlElement) PNode.Tag;
					rtnval = (pelem.Name == "vlnGroup");
				}
				else
					rtnval = true;
			}
			return rtnval;
		}
		/*
		 * Clear the edit display (panel on the right side)
		 */
		protected int roTreeView_ClearEditDisplay(bool cancel)
		{
			if (ctlXMLEdit2 != null)
			{
				if (cancel != true)
				{
					// first see if there is changes to data, if so, then prompt to see if 
					// user wants to continue.
					bool chgdata = ctlXMLEdit2.DataChanged();
					if (chgdata == true)
					{
						DialogResult dr = MessageBox.Show("Do you want to save your changes?","Warning:",MessageBoxButtons.YesNoCancel);
						if (dr == DialogResult.Yes)
						{
							TreeNode tr=null;
							bool ok = SaveRO(ref tr);   // savero needs a tree node
							if (ok == false) return -1;
						}
						else if (dr == DialogResult.Cancel)
							return -1;
					}
				}
				ctlXMLEdit2.Dispose();
				this.panel2.Controls.Remove(ctlXMLEdit2);
				this.panel2.Visible = false;
				tbtnSave.Enabled = false;
				menuROSave.Enabled = tbtnSave.Enabled;
				tbtnRestore.Enabled = false;
				tbtnSaveAs.Enabled = false;
				tbtnDuplicate.Enabled = false;
				tbtnZoom.Enabled = false;
				tbtnZoom.Text = "Zoom";
				ctlXMLEdit2 = null;
			}
			// The current text box no longer has focus.
			CurrentTextBox = null;
			tbtnCancel.Enabled = false; 
			roTreeView_ResetEditMenu();
			duplicate_active = false;
			return 0;
		}

		protected void roListView_ClearListDisplay()
		{
			if (roListView != null)
			{
				roListView.Dispose();
				this.panel1.Controls.Remove(roListView);
				roListView=null;
			}
		}

		private void CreateCtlXmlEdit2(VlnXmlElement curelem, XmlSchema myschema, ArrayList reqfields)
		{
			ctlXMLEdit2 = new ctlXMLEditLib.ctlXMLEdit(curelem,myschema,reqfields);
			ctlXMLEdit2.AutoScroll = true;
			ctlXMLEdit2.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			ctlXMLEdit2.Name = "ctlXMLEdit2";
			ctlXMLEdit2.Size = new System.Drawing.Size(ctlXMLEdit2.GetMaxWidth(),ctlXMLEdit2.GetMaxLength());
			this.panel2.Visible = true;
			this.panel2.Size =  new System.Drawing.Size(ctlXMLEdit2.GetMaxWidth()+20,ctlXMLEdit2.GetMaxLength()+10);
			this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
			ctlXMLEdit2.TabIndex = 4;
			ctlXMLEdit2.Tag = "";
			/*
			 * Spin through all of the controls and assign an event handler
			 * for changed text so that when the user changes any of the RO Text,
			 * the Save button will become enabled
			 */
			System.Collections.IEnumerator ctlEnumerator = ctlXMLEdit2.Controls.GetEnumerator();
			while (ctlEnumerator.MoveNext())
			{
				Control TmpInfo;
				TmpInfo = (Control)ctlEnumerator.Current;
				if (TmpInfo is GroupBox)
				{
					System.Collections.IEnumerator ctlGroup = TmpInfo.Controls.GetEnumerator();;
					while(ctlGroup.MoveNext())
					{
						Control tmpradio = (Control) ctlGroup.Current;
						tmpradio.Click += new EventHandler(ctlXMLEdit2_ClickControl);
					}
				}
				else
				{
					TmpInfo.TextChanged += new EventHandler(ctlXMLEdit2_TextChanged);
					TmpInfo.Click += new EventHandler(ctlXMLEdit2_ClickControl);
				}
			}
			this.panel2.Controls.Add(ctlXMLEdit2);
			tbtnCancel.Enabled = true; 
		}

		private void EditRO(VlnXmlElement curelem)
		{
			newone=null;
			// can't edit fields for top or top group nodes (top node not editable,
			// and top group node data change at properties level).
			if (curelem.Name == "RO_Root" || curelem.ParentNode.Name == "RO_Root") return;

			int retval = roTreeView_ClearEditDisplay(false);
			if (retval == -1) return;
			roListView_ClearListDisplay();

			XmlSchema myschema;
			// If no schema exists, then the definition of the item may not be complete - give
			// a message. (B2004-017)
			if (curelem.Name != "vlnGroup")
			{
				myschema = myrodb.RODB_GetSchema(curelem);
				if (myschema==null)
				{
					MessageBox.Show("RO Definition does not exist, check RO Definition under Properties for the Group that contains this RO.");
					return;
				}
			}
			else
			{
				myschema = myrodb.RODB_GetGroupSchema(curelem);
				if (myschema==null)
				{
					MessageBox.Show("Subgroup Definition does not exist, check Subgroup Definition under Properties for the Group that contains this Subgroup.");
					return;
				}
			}
	
			ArrayList reqfields = curelem.GetRequiredFields();
			CreateCtlXmlEdit2(curelem,myschema,reqfields);
			this.panel2.Controls.Add(ctlXMLEdit2);
			tbtnSave.Enabled=false; // set initial states of buttons on edit
			tbtnRestore.Enabled=false;
			tbtnCancel.Enabled=true;
			tbtnSaveAs.Enabled=false;
			tbtnDuplicate.Enabled=true;
			tbtnZoom.Enabled = false;
			ctlXMLEdit2.Focus();
		}
		protected void roTreeView_OnDoubleClick (object sender,	System.EventArgs e)
		{
			VlnXmlElement curelem = (VlnXmlElement) roTreeView.SelectedNode.Tag;
			EditRO(curelem);
		}

		protected void roTreeView_ResetEditMenu ()
		{
			this.menuEditCopy.Enabled = false;
			this.menuEditCut.Enabled = false;
			this.menuEditPaste.Enabled = false;
			this.menuEditDelete.Enabled = false;
			this.menuEditSelAll.Enabled = false;
			this.menuEditUndo.Enabled = false;
		}


		protected void ctlXMLEdit2_ClickControl(object sender, EventArgs e)
		{
			TextBox tmpTxtbx = new TextBox();
			CurrentTextBox = null;

			roTreeView_ResetEditMenu();

			if (sender.GetType() == tmpTxtbx.GetType())
			{
				tmpTxtbx = (TextBox)sender;
				CurrentTextBox = tmpTxtbx; // the text box currently selected
				
				if (CurrentTextBox.Multiline)
				{
					tbtnZoom.Text = "Zoom";
					tbtnZoom.Enabled = true;
				}
				else if (CurrentTextBox == ctlXMLEdit2.GetGraphicsFiletextbox() && CurrentTextBox.Text != null && CurrentTextBox.Text != "")
				{
					tbtnZoom.Enabled = true;
					tbtnZoom.Text = "View Image";
				}
				else 
				{
					tbtnZoom.Text = "Zoom";
					tbtnZoom.Enabled = false;
				}

				if (tmpTxtbx.CanUndo)
					this.menuEditUndo.Enabled = true;

				if (tmpTxtbx.TextLength != tmpTxtbx.SelectionLength)
				{
					this.menuEditSelAll.Enabled = true;
				}

				if (tmpTxtbx.SelectionLength > 0)
				{
					this.menuEditDelete.Enabled = true;
					this.menuEditCopy.Enabled = true;
					this.menuEditCut.Enabled = true;
				}
				object dataobj = System.Windows.Forms.Clipboard.GetDataObject();
				if (dataobj != null)
					this.menuEditPaste.Enabled=true;
			}
			else if (sender is RadioButton)
			{
				tbtnCancel.Enabled = true;
				tbtnSave.Enabled = true;
				tbtnRestore.Enabled = true;
				tbtnSaveAs.Enabled = true;
			}							  
			menuROSave.Enabled = tbtnSave.Enabled;
		}


		protected void ctlXMLEdit2_TextChanged(object sender, EventArgs e)
		{
			if (CurrentTextBox != null)
			{
				this.menuEditUndo.Enabled = true;
				this.menuEditSelAll.Enabled = (CurrentTextBox.TextLength > 0);
			}

			tbtnSave.Enabled = true;
			tbtnRestore.Enabled = true;
			tbtnSaveAs.Enabled = true;
			tbtnCancel.Enabled = true;
			menuROSave.Enabled = tbtnSave.Enabled;
		}

		private void LoadKids(TreeNode enode)
		{
			VlnXmlElement elem;
			elem = (VlnXmlElement)enode.Tag;
			string haskids;
			string kidsloaded;
			haskids = elem.GetAttribute("HasChild");
			kidsloaded = elem.GetAttribute("ChildLoaded");
			if (haskids == "True" && kidsloaded == "False" )
			{
				// if there's a dummy tree node (used to have tree control expansion for
				// items not yet loaded, delete child in tree control)
				XmlNode tmpnode = (XmlNode) elem;
				XmlNode chldnode;
				VlnXmlElement echild;
				if (enode.FirstNode.Text == "VLN_DUMMY_FOR_TREE") enode.FirstNode.Remove();
				Cursor.Current = Cursors.WaitCursor;
				myrodb.RODB_GetChildData(elem,true);
				chldnode = tmpnode.FirstChild;
				while (chldnode != null)
				{
					if (chldnode is VlnXmlElement)
					{
						echild = (VlnXmlElement) chldnode;
						TreeNode chldnd;
						if (echild.Name == "vlnGroup") 
						{
							chldnd = new TreeNode(echild.GetAttribute("MenuTitle"),ROGROUPIMAGE,ROGROUPIMAGE); 
							chldnd.Tag = echild;
							enode.Nodes.Add(chldnd);
							// add a 'dummy' node to tree if there are any children
							string haskids1="False";
							string kidsloaded1="False";
							if (echild.HasAttribute("HasChild")==true)
								haskids1 = echild.GetAttribute("HasChild");
							if (echild.HasAttribute("ChildLoaded")==true)
								kidsloaded1 = echild.GetAttribute("ChildLoaded");
							if (haskids1=="True" && kidsloaded1=="False")
							{
								TreeNode subch = new TreeNode("VLN_DUMMY_FOR_TREE");
								chldnd.Nodes.Add(subch);				
							}
						}
						else
						{
							// If this is a group defintion subtree it will only have one
							// child, which is the text definition for the subgroup. Don't
							// include these in the tree.
							int levelcnt = chldnode.ChildNodes.Count;
							string TheMenuTitle = echild.GetAttribute("MenuTitle");
							if (levelcnt>=1 && !TheMenuTitle.Equals(""))
							{
								chldnd = new TreeNode(TheMenuTitle,ROIMAGE,ROIMAGE);
								chldnd.Tag = echild;
								enode.Nodes.Add(chldnd);
							}
						}
					}
					chldnode = chldnode.NextSibling;
				}
				Cursor.Current = Cursors.Default;	
			}
		}

		protected void roTreeView_BeforeExpand(object sender, 
			System.Windows.Forms.TreeViewCancelEventArgs e)
		{
			LoadKids(e.Node);
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the co`de editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
			this.imageListRoTree = new System.Windows.Forms.ImageList(this.components);
			this.splitter1 = new System.Windows.Forms.Splitter();
			this.mainMenu1 = new System.Windows.Forms.MainMenu(this.components);
			this.menuRO = new System.Windows.Forms.MenuItem();
			this.menuRONew = new System.Windows.Forms.MenuItem();
			this.menuNewGroup = new System.Windows.Forms.MenuItem();
			this.menuNewRefObj = new System.Windows.Forms.MenuItem();
			this.menuItem1 = new System.Windows.Forms.MenuItem();
			this.menuROEdit = new System.Windows.Forms.MenuItem();
			this.menuRODelete = new System.Windows.Forms.MenuItem();
			this.menuROSave = new System.Windows.Forms.MenuItem();
			this.menuROProperties = new System.Windows.Forms.MenuItem();
			this.menuItem10 = new System.Windows.Forms.MenuItem();
			this.menuROExit = new System.Windows.Forms.MenuItem();
			this.menuEdit = new System.Windows.Forms.MenuItem();
			this.menuEditUndo = new System.Windows.Forms.MenuItem();
			this.menuItem3 = new System.Windows.Forms.MenuItem();
			this.menuEditCut = new System.Windows.Forms.MenuItem();
			this.menuEditCopy = new System.Windows.Forms.MenuItem();
			this.menuEditPaste = new System.Windows.Forms.MenuItem();
			this.menuEditDelete = new System.Windows.Forms.MenuItem();
			this.menuItem5 = new System.Windows.Forms.MenuItem();
			this.menuEditSelAll = new System.Windows.Forms.MenuItem();
			this.menuTools = new System.Windows.Forms.MenuItem();
			this.menuToolsROFST = new System.Windows.Forms.MenuItem();
			this.menuHelp = new System.Windows.Forms.MenuItem();
			this.menuHelpAbout = new System.Windows.Forms.MenuItem();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.panel1 = new System.Windows.Forms.Panel();
			this.panel2 = new System.Windows.Forms.Panel();
			this.roTreeView = new System.Windows.Forms.TreeView();
			this.tbar = new System.Windows.Forms.ToolBar();
			this.tbtnSave = new System.Windows.Forms.ToolBarButton();
			this.tbtnCancel = new System.Windows.Forms.ToolBarButton();
			this.tbtnRestore = new System.Windows.Forms.ToolBarButton();
			this.tbtnSaveAs = new System.Windows.Forms.ToolBarButton();
			this.tbtnDuplicate = new System.Windows.Forms.ToolBarButton();
			this.tbtnZoom = new System.Windows.Forms.ToolBarButton();
			this.imageListToolBar = new System.Windows.Forms.ImageList(this.components);
			this.panel1.SuspendLayout();
			this.SuspendLayout();
			// 
			// imageListRoTree
			// 
			this.imageListRoTree.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListRoTree.ImageStream")));
			this.imageListRoTree.TransparentColor = System.Drawing.Color.Transparent;
			this.imageListRoTree.Images.SetKeyName(0, "");
			this.imageListRoTree.Images.SetKeyName(1, "");
			// 
			// splitter1
			// 
			this.splitter1.Location = new System.Drawing.Point(264, 31);
			this.splitter1.Name = "splitter1";
			this.splitter1.Size = new System.Drawing.Size(10, 588);
			this.splitter1.TabIndex = 4;
			this.splitter1.TabStop = false;
			// 
			// mainMenu1
			// 
			this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuRO,
            this.menuEdit,
            this.menuTools,
            this.menuHelp,
            this.menuItem2});
			// 
			// menuRO
			// 
			this.menuRO.Index = 0;
			this.menuRO.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuRONew,
            this.menuItem1,
            this.menuROEdit,
            this.menuRODelete,
            this.menuROSave,
            this.menuROProperties,
            this.menuItem10,
            this.menuROExit});
			this.menuRO.Text = "RO";
			// 
			// menuRONew
			// 
			this.menuRONew.Index = 0;
			this.menuRONew.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuNewGroup,
            this.menuNewRefObj});
			this.menuRONew.Text = "New ...";
			// 
			// menuNewGroup
			// 
			this.menuNewGroup.Index = 0;
			this.menuNewGroup.Text = "Group";
			this.menuNewGroup.Click += new System.EventHandler(this.menuNewGroup_Click);
			// 
			// menuNewRefObj
			// 
			this.menuNewRefObj.Index = 1;
			this.menuNewRefObj.Text = "Referenced Object";
			this.menuNewRefObj.Click += new System.EventHandler(this.menuNewRefObj_Click);
			// 
			// menuItem1
			// 
			this.menuItem1.Index = 1;
			this.menuItem1.Text = "-";
			// 
			// menuROEdit
			// 
			this.menuROEdit.Enabled = false;
			this.menuROEdit.Index = 2;
			this.menuROEdit.Text = "Edit";
			this.menuROEdit.Click += new System.EventHandler(this.menuROEdit_Click);
			// 
			// menuRODelete
			// 
			this.menuRODelete.Index = 3;
			this.menuRODelete.Text = "Delete";
			this.menuRODelete.Click += new System.EventHandler(this.menuRODelete_Click);
			// 
			// menuROSave
			// 
			this.menuROSave.Enabled = false;
			this.menuROSave.Index = 4;
			this.menuROSave.Text = "Save";
			this.menuROSave.Click += new System.EventHandler(this.menuROSave_Click);
			// 
			// menuROProperties
			// 
			this.menuROProperties.Index = 5;
			this.menuROProperties.Text = "Properties";
			this.menuROProperties.Click += new System.EventHandler(this.menuROProperties_Click);
			// 
			// menuItem10
			// 
			this.menuItem10.Index = 6;
			this.menuItem10.Text = "-";
			// 
			// menuROExit
			// 
			this.menuROExit.Index = 7;
			this.menuROExit.Text = "Exit RO Editor";
			this.menuROExit.Click += new System.EventHandler(this.menuROExit_Click);
			// 
			// menuEdit
			// 
			this.menuEdit.Index = 1;
			this.menuEdit.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuEditUndo,
            this.menuItem3,
            this.menuEditCut,
            this.menuEditCopy,
            this.menuEditPaste,
            this.menuEditDelete,
            this.menuItem5,
            this.menuEditSelAll});
			this.menuEdit.Text = "Edit";
			// 
			// menuEditUndo
			// 
			this.menuEditUndo.Enabled = false;
			this.menuEditUndo.Index = 0;
			this.menuEditUndo.Text = "&Undo";
			this.menuEditUndo.Click += new System.EventHandler(this.menuEditUndo_Click);
			// 
			// menuItem3
			// 
			this.menuItem3.Index = 1;
			this.menuItem3.Text = "-";
			// 
			// menuEditCut
			// 
			this.menuEditCut.Enabled = false;
			this.menuEditCut.Index = 2;
			this.menuEditCut.Text = "Cu&t";
			this.menuEditCut.Click += new System.EventHandler(this.menuEditCut_Click);
			// 
			// menuEditCopy
			// 
			this.menuEditCopy.Enabled = false;
			this.menuEditCopy.Index = 3;
			this.menuEditCopy.Text = "&Copy";
			this.menuEditCopy.Click += new System.EventHandler(this.menuEditCopy_Click);
			// 
			// menuEditPaste
			// 
			this.menuEditPaste.Enabled = false;
			this.menuEditPaste.Index = 4;
			this.menuEditPaste.Text = "&Paste";
			this.menuEditPaste.Click += new System.EventHandler(this.menuEditPaste_Click);
			// 
			// menuEditDelete
			// 
			this.menuEditDelete.Enabled = false;
			this.menuEditDelete.Index = 5;
			this.menuEditDelete.Text = "&Delete";
			this.menuEditDelete.Click += new System.EventHandler(this.menuEditDelete_Click);
			// 
			// menuItem5
			// 
			this.menuItem5.Index = 6;
			this.menuItem5.Text = "-";
			// 
			// menuEditSelAll
			// 
			this.menuEditSelAll.Enabled = false;
			this.menuEditSelAll.Index = 7;
			this.menuEditSelAll.Text = "Select &All";
			this.menuEditSelAll.Click += new System.EventHandler(this.menuEditSelAll_Click);
			// 
			// menuTools
			// 
			this.menuTools.Index = 2;
			this.menuTools.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuToolsROFST});
			this.menuTools.Text = "Tools";
			// 
			// menuToolsROFST
			// 
			this.menuToolsROFST.Index = 0;
			this.menuToolsROFST.Text = "Create RO.FST";
			this.menuToolsROFST.Click += new System.EventHandler(this.menuToolsROFST_Click);
			// 
			// menuHelp
			// 
			this.menuHelp.Index = 3;
			this.menuHelp.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuHelpAbout});
			this.menuHelp.Text = "Help";
			// 
			// menuHelpAbout
			// 
			this.menuHelpAbout.Index = 0;
			this.menuHelpAbout.Text = "About";
			this.menuHelpAbout.Click += new System.EventHandler(this.menuHelpAbout_Click);
			// 
			// menuItem2
			// 
			this.menuItem2.Index = 4;
			this.menuItem2.Text = "";
			// 
			// panel1
			// 
			this.panel1.AutoScroll = true;
			this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
			this.panel1.Controls.Add(this.panel2);
			this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
			this.panel1.Location = new System.Drawing.Point(274, 31);
			this.panel1.Name = "panel1";
			this.panel1.Size = new System.Drawing.Size(542, 588);
			this.panel1.TabIndex = 5;
			// 
			// panel2
			// 
			this.panel2.AutoScroll = true;
			this.panel2.Location = new System.Drawing.Point(0, 0);
			this.panel2.Name = "panel2";
			this.panel2.Size = new System.Drawing.Size(282, 136);
			this.panel2.TabIndex = 0;
			this.panel2.Visible = false;
			// 
			// roTreeView
			// 
			this.roTreeView.Dock = System.Windows.Forms.DockStyle.Left;
			this.roTreeView.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
			this.roTreeView.ImageIndex = 0;
			this.roTreeView.ImageList = this.imageListRoTree;
			this.roTreeView.ItemHeight = 18;
			this.roTreeView.Location = new System.Drawing.Point(0, 31);
			this.roTreeView.Name = "roTreeView";
			this.roTreeView.SelectedImageIndex = 0;
			this.roTreeView.Size = new System.Drawing.Size(264, 588);
			this.roTreeView.TabIndex = 3;
			this.roTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.roTreeView_AfterSelect_1);
			// 
			// tbar
			// 
			this.tbar.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] {
            this.tbtnSave,
            this.tbtnCancel,
            this.tbtnRestore,
            this.tbtnSaveAs,
            this.tbtnDuplicate,
            this.tbtnZoom});
			this.tbar.DropDownArrows = true;
			this.tbar.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
			this.tbar.ImageList = this.imageListToolBar;
			this.tbar.Location = new System.Drawing.Point(0, 0);
			this.tbar.Name = "tbar";
			this.tbar.ShowToolTips = true;
			this.tbar.Size = new System.Drawing.Size(816, 31);
			this.tbar.TabIndex = 0;
			this.tbar.TextAlign = System.Windows.Forms.ToolBarTextAlign.Right;
			this.tbar.ButtonClick += new System.Windows.Forms.ToolBarButtonClickEventHandler(this.tbar_OnClick);
			// 
			// tbtnSave
			// 
			this.tbtnSave.Enabled = false;
			this.tbtnSave.ImageIndex = 0;
			this.tbtnSave.Name = "tbtnSave";
			this.tbtnSave.Text = "Save";
			// 
			// tbtnCancel
			// 
			this.tbtnCancel.Enabled = false;
			this.tbtnCancel.ImageIndex = 1;
			this.tbtnCancel.Name = "tbtnCancel";
			this.tbtnCancel.Text = "Cancel";
			// 
			// tbtnRestore
			// 
			this.tbtnRestore.Enabled = false;
			this.tbtnRestore.ImageIndex = 2;
			this.tbtnRestore.Name = "tbtnRestore";
			this.tbtnRestore.Text = "Restore";
			// 
			// tbtnSaveAs
			// 
			this.tbtnSaveAs.Enabled = false;
			this.tbtnSaveAs.ImageIndex = 3;
			this.tbtnSaveAs.Name = "tbtnSaveAs";
			this.tbtnSaveAs.Text = "Save As";
			// 
			// tbtnDuplicate
			// 
			this.tbtnDuplicate.Enabled = false;
			this.tbtnDuplicate.ImageIndex = 4;
			this.tbtnDuplicate.Name = "tbtnDuplicate";
			this.tbtnDuplicate.Text = "Duplicate";
			// 
			// tbtnZoom
			// 
			this.tbtnZoom.Enabled = false;
			this.tbtnZoom.ImageIndex = 5;
			this.tbtnZoom.Name = "tbtnZoom";
			this.tbtnZoom.Text = "Zoom";
			// 
			// imageListToolBar
			// 
			this.imageListToolBar.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListToolBar.ImageStream")));
			this.imageListToolBar.TransparentColor = System.Drawing.Color.Transparent;
			this.imageListToolBar.Images.SetKeyName(0, "");
			this.imageListToolBar.Images.SetKeyName(1, "");
			this.imageListToolBar.Images.SetKeyName(2, "");
			this.imageListToolBar.Images.SetKeyName(3, "");
			this.imageListToolBar.Images.SetKeyName(4, "");
			this.imageListToolBar.Images.SetKeyName(5, "");
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
			this.ClientSize = new System.Drawing.Size(816, 619);
			this.Controls.Add(this.panel1);
			this.Controls.Add(this.splitter1);
			this.Controls.Add(this.roTreeView);
			this.Controls.Add(this.tbar);
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.Menu = this.mainMenu1;
			this.Name = "Form1";
			this.Text = "RO Edit";
			this.panel1.ResumeLayout(false);
			this.ResumeLayout(false);
			this.PerformLayout();

		}
		#endregion

		[DllImport("user32.dll")]
		static extern bool SetForegroundWindow(IntPtr hWnd);
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		static void BringWindowToFront()
		{
			Process currentProcess = Process.GetCurrentProcess();
			Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName);
			Process process = null;
			for (int i = 0; i < processes.Length; i++)
			{
				if (processes[i].SessionId != currentProcess.SessionId)
				{
					process = processes[i];
					break;
				}
			}
			if (process == null) return;
			SetForegroundWindow(process.MainWindowHandle);
		}

		[STAThread]
		static void Main(string[] args) 
		{
			bool StartupROEditor = true;
			FileStream fsown=null;
			FileInfo fiown=null;
			String specificro = null;
			string ConnectionPath = "";
			// Let's open the database & set up for the tree structure...

			// if an RO directory path was passed in, then change the
			// current working directory to it.
			// this path will also be used to generate a connection string
			// the the Access database.
			if (args.Length > 0)
			{
				ConnectionPath = args[0];
//				Directory.SetCurrentDirectory(ConnectionPath);
			}
			else // find ROPATH
			{
				ConnectionPath = FindTheRODirectory();
			}
			if (args.Length > 1)
				specificro = args[1];
			try 
			{
				// Convert the RO data if needed
					if (!CheckForDataConversion(ConnectionPath))
						ConnectionPath = null; // force exit
			}
			catch (Exception e)
			{
				MessageBox.Show(e.Message, "Error on check for data conversion");
			//	Application.Exit();
			}
			// Process the given RO Path
			if (ConnectionPath == null)
			{
				// no RO directory
				MessageBox.Show("Could not locate a Referenced Objects (RO) directory.\n\nIt should be inside your VExxx directory or at the same level as your VExxx directory.","RO Editor");
				StartupROEditor = false;
			}
			else if (ConnectionPath.Equals(""))
			{
				// already in RO directory
				ConnectionPath = Directory.GetCurrentDirectory();
			}
			else
			{
				// Change to the RO Directory
				try
				{
					Directory.SetCurrentDirectory(ConnectionPath);
				}
				catch (Exception e)
				{
					MessageBox.Show(e.Message, e.GetType().ToString());
				}
			}

			if  (StartupROEditor)
			{
				// open an existing file, or create a new one
				try 
				{
					fiown = new FileInfo("RoEditor.own");
					fsown = fiown.Open(FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
					TextReader tr = new StreamReader(fsown);
					string who = tr.ReadToEnd();
					tr.Close();
					if (who.Contains(Environment.UserName.ToUpper()))
					{
						BringWindowToFront();
						return;
					}
				}
				catch(Exception e)
				{
					MessageBox.Show(e.Message,"fileinfo");
				}
				// Open the file just specified. Open it so that no-one else can use it
				try
				{
					fsown = fiown.Open( FileMode.Create, FileAccess.ReadWrite, FileShare.Read );
					TextWriter tw = new StreamWriter(fsown);
					tw.WriteLine("Current User:  {0}, Date and Time Started:  {1}", Environment.UserName.ToUpper(), DateTime.Now.ToString("MM/dd/yyyy @ hh:mm"));
					tw.Flush();
				} 
				catch (IOException ex) 
				{
					fsown = fiown.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
					TextReader tr = new StreamReader(fsown);
					string who = tr.ReadToEnd();
					tr.Close();
					if(who.Contains(Environment.UserName.ToUpper()))
					{
						BringWindowToFront();

						//Process[] p = Process.GetProcessesByName("ROEditor");
						//Process cp = Process.GetCurrentProcess();
						//for (int i = 0; i < p.Length; i++)
						//{
						//  if (p[i].SessionId != cp.SessionId)
						//  {
						//    SetForegroundWindow(p[i].MainWindowHandle);
						//    break;
						//  }
						//}
					}
					else
						MessageBox.Show(who, "Another user is executing the RoEditor");
					return;
				}

				// If there isn't a RO database file, ask user if we should create an empty one.
				if (!File.Exists("ROMaster.mdb") && !UsingSQLServer(Directory.GetCurrentDirectory()))
				{
					DialogResult AnswerYN;
					string msgstr = "The RO directory (" + Directory.GetCurrentDirectory() +") is empty.\n\n Create an empty RO database?";
					AnswerYN = MessageBox.Show(msgstr,"RO Editor",MessageBoxButtons.YesNo);
					if (AnswerYN == DialogResult.Yes)
					{
						string SourceRODatabase = Application.StartupPath + "\\ROMaster.mdb";
						string DestRODatabase = Directory.GetCurrentDirectory() + "\\ROMaster.mdb";
						File.Copy(SourceRODatabase,DestRODatabase);
					}
					else
						StartupROEditor = false;
				}
			}

			if  (StartupROEditor)
			{
				Application.Run(new Form1(ConnectionPath,specificro));
			
				if (fsown != null)
				{
					fsown.Close();
					fiown.Delete();
					}
				Application.Exit();
			}
		}

		/*
		 * Look for the RO directory via PROC.INI and by
		 * looking for a \RO directory in the current VEplant
		 * directory and at the same level as VEplant
		 */
		static string FindTheRODirectory()
		{
			string RtnStr = "";
			string CurDir = Directory.GetCurrentDirectory();
			CurDir = CurDir.ToUpper();
			bool InProcdureDir = false;

			// are we in the RO directory?
			if (!CurDir.EndsWith("\\RO")) //not in RO directory
			{
				if (File.Exists("PROC.INI")) // Get the ROPATH from the PROC.INI file if possible
				{
					InProcdureDir = true;
					IniReader ini = new IniReader("PROC.INI");
					RtnStr = ini.ReadString("RO Defaults","ROPATH","");
				}
				if (RtnStr.Equals("")) // no ROPATH specified
				{
					RtnStr = "..\\RO"; // check default location
					if (!Directory.Exists(RtnStr))
					{
						// Check for Global ROs (at the same directory level as the VEplant directory)
						if (CurDir.EndsWith("TMPCHG")) // handle temporary change directory
						{
							InProcdureDir = false;
							RtnStr = "..\\..\\..\\..\\RO";
						}
						else // Check for Global RO, assume we are in PROCS or .PRC directory
							RtnStr = "..\\..\\RO";
						if (!Directory.Exists(RtnStr) && InProcdureDir)
						{
							// Could not find RO directory.
							// Instruct the user to create one.
							DialogResult AnswerYN;
							int idx = CurDir.LastIndexOf("\\");
							RtnStr = CurDir.Substring(0,idx+1) + "RO"; // default location
							string msgstr = "A RO directory (folder) does not exist.\n\n Create a RO directory in the default location (" + RtnStr + ")?";
							AnswerYN = MessageBox.Show(msgstr,"RO Editor",MessageBoxButtons.YesNo);
							if (AnswerYN == DialogResult.Yes)
							{
								Directory.CreateDirectory(RtnStr);
							}
							else
								RtnStr = null; 
						}
						else RtnStr = null;
					}
				}
			}
			return RtnStr;
		}

		static bool UsingSQLServer(string ROdir)
		{
			bool Rtn = false;
			string RtnStr;
			string ROiniPath = ROdir + "\\ROAPP.INI";
			IniReader ini = new IniReader(ROiniPath);
			RtnStr = ini.ReadString("Database Server","Path","");
			if (RtnStr.Length > 1)
				Rtn = true;
			return Rtn;
		}

		static bool CheckForDataConversion(string ROdir)
		{
			bool Rtn = true;
			// Check to see if we need to convert Old RO data
			if (ROdir != null)
			{
				string testParadoxFile = ROdir;
				string testAccessFile = ROdir;
				if (!ROdir.Equals(""))
				{
					testParadoxFile += "\\";
					testAccessFile += "\\";
				}
				
				testParadoxFile += "ROMASTER.DB"; // Paradox file
				testAccessFile += "ROMaster.mdb"; // Access file
//				if (File.Exists(testParadoxFile))
				if (File.Exists(testParadoxFile) && !(File.Exists(testAccessFile) || UsingSQLServer(ROdir)))
				{
					// Display a message to the user that the data needs converted
					DialogResult AnswerYN;
					AnswerYN = MessageBox.Show("The RO data needs to be converted for the New RO Editor.\n\n Proceed with the data conversion?","RO Editor",MessageBoxButtons.YesNo);
					if (AnswerYN == DialogResult.Yes)
					{
						// Convert old RO Data
						string argstr = ROdir;
						if (ROdir.Equals(""))
							argstr = Directory.GetCurrentDirectory();
						string ConversionExePath = Application.StartupPath + "\\ParadoxConversion.exe ";
						
						// Need to move out of RO directory to convert it
						Directory.SetCurrentDirectory("..\\");
						
						// create a process & wait until it exits.
						Process myProcess = new Process();
						myProcess.StartInfo.FileName = ConversionExePath;
						myProcess.StartInfo.Arguments=argstr;
			
						myProcess.Start();
						myProcess.WaitForExit();

						Directory.SetCurrentDirectory(argstr);
					}
					else
						Rtn = false;
				}
			}
			return Rtn;
		}

		private void menuROSave_Click(object sender, System.EventArgs e)
		{
			tbar_SaveClick();
		}

		private void menuROExit_Click(object sender, System.EventArgs e)
		{
			Close();
			Application.Exit(); // Exit() does not run the destructors
		}

		/*
		 * If the xml data becomes inconsistent with the tree view, reload the first
		 * level.
		 */
		private void CleanUpTree(VlnXmlElement curelem, TreeNode nd)
		{
			// Unload any children because data may have changed and it can be
			// reloaded.
			nd.Collapse();
			int cnt = nd.Nodes.Count;
			bool add_dummykid = false;
			if (cnt > 0) add_dummykid = true;
			for (int i=0; i<cnt; i++)
				nd.Nodes[0].Remove();
			// if haskids & kids loaded, delete them and add a VLN_DUMMY_FOR_TREE in the
			// tree control if there isn't one. This will sink up tree with xml tree in 
			// case group definition needed to read in any of the subtree to reset
			// fieldnames, menutitles, or accessory page id data.
			string haskids, kidsloaded;
			haskids = curelem.GetAttribute("HasChild");
			kidsloaded = curelem.GetAttribute("ChildLoaded");
			if (haskids == "True" && kidsloaded == "True" )
			{
				VlnXmlElement kid, delkid;
				XmlNode ndkid;
				ndkid = curelem.FirstChild;
				while (ndkid != null)
				{
					delkid = null;
					if (ndkid is VlnXmlElement)
					{
						kid = (VlnXmlElement) ndkid;
						if (kid.HasAttribute("RecID"))delkid = kid;
					}
					ndkid = ndkid.NextSibling;
					if (delkid != null) curelem.RemoveChild(delkid);
				}
				curelem.SetAttribute("ChildLoaded", "False");
			}
			if (add_dummykid)
			{
				TreeNode subch = new TreeNode("VLN_DUMMY_FOR_TREE");
				//roTreeView.SelectedNode.Nodes.Add(subch);
				nd.Nodes.Add(subch);
			}
		}

		private void menuROProperties_Click(object sender, System.EventArgs e)
		{
			roListView_ClearListDisplay();
			bool didcleanup=false;  // flags whether we needed to remove elements from trees
			// to match xml data to tree.
			VlnXmlElement curelem = (VlnXmlElement) roTreeView.SelectedNode.Tag;
			LoadKids(roTreeView.SelectedNode);
			if (curelem.Name == "vlnGroup") 
			{
				GroupDefFrm grdef = new GroupDefFrm(curelem,myrodb,roTreeView.SelectedNode.Text,-1);
				grdef.ShowDialog();

				// if the group text was modified, update the tree. If it was a subgroup,
				// tree nodes are deleted and reread in.
				if (curelem.ParentNode != null && curelem.ParentNode.Name == "RO_Root") 
					roTreeView.SelectedNode.Text = CvtFldToUserFld(curelem.FirstChild.Value);
				// menu, field or accpageid changes may have had to load data which
				// makes the xmltree not be in sync with the tree control. if so clear it.
				if (curelem.HasAttribute("TreeNotData"))
				{
					didcleanup = true;
					CleanUpTree(curelem, roTreeView.SelectedNode);
					curelem.RemoveAttribute("TreeNotData");
				}
				VlnXmlElement topele = (VlnXmlElement) rootXml.FirstChild;
				while (topele != null)
				{
					if (topele.HasAttribute("TreeNotData")) 
					{
						topele.RemoveAttribute("TreeNotData");
						int cnt = rootNode.GetNodeCount(false);
						for(int i=0;i<cnt;i++)
						{
							TreeNode nd = rootNode.Nodes[i];
							if (nd.Tag == topele)
							{
								didcleanup = true;
								CleanUpTree(topele,nd);
							}
						}
					}
					topele = (VlnXmlElement) topele.NextSibling;
				}
				// if a fieldname changed, we may even have to check the 'top' group nodes
				
				this.roTreeView.Refresh();
				if (didcleanup) roTreeView_ClearEditDisplay(false);
			}
		
		}

		/*
		 * Create a new RO Group
		 */
		private void menuNewGroup_Click(object sender, System.EventArgs e)
		{
			VlnXmlElement curelem = (VlnXmlElement) roTreeView.SelectedNode.Tag;
			// if this is being added from the top, do a new table and main group.
			// otherwise, handle like a new ro.
			if (curelem.Name == "RO_Root")
			{
				GroupNewFrm grnew = new GroupNewFrm(myrodb, curelem);
				grnew.ShowDialog();
				VlnXmlElement topele;
				topele = (VlnXmlElement) curelem.FirstChild;
				// see if new element(s) to add to tree control
				while (topele != null)
				{
					if (topele.HasAttribute("TreeNotData")) 
					{
						topele.RemoveAttribute("TreeNotData");
						TreeNode topnd = new TreeNode(topele.GetAttribute("MenuTitle"),ROGROUPIMAGE,ROGROUPIMAGE);
						topnd.Tag = topele;
						roTreeView.SelectedNode.Nodes.Add(topnd);
						roTreeView.Refresh();
						updateRoListView(roTreeView.SelectedNode);
					}
					topele = (VlnXmlElement) topele.NextSibling;
				}
				return;
			}

			XmlSchema myschema = myrodb.RODB_GetGroupSchema(curelem);
			if (myschema==null)
			{
				MessageBox.Show("Subgroup Definition does not exist, check Subgroup Definition under Properties for the Group that contains this Subgroup.");
				return;
			}
			VlnXmlElement nelem = (VlnXmlElement) curelem.OwnerDocument.CreateElement("vlnGroup");
			if (curelem.Name != "vlnGroup") // selected new group off ro, add to parent
			{
				curelem.ParentNode.AppendChild((XmlNode) nelem);
				TreeNewparent=roTreeView.SelectedNode.Parent;
			}
			else
			{	
				curelem.AppendChild(nelem);
				TreeNewparent=roTreeView.SelectedNode;
			}
			newone = nelem;
			
			ArrayList reqfields = curelem.GetRequiredFields();
			int retval = roTreeView_ClearEditDisplay(false);
			if (retval == -1) return;
			roListView_ClearListDisplay();
			CreateCtlXmlEdit2(nelem,myschema,reqfields);
			tbtnSave.Enabled=false; // initial disable the save button	
			ctlXMLEdit2.Focus();
			tbtnZoom.Enabled = false;
			tbtnCancel.Enabled = true;
		}

		/*
		 * Create a new RO value
		 */
		private void menuNewRefObj_Click(object sender, System.EventArgs e)
		{
			int retval = roTreeView_ClearEditDisplay(false);
			if (retval == -1) return;
			roListView_ClearListDisplay();
			VlnXmlElement curelem = (VlnXmlElement) roTreeView.SelectedNode.Tag;
			// get the schema for this element
			XmlSchema myschema = myrodb.RODB_GetSchema(curelem);
			// make a dummy parent which is the 'group' level so that it can be
			// associated with a schema.
			XmlNode parent = curelem.ParentNode;
			VlnXmlElement nmele=curelem;
			while(parent.Name != "RO_Root")
			{
				nmele = (VlnXmlElement) parent;
				parent = (VlnXmlElement) parent.ParentNode;
			}

			// get the name for the new element...
			int indx = nmele.InnerXml.IndexOf("<");
			string nm = null;
			if (indx<0)  // not found, just use innerxml
				nm = nmele.InnerText;
			else
				nm = nmele.InnerXml.Substring(0,indx);
			VlnXmlElement nelem = (VlnXmlElement) curelem.OwnerDocument.CreateElement(CvtUserFldToFld(nm));
			if (curelem.Name != "vlnGroup") // selected new ro off ro, add to parent
			{
				curelem.ParentNode.AppendChild((XmlNode) nelem);
				TreeNewparent = roTreeView.SelectedNode.Parent;
			}
			else
			{
				curelem.AppendChild(nelem);
				TreeNewparent = roTreeView.SelectedNode;
			}
			newone = nelem;
			ArrayList reqfields = nelem.GetRequiredFields();
			
			CreateCtlXmlEdit2(nelem,myschema,reqfields);
			tbtnSave.Enabled=false; // initial disable the save button
			ctlXMLEdit2.Focus();
			tbtnZoom.Enabled = false;
			tbtnCancel.Enabled = true;
		}
		/*
		 *Delete currently selected RO Group or RO Value
		 */
		private void menuRODelete_Click(object sender, System.EventArgs e)
		{
			bool success=false;
			XmlNode nd = (XmlNode) roTreeView.SelectedNode.Tag;
			if (nd.ParentNode.Name == "RO_Root")
				success = myrodb.RODB_DeleteGroup(nd,null,null);
			else
				success = myrodb.RODB_DeleteRO(nd);
			if (success == true)
			{
				// remove from xml tree & the tree control
				XmlNode parent = nd.ParentNode;
				parent.RemoveChild(nd);	
				updateRoListView(roTreeView.SelectedNode.Parent);
				roTreeView.SelectedNode.Remove();
				roTreeView.Refresh();	
			}
		}

		/*
		 * Cut text from current text box to windows clipboard
		 */
		private void menuEditCut_Click(object sender, System.EventArgs e)
		{
			if (CurrentTextBox != null)
			{
				CurrentTextBox.Cut();
				this.menuEditCopy.Enabled = false;
				this.menuEditCut.Enabled = false;
				this.menuEditPaste.Enabled = true;
				this.menuEditDelete.Enabled = false;
				this.menuEditSelAll.Enabled = false;
				this.menuEditUndo.Enabled = true;
			}
		
		}
 
		/*
		 * Copy text from current text box to windows clipboard
		 */
		private void menuEditCopy_Click(object sender, System.EventArgs e)
		{
			if (CurrentTextBox != null)
			{
				CurrentTextBox.Copy();
			}
		}

		/*
		 * Paste from windows clipborad to the current text box
		 */
		private void menuEditPaste_Click(object sender, System.EventArgs e)
		{
			if (CurrentTextBox != null)
			{
				CurrentTextBox.Paste();
				this.menuEditCopy.Enabled = false;
				this.menuEditCut.Enabled = false;
				this.menuEditPaste.Enabled = true;
				this.menuEditDelete.Enabled = false;
				this.menuEditSelAll.Enabled = true;
				this.menuEditUndo.Enabled = true;
			}
		}

		/*
		 * Create The RO.FST file
		 */
		private void menuToolsROFST_Click(object sender, System.EventArgs e)
		{
			Cursor.Current = Cursors.WaitCursor;
			RO_FST ROFST = new RO_FST(myrodb,myroXmlDoc);
			ROFST.Create();
			VlnXmlElement topele = (VlnXmlElement) rootXml.FirstChild;
			while (topele != null)
			{
				if (topele.HasAttribute("TreeNotData")) 
				{
					topele.RemoveAttribute("TreeNotData");
					int cnt = rootNode.GetNodeCount(false);
					for(int i=0;i<cnt;i++)
					{
						TreeNode nd = rootNode.Nodes[i];
						if (nd.Tag == topele)
						{
							CleanUpTree(topele,nd);
						}
					}
				}
				topele = (VlnXmlElement) topele.NextSibling;
			}
			// if a fieldname changed, we may even have to check the 'top' group nodes
				
			this.roTreeView.Refresh();
			roTreeView_ClearEditDisplay(false);
			Cursor.Current = Cursors.Default;
		}

		/*
		 * Show Help About dialog
		 */
		private void menuHelpAbout_Click(object sender, System.EventArgs e)
		{
			//AboutDlg dlg = new AboutDlg();
			AboutROEditor dlg = new AboutROEditor();
			dlg.ShowDialog();
		}

		/*
		 * Edit the text fields associated with the current tree node
		 */
		private void menuROEdit_Click(object sender, System.EventArgs e)
		{
			roTreeView_OnDoubleClick (sender, e);
		}


		/*
		 * Undo text changes in the current text box
		 */
		private void menuEditUndo_Click(object sender, System.EventArgs e)
		{
			if (CurrentTextBox != null)
			{
				CurrentTextBox.Undo();
				CurrentTextBox.ClearUndo();
				this.menuEditCopy.Enabled = true;
				this.menuEditCut.Enabled = true;
				this.menuEditPaste.Enabled = true;
				this.menuEditDelete.Enabled = true;
				this.menuEditSelAll.Enabled = (CurrentTextBox.TextLength != CurrentTextBox.SelectionLength);
				this.menuEditUndo.Enabled = false;
			}

		}

		/*
		 * Clear the text in the current text box
		 */
		private void menuEditDelete_Click(object sender, System.EventArgs e)
		{
			if (CurrentTextBox != null)
			{
				DialogResult dr = MessageBox.Show("You will not be able to Undo this delete.\n Continue with delete?","Warning:",MessageBoxButtons.YesNo,MessageBoxIcon.Warning);

				if (dr == DialogResult.Yes)
				{
					CurrentTextBox.Clear();
					this.menuEditCopy.Enabled = false;
					this.menuEditCut.Enabled = false;
					this.menuEditPaste.Enabled = true;
					this.menuEditDelete.Enabled = false;
					this.menuEditSelAll.Enabled = false;
					this.menuEditUndo.Enabled = false;
				}
			}

		}

		/*
		 * Delete all the text in the current text box
		 */
		private void menuEditSelAll_Click(object sender, System.EventArgs e)
		{
			if (CurrentTextBox != null)
			{
				CurrentTextBox.SelectAll();
				this.menuEditCopy.Enabled = true;
				this.menuEditCut.Enabled = true;
				this.menuEditPaste.Enabled = true;
				this.menuEditDelete.Enabled = true;
				this.menuEditSelAll.Enabled = false;
			}

		}

		/*
		// Tool Bar Support
		 */

		private void tbar_OnClick(object obj, ToolBarButtonClickEventArgs tbbcea)
		{
			ToolBarButton tbb = tbbcea.Button;
			
			// see which event should be called.
			if (tbb.Text == "Cancel")
				tbar_CancelClick();
			else if (tbb.Text == "Save")
				tbar_SaveClick();
			else if (tbb.Text == "Save As")
				tbar_SaveAsClick();
			else if (tbb.Text == "Duplicate")
				tbar_DuplicateClick();
			else if (tbb.Text == "Restore")
				tbar_RestoreClick();
			else if (tbb.Text == "Zoom"||tbb.Text == "View Image")
				ctlXMLEdit2.btnZoom_click(null, null);
		}

		private void tbar_RestoreClick()
		{
			ctlXMLEdit2.RestoreData();
			tbtnRestore.Enabled = false;
			tbtnDuplicate.Enabled = true;
			tbtnSave.Enabled = false;
			tbtnSaveAs.Enabled = false;
			duplicate_active = false;
		}

		private void tbar_CancelClick()
		{
			if (newone != null)
			{
				XmlNode parent = newone.ParentNode;
				parent.RemoveChild(newone);
				newone = null;
			}
			roTreeView_ClearEditDisplay(true);
		}

		private bool SaveRO(ref TreeNode newt)
		{
			bool success;
			success = ctlXMLEdit2.SaveData();
			if (!success)
			{
				MessageBox.Show("Save Failed");
				return false;
			} 
			VlnXmlElement myro;
			if (newone != null)
				myro = newone;
			else
				myro = (VlnXmlElement)roTreeView.SelectedNode.Tag;
			string mnutmp;
			if (myro.Name != "vlnGroup")
			{	
				mnutmp = myro.GetMenuValueTemplate("MenuItem");
				// check for duplicates on accessory page id, if it changed.
				string acctmpl = myro.GetAccPageIDTemplate();
				string newacc = myro.GetAccPageIDString(acctmpl);
				if (newacc==null)return false;
				if (newone != null)  // if this is new, set the table for accpageid check
				{
					XmlNode nd = (XmlNode) myro.ParentNode;
					VlnXmlElement end = (VlnXmlElement) nd;
					string tb = end.GetAttribute("Table");
					myro.SetAttribute("Table",tb);
				}
				string t1 = newacc.Trim();
				string t2 = myro.GetAttribute("AccPageID");
				string t3 = t2.Trim();
				if (t1 != t3)
				{
					if (myrodb.IsDuplicateAccPageID(myro,newacc)== true)
					{
						MessageBox.Show("The fields used for the \"Accessory Pages Access\" values must be unique. The fields used in these values can be found under \"Properties\" of an RO Group. Cannot save.","Problem saving data");
						return false;
					}
					myro.SetAttribute("AccPageID", myro.GetAccPageIDString(acctmpl));
				}
			}
			else
				mnutmp = myro.GetMenuValueTemplate("GroupMenuItem");
			string mnutitle = myro.GetMenuString(mnutmp, false);

			success = myro.IsDuplicateMenuTitle(mnutitle);
			if (success==true)   // just reuse boolean, true means it's duplicate
			{
				MessageBox.Show("The fields used for the \"Menu\" values must be unique. The fields used in these values can be found under \"Properties\" of an RO Group. Cannot save.","Problem saving data");
				return false;
			}

			myro.SetAttribute("MenuTitle",mnutitle);

			// If this doesn't have a recid, insert it.
			if (newone != null)
			{
				success = myrodb.RODB_InsertRO(myro);
				if (success == true)
				{
					int img = (myro.Name=="vlnGroup")?ROGROUPIMAGE:ROIMAGE;
					newt = new TreeNode(mnutitle,img,img);
					newt.Tag = myro;
					TreeNewparent.Nodes.Add(newt);
				}
			}
			else
			{
				newt=null;
				success = myrodb.RODB_WriteRO((VlnXmlElement)roTreeView.SelectedNode.Tag);
				if (success==true) roTreeView.SelectedNode.Text = mnutitle;
			}
			newone = null;
			return true;
		}

		private void tbar_SaveClick()
		{
			// if duplicate was created, then save it as a new RO.
			if (duplicate_active)
			{
				tbar_SaveAsClick();
				return;
			}
			bool success;
			TreeNode newtree = null;

			success = SaveRO(ref newtree);
			if (success == false) return;

			if (newtree != null)
			{
				newtree.TreeView.SelectedNode = newtree;
				roTreeView.Refresh();
			}
			else
				roTreeView.Refresh();
	
			tbtnCancel.Enabled = true;
			tbtnDuplicate.Enabled = true;
			tbtnRestore.Enabled=false;
			tbtnSave.Enabled = false;
			tbtnSaveAs.Enabled = false;
			menuROSave.Enabled = false;
		}

		private void tbar_SaveAsClick()
		{
			bool dup;
			bool success;
			VlnXmlElement newro = (VlnXmlElement) roTreeView.SelectedNode.Tag;
			VlnXmlElement origro = (VlnXmlElement) newro.Clone();
			XmlNode parent = newro.ParentNode;
			success = ctlXMLEdit2.SaveData();
			if (!success)
			{
				tbtnRestore.Enabled = false; // old data may not be around
				MessageBox.Show("Save Failed");
				return;
			}
			
			string mnutmp;
			// set attributes for access id, retval (if RRO) and menu value for
			// rro and group.
			string acctmpl = null;
			string savrec = newro.GetAttribute("RecID");
			if (newro.Name != "vlnGroup")
			{	
				mnutmp = newro.GetMenuValueTemplate("MenuItem");
				// check for duplicates on accessory page id, if it changed.
				acctmpl = newro.GetAccPageIDTemplate();
				string newacc = newro.GetAccPageIDString(acctmpl);
				
				//isduplicateaccpageid needs no recid attribute for any new
				// ros (which is what we have hear for saveas or duplicate)
				newro.RemoveAttribute("RecID");
				dup = myrodb.IsDuplicateAccPageID(newro,newacc);
				newro.SetAttribute("RecID",savrec);
				if (dup==true)
				{
					MessageBox.Show("The fields used for the \"Accessory Pages Access\" values must be unique. The fields used in these values can be found under \"Properties\" of an RO Group. Cannot save.","Problem saving data");
					ctlXMLEdit2.SetNotSaved();
					tbtnRestore.Enabled = false;  // can't restore data, may have saved
					return;
				}
			}
			else
				mnutmp = newro.GetMenuValueTemplate("GroupMenuItem");
			string mnutitle = newro.GetMenuString(mnutmp, false);
			parent.AppendChild((XmlNode) origro);  // need this for duplicate check.
			dup = newro.IsDuplicateMenuTitle(mnutitle);
			if (dup==true)
			{
				MessageBox.Show( "The fields used for the \"Menu\" values must be unique. The fields used in these values can be found under \"Properties\" of an RO Group. Cannot save.","Problem saving data");
				parent.RemoveChild(origro);
				tbtnRestore.Enabled = false;  
				ctlXMLEdit2.SetNotSaved();
				return;
			}
			if (acctmpl!=null)newro.SetAttribute("AccPageID", newro.GetAccPageIDString(acctmpl));	
			newro.SetAttribute("MenuTitle",mnutitle);
			newro.RemoveAttribute("RecID");  // get a new one.
			success = myrodb.RODB_InsertRO(newro);
			if (success == true)
			{
				int img = (newro.Name=="vlnGroup")?ROGROUPIMAGE:ROIMAGE;
				TreeNode newt = new TreeNode(mnutitle,img,img);
				newt.Tag = newro;
				roTreeView.SelectedNode.Parent.Nodes.Add(newt);
				roTreeView.SelectedNode.Tag = origro;
				LastSelectedNode = newt;   //do this so that no prompt for data save on node select
				newt.TreeView.SelectedNode = newt;
				roTreeView.Refresh();
				tbtnRestore.Enabled=false;
				tbtnSave.Enabled = false;
				tbtnCancel.Enabled = true;
				tbtnSaveAs.Enabled = false;
				tbtnDuplicate.Enabled = true;
				duplicate_active = false;
			}
			else
				newro.SetAttribute("RecID",savrec);
			
			newone = null;
		}

		private void tbar_DuplicateClick()
		{
			duplicate_active = true;
			// disable duplicate until save or saveas.
			tbtnDuplicate.Enabled = false;
		}

		protected void tbar_ZoomClick (object sender,	System.EventArgs e)
		{
			ctlXMLEdit2.btnZoom_click(sender, e);

		}

		///////////////////  List view support /////////////
		///

		private void roListView_OnDoubleClick(object sender, System.EventArgs e)
		{
			bool attop = false;
			// syncronize this with the tree.
			ListView.SelectedListViewItemCollection itemList = roListView.SelectedItems;
			ListViewItem item = itemList[0];

			TreeNode selectedNode = roTreeView.SelectedNode;
			selectedNode.Expand();

			// Find the node in the tree view, select it & expand it.
			// The menu title is always what was in the tree view.
			VlnXmlElement ele = (VlnXmlElement)item.Tag;
			string mnutitle;
			if (ele.ParentNode != null && ele.ParentNode.Name == "RO_Root")
			{
				attop = true;
				mnutitle = CvtFldToUserFld(ele.FirstChild.Value);
			}
			else
				mnutitle = ele.GetAttribute("MenuTitle");
			foreach (TreeNode searchNode in selectedNode.Nodes)
			{
				if (searchNode.Text.Equals(mnutitle))
				{
					roTreeView.SelectedNode = searchNode;
					searchNode.Expand();

					updateRoListView(searchNode);
					break;
				}
			}
			if (ele.Name != "vlnGroup" && attop==false) 
				EditRO(ele);	
		}


		private void DisplayGroupElements(VlnXmlElement selele)
		{
			ROField rof;
			string nm, tmp=null;
			roListView.Clear();
			bool AllGroups = true;
			ArrayList InUseList = null;
			// Create a column header (in case the list is being displayed in Details view)
			if (selele.Name != "RO_Root")
			{
				ArrayList AvailList = myrodb.RODB_GetFields(selele, 0);
				InUseList = myrodb.RODB_GetFieldsInUse(selele, AvailList, "FieldsInUse", ref tmp, true);
			}

			// Put out fields and their associated data.
			if (InUseList != null) 
			{
				for (int i=0; i< InUseList.Count; i++)
				{
					rof = (ROField) InUseList[i];
					if (rof.GetFieldname != null)
					{
						uint ftype = rof.GetFieldType;
						if (ftype == 1 || ftype == 2 || ftype==4 || ftype==128)
							roListView.Columns.Add(rof.GetFieldname, 100,HorizontalAlignment.Left);
					}
				}
			}
			// now add data.
			XmlNode nd;
			string str;
			XmlNode curnd = selele.FirstChild;
			while (curnd != null)
			{
				if (curnd is VlnXmlElement)
				{
					VlnXmlElement curele = (VlnXmlElement) curnd;
					if (curele.Name == "vlnGroup")
					{
						if (selele.Name == "RO_Root")
							str = CvtFldToUserFld(curele.FirstChild.Value);
						else
							str = curele.GetAttribute("MenuTitle");
						ListViewItem item = new ListViewItem(str, ROGROUPIMAGE);
						roListView.Items.Add(item);
						item.Tag = curele;
					}
					else
					{
						int levelcnt = curele.ChildNodes.Count;
						string TheMenuTitle = curele.GetAttribute("MenuTitle");
						if ((levelcnt > 1) || (levelcnt==1 && !TheMenuTitle.Equals("")))
						{
							AllGroups = false;
							ListViewItem item=null;
							bool first = true;
							for (int i=0; i< InUseList.Count; i++)
							{
								rof = (ROField) InUseList[i];
								if (rof.GetFieldname != null)
								{
									uint ftype = rof.GetFieldType;
									if (ftype == 1 || ftype == 2 || ftype == 4 || ftype == 128)
									{
										string nm0 = rof.GetFieldname;
										nm = rof.MakeFieldName(nm0);
										nd = curele.SelectSingleNode(nm);
										if (nd==null)nd = curele.SelectSingleNode("*/"+nm);
										if (nd==null)
											nd = curele.GetCurrentOfMultiFields(curele,nm);
//										if (nd==null)nd = curele.SelectSingleNode(nm+"a");
//										if (nd==null)nd = curele.SelectSingleNode(nm+"b");
//										if (nd==null)nd = curele.SelectSingleNode(nm+"c");
//										if (nd==null)nd = curele.SelectSingleNode(nm+"d");
										string data;
										if(nd==null)
											data=" ";
										else
											data=nd.InnerText;
										if(first==true)
										{
											item = new ListViewItem(data,ROIMAGE);
											first=false;
											item.Tag = curele;
										}
										else
											item.SubItems.Add(data);
									}
								}
							}
							roListView.Items.Add(item);
						}
					}
				}
				curnd = curnd.NextSibling;				
			}
			if (AllGroups == true)
			{
				roListView.Columns.Clear();
				roListView.Columns.Add("Group",250,HorizontalAlignment.Left);
			}
			
			roListView.Visible=true;
		}
		
		private void updateRoListView(TreeNode node)
		{
			VlnXmlElement selele;
			selele = (VlnXmlElement) node.Tag;
			if (selele.Name != "vlnGroup" && selele.Name != "RO_Root")
			{
				// if we already have a list view, and we're still under the same parent,
				// leave the list view, otherwise clear it.
				VlnXmlElement curele = null;
				if (roListView != null && roListView.Items.Count > 0) 
				{
					curele = (VlnXmlElement) roListView.Items[0].Tag;
					if (selele.ParentNode != curele.ParentNode)roListView_ClearListDisplay();
				}
				return;
			}
			else
			{
				if (roListView == null)
				{
					this.roListView = new System.Windows.Forms.ListView();
					this.panel1.Controls.Add(roListView);
					this.roListView.Dock = System.Windows.Forms.DockStyle.Fill;
					this.roListView.LargeImageList = this.imageListRoTree;
					this.roListView.Name = "roListView";
					this.roListView.Size = new System.Drawing.Size(688, 700);
					this.roListView.AllowColumnReorder = true;
					this.roListView.FullRowSelect = true;
					this.roListView.SmallImageList = this.imageListRoTree;
					this.roListView.TabIndex = 5;
					this.roListView.DoubleClick += new System.EventHandler(this.roListView_OnDoubleClick);
					this.roListView.View = View.Details;
					MyListViewComparer LVCompare = new MyListViewComparer();
					this.roListView.ListViewItemSorter = LVCompare;
					roListView.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.roListView_Column_Header_OnClick);
				}
				
				DisplayGroupElements(selele);
			}

		}

		void roListView_Column_Header_OnClick(object sender, ColumnClickEventArgs e)
		{
			int indx = e.Column;
			MyListViewComparer LVCompare = (MyListViewComparer) roListView.ListViewItemSorter;
			LVCompare.SetColumnToSortBy(indx);
			roListView.Sort();
		}

		private void roTreeView_AfterSelect_1(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
		
		}
	}
	
	// This class is used to sort by the selected list view column
	public class MyListViewComparer : IComparer
	{
		int column;

		public int Compare (object x, object y)
		{
			ListViewItem xitm = (ListViewItem) x;
			ListViewItem yitm = (ListViewItem) y;

			string xbuff = xitm.SubItems[column].Text;
			string ybuff = yitm.SubItems[column].Text;
			int rtnval = 0;
			int xcnt=0,ycnt=0;
			int xlen,ylen;
			byte xbyte, ybyte;
			xlen = xbuff.Length;
			ylen = ybuff.Length;
			if (xbuff[0] == '<')
				rtnval = 0;
			if (ybuff[0] == '<')
				rtnval = 0;
			while ((rtnval==0) && ((xcnt < xlen) || (ycnt < ylen)))
			{
				xbyte = (xcnt == xlen)? (byte)0 : (byte)xbuff[xcnt++];
				ybyte = (ycnt == ylen)? (byte)0 : (byte)ybuff[ycnt++];
				rtnval = xbyte - ybyte;
			}
				
			return rtnval;
		}

		public void SetColumnToSortBy(int col)
		{
			column = col;
		}
		
	}
	
}
