Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
474 lines
9.0 KiB
C++
474 lines
9.0 KiB
C++
// HNode.cpp: implementation of the HNode class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "Peeper.h"
|
|
#include "HNode.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[]=__FILE__;
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
//CArray<HNode,HNode &> HNode::Guff;
|
|
//DWORD HNode::ObjCount;
|
|
|
|
HNode *HNode::Create()
|
|
{
|
|
return new HNode;
|
|
}
|
|
|
|
void HNode::Delete(HNode *node)
|
|
{
|
|
delete node;
|
|
}
|
|
|
|
|
|
HNode::HNode()
|
|
{
|
|
Children.SetSize(0,5);
|
|
Clones.SetSize(0,5);
|
|
Original=NULL;
|
|
Parent=NULL;
|
|
Item=NULL;
|
|
Flag=0;
|
|
}
|
|
|
|
|
|
bool HNode::AddLocalFile(const CString &fname,const CString &path)
|
|
{
|
|
return NewChild()->ParseLocalFile(fname,path);
|
|
}
|
|
|
|
bool HNode::ParseLocalFile(const CString &fname,const CString &path)
|
|
{
|
|
FName=fname;
|
|
Path=path;
|
|
Flag=0;
|
|
|
|
FName.Replace('/','\\');
|
|
int loc=FName.ReverseFind('\\');
|
|
if(loc>=0) // If path was included add it
|
|
{
|
|
Path+=FName.Left(loc+1);
|
|
FName=FName.Mid(loc+1);
|
|
}
|
|
|
|
|
|
CString fbuf;
|
|
if(SysGetFile(FName,Path,fbuf))
|
|
{
|
|
return Parse(fbuf.GetBuffer(0));
|
|
fbuf.ReleaseBuffer();
|
|
}
|
|
else
|
|
{
|
|
return ParseGlobalFile(fname);
|
|
}
|
|
}
|
|
|
|
bool HNode::ParseGlobalFile(const CString &fname)
|
|
{
|
|
FName=fname;
|
|
Flag=0;
|
|
|
|
CString path,fbuf;
|
|
if(PathMan->GetFile(FName,Path,fbuf))
|
|
{
|
|
FName.Replace('/','\\');
|
|
int loc=FName.ReverseFind('\\');
|
|
if(loc>=0) // If path was included add it
|
|
{
|
|
Path+=FName.Left(loc+1);
|
|
FName=FName.Mid(loc+1);
|
|
}
|
|
|
|
return Parse(fbuf.GetBuffer(0));
|
|
}
|
|
else
|
|
{
|
|
Flag|=HN_NOTFOUND;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool HNode::IsAbove(HNode *node)
|
|
{
|
|
if(IsSameName(node)) return true;
|
|
if(Parent==NULL) return false;
|
|
return Parent->IsAbove(node);
|
|
}
|
|
|
|
bool HNode::Parse(char *fbuf)
|
|
{
|
|
|
|
if(Parent && Parent->IsAbove(this)) // If the file is in the Tree we have a loop
|
|
{
|
|
Flag|=HN_LOOP;
|
|
return false;
|
|
}
|
|
|
|
// If the file has been parsed before copy it
|
|
if(CopyFromTree(this))
|
|
return true;
|
|
|
|
|
|
int start=0;
|
|
int bufsize=strlen(fbuf);
|
|
bool foundinclude=false;
|
|
int sd,ed;
|
|
|
|
for(;;)
|
|
{
|
|
|
|
|
|
for(foundinclude=false;!foundinclude;)
|
|
{
|
|
while(
|
|
!(fbuf[start]=='/' && (fbuf[start+1]=='/') || fbuf[start+1]=='*') &&
|
|
fbuf[start]!='#' &&
|
|
start<bufsize)
|
|
start++;
|
|
|
|
if((fbuf[start]=='/') && (fbuf[start+1]=='/'))
|
|
{
|
|
while(fbuf[start]!='\x0D' && start<bufsize) start++; // swallow white spaces
|
|
if(start>=bufsize) return true;
|
|
}
|
|
else if((fbuf[start]=='/') && (fbuf[start+1]=='*'))
|
|
{
|
|
start+=2;
|
|
if(start>=bufsize) {Flag|=HN_PARSEERROR; return true;}
|
|
while(!(fbuf[start]!='*' && fbuf[start+1]!='/') && start<bufsize) start++; // swallow white spaces
|
|
if(start>=bufsize) {Flag|=HN_PARSEERROR; return true;}
|
|
}
|
|
else
|
|
|
|
{
|
|
if(start>=bufsize) return true;
|
|
start++;
|
|
while((fbuf[start]==' ' || fbuf[start]=='\t') && fbuf[start]!='\x0D') start++; // swallow white spaces
|
|
if(!strncmp(fbuf+start,"include",7))
|
|
{
|
|
start+=7;
|
|
foundinclude=true;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(sd=start;fbuf[sd]!='\"' && fbuf[sd]!='\x0D';sd++);
|
|
if(fbuf[sd]=='\"')
|
|
{
|
|
sd++;
|
|
for(ed=sd;fbuf[ed]!='\"' && fbuf[ed]!='\x0D';ed++);
|
|
if(fbuf[ed]!='\"') { Flag|=HN_PARSEERROR; return true; }
|
|
fbuf[ed]=0;
|
|
NewChild()->ParseLocalFile(fbuf+sd,Path);
|
|
}
|
|
else
|
|
{
|
|
for(sd=start;fbuf[sd]!='<' && fbuf[sd]!='\x0D';sd++);
|
|
if(fbuf[sd]=='\x0D') { Flag|=HN_PARSEERROR; return true; }
|
|
sd++;
|
|
for(ed=sd;fbuf[ed]!='>' && fbuf[ed]!='\x0D';ed++);
|
|
if(fbuf[ed]!='>') { Flag|=HN_PARSEERROR; return true; }
|
|
fbuf[ed]=0;
|
|
NewChild()->ParseGlobalFile(fbuf+sd);
|
|
}
|
|
start=ed+2;
|
|
}
|
|
}
|
|
|
|
bool HNode::CopyFromTreeDown(HNode *dest)
|
|
{
|
|
if(IsCopy()) return false;
|
|
if(IsSameName(dest))
|
|
{
|
|
dest->Copy(this);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
int size=Children.GetSize();
|
|
for(int i=0;i<size;i++)
|
|
{
|
|
HNode *node=Children[i];
|
|
if(node->CopyFromTreeDown(dest))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool HNode::CopyFromTree(HNode *dest)
|
|
{
|
|
if(!Parent) return false;
|
|
|
|
for(int i=0;i<Parent->Children.GetSize();i++)
|
|
if(Parent->Children[i]!=this && !(Parent->Children[i]->Flag&HN_LOOP))
|
|
{
|
|
if(Parent->Children[i]->CopyFromTreeDown(dest))
|
|
return true;
|
|
}
|
|
return Parent->CopyFromTree(dest);
|
|
}
|
|
|
|
void HNode::FillTree(CTreeCtrl *tree,HNode *stopat,HTREEITEM parent)
|
|
{
|
|
if(stopat==NULL) return;
|
|
|
|
|
|
}
|
|
|
|
|
|
void HNode::FillTree(CTreeCtrl *tree,HTREEITEM parent,int level,int levelmax)
|
|
{
|
|
if(level>levelmax) return;
|
|
Item=parent;
|
|
if(!IsRoot() && level>0)
|
|
{
|
|
Item=AddItem(tree,parent);
|
|
}
|
|
|
|
for(int i=0;i<Children.GetSize();i++)
|
|
{
|
|
Children[i]->FillTree(tree,Item,level+1);
|
|
}
|
|
|
|
}
|
|
|
|
HTREEITEM HNode::AddItem(CTreeCtrl *tree,HTREEITEM parent)
|
|
{
|
|
HTREEITEM itm;
|
|
if(Flag&HN_NOTFOUND || Flag&HN_LOOP)
|
|
{
|
|
CString con;
|
|
if(Flag&HN_NOTFOUND) con+="(Not Found)";
|
|
if(Flag&HN_LOOP) con+="(Circular)";
|
|
itm=tree->InsertItem(Path+FName+con,parent);
|
|
}
|
|
else
|
|
{
|
|
itm=tree->InsertItem(Path+FName,parent);
|
|
}
|
|
tree->SetItemData(itm,(DWORD)this);
|
|
|
|
return itm;
|
|
}
|
|
|
|
|
|
void HNode::FillReverseTree(CTreeCtrl *tree,HTREEITEM parent)
|
|
{
|
|
if(IsRoot()) return;
|
|
HTREEITEM itm=AddItem(tree,parent);
|
|
|
|
if(!Parent) return;
|
|
|
|
Parent->FillReverseTree(tree,itm);
|
|
|
|
int i;
|
|
for(i=0;i<Clones.GetSize();i++)
|
|
if(Clones[i]!=this && Clones[i]->Parent)
|
|
Clones[i]->Parent->FillReverseTree(tree,itm);
|
|
|
|
if(IsCopy())
|
|
{
|
|
if(Original->Parent)
|
|
Original->Parent->FillReverseTree(tree,itm);
|
|
|
|
for(int i=0;i<Original->Clones.GetSize();i++)
|
|
if(Original->Clones[i]!=this && Original->Clones[i]->Parent)
|
|
Original->Clones[i]->Parent->FillReverseTree(tree,itm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void HNode::Copy(HNode *node)
|
|
{
|
|
ASSERT(node!=this);
|
|
Destroy();
|
|
FName=node->FName;
|
|
Path=node->Path;
|
|
Flag=node->Flag;
|
|
PathMan=node->PathMan;
|
|
|
|
Original=node;
|
|
node->Clones.Add(this);
|
|
|
|
|
|
for(int i=0;i<node->Children.GetSize();i++)
|
|
{
|
|
Children.Add(node->Children[i]);
|
|
}
|
|
// VerifyNode();
|
|
}
|
|
|
|
void HNode::Destroy()
|
|
{
|
|
|
|
if(!IsCopy())
|
|
{
|
|
for(int i=0;i<Children.GetSize();i++)
|
|
{
|
|
HNode *node=Children[i];
|
|
ASSERT(node!=NULL);
|
|
ASSERT(node->Parent==this);
|
|
Delete(node);
|
|
Children[i]=NULL;
|
|
}
|
|
}
|
|
|
|
Children.RemoveAll();
|
|
Clones.RemoveAll();
|
|
FName="";
|
|
Path="";
|
|
Flag=0;
|
|
Original=NULL;
|
|
PathMan=NULL;
|
|
}
|
|
|
|
|
|
DWORD HNode::NodeCount()
|
|
{
|
|
int sum=1;
|
|
for(int i=0;i<Children.GetSize();i++)
|
|
{
|
|
sum+=Children[i]->NodeCount();
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
DWORD HNode::TreeSize()
|
|
{
|
|
int sum=sizeof(HNode)+Children.GetSize()*sizeof(HNode *)+FName.GetLength()+Path.GetLength();
|
|
if(!IsCopy())
|
|
{
|
|
for(int i=0;i<Children.GetSize();i++)
|
|
{
|
|
sum+=Children[i]->TreeSize();
|
|
}
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
HNode *HNode::AddChild(HNode *child)
|
|
{
|
|
ASSERT(child!=NULL);
|
|
ASSERT(child->Parent==NULL);
|
|
Children.Add(child);
|
|
child->Parent=this;
|
|
child->PathMan=PathMan;
|
|
return child;
|
|
}
|
|
|
|
void HNode::VerifyNode()
|
|
{
|
|
ASSERT(this);
|
|
for(int i=0;i<Children.GetSize();i++)
|
|
{
|
|
ASSERT(Children[i]);
|
|
ASSERT(Children[i]->Parent);
|
|
ASSERT(Children[i]->Parent==this);
|
|
Children[i]->VerifyNode();
|
|
}
|
|
|
|
}
|
|
|
|
void HNode::ParseDsp(const CString &fname,const CString &path)
|
|
{
|
|
FName=fname;
|
|
Path=path;
|
|
|
|
CString dspbuf;
|
|
// CString path=Path.Left(Path.ReverseFind('\\')+1);
|
|
bool res=SysGetFile(FName,Path,dspbuf);
|
|
ASSERT(res);
|
|
int start=0;
|
|
|
|
start=dspbuf.Find("SOURCE=");
|
|
CString sfname;
|
|
while(start>=0)
|
|
{
|
|
start+=strlen("SOURCE=");
|
|
int endl=dspbuf.Find('\x0D',start);
|
|
if(endl>=0)
|
|
{
|
|
sfname=dspbuf.Mid(start,endl-start);
|
|
if(sfname.Left(2)==".\\") sfname=sfname.Mid(2);
|
|
if(!sfname.Right(4).CompareNoCase(".cpp") || !sfname.Right(2).CompareNoCase(".c"))
|
|
AddLocalFile(sfname,Path);
|
|
}
|
|
|
|
start=dspbuf.Find("SOURCE=",start+1);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
HNode *HNode::Find(const CString fname,HNode *after,bool returnnext)
|
|
{
|
|
if(after==NULL) returnnext=true;
|
|
if(!FName.CompareNoCase(fname))
|
|
{
|
|
if(returnnext) return this;
|
|
if(after==this) returnnext=true;
|
|
}
|
|
|
|
HNode *ret=NULL;
|
|
|
|
|
|
|
|
for(int i=0;i<Children.GetSize();i++)
|
|
{
|
|
ret=Children[i]->Find(fname,after,returnnext);
|
|
if(ret) return ret;
|
|
}
|
|
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void HNode::DrillDownTo(CTreeCtrl *tree)
|
|
{
|
|
if(IsRoot())
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
Parent->DrillDownTo(tree);
|
|
|
|
int i;
|
|
|
|
if(Item==NULL) // If I haven't been added
|
|
{
|
|
for(i=0;i>Parent->Children.GetSize();i++) // Add me and my siblings
|
|
Parent->Children[i]->Item=Parent->Children[i]->AddItem(tree,Parent->Item);
|
|
|
|
ASSERT(Item);
|
|
}
|
|
|
|
for(i=0;i>Children.GetSize();i++) // Add my children
|
|
if(!Children[i]->Item)
|
|
Children[i]->Item=Children[i]->AddItem(tree,Parent->Item);
|
|
|
|
|
|
tree->Expand(Parent->Item,TVE_EXPAND); // Expand my parent
|
|
}
|
|
|
|
|
|
HNode::~HNode()
|
|
{
|
|
Destroy();
|
|
Parent=NULL;
|
|
}
|