Files
RP411/MUNGA/NOTATION.cpp
T
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet',
built on the MUNGA engine and its L4 (Win32/DirectX) platform layer:

- MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend
- RP / RP_L4: Red Planet game logic and Win32 application
- DivLoader, Setup1: asset loader and installer project
- lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies

Removed stale Subversion metadata and added .gitignore/.gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:59:51 -05:00

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, &notepage);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
long
NotationFile::EntryCount(const char *pagename)
{
// let FindNotePage() check this and pagename
NotePage
*notepage;
if (FindNotePage(pagename, &notepage))
{
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, &notepage))
{
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, &notepage))
{
Check(notepage);
if (notepage->FindNote(entryname, &notation))
{
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, &notepage))
{
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, &notepage))
{
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, &notepage))
{
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, &notepage))
{
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, &notepage))
{
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, &notepage, &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, &notation, &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, &notation, &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
//===========================================================================//