2013-03-25 20:33:33 +00:00

3074 lines
77 KiB
C#

/*********************************************************************************************
* Copyright 2005 - Volian Enterprises, Inc. All rights reserved.
* Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
* ------------------------------------------------------------------------------
* $Workfile: ROFST.cs $ $Revision: 13 $
* $Author: Kathy $ $Date: 8/31/05 11:32a $
*
* $History: ROFST.cs $
*
* ***************** Version 13 *****************
* User: Kathy Date: 8/31/05 Time: 11:32a
* Updated in $/LibSource/ROFST
* B2005-032: new groups crashed when writing to ro.fst during approve
* sel.
*
* ***************** Version 12 *****************
* User: Kathy Date: 8/16/05 Time: 2:52p
* Updated in $/LibSource/ROFST
* B2005-030: crash when writing ro.fst for new ro
*
* ***************** Version 11 *****************
* User: Kathy Date: 6/21/05 Time: 1:36p
* Updated in $/LibSource/ROFST
* FindModROs for approve selected, crash on xyplot with missing end ">"
*
* ***************** Version 10 *****************
* User: Jsj Date: 6/02/05 Time: 11:31a
* Updated in $/LibSource/ROFST
* fix for approving with conditional ROs
*
* ***************** Version 9 *****************
* User: Jsj Date: 5/20/05 Time: 9:21a
* Updated in $/LibSource/ROFST
* fixed getro for cases when using unit specific info to process the RO
* return value.
*
* ***************** Version 8 *****************
* User: Jsj Date: 5/17/05 Time: 11:48a
* Updated in $/LibSource/ROFST
* fixed approve graphic bug, added default graphic extension as part of
* ROFST class initialization, code cleanup
*
* ***************** Version 7 *****************
* User: Kathy Date: 5/11/05 Time: 9:26a
* Updated in $/LibSource/ROFST
* add close method
*
* ***************** Version 6 *****************
* User: Jsj Date: 4/07/05 Time: 11:15a
* Updated in $/LibSource/ROFST
* fixes
*
* ***************** Version 5 *****************
* User: Jsj Date: 3/31/05 Time: 9:16a
* Updated in $/LibSource/ROFST
*
* ***************** Version 4 *****************
* User: Jsj Date: 3/28/05 Time: 12:18p
* Updated in $/LibSource/ROFST
*
* ***************** Version 3 *****************
* User: Jsj Date: 3/22/05 Time: 9:52a
* Updated in $/LibSource/ROFST
* March 22 2005 update for merge
*
* ***************** Version 2 *****************
* User: Jsj Date: 3/14/05 Time: 1:36p
* Updated in $/LibSource/ROFST
* update
*
* ***************** Version 1 *****************
* User: Jsj Date: 3/10/05 Time: 3:53p
* Created in $/LibSource/ROFST
*
* ***************** Version 1 *****************
* User: Jsj Date: 3/10/05 Time: 3:49p
* Created in $/LibSource/ROFST/ROFST
*
*********************************************************************************************/
using System;
using System.IO;
using System.Windows.Forms;
using System.Text;
using System.Collections;
using VlnStatus;
using Utils;
/*
* This namespace is used in both VE-PROMS and the RO Editor programs.
*/
namespace ROFST_FILE
{
/*
* Globally used functions amoung a few of the classes in this namespace
*/
public class ROProcessTools
{
// For now, have hooks to set and get the current
// procedure number along with the Maxium Procedure
// Number length. The 16-bit code used globals
// jsj - 6/2/2005
private static string PNumber = " "; // default to blank
private static int mxPrcLen = 30; // default to 30 chars
static ROProcessTools()
{
}
public static string ProcedureNumber
{
set { PNumber = value.ToString();}
get { return PNumber; }
}
public static int MaxProcNumLen
{
set { mxPrcLen = (int)value;}
get { return mxPrcLen;}
}
public static string UnitSpecific(string str, int len, int trm, int maxPrcNumLen)
{
// This routine retrieves the procedure number format from the
// current directory and uses it to adjust the procedure number
// in the specified string
string retvalu="";
string asis="#";
string pnum;
if( str == null || str.Length == 0 ) return null;
/*
* Bug fix: B2005-017 3/2/2005
* Need to use the largest procedure number length that's in the
* SET.DFF file. "LargestNumber" is the largest length after the
* procedure number is replaced via the SET.INI file "replace" list.
*
if(len==0)len=LargestNumber;
*/
if(len==0)len=maxPrcNumLen; //LargestRawSetNumber
string mstr;
PrivateProfile proc_ini = new PrivateProfile("proc.ini");
mstr = proc_ini.Attr("unit", "procedure number");
if (mstr == null) mstr = asis;
pnum=mstr;
if(pnum.Equals(asis))
{
retvalu=str;
}
else if (!pnum.Equals("") && pnum[0] == '!')
{
if (File.Exists("set.ini"))
{
string p = str;
string q, tonum;
StringBuilder rbldr = new StringBuilder();
int newl, dw, cnt=0, lstr;
p = p.TrimStart(" ".ToCharArray());
lstr = p.Length;
if (len > lstr) len = lstr;
mstr = p.Substring(0,len);
mstr = mstr.TrimEnd(" \t\r\n".ToCharArray());
/* debug
string debugstr = "|" + mstr + "|";
*/
PrivateProfile set_ini = new PrivateProfile("set.ini");
tonum = set_ini.Attr("replace", mstr);
if (tonum == null || tonum.Equals("")) tonum = mstr;
newl = tonum.Length;
dw = newl - (lstr);
q = str; p = tonum;
int strptr=0;
for (strptr=0; str[strptr] == ' '; strptr++)
rbldr.Append(" ");//initial spaces
int pptr=0;
while (cnt < len)
{
if (tonum!=null && pptr < tonum.Length)
rbldr.Append(tonum[pptr++]);
else if (trm == 1) break;
else if (cnt < lstr) rbldr.Append(" ");
else break;
cnt++;
}
if (trm==0)
{
strptr+=len;
while (str!=null && strptr < str.Length)
rbldr.Append(str[strptr++]);
}
retvalu = rbldr.ToString();
}
else
{
retvalu=str;
}
}
else
{
StringBuilder rbldr = new StringBuilder();
// create pointers to use to transfer info
int pnumPtr = 0, strPtr=0, endStrPtr = str.Length-1;
string pad = "";
// determine if the procedure number should be padded instead
if(str[0]==' ')pad=" ";
// copy from the procedure number definition to the pound symbol
if (!pnum.Equals(""))
{
while(pnumPtr < pnum.Length && pnum[pnumPtr] != '#')
{
rbldr.Append(((!pad.Equals(""))? pad : pnum[pnumPtr].ToString()));
pnumPtr++;
}
// skip the pound sign
if(pnumPtr < pnum.Length && pnum[pnumPtr]!=0)pnumPtr++;
}
// assuming that the procedure number occurs at the beginning of
// str, check to see where it ends
if(str.Length > len)endStrPtr=len-1;
// find the end of the procedure number
while(endStrPtr > strPtr && str[endStrPtr]==' ')endStrPtr--;
// copy the procedure number
while(strPtr <= endStrPtr)rbldr.Append(str[strPtr++]);
// copy the rest of the format
while(pnumPtr < pnum.Length)
{
rbldr.Append(((!pad.Equals(""))? pad : pnum[pnumPtr].ToString()));
pnumPtr++;
}
// copy the rest of the given string
while(strPtr < str.Length)rbldr.Append(str[strPtr++]);
retvalu = rbldr.ToString();
}
return retvalu;
}
public static int matchingBrace(string str)
{
int strptr = 0;
int level=1;
while(level > 0)
{
strptr++;
switch(str[strptr])
{
case '{':
level++;
break;
case '}':
level--;
break;
}
}
return strptr;
}
public static int nextDelimiter(string delim,string str,int l)
{
int nxtdelim = -1;
int strptr = 0;
while(l-- > 0 && (nxtdelim == -1))
{
if (delim.IndexOf(str[strptr])>-1)
nxtdelim = strptr;
strptr++;
}
return nxtdelim;
}
public static string getProfile(string grp, string nam)
{
return getProfile(grp,nam,0);
}
public static string getProfile(string grp, string nam, int flag)
{
string buff=null;
if( grp==null ) return null;
PrivateProfile proc_ini = new PrivateProfile("proc.ini");
buff = proc_ini.Attr(grp,nam);
if (buff == null)
buff = "";
if(buff.Equals(""))
{
if (flag == 0)
buff = "<" + grp + "-" + nam + ">";
else
return null;
}
return buff;
}
public static string evaluate(string str,int len)
{
string retval=null;
string swhir = "PSU"; /* order inwhich to check */
string pn;
if(str[1]=='-')
{
int swptr = swhir.IndexOf((str.ToUpper())[0]);
byte swchar = 0;
if( swptr > -1 ) swchar = (byte)swhir[swptr];
byte sav=(byte)str[len];
str = str.Substring(0,len);
while ((swptr > -1) && (swhir[swptr] != 0) && retval == null)
{
if (swchar == 0) swchar = (byte)str[0];
switch((char)swchar)
{
case 'U':
retval=getProfile("Unit",str.Substring(2),swhir[swptr]);
break;
case 'S':
retval=getProfile("Procedure Set",str.Substring(2),swhir[swptr]);
break;
case 'P':
pn = UnitSpecific(PNumber, 0, 1, mxPrcLen);
retval=getProfile(pn,str.Substring(2),swhir[swptr]);
break;
}
if (retval == null)
swchar= (byte)swhir[++swptr];
}
StringBuilder sb1 = new StringBuilder(str);
sb1.Insert(len,sav);
str = sb1.ToString();
}
else if(len==1 && (str.ToUpper())[0]=='U')
{
retval=getProfile("Unit","Number");
}
else if(len==2 && str.ToUpper().StartsWith("ID"))
{
retval=getProfile("Unit","ID");
}
if(retval == null)
{
retval=str.Substring(0,len+2>str.Length?str.Length:len+2);
}
return retval;
}
}
/// <summary>
/// Summary description for ROFSTHeader.
/// </summary>
public class FST_FileHeader
{
public int hSize; // size of header structure (record)
public short hYear;// year this header was designed (1993)
public byte hMonth;// month this header was designed (10)
public byte hDay;// day this header was designed (25)
public short hcYear;// FST file creation year
public byte hcMonth;// FST file creation month
public byte hcDay;// FST file creation day
public byte hcHour;// FST file creation hour
public byte hcMin;// FST file creation minute
public byte hcSec;// FST file creation seconds
public byte hcHund;// FST file creation hundredth seconds
public uint dboffset;// end of RO data, start of database list
// Constructors
// default constructor creates with zero'd out values
public FST_FileHeader()
{
hSize = 0;
hYear = 0;
hMonth = 0;
hDay = 0;
hcYear = 0;
hcMonth = 0;
hcDay = 0;
hcHour = 0;
hcMin = 0;
hcSec = 0;
hcHund = 0;
dboffset = 0;
}
// Constructor that initializes with pass in values
FST_FileHeader(int Size, short Year, byte Month, byte Day, short cYear, byte cMonth,
byte cDay, byte cHour, byte cMin, byte cSec, byte cHund, uint offset)
{
hSize = Size;
hYear = Year;
hMonth = Month;
hDay = Day;
hcYear = cYear;
hcMonth = cMonth;
hcDay = cDay;
hcHour = cHour;
hcMin = cMin;
hcSec = cSec;
hcHund = cHund;
dboffset = offset;
}
public void Read (BinaryReader br)
{
hSize = br.ReadInt32();
hYear = br.ReadInt16();
hMonth = br.ReadByte();
hDay = br.ReadByte();
hcYear = br.ReadInt16();
hcMonth = br.ReadByte();
hcDay = br.ReadByte();
hcHour = br.ReadByte();
hcMin = br.ReadByte();
hcSec = br.ReadByte();
// byte tbyte = br.ReadByte();
// hcHund = (sbyte)tbyte;
hcHund = br.ReadByte();
dboffset = br.ReadUInt32();
// return new FST_FileHeader(fSize,fYear,fMonth,fDay,
// fcYear,fcMonth,fcDay,fcHour,fcMin,fcSec,fcHund,fdboffset);
}
public void Write (BinaryWriter bw)
{
bw.Write(hSize);
bw.Write(hYear);
bw.Write(hMonth);
bw.Write(hDay);
bw.Write(hcYear);
bw.Write(hcMonth);
bw.Write(hcDay);
bw.Write(hcHour);
bw.Write(hcMin);
bw.Write(hcSec);
bw.Write(hcHund);
bw.Write(dboffset);
}
public int GetStructSize()
{
int rtval = 0;
// You can only use sizeof() in unsafe compiles
// so we'll do it by hand...
// each number is the number of bytes
rtval += 4; //sizeof(hSize);
rtval += 2; //sizeof(hYear);
rtval += 1; //sizeof(hMonth);
rtval += 1; //sizeof(hDay);
rtval += 2; //sizeof(hcYear);
rtval += 1; //sizeof(hcMonth);
rtval += 1; //sizeof(hcDay);
rtval += 1; //sizeof(hcHour);
rtval += 1; //sizeof(hcMin);
rtval += 1; //sizeof(hcSec);
rtval += 1; //sizeof(hcHund);
rtval += 4; //sizeof(dboffset);
return rtval;
}
public void SetHeader(uint offset)
{
hSize = GetStructSize();
hYear = 1993;
hMonth = 10;
hDay = 25;
DateTime dt = DateTime.Now;
hcYear = (short)dt.Year;
hcMonth = (byte)dt.Month;
hcDay = (byte)dt.Day;
hcHour = (byte)dt.Hour;
hcMin = (byte)dt.Minute;
hcSec = (byte)dt.Second;
hcHund = (byte)dt.Millisecond;
dboffset = offset;
}
}
public class ROFST_DbInfo
{
public ushort dbiID; // Number part of table name (RO000002 => 02)
public ushort dbiType; // database type (Setpoint,Graphics,User defined)
public ushort dbiAW; // length of widest AccPageID
public uint dbiGL; // FST file position of this group
public uint dbiIL; // FST file position of list of ROIDs
public uint dbiAL; // FST file position of list of AccPageIDs
public uint dbiEND; // FST file position of the end of this group
// !!! make sure to convert strings to char arrays when writing
public string dbiTitle; // database title
public string dbiAP; // AccPageID Prefix (ex. SP- )
// Constructors
// default constructor creates with zero'd out values
public ROFST_DbInfo()
{
dbiID = 0;
dbiType = 0;
dbiAW = 0;
dbiGL = 0;
dbiIL = 0;
dbiAL = 0;
dbiEND = 0;
dbiTitle = "";
dbiAP = "";
}
// Constructor that initializes with pass in values
ROFST_DbInfo(ushort ID, ushort Type, ushort AW, uint GL, uint IL, uint AL, uint END,
string Title, string dbiAP)
{
dbiID = ID;
dbiType = Type;
dbiAW = AW;
dbiGL = GL;
dbiIL = IL;
dbiAL = AL;
dbiEND = END;
dbiTitle = Title;
dbiAP = dbiAP;
}
public void WriteUntAndShort(BinaryWriter bw)
{
bw.Write(dbiID);
bw.Write(dbiType);
bw.Write(dbiAW);
bw.Write(dbiGL);
bw.Write(dbiIL);
bw.Write(dbiAL);
bw.Write(dbiEND);
}
void WriteString(BinaryWriter bw, string str)
{
byte nullbyte = 0;
byte []wrBytes = new byte[str.Length + 1];
int i;
for(i =0; i < str.Length; i++)
{
// byte WrByte;
// WrByte = (byte)str[i];
// bw.Write(WrByte);
wrBytes[i] = (byte)str[i];
}
wrBytes[i] = nullbyte;
bw.Write(wrBytes);
// bw.Write(nullbyte);
}
public void WriteStrings(BinaryWriter bw)
{
WriteString(bw,dbiTitle);
WriteString(bw,dbiAP);
}
public uint GetStructSize()
{
uint rtval = 0;
// You can only use sizeof() in unsafe compiles
// so we'll do it by hand...
// each number is the number of bytes
rtval += 2; //sizeof(dbiID);
rtval += 2; //sizeof(dbiType);
rtval += 2; //sizeof(dbiAW);
rtval += 4; //sizeof(dbiGL);
rtval += 4; //sizeof(dbiIL);
rtval += 4; //sizeof(dbiAL);
rtval += 4; //sizeof(dbiEND);
rtval += 4; //sizeof(uint); // to simulate the (char *) in the old code (16 datatypes)
rtval += 4; //sizeof(uint); // to simulate the (char *) in the old code (16 datatypes)
return rtval;
}
public void Load(BinaryReader br)
{
ReadValues(br);
}
// public void ReadStrings(BinaryReader br)
// {
// dbiTitle = ROFST_File.LoadString(br);
// dbiAP = ROFST_File.LoadString(br);
// }
public void ReadValues(BinaryReader br)
{
dbiID = br.ReadUInt16();
dbiType = br.ReadUInt16();
dbiAW = br.ReadUInt16();
dbiGL = br.ReadUInt32();
dbiIL = br.ReadUInt32();
dbiAL = br.ReadUInt32();
dbiEND = br.ReadUInt32();
uint tmp = br.ReadUInt32();
uint tmp1 = br.ReadUInt32();
}
}
// structure to hold information to add a new group
public struct AddGroup
{
public uint grp_id;
public uint grp_parid;
public string grp_name;
public short grp_type;
public short grp_stat;
public uint grp_offset;
public int grp_pargrpidx;
// These functions are needed to update values when
// referenced from the ArrayLists (allNewGrps)
// public void OR_grp_type(short val)
// {
// ushort gtype = (ushort)grp_type;
// gtype |= (ushort)val;
// grp_type = (short)gtype;
// }
//
//
// public void SET_grp_parid(uint val)
// {
// grp_parid = val;
// }
//
//
// public void SET_grp_pargrpidx(int val)
// {
// grp_pargrpidx = val;
// }
//
//
// public void SET_grp_stat(short val)
// {
// grp_stat = val;
// }
//
//
// public void SET_grp_offset(uint val)
// {
// grp_offset = val;
// }
}
// structure to hold information to add a new RO
public struct AddRO
{
public uint ro_id;
public uint ro_parid;
public string ro_num;
public string ro_desc;
public string ro_val;
public short ro_type;
public short ro_stat;
public int ro_offset;
public int ro_pargrpidx; // index into allNewGrps
// These functions are needed to update values when
// referenced from the ArrayLists (allNewRos)
// public void SET_ro_pargrpidx(int val)
// {
// ro_pargrpidx = val;
// }
//
//
// public void SET_ro_parid(uint val)
// {
// ro_parid = val;
// }
//
//
// public void SET_ro_stat(short val)
// {
// ro_stat = val;
// }
//
//
// public void SET_ro_offset(int val)
// {
// ro_offset = val;
// }
}
// structure to hold RO difference information
public struct DiffRO
{
public uint id;
public short type;
public string desc;
public string val;
public uint oldoff; // index into old RO.FST file (approved)
}
// RO update info arrays.
// one of these structures is created from each RO database
// (Setpoints, Graphics, User Defined, etc.)
public struct dbinew
{
public ArrayList aryAddedRO;
public ArrayList aryAddedGroup;
public ArrayList aryAddedDiff;
}
// structure to store file positions in the RO.FST file
public struct locinc
{
public uint maxloc;
public int inc;
}
/*
** Structure of the graphics' values.
** LocalGrfStats ( in ROFST_File class) is used to hold the current
** values "locally" in memory
*/
public struct GrfStats
{
public string PixFileName;
public int PixFileTime;
public short PixFileHeight;
public short PixFileWidth;
public void Clear()
{
PixFileName="";
PixFileTime = 0;
PixFileHeight = 0;
PixFileWidth = 0;
}
public void Load(string instr)
{
short DeciPerRow = 120;
short DeciPerCol = 60;
StringBuilder sb = new StringBuilder();
int i=0;
bool nl = false;
/*
sscanf(retval,"%s\n%08lx\n%04x\n%04x",LocalGrfStats.PixFileName,
&LocalGrfStats.PixFileTime,&LocalGrfStats.PixFileHeight,
&LocalGrfStats.PixFileWidth);
LocalGrfStats.PixFileHeight *= DeciPerRow;
LocalGrfStats.PixFileWidth *= DeciPerCol;
*/
while (!nl && (instr[i]!= 0))
{
if (instr[i]=='\n')
nl=true;
else
sb.Append(instr[i]);
i++;
}
if (nl)
{
PixFileName = sb.ToString();
}
nl = false;
sb.Remove(0,sb.Length);
while (!nl && (instr[i]!=0))
{
if (instr[i]=='\n')
nl=true;
else
sb.Append(instr[i]);
i++;
}
PixFileTime = Convert.ToInt32(sb.ToString(),16);
nl = false;
sb.Remove(0,sb.Length);
while (!nl && (instr[i]!=0))
{
if (instr[i]=='\n')
nl=true;
else
sb.Append(instr[i]);
i++;
}
PixFileHeight = Convert.ToInt16(sb.ToString(),16);
PixFileHeight *= DeciPerRow;
sb.Remove(0,sb.Length);
while ((i < instr.Length) && (instr[i]!=0))
{
sb.Append(instr[i]);
i++;
}
PixFileWidth = Convert.ToInt16(sb.ToString(),16);
PixFileWidth *= DeciPerCol;
}
}
public class ROFST_File
{
public enum ROTypes
{
None=0, Text=1, Table=2, Plot=4, Figure=8
};
private string [] UnitVariables =
{
"All of the following",//
"Number", // 1L; - 1, 2 etc.
"Other Number", // 2L; - 2, 1 etc.
"Text", // 3L; - One, Two etc. or Unit One, Unit Two
"Other Text", // 4L; - Two, One etc. or Unit Two, Unit One
"ID", // 5L; - 1Bw, 2Bw etc.
"Other ID", // 6L; - 2Bw, 1Bw etc.
"Name", // 7L; - Braidwood Unit 1
"Other Name" // 8L; - Braidwood Unit 2
};
private uint NumUnitVariables =9;
private ArrayList [] allNewRos; // new ROs
private ArrayList [] allDifferences; // changed ROs
private ArrayList [] allNewGrps; // new Groups
private ArrayList allLocations; // positions in RO.FST
private int curTblIdx=0; // index into allxxxxx arraylists
private uint NewID = 0xFFFF0000;
private uint whereisgl = 0;
private ushort maxaw=0;
private ushort maxtype=0;
private int lastLocationIdx = 0;
public BinaryReader brROFst; // file handle into RO.FST
public ArrayList DatabasesInfo; // Holds the current RO.FST data
public ArrayList dbiNewInfo; // will hold new RO.FST data
public short numDatabases; // number of databases in RO.FST
public FST_FileHeader Header;
// public UserRunTime usrRunTime;
public string DirPath;
public string DefaultGraphicFileExt = "";
// RO Graphics information
GrfStats LocalGrfStats;
// constructor loads ro.fst databases
// public ROFST(string path, UserRunTime urt)
public ROFST_File(string path)
{
try
{
brROFst = new BinaryReader(File.Open(path,System.IO.FileMode.Open,System.IO.FileAccess.ReadWrite,FileShare.ReadWrite));
}
catch (Exception e)
{
MessageBox.Show("Open "+path+"\n\n" + e.Message,"RO.FST Error");
return;
}
DirPath = path; // path of RO.FST file
// usrRunTime = urt;
// Read the RO.FST header information
Header = new FST_FileHeader();
Header.Read(brROFst);
brROFst.BaseStream.Seek(Header.dboffset,SeekOrigin.Begin);
uint howbig = brROFst.ReadUInt32();
short howmany = brROFst.ReadInt16();
numDatabases = howmany;
// dbcount = numDatabases;
DatabasesInfo = new ArrayList();
dbiNewInfo = new ArrayList();
// Load the database into the arrays
for (int i=0;i<numDatabases;i++)
{
dbinew dbinewItem;
ROFST_DbInfo tmpDBinfo;
tmpDBinfo = new ROFST_DbInfo();
tmpDBinfo.Load(brROFst);
DatabasesInfo.Add(tmpDBinfo);
dbinewItem = new dbinew();
dbiNewInfo.Add(dbinewItem);
}
for (int i=0;i<numDatabases;i++)
{
// load the titles and accessory page ids
// ((ROFST_DbInfo)DatabasesInfo[i]).ReadStrings(brROFst);
((ROFST_DbInfo)DatabasesInfo[i]).dbiTitle = GetAsciiString(brROFst);
((ROFST_DbInfo)DatabasesInfo[i]).dbiAP = GetAsciiString(brROFst);
}
// get the default graphic file extension
GetDefaultGraphicFileExtension();
}
~ ROFST_File()
{
if (brROFst!=null)brROFst.Close();
}
public void Close()
{
if (brROFst!=null)brROFst.Close();
brROFst=null;
}
private void GetDefaultGraphicFileExtension()
{
// get the full path to the VEPROMS.INI file
string ApplicationPath = Application.StartupPath;
string ApplPathUp = ApplicationPath.ToUpper();
int idx = ApplPathUp.IndexOf("VE-PROMS.NET\\BIN");
string PromsINI = ApplicationPath.Substring(0,idx);
PromsINI += "VE-PROMS\\VEPROMS.INI";
PrivateProfile extINI = new PrivateProfile(PromsINI);
string defGrExt=extINI.Attr("Graphics", "defaultext");
if (defGrExt == null || defGrExt == "")
{
// check the ROAPP.INI in the RO directory
string ropath = extINI.Attr("RO Defaults","ROPATH");
if (ropath == null || ropath == "") ropath = "..\\RO";
string src = ropath + "\\ROAPP.INI";
if (File.Exists(src))
{
PrivateProfile roappINI = new PrivateProfile(src);
defGrExt = roappINI.Attr("ROApp","Extention");
}
if (defGrExt == null || defGrExt == "")
defGrExt="TIF";
}
DefaultGraphicFileExt = defGrExt;
}
// Find the location of an RO value in the RO.FST file
private uint FindRO(uint id, uint start, uint end)
{
uint retval=0;
uint topid=0,botid=0,recs=0,siz=0;
siz=8; // c code:sizeof(topid)*2;
recs=(end-start)/siz;
uint guessr,guess=0,guessid=0;
uint botr=0,topr=recs;
//getID(end-siz,&topoff);
brROFst.BaseStream.Seek(end-siz,SeekOrigin.Begin);
topid=brROFst.ReadUInt32();
if(id==topid)return end-siz; // Last record
//getID(start,&botoff);
brROFst.BaseStream.Seek(start,SeekOrigin.Begin);
botid=brROFst.ReadUInt32();
if(id==botid)return start; // First record
if(id < botid || id > topid)return 0; // Beyond range
while (topr > botr+1)
{
guessr=botr+((topr-botr)*(id-botid))/(topid-botid);
if (guessr==botr) guessr=botr+1;
else if (guessr==topr) guessr=topr-1;
guess=start+guessr*siz;
brROFst.BaseStream.Seek(guess,SeekOrigin.Begin);
//getID(guess,&retval)
guessid=brROFst.ReadUInt32();
if(guessid==id)
{
break; // found, break out of while loop
}
else if(guessid < id)
{
botr=guessr;
botid=guessid;
}
else
{
topr=guessr;
topid=guessid;
}
}
if(guessid==id)retval=guess; // Any other record
return retval;
}
private uint _getID(uint off,ref uint nxtoff)
{
uint retval = 0;
if (off > 0)
{
brROFst.BaseStream.Seek(off,SeekOrigin.Begin);
retval = brROFst.ReadUInt32();
nxtoff = brROFst.ReadUInt32();
}
return retval;
}
// Find the location of an RO value in the RO.FST file
private uint toolsFindRO(uint id, uint start, uint end)
{
uint retval=0;
uint topid=0,botid=0,recs=0,siz=0;
siz=8; // c code:sizeof(topid)*2;
recs=(end-start)/siz; //c code: (end-start)>>3
uint guessr,guess=0,guessid=0;
uint botr=0,topr=recs;
uint topoff =0, botoff=0;
//getID(end-siz,&topoff);
topid=_getID(end-siz,ref topoff);
if(id==topid)return topoff; // Last record
//getID(start,&botoff);
botid=_getID(start,ref botoff);
if(id==botid)return botoff; // First record
if(id < botid || id > topid)return 0; // Beyond range
while (topr > botr+1)
{
guessr=botr+((topr-botr)/2);
if (guessr==botr) guessr++;
else if (guessr==topr) guessr--;
//getID(guess,&retval)
guessid=_getID(start+guessr*siz,ref retval);
if(guessid==id)
{
break; // found, break out of while loop
}
else if(guessid < id)
{
botr=guessr;
botid=guessid;
}
else
{
topr=guessr;
topid=guessid;
}
}
if (guessid == id) return retval;
return 0;
}
// return the type of the given RO
private ROTypes FindROType(uint rec, uint start, uint end)
{
short retval=0;
byte[] tbyte= new byte[100];
uint fnd;
if((fnd=FindRO(rec,start,end))>0)
{
uint offset=brROFst.ReadUInt32();
brROFst.BaseStream.Seek((long)offset,SeekOrigin.Begin);
uint guessid=brROFst.ReadUInt32();
uint parid=brROFst.ReadUInt32();
short count=brROFst.ReadInt16();
retval=brROFst.ReadInt16(); // RO Type
}
return (ROTypes)retval;
}
// Get the RO Type from the ROID
public ROTypes GetROType(string ROID)
{
// break up ROID into table and record
ushort tbl = System.Convert.ToUInt16(ROID.Substring(0,4),16);
uint rec = System.Convert.ToUInt32(ROID.Substring(4,8),16);
ushort opt=0;
if (ROID.Length>12) opt = System.Convert.ToUInt16(ROID.Substring(8,ROID.Length-12),16);
if (tbl==0xFFFF)
return ROTypes.None; // 0xFFFF is ro from proc.ini file
int num=0;
for (int i=0; i < numDatabases && ((ROFST_DbInfo)DatabasesInfo[i]).dbiID!=tbl;i++) num++;
if (num < numDatabases)
{
return FindROType(rec,((ROFST_DbInfo)DatabasesInfo[num]).dbiIL,((ROFST_DbInfo)DatabasesInfo[num]).dbiAL);
}
return ROTypes.None;
}
private string FindROText(uint id, uint start,uint end)
{
string retval=null;
uint fnd;
if((fnd=FindRO(id,start,end))>0)
{
uint offset=brROFst.ReadUInt32();
brROFst.BaseStream.Seek((long)offset,SeekOrigin.Begin);
uint guessid=brROFst.ReadUInt32();
uint parid=brROFst.ReadUInt32();
short count=brROFst.ReadInt16();
ushort typ=brROFst.ReadUInt16();
if (count<0)retval=GetAsciiString(brROFst);
}
return retval;
}
// return the RO defined in the PROC.INI file
// (master / slave logic)
private string roUnitValue(uint rec)
{
string buff="";
PrivateProfile proc_ini = new PrivateProfile("proc.ini");
for(int i=0; i < NumUnitVariables; i++)
{
if((i+1) == rec)
{
buff = proc_ini.Attr("Unit",UnitVariables[i+1]);
if (buff == null || buff.Equals(""))
buff = "{"+ UnitVariables[i+1] + "}";
break; // break out of for loop
}
}
return buff;
}
//
// this function will take the ro text value and see if
// a macro has been used. If so it will perform the macro
// operation on the substring in the text value
//
// right now the only macro is @HSP(), where every space between
// the "(" and ")" will be replaced with a hardspace
//
public string processMacros(string rostring)
{
StringBuilder bldstr = new StringBuilder();
int cptr = -1;
int stptr = 0;
if( rostring == null ) return rostring;
while( (cptr = rostring.IndexOf("@HSP(",stptr)) != -1 )
{
bldstr.Append(rostring.Substring(0,cptr-stptr));
int cptr2 = rostring.IndexOf(")",cptr);
if (cptr2 != -1)
{
int numspaces = cptr2 - cptr - 5;
for (int i=0; i< numspaces; i++)
bldstr.Append("\xFF");
stptr = cptr2 + 1;
}
else
{
bldstr.Append(rostring.Substring(cptr,5));
stptr += 5;
}
}
if (stptr < rostring.Length)
bldstr.Append(rostring.Substring(stptr));
return bldstr.ToString();
}
private string processROString(string rostr, short menuitem)
{
string newstr="";
strList2 strlst2 = new strList2(rostr);
strList strlst = new strList(strlst2.toText());
newstr = strlst.toText((int)menuitem);
newstr = newstr.Replace("\\n","\n");
newstr = processMacros(newstr);
return newstr;
}
public string GetRO(string ROID)
{
return _GetRO(ROID,1);
}
public string GetEntireRO(string ROID)
{
return _GetRO(ROID,0);
}
public string GetRO(string ROID, string ProcNum)
{
ROProcessTools.ProcedureNumber = ProcNum;
return GetRO(ROID);
}
public string GetEntireRO(string ROID, string ProcNum)
{
ROProcessTools.ProcedureNumber = ProcNum;
return GetEntireRO(ROID);
}
// Get the RO value from the ROID
private string _GetRO(string ROID_in, short procopt)
{
string ROID = ROID_in;
if (ROID.Length == 12)
ROID = ROID + "0000";
ushort tbl = System.Convert.ToUInt16(ROID.Substring(0,4),16);
uint rec = System.Convert.ToUInt32(ROID.Substring(4,8),16);
ushort opt=0;
// clear graphics info
LocalGrfStats.Clear();
opt = System.Convert.ToUInt16(ROID.Substring(12,ROID.Length-12),16);
if (tbl==0xFFFF)
return roUnitValue(rec); // RO in PROC.INI file
int num=0;
for(int i=0; i < numDatabases && ((ROFST_DbInfo)DatabasesInfo[i]).dbiID!=tbl;i++) num++;
string retval = null;
if(num < numDatabases)
{
retval=FindROText(rec,((ROFST_DbInfo)DatabasesInfo[num]).dbiIL,((ROFST_DbInfo)DatabasesInfo[num]).dbiAL);
}
if ((retval!=null&&retval!="") && (GetROType(ROID)==ROTypes.Figure))
{
// load graphic stats
StringBuilder sbtmp = new StringBuilder();
LocalGrfStats.Load(retval);
sbtmp.Append(LocalGrfStats.PixFileName);
sbtmp.Append("\n");
sbtmp.Append(LocalGrfStats.PixFileTime.ToString("x8"));
sbtmp.Append("\n");
sbtmp.Append(LocalGrfStats.PixFileHeight.ToString("x4"));
sbtmp.Append("\n");
sbtmp.Append(LocalGrfStats.PixFileWidth.ToString("x4"));
retval = sbtmp.ToString();
}
if(retval!=null && retval.Length>0 && !(GetROType(ROID)==ROTypes.Figure))
{
retval = retval.Replace("\r","");
if (procopt!=0)
{
string newstr = processROString(retval,(short)opt);
if (newstr!=null && !newstr.Equals(""))
retval = newstr;
}
}
return retval;
}
// Get the RO's parent ID
private uint GetParent(uint rec, uint start,uint end,ref uint offset)
{
uint parid=0;
uint fnd;
if((fnd=FindRO(rec,start,end))>0)
{
offset=brROFst.ReadUInt32();
brROFst.BaseStream.Seek((long)offset,SeekOrigin.Begin);
uint guessid=brROFst.ReadUInt32();
parid=brROFst.ReadUInt32();
}
return parid;
}
// Get the RO's parent ID from the ROID
public uint GetROParent(string ROID)
{
ushort tbl = Convert.ToUInt16(ROID.Substring(0,4),16);
uint rec = Convert.ToUInt32(ROID.Substring(4,8),16);
uint retval=0;
int indx=0;
for(int i=0; i < numDatabases && ((ROFST_DbInfo)DatabasesInfo[i]).dbiID!=tbl; i++) indx++; // position to the RO database
if(indx < numDatabases)
{
uint offset=0;
retval=GetParent(rec,((ROFST_DbInfo)DatabasesInfo[indx]).dbiIL,((ROFST_DbInfo)DatabasesInfo[indx]).dbiAL,ref offset);
}
return retval;
}
// Get the group title
private string GetDescription(ushort tbl, uint rec)
{
string retval=null;
if(tbl==0xFFFF)
{
if(rec == 0)
{
retval="Unit Information";
}
else if (rec <= NumUnitVariables)
{
int irec = (int)rec;
retval=UnitVariables[irec];
}
}
else
{
int indx=0;
for(int i=0; i < numDatabases && ((ROFST_DbInfo)DatabasesInfo[i]).dbiID!=tbl; i++) indx++;
if(indx < numDatabases)
{
uint id;
brROFst.BaseStream.Seek(((ROFST_DbInfo)DatabasesInfo[indx]).dbiGL,SeekOrigin.Begin);
id = brROFst.ReadUInt32();
if((rec==0) || rec==id)
{
retval=((ROFST_DbInfo)DatabasesInfo[indx]).dbiTitle;
}
else
{
uint offset=0;
uint parid = this.GetParent(rec,((ROFST_DbInfo)DatabasesInfo[indx]).dbiIL,((ROFST_DbInfo)DatabasesInfo[indx]).dbiAL,ref offset);
if(parid!=0)
{
uint t1 = FindRO(parid,((ROFST_DbInfo)DatabasesInfo[indx]).dbiIL,((ROFST_DbInfo)DatabasesInfo[indx]).dbiAL);
t1 = brROFst.ReadUInt32();
uint guessid;
brROFst.BaseStream.Seek(t1,SeekOrigin.Begin);
guessid = brROFst.ReadUInt32();
parid = brROFst.ReadUInt32();
short count;
count = brROFst.ReadInt16();
for(int i=0; i < count && retval == null; i++)
{
uint off;
off=brROFst.ReadUInt32();
ushort typ;
typ=brROFst.ReadUInt16();
if(off==offset)
{
retval = GetAsciiString(brROFst);
}
else
{
SkipString(brROFst);
}
}
}
}
}
}
return retval;
}
// Get the group title by ROID
public string GetRODescription(string ROID)
{
ushort tbl = Convert.ToUInt16(ROID.Substring(0,4),16);
uint rec = Convert.ToUInt32(ROID.Substring(4,8),16);
return (GetDescription(tbl,rec));
}
// get the Accessory Page ID
string FindROAccID(uint id, uint start, uint end)
{
// Returns allocated space
string retval=null;
if(FindRO(id,start,end)!=0)
{
uint offset = brROFst.ReadUInt32();
brROFst.BaseStream.Seek(offset,SeekOrigin.Begin);
uint guessid = brROFst.ReadUInt32();
uint parid = brROFst.ReadUInt32();
short count = brROFst.ReadInt16();
ushort ltyp = brROFst.ReadUInt16();
SkipString(brROFst);
retval = GetAsciiString(brROFst);
}
return retval;
}
private string roUnitAccID(uint rec)
{
string rotbuf="";
for(int i=0; i < NumUnitVariables; i++)
{
if((i+1L)==rec)
{
rotbuf = "U-"+UnitVariables[i+1];
break; // break out of for loop
}
}
return rotbuf;
}
// Get accessory page ID via the table and record
// also include unit specs from ini file
private string GetAccID(ushort tbl, uint rec)
{
string retval=null;
if (tbl==0xFFFF)
{
return roUnitAccID(rec); // PROC.INI ro
}
int indx=0;
for(int i=0; i < numDatabases && ((ROFST_DbInfo)DatabasesInfo[i]).dbiID!=tbl; i++)indx++;
if(indx < numDatabases)
{
retval=FindROAccID(rec,((ROFST_DbInfo)DatabasesInfo[indx]).dbiIL,((ROFST_DbInfo)DatabasesInfo[indx]).dbiAL);
if (retval == null)
retval=""; // RO not found, has ? in procedures
else
retval = ((ROFST_DbInfo)DatabasesInfo[indx]).dbiAP + "-" + retval;
}
return retval;
}
// Get the accessory page ID from the ROID
// includes unit specs from ini file
public string RoidToAccId(string ROID)
{
ushort tbl = Convert.ToUInt16(ROID.Substring(0,4),16);
uint rec = Convert.ToUInt32(ROID.Substring(4,8),16);
if(tbl != 0)
return GetAccID(tbl,rec);
return null;
}
// Get the accessory page ID
private string GetAppID(ushort tbl)
{
string retval = null;
if (tbl==0xFFFF)
{
return "U"; // PROC.INI ro
}
int indx=0;
for(int i=0; i < numDatabases && ((ROFST_DbInfo)DatabasesInfo[i]).dbiID!=tbl; i++) indx++;
if(indx < numDatabases)
return ((ROFST_DbInfo)DatabasesInfo[indx]).dbiAP;
return retval;
}
// Get the accessory page ID from the ROID
public string GetROAppID(string ROID)
{
ushort tbl = Convert.ToUInt16(ROID.Substring(0,4),16);
uint rec = Convert.ToUInt32(ROID.Substring(4,8),16);
return GetAppID(tbl);
}
public uint FindROFromTblRec(ushort tbl, uint id)
{
if(tbl==0xFFFF)
{
//PROC.INI ro
if (id < NumUnitVariables) return 1;
return 0;
}
int indx=0;
for(int i=0; i < numDatabases && ((ROFST_DbInfo)DatabasesInfo[i]).dbiID!=tbl;i++) indx++;
if (indx==numDatabases) return 0;
return FindRO(id,((ROFST_DbInfo)DatabasesInfo[indx]).dbiIL,((ROFST_DbInfo)DatabasesInfo[indx]).dbiAL);
}
public bool ROExists(string ROID)
{
ushort tbl = Convert.ToUInt16(ROID.Substring(0,4),16);
uint rec = Convert.ToUInt32(ROID.Substring(4,8),16);
uint off = FindROFromTblRec(tbl,rec);
return (off!=0);
}
public static void SkipString(BinaryReader br)
{
byte []input = {0};
do
{
try
{
input[0] = br.ReadByte();
}
catch (System.IO.EndOfStreamException)
{
input[0] = 0;
}
}while (input[0] != 0);
return;
}
public static string GetAsciiString(BinaryReader br, int len)
{
StringBuilder inpstr = new StringBuilder();
byte input = 0;
int cnt = 0;
do
{
try
{
input = br.ReadByte();
inpstr.Append(Convert.ToChar(input));
}
catch (System.IO.EndOfStreamException)
{
input = 0;
while (cnt < len)
{
inpstr.Append(Convert.ToChar(input));
cnt++;
}
}
cnt++;
}while (cnt < len);
return (inpstr.ToString());
}
public static string GetAsciiString(BinaryReader br)
{
StringBuilder inpstr = new StringBuilder();
byte input = 0;
do
{
try
{
input = br.ReadByte();
if (input > 0)
{
inpstr.Append(Convert.ToChar(input));
}
}
catch (System.IO.EndOfStreamException)
{
input = 0;
}
}while (input != 0);
return (inpstr.ToString());
}
// return the index into the the DatabasesInfo array
private short GetTable(ushort tblid)
{
short found = -1;
for(short i = 0; (i < numDatabases) && (found == -1); i++)
{
if (tblid == ((ROFST_DbInfo)DatabasesInfo[i]).dbiID)
found = i;
}
if (found == -1)
{
// add a new item to the list
found = numDatabases;
ROFST_DbInfo tmpDbInfo = new ROFST_DbInfo();
tmpDbInfo.dbiID = tblid;
DatabasesInfo.Add(tmpDbInfo);
dbinew dbinewItem;
dbinewItem = new dbinew();
dbiNewInfo.Add(dbinewItem);
numDatabases++;
}
return found;
}
// Add a new RO record to the arraylist of allNewRos
private int AddNewRO(uint id,string num,string desc,string val,short type,uint grpn)
{
int rtval;
AddRO tmpAddRO = new AddRO();
tmpAddRO.ro_id = id;
tmpAddRO.ro_num = num;
tmpAddRO.ro_desc = desc;
tmpAddRO.ro_val = val;
tmpAddRO.ro_type = type;
tmpAddRO.ro_parid = grpn;
(allNewRos[curTblIdx]).Add(tmpAddRO);
rtval = (allNewRos[curTblIdx]).Count -1;
return rtval;
}
private int AddNewRO(string num,string desc,string val,short type,uint grpn)
{
return AddNewRO(NewID++, num, desc, val, type, grpn);
}
// Add a new Group record to the arraylist of allNewGrps
private int AddNewGroup(uint id,string grpname,short type)
{
int rtval;
AddGroup tmpAddGroup = new AddGroup();
tmpAddGroup.grp_id = id;
tmpAddGroup.grp_name = grpname;
tmpAddGroup.grp_type = type;
(allNewGrps[curTblIdx]).Add(tmpAddGroup);
rtval = (allNewGrps[curTblIdx]).Count -1;
return rtval;
}
private int AddNewGroup(string grpname,short type)
{
return AddNewGroup(NewID++,grpname,type);
}
// Return the index into the allNewGrps arraylist
private int FindNewGroup(uint rec)
{
int rtval = -1;
for (int i=0; i < (allNewGrps[curTblIdx]).Count && rtval == -1; i++)
{
if (((AddGroup)(allNewGrps[curTblIdx])[i]).grp_id == rec)
rtval = i;
}
return rtval;
}
private int connectToNewGroupfRO(int lastaddROIDX,uint rec,uint parid,string desc)
{
int newgrpIDX;
// position to the correct RO group
if((newgrpIDX=FindNewGroup(rec))== -1)
{
// group not found, add a new one
newgrpIDX=AddNewGroup(rec,desc,0);
}
//update parent info
AddRO taddro = (AddRO)(allNewRos[curTblIdx][lastaddROIDX]);
taddro.ro_pargrpidx = newgrpIDX;
taddro.ro_parid = rec;
allNewRos[curTblIdx].RemoveAt(lastaddROIDX);
allNewRos[curTblIdx].Insert(lastaddROIDX,taddro);
//update group info
AddGroup taddgroup = (AddGroup)(allNewGrps[curTblIdx][newgrpIDX]);
taddgroup.grp_type |= ((AddRO)(allNewRos[curTblIdx])[lastaddROIDX]).ro_type;
taddgroup.grp_parid = parid;
allNewGrps[curTblIdx].RemoveAt(newgrpIDX);
allNewGrps[curTblIdx].Insert(newgrpIDX,taddgroup);
return newgrpIDX;
}
private int connectToNewGroup(int lastaddgrpIDX,uint rec,uint parid,string desc)
{
// update group info
int newgrpIDX;
// position to the correct RO group
if((newgrpIDX=FindNewGroup(rec))== -1)
{
// group not found, add a new one
newgrpIDX=AddNewGroup(rec,desc,0);
}
AddGroup taddgroup = (AddGroup)(allNewGrps[curTblIdx][lastaddgrpIDX]);
taddgroup.grp_pargrpidx = newgrpIDX;
taddgroup.grp_parid = rec;
allNewGrps[curTblIdx].RemoveAt(lastaddgrpIDX);
allNewGrps[curTblIdx].Insert(lastaddgrpIDX,taddgroup);
taddgroup = (AddGroup)(allNewGrps[curTblIdx][newgrpIDX]);
taddgroup.grp_type |= ((AddGroup)(allNewGrps[curTblIdx])[lastaddgrpIDX]).grp_type;
taddgroup.grp_parid = parid;
allNewGrps[curTblIdx].RemoveAt(newgrpIDX);
allNewGrps[curTblIdx].Insert(newgrpIDX,taddgroup);
return newgrpIDX;
}
private void addDifference(uint id,string val,string desc,short type,uint offset)
{
DiffRO tmpDiff = new DiffRO();
tmpDiff.id=id;
tmpDiff.type=type;
tmpDiff.desc=desc;
tmpDiff.val=val;
tmpDiff.oldoff=offset;
allDifferences[curTblIdx].Add(tmpDiff);
}
private short ReadShort(BinaryReader br)
{
short rtnval = -1;
try
{
rtnval = br.ReadInt16();
}
catch (Exception)
{
rtnval = -1;
}
return rtnval;
}
/*
* Read in the ROFST Update file. Put the changes in array lists
* to that will be used to organize and merge the differences into
* the target RO.FST file (usually in the Approved directory). For
* array lists, use the number of databases from the working draft
* (there may be new databases created since last approval)
*/
public void processAppUpdFile(string sAppUpdFile, short nDB)
{
BinaryReader brAppUpd;
string num, desc, val;
short typ, inch;
uint rec;
ushort tbl;
uint parid;
int LastAddedROIDX=-1, LastAddedGrpIDX=-1;
curTblIdx = 0; // initialize Current Table Index
allNewRos = (ArrayList [])new ArrayList[nDB];
allNewGrps = (ArrayList [])new ArrayList[nDB];
allDifferences = (ArrayList [])new ArrayList[nDB];
allLocations = new ArrayList();
for (int i=0; i<nDB; i++)
{
allNewRos[i] = new ArrayList();
allNewGrps[i] = new ArrayList();
allDifferences[i] = new ArrayList();
}
// Initialize the allLocations array
locinc tmplocinc = new locinc();
tmplocinc.inc = 0;
tmplocinc.maxloc = 0xFFFFFFFF;
allLocations.Add(tmplocinc);
// Open the AppUpd file and read in the RO.FST changes
try
{
brAppUpd = new BinaryReader(File.Open(sAppUpdFile,System.IO.FileMode.Open,System.IO.FileAccess.Read,FileShare.Read));
}
catch (Exception e)
{
MessageBox.Show("Open "+sAppUpdFile+"\n\n" + e.Message,"Approval Error");
return;
}
while ((inch = ReadShort(brAppUpd)) != -1)
{
if (inch == 0 || inch == 1)
{
// Read the ROID for the Table and Record Number
tbl = brAppUpd.ReadUInt16(); // table number
rec = brAppUpd.ReadUInt32(); // RO Record number
// Position to the correct RO database
// ex. Setpoint, Graphics, User Defined, etc.
curTblIdx = GetTable(tbl);
// Read in the RO FST record information
parid = brAppUpd.ReadUInt32(); // Parid
typ = brAppUpd.ReadInt16(); // type
desc = GetAsciiString(brAppUpd); // description
val = GetAsciiString(brAppUpd); // value
num = GetAsciiString(brAppUpd); // acc ID
if (inch==0)
// New RO FST record
LastAddedROIDX = AddNewRO(rec,num,desc,val,typ,parid);
else
{
// Find existing RO FST record in Approved RO.FST
uint start = ((ROFST_DbInfo)DatabasesInfo[curTblIdx]).dbiIL;
uint end = ((ROFST_DbInfo)DatabasesInfo[curTblIdx]).dbiAL;
//NOTE: the FindRO() used in the old rofstupd.c code
// had some differences, but we will try the following
// version of this function since its logic appears in
// other areas of VE-PROMS code.
uint OldOff = toolsFindRO(rec,start,end);
// Save the differences
addDifference(rec,val,desc,typ,OldOff);
}
}
else
{
rec = brAppUpd.ReadUInt32(); // RO Record number
parid = brAppUpd.ReadUInt32();
desc = GetAsciiString(brAppUpd);
if (parid == 0)
{
string apid= GetAsciiString(brAppUpd);
((ROFST_DbInfo)DatabasesInfo[curTblIdx]).dbiTitle = desc;
((ROFST_DbInfo)DatabasesInfo[curTblIdx]).dbiAP = apid;
}
if (LastAddedROIDX != -1)
// update value in allNewRos
LastAddedGrpIDX = connectToNewGroupfRO(LastAddedROIDX,rec,parid,desc);
else
// update value in allNewGrps
LastAddedGrpIDX = connectToNewGroup(LastAddedGrpIDX,rec,parid,desc);
LastAddedROIDX = -1;
}
}
brAppUpd.Close();
}
// format strings used in the RO.FST menus that are displayed
// in the VE-PROMS Editor
private void placeText(StringBuilder buff,ushort doff,ushort wid,string instr)
{
ushort siznum=0;
string str = instr;
int idx =0;
if(doff != 0)
{
str = str.TrimStart(' '); // skip leading spaces
ushort l=(ushort)str.Length;
string numandsigns = "0123456789+-";
while (numandsigns.IndexOf(str[idx])!=-1)
{
siznum++;
idx++;
}
if(siznum==0)
{// doff is calculated to keep the values positive
doff=((ushort)(siznum+(wid-l)/2)); // if no digits - center
}
else if(((doff-siznum)+l) > wid)
{
doff=(ushort)(wid-siznum-l);
}
while(wid > 0 && siznum < doff)
{ // add spaces if necessary for alignment
buff.Append(' ');
siznum++;
wid--;
}
}
idx = 0;
while(wid > 0)
{ // output the value or spaces to the specified width
if (idx < str.Length && str[idx] != 0 && str[idx] != '\n')
buff.Append(str[idx]);
else
buff.Append(" ");
wid--;
idx++;
}
}
private string getMenuString(short type,string val,string desc)
{
StringBuilder buff = new StringBuilder();
switch(type)
{
case 1:
placeText(buff,5,17,val);
buff.Append(" ");
break;
case 2:
placeText(buff,5,17,"(Table)");
buff.Append(" ");
break;
case 4:
placeText(buff,5,17,"(Graph)");
buff.Append(" ");
break;
}
buff.Append(desc);
return buff.ToString();
}
public void WriteString(BinaryWriter NewFSTFile, string str,bool AddNull)
{
int n=str.Length;
if (AddNull)
n++;
byte [] b = new byte[n];
for(int i =0; i < str.Length; i++)
{
b[i] = (byte)str[i];
}
NewFSTFile.Write(b,0,n);
}
public uint saveNewMenuEntries(BinaryWriter NewFSTFile,uint id)
{
long start=NewFSTFile.Seek(0,System.IO.SeekOrigin.Current);
int numNewRos = (allNewRos[curTblIdx]).Count;
int cntNewRos = 0;
while (cntNewRos < numNewRos)
{
// Skip to the one to be saved
while ((cntNewRos < numNewRos) &&
(((AddRO)(allNewRos[curTblIdx])[cntNewRos]).ro_stat != 1) &&
((AddRO)(allNewRos[curTblIdx])[cntNewRos]).ro_parid != id)
cntNewRos++;
// If one exists, save it and skip to the next one
if (cntNewRos < numNewRos)
{
AddRO taddro = (AddRO)(allNewRos[curTblIdx][cntNewRos]);
taddro.ro_stat = 2;
allNewRos[curTblIdx].RemoveAt(cntNewRos);
allNewRos[curTblIdx].Insert(cntNewRos,taddro);
// Save the offset
NewFSTFile.Write(((AddRO)(allNewRos[curTblIdx])[cntNewRos]).ro_offset);
// Save the type
NewFSTFile.Write(((AddRO)(allNewRos[curTblIdx])[cntNewRos]).ro_type);
// Get the menu string
string mnustr = getMenuString(((AddRO)(allNewRos[curTblIdx])[cntNewRos]).ro_type,((AddRO)(allNewRos[curTblIdx])[cntNewRos]).ro_val,((AddRO)(allNewRos[curTblIdx])[cntNewRos]).ro_desc);
// Save menu entry
WriteString(NewFSTFile,mnustr,true);
cntNewRos++;
}
}
int cntNewGrps = 0;
int numNewGrps = (allNewGrps[curTblIdx]).Count;
while (cntNewGrps < numNewGrps)
{
// Skip to the one to be saved
while ((cntNewGrps < numNewGrps) &&
(((AddGroup)(allNewGrps[curTblIdx])[cntNewGrps]).grp_stat != 1 ||
((AddGroup)(allNewGrps[curTblIdx])[cntNewGrps]).grp_parid != id))
cntNewGrps++;
// If one exists, save it and skip to the next one
if(cntNewGrps < numNewGrps)
{
// Change stat to menu entry saved
AddGroup taddgroup = (AddGroup)(allNewGrps[curTblIdx][cntNewGrps]);
taddgroup.grp_stat = 2;
allNewGrps[curTblIdx].RemoveAt(cntNewGrps);
allNewGrps[curTblIdx].Insert(cntNewGrps,taddgroup);
// Save the offset
NewFSTFile.Write(((AddGroup)(allNewGrps[curTblIdx])[cntNewGrps]).grp_offset);
// Save the type
NewFSTFile.Write(((AddGroup)(allNewGrps[curTblIdx])[cntNewGrps]).grp_type);
// Save menu entry
WriteString(NewFSTFile,((AddGroup)(allNewGrps[curTblIdx])[cntNewGrps]).grp_name,true);
cntNewGrps++;
}
}
return ((uint)((NewFSTFile.Seek(0,System.IO.SeekOrigin.Current)) - start));
}
public void AddLocation(uint location,int inc)
{
int t_inc = ((locinc)allLocations[lastLocationIdx]).inc;
if (location == ((locinc)allLocations[lastLocationIdx]).maxloc)
{
// update the current record
// - need to remove current item, then insert new item.
locinc tmploc = (locinc)(allLocations[lastLocationIdx]);
tmploc.inc += inc;
allLocations.RemoveAt(lastLocationIdx);
allLocations.Insert(lastLocationIdx,tmploc);
}
else
{
locinc tmploc = (locinc)(allLocations[lastLocationIdx]);
locinc newloc = new locinc();
// new item gets last item's maxloc
newloc.maxloc = tmploc.maxloc;
newloc.inc = tmploc.inc + inc;
// update the current record
// - need to remove current item, then insert new item.
tmploc.maxloc = location; //update maxloc
allLocations.RemoveAt(lastLocationIdx);
allLocations.Insert(lastLocationIdx,tmploc);
// append the new item
allLocations.Add(newloc);
lastLocationIdx++;
}
}
public short saveAdditions(BinaryWriter NewFSTFile,uint parid,uint start)
{
// Initialize count of added entries
short count = 0;
// Initialize count of added bytes
int bytes = 0;
int numgroups = (allNewGrps[curTblIdx]).Count;
int grpcnt = 0;
while (grpcnt < numgroups)
{
if (((AddGroup)(allNewGrps[curTblIdx])[grpcnt]).grp_stat == 0 && ((AddGroup)(allNewGrps[curTblIdx])[grpcnt]).grp_parid == parid)
{
// Save new group
// Change stat to inprogress
AddGroup taddgroup = (AddGroup)(allNewGrps[curTblIdx][grpcnt]);
taddgroup.grp_stat = 99;
allNewGrps[curTblIdx].RemoveAt(grpcnt);
allNewGrps[curTblIdx].Insert(grpcnt,taddgroup);
count++;
// Save any children
short howmany = saveAdditions(NewFSTFile,((AddGroup)(allNewGrps[curTblIdx])[grpcnt]).grp_id,start);
// Remember the offset
taddgroup = (AddGroup)(allNewGrps[curTblIdx][grpcnt]);
taddgroup.grp_offset = (uint)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current); // ftell(ofile)
allNewGrps[curTblIdx].RemoveAt(grpcnt);
allNewGrps[curTblIdx].Insert(grpcnt,taddgroup);
// Save ID
if (((AddGroup)(allNewGrps[curTblIdx])[grpcnt]).grp_parid == 0)
{
whereisgl = (uint)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current);
}
NewFSTFile.Write(((AddGroup)(allNewGrps[curTblIdx])[grpcnt]).grp_id);
// Save the Parent ID
NewFSTFile.Write(((AddGroup)(allNewGrps[curTblIdx])[grpcnt]).grp_parid);
// save howmany
NewFSTFile.Write(howmany);
// save children
saveNewMenuEntries(NewFSTFile,((AddGroup)(allNewGrps[curTblIdx])[grpcnt]).grp_id);
taddgroup = (AddGroup)(allNewGrps[curTblIdx][grpcnt]);
taddgroup.grp_stat = 1;
allNewGrps[curTblIdx].RemoveAt(grpcnt);
allNewGrps[curTblIdx].Insert(grpcnt,taddgroup);
bytes += (int)(NewFSTFile.Seek(0,System.IO.SeekOrigin.Current) - ((AddGroup)(allNewGrps[curTblIdx])[grpcnt]).grp_offset);
}
grpcnt++;
}
// Second check new ROs
int rocnt = 0;
int numros = (allNewRos[curTblIdx]).Count;
while (rocnt < numros)
{
// save new RO
if (((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_stat == 0 &&
((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_parid == parid)
{
// change the stat
AddRO taddro = (AddRO)(allNewRos[curTblIdx][rocnt]);
taddro.ro_stat = 1;
// Increment count
count++;
taddro.ro_offset = (int)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current);
allNewRos[curTblIdx].RemoveAt(rocnt);
allNewRos[curTblIdx].Insert(rocnt,taddro);
// Save the ID
NewFSTFile.Write(((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_id);
// Save the Parent ID
NewFSTFile.Write(((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_parid);
// Save -1
NewFSTFile.Write((short)-1);
// Save type
NewFSTFile.Write(((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_type);
maxtype |= (ushort)((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_type;
// Save value
WriteString(NewFSTFile,((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_val,true);
// Save accid
short aw = (short)((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_num.Length;
if (aw > maxaw) maxaw = (ushort)aw;
WriteString(NewFSTFile,((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_num,true);
// Calculate the number of extra bytes output
bytes+=(int)(NewFSTFile.Seek(0,System.IO.SeekOrigin.Current) - ((AddRO)(allNewRos[curTblIdx])[rocnt]).ro_offset);
}
rocnt++;
}
// Adjust the location information
if (bytes != 0 && start > 0)
AddLocation(start - 1,bytes);
return count;
}
// was a difference flagged for this RO
// - check via saved offsets into the RO.fST file
public int isDifferent(uint off)
{
int allDiffCnt = 0;
int NumAllDiff = (allDifferences[curTblIdx]).Count;
while (allDiffCnt < NumAllDiff)
{
if (((DiffRO)(allDifferences[curTblIdx])[allDiffCnt]).oldoff == off)
return allDiffCnt;
allDiffCnt++;
}
return -1;
}
public uint newLocation(uint oldlocation)
{
int idx = 0;
while (oldlocation > ((locinc)allLocations[idx]).maxloc) idx++;
return oldlocation + (uint)((locinc)allLocations[idx]).inc;
}
public void processGroupRecords(BinaryWriter NewFSTFile,uint end)
{
uint start;
while ((start=(uint)brROFst.BaseStream.Seek(0,System.IO.SeekOrigin.Current)) < end)
{
// Read ID
uint id = brROFst.ReadUInt32();
// Read Parent ID
uint parid = brROFst.ReadUInt32();
// Read How Many
short howmany = brROFst.ReadInt16();
// Check of additions and write them
short howmanyplus = howmany;
if (howmany >= 0)
howmanyplus += saveAdditions(NewFSTFile,id,start);
if (parid == 0)
whereisgl = (uint)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current); // ftell(ofile)
// Write ID
NewFSTFile.Write(id);
// Write Parent ID
NewFSTFile.Write(parid);
// Write howmany
NewFSTFile.Write(howmanyplus);
// If group - read and write menu list
int starti = (int)brROFst.BaseStream.Seek(0,System.IO.SeekOrigin.Current); // ftell(rofstfile)
int starto = (int)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current); // ftell(ofile)
if (howmanyplus >= 0)
{
// for orignal entries
for (int i=0;i<howmany;i++)
{
// Read Offset
uint offset = brROFst.ReadUInt32();
// Read Type
short type = brROFst.ReadInt16();
// Read Menu
string menustr = GetAsciiString(brROFst);
// Look for differences
int thisdiff = isDifferent(offset);
if (thisdiff != -1)
{
type = ((DiffRO)(allDifferences[curTblIdx])[thisdiff]).type;
menustr = getMenuString(type,((DiffRO)(allDifferences[curTblIdx])[thisdiff]).val,((DiffRO)(allDifferences[curTblIdx])[thisdiff]).desc);
}
// Save new offset
NewFSTFile.Write(newLocation(offset));
// Save type
NewFSTFile.Write(type);
// Save menu
WriteString(NewFSTFile,menustr,true);
}
// Save new entries
if (howmanyplus > howmany)
{
saveNewMenuEntries(NewFSTFile,id);
}
}
else
{
// if RO - read RO record
// Read type
short type = brROFst.ReadInt16();
// Read value
string val = GetAsciiString(brROFst);
// Read accid
string num = GetAsciiString(brROFst);
// check if changed
int thisdiff = isDifferent(start);
if (thisdiff != -1)
{
type = ((DiffRO)(allDifferences[curTblIdx])[thisdiff]).type;
val = ((DiffRO)(allDifferences[curTblIdx])[thisdiff]).val;
}
// Save type
NewFSTFile.Write(type);
// Save value
WriteString(NewFSTFile,val,true);
// Save accid
WriteString(NewFSTFile,num,true);
}
int originalSize = (int)brROFst.BaseStream.Seek(0,System.IO.SeekOrigin.Current) - starti;
int copySize = (int)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current) - starto;
if (copySize != originalSize)
AddLocation(start,copySize - originalSize);
}
if (end == 0)
{
maxtype = 0;
maxaw = 0;
saveAdditions(NewFSTFile,0,0);
}
}
public int getROAccLess(string minnum)
{
int romin = -1;
int roptr = 0;
int numroptr = (allNewRos[curTblIdx]).Count;
while (roptr < numroptr)
{
// skip processed entries
while ((roptr < numroptr) &&
((AddRO)(allNewRos[curTblIdx])[roptr]).ro_stat == 4) roptr++;
if ((roptr < numroptr))
{
// Look for "smallest"
if ((minnum==null)||
((AddRO)(allNewRos[curTblIdx])[roptr]).ro_num.CompareTo(minnum) < 0)
{
romin = roptr;
minnum = ((AddRO)(allNewRos[curTblIdx])[roptr]).ro_num;
}
roptr++;
}
}
return romin;
}
public void putFixed(BinaryWriter NewFstFile, string str, short len)
{
int n=len; //str.Length;
int strlen = str.Length;
byte [] b = new byte[len];
// write a fixed length of a string.
for (int i =0; n > 0; i++)
{
if (i < strlen)
b[i] = (byte)str[i];
else
b[i] = (byte)0; // pad with NULLs if smaller than "len"
n--;
}
NewFstFile.Write(b,0,len);
}
public void processAccIdRecords(BinaryWriter NewFSTFile,uint end,short len)
{
int extra = 0;
int roptr = 0;
while (brROFst.BaseStream.Seek(0,System.IO.SeekOrigin.Current) < end)
{
// Read ID
uint id = brROFst.ReadUInt32();
// Read accID
string num = GetAsciiString(brROFst,len);
// Check other accIDs in new records and save
while ((roptr = getROAccLess(num)) != -1)
{
extra+=(len + 4); //sizeof(ulong 16bit)+len
NewFSTFile.Write(((AddRO)(allNewRos[curTblIdx])[roptr]).ro_id);
putFixed(NewFSTFile,((AddRO)(allNewRos[curTblIdx])[roptr]).ro_num,len);
AddRO taddro = (AddRO)(allNewRos[curTblIdx][roptr]);
taddro.ro_stat = 4;
allNewRos[curTblIdx].RemoveAt(roptr);
allNewRos[curTblIdx].Insert(roptr,taddro);
}
// Write ID
NewFSTFile.Write(id);
// Write accID
putFixed(NewFSTFile,num,len);
}
// Save remaining RO info
while ((roptr = getROAccLess(null))!=-1)
{
extra += (len+4); //sizeof(ulong 16bit)+len
NewFSTFile.Write(((AddRO)(allNewRos[curTblIdx])[roptr]).ro_id);
putFixed(NewFSTFile,((AddRO)(allNewRos[curTblIdx])[roptr]).ro_num,len);
AddRO taddro = (AddRO)(allNewRos[curTblIdx][roptr]);
taddro.ro_stat = 4;
allNewRos[curTblIdx].RemoveAt(roptr);
allNewRos[curTblIdx].Insert(roptr,taddro);
}
if (extra > 0)
AddLocation(end-1,extra);
}
public void nextIDandOffset(ref uint nxtid, ref uint nxtoff)
{
int roptr = 0, romin = -1;
int numroptr = (allNewRos[curTblIdx]).Count;
int grpptr = 0, grpmin = -1;
int numgrpptr = (allNewGrps[curTblIdx]).Count;
while (roptr < numroptr)
{
if (((AddRO)(allNewRos[curTblIdx])[roptr]).ro_id > nxtid &&
(romin == -1 || ((AddRO)(allNewRos[curTblIdx])[roptr]).ro_id < ((AddRO)(allNewRos[curTblIdx])[romin]).ro_id))
romin = roptr;
roptr++;
}
while (grpptr < numgrpptr)
{
if (((AddGroup)(allNewGrps[curTblIdx])[grpptr]).grp_id > nxtid &&
(grpmin == -1 || ((AddGroup)(allNewGrps[curTblIdx])[grpptr]).grp_id < ((AddGroup)(allNewGrps[curTblIdx])[grpmin]).grp_id))
grpmin = grpptr;
grpptr++;
}
if (grpmin != -1)
{
if ((romin != -1) && ((AddRO)(allNewRos[curTblIdx])[romin]).ro_id < ((AddGroup)(allNewGrps[curTblIdx])[grpmin]).grp_id)
{
AddRO taddro = (AddRO)(allNewRos[curTblIdx][romin]);
taddro.ro_stat = 3;
allNewRos[curTblIdx].RemoveAt(romin);
allNewRos[curTblIdx].Insert(romin,taddro);
nxtid = ((AddRO)(allNewRos[curTblIdx])[romin]).ro_id;
nxtoff = (uint)((AddRO)(allNewRos[curTblIdx])[romin]).ro_offset;
}
else
{
AddGroup taddgroup = (AddGroup)(allNewGrps[curTblIdx][grpmin]);
taddgroup.grp_stat = 3;
allNewGrps[curTblIdx].RemoveAt(grpmin);
allNewGrps[curTblIdx].Insert(grpmin,taddgroup);
nxtid = ((AddGroup)(allNewGrps[curTblIdx])[grpmin]).grp_id;
nxtoff = ((AddGroup)(allNewGrps[curTblIdx])[grpmin]).grp_offset;
}
}
else
{
if (romin != -1)
{
AddRO taddro = (AddRO)(allNewRos[curTblIdx][romin]);
taddro.ro_stat = 3;
allNewRos[curTblIdx].RemoveAt(romin);
allNewRos[curTblIdx].Insert(romin,taddro);
nxtid = ((AddRO)(allNewRos[curTblIdx])[romin]).ro_id;
nxtoff = (uint)((AddRO)(allNewRos[curTblIdx])[romin]).ro_offset;
}
else
{
nxtid = 0;
nxtoff = 0;
}
}
}
public void processIdRecords(BinaryWriter NewFstFile,uint end)
{
int extra = 0;
uint nxtid =0, nxtoff=0;
nextIDandOffset(ref nxtid,ref nxtoff);
while (brROFst.BaseStream.Seek(0,System.IO.SeekOrigin.Current) < end)
{
// Read ID
uint id = brROFst.ReadUInt32();
// Look for new entries that precede ID
while (nxtid != 0 && nxtid < id)
{
extra += 8; // sizeof(ulong 16bit) * 2
NewFstFile.Write(nxtid);
NewFstFile.Write(nxtoff);
nextIDandOffset(ref nxtid,ref nxtoff); // passed by reference
}
// Write ID
NewFstFile.Write(id);
// Read Offset
uint off = brROFst.ReadUInt32();
// Write new offset
NewFstFile.Write(newLocation(off));
}
// Save new RO entries and Group entries
while (nxtid != 0)
{
extra += 8; // sizeof(ulong 16bit)*2
NewFstFile.Write(nxtid);
NewFstFile.Write(nxtoff);
nextIDandOffset(ref nxtid,ref nxtoff); // passed by reference
}
if (extra != 0)
AddLocation(end-1,extra);
}
/*
* Merge the changes into the RO.FST file (usually Approved directory)
*/
public void CreateMergedFSTFile(string NewFStName)
{
BinaryWriter NewFSTFile=null;
// Open a new FST file for writing
try
{
NewFSTFile = new BinaryWriter(File.Open(NewFStName,System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite,FileShare.None));
}
catch (Exception e)
{
MessageBox.Show("Error Opening "+NewFStName +"\n\n" + e.Message,"Approval Error");
}
// Write the RO.FST header
Header.Write(NewFSTFile);
// Position the old FST file past the header
brROFst.BaseStream.Seek(Header.GetStructSize(),System.IO.SeekOrigin.Begin);
// Loop through each database
for (short i=0; i < numDatabases; i++)
{
// Set the current table index used to access the allNewRos,
// allNewGrps, and allDifferences arrays
curTblIdx = i;
// Loop through the Group and RO records
// Update the RO Group information
processGroupRecords(NewFSTFile,((ROFST_DbInfo)DatabasesInfo[i]).dbiIL);
if (((ROFST_DbInfo)DatabasesInfo[i]).dbiAW == 0)
((ROFST_DbInfo)DatabasesInfo[i]).dbiAW = maxaw;
if (((ROFST_DbInfo)DatabasesInfo[i]).dbiType == 0)
((ROFST_DbInfo)DatabasesInfo[i]).dbiType = maxtype;
((ROFST_DbInfo)DatabasesInfo[i]).dbiGL = whereisgl;
((ROFST_DbInfo)DatabasesInfo[i]).dbiIL = (uint)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current);
// Loop through the ID list
processIdRecords(NewFSTFile,((ROFST_DbInfo)DatabasesInfo[i]).dbiAL);
((ROFST_DbInfo)DatabasesInfo[i]).dbiAL = (uint)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current);
// Loop through the accid list
processAccIdRecords(NewFSTFile,((ROFST_DbInfo)DatabasesInfo[i]).dbiEND,(short)((ROFST_DbInfo)DatabasesInfo[i]).dbiAW);
((ROFST_DbInfo)DatabasesInfo[i]).dbiEND = (uint)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current);
}
// Save the Database info
uint lngbuf = 0;
// Save the current location in the new fst file
uint dblength = (uint)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current);
NewFSTFile.Write(lngbuf);
NewFSTFile.Write(numDatabases);
uint lngval;
ROFST_DbInfo tmpdbinfo = new ROFST_DbInfo();
lngval = (uint)(tmpdbinfo.GetStructSize() * numDatabases);
for (int i=0;i<numDatabases;i++)
{
NewFSTFile.Write(((ROFST_DbInfo)DatabasesInfo[i]).dbiID);
NewFSTFile.Write(((ROFST_DbInfo)DatabasesInfo[i]).dbiType);
NewFSTFile.Write(((ROFST_DbInfo)DatabasesInfo[i]).dbiAW);
NewFSTFile.Write(((ROFST_DbInfo)DatabasesInfo[i]).dbiGL);
NewFSTFile.Write(((ROFST_DbInfo)DatabasesInfo[i]).dbiIL);
NewFSTFile.Write(((ROFST_DbInfo)DatabasesInfo[i]).dbiAL);
NewFSTFile.Write(((ROFST_DbInfo)DatabasesInfo[i]).dbiEND);
NewFSTFile.Write(lngval);
lngval += (uint)((ROFST_DbInfo)DatabasesInfo[i]).dbiTitle.Length + 1;
NewFSTFile.Write(lngval);
lngval += (uint)((ROFST_DbInfo)DatabasesInfo[i]).dbiAP.Length + 1;
}
for (short i=0;i<numDatabases;i++)
{
WriteString(NewFSTFile,((ROFST_DbInfo)DatabasesInfo[i]).dbiTitle,true);
WriteString(NewFSTFile,((ROFST_DbInfo)DatabasesInfo[i]).dbiAP,true);
}
// locate the end
uint dbend = (uint)NewFSTFile.Seek(0,System.IO.SeekOrigin.Current); // ftell(ofile)
// How long is the db info
NewFSTFile.Seek((int)dblength,System.IO.SeekOrigin.Begin);
lngbuf = dbend-dblength-4; //dbend-dblength-sizeof(dblength)
NewFSTFile.Write(lngbuf);
// Go to the beginning of the new file
NewFSTFile.Seek(0,System.IO.SeekOrigin.Begin);
// Save the header again
if (Header.hcYear==0)
Header.SetHeader(dblength); // sets the header and date/time
else
Header.dboffset = dblength;
Header.Write(NewFSTFile);
NewFSTFile.Flush();
NewFSTFile.Close();
uint test = (uint) Header.hcHund;
// stamp the new FST file with the RO.FST header date/time
DateTime dt = new DateTime((int)Header.hcYear,(int)Header.hMonth,(int)Header.hDay,(int)Header.hcHour,(int)Header.hcMin,(int)Header.hcSec,(int)Header.hcHund);
File.SetLastWriteTime(NewFStName,dt);
}
}
/*************************************************************************/
public class strEntry
{
public strEntry()
{
}
public virtual string toText(int mi){return "";}
public virtual int getLength(int mi){return 0;}
}
public class seText : strEntry
{
public string str;
public int len;
public seText(string instr, int inlen)
{
str = instr.Substring(0,inlen);
len = inlen;
}
public override string toText(int mi)
{
return str;
}
public override int getLength(int mi)
{
return len;
}
}
public class seUser : strEntry
{
string uvalue;
int len;
public seUser(string str, int l)
{
uvalue = ROProcessTools.evaluate(str,l);
len = uvalue.Length;
}
public override string toText(int mi)
{
return uvalue;
}
public override int getLength(int mi)
{
return len;
}
}
public class strList
{
public varList vList;
public menuList mList;
private ArrayList aryStrEntry;
public strList(string str)
{
vList = new varList();
mList = new menuList();
aryStrEntry = new ArrayList();
Process(str,str.Length);
}
public strList(string str, int l, varList vl, menuList ml)
{
if (vl == null)
vList = new varList();
else
vList = vl;
if (ml == null)
mList = new menuList();
else
mList = ml;
if (aryStrEntry == null)
aryStrEntry = new ArrayList();
Process(str.Substring(0,l),l);
}
public void Add(strEntry se)
{
aryStrEntry.Add(se);
}
public void processCondition(string cnd, string opt, int lc, int lo)
{
// equaluate condition
string stat = ROProcessTools.evaluate(cnd,lc);
int ls = stat.Length;
// look for match - remember default
string match=null;
int matchlen = 0;
string def = null;
int deflen = 0;
while (lo > 0 && match == null)
{
int end = ROProcessTools.matchingBrace(opt);
int eq = opt.IndexOf('=');
int len = end + 1; // +1 to include the '}'
int li = eq-1;
int ld = len-li-3; // One for '{', '=' and '}'
if (def == null || eq == 1)
{
def = opt.Substring(eq+1,ld);
deflen = ld;
}
if (ls == li && stat.StartsWith(opt.Substring(1,li)))
{
match = opt.Substring(eq+1,ld);
matchlen = ld;
}
opt = opt.Substring(len);
lo -= len;
}
// if match process option - or process default
if (match == null)
{
match = def;
matchlen = deflen;
}
Process(match,matchlen);
}
public void processBrace(string str, int l, ref int nfnd)
{
int nxt = ROProcessTools.nextDelimiter("{=",str,l); // -1 means not found
if(nxt == -1) // varUse
{
strList found = null;
found = vList.lookFor(str,l);
if (found != null)
Add(new seVarUse(found));
else
nfnd = 1;
}
else
{
if (str[nxt] == '{') // conditonal or menu
{
if(nxt==0)
{ // menu
mList.Process(str,l,vList);
Add(new seMenuUse(mList));
}
else
{ // conditional
processCondition(str, str.Substring(nxt), nxt, l -nxt);
}
}
else
{ // must be variable definiton
vList.Add(str, str.Substring(nxt+1), nxt, l - nxt - 1, mList);
}
}
}
public void Process (string str, int len)
{
int nxtDlm = -1; // -1 = not found
while (len > 0)
{
nxtDlm = ROProcessTools.nextDelimiter("{",str,len);
if (nxtDlm == -1)
{
// add entire string as is
Add(new seText(str,len));
//str = str.Substring(len); don't think we need to do this
len = 0;
}
else
{
int cnt = 0;
if (nxtDlm > 0)
{
// add preceeding text
Add(new seText(str,nxtDlm));
str = str.Substring(nxtDlm);
len-=nxtDlm;
}
// add text group by delimiter, including
// the delimiters
nxtDlm = ROProcessTools.matchingBrace(str)+1;
cnt = nxtDlm;
int nfnd = 0;
processBrace(str.Substring(1),cnt-2,ref nfnd);
if (nfnd > 0)
{
Add(new seText(str,cnt));
}
// position to next delimiter grouping
len -= cnt;
str = str.Substring(nxtDlm);
}
}
}
public string toText(int mi)
{
StringBuilder bldstr = new StringBuilder();
for (int i=0; i < aryStrEntry.Count; i++)
{
bldstr.Append(((strEntry)aryStrEntry[i]).toText(mi));
}
return bldstr.ToString();
}
public int getLength(int mi)
{
int rtnval = 0;
for (int i=0; i < aryStrEntry.Count; i++)
{
rtnval += (((strEntry)aryStrEntry[i]).getLength(mi));
}
return rtnval;
}
public int menuCount()
{
return mList.getCount();
}
public string getIds(ref int cnt)
{
// return a string of the IDs
return mList.getIds(ref cnt);
}
}
public class strList2
{
private ArrayList aryStrEntry;
public strList2(string str)
{
int l=str.Length;
if (aryStrEntry == null)
aryStrEntry = new ArrayList();
while(l > 0)
{
int ptr=ROProcessTools.nextDelimiter("<",str,l);
int cptr = (ptr==-1)?-1:ROProcessTools.nextDelimiter(">",str.Substring(ptr,str.Length - ptr),str.Length-ptr);
if(ptr == -1 || (ptr>-1 && cptr == -1))
{
Add(new seText(str,l));
l=0;
}
else
{
int cnt = ptr; //(int)(ptr-str);
if(cnt > 0)
{
Add(new seText(str,cnt));
l-=cnt;
str = str.Substring(ptr); // str=ptr
}
ptr=ROProcessTools.nextDelimiter(">",str,l)+1;
cnt = ptr;//(int)(ptr-str);
string tmpstr = str.Substring(1);
Add(new seUser(tmpstr,cnt-2));
l-=cnt;
str = str.Substring(ptr);//str=ptr;
}
}
}
public void Add (strEntry se)
{
aryStrEntry.Add(se);
}
public string toText()
{
StringBuilder bldstr = new StringBuilder();
for (int i=0; i < aryStrEntry.Count; i++)
{
bldstr.Append(((strEntry)aryStrEntry[i]).toText(0));
}
return bldstr.ToString();
}
}
public class varEntry
{
string Name;
int Len;
strList Definition;
public varEntry(string InName, string InDef, int lenInName, int lenInDef, varList vlist, menuList mlist)
{
Definition = new strList(InDef,lenInDef,vlist,mlist);
Name = InName.Substring(0,lenInName);
Len = lenInName;
}
public strList lookFor(string nam, int l)
{
string tname = nam.Substring(0,l);
if (l == Len && (Name.CompareTo(tname)==0))
return Definition; // found
return null; // not found
}
}
public class varList
{
ArrayList varEntryAry;
public varList()
{
varEntryAry = new ArrayList();
}
public void Add(string InName, string InDef, int lenInName, int lenInDef, menuList mlist)
{
varEntry tmpEntry = new varEntry(InName,InDef,lenInName,lenInDef,null,mlist);
varEntryAry.Add(tmpEntry);
}
public strList lookFor(string str, int len)
{
strList rtnval = null;
for (int i = 0; (rtnval == null) && (i < varEntryAry.Count); i++)
{
rtnval = ((varEntry)varEntryAry[i]).lookFor(str,len);
}
return rtnval;
}
}
public class seVarUse : strEntry
{
strList Def;
public seVarUse(strList d)
{
Def = d;
}
public override string toText(int mi)
{
return Def.toText(mi);
}
public override int getLength(int mi)
{
return Def.getLength(mi);
}
}
public class menuEntry
{
byte id;
strList definition;
public menuEntry(string idptr,string def,int li,int ld,varList vlst)
{
definition = new strList(def, ld, vlst,null);
// save the id
if(li != 0)
id=(byte)idptr[0];
else
id=0;
}
public int getLength(int mi)
{
if(mi==(int)id || mi==-1)
return definition.getLength(mi);
else
return 0;
}
public virtual string toText(int mi)
{
if (mi == id || mi==-1)
return definition.toText(mi);
else
return "";
}
public string getID()
{
string rtnstr = id.ToString();
return rtnstr;
}
public int getCount()
{
return 1;
}
}
public class menuList : strEntry
{
ArrayList aryMenuList;
public menuList()
{
aryMenuList = new ArrayList();
}
public void Add(menuEntry MnuEntry)
{
aryMenuList.Add(MnuEntry);
}
private int _getLength(int mi)
{
int lcnt = aryMenuList.Count;
int rtnval =0;
for (int i=0; i < lcnt; i++)
{
rtnval += (((menuEntry)aryMenuList[i])).getLength(mi);
}
return rtnval;
}
private int _getLenAndLookat(int mi, ref int lookat)
{
int len =0;
lookat = mi;
if (aryMenuList.Count > 0)
{
len=_getLength(lookat);
if (len ==0)
{
lookat = 0;
len = _getLength(lookat);
}
if (len == 0)
{
lookat = -1;
len = _getLength(lookat);
}
}
return len;
}
public override int getLength(int mi)
{
int lookat=0;
return _getLenAndLookat(mi,ref lookat);
}
public override string toText(int mi)
{
StringBuilder rtnstr = new StringBuilder();
int lookat=0;
int len = _getLenAndLookat(mi,ref lookat);
if (aryMenuList.Count > 0)
{
for (int i = 0; i< aryMenuList.Count; i++)
{
string roval = ((menuEntry)aryMenuList[i]).toText(lookat);
if (lookat == -1)
{
// For Approve Individual, show all possible RO
// values (for conditional RO's)
// We may need to add a flag here later on when
// this logic is used in the Procedure Editor.
if (i > 0 && !roval.Equals(""))
rtnstr.Append("\n");
}
rtnstr.Append(roval);
}
}
return rtnstr.ToString();
}
public string getIds(ref int cnt)
{
StringBuilder rtnstr = new StringBuilder();
cnt = getCount();
int arycnt = aryMenuList.Count;
for (int i=0; i<arycnt; i++)
{
rtnstr.Append(((menuEntry)aryMenuList[i]).getID());
}
return rtnstr.ToString();
}
public int getCount()
{
int rtncnt=0;
int arycnt = aryMenuList.Count;
for (int i=0; i<arycnt; i++)
{
rtncnt+=(((menuEntry)aryMenuList[i]).getCount());
}
return rtncnt;
}
public void Process(string str,int l, varList v)
{
// get each piece and add a new entry
do
{
int end= ROProcessTools.matchingBrace(str);
int eq=str.IndexOf('=');
int len = end + 1; // +1 to include the '}'
int li = eq - 1;
int ld = len-li-3; // One for '{', '=' and '}'
Add(new menuEntry(str.Substring(1),str.Substring(eq+1),li,ld,v));
// point to the next piece
str = str.Substring(len);
l -= len;
} while(l > 0);
}
}
public class seMenuUse : strEntry
{
menuList ml;
public seMenuUse(menuList m)
{
ml=m;
}
public override string toText(int mi)
{
return ml.toText(mi);
}
public override int getLength(int mi)
{
return ml.getLength(mi);
}
}
}