avp/src/win95/mishchnk.cpp

1999 lines
44 KiB
C++
Raw Normal View History

#include "chunk.hpp"
#include "chnktype.hpp"
#include "mishchnk.hpp"
#include "shpchunk.hpp"
#include "obchunk.hpp"
#include "huffman.hpp"
#ifdef cencon
#define new my_new
#endif
// Class Lockable_Chunk_With_Children functions
#if cencon
#else
extern char * users_name;
#endif
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(mishchnk)
BOOL Lockable_Chunk_With_Children::lock_chunk(File_Chunk & fchunk)
{
if (!fchunk.filename) return FALSE;
if (local_lock) return FALSE; // you can't lock a chunk twice
#if DisableLock
if(external_lock) return FALSE;
local_lock = TRUE;
set_lock_user (users_name);
return TRUE;
#else
if (!fchunk.check_file()) return FALSE;
if (updated_outside || external_lock) return FALSE;
HANDLE rif_file;
unsigned long bytes_read;
int tries = 0;
rif_file = CreateFile (fchunk.filename, GENERIC_WRITE + GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
while(rif_file == INVALID_HANDLE_VALUE && tries<10)
{
rif_file = CreateFile (fchunk.filename, GENERIC_WRITE + GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
tries ++;
clock_t ctime = clock();
double secs = (double)ctime / (double)CLOCKS_PER_SEC;
double secsgone;
do
{
ctime = clock();
secsgone = (double)ctime / (double)CLOCKS_PER_SEC;
}
while( (secsgone-secs)<1);
}
if (rif_file == INVALID_HANDLE_VALUE) {
return FALSE;
}
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> chfptrs;
list_chunks_in_file(& chfptrs, rif_file, identifier);
LIF<int> cfpl(&chfptrs);
if (chfptrs.size()) {
for (; !cfpl.done(); cfpl.next()) {
SetFilePointer (rif_file, cfpl(),0,FILE_BEGIN);
if (file_equals(rif_file)) break;
}
}
if (!cfpl.done()) {
// go to start of chunk
SetFilePointer (rif_file,cfpl(),0,FILE_BEGIN);
// get header list
if (get_head_id())
{
List<int> obhead;
list_chunks_in_file(& obhead, rif_file, get_head_id());
assert (obhead.size() == 1);
int flags;
// go to lock status in header
SetFilePointer(rif_file,obhead.first_entry() + 12,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &flags, 4, &bytes_read, 0);
SetFilePointer(rif_file,-4,0,FILE_CURRENT);
flags |= GENERAL_FLAG_LOCKED;
WriteFile (rif_file, (long *) &flags, 4, &bytes_read, 0);
WriteFile (rif_file, (long *) &users_name[0], 16, &bytes_read, 0);
}
}
local_lock = TRUE;
set_lock_user (users_name);
CloseHandle (rif_file);
return TRUE;
#endif
}
BOOL Lockable_Chunk_With_Children::unlock_chunk (File_Chunk & fchunk, BOOL updateyn)
{
if (updateyn) {
updated = TRUE;
}
#if DisableLock
local_lock = FALSE;
(void)fchunk;
#else
else
{
fchunk.check_file();
if (updated_outside || external_lock) return FALSE;
HANDLE rif_file;
unsigned long bytes_read;
rif_file = CreateFile (fchunk.filename, GENERIC_WRITE + GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
if (rif_file == INVALID_HANDLE_VALUE) {
return FALSE;
}
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> chfptrs;
list_chunks_in_file(& chfptrs, rif_file, identifier);
List<obinfile> obs;
char name[50];
LIF<int> ofpl(&chfptrs);
if (chfptrs.size()) {
for (; !ofpl.done(); ofpl.next()) {
SetFilePointer (rif_file, ofpl(),0,FILE_BEGIN);
if (file_equals(rif_file)) break;
}
}
if (!ofpl.done()) {
// go to start of chunk
SetFilePointer (rif_file,ofpl(),0,FILE_BEGIN);
// get header list
if (get_head_id())
{
List<int> obhead;
list_chunks_in_file(& obhead, rif_file, get_head_id());
assert (obhead.size() == 1);
int flags;
// go to lock status in header
SetFilePointer(rif_file,obhead.first_entry() + 12,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &flags, 4, &bytes_read, 0);
SetFilePointer(rif_file,-4,0,FILE_CURRENT);
flags &= ~GENERAL_FLAG_LOCKED;
WriteFile (rif_file, (long *) &flags, 4, &bytes_read, 0);
WriteFile (rif_file, (long *) &users_name[0], 16, &bytes_read, 0);
}
}
local_lock = FALSE;
CloseHandle (rif_file);
}
#endif
return TRUE;
}
BOOL Lockable_Chunk_With_Children::update_chunk_in_file(HANDLE &rif_file)
{
unsigned long bytes_read;
int length = 0;
const char * hd_id = get_head_id();
if (!hd_id) return FALSE;
SetFilePointer (rif_file,0,0,FILE_BEGIN);
//twprintf("\nLooking for chunks in file\n");
List<int> shpfptrs;
list_chunks_in_file(& shpfptrs, rif_file, identifier);
// look through chunks for the save of our current chunk
//twprintf("Checking each chunk\n");
LIF<int> sfpl(&shpfptrs);
if (shpfptrs.size()) {
for (; !sfpl.done(); sfpl.next()) {
SetFilePointer (rif_file, sfpl()+8,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &(length), 4, &bytes_read, 0);
SetFilePointer (rif_file, sfpl(),0,FILE_BEGIN);
if (file_equals(rif_file)) break;
}
}
// then load the file after that chunk into a buffer,
// output the chunk and write the buffer
// unless the chunk is the last one in the file
//twprintf("Updating file\n");
if (!sfpl.done())
{
int file_length = GetFileSize(rif_file,0);
if (file_length > (sfpl() + length)) {
SetFilePointer (rif_file, sfpl() + length,0,FILE_BEGIN);
char * tempbuffer;
tempbuffer = new char [file_length - (sfpl() + length)];
ReadFile (rif_file, (long *) tempbuffer, (file_length - (sfpl() + length)), &bytes_read, 0);
SetFilePointer (rif_file, sfpl() ,0,FILE_BEGIN);
if (!deleted)
{
size_chunk();
output_chunk(rif_file);
}
WriteFile (rif_file, (long *) tempbuffer, (file_length - (sfpl() + length)), &bytes_read, 0);
delete [] tempbuffer;
SetEndOfFile (rif_file);
}
else{
SetFilePointer (rif_file, sfpl() ,0,FILE_BEGIN);
if (!deleted)
{
size_chunk();
output_chunk(rif_file);
}
SetEndOfFile (rif_file);
}
}
else {
SetFilePointer (rif_file,0 ,0,FILE_END);
if (!deleted)
{
size_chunk();
output_chunk(rif_file);
}
SetEndOfFile (rif_file);
}
local_lock = FALSE;
updated = FALSE;
int file_length = GetFileSize(rif_file,0);
SetFilePointer (rif_file,8,0,FILE_BEGIN);
WriteFile (rif_file, (long *) &file_length, 4, &bytes_read, 0);
// DO NOT PUT ANY CODE AFTER THIS
if (deleted) delete this;
// OR ELSE !!!
return TRUE;
}
size_t Lockable_Chunk_With_Children::size_chunk_for_process()
{
if (output_chunk_for_process)
return size_chunk();
return(chunk_size = 0);
}
void Lockable_Chunk_With_Children::fill_data_block_for_process(char * data_start)
{
if (output_chunk_for_process)
{
fill_data_block(data_start);
output_chunk_for_process = FALSE;
}
}
///////////////////////////////////////
// Class File_Chunk functions
/*
Children for File_Chunk :
"REBSHAPE" Shape_Chunk
"RSPRITES" AllSprites_Chunk
"RBOBJECT" Object_Chunk
"RIFVERIN" RIF_Version_Num_Chunk
"REBENVDT" Environment_Data_Chunk
"REBENUMS" Enum_Chunk
"OBJCHIER" Object_Hierarchy_Chunk
"OBHALTSH" Object_Hierarchy_Alternate_Shape_Set_Chunk
"HIDEGDIS" Hierarchy_Degradation_Distance_Chunk
"INDSOUND" Indexed_Sound_Chunk
"HSETCOLL" Hierarchy_Shape_Set_Collection_Chunk
"DUMMYOBJ" Dummy_Object_Chunk
*/
File_Chunk::File_Chunk(const char * file_name)
: Chunk_With_Children (NULL, "REBINFF2")
{
// Load in whole chunk and traverse
char rifIsCompressed = FALSE;
char *uncompressedData = NULL;
HANDLE rif_file;
DWORD file_size;
DWORD file_size_from_file;
unsigned long bytes_read;
char * buffer;
char * buffer_ptr;
char id_buffer[9];
Parent_File = this;
error_code = 0;
object_array_size=0;
object_array=0;
filename = new char [strlen(file_name) + 1];
strcpy (filename, file_name);
rif_file = CreateFileA (file_name, GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
if (rif_file == INVALID_HANDLE_VALUE) {
error_code = CHUNK_FAILED_ON_LOAD;
return;
}
file_size = GetFileSize (rif_file, NULL);
if (!ReadFile(rif_file, id_buffer, 8, &bytes_read, 0)) {
error_code = CHUNK_FAILED_ON_LOAD;
CloseHandle (rif_file);
return;
}
#if UseOldChunkLoader
if (strncmp (id_buffer, "REBINFLF", 8)) {
error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
CloseHandle (rif_file);
return;
}
#else
/* KJL 16:46:14 19/09/98 - check for a compressed rif */
if (!strncmp (id_buffer, COMPRESSED_RIF_IDENTIFIER, 8))
{
rifIsCompressed = TRUE;
}
else if (strncmp (id_buffer, "REBINFF2", 8))
{
error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
CloseHandle (rif_file);
return;
}
#endif
buffer = new char [file_size];
/* KJL 17:57:44 19/09/98 - if the rif is compressed, we must load the whole
file in and then pass it to the decompression routine, which will return a
pointer to the original data. */
if (rifIsCompressed)
{
if (!ReadFile(rif_file, buffer+8, (file_size-8), &bytes_read, 0))
{
error_code = CHUNK_FAILED_ON_LOAD;
CloseHandle (rif_file);
return;
}
uncompressedData = HuffmanDecompress((HuffmanPackage*)buffer);
file_size = ((HuffmanPackage*)buffer)->UncompressedDataSize;
delete [] buffer; // kill the buffer the compressed file was loaded into
buffer_ptr = buffer = uncompressedData+12; // skip header data
}
else // the normal uncompressed approach:
{
if (!ReadFile(rif_file, &file_size_from_file, 4, &bytes_read, 0)) {
error_code = CHUNK_FAILED_ON_LOAD;
CloseHandle (rif_file);
return;
}
if (file_size != file_size_from_file) {
error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
CloseHandle (rif_file);
return;
}
if (!ReadFile(rif_file, buffer, (file_size-12), &bytes_read, 0))
{
error_code = CHUNK_FAILED_ON_LOAD;
CloseHandle (rif_file);
return;
}
buffer_ptr = buffer;
}
// Process the RIF
// The start of the first chunk
while ((buffer_ptr-buffer)< ((signed) file_size-12) && !error_code) {
if ((*(int *)(buffer_ptr + 8)) + (buffer_ptr-buffer) > ((signed)file_size-12)) {
error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
break;
}
DynCreate(buffer_ptr);
buffer_ptr += *(int *)(buffer_ptr + 8);
}
/* KJL 17:59:42 19/09/98 - release the memory holding the rif */
if (rifIsCompressed)
{
free(uncompressedData);
}
else
{
delete [] buffer;
}
CloseHandle (rif_file);
post_input_processing();
}
File_Chunk::File_Chunk()
: Chunk_With_Children (NULL, "REBINFF2")
{
// Empty File chunk
new RIF_Version_Num_Chunk (this);
filename = 0;
object_array_size=0;
object_array=0;
}
File_Chunk::~File_Chunk()
{
if (filename)
delete [] filename;
if(object_array)
free(object_array);
}
#define SAVE_USING_COMPRESSION 1
BOOL File_Chunk::write_file (const char * fname)
{
if(!fname) return FALSE;
//if a read_only file exists with this filename , then abort attempt to save
DWORD attributes = GetFileAttributesA(fname);
if (0xffffffff!=attributes)
{
if (attributes & FILE_ATTRIBUTE_READONLY)
{
return FALSE;
}
}
HANDLE rif_file;
if (filename) delete [] filename;
filename = new char [strlen(fname) + 1];
strcpy (filename, fname);
//save under a temporary name in case a crash occurs during save;
int filename_start_pos=0;
int pos=0;
while(fname[pos])
{
if(fname[pos]=='\\' || fname[pos]==':')
{
filename_start_pos=pos+1;
}
//go to next MBCS character in string
pos+=_mbclen((unsigned const char*)&fname[pos]);
}
if(!fname[filename_start_pos]) return FALSE;
char* temp_name=new char[strlen(fname)+7];
strcpy(temp_name,fname);
strcpy(&temp_name[filename_start_pos],"~temp~");
strcpy(&temp_name[filename_start_pos+6],&fname[filename_start_pos]);
prepare_for_output();
#if SAVE_USING_COMPRESSION
//create a block containing the uncompressed rif file
unsigned char* uncompressedData = (unsigned char*) make_data_block_from_chunk();
if(!uncompressedData) return FALSE;
//do the compression thing
HuffmanPackage *outPackage = HuffmanCompression(uncompressedData,chunk_size);
delete [] uncompressedData;
if(!outPackage) return FALSE;
//and now try to write the file
rif_file = CreateFileA (temp_name, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
FILE_FLAG_RANDOM_ACCESS, 0);
if (rif_file == INVALID_HANDLE_VALUE) {
delete [] temp_name;
free (outPackage);
return FALSE;
}
unsigned long junk;
BOOL ok;
ok = WriteFile (rif_file, (long *) outPackage,outPackage->CompressedDataSize+sizeof(HuffmanPackage), &junk, 0);
CloseHandle (rif_file);
free (outPackage);
if(!ok) return FALSE;
#else
size_chunk();
rif_file = CreateFileA (temp_name, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
FILE_FLAG_RANDOM_ACCESS, 0);
if (rif_file == INVALID_HANDLE_VALUE) {
delete [] temp_name;
return FALSE;
}
if (!(this->output_chunk(rif_file)))
{
CloseHandle (rif_file);
delete [] temp_name;
return FALSE;
}
CloseHandle (rif_file);
#endif
//Delete the old file with this name (if it exists) , and rename the temprary file
DeleteFileA(fname);
MoveFileA(temp_name,fname);
delete [] temp_name;
return TRUE;
}
// the file_chunk must link all of its shapes & objects together
void File_Chunk::post_input_processing()
{
List<Shape_Chunk *> shplist;
List<Object_Chunk *> objlist;
List<Chunk *> child_lists;
lookup_child("REBSHAPE",child_lists);
while (child_lists.size()) {
shplist.add_entry((Shape_Chunk *)child_lists.first_entry());
child_lists.delete_first_entry();
}
lookup_child("RBOBJECT",child_lists);
while (child_lists.size()) {
objlist.add_entry((Object_Chunk *)child_lists.first_entry());
child_lists.delete_first_entry();
}
LIF<Shape_Chunk *> sli(&shplist);
for (; !sli.done(); sli.next())
{
Shape_Chunk::max_id = max (Shape_Chunk::max_id,sli()->get_header()->file_id_num);
}
Shape_Chunk** shape_array=new Shape_Chunk*[Shape_Chunk::max_id+1];
for(sli.restart();!sli.done();sli.next())
{
shape_array[sli()->get_header()->file_id_num]=sli();
}
for (LIF<Object_Chunk *> ol(&objlist); !ol.done(); ol.next())
{
ol()->assoc_with_shape(shape_array[ol()->get_header()->shape_id_no]);
}
delete shape_array;
Chunk_With_Children::post_input_processing();
}
BOOL File_Chunk::check_file()
{
if (!filename) return TRUE;
#if DisableLock
return(TRUE);
#else
int flags;
int v_no;
char locker[17];
HANDLE rif_file;
unsigned long bytes_read;
int tries = 0;
rif_file = CreateFileA (filename, GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
while(rif_file == INVALID_HANDLE_VALUE && tries<10)
{
rif_file = CreateFileA (filename, GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
tries ++;
clock_t ctime = clock();
double secs = (double)ctime / (double)CLOCKS_PER_SEC;
double secsgone;
do
{
ctime = clock();
secsgone = (double)ctime / (double)CLOCKS_PER_SEC;
}
while( (secsgone-secs)<1);
}
if (rif_file == INVALID_HANDLE_VALUE) {
error_code = CHECK_FAILED_NOT_OPEN;
return FALSE;
}
if (rif_file == INVALID_HANDLE_VALUE) {
error_code = CHECK_FAILED_NOT_OPEN;
return FALSE;
}
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> obfptrs;
list_chunks_in_file(& obfptrs, rif_file, "RBOBJECT");
// ok, go through the objects, first locate the header and find
// the associated object.
if (obfptrs.size()) {
for (LIF<int> obflst(&obfptrs); !obflst.done(); obflst.next()) {
// go to start of chunk
SetFilePointer (rif_file,obflst(),0,FILE_BEGIN);
// get header list
List<int> obhead;
list_chunks_in_file(& obhead, rif_file, "OBJHEAD1");
assert (obhead.size() == 1);
// go to lock status in header
SetFilePointer(rif_file,obhead.first_entry() + 12,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &flags, 4, &bytes_read, 0);
ReadFile (rif_file, (long *) locker, 16, &bytes_read, 0);
// go to version number
SetFilePointer(rif_file,obhead.first_entry() + 88,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &v_no, 4, &bytes_read, 0);
char name[50];
// get object identifier
SetFilePointer(rif_file,obhead.first_entry() + 96,0,FILE_BEGIN);
int i = 0;
do ReadFile (rif_file, (long *) (name + i), 1, &bytes_read, 0);
while (name[i++] != 0);
Object_Chunk * tmpob;
Object_Header_Chunk * tmpobh;
List<Chunk *> obchs;
lookup_child ("RBOBJECT",obchs);
if (obchs.size()){
for (LIF<Chunk *> obchls(&obchs); !obchls.done(); obchls.next()){
tmpob = (Object_Chunk *)obchls();
// if this is the same object
if (!strcmp (name, tmpob->object_data.o_name)) break;
}
if (!obchls.done()) {
tmpobh = tmpob->get_header();
if (tmpobh) {
if (tmpobh->version_no < v_no)
tmpob->updated_outside = TRUE;
if (flags & GENERAL_FLAG_LOCKED) {
// do the lock check
if (!tmpob->local_lock) {
tmpob->external_lock = TRUE;
strncpy(tmpobh->lock_user, locker,16);
tmpobh->lock_user[16] = '\0';
}
else if (strncmp(tmpobh->lock_user, locker,16)) {
tmpob->external_lock = TRUE;
strncpy(tmpobh->lock_user, locker,16);
tmpobh->lock_user[16] = '\0';
}
}
}
}
}
}
}
// shapes
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> shpfptrs;
list_chunks_in_file(& shpfptrs, rif_file, "REBSHAPE");
if (shpfptrs.size()) {
for (LIF<int> shpflst(&shpfptrs); !shpflst.done(); shpflst.next()) {
// go to start of chunk
SetFilePointer (rif_file,shpflst(),0,FILE_BEGIN);
// get header list
List<int> shphead;
list_chunks_in_file(& shphead, rif_file, "SHPHEAD1");
assert (shphead.size() == 1);
// go to lock status in header
SetFilePointer(rif_file,shphead.first_entry() + 12,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &flags, 4, &bytes_read, 0);
ReadFile (rif_file, (long *) locker, 16, &bytes_read, 0);
int id;
// get shape identifier
ReadFile (rif_file, (long *) &id, 4, &bytes_read, 0);
// Here we update max_id
Shape_Chunk::max_id = max (Shape_Chunk::max_id,id);
// go to version number
SetFilePointer(rif_file,shphead.first_entry() + 100,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &v_no, 4, &bytes_read, 0);
Shape_Chunk * tmpshp;
Shape_Header_Chunk * tmpshph;
List<Chunk *> shpchs;
lookup_child ("REBSHAPE",shpchs);
if (shpchs.size()){
for (LIF<Chunk *> shpchls(&shpchs); !shpchls.done(); shpchls.next()){
tmpshp = (Shape_Chunk *)shpchls();
tmpshph = tmpshp->get_header();
// if this is the same object
if (tmpshph)
if (id == tmpshph->file_id_num) break;
}
if (!shpchls.done()) {
if (tmpshph->version_no < v_no)
tmpshp->updated_outside = TRUE;
if (flags & GENERAL_FLAG_LOCKED) {
// do the lock check
if (!tmpshp->local_lock) {
tmpshp->external_lock = TRUE;
strncpy(tmpshph->lock_user, locker,16);
tmpshph->lock_user[16] = '\0';
}
else if (strncmp(tmpshph->lock_user, locker,16)) {
tmpshp->external_lock = TRUE;
strncpy(tmpshph->lock_user, locker,16);
tmpshph->lock_user[16] = '\0';
}
}
}
}
}
}
// sprites
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> sprfptrs;
list_chunks_in_file(& sprfptrs, rif_file, "RSPRITES");
List<Chunk *> sprchlst;
lookup_child("RSPRITES",sprchlst);
AllSprites_Chunk * sprch;
AllSprites_Header_Chunk * sprhead = 0;
if (sprchlst.size())
{
sprch = (AllSprites_Chunk *)sprchlst.first_entry();
sprhead = sprch->get_header();
}
if (sprhead)
{
if (sprfptrs.size())
{
SetFilePointer (rif_file,sprfptrs.first_entry(),0,FILE_BEGIN);
// get header list
List<int> sprchhl;
list_chunks_in_file(& sprchhl, rif_file, "ASPRHEAD");
assert (sprchhl.size() == 1);
// go to lock status in header
SetFilePointer(rif_file,sprchhl.first_entry() + 12,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &flags, 4, &bytes_read, 0);
ReadFile (rif_file, (long *) locker, 16, &bytes_read, 0);
// go to version number
SetFilePointer(rif_file,sprchhl.first_entry() + 32,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &v_no, 4, &bytes_read, 0);
if (sprhead->version_no < v_no)
{
sprch->updated_outside = TRUE;
}
if (flags & GENERAL_FLAG_LOCKED)
{
if (!sprch->local_lock) {
sprch->external_lock = TRUE;
strncpy(sprhead->lock_user, locker,16);
sprhead->lock_user[16] = '\0';
}
else if (strncmp(sprhead->lock_user, locker,16)) {
sprch->external_lock = TRUE;
strncpy(sprhead->lock_user, locker,16);
sprhead->lock_user[16] = '\0';
}
}
}
}
// environment data
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> edfptrs;
list_chunks_in_file(& edfptrs, rif_file, "REBENVDT");
Environment_Data_Chunk * ed;
Environment_Data_Header_Chunk * edhead = 0;
ed = (Environment_Data_Chunk *)lookup_single_child("REBENVDT");
if (ed)
{
edhead = ed->get_header();
}
if (edhead)
{
if (edfptrs.size())
{
SetFilePointer (rif_file,edfptrs.first_entry(),0,FILE_BEGIN);
// get header list
List<int> edhl; list_chunks_in_file(& edhl, rif_file, "ENDTHEAD");
assert (edhl.size() == 1);
// go to lock status in header
SetFilePointer(rif_file,edhl.first_entry() + 12,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &flags, 4, &bytes_read, 0);
ReadFile (rif_file, (long *) locker, 16, &bytes_read, 0);
// go to version number
SetFilePointer(rif_file,edhl.first_entry() + 32,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &v_no, 4, &bytes_read, 0);
if (edhead->version_no < v_no)
{
ed->updated_outside = TRUE;
}
if (flags & GENERAL_FLAG_LOCKED)
{
if (!ed->local_lock) {
ed->external_lock = TRUE;
strncpy(edhead->lock_user, locker,16);
edhead->lock_user[16] = '\0';
}
else if (strncmp(edhead->lock_user, locker,16)) {
ed->external_lock = TRUE;
strncpy(edhead->lock_user, locker,16);
edhead->lock_user[16] = '\0';
}
}
}
}
// check file for REBENUMS chunk
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> enumfptrs; list_chunks_in_file(& enumfptrs, rif_file, "REBENUMS");
Enum_Chunk * enumch;
Enum_Header_Chunk * enumhead = 0;
enumch = (Enum_Chunk *)lookup_single_child("REBENUMS");
if (enumch)
{
enumhead = enumch->get_header();
}
if (enumhead)
{
if (enumfptrs.size())
{
SetFilePointer (rif_file,enumfptrs.first_entry(),0,FILE_BEGIN);
// get header list
List<int> enumchhl; list_chunks_in_file(& enumchhl, rif_file, "ENUMHEAD");
assert (enumchhl.size() == 1);
// go to lock status in header
SetFilePointer(rif_file,enumchhl.first_entry() + 12,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &flags, 4, &bytes_read, 0);
ReadFile (rif_file, (long *) locker, 16, &bytes_read, 0);
// go to version number
SetFilePointer(rif_file,enumchhl.first_entry() + 32,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &v_no, 4, &bytes_read, 0);
if (enumhead->version_no < v_no)
{
enumch->updated_outside = TRUE;
}
if (flags & GENERAL_FLAG_LOCKED)
{
if (!enumch->local_lock) {
enumch->external_lock = TRUE;
strncpy(enumhead->lock_user, locker,16);
enumhead->lock_user[16] = '\0';
}
else if (strncmp(enumhead->lock_user, locker,16)) {
enumch->external_lock = TRUE;
strncpy(enumhead->lock_user, locker,16);
enumhead->lock_user[16] = '\0';
}
}
}
}
CloseHandle (rif_file);
return TRUE;
#endif
}
#if InterfaceEngine
extern File_Chunk * Env_Chunk;
#endif
BOOL File_Chunk::update_file()
{
#if DisableLock
if (!filename) return FALSE;
char tempname [256];
strcpy (tempname, filename);
List<Shape_Chunk *> slist;
list_shapes(&slist);
List<Object_Chunk *> olist;
list_objects(&olist);
for (LIF<Shape_Chunk *> sli(&slist); !sli.done(); sli.next())
{
if (sli()->deleted)
{
delete sli();
}
}
for (LIF<Object_Chunk *> oli(&olist); !oli.done(); oli.next())
{
if (oli()->deleted)
{
delete oli();
}
}
return(write_file(tempname));
#else
#if InterfaceEngine
// log, to track error
char fname [256];
char * dotpos;
strcpy (fname, filename);
dotpos = strrchr (fname, '.');
sprintf (dotpos, ".log");
FILE * log = fopen (fname, "a");
#endif
if (!filename) return FALSE;
twprintf("Updating %s\n",filename);
check_file();
HANDLE rif_file;
unsigned long bytes_read;
int tries = 0;
//twprintf("Opening file\n");
rif_file = CreateFileA (filename, GENERIC_WRITE + GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
if (rif_file == INVALID_HANDLE_VALUE)
{
DWORD error_num = GetLastError();
switch (error_num)
{
case ERROR_SHARING_VIOLATION:
twprintf("Sharing violation - retrying\n");
break;
case ERROR_ACCESS_DENIED:
twprintf("File is Read Only\n");
return FALSE;
default:
twprintf("Unknown error updating file, Error code %#08x\n",error_num);
return FALSE;
}
}
while(rif_file == INVALID_HANDLE_VALUE && tries<10)
{
twprintf("Again...\n");
rif_file = CreateFileA (filename, GENERIC_WRITE + GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
tries ++;
clock_t ctime = clock();
double secs = (double)ctime / (double)CLOCKS_PER_SEC;
double secsgone;
do
{
ctime = clock();
secsgone = (double)ctime / (double)CLOCKS_PER_SEC;
}
while( (secsgone-secs)<1);
}
if (rif_file == INVALID_HANDLE_VALUE) {
error_code = CHECK_FAILED_NOT_OPEN;
twprintf("ERROR - SHARING VIOLATION UNRESOLVED\n\n");
return FALSE;
}
//twprintf("Opened\n\n");
prepare_for_output();
SetFilePointer (rif_file,0,0,FILE_BEGIN);
//twprintf("Version info\n");
List<int> verinf; list_chunks_in_file(& verinf, rif_file, "RIFVERIN");
// taking first entry of this list, if there are more - tough ha ha
// there shouldn't be
// Just increment it by one and reoutput
// check_file sets the internal copy of the chunk to the current file
// setting, so we need to increment that as well
if (verinf.size()) {
int f_version_num;
SetFilePointer (rif_file,verinf.first_entry() + 12,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &f_version_num, 4, &bytes_read, 0);
SetFilePointer (rif_file,verinf.first_entry() + 12,0,FILE_BEGIN);
RIF_Version_Num_Chunk* rvnc=(RIF_Version_Num_Chunk*)lookup_single_child ("RIFVERIN");
if (rvnc)
rvnc->file_version_no++;
f_version_num++;
WriteFile (rif_file, (long *) &f_version_num, 4, &bytes_read, 0);
}
// go through the list of shape chunks looking for shape chunks to output
//twprintf("\nShapes\n");
List<Chunk *> shplst;
lookup_child ("REBSHAPE",shplst);
if (shplst.size())
for (LIF<Chunk *> sli(&shplst); !sli.done(); sli.next()) {
Shape_Chunk * tmpshpptr = ((Shape_Chunk *)sli());
if (tmpshpptr->updated &&
!(tmpshpptr->updated_outside || tmpshpptr->external_lock))
tmpshpptr->update_chunk_in_file(rif_file);
}
// go through the list of object chunks looking for chunks to output
//twprintf("\nObjects\n");
List<Chunk *> oblst;
lookup_child ("RBOBJECT",oblst);
if (oblst.size())
for (LIF<Chunk *> oli(&oblst); !oli.done(); oli.next()) {
Object_Chunk * tmpobptr = ((Object_Chunk *)oli());
if (tmpobptr->updated && !(tmpobptr->updated_outside || tmpobptr->external_lock))
tmpobptr->update_chunk_in_file(rif_file);
}
//twprintf("\nSprites\n");
List<Chunk *> sprfptrs;
lookup_child ("RSPRITES",sprfptrs);
AllSprites_Chunk * sprch;
if (sprfptrs.size())
{
sprch = (AllSprites_Chunk *)sprfptrs.first_entry();
if (sprch->updated &&
!(sprch->updated_outside || sprch->external_lock))
sprch->update_chunk_in_file(rif_file);
}
//twprintf("\nEnvironment data\n");
Environment_Data_Chunk * ed;
ed = (Environment_Data_Chunk *)lookup_single_child ("REBENVDT");
if (ed)
{
#if InterfaceEngine
fprintf (log, "Env_Data %d %d %d %d", ed->updated, ed->local_lock, ed->updated_outside, ed->external_lock);
#endif
if (ed->updated &&
!(ed->updated_outside || ed->external_lock))
ed->update_chunk_in_file(rif_file);
}
//twprintf("\nEnum data\n");
List<Chunk *> enumfptrs;
lookup_child ("REBENUMS",enumfptrs);
Enum_Chunk * enumch;
if (enumfptrs.size())
{
enumch = (Enum_Chunk *)enumfptrs.first_entry();
if (enumch->updated &&
!(enumch->updated_outside || enumch->external_lock))
enumch->update_chunk_in_file(rif_file);
}
//
int file_length = GetFileSize(rif_file,0);
SetFilePointer (rif_file,8,0,FILE_BEGIN);
WriteFile (rif_file, (long *) &file_length, 4, &bytes_read, 0);
CloseHandle (rif_file);
#if InterfaceEngine
fclose (log);
#endif
return TRUE;
#endif //DisableLock
}
BOOL File_Chunk::update_chunks_from_file()
{
#if DisableLock
return(TRUE);
#endif
if (!filename) return FALSE;
check_file();
HANDLE rif_file;
unsigned long bytes_read;
rif_file = CreateFileA (filename, GENERIC_WRITE + GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
if (rif_file == INVALID_HANDLE_VALUE) {
error_code = CHECK_FAILED_NOT_OPEN;
return FALSE;
}
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> verinf; list_chunks_in_file(& verinf, rif_file, "RIFVERIN");
if (verinf.size()) {
int f_version_num;
SetFilePointer (rif_file,verinf.first_entry() + 12,0,FILE_BEGIN);
ReadFile (rif_file, (long *) &f_version_num, 4, &bytes_read, 0);
SetFilePointer (rif_file,verinf.first_entry() + 12,0,FILE_BEGIN);
List<Chunk *> lverinf;
lookup_child ("RIFVERIN",lverinf);
if (lverinf.size())
if (f_version_num == ((RIF_Version_Num_Chunk *)(lverinf.first_entry()))->file_version_no){
CloseHandle (rif_file);
return TRUE;
}
}
// go through the list of object chunks looking for chunks to input
List<Chunk *> oblst;
lookup_child ("RBOBJECT",oblst);
if (oblst.size())
for (LIF<Chunk *> oli(&oblst); !oli.done(); oli.next()) {
Object_Chunk * tmpobptr = ((Object_Chunk *)oli());
if (tmpobptr->updated_outside) {
// find the chunk, then input it to a buffer and create a new object
// from the buffer
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> obfptrs; list_chunks_in_file(& obfptrs, rif_file, "RBOBJECT");
char name[50];
LIF<int> ofpl(&obfptrs);
if (obfptrs.size()) {
for (; !ofpl.done(); ofpl.next()) {
SetFilePointer (rif_file, ofpl(),0,FILE_BEGIN);
// get header list
List<int> obhead; list_chunks_in_file(& obhead, rif_file, "OBJHEAD1");
assert (obhead.size() == 1);
// get object identifier
SetFilePointer(rif_file,obhead.first_entry() + 96,0,FILE_BEGIN);
int i = 0;
do ReadFile (rif_file, (long *) (name + i), 1, &bytes_read, 0);
while (name[i++] != 0);
if (!strcmp(name, tmpobptr->object_data.o_name)) break;
}
}
if (!ofpl.done()) {
char * buffer;
SetFilePointer (rif_file,ofpl()+8,0,FILE_BEGIN);
int length;
ReadFile(rif_file, (long *) &length, 4, &bytes_read, 0);
buffer = new char [length];
ReadFile(rif_file, (long *) buffer, length-12, &bytes_read, 0);
new Object_Chunk (this, buffer, length-12);
delete [] buffer;
if (tmpobptr->get_header())
if (tmpobptr->get_header()->associated_shape)
tmpobptr->deassoc_with_shape(tmpobptr->get_header()->associated_shape);
delete tmpobptr;
}
}
}
// go through the list of shape chunks looking for shape chunks to input
List<Chunk *> shplst;
lookup_child ("REBSHAPE",shplst);
if (shplst.size())
for (LIF<Chunk *> sli(&shplst); !sli.done(); sli.next()) {
Shape_Chunk * tmpshpptr = ((Shape_Chunk *)sli());
Shape_Header_Chunk * shhead = tmpshpptr->get_header();
if (!shhead) continue;
if (tmpshpptr->updated_outside) {
// find the chunk, then input it to a buffer and create a new object
// from the buffer
SetFilePointer (rif_file,0,0,FILE_BEGIN);
List<int> shfptrs; list_chunks_in_file(& shfptrs, rif_file, "REBSHAPE");
LIF<int> sfpl(&shfptrs);
if (shfptrs.size()) {
for (sfpl.restart(); !sfpl.done(); sfpl.next()) {
SetFilePointer (rif_file, sfpl(),0,FILE_BEGIN);
// get header list
List<int> shphead; list_chunks_in_file(& shphead, rif_file, "SHPHEAD1");
assert (shphead.size() == 1);
// get object identifier
SetFilePointer(rif_file,shphead.first_entry() + 32,0,FILE_BEGIN);
int sh_number;
ReadFile (rif_file, (long *) &sh_number, 4, &bytes_read, 0);
if (sh_number == shhead->file_id_num) break;
}
}
if (!sfpl.done()) {
char * buffer;
SetFilePointer (rif_file,sfpl()+8,0,FILE_BEGIN);
int length;
ReadFile(rif_file, (long *) &length, 4, &bytes_read, 0);
buffer = new char [length];
ReadFile(rif_file, (long *) buffer, length-12, &bytes_read, 0);
new Shape_Chunk (this, buffer, length-12);
delete [] buffer;
// Associate with the new objects
if ((shhead->associated_objects_store).size())
{
for (LIF<Object_Chunk *> aol(&(shhead->associated_objects_store)); !aol.done(); aol.next())
{
tmpshpptr->deassoc_with_object(aol());
}
}
delete tmpshpptr;
}
}
}
post_input_processing();
CloseHandle(rif_file);
return TRUE;
}
void File_Chunk::list_objects(List<Object_Chunk *> * pList)
{
Chunk * child_ptr = children;
while (pList->size())
pList->delete_first_entry();
if (children)
while (child_ptr != NULL) {
if (strncmp ("RBOBJECT", child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
pList->add_entry((Object_Chunk *)child_ptr);
}
child_ptr = child_ptr->next;
}
}
void File_Chunk::list_shapes(List<Shape_Chunk *> * pList)
{
Chunk * child_ptr = children;
while (pList->size())
pList->delete_first_entry();
if (children)
while (child_ptr != NULL) {
if (strncmp ("REBSHAPE", child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
pList->add_entry((Shape_Chunk *)child_ptr);
}
child_ptr = child_ptr->next;
}
}
void File_Chunk::list_dummy_objects(List<Dummy_Object_Chunk *> * pList){
Chunk * child_ptr = children;
while (pList->size())
pList->delete_first_entry();
if (children)
while (child_ptr != NULL) {
if (strncmp ("DUMMYOBJ", child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
pList->add_entry((Dummy_Object_Chunk *)child_ptr);
}
child_ptr = child_ptr->next;
}
}
Environment_Data_Chunk * File_Chunk::get_env_data()
{
List<Environment_Data_Chunk *> e_list;
Chunk * child_ptr = children;
if (children)
while (child_ptr != NULL) {
if (strncmp ("REBENVDT", child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
e_list.add_entry((Environment_Data_Chunk *)child_ptr);
}
child_ptr = child_ptr->next;
}
// There can be only ONE.
assert (e_list.size() < 2);
if (e_list.size())
return e_list.first_entry();
else
{
return(0);
}
}
void File_Chunk::build_object_array()
{
List<Object_Chunk*> oblist;
list_objects(&oblist);
if(object_array)
{
free(object_array);
object_array=0;
}
object_array_size=0;
LIF<Object_Chunk*> oblif(&oblist);
//find the highest object index
for(oblif.restart();!oblif.done();oblif.next())
{
object_array_size=max(object_array_size,oblif()->object_data.index_num+1);
}
if(object_array_size<=0) return;
object_array = (Object_Chunk**) malloc(sizeof(Object_Chunk*)*object_array_size);
for(int i=0;i<object_array_size;i++)
{
object_array[i]=0;
}
//now fill in object array
for(oblif.restart();!oblif.done();oblif.next())
{
int index=oblif()->object_data.index_num;
if(index>=0)
{
object_array[index]=oblif();
}
}
}
Object_Chunk* File_Chunk::get_object_by_index(int index)
{
if(!object_array) build_object_array();
if(index<0 || index>=object_array_size)return 0;
return object_array[index];
}
void File_Chunk::assign_index_to_object(Object_Chunk* object)
{
assert(object);
if(!object_array) build_object_array();
//see if there is a free index
for(int i=0;i<object_array_size;i++)
{
if(!object_array[i])
{
object->object_data_store->index_num=i;
object_array[i]=object;
return;
}
}
//add a new entry on the end of the array
object_array_size++;
object_array=(Object_Chunk**) realloc(object_array,sizeof(Object_Chunk*)*object_array_size);
object->object_data_store->index_num=object_array_size-1;;
object_array[object_array_size-1]=object;
}
/////////////////////////////////////////
// Class GodFather_Chunk functions
/*
Children for GodFather_Chunk :
"REBSHAPE" Shape_Chunk
"RSPRITES" AllSprites_Chunk
"RBOBJECT" Object_Chunk
"RIFVERIN" RIF_Version_Num_Chunk
"REBENVDT" Environment_Data_Chunk
"REBENUMS" Enum_Chunk
"OBJCHIER" Object_Hierarchy_Chunk
"OBHALTSH" Object_Hierarchy_Alternate_Shape_Set_Chunk
*/
GodFather_Chunk::GodFather_Chunk(char * buffer, size_t size)
: Chunk_With_Children (NULL, "REBINFF2")
{
Parent_File = this;
char * buffer_ptr = buffer;
// The start of the first chunk
while ((buffer_ptr-buffer)< ((signed)size-12) && !error_code) {
if ((*(int *)(buffer_ptr + 8)) + (buffer_ptr-buffer) > ((signed)size-12)) {
error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
break;
}
DynCreate(buffer_ptr);
buffer_ptr += *(int *)(buffer_ptr + 8);
}
}
/////////////////////////////////////////
// Class RIF_Version_Num_Chunk functions
RIF_IMPLEMENT_DYNCREATE("RIFVERIN",RIF_Version_Num_Chunk)
void RIF_Version_Num_Chunk::fill_data_block(char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = file_version_no;
}
/////////////////////////////////////////
// Class RIF_Name_Chunk functions
RIF_IMPLEMENT_DYNCREATE("RIFFNAME",RIF_Name_Chunk)
RIF_Name_Chunk::RIF_Name_Chunk (Chunk_With_Children * parent, const char * rname)
: Chunk (parent, "RIFFNAME")
{
rif_name = new char [strlen(rname)+1];
strcpy (rif_name, rname);
}
RIF_Name_Chunk::RIF_Name_Chunk (Chunk_With_Children * parent, const char * rdata, size_t /*rsize*/)
: Chunk (parent, "RIFFNAME")
{
rif_name = new char [strlen(rdata)+1];
strcpy (rif_name, rdata);
}
RIF_Name_Chunk::~RIF_Name_Chunk ()
{
if (rif_name)
delete [] rif_name;
}
void RIF_Name_Chunk::fill_data_block (char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
strcpy (data_start, rif_name);
}
///////////////////////////////////////
/*
Children for RIF_File_Chunk :
"REBSHAPE" Shape_Chunk
"RSPRITES" AllSprites_Chunk
"RBOBJECT" Object_Chunk
"RIFVERIN" RIF_Version_Num_Chunk
"REBENVDT" Environment_Data_Chunk
"OBJCHIER" Object_Hierarchy_Chunk
"OBHALTSH" Object_Hierarchy_Alternate_Shape_Set_Chunk
*/
RIF_File_Chunk::RIF_File_Chunk (Chunk_With_Children * parent, const char * file_name)
: Chunk_With_Children (parent, "SUBRIFFL")
{
char rifIsCompressed = FALSE;
char *uncompressedData = NULL;
HANDLE rif_file;
DWORD file_size;
DWORD file_size_from_file;
unsigned long bytes_read;
char * buffer;
char * buffer_ptr;
char id_buffer[9];
Chunk * ParentFileStore = Parent_File;
Parent_File = this;
error_code = 0;
rif_file = CreateFileA (file_name, GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, 0);
if (rif_file == INVALID_HANDLE_VALUE) {
error_code = CHUNK_FAILED_ON_LOAD;
Parent_File = ParentFileStore;
return;
}
file_size = GetFileSize (rif_file, NULL);
if (!ReadFile(rif_file, id_buffer, 8, &bytes_read, 0)) {
error_code = CHUNK_FAILED_ON_LOAD;
CloseHandle (rif_file);
Parent_File = ParentFileStore;
return;
}
//check for compressed rif
if (!strncmp (id_buffer, COMPRESSED_RIF_IDENTIFIER, 8))
{
rifIsCompressed = TRUE;
}
else if (strncmp (id_buffer, "REBINFF2", 8)) {
error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
CloseHandle (rif_file);
Parent_File = ParentFileStore;
return;
}
buffer = new char [file_size];
/* KJL 17:57:44 19/09/98 - if the rif is compressed, we must load the whole
file in and then pass it to the decompression routine, which will return a
pointer to the original data. */
if (rifIsCompressed)
{
if (!ReadFile(rif_file, buffer+8, (file_size-8), &bytes_read, 0))
{
error_code = CHUNK_FAILED_ON_LOAD;
CloseHandle (rif_file);
Parent_File = ParentFileStore;
delete [] buffer;
return;
}
uncompressedData = HuffmanDecompress((HuffmanPackage*)buffer);
file_size = ((HuffmanPackage*)buffer)->UncompressedDataSize;
delete [] buffer; // kill the buffer the compressed file was loaded into
buffer_ptr = buffer = uncompressedData+12; // skip header data
}
else // the normal uncompressed approach:
{
//get the file size stored in the rif file
if (!ReadFile(rif_file, &file_size_from_file, 4, &bytes_read, 0)) {
error_code = CHUNK_FAILED_ON_LOAD;
CloseHandle (rif_file);
Parent_File = ParentFileStore;
delete [] buffer;
return;
}
//and compare with the actual file size
if (file_size != file_size_from_file) {
error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
CloseHandle (rif_file);
Parent_File = ParentFileStore;
delete [] buffer;
return;
}
//read the rest of the file into the buffer
if (!ReadFile(rif_file, buffer, (file_size-12), &bytes_read, 0))
{
error_code = CHUNK_FAILED_ON_LOAD;
CloseHandle (rif_file);
Parent_File = ParentFileStore;
delete [] buffer;
return;
}
buffer_ptr = buffer;
}
// Process the RIF
// The start of the first chunk
while ((buffer_ptr-buffer)< ((signed) file_size-12) && !error_code) {
if ((*(int *)(buffer_ptr + 8)) + (buffer_ptr-buffer) > ((signed)file_size-12)) {
error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
break;
}
DynCreate(buffer_ptr);
buffer_ptr += *(int *)(buffer_ptr + 8);
}
/* KJL 17:59:42 19/09/98 - release the memory holding the rif */
if (rifIsCompressed)
{
free(uncompressedData);
}
else
{
delete [] buffer;
}
CloseHandle (rif_file);
post_input_processing();
Parent_File = ParentFileStore;
}
void RIF_File_Chunk::post_input_processing()
{
List<Shape_Chunk *> shplist;
List<Object_Chunk *> objlist;
List<Chunk *> child_lists;
lookup_child("REBSHAPE",child_lists);
while (child_lists.size()) {
shplist.add_entry((Shape_Chunk *)child_lists.first_entry());
child_lists.delete_first_entry();
}
lookup_child("RBOBJECT",child_lists);
while (child_lists.size()) {
objlist.add_entry((Object_Chunk *)child_lists.first_entry());
child_lists.delete_first_entry();
}
for (LIF<Object_Chunk *> ol(&objlist); !ol.done(); ol.next()) {
if (ol()->get_header()) {
for (LIF<Shape_Chunk *> sl(&shplist);
!sl.done(); sl.next()) {
if (sl()->get_header())
if (sl()->get_header()->file_id_num == ol()->get_header()->shape_id_no){
ol()->assoc_with_shape(sl());
break;
}
}
}
}
for (LIF<Shape_Chunk *> sli(&shplist); !sli.done(); sli.next())
{
Shape_Chunk::max_id = max (Shape_Chunk::max_id,sli()->get_header()->file_id_num);
}
Chunk_With_Children::post_input_processing();
}
void RIF_File_Chunk::list_objects(List<Object_Chunk *> * pList)
{
Chunk * child_ptr = children;
while (pList->size())
pList->delete_first_entry();
if (children)
while (child_ptr != NULL) {
if (strncmp ("RBOBJECT", child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
pList->add_entry((Object_Chunk *)child_ptr);
}
child_ptr = child_ptr->next;
}
}
void RIF_File_Chunk::list_shapes(List<Shape_Chunk *> * pList)
{
Chunk * child_ptr = children;
while (pList->size())
pList->delete_first_entry();
if (children)
while (child_ptr != NULL) {
if (strncmp ("REBSHAPE", child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
pList->add_entry((Shape_Chunk *)child_ptr);
}
child_ptr = child_ptr->next;
}
}
Environment_Data_Chunk * RIF_File_Chunk::get_env_data()
{
List<Environment_Data_Chunk *> e_list;
Chunk * child_ptr = children;
if (children)
while (child_ptr != NULL) {
if (strncmp ("REBENVDT", child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
e_list.add_entry((Environment_Data_Chunk *)child_ptr);
}
child_ptr = child_ptr->next;
}
// There can be only ONE.
assert (e_list.size() < 2);
if (e_list.size())
return e_list.first_entry();
else
{
return(0);
}
}