Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.
Layout:
engine/ MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
models) + image codec; the minimal rp/ headers the audio HAL needs
game/ reconstructed BT logic + surviving-original BT source + fwd shims
+ WinMain launcher
content/ full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
docs/ format specs + reconstruction ledgers
reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
tools/ MP console emulator + map/resource scanners
One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2111 lines
41 KiB
C++
2111 lines
41 KiB
C++
#include "munga.h"
|
|
#include "notation.h"
|
|
#include "namelist.h"
|
|
|
|
//#############################################################################
|
|
//############## NotationFile ###########################################
|
|
//#############################################################################
|
|
|
|
NotationFile::NotationFile(
|
|
const char *filename,
|
|
Enumeration operation_modes
|
|
)
|
|
{
|
|
Check_Pointer(this);
|
|
//do not check filename here
|
|
|
|
fileName = NULL;
|
|
firstNotePage = lastNotePage = NULL;
|
|
pageCount = cleanPageCount = 0;
|
|
dirtyFlag = False;
|
|
saveNotePage = NULL;
|
|
operationModes = operation_modes;
|
|
|
|
if (filename && *filename)
|
|
{
|
|
Check_Pointer(filename);
|
|
ReadFile(filename);
|
|
}
|
|
Check(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NotationFile::~NotationFile()
|
|
{
|
|
Check(this);
|
|
|
|
NotePage
|
|
*next = firstNotePage;
|
|
|
|
if (dirtyFlag)
|
|
{
|
|
if (fileName && *fileName && !WriteFile())
|
|
{
|
|
std::cerr << "NotationFile: Error writing file '" << fileName <<
|
|
"' - changes lost!" << std::endl;
|
|
}
|
|
}
|
|
|
|
while (next)
|
|
{
|
|
Check(next);
|
|
firstNotePage = next->nextNotePage;
|
|
Unregister_Object(next);
|
|
delete next;
|
|
next = firstNotePage;
|
|
}
|
|
if (fileName)
|
|
{
|
|
Unregister_Pointer(fileName);
|
|
delete fileName;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
NotationFile::PageExists(const char *pagename)
|
|
{
|
|
// let FindNotePage() check this and pagename
|
|
|
|
NotePage
|
|
*notepage;
|
|
|
|
return FindNotePage(pagename, ¬epage);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
long
|
|
NotationFile::EntryCount(const char *pagename)
|
|
{
|
|
// let FindNotePage() check this and pagename
|
|
|
|
NotePage
|
|
*notepage;
|
|
|
|
if (FindNotePage(pagename, ¬epage))
|
|
{
|
|
Check(notepage);
|
|
return ((operationModes&CleanEntryListMode)?notepage->cleanNotationCount:notepage->notationCount);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NotationFile::NotePage*
|
|
NotationFile::SetPage(
|
|
const char *pagename,
|
|
const char *comment
|
|
)
|
|
{
|
|
// let FindNotePage() check this and pagename
|
|
// let AppentPage() or SetComment() check comment
|
|
|
|
NotePage
|
|
*notepage;
|
|
|
|
SetDirty();
|
|
if (!FindNotePage(pagename, ¬epage))
|
|
{
|
|
notepage = AppendPage(pagename, comment);
|
|
}
|
|
else
|
|
{
|
|
notepage->SetComment(comment);
|
|
}
|
|
return notepage;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NotationFile::NotePage*
|
|
NotationFile::AppendPage(
|
|
const char *pagename,
|
|
const char *comment
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
// let SetComment() check comment
|
|
|
|
NotePage
|
|
*notepage;
|
|
|
|
SetDirty();
|
|
notepage = new NotePage(this);
|
|
Register_Object(notepage);
|
|
notepage->SetName(pagename, &cleanPageCount);
|
|
notepage->SetComment(comment);
|
|
AppendNotePage(notepage);
|
|
|
|
return notepage;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
NotationFile::GetEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
const char **contents
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
Check_Pointer(contents);
|
|
|
|
NotePage
|
|
*notepage;
|
|
Notation
|
|
*notation;
|
|
|
|
//---------------
|
|
// return string
|
|
//---------------
|
|
if (FindNotePage(pagename, ¬epage))
|
|
{
|
|
Check(notepage);
|
|
if (notepage->FindNote(entryname, ¬ation))
|
|
{
|
|
Check(notation);
|
|
*contents = notation->GetEntry();
|
|
return True;
|
|
}
|
|
}
|
|
return False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
NotationFile::GetEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
int *value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
Check_Pointer(value);
|
|
|
|
const char
|
|
*contents;
|
|
|
|
//----------------
|
|
// return integer
|
|
//----------------
|
|
if (GetEntry(pagename, entryname, &contents))
|
|
{
|
|
Check_Pointer(contents);
|
|
*value = atoi(contents);
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
NotationFile::GetEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
Scalar *value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
Check_Pointer(value);
|
|
|
|
const char
|
|
*contents;
|
|
|
|
//---------------
|
|
// return scalar
|
|
//---------------
|
|
if (GetEntry(pagename, entryname, &contents))
|
|
{
|
|
Check_Pointer(contents);
|
|
*value = atof(contents);
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
NotationFile::GetEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
double *value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
Check_Pointer(value);
|
|
|
|
const char
|
|
*contents;
|
|
|
|
//---------------
|
|
// return double
|
|
//---------------
|
|
if (GetEntry(pagename, entryname, &contents))
|
|
{
|
|
Check_Pointer(contents);
|
|
*value = atof(contents);
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
NotationFile::GetLogicalEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
Logical *value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
Check_Pointer(value);
|
|
|
|
const char
|
|
*contents;
|
|
|
|
//----------------
|
|
// return Logical
|
|
//----------------
|
|
if (GetEntry(pagename, entryname, &contents))
|
|
{
|
|
Check_Pointer(contents);
|
|
//--------------------------------------------------------
|
|
// these stricmp()'s must not affected by IgnoreCaseModes
|
|
//--------------------------------------------------------
|
|
*value = (!stricmp(contents, "true") || !stricmp(contents, "yes") || atoi(contents) != 0);
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::SetEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
const char *contents
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
if (contents) { Check_Pointer(contents); }
|
|
|
|
NotePage
|
|
*notepage;
|
|
Notation
|
|
*notation;
|
|
|
|
SetDirty();
|
|
//---------------
|
|
// assign string
|
|
//---------------
|
|
if (!FindNotePage(pagename, ¬epage))
|
|
{
|
|
notepage = AppendPage(pagename);
|
|
}
|
|
notation = new Notation;
|
|
Register_Object(notation);
|
|
notation->SetName(entryname, &(notepage->cleanNotationCount));
|
|
notation->SetEntry(contents);
|
|
notepage->UpdateNote(notation);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::SetEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
int value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
|
|
static char
|
|
contents[12];
|
|
std::ostrstream stream(contents, sizeof(contents));
|
|
|
|
stream << value << std::ends;
|
|
|
|
SetEntry(pagename, entryname, contents);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::SetEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
Scalar value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
|
|
static char
|
|
contents[32];
|
|
std::ostrstream stream(contents, sizeof(contents));
|
|
|
|
stream << value << std::ends;
|
|
|
|
SetEntry(pagename, entryname, contents);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::SetEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
double value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
|
|
static char
|
|
contents[64];
|
|
std::ostrstream stream(contents, sizeof(contents));
|
|
|
|
stream << value << std::ends;
|
|
|
|
SetEntry(pagename, entryname, contents);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::SetLogicalEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
Logical value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
|
|
static char
|
|
contents[6];
|
|
std::ostrstream stream(contents, sizeof(contents));
|
|
|
|
if (value)
|
|
{
|
|
stream << "True" << std::ends;
|
|
}
|
|
else
|
|
{
|
|
stream << "False" << std::ends;
|
|
}
|
|
|
|
SetEntry(pagename, entryname, contents);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::AppendEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
const char *contents
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
if (entryname) { Check_Pointer(entryname); }
|
|
if (contents) { Check_Pointer(contents); }
|
|
|
|
NotePage
|
|
*notepage;
|
|
Notation
|
|
*notation;
|
|
|
|
SetDirty();
|
|
//---------------
|
|
// assign string
|
|
//---------------
|
|
if (!FindNotePage(pagename, ¬epage))
|
|
{
|
|
notepage = AppendPage(pagename);
|
|
}
|
|
notation = new Notation;
|
|
Register_Object(notation);
|
|
notation->SetName(entryname, &(notepage->cleanNotationCount));
|
|
notation->SetEntry(contents);
|
|
notepage->AppendNote(notation);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::AppendEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
int value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
|
|
static char
|
|
contents[12];
|
|
std::ostrstream stream(contents, sizeof(contents));
|
|
|
|
stream << value << std::ends;
|
|
|
|
AppendEntry(pagename, entryname, contents);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::AppendEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
Scalar value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
|
|
static char
|
|
contents[32];
|
|
std::ostrstream stream(contents, sizeof(contents));
|
|
|
|
stream << value << std::ends;
|
|
|
|
AppendEntry(pagename, entryname, contents);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::AppendEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
double value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
|
|
static char
|
|
contents[64];
|
|
std::ostrstream stream(contents, sizeof(contents));
|
|
|
|
stream << value << std::ends;
|
|
|
|
AppendEntry(pagename, entryname, contents);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::AppendLogicalEntry(
|
|
const char *pagename,
|
|
const char *entryname,
|
|
Logical value
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
|
|
static char
|
|
contents[6];
|
|
std::ostrstream stream(contents, sizeof(contents));
|
|
|
|
if (value)
|
|
{
|
|
stream << "True" << std::ends;
|
|
}
|
|
else
|
|
{
|
|
stream << "False" << std::ends;
|
|
}
|
|
|
|
AppendEntry(pagename, entryname, contents);
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NameList*
|
|
NotationFile::MakeEntryList(
|
|
const char *pagename,
|
|
const char *entryname_prefix
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
//do not check entryname_prefix here
|
|
|
|
NotePage
|
|
*notepage;
|
|
|
|
//--------------------------------------------------
|
|
// return namelist of matching entries and contents
|
|
//--------------------------------------------------
|
|
if (FindNotePage(pagename, ¬epage))
|
|
{
|
|
return MakeEntryList(notepage, entryname_prefix);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NameList*
|
|
NotationFile::MakeEntryList(
|
|
NotePage *notepage,
|
|
const char *entryname_prefix
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(notepage);
|
|
//do not check entryname_prefix here
|
|
|
|
const char
|
|
*name_prefix = entryname_prefix?entryname_prefix:"\0";
|
|
Check_Pointer(name_prefix);
|
|
const int
|
|
length = strlen(name_prefix);
|
|
NameList
|
|
*namelist;
|
|
Notation
|
|
*notation;
|
|
const char
|
|
*name;
|
|
Logical
|
|
prefix_matches,
|
|
add_entry;
|
|
|
|
//--------------------------------------------------
|
|
// return namelist of matching entries and contents
|
|
//--------------------------------------------------
|
|
namelist = new NameList;
|
|
//do not register namelist
|
|
notation = notepage->firstNotation;
|
|
while (notation)
|
|
{
|
|
Check(notation);
|
|
name = notation->GetName();
|
|
if (name)
|
|
{
|
|
Check_Pointer(name);
|
|
if (operationModes&IgnoreEntryCaseMode)
|
|
{
|
|
prefix_matches = (!strnicmp(name, name_prefix, length));
|
|
}
|
|
else
|
|
{
|
|
prefix_matches = (!strncmp(name, name_prefix, length));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
prefix_matches = (entryname_prefix == NULL);
|
|
}
|
|
if (operationModes&CleanEntryListMode)
|
|
{
|
|
add_entry = (notation->cleanNotation && prefix_matches);
|
|
}
|
|
else if (name)
|
|
{
|
|
add_entry = (prefix_matches);
|
|
}
|
|
else if (operationModes&SkipBlanksListMode)
|
|
{
|
|
add_entry = False;
|
|
}
|
|
else
|
|
{
|
|
//------------------------------------------------------
|
|
// HACK: NameList::AddEntry() should accept name==NULL
|
|
//------------------------------------------------------
|
|
add_entry = False;
|
|
//add_entry = (prefix_matches);
|
|
}
|
|
if (add_entry)
|
|
{
|
|
if (notation->GetEntry())
|
|
{ Check_Pointer(notation->GetEntry()); }
|
|
namelist->AddEntry(name, (void *)notation->GetEntry());
|
|
}
|
|
notation = notation->nextNotation;
|
|
}
|
|
return namelist;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NameList*
|
|
NotationFile::MakePageList(const char *pagename_prefix)
|
|
{
|
|
Check(this);
|
|
//do not check pagename_prefix here
|
|
|
|
const char
|
|
*name_prefix = pagename_prefix?pagename_prefix:"\0";
|
|
Check_Pointer(name_prefix);
|
|
const int
|
|
length = strlen(name_prefix);
|
|
NameList
|
|
*namelist;
|
|
NotePage
|
|
*notepage;
|
|
const char
|
|
*name;
|
|
Logical
|
|
prefix_matches,
|
|
add_page;
|
|
|
|
//-----------------------------------------------------
|
|
// return namelist of matching pagenames and notepages
|
|
//-----------------------------------------------------
|
|
namelist = new NameList;
|
|
//do not register namelist
|
|
notepage = firstNotePage;
|
|
while (notepage)
|
|
{
|
|
Check(notepage);
|
|
name = notepage->GetName();
|
|
if (name)
|
|
{
|
|
Check_Pointer(name);
|
|
if (operationModes&IgnorePageCaseMode)
|
|
{
|
|
prefix_matches = (!strnicmp(name, name_prefix, length));
|
|
}
|
|
else
|
|
{
|
|
prefix_matches = (!strncmp(name, name_prefix, length));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
prefix_matches = (pagename_prefix == NULL);
|
|
}
|
|
if (operationModes&CleanPageListMode)
|
|
{
|
|
add_page = (notepage->cleanPage && prefix_matches);
|
|
}
|
|
else if (name)
|
|
{
|
|
add_page = (prefix_matches);
|
|
}
|
|
else if (operationModes&SkipBlanksListMode)
|
|
{
|
|
add_page = False;
|
|
}
|
|
else
|
|
{
|
|
//------------------------------------------------------
|
|
// HACK: NameList::AddEntry() should accept name==NULL
|
|
//------------------------------------------------------
|
|
add_page = False;
|
|
//add_page = (pagename_prefix==NULL);
|
|
}
|
|
if (add_page)
|
|
{
|
|
namelist->AddEntry(name, (void *)notepage);
|
|
}
|
|
notepage = notepage->nextNotePage;
|
|
}
|
|
return namelist;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AlphaNameList*
|
|
NotationFile::MakeAlphaEntryList(
|
|
const char *pagename,
|
|
const char *entryname_prefix
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
//do not check entryname_prefix here
|
|
|
|
NotePage
|
|
*notepage;
|
|
|
|
//-------------------------------------------------------
|
|
// return alphanamelist of matching entries and contents
|
|
//-------------------------------------------------------
|
|
if (FindNotePage(pagename, ¬epage))
|
|
{
|
|
return MakeAlphaEntryList(notepage, entryname_prefix);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AlphaNameList*
|
|
NotationFile::MakeAlphaEntryList(
|
|
NotePage *notepage,
|
|
const char *entryname_prefix
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(notepage);
|
|
//do not check entryname_prefix here
|
|
|
|
const char
|
|
*name_prefix = entryname_prefix?entryname_prefix:"\0";
|
|
Check_Pointer(name_prefix);
|
|
const int
|
|
length = strlen(name_prefix);
|
|
AlphaNameList
|
|
*namelist;
|
|
Notation
|
|
*notation;
|
|
const char
|
|
*name;
|
|
Logical
|
|
prefix_matches,
|
|
add_entry;
|
|
|
|
//-------------------------------------------------------
|
|
// return alphanamelist of matching entries and contents
|
|
//-------------------------------------------------------
|
|
namelist = new AlphaNameList;
|
|
//do not register namelist
|
|
notation = notepage->firstNotation;
|
|
while (notation)
|
|
{
|
|
Check(notation);
|
|
name = notation->GetName();
|
|
if (name)
|
|
{
|
|
Check_Pointer(name);
|
|
if (operationModes&IgnoreEntryCaseMode)
|
|
{
|
|
prefix_matches = (!strnicmp(name, name_prefix, length));
|
|
}
|
|
else
|
|
{
|
|
prefix_matches = (!strncmp(name, name_prefix, length));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
prefix_matches = (entryname_prefix == NULL);
|
|
}
|
|
if (operationModes&CleanEntryListMode)
|
|
{
|
|
add_entry = (notation->cleanNotation && prefix_matches);
|
|
}
|
|
else if (name)
|
|
{
|
|
add_entry = (prefix_matches);
|
|
}
|
|
else if (operationModes&SkipBlanksListMode)
|
|
{
|
|
add_entry = False;
|
|
}
|
|
else
|
|
{
|
|
//------------------------------------------------------
|
|
// HACK: NameList::AddEntry() should accept name==NULL
|
|
//------------------------------------------------------
|
|
add_entry = False;
|
|
//add_entry = (entryname_prefix==NULL);
|
|
}
|
|
if (add_entry)
|
|
{
|
|
if (notation->GetEntry())
|
|
{ Check_Pointer(notation->GetEntry()); }
|
|
namelist->AddEntry(name, (void *)notation->GetEntry());
|
|
}
|
|
notation = notation->nextNotation;
|
|
}
|
|
return namelist;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AlphaNameList*
|
|
NotationFile::MakeAlphaPageList(const char *pagename_prefix)
|
|
{
|
|
Check(this);
|
|
//do not check pagename_prefix here
|
|
|
|
const char
|
|
*name_prefix = pagename_prefix?pagename_prefix:"\0";
|
|
Check_Pointer(name_prefix);
|
|
const int
|
|
length = strlen(name_prefix);
|
|
AlphaNameList
|
|
*namelist;
|
|
NotePage
|
|
*notepage;
|
|
const char
|
|
*name;
|
|
Logical
|
|
prefix_matches,
|
|
add_page;
|
|
|
|
//----------------------------------------------------------
|
|
// return alphanamelist of matching pagenames and notepages
|
|
//----------------------------------------------------------
|
|
namelist = new AlphaNameList;
|
|
//do not register namelist
|
|
notepage = firstNotePage;
|
|
while (notepage)
|
|
{
|
|
Check(notepage);
|
|
name = notepage->GetName();
|
|
if (name)
|
|
{
|
|
Check_Pointer(name);
|
|
if (operationModes&IgnorePageCaseMode)
|
|
{
|
|
prefix_matches = (!strnicmp(name, name_prefix, length));
|
|
}
|
|
else
|
|
{
|
|
prefix_matches = (!strncmp(name, name_prefix, length));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
prefix_matches = (pagename_prefix == NULL);
|
|
}
|
|
if (operationModes&CleanPageListMode)
|
|
{
|
|
add_page = (notepage->cleanPage && prefix_matches);
|
|
}
|
|
else if (name)
|
|
{
|
|
add_page = (prefix_matches);
|
|
}
|
|
else if (operationModes&SkipBlanksListMode)
|
|
{
|
|
add_page = False;
|
|
}
|
|
else
|
|
{
|
|
//------------------------------------------------------
|
|
// HACK: NameList::AddEntry() should accept name==NULL
|
|
//------------------------------------------------------
|
|
add_page = False;
|
|
//add_page = (pagename_prefix==NULL);
|
|
}
|
|
if (add_page)
|
|
{
|
|
namelist->AddEntry(name, (void *)notepage);
|
|
}
|
|
notepage = notepage->nextNotePage;
|
|
}
|
|
return namelist;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::DeleteEntry(
|
|
const char *pagename,
|
|
const char *entryname
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(entryname);
|
|
|
|
NotePage
|
|
*notepage;
|
|
|
|
//---------------------------
|
|
// if found, delete Notation
|
|
//---------------------------
|
|
if (FindNotePage(pagename, ¬epage))
|
|
{
|
|
Check(notepage);
|
|
SetDirty();
|
|
notepage->DeleteNote(entryname);
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::DeletePage(const char *pagename)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
|
|
NotePage
|
|
*notepage,
|
|
*prev;
|
|
|
|
//----------------------------
|
|
// if found, delete Note_Page
|
|
//----------------------------
|
|
if (FindNotePage(pagename, ¬epage, &prev))
|
|
{
|
|
DeletePage(notepage, prev);
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::ReadFile(const char *filename)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(filename);
|
|
|
|
std::ifstream notefile(filename);
|
|
char buffer[512];
|
|
Logical was_empty = IsEmpty();
|
|
|
|
//-------------------------------
|
|
// store first notation filename
|
|
//-------------------------------
|
|
if (!fileName)
|
|
{
|
|
fileName = new char[strlen(filename) + 1];
|
|
Register_Pointer(fileName);
|
|
strcpy(fileName, filename);
|
|
}
|
|
|
|
//--------------------
|
|
// read notation file
|
|
//--------------------
|
|
if (notefile)
|
|
{
|
|
//Dump( "--- read notation file ---" );
|
|
|
|
while (notefile.getline(buffer, sizeof(buffer)))
|
|
{
|
|
//------------------------------
|
|
// process line of NotationFile
|
|
//------------------------------
|
|
Read(buffer);
|
|
}
|
|
notefile.close();
|
|
Read(NULL); // (reset static variable)
|
|
|
|
//Dump( "--- end ---" );
|
|
}
|
|
if (was_empty)
|
|
{
|
|
dirtyFlag = False;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::ReadText(
|
|
char *start,
|
|
long length
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(start);
|
|
|
|
char
|
|
*stop,
|
|
*buffer;
|
|
Logical
|
|
was_empty = IsEmpty();
|
|
|
|
//--------------------------------
|
|
// read notation file from memory
|
|
//--------------------------------
|
|
stop = start + length;
|
|
while (start < stop)
|
|
{
|
|
//---------------------------------------------------------
|
|
// this must preceed Read() which does not preserve buffer
|
|
//---------------------------------------------------------
|
|
buffer = start;
|
|
start = strchr(buffer, '\0') + 1;
|
|
|
|
//------------------------------
|
|
// process line of NotationFile
|
|
//------------------------------
|
|
Read(buffer);
|
|
}
|
|
Read(NULL); // (reset static variable)
|
|
if (was_empty)
|
|
{
|
|
dirtyFlag = False;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
NotationFile::WriteFile(const char *filename)
|
|
{
|
|
Check(this);
|
|
//do not check filename
|
|
|
|
std::ofstream output;
|
|
|
|
if (filename && *filename)
|
|
{
|
|
Check_Pointer(filename);
|
|
output.open(filename);
|
|
}
|
|
else if (fileName && *fileName)
|
|
{
|
|
Check_Pointer(fileName);
|
|
output.open(fileName);
|
|
}
|
|
else
|
|
{
|
|
return False; // you tried to WriteFile with no default fileName!
|
|
}
|
|
|
|
if (output.is_open())
|
|
{
|
|
Write(output);
|
|
output.close();
|
|
if (filename && *filename)
|
|
{
|
|
if (fileName)
|
|
{
|
|
Unregister_Pointer(fileName);
|
|
delete fileName;
|
|
}
|
|
fileName = new char[strlen(filename) + 1];
|
|
Register_Pointer(fileName);
|
|
strcpy(fileName, filename);
|
|
}
|
|
dirtyFlag = False;
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
long
|
|
NotationFile::SizeOfText()
|
|
{
|
|
Check(this);
|
|
|
|
std::ofstream
|
|
dummy;
|
|
|
|
return Write(dummy, Size_Only);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
long
|
|
NotationFile::WriteText(
|
|
char *buffer,
|
|
long size
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(buffer);
|
|
Verify( size >= 0 );
|
|
|
|
std::ostrstream
|
|
output(buffer, size);
|
|
long
|
|
actual_size;
|
|
|
|
if ((actual_size = Write(output, Text_Memory)) <= size)
|
|
{
|
|
dirtyFlag = False;
|
|
return actual_size;
|
|
}
|
|
|
|
return -1L;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::Abort()
|
|
{
|
|
Check(this);
|
|
dirtyFlag = False;
|
|
this->~NotationFile();
|
|
//this->NotationFile(); //does not compile!
|
|
*this = NotationFile();
|
|
Check(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::DeleteStandardPages()
|
|
{
|
|
Check(this);
|
|
|
|
NotePage
|
|
*prev = NULL,
|
|
*notepage = firstNotePage,
|
|
*next;
|
|
const char
|
|
*name;
|
|
|
|
while (notepage)
|
|
{
|
|
Check(notepage);
|
|
next = notepage->nextNotePage;
|
|
name = notepage->pageName;
|
|
if (*name != '_' && strcmp(name, "LAB_ONLY") != 0)
|
|
{
|
|
DeletePage(notepage, prev);
|
|
}
|
|
else
|
|
{
|
|
prev = notepage;
|
|
}
|
|
notepage = next;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::MarkLabOnly()
|
|
{
|
|
Check(this);
|
|
|
|
if (!IsMarkedLabOnly())
|
|
{
|
|
SetPage("LAB_ONLY","\t// this file has not been approved for release");
|
|
AppendEntry("LAB_ONLY", NULL, (char *)NULL); // (blank line)
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::AppendNotePage(NotePage *notepage)
|
|
{
|
|
Check(this);
|
|
Check(notepage);
|
|
|
|
//---------------------------------
|
|
// append NotePage to NotationFile
|
|
//---------------------------------
|
|
if (!lastNotePage)
|
|
{
|
|
firstNotePage = notepage;
|
|
}
|
|
else
|
|
{
|
|
Check(lastNotePage);
|
|
lastNotePage->nextNotePage = notepage;
|
|
}
|
|
lastNotePage = notepage;
|
|
lastNotePage->nextNotePage = NULL;
|
|
if (notepage->cleanPage)
|
|
{
|
|
++cleanPageCount;
|
|
}
|
|
++pageCount;
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
NotationFile::FindNotePage(
|
|
const char *pagename,
|
|
NotePage **notepage
|
|
)
|
|
{
|
|
//-----------------------------------------------------------------
|
|
// HACK: This routine should be changed to support NULL pagename.
|
|
//-----------------------------------------------------------------
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(notepage);
|
|
|
|
//-------------------------------------------
|
|
// check to see if same as previous NotePage
|
|
//-------------------------------------------
|
|
if (saveNotePage &&
|
|
saveNotePage->pageName &&
|
|
((operationModes&IgnorePageCaseMode &&
|
|
!stricmp(saveNotePage->pageName, pagename)) ||
|
|
(!(operationModes&IgnorePageCaseMode) &&
|
|
!strcmp(saveNotePage->pageName, pagename))))
|
|
{
|
|
Check(saveNotePage);
|
|
*notepage = saveNotePage;
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
//------------------------------
|
|
// search for matching NotePage
|
|
//------------------------------
|
|
NotePage
|
|
*notepg = firstNotePage;
|
|
|
|
while (notepg)
|
|
{
|
|
Check(notepg);
|
|
if (notepg->pageName &&
|
|
((operationModes&IgnorePageCaseMode &&
|
|
!stricmp(notepg->pageName, pagename)) ||
|
|
(!(operationModes&IgnorePageCaseMode) &&
|
|
!strcmp(notepg->pageName, pagename))))
|
|
{
|
|
*notepage = saveNotePage = notepg;
|
|
return True;
|
|
}
|
|
notepg = notepg->nextNotePage;
|
|
}
|
|
}
|
|
//-----------
|
|
// not found
|
|
//-----------
|
|
*notepage = NULL;
|
|
return False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
NotationFile::FindNotePage(
|
|
const char *pagename,
|
|
NotePage **notepage,
|
|
NotePage **prevpage
|
|
)
|
|
{
|
|
//-----------------------------------------------------------------
|
|
// HACK: This routine should be changed to support NULL pagename.
|
|
//-----------------------------------------------------------------
|
|
Check(this);
|
|
Check_Pointer(pagename);
|
|
Check_Pointer(notepage);
|
|
Check_Pointer(prevpage);
|
|
|
|
NotePage
|
|
*notepg = firstNotePage,
|
|
*prev = NULL;
|
|
|
|
//------------------------------
|
|
// search for matching NotePage
|
|
//------------------------------
|
|
while (notepg)
|
|
{
|
|
Check(notepg);
|
|
if (notepg->pageName &&
|
|
((operationModes&IgnorePageCaseMode &&
|
|
!stricmp(notepg->pageName, pagename)) ||
|
|
(!(operationModes&IgnorePageCaseMode) &&
|
|
!strcmp(notepg->pageName, pagename))))
|
|
{
|
|
*notepage = notepg;
|
|
*prevpage = prev;
|
|
return True;
|
|
}
|
|
prev = notepg;
|
|
notepg = notepg->nextNotePage;
|
|
}
|
|
//-----------
|
|
// not found
|
|
//-----------
|
|
*notepage = *prevpage = NULL;
|
|
return False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::DeletePage(
|
|
NotePage *notepage,
|
|
NotePage *prev
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(notepage);
|
|
//do not check prev here
|
|
|
|
//---------------------------
|
|
// remove & delete Note_Page
|
|
//---------------------------
|
|
SetDirty();
|
|
|
|
if (prev)
|
|
{
|
|
Check(prev);
|
|
prev->nextNotePage = notepage->nextNotePage;
|
|
}
|
|
else
|
|
{
|
|
firstNotePage = notepage->nextNotePage;
|
|
}
|
|
if (lastNotePage == notepage)
|
|
{
|
|
lastNotePage = prev;
|
|
}
|
|
if (notepage == saveNotePage)
|
|
{
|
|
saveNotePage = NULL;
|
|
}
|
|
if (notepage->cleanPage)
|
|
{
|
|
--cleanPageCount;
|
|
}
|
|
--pageCount;
|
|
Unregister_Object(notepage);
|
|
delete notepage;
|
|
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::Read(char *buffer)
|
|
{
|
|
Check(this);
|
|
//do not check buffer here
|
|
|
|
static NotePage
|
|
*notepage = NULL;
|
|
Notation
|
|
*notation;
|
|
char
|
|
*token,
|
|
*entry,
|
|
*p;
|
|
Logical
|
|
// blank_line,
|
|
comment_line;
|
|
|
|
if (!buffer)
|
|
{
|
|
//------------------------------
|
|
// reset notepage for next read
|
|
//------------------------------
|
|
notepage = NULL;
|
|
return;
|
|
}
|
|
Check_Pointer(buffer);
|
|
|
|
//--------------------------------
|
|
// find first non-blank character
|
|
//--------------------------------
|
|
p = buffer;
|
|
while (*p == ' ' || *p == '\t')
|
|
{
|
|
++p;
|
|
}
|
|
|
|
//--------------------
|
|
// begin new NotePage
|
|
//--------------------
|
|
if (*p == '[')
|
|
{
|
|
token = p+1;
|
|
if ((p = strchr(token, ']')) != NULL)
|
|
{
|
|
*p = '\0';
|
|
++p;
|
|
}
|
|
notepage = AppendPage(token, p);
|
|
// std::cerr << "[" << notepage->GetName() << "]" << std::endl; // TESTING!
|
|
// notepage->Write( std::cerr ); // TESTING!
|
|
return;
|
|
}
|
|
|
|
//---------------------------------
|
|
// detect blank lines and comments
|
|
//---------------------------------
|
|
// blank_line = (*p == '\0');
|
|
comment_line = Comment_Line(p);
|
|
|
|
//---------------
|
|
// read Notation
|
|
//---------------
|
|
token = p;
|
|
if ((p = strchr(token, '=')) != NULL)
|
|
{
|
|
*p = '\0';
|
|
entry = ++p;
|
|
// if (*entry == '\0')
|
|
// {
|
|
// entry = NULL;
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
entry = NULL;
|
|
}
|
|
if (*token == '\0')
|
|
{
|
|
token = NULL;
|
|
}
|
|
|
|
//------------------------
|
|
// remove trailing blanks
|
|
//------------------------
|
|
if (token && !comment_line)
|
|
{
|
|
p = strchr(token, '\0') - 1;
|
|
while (*p == ' ' || *p == '\t')
|
|
{
|
|
*p = '\0';
|
|
if (--p < token)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!notepage)
|
|
{
|
|
notepage = new NotePage(this);
|
|
Register_Object(notepage);
|
|
AppendNotePage(notepage);
|
|
}
|
|
notation = new Notation;
|
|
Register_Object(notation);
|
|
notation->SetName(token, &(notepage->cleanNotationCount));
|
|
notation->SetEntry(entry);
|
|
notepage->AppendNote(notation);
|
|
// std::cerr << token << "=" << entry << std::endl; // TESTING!
|
|
// notation->Write( std::cerr ); // TESTING!
|
|
// notepage->Write( std::cerr ); // TESTING!
|
|
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
long
|
|
NotationFile::Write(
|
|
std::ostream &stream,
|
|
WriteMode mode
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
NotePage
|
|
*notepg = firstNotePage;
|
|
long
|
|
size = 0;
|
|
|
|
while (notepg)
|
|
{
|
|
Check(notepg);
|
|
size += notepg->WriteNote(stream, mode);
|
|
notepg = notepg->nextNotePage;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
NotationFile::TestInstance() const
|
|
{
|
|
//do not Check(this);
|
|
if (fileName) { Check_Pointer(fileName); }
|
|
if (firstNotePage) { Check_Signature(firstNotePage); }
|
|
if (lastNotePage) { Check_Signature(lastNotePage); }
|
|
if (saveNotePage) { Check_Signature(saveNotePage); }
|
|
return True;
|
|
}
|
|
|
|
//#############################################################################
|
|
//############## NotationFile::Notation #################################
|
|
//#############################################################################
|
|
|
|
NotationFile__Notation::~NotationFile__Notation()
|
|
{
|
|
Check(this);
|
|
|
|
if (notationName)
|
|
{
|
|
Check_Pointer(notationName);
|
|
Unregister_Pointer(notationName);
|
|
delete notationName;
|
|
}
|
|
if (notationEntry)
|
|
{
|
|
Check_Pointer(notationEntry);
|
|
Unregister_Pointer(notationEntry);
|
|
delete notationEntry;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::Notation::SetName(
|
|
const char *entryname,
|
|
long *clean_notation_count
|
|
)
|
|
{
|
|
Check(this);
|
|
//do not check entryname here
|
|
Check_Pointer(clean_notation_count);
|
|
|
|
if (notationName)
|
|
{
|
|
if (cleanNotation)
|
|
{
|
|
cleanNotation = False;
|
|
--(*clean_notation_count);
|
|
}
|
|
Check_Pointer(notationName);
|
|
Unregister_Pointer(notationName);
|
|
delete notationName;
|
|
}
|
|
if (entryname) // (do not add "&& *entryname")
|
|
{
|
|
Check_Pointer(entryname);
|
|
notationName = new char[strlen(entryname) + 1];
|
|
Register_Pointer(notationName);
|
|
strcpy(notationName, entryname);
|
|
cleanNotation = (*notationName && !Comment_Line(notationName));
|
|
}
|
|
else
|
|
{
|
|
notationName = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::Notation::SetEntry(const char *contents)
|
|
{
|
|
Check(this);
|
|
//do not check contents here
|
|
|
|
if (notationEntry)
|
|
{
|
|
Check_Pointer(notationEntry);
|
|
Unregister_Pointer(notationEntry);
|
|
delete notationEntry;
|
|
}
|
|
if (contents) // (do not add "&& *contents")
|
|
{
|
|
Check_Pointer(contents);
|
|
notationEntry = new char[strlen(contents) + 1];
|
|
Register_Pointer(notationEntry);
|
|
strcpy(notationEntry, contents);
|
|
}
|
|
else
|
|
{
|
|
notationEntry = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
long
|
|
NotationFile::Notation::WriteNotation(
|
|
std::ostream &stream,
|
|
NotationFile::WriteMode mode
|
|
) const
|
|
{
|
|
Check(this);
|
|
|
|
// Logical
|
|
// comment_line = True;
|
|
long
|
|
size = 0;
|
|
|
|
if (notationName)
|
|
{
|
|
Check_Pointer(notationName);
|
|
if (mode)
|
|
{
|
|
stream << notationName;
|
|
}
|
|
if (mode != NotationFile::Disk_File)
|
|
{
|
|
size += strlen(notationName);
|
|
}
|
|
// comment_line = Comment_Line(notationName);
|
|
// if (!comment_line)
|
|
// {
|
|
// stream << "=";
|
|
// }
|
|
}
|
|
if (notationEntry)
|
|
{
|
|
Check_Pointer(notationEntry);
|
|
// if (comment_line)
|
|
// {
|
|
// stream << "=";
|
|
// }
|
|
if (mode)
|
|
{
|
|
stream << "=" << notationEntry;
|
|
}
|
|
if (mode != NotationFile::Disk_File)
|
|
{
|
|
size += strlen(notationEntry) + 1;
|
|
}
|
|
}
|
|
if (mode == NotationFile::Disk_File)
|
|
{
|
|
stream << std::endl;
|
|
}
|
|
else if (mode)
|
|
{
|
|
stream << std::ends;
|
|
}
|
|
if (mode != NotationFile::Disk_File)
|
|
{
|
|
size += 1;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
NotationFile::Notation::TestInstance() const
|
|
{
|
|
//do not Check(this);
|
|
if (nextNotation) { Check_Signature(nextNotation); }
|
|
if (notationName) { Check_Pointer(notationName); }
|
|
if (notationEntry) { Check_Pointer(notationEntry); }
|
|
return True;
|
|
}
|
|
|
|
//#############################################################################
|
|
//############## NotationFile::NotePage #################################
|
|
//#############################################################################
|
|
|
|
NotationFile__NotePage::NotationFile__NotePage(NotationFile *notation_file)
|
|
{
|
|
Check_Pointer(this);
|
|
Check(notation_file);
|
|
|
|
notationFile = notation_file;
|
|
nextNotePage = NULL;
|
|
firstNotation = lastNotation = NULL;
|
|
notationCount = cleanNotationCount = 0;
|
|
pageName = pageComment = NULL;
|
|
cleanPage = False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NotationFile__NotePage::~NotationFile__NotePage()
|
|
{
|
|
Check(this);
|
|
|
|
NotationFile::Notation
|
|
*notation = firstNotation;
|
|
|
|
while (notation)
|
|
{
|
|
Check(notation);
|
|
firstNotation = notation->nextNotation;
|
|
Unregister_Object(notation);
|
|
delete notation;
|
|
notation = firstNotation;
|
|
}
|
|
if (pageName)
|
|
{
|
|
Check_Pointer(pageName);
|
|
Unregister_Pointer(pageName);
|
|
delete pageName;
|
|
}
|
|
if (pageComment)
|
|
{
|
|
Check_Pointer(pageComment);
|
|
Unregister_Pointer(pageComment);
|
|
delete pageComment;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::NotePage::SetName(
|
|
const char *pagename,
|
|
long *clean_page_count
|
|
)
|
|
{
|
|
Check(this);
|
|
//do not check pagename here
|
|
Check_Pointer(clean_page_count);
|
|
|
|
if (pageName)
|
|
{
|
|
if (cleanPage)
|
|
{
|
|
cleanPage = False;
|
|
--(*clean_page_count);
|
|
}
|
|
Check_Pointer(pageName);
|
|
Unregister_Pointer(pageName);
|
|
delete pageName;
|
|
}
|
|
if (pagename) // (do not add "&& *pagename")
|
|
{
|
|
Check_Pointer(pagename);
|
|
pageName = new char[strlen(pagename) + 1];
|
|
Register_Pointer(pageName);
|
|
strcpy(pageName, pagename);
|
|
cleanPage = (*pageName && (*pageName != '!') && strcmp(pageName, "LAB_ONLY"));
|
|
}
|
|
else
|
|
{
|
|
pageName = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::NotePage::SetComment(const char *comment)
|
|
{
|
|
Check(this);
|
|
//do not check comment here
|
|
|
|
if (pageComment)
|
|
{
|
|
Check_Pointer(pageComment);
|
|
Unregister_Pointer(pageComment);
|
|
delete pageComment;
|
|
}
|
|
if (comment && *comment)
|
|
{
|
|
Check_Pointer(comment);
|
|
pageComment = new char[strlen(comment) + 1];
|
|
Register_Pointer(pageComment);
|
|
strcpy(pageComment, comment);
|
|
}
|
|
else
|
|
{
|
|
pageComment = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::NotePage::AppendNote(NotationFile::Notation *note)
|
|
{
|
|
Check(this);
|
|
Check(note);
|
|
|
|
//-----------------------------
|
|
// append Notation to NotePage
|
|
//-----------------------------
|
|
if (!lastNotation)
|
|
{
|
|
firstNotation = note;
|
|
}
|
|
else
|
|
{
|
|
Check(lastNotation);
|
|
lastNotation->nextNotation = note;
|
|
}
|
|
lastNotation = note;
|
|
lastNotation->nextNotation = NULL;
|
|
if (note->cleanNotation)
|
|
{
|
|
++cleanNotationCount;
|
|
}
|
|
++notationCount;
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
NotationFile::NotePage::FindNote(
|
|
const char *entryname,
|
|
NotationFile::Notation **note
|
|
)
|
|
{
|
|
NotationFile::Notation
|
|
*prev;
|
|
|
|
return FindNote(entryname, note, &prev);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
NotationFile::NotePage::FindNote(
|
|
const char *entryname,
|
|
NotationFile::Notation **note,
|
|
NotationFile::Notation **prev
|
|
)
|
|
{
|
|
//------------------------------------------------------------------
|
|
// HACK: This routine should be changed to support NULL entryname.
|
|
//------------------------------------------------------------------
|
|
Check(this);
|
|
Check_Pointer(entryname);
|
|
Check_Pointer(note);
|
|
Check_Pointer(prev);
|
|
|
|
NotationFile::Notation
|
|
*notation = firstNotation,
|
|
*previous = NULL;
|
|
|
|
//------------------------------
|
|
// search for matching Notation
|
|
//------------------------------
|
|
while (notation)
|
|
{
|
|
Check(notation);
|
|
if (notation->notationName &&
|
|
((notationFile->operationModes&NotationFile::IgnoreEntryCaseMode &&
|
|
!stricmp(notation->notationName, entryname)) ||
|
|
(!(notationFile->operationModes&NotationFile::IgnoreEntryCaseMode) &&
|
|
!strcmp(notation->notationName, entryname))))
|
|
{
|
|
*note = notation;
|
|
*prev = previous;
|
|
return True;
|
|
}
|
|
previous = notation;
|
|
notation = notation->nextNotation;
|
|
}
|
|
//-----------
|
|
// not found
|
|
//-----------
|
|
*note = *prev = NULL;
|
|
return False;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::NotePage::UpdateNote(NotationFile::Notation *note)
|
|
{
|
|
Check(this);
|
|
Check(note);
|
|
|
|
NotationFile::Notation
|
|
*notation,
|
|
*prev;
|
|
|
|
//------------------------------
|
|
// search for matching Notation
|
|
//------------------------------
|
|
if (FindNote(note->notationName, ¬ation, &prev))
|
|
{
|
|
Check(notation);
|
|
|
|
//------------------
|
|
// replace Notation
|
|
//------------------
|
|
if (prev)
|
|
{
|
|
Check(prev);
|
|
prev->nextNotation = note;
|
|
}
|
|
else
|
|
{
|
|
firstNotation = note;
|
|
}
|
|
if ((note->nextNotation = notation->nextNotation) == NULL)
|
|
{
|
|
lastNotation = note;
|
|
}
|
|
Unregister_Object(notation);
|
|
delete notation;
|
|
}
|
|
else
|
|
{
|
|
//-----------------
|
|
// append Notation
|
|
//-----------------
|
|
AppendNote(note);
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NotationFile::NotePage::DeleteNote(const char *entryname)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(entryname);
|
|
|
|
NotationFile::Notation
|
|
*notation,
|
|
*prev;
|
|
|
|
//------------------------------
|
|
// search for matching Notation
|
|
//------------------------------
|
|
if (FindNote(entryname, ¬ation, &prev))
|
|
{
|
|
Check(notation);
|
|
|
|
//--------------------------
|
|
// remove & delete Notation
|
|
//--------------------------
|
|
if (prev)
|
|
{
|
|
Check(prev);
|
|
prev->nextNotation = notation->nextNotation;
|
|
}
|
|
else
|
|
{
|
|
firstNotation = notation->nextNotation;
|
|
}
|
|
if (lastNotation == notation)
|
|
{
|
|
lastNotation = prev;
|
|
}
|
|
if (notation->cleanNotation)
|
|
{
|
|
--cleanNotationCount;
|
|
}
|
|
--notationCount;
|
|
Unregister_Object(notation);
|
|
delete notation;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
long
|
|
NotationFile::NotePage::WriteNote(
|
|
std::ostream &stream,
|
|
NotationFile::WriteMode mode
|
|
) const
|
|
{
|
|
Check(this);
|
|
|
|
NotationFile::Notation
|
|
*notation = firstNotation;
|
|
long
|
|
size = 0;
|
|
|
|
if (pageName)
|
|
{
|
|
Check_Pointer(pageName);
|
|
if (mode)
|
|
{
|
|
stream << "[" << pageName << "]";
|
|
}
|
|
if (mode != NotationFile::Disk_File)
|
|
{
|
|
size += strlen(pageName) + 2;
|
|
}
|
|
}
|
|
if (pageComment)
|
|
{
|
|
Check_Pointer(pageComment);
|
|
if (mode)
|
|
{
|
|
stream << pageComment;
|
|
}
|
|
if (mode != NotationFile::Disk_File)
|
|
{
|
|
size += strlen(pageComment);
|
|
}
|
|
}
|
|
if (pageName || pageComment)
|
|
{
|
|
if (mode == NotationFile::Disk_File)
|
|
{
|
|
stream << std::endl;
|
|
}
|
|
else if (mode)
|
|
{
|
|
stream << std::ends;
|
|
}
|
|
if (mode != NotationFile::Disk_File)
|
|
{
|
|
size += 1;
|
|
}
|
|
}
|
|
while (notation)
|
|
{
|
|
Check(notation);
|
|
size += notation->WriteNotation(stream, mode);
|
|
notation = notation->nextNotation;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
NotationFile::NotePage::TestInstance() const
|
|
{
|
|
//do not Check(this);
|
|
if (nextNotePage) { Check_Signature(nextNotePage); }
|
|
if (firstNotation) { Check_Signature(firstNotation); }
|
|
if (lastNotation) { Check_Signature(lastNotation); }
|
|
if (pageName) { Check_Pointer(pageName); }
|
|
return True;
|
|
}
|
|
|
|
//#############################################################################
|
|
//############## TestClass() ############################################
|
|
//#############################################################################
|
|
|
|
#if defined(TEST_CLASS)
|
|
#include "notation.tcp"
|
|
#endif
|
|
|
|
//===========================================================================//
|