/*********************************************************************************************
 * 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 description for Form1.
	/// 
	///
	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
		public TextBox CurrentTextBox
		{
			get { return _CurrentTextBox; }
			set { _CurrentTextBox = value; }
		}
		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 bool duplicate_active
		{
			get { return _duplicate_active; }
			set
			{
				_duplicate_active = value;
			// C2015-017 hide the label indicating user is working with a duplicate of an exiting RO
				lblDuplicateRO.Visible = value;
			}
		}
		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 Label lblDuplicateRO;
		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);
			// RODB_ReadRO will return a NULL if the RO cannot be found
			// Pop up a message box to notify the user.
			// This will leave the RO Editor open.  The user can continue to work or just close it.
			if (spro == null)
			{
				MessageBox.Show("Could not find this RO", "RO Not Found", MessageBoxButtons.OK);
				return;
			}
			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 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  
			{
				// B2017-015: if editing a group/subgroup, use the parent's schema to get the fields to edit for the menuing.   
				VlnXmlElement sch = curelem;
				if (curelem.ParentNode.Name != "RO_Root") sch = (VlnXmlElement) sch.ParentNode;
				myschema = myrodb.RODB_GetGroupSchema(sch);
				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);
		}
		/// 
		/// Clean up any resources being used.
		/// 
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}
		#region Windows Form Designer generated code
		/// 
		/// Required method for Designer support - do not modify
		/// the contents of this method with the co`de editor.
		/// 
		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.lblDuplicateRO = new System.Windows.Forms.Label();
			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(220, 28);
			this.splitter1.Name = "splitter1";
			this.splitter1.Size = new System.Drawing.Size(8, 591);
			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(228, 28);
			this.panel1.Name = "panel1";
			this.panel1.Size = new System.Drawing.Size(588, 591);
			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(235, 118);
			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, 28);
			this.roTreeView.Name = "roTreeView";
			this.roTreeView.SelectedImageIndex = 0;
			this.roTreeView.Size = new System.Drawing.Size(220, 591);
			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, 28);
			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, "");
			// 
			// lblDuplicateRO
			// 
			this.lblDuplicateRO.AutoSize = true;
			this.lblDuplicateRO.ForeColor = System.Drawing.Color.Red;
			this.lblDuplicateRO.Location = new System.Drawing.Point(491, 9);
			this.lblDuplicateRO.Name = "lblDuplicateRO";
			this.lblDuplicateRO.Size = new System.Drawing.Size(139, 13);
			this.lblDuplicateRO.TabIndex = 6;
			this.lblDuplicateRO.Text = "Working With Duplicate RO";
			this.lblDuplicateRO.Visible = false;
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(816, 619);
			this.Controls.Add(this.lblDuplicateRO);
			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);
		/// 
		/// The main entry point for the application.
		/// 
		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)
			{
				// The ROEditor.OWN file assures that only one individual at a time can edit the RO database.  
				// The file is opened and kept open while the user is editing the database.  The contents of the
				// file will identify the current user and state when the edit session began.
				try 
				{
					fiown = new FileInfo("RoEditor.own");
					try {
						// Try to delete the owner file.  If another process has the file open, this delete will fail.
						// If the file is closed, it will be deleted, and the user will be placed in the editor.  The users
						// name and the time when this session began will be placed in the owner file.
						fiown.Delete(); 
					}
					catch(Exception ex)
					{
						fsown = fiown.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
						TextReader tr1 = new StreamReader(fsown);
						string who1 = tr1.ReadToEnd();
						MessageBox.Show(ex.Message + "\r\n\r\n" + who1, "RO Editor In Use", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
					}
					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 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;
		}
		
	}
	
}