// -----------------------------------------------------------------------------
// Adds all available colour configuration names to [names]
// -----------------------------------------------------------------------------
void ColourConfiguration::putConfigurationNames(vector<std::string>& names)
{
	// TODO: search custom folder

	// Search resource pk3
	auto res = App::archiveManager().programResourceArchive();
	auto dir = res->dir("config/colours");
	for (unsigned a = 0; a < dir->numEntries(); a++)
		names.emplace_back(dir->entryAt(a)->nameNoExt());
}
Beispiel #2
0
// important that it be big enough, not so important it's exact
int OsConfigDb::calculateBufferSize() const
{
    int n = numEntries();
    size_t size = n * strlen(DB_LINE_FORMAT);
    for (int i = 0; i < n; i++)
    {
        DbEntry *pEntry = (DbEntry *)mDb.at(i);
        size += pEntry->key.length() + pEntry->value.length();
    }
    return size;
}
Beispiel #3
0
	void CategoryTree::onContextMenu( wxTreeEvent& p_event ) {
		wxArrayTreeItemIds ids;
		this->GetSelections( ids );

		if ( ids.Count( ) > 0 ) {
			// Start with counting the total amount of entries
			uint count = 0;
			const DatIndexEntry* firstEntry = nullptr;
			for ( uint i = 0; i < ids.Count( ); i++ ) {
				auto itemData = static_cast<const CategoryTreeItem*>( this->GetItemData( ids[i] ) );
				if ( itemData->dataType( ) == CategoryTreeItem::DT_Entry ) {
					if ( !firstEntry ) {
						firstEntry = ( const DatIndexEntry* ) itemData->data( );
					}
					count++;
				} else if ( itemData->dataType( ) == CategoryTreeItem::DT_Category ) {
					auto category = static_cast<const DatIndexCategory*>( itemData->data( ) );
					count += category->numEntries( true );
					if ( !firstEntry && category->numEntries( ) ) {
						firstEntry = category->entry( 0 );
					}
				}
			}

			// Create the menu
			if ( count > 0 ) {
				wxMenu newMenu;
				if ( count == 1 ) {
					newMenu.Append( wxID_SAVE, wxString::Format( wxT( "Extract file %s..." ), firstEntry->name( ) ) );
					newMenu.Append( wxID_SAVEAS, wxString::Format( wxT( "Extract file %s (raw)..." ), firstEntry->name( ) ) );
				} else {
					newMenu.Append( wxID_SAVE, wxString::Format( wxT( "Extract %d files..." ), count ) );
					newMenu.Append( wxID_SAVEAS, wxString::Format( wxT( "Extract %d files (raw)..." ), count ) );
				}
				this->PopupMenu( &newMenu );
			}
		}
	}
// -----------------------------------------------------------------------------
// Reads saved colour configuration [name]
// -----------------------------------------------------------------------------
bool ColourConfiguration::readConfiguration(std::string_view name)
{
	// TODO: search custom folder

	// Search resource pk3
	auto res = App::archiveManager().programResourceArchive();
	auto dir = res->dir("config/colours");
	for (unsigned a = 0; a < dir->numEntries(); a++)
	{
		if (StrUtil::equalCI(dir->entryAt(a)->nameNoExt(), name))
			return readConfiguration(dir->entryAt(a)->data());
	}

	return false;
}
Beispiel #5
0
	void CategoryTree::onItemExpanding( wxTreeEvent& p_event ) {
		auto id = p_event.GetItem( );
		auto itemData = static_cast<CategoryTreeItem*>( this->GetItemData( id ) );

		// If this is not a category, skip it
		if ( itemData && itemData->dataType( ) != CategoryTreeItem::DT_Category ) {
			return;
		}

		// Give it the open folder icon instead
		this->SetItemImage( id, CategoryTreeImageList::IT_OpenFolder );

		// Skip if the category isn't dirty
		if ( !itemData->isDirty( ) ) {
			return;
		} else {
			this->DeleteChildren( id );
		}

		// Fetch the category info
		auto category = static_cast<const DatIndexCategory*>( itemData->data( ) );
		if ( !category ) {
			return;
		}

		// Add all contained entries
		for ( uint i = 0; i < category->numEntries( ); i++ ) {
			auto entry = category->entry( i );
			if ( !entry ) {
				continue;
			}
			//this->AddEntry(id, *entry);
			this->AppendItem( id, entry->name( ), this->getImageForEntry( *entry ), -1, new CategoryTreeItem( CategoryTreeItem::DT_Entry, entry ) );
		}
		this->SortChildren( id );

		// Add sub-categories last
		for ( uint i = 0; i < category->numSubCategories( ); i++ ) {
			auto subcategory = category->subCategory( i );
			if ( !subcategory ) {
				continue;
			}
			this->ensureHasCategory( *subcategory, true );
		}

		// Un-dirty!
		itemData->setDirty( false );
	}
Beispiel #6
0
void OsConfigDb::storeToBuffer(char *buff) const
{
    char *p = buff;
    int n = numEntries();
    for (int i = 0; i < n; i++)
    {
        DbEntry *pEntry = (DbEntry *)mDb.at(i);
        removeChars(&pEntry->key, '\r');
        removeChars(&pEntry->value, '\n');

        sprintf(p, DB_LINE_FORMAT, (char *)pEntry->key.data(),
                (char *)pEntry->value.data());

        p = buff + strlen(buff);
    }
}
Beispiel #7
0
// Relative to rKey, return the key and value associated with
// next (lexicographically ordered) key/value pair stored in the
// database.  If rKey is the empty string, key and value associated
// with the first entry in the database will be returned.
// Returns
//   OS_SUCCESS if there is a "next" entry
//   OS_NOT_FOUND if rKey is not found in the database and is not the
//      empty string
//   OS_NO_MORE_DATA if there is no "next" entry
OsStatus OsConfigDb::getNext(const UtlString& rKey,
                             UtlString& rNextKey,
                             UtlString& rNextValue) const
{
   OsReadLock  lock(mRWMutex);
   UtlBoolean  foundMatch;
   size_t      nextIdx = 0;
   DbEntry     lookupPair(rKey);
   DbEntry*    pEntry;

   foundMatch = FALSE;
   if (rKey.compareTo("") == 0)
   {
      foundMatch = TRUE;         // if the key is the empty string, then
      nextIdx = 0;               // return the first entry in the database
   }
   else
   {
      size_t idx = mDb.index(&lookupPair);
      if (idx != UTL_NOT_FOUND)
      {
         foundMatch = TRUE;
         nextIdx = idx + 1;
      }
   }

   if (foundMatch && (((int)nextIdx) < numEntries()))
   {
      pEntry     = (DbEntry *)mDb.at(nextIdx);
      rNextKey   = pEntry->key;
      rNextValue = pEntry->value;

      return OS_SUCCESS;
   }

   rNextKey   = "";
   rNextValue = "";

   if (!foundMatch)
      return OS_NOT_FOUND;
   else
      return OS_NO_MORE_DATA;
}
std::string kyleAndKristinTrends::getNthPopular(unsigned int n){
	if (!isSorted){
		std::sort(sortingArr.begin(), sortingArr.end(), 
		[this](const std::pair<std::string, unsigned int> i, std::pair<std::string, unsigned int> j) 
		{
			isSorted = true;
			if (ints[i.second] == ints[j.second]){
			return (i.first < j.first);
		}

		return (ints[i.second] > ints[j.second]); });
		
	}
	if (n <= numEntries()){
		return sortingArr[n].first;
		
	}
	//If they give bad input, return empty string.
	return "";
	
	
}
void Table::hashStats(ostream &out) const {
  
  out << "Number of hash buckets: " << hashSize << endl;
  out << "Number of entries: " << numEntries() << endl;

  int numBuckets = 0;
  int temp;
  int longestChain = 0;
  for(int i = 0; i < hashSize; i++){
    if(hashTable[i] != NULL) {
      numBuckets++;
      temp = countNodes(hashTable[i]);
      if(temp > longestChain) {
	longestChain = temp;
      }
    }
  }

  out << "Number of non-empty buckets: " << numBuckets << endl;
  out << "Longest chain: " << longestChain << endl;
  
}
Beispiel #10
0
// -----------------------------------------------------------------------------
// Loads all text language definitions from slade.pk3
// -----------------------------------------------------------------------------
bool TextLanguage::loadLanguages()
{
	// Get slade resource archive
	auto res_archive = App::archiveManager().programResourceArchive();

	// Read language definitions from resource archive
	if (res_archive)
	{
		// Get 'config/languages' directly
		auto dir = res_archive->dir("config/languages");

		if (dir)
		{
			// Read all entries in this dir
			for (unsigned a = 0; a < dir->numEntries(); a++)
				readLanguageDefinition(dir->entryAt(a)->data(), dir->entryAt(a)->name());
		}
		else
			Log::warning(
				1, "Warning: 'config/languages' not found in slade.pk3, no builtin text language definitions loaded");
	}

	return true;
}
void TimeSeriesAggregate::setOutputCol(time_t startTime,
                                       int sliceNum,
                                       time_t width)
{
  time_t targetTime = (isFirstVal_ ? startTime : startTime + width);
  time_t currTime = 0;

  // Find the last entry before our target time, if it exists.
  // Include the target time for first value, exclude it for
  // last value (in that case the target time already belongs
  // to the next time slice)
  while (currIx_+1 < numEntries() &&
         ((isFirstVal_ && getTime(currIx_+1) <= targetTime) ||
          (!isFirstVal_ && getTime(currIx_+1) < targetTime)))
    currIx_++;

  if (currIx_ >= 0)
    currTime = getTime(currIx_);

  if (isConstInterpol_)
    {
      // currIx_ points to the entry with the last known constant
      // value to use or currIx_ is -1 (no last known value exists)
      if (currIx_ < 0 ||
          (useLong_ && lValues_[currIx_].isNull()) ||
          (!useLong_ && dValues_[currIx_].isNull()))
        // produce a NULL value
        outTup_.setNull(outputColNum_);
      else if (useLong_)
        outTup_.setLong(outputColNum_, lValues_[currIx_].getVal());
      else
        outTup_.setDouble(outputColNum_, dValues_[currIx_].getVal());
    } // constant interpolation
  else
    {
      // linear interpolation, always uses a double value

      // currIx_ points to the last known value or is -1 (no last
      // known value exists). Now look for the next known value.
      NullableTimedValue<double> interpolatedVal;

      if (currIx_ >= 0 && currTime == targetTime)
        {
          // currIx_ and nextIx_ point to the one
          // entry describing the value, no interpolation needed
          interpolatedVal = dValues_[currIx_];
        }
      else if (currIx_ < 0 || currIx_+1 >= numEntries())
        {
          // produce a NULL value for these boundary cases where
          // we are missing an upper or lower entry to use for
          // interpolation
          interpolatedVal = NullableTimedValue<double>(true, targetTime, 0.0);
        }
      else
        {
          // currIx_ and the next entry should have time values
          // that form an interval we can use to interpolate
          interpolatedVal =
            dValues_[currIx_].interpolateLinear(
                    targetTime,
                    dValues_[currIx_+1]);
        }

      // now produce the value
      if (interpolatedVal.isNull())
        outTup_.setNull(outputColNum_);
      else
        outTup_.setDouble(outputColNum_, interpolatedVal.getVal());
    } // linear interpolation
}
Beispiel #12
0
/* RffArchive::open
 * Reads grp format data from a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool RffArchive::open(MemChunk& mc)
{
	// Check data was given
	if (!mc.hasData())
		return false;

	// Read grp header
	uint8_t magic[4];
	uint32_t version, dir_offset, num_lumps;

	mc.seek(0, SEEK_SET);
	mc.read(magic, 4);			// Should be "RFF\x18"
	mc.read(&version, 4);		// 0x01 0x03 \x00 \x00
	mc.read(&dir_offset, 4);	// Offset to directory
	mc.read(&num_lumps, 4);		// No. of lumps in rff

	// Byteswap values for big endian if needed
	dir_offset = wxINT32_SWAP_ON_BE(dir_offset);
	num_lumps = wxINT32_SWAP_ON_BE(num_lumps);
	version = wxINT32_SWAP_ON_BE(version);

	// Check the header
	if (magic[0] != 'R' || magic[1] != 'F' || magic[2] != 'F' || magic[3] != 0x1A || version != 0x301)
	{
		wxLogMessage("RffArchive::openFile: File %s has invalid header", filename);
		Global::error = "Invalid rff header";
		return false;
	}

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	// Read the directory
	RFFLump* lumps = new RFFLump[num_lumps];
	mc.seek(dir_offset, SEEK_SET);
	theSplashWindow->setProgressMessage("Reading rff archive data");
	mc.read (lumps, num_lumps * sizeof(RFFLump));
	BloodCrypt (lumps, dir_offset, num_lumps * sizeof(RFFLump));
	for (uint32_t d = 0; d < num_lumps; d++)
	{
		// Update splash window progress
		theSplashWindow->setProgress(((float)d / (float)num_lumps));

		// Read lump info
		char name[13] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
		uint32_t offset = wxINT32_SWAP_ON_BE(lumps[d].FilePos);
		uint32_t size = wxINT32_SWAP_ON_BE(lumps[d].Size);

		// Reconstruct name
		int i, j = 0;
		for (i = 0; i < 8; ++i)
		{
			if (lumps[d].Name[i] == 0) break;
			name[i] = lumps[d].Name[i];
		}
		for (name[i++] = '.'; j < 3; ++j)
			name[i+j] = lumps[d].Extension[j];

		// If the lump data goes past the end of the file,
		// the rfffile is invalid
		if (offset + size > mc.getSize())
		{
			wxLogMessage("RffArchive::open: rff archive is invalid or corrupt");
			Global::error = "Archive is invalid and/or corrupt";
			setMuted(false);
			return false;
		}

		// Create & setup lump
		ArchiveEntry* nlump = new ArchiveEntry(wxString::FromAscii(name), size);
		nlump->setLoaded(false);
		nlump->exProp("Offset") = (int)offset;
		nlump->setState(0);

		// Is the entry encrypted?
		if (lumps[d].Flags & 0x10)
			nlump->setEncryption(ENC_BLOOD);

		// Add to entry list
		getRoot()->addEntry(nlump);
	}
	delete[] lumps;

	// Detect all entry types
	MemChunk edata;
	theSplashWindow->setProgressMessage("Detecting entry types");
	for (size_t a = 0; a < numEntries(); a++)
	{
		// Update splash window progress
		theSplashWindow->setProgress((((float)a / (float)num_lumps)));

		// Get entry
		ArchiveEntry* entry = getEntry(a);

		// Read entry data if it isn't zero-sized
		if (entry->getSize() > 0)
		{
			// Read the entry data
			mc.exportMemChunk(edata, getEntryOffset(entry), entry->getSize());

			// If the entry is encrypted, decrypt it
			if (entry->isEncrypted())
			{
				uint8_t* cdata = new uint8_t[entry->getSize()];
				memcpy(cdata, edata.getData(), entry->getSize());
				int cryptlen = entry->getSize() < 256 ? entry->getSize() : 256;
				BloodCrypt(cdata, 0, cryptlen);
				edata.importMem(cdata, entry->getSize());
				delete[] cdata;
			}

			// Import data
			entry->importMemChunk(edata);
		}

		// Detect entry type
		EntryType::detectEntryType(entry);

		// Unload entry data if needed
		if (!archive_load_data)
			entry->unloadData();

		// Set entry to unchanged
		entry->setState(0);
	}

	// Detect maps (will detect map entry types)
	//theSplashWindow->setProgressMessage("Detecting maps");
	//detectMaps();

	// Setup variables
	setMuted(false);
	setModified(false);
	announce("opened");

	theSplashWindow->setProgressMessage("");

	return true;
}
Beispiel #13
0
OsStatus OsConfigDb::updateFile(const char* filename) const
{
   UtlString originalFileContents;
   long fileLength = OsFile::openAndRead(filename, originalFileContents);
   const char* unparsedBits = originalFileContents;
   int unparsedLength = originalFileContents.length();

   // Loop through and try to preserve comments, space and order
   int lineStart = 0;
   int lineEnd = 0;
   UtlHashBag writtenNames;
   UtlString newFileContents;
   UtlString name;
   UtlString value;
   UtlString newValue;

   while(lineStart < unparsedLength)
   {
      lineEnd = UtlTokenizer::nextDelim(unparsedBits, lineStart, unparsedLength, "\n\r");

      //printf("start: %d end: %d length: %d\n", lineStart, lineEnd, unparsedLength);

      UtlString oneLine(&unparsedBits[lineStart], lineEnd - lineStart);

      //printf("Line: <%s>\n", oneLine.data());

      // If line contains a parameter
      if(parseLine(oneLine, mCapitalizeName, filename, name, value))
      {
         //printf("name<%s> value<%s>\n", name.data(), value.data());
         if(get(name, newValue) == OS_SUCCESS &&
            !writtenNames.contains(&name))
         {
            //printf("Wrote name<%s>\n", name.data());
            // The parameter still exists in the configDb and we have not yet
            // written it out, write the potentially changed value
            newFileContents.appendFormat("%s : %s\n", name.data(), newValue.data());

            // Save names/parameters written so that we can figure out what has not
            // been written out
            writtenNames.insert(new UtlString(name));
         }
         // else the parameter was removed, do nothing
      }
   
      // The line was a comment or blank line, write it back out the same
      else
      {
         newFileContents.appendFormat("%s\n", oneLine.data());
      }

      lineStart = lineEnd + 1;
   }

   int paramIndex;
   int paramCount = numEntries();
   DbEntry* paramEntry;

   for (paramIndex = 0; paramIndex < paramCount; paramIndex++)
   {
      paramEntry = (DbEntry*) mDb.at(paramIndex);

      removeNewlineReturns(paramEntry->key);
      removeNewlineReturns(paramEntry->value);

      // We have not written the value yet
      if(!writtenNames.contains(&(paramEntry->key)))
      {
          newFileContents.appendFormat("%s : %s\n", paramEntry->key.data(), paramEntry->value.data());
          writtenNames.insert(new UtlString(paramEntry->key));
      }
   }

   fileLength = OsFile::openAndWrite(filename, newFileContents);
 
   writtenNames.destroyAll();

   return(fileLength > 0 ? OS_SUCCESS : OS_INVALID_ARGUMENT);
}
Beispiel #14
0
/* Wad2Archive::open
 * Reads wad format data from a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool Wad2Archive::open(MemChunk& mc)
{
	// Check data was given
	if (!mc.hasData())
		return false;

	// Read wad header
	uint32_t	num_lumps = 0;
	uint32_t	dir_offset = 0;
	char		wad_type[4] = "";
	mc.seek(0, SEEK_SET);
	mc.read(&wad_type, 4);		// Wad type
	mc.read(&num_lumps, 4);		// No. of lumps in wad
	mc.read(&dir_offset, 4);	// Offset to directory

	// Byteswap values for big endian if needed
	num_lumps = wxINT32_SWAP_ON_BE(num_lumps);
	dir_offset = wxINT32_SWAP_ON_BE(dir_offset);

	// Check the header
	if (wad_type[0] != 'W' || wad_type[1] != 'A' || wad_type[2] != 'D' ||
	        (wad_type[3] != '2' && wad_type[3] != '3'))
	{
		wxLogMessage("Wad2Archive::open: Invalid header");
		Global::error = "Invalid wad2 header";
		return false;
	}
	if (wad_type[3] == '3')
		wad3 = true;

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	// Read the directory
	mc.seek(dir_offset, SEEK_SET);
	theSplashWindow->setProgressMessage("Reading wad archive data");
	for (uint32_t d = 0; d < num_lumps; d++)
	{
		// Update splash window progress
		theSplashWindow->setProgress(((float)d / (float)num_lumps));

		// Read lump info
		wad2entry_t info;
		mc.read(&info, 32);

		// Byteswap values for big endian if needed
		info.offset = wxINT32_SWAP_ON_BE(info.offset);
		info.size = wxINT32_SWAP_ON_BE(info.size);
		info.dsize = wxINT32_SWAP_ON_BE(info.dsize);

		// If the lump data goes past the end of the file,
		// the wadfile is invalid
		if ((unsigned)(info.offset + info.dsize) > mc.getSize())
		{
			wxLogMessage("Wad2Archive::open: Wad2 archive is invalid or corrupt");
			Global::error = "Archive is invalid and/or corrupt";
			setMuted(false);
			return false;
		}

		// Create & setup lump
		ArchiveEntry* nlump = new ArchiveEntry(wxString::FromAscii(info.name, 16), info.dsize);
		nlump->setLoaded(false);
		nlump->exProp("Offset") = (int)info.offset;
		nlump->exProp("W2Type") = info.type;
		nlump->exProp("W2Size") = (int)info.size;
		nlump->exProp("W2Comp") = !!(info.cmprs);
		nlump->setState(0);

		// Add to entry list
		getRoot()->addEntry(nlump);
	}

	// Detect all entry types
	MemChunk edata;
	theSplashWindow->setProgressMessage("Detecting entry types");
	for (size_t a = 0; a < numEntries(); a++)
	{
		// Update splash window progress
		theSplashWindow->setProgress((((float)a / (float)num_lumps)));

		// Get entry
		ArchiveEntry* entry = getEntry(a);

		// Read entry data if it isn't zero-sized
		if (entry->getSize() > 0)
		{
			// Read the entry data
			mc.exportMemChunk(edata, (int)entry->exProp("Offset"), entry->getSize());
			entry->importMemChunk(edata);
		}

		// Detect entry type
		EntryType::detectEntryType(entry);

		// Unload entry data if needed
		if (!archive_load_data)
			entry->unloadData();

		// Set entry to unchanged
		entry->setState(0);
	}

	// Detect maps (will detect map entry types)
	theSplashWindow->setProgressMessage("Detecting maps");
	detectMaps();

	// Setup variables
	setMuted(false);
	setModified(false);
	announce("opened");

	theSplashWindow->setProgressMessage("");

	return true;
}
Beispiel #15
0
/* GobArchive::open
 * Reads gob format data from a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool GobArchive::open(MemChunk& mc)
{
	// Check data was given
	if (!mc.hasData())
		return false;

	// Check size
	if (mc.getSize() < 12)
		return false;

	// Check magic header
	if (mc[0] != 'G' || mc[1] != 'O' || mc[2] != 'B' || mc[3] != 0xA)
		return false;

	// Get directory offset
	uint32_t dir_offset = 0;
	mc.seek(4, SEEK_SET);
	mc.read(&dir_offset, 4);
	dir_offset = wxINT32_SWAP_ON_BE(dir_offset);

	// Check size
	if ((unsigned)mc.getSize() < (dir_offset + 4))
		return false;

	// Get number of lumps
	uint32_t num_lumps = 0;
	mc.seek(dir_offset, SEEK_SET);
	mc.read(&num_lumps, 4);
	num_lumps = wxINT32_SWAP_ON_BE(num_lumps);

	// Compute directory size
	uint32_t dir_size = (num_lumps * 21) + 4;
	if ((unsigned)mc.getSize() < (dir_offset + dir_size))
		return false;

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	// Read the directory
	theSplashWindow->setProgressMessage("Reading gob archive data");
	for (uint32_t d = 0; d < num_lumps; d++)
	{
		// Update splash window progress
		theSplashWindow->setProgress(((float)d / (float)num_lumps));

		// Read lump info
		uint32_t offset = 0;
		uint32_t size = 0;
		char name[13] = "";

		mc.read(&offset, 4);	// Offset
		mc.read(&size, 4);		// Size
		mc.read(name, 13);		// Name
		name[12] = '\0';

		// Byteswap values for big endian if needed
		size = wxINT32_SWAP_ON_BE(size);

		// If the lump data goes past the end of the file,
		// the gobfile is invalid
		if (offset + size > mc.getSize())
		{
			wxLogMessage("GobArchive::open: gob archive is invalid or corrupt");
			Global::error = "Archive is invalid and/or corrupt";
			setMuted(false);
			return false;
		}

		// Create & setup lump
		ArchiveEntry* nlump = new ArchiveEntry(wxString::FromAscii(name), size);
		nlump->setLoaded(false);
		nlump->exProp("Offset") = (int)offset;
		nlump->setState(0);

		// Add to entry list
		getRoot()->addEntry(nlump);
	}

	// Detect all entry types
	MemChunk edata;
	theSplashWindow->setProgressMessage("Detecting entry types");
	for (size_t a = 0; a < numEntries(); a++)
	{
		// Update splash window progress
		theSplashWindow->setProgress((((float)a / (float)num_lumps)));

		// Get entry
		ArchiveEntry* entry = getEntry(a);

		// Read entry data if it isn't zero-sized
		if (entry->getSize() > 0)
		{
			// Read the entry data
			mc.exportMemChunk(edata, getEntryOffset(entry), entry->getSize());
			entry->importMemChunk(edata);
		}

		// Detect entry type
		EntryType::detectEntryType(entry);

		// Unload entry data if needed
		if (!archive_load_data)
			entry->unloadData();

		// Set entry to unchanged
		entry->setState(0);
	}

	// Setup variables
	setMuted(false);
	setModified(false);
	announce("opened");

	theSplashWindow->setProgressMessage("");

	return true;
}
Beispiel #16
0
/* LfdArchive::open
 * Reads lfd format data from a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool LfdArchive::open(MemChunk& mc)
{
	// Check data was given
	if (!mc.hasData())
		return false;

	// Check size
	if (mc.getSize() < 16)
		return false;

	// Check magic header
	if (mc[0] != 'R' || mc[1] != 'M' || mc[2] != 'A' || mc[3] != 'P')
		return false;

	// Get directory length
	uint32_t dir_len = 0;
	mc.seek(12, SEEK_SET);
	mc.read(&dir_len, 4);
	dir_len = wxINT32_SWAP_ON_BE(dir_len);

	// Check size
	if ((unsigned)mc.getSize() < (dir_len) || dir_len % 16)
		return false;

	// Guess number of lumps
	uint32_t num_lumps = dir_len / 16;

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	// Read each entry
	theSplashWindow->setProgressMessage("Reading lfd archive data");
	size_t offset = dir_len + 16;
	size_t size = mc.getSize();
	for (uint32_t d = 0; offset < size; d++)
	{
		// Update splash window progress
		theSplashWindow->setProgress(((float)d / (float)num_lumps));

		// Read lump info
		uint32_t length = 0;
		char type[5] = "";
		char name[9] = "";

		mc.read(type, 4);		// Type
		mc.read(name, 8);		// Name
		mc.read(&length, 4);	// Size
		name[8] = '\0'; type[4] = 0;

		// Move past the header
		offset += 16;

		// Byteswap values for big endian if needed
		length = wxINT32_SWAP_ON_BE(length);

		// If the lump data goes past the end of the file,
		// the gobfile is invalid
		if (offset + length > size)
		{
			wxLogMessage("LfdArchive::open: lfd archive is invalid or corrupt");
			Global::error = "Archive is invalid and/or corrupt";
			setMuted(false);
			return false;
		}

		// Create & setup lump
		wxFileName fn(name);
		fn.SetExt(type);
		ArchiveEntry* nlump = new ArchiveEntry(fn.GetFullName(), length);
		nlump->setLoaded(false);
		nlump->exProp("Offset") = (int)offset;
		nlump->setState(0);

		// Add to entry list
		getRoot()->addEntry(nlump);

		// Move to next entry
		offset += length;
		mc.seek(offset, SEEK_SET);
	}

	if (num_lumps != numEntries())
		wxLogMessage("Warning: computed %i lumps, but actually %i entries", num_lumps, numEntries());

	// Detect all entry types
	MemChunk edata;
	theSplashWindow->setProgressMessage("Detecting entry types");
	for (size_t a = 0; a < numEntries(); a++)
	{
		// Update splash window progress
		theSplashWindow->setProgress((((float)a / (float)num_lumps)));

		// Get entry
		ArchiveEntry* entry = getEntry(a);

		// Read entry data if it isn't zero-sized
		if (entry->getSize() > 0)
		{
			// Read the entry data
			mc.exportMemChunk(edata, getEntryOffset(entry), entry->getSize());
			entry->importMemChunk(edata);
		}

		// Detect entry type
		EntryType::detectEntryType(entry);

		// Unload entry data if needed
		if (!archive_load_data)
			entry->unloadData();

		// Set entry to unchanged
		entry->setState(0);
	}

	// Setup variables
	setMuted(false);
	setModified(false);
	announce("opened");

	theSplashWindow->setProgressMessage("");

	return true;
}
Beispiel #17
0
/* WadArchive::write
 * Writes the wad archive to a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool WadArchive::write(MemChunk& mc, bool update)
{
	// Don't write if iwad
	if (iwad && iwad_lock)
	{
		Global::error = "IWAD saving disabled";
		return false;
	}

	// Determine directory offset & individual lump offsets
	uint32_t dir_offset = 12;
	ArchiveEntry* entry = NULL;
	for (uint32_t l = 0; l < numEntries(); l++)
	{
		entry = getEntry(l);
		setEntryOffset(entry, dir_offset);
		dir_offset += entry->getSize();
	}

	// Clear/init MemChunk
	mc.clear();
	mc.seek(0, SEEK_SET);
	mc.reSize(dir_offset + numEntries() * 16);

	// Setup wad type
	char wad_type[4] = { 'P', 'W', 'A', 'D' };
	if (iwad) wad_type[0] = 'I';

	// Write the header
	uint32_t num_lumps = numEntries();
	mc.write(wad_type, 4);
	mc.write(&num_lumps, 4);
	mc.write(&dir_offset, 4);

	// Write the lumps
	for (uint32_t l = 0; l < num_lumps; l++)
	{
		entry = getEntry(l);
		mc.write(entry->getData(), entry->getSize());
	}

	// Write the directory
	for (uint32_t l = 0; l < num_lumps; l++)
	{
		entry = getEntry(l);
		char name[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
		long offset = getEntryOffset(entry);
		long size = entry->getSize();

		for (size_t c = 0; c < entry->getName().length() && c < 8; c++)
			name[c] = entry->getName()[c];

		mc.write(&offset, 4);
		mc.write(&size, 4);
		mc.write(name, 8);

		if (update)
		{
			entry->setState(0);
			entry->exProp("Offset") = (int)offset;
		}
	}

	return true;
}
Beispiel #18
0
/* WadArchive::findLast
 * Returns the last entry matching the search criteria in [options],
 * or NULL if no matching entry was found
 *******************************************************************/
ArchiveEntry* WadArchive::findLast(search_options_t& options)
{
	// Init search variables
	ArchiveEntry* start = getEntry(numEntries()-1);
	ArchiveEntry* end = NULL;
	options.match_name = options.match_name.Lower();

	// "graphics" namespace is the global namespace in a wad
	if (options.match_namespace == "graphics")
		options.match_namespace = "";

	// "global" namespace has no name, by the way
	if (options.match_namespace == "global")
		options.match_namespace = "";

	// Check for namespace to search
	if (!options.match_namespace.IsEmpty())
	{
		// Find matching namespace
		bool ns_found = false;
		for (unsigned a = 0; a < namespaces.size(); a++)
		{
			if (namespaces[a].name == options.match_namespace)
			{
				start = namespaces[a].end->prevEntry();
				end = namespaces[a].start;
				ns_found = true;
				break;
			}
		}

		// Return none if namespace not found
		if (!ns_found)
			return NULL;
	}

	// Begin search
	ArchiveEntry* entry = start;
	while (entry != end)
	{
		// Check type
		if (options.match_type)
		{
			if (entry->getType() == EntryType::unknownType())
			{
				if (!options.match_type->isThisType(entry))
				{
					entry = entry->prevEntry();
					continue;
				}
			}
			else if (options.match_type != entry->getType())
			{
				entry = entry->prevEntry();
				continue;
			}
		}

		// Check name
		if (!options.match_name.IsEmpty())
		{
			if (!options.match_name.Matches(entry->getName().Lower()))
			{
				entry = entry->prevEntry();
				continue;
			}
		}

		// Entry passed all checks so far, so we found a match
		return entry;
	}

	// No match found
	return NULL;
}
Beispiel #19
0
/* WadArchive::updateNamespaces
 * Updates the namespace list
 *******************************************************************/
void WadArchive::updateNamespaces()
{
	// Clear current namespace info
	while (namespaces.size() > 0)
		namespaces.pop_back();

	// Go through all entries
	for (unsigned a = 0; a < numEntries(); a++)
	{
		ArchiveEntry* entry = getRoot()->getEntry(a);

		// Check for namespace begin
		if (entry->getName().Matches("*_START"))
		{
			// Create new namespace
			wad_ns_pair_t ns(entry, NULL);
			string name = entry->getName();
			ns.name = name.Left(name.Length() - 6).Lower();
			ns.start_index = entryIndex(ns.start);

			// Convert some special cases (because technically PP_START->P_END is a valid namespace)
			if (ns.name == "pp")
				ns.name = "p";
			if (ns.name == "ff")
				ns.name = "f";
			if (ns.name == "ss")
				ns.name = "s";
			if (ns.name == "tt")
				ns.name = "t";

			// Add to namespace list
			namespaces.push_back(ns);
		}
		// Check for namespace end
		else if (entry->getName().Matches("?_END") || entry->getName().Matches("??_END"))
		{
			// Get namespace 'name'
			int len = entry->getName().Length() - 4;
			string ns_name = entry->getName().Left(len).Lower();

			// Convert some special cases (because technically P_START->PP_END is a valid namespace)
			if (ns_name == "pp")
				ns_name = "p";
			if (ns_name == "ff")
				ns_name = "f";
			if (ns_name == "ss")
				ns_name = "s";
			if (ns_name == "tt")
				ns_name = "t";

			// Check if it's the end of an existing namespace
			// Remember entry is getEntry(a)? index is 'a'
			//size_t index = entryIndex(entry);

			bool found = false;
			for (unsigned b = 0; b < namespaces.size(); b++)
			{
				// Can't close a namespace that starts afterwards
				if (namespaces[b].start_index > a)
					break;
				// Can't close an already-closed namespace
				if (namespaces[b].end != NULL)
					continue;
				if (S_CMP(ns_name, namespaces[b].name))
				{
					found = true;
					namespaces[b].end = entry;
					namespaces[b].end_index = a;
					break;
				}
			}
			// Flat hack: closing the flat namespace without opening it
			if (found == false && ns_name == "f")
			{
				wad_ns_pair_t ns(getRoot()->getEntry(0), entry);
				ns.start_index = 0;
				ns.end_index = a;
				ns.name = "f";
				namespaces.push_back(ns);
			}
		}
	}

	// ROTT stuff. The first lump in the archive is always WALLSTRT, the last lump is either
	// LICENSE (darkwar.wad) or VENDOR (huntbgin.wad), with TABLES just before in both cases.
	// The shareware version has 2091 lumps, the complete version has about 50% more.
	if (numEntries() > 2090 && getRoot()->getEntry(0)->getName().Matches("WALLSTRT") &&
	        getRoot()->getEntry(numEntries()-2)->getName().Matches("TABLES"))
	{
		wad_ns_pair_t ns(getRoot()->getEntry(0), getRoot()->getEntry(numEntries()-1));
		ns.name = "rott";
		ns.start_index = 0;
		ns.end_index = entryIndex(ns.end);
		namespaces.push_back(ns);
	}


	// Check namespaces
	for (unsigned a = 0; a < namespaces.size(); a++)
	{
		wad_ns_pair_t& ns = namespaces[a];

		// Check the namespace has an end
		if (!ns.end)
		{
			// If not, remove the namespace as it is invalid
			namespaces.erase(namespaces.begin() + a);
			a--;
			continue;
		}

		// Check namespace name for special cases
		for (int n = 0; n < n_special_namespaces; n++)
		{
			if (S_CMP(ns.name, special_namespaces[n].letter))
				ns.name = special_namespaces[n].name;
		}

		ns.start_index = entryIndex(ns.start);
		ns.end_index = entryIndex(ns.end);

		// Testing
		//wxLogMessage("Namespace %s from %s (%d) to %s (%d)", ns.name,
		//	ns.start->getName(), ns.start_index, ns.end->getName(), ns.end_index);
	}
}
Beispiel #20
0
// Return TRUE if the Rsc database is empty.
UtlBoolean UtlRscStore::isEmpty(void) const
{
   return (numEntries() == 0);
}
Beispiel #21
0
// -----------------------------------------------------------------------------
// Reads grp format data from a MemChunk
// Returns true if successful, false otherwise
// -----------------------------------------------------------------------------
bool GrpArchive::open(MemChunk& mc)
{
	// Check data was given
	if (!mc.hasData())
		return false;

	// Read grp header
	uint32_t num_lumps     = 0;
	char     ken_magic[13] = "";
	mc.seek(0, SEEK_SET);
	mc.read(ken_magic, 12); // "KenSilverman"
	mc.read(&num_lumps, 4); // No. of lumps in grp

	// Byteswap values for big endian if needed
	num_lumps = wxINT32_SWAP_ON_BE(num_lumps);

	// Null-terminate the magic header
	ken_magic[12] = 0;

	// Check the header
	if (!(S_CMP(wxString::FromAscii(ken_magic), "KenSilverman")))
	{
		Log::error(S_FMT("GrpArchive::openFile: File %s has invalid header", filename_));
		Global::error = "Invalid grp header";
		return false;
	}

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	// The header takes as much space as a directory entry
	uint32_t entryoffset = 16 * (1 + num_lumps);

	// Read the directory
	UI::setSplashProgressMessage("Reading grp archive data");
	for (uint32_t d = 0; d < num_lumps; d++)
	{
		// Update splash window progress
		UI::setSplashProgress(((float)d / (float)num_lumps));

		// Read lump info
		char     name[13] = "";
		uint32_t offset   = entryoffset;
		uint32_t size     = 0;

		mc.read(name, 12); // Name
		mc.read(&size, 4); // Size
		name[12] = '\0';

		// Byteswap values for big endian if needed
		size = wxINT32_SWAP_ON_BE(size);

		// Increase offset of next entry by this entry's size
		entryoffset += size;

		// If the lump data goes past the end of the file,
		// the grpfile is invalid
		if (offset + size > mc.size())
		{
			Log::error("GrpArchive::open: grp archive is invalid or corrupt");
			Global::error = "Archive is invalid and/or corrupt";
			setMuted(false);
			return false;
		}

		// Create & setup lump
		auto nlump = std::make_shared<ArchiveEntry>(wxString::FromAscii(name), size);
		nlump->setLoaded(false);
		nlump->exProp("Offset") = (int)offset;
		nlump->setState(ArchiveEntry::State::Unmodified);

		// Add to entry list
		rootDir()->addEntry(nlump);
	}

	// Detect all entry types
	MemChunk edata;
	UI::setSplashProgressMessage("Detecting entry types");
	for (size_t a = 0; a < numEntries(); a++)
	{
		// Update splash window progress
		UI::setSplashProgress((((float)a / (float)num_lumps)));

		// Get entry
		auto entry = entryAt(a);

		// Read entry data if it isn't zero-sized
		if (entry->size() > 0)
		{
			// Read the entry data
			mc.exportMemChunk(edata, getEntryOffset(entry), entry->size());
			entry->importMemChunk(edata);
		}

		// Detect entry type
		EntryType::detectEntryType(entry);

		// Unload entry data if needed
		if (!archive_load_data)
			entry->unloadData();

		// Set entry to unchanged
		entry->setState(ArchiveEntry::State::Unmodified);
	}

	// Setup variables
	setMuted(false);
	setModified(false);
	announce("opened");

	UI::setSplashProgressMessage("");

	return true;
}
Beispiel #22
0
/* DatArchive::write
 * Writes the dat archive to a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool DatArchive::write(MemChunk& mc, bool update)
{
	// Only two bytes are used for storing entry amount,
	// so abort for excessively large files:
	if (numEntries() > 65535)
		return false;

	// Determine directory offset, name offsets & individual lump offsets
	uint32_t dir_offset = 10;
	uint16_t name_offset = numEntries() * 12;
	uint32_t name_size = 0;
	string previousname = "";
	uint16_t* nameoffsets = new uint16_t[numEntries()];
	ArchiveEntry* entry = NULL;
	for (uint16_t l = 0; l < numEntries(); l++)
	{
		entry = getEntry(l);
		setEntryOffset(entry, dir_offset);
		dir_offset += entry->getSize();

		// Does the entry has a name?
		string name = entry->getName();
		if (l > 0 && previousname.length() > 0 && name.length() > previousname.length() &&
		        !previousname.compare(0, previousname.length(), name, 0, previousname.length()) &&
		        name.at(previousname.length()) == '+')
		{
			// This is a fake name
			name = "";
			nameoffsets[l] = 0;
		}
		else
		{
			// This is a true name
			previousname = name;
			nameoffsets[l] = uint16_t(name_offset + name_size);
			name_size += name.length() + 1;
		}
	}

	// Clear/init MemChunk
	mc.clear();
	mc.seek(0, SEEK_SET);
	mc.reSize(dir_offset + name_size + numEntries() * 12);

	// Write the header
	uint16_t num_lumps = wxINT16_SWAP_ON_BE(numEntries());
	dir_offset = wxINT32_SWAP_ON_BE(dir_offset);
	uint32_t unknown = 0;
	mc.write(&num_lumps, 2);
	mc.write(&dir_offset, 4);
	mc.write(&unknown, 4);

	// Write the lumps
	for (uint16_t l = 0; l < numEntries(); l++)
	{
		entry = getEntry(l);
		mc.write(entry->getData(), entry->getSize());
	}

	// Write the directory
	for (uint16_t l = 0; l < num_lumps; l++)
	{
		entry = getEntry(l);

		uint32_t offset = wxINT32_SWAP_ON_BE(getEntryOffset(entry));
		uint32_t size = wxINT32_SWAP_ON_BE(entry->getSize());
		uint16_t nameofs = wxINT16_SWAP_ON_BE(nameoffsets[l]);
		uint16_t flags = wxINT16_SWAP_ON_BE((entry->isEncrypted() == ENC_SCRLE0) ? 1 : 0);

		mc.write(&offset,	4);		// Offset
		mc.write(&size,		4);		// Size
		mc.write(&nameofs,	2);		// Name offset
		mc.write(&flags,	2);		// Flags

		if (update)
		{
			entry->setState(0);
			entry->exProp("Offset") = (int)wxINT32_SWAP_ON_BE(offset);
		}
	}

	// Write the names
	for (uint16_t l = 0; l < num_lumps; l++)
	{
		uint8_t zero = 0;
		entry = getEntry(l);
		if (nameoffsets[l])
		{
			mc.write(CHR(entry->getName()), entry->getName().length());
			mc.write(&zero, 1);
		}
	}

	// Clean-up
	delete[] nameoffsets;

	// Finished!
	return true;
}
Beispiel #23
0
bool kvoctrainDoc::parseBody_e (XmlElement elem, XmlReader& xml)
{
  grade_t       grade,
                r_grade;
  int           qcount,
                r_qcount;
  int           bcount,
                r_bcount;
  QString       remark;
  QString       pronunce;
  time_t        qdate,
                r_qdate;
  bool          inquery;
  bool          active;
  QString       lang;
  QString       textstr;
  QString       exprtype;
  bool          org_found = false;
  QString       q_org,
                q_trans;
  QString       query_id;
  kvoctrainExpr expr;
  int           lesson;
  int           width;
  QString       type;
  QString       faux_ami_f;
  QString       faux_ami_t;
  QString       synonym;
  QString       example;
  QString       antonym;
  QString       usage;
  QString       paraphrase;
  vector<Conjugation> conjug;
  Comparison     comparison;
  MultipleChoice mc;

  if (!extract_KVT_E_attr (xml, elem, lesson, inquery, active, exprtype))
    return false;

  if (lesson
      && lesson > (int) lesson_descr.size() ) { // description missing ?
    QString s;
    for (int i = lesson_descr.size(); i < lesson; i++) {
      s.setNum (i+1);
      s.insert (0, "#");  // invent descr according to number
      lesson_descr.push_back (s);
    }
  }

  if (! xml.readElement (elem) ) {
    errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
    return false;
  }

  if (elem.tag() == KV_EXPR && !elem.isEndTag() ) {
    errorKvtMl (xml.lineNumber(),
                i18n("disallowed occurrence of tag <%1>").arg(elem.tag()));
    return false;
  }

  unsigned int count = 0;
  org_found = false;
  while (elem.tag() != KV_EXPR) {

    // now want "original" and one or more "translations"

    // found original <o>

    if (elem.tag() == KV_ORG && !elem.isEndTag() ) {
      if (org_found) {
        errorKvtMl (xml.lineNumber(),
                    i18n("repeated occurrence of tag <%1>").arg(elem.tag()));
        return false;
      }
      org_found = true;

      type = exprtype;
      if (!extract_O_T_attr (
                        xml,
                        elem,
                        lang,
                        grade,  r_grade,
                        qcount, r_qcount,
                        qdate,  r_qdate,
                        remark,
                        bcount, r_bcount,
                        query_id,
                        pronunce,
                        width,
                        type,
                        faux_ami_t,
                        faux_ami_f,
                        synonym,
                        example,
                        antonym,
                        usage,
                        paraphrase))
        return false;


      if (vocabulary.size() == 0) {  // only accept in first entry
        if (width >= 0)
          setSizeHint (count, width);

        if (query_id == KV_O)
          q_org = lang;

        if (query_id == KV_T)
          q_trans = lang;
      }

      if (langs.size() == 0) {          // first entry
        if (lang.isEmpty())                 // no definition in first entry
          lang = "original";
        langs.push_back(lang);

      }
      else {
        if (lang != langs[0] && !lang.isEmpty()) {  // different originals ?
          errorKvtMl (xml.lineNumber(),
                      i18n("ambiguous definition of language code"));
          return false;
        }
      }
      count = 0;

//========================================
// FIXME:: make loop for this

      if (! xml.readElement (elem) ) {
        errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
        return false;
      }

      if (elem.tag () == KV_CONJUG_GRP && !elem.isEndTag() ) {
        if (!loadConjugKvtMl (conjug, (QString) KV_CON_TYPE, elem, xml))
          return false;

        if (! xml.readElement (elem) ) {
          errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
          return false;
        }
      }

      comparison.clear();
      if (elem.tag () == KV_COMPARISON_GRP && !elem.isEndTag() ) {
        if (!loadComparison (comparison, elem, xml))
          return false;

        if (! xml.readElement (elem) ) {
          errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
          return false;
        }
      }

      mc.clear();
      if (elem.tag () == KV_MULTIPLECHOICE_GRP && !elem.isEndTag() ) {
        if (!loadMultipleChoice (mc, elem, xml))
          return false;

        if (! xml.readElement (elem) ) {
          errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
          return false;
        }
      }

      if (elem.tag() == "#PCDATA") { // element data
        textstr = xml.getText();
        if (! xml.readElement (elem) ) {
          errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
          return false;
        }

        if (elem.tag() != KV_ORG || !elem.isEndTag() ) {
          errorKvtMl (xml.lineNumber(),
                      i18n("expected ending tag <%1>").arg(KV_ORG));
          return false;
        }
      }
      else {
        if (elem.tag() != KV_ORG || !elem.isEndTag() ) {
          errorKvtMl (xml.lineNumber(),
                      i18n("expected ending tag <%1>").arg(KV_ORG));
          return false;
        }
        textstr = "";
      }

//========================================

      expr = kvoctrainExpr (textstr);
      expr.setLesson (lesson);
      expr.setInQuery(inquery);
      expr.setActive(active);

      if (conjug.size() > 0) {
        expr.setConjugation(0, conjug[0]);
        conjug.clear();
      }
      if (!comparison.isEmpty()) {
        expr.setComparison(0, comparison);
        comparison.clear();
      }
      if (!mc.isEmpty()) {
        expr.setMultipleChoice(0, mc);
        mc.clear();
      }
      if (!remark.isEmpty() )
        expr.setRemark (0, remark);
      if (!pronunce.isEmpty() )
        expr.setPronunce (0, pronunce);
      if (!type.isEmpty() )
        expr.setType(0, type);
      if (!synonym.isEmpty() )
        expr.setSynonym(0, synonym);
      if (!example.isEmpty() )
        expr.setExample(0, example);
      if (!usage.isEmpty() )
        expr.setUsageLabel(0, usage);
      if (!paraphrase.isEmpty() )
        expr.setParaphrase(0, paraphrase);
      if (!antonym.isEmpty() )
        expr.setAntonym(0, antonym);
    }

    // found translation <t>

    else if (elem.tag() == KV_TRANS && !elem.isEndTag() ) {
      if (!org_found) {   // must be preceded by "original"
        errorKvtMl (xml.lineNumber(),
                    i18n("starting tag <%1> is missing").arg(KV_ORG));
        return false;
      }

      count++;
      type = exprtype;
      if (!extract_O_T_attr (
                        xml,
                        elem,
                        lang,
                        grade,  r_grade,
                        qcount, r_qcount,
                        qdate,  r_qdate,
                        remark,
                        bcount, r_bcount,
                        query_id,
                        pronunce,
                        width,
                        type,
                        faux_ami_f,
                        faux_ami_t,
                        synonym,
                        example,
                        antonym,
                        usage,
                        paraphrase))
       return false;

      if (vocabulary.size() == 0) {  // only accept in first entry
        if (width >= 0)
          setSizeHint (count, width);

        if (query_id == KV_O)
          q_org = lang;

        if (query_id == KV_T)
          q_trans = lang;

      }

      if (langs.size() <= count) {      // new translation
        if (lang.isEmpty()) {               // no definition in first entry ?
          lang.setNum (langs.size() );
          lang.insert (0, "translation ");
        }
        langs.push_back(lang);

      }
      else {
        if (lang != langs[count] && !lang.isEmpty()) { // different language ?
          errorKvtMl (xml.lineNumber(),
                      i18n("ambiguous definition of language code"));
          return false;
        }
      }

//========================================
// FIXME:: make loop for this

      if (! xml.readElement (elem) ) {
        errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
        return false;
      }

      if (elem.tag () == KV_CONJUG_GRP && !elem.isEndTag() ) {
        if (!loadConjugKvtMl (conjug, (QString) KV_CON_TYPE, elem, xml))
          return false;

        if (! xml.readElement (elem) ) {
          errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
          return false;
        }
      }

      comparison.clear();
      if (elem.tag () == KV_COMPARISON_GRP && !elem.isEndTag() ) {
        if (!loadComparison (comparison, elem, xml))
          return false;

        if (! xml.readElement (elem) ) {
          errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
          return false;
        }
      }

      mc.clear();
      if (elem.tag () == KV_MULTIPLECHOICE_GRP && !elem.isEndTag() ) {
        if (!loadMultipleChoice (mc, elem, xml))
          return false;

        if (! xml.readElement (elem) ) {
          errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
          return false;
        }
      }

      textstr = "";
      if (elem.tag() == "#PCDATA") { // element data
        textstr = xml.getText();

        if (! xml.readElement (elem) ) {
          errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
          return false;
        }

        if (elem.tag() != KV_TRANS || !elem.isEndTag() ) {
          errorKvtMl (xml.lineNumber(),
                      i18n("expected ending tag <%1>").arg(KV_TRANS));
          return false;
        }
        // expr ...
      }
      else {
        if (elem.tag() != KV_TRANS || !elem.isEndTag() ) {
          errorKvtMl (xml.lineNumber(),
                      i18n("expected ending tag <%1>").arg(KV_TRANS));
          return false;
        }
        textstr = "";
      }

//========================================

      if (!org_found) {
        errorKvtMl (xml.lineNumber(),
                    i18n("starting tag <%1> is missing").arg(KV_ORG));
        return false;
      }
/*
      if (qcount == 0) {
        grade = KV_NORM_GRADE;
      }

      if (r_qcount == 0) {
        r_grade = KV_NORM_GRADE;
      }
*/
      expr.addTranslation (textstr, grade, r_grade);
      expr.setQueryCount  (count, qcount, false);
      expr.setQueryCount  (count, r_qcount, true);
      expr.setBadCount    (count, bcount, false);
      expr.setBadCount    (count, r_bcount, true);
      expr.setQueryDate   (count, qdate, false);
      expr.setQueryDate   (count, r_qdate, true);

      if (conjug.size() > 0) {
        expr.setConjugation(count, conjug[0]);
        conjug.clear();
      }
      if (!comparison.isEmpty()) {
        expr.setComparison(count, comparison);
        comparison.clear();
      }
      if (!mc.isEmpty()) {
        expr.setMultipleChoice(count, mc);
        mc.clear();
      }
      if (!type.isEmpty() )
        expr.setType (count, type);
      if (!remark.isEmpty() )
        expr.setRemark (count, remark);
      if (!pronunce.isEmpty() )
        expr.setPronunce (count, pronunce);
      if (!faux_ami_f.isEmpty() )
        expr.setFauxAmi (count, faux_ami_f, false);
      if (!faux_ami_t.isEmpty() )
        expr.setFauxAmi (count, faux_ami_t, true);
      if (!synonym.isEmpty() )
        expr.setSynonym (count, synonym);
      if (!example.isEmpty() )
        expr.setExample (count, example);
      if (!usage.isEmpty() )
        expr.setUsageLabel (count, usage);
      if (!paraphrase.isEmpty() )
        expr.setParaphrase (count, paraphrase);
      if (!antonym.isEmpty() )
        expr.setAntonym (count, antonym);
    }
    else {
      if (elem.isEndTag() ) {
        errorKvtMl (xml.lineNumber(),
                    i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
        return false;
      }
      else {
        unknownElement (xml.lineNumber(), elem.tag());
        return false;
      }
    }

    if (! xml.readElement (elem) ) {
      errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
      return false;
    }
  }
  if (numEntries() == 0)
    setQueryLang (q_org, q_trans);
  vocabulary.push_back (expr);

  return true;
}
Beispiel #24
0
/* LfdArchive::write
 * Writes the lfd archive to a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool LfdArchive::write(MemChunk& mc, bool update)
{
	// Determine total size
	uint32_t dir_size = (numEntries() + 1)<<4;
	uint32_t total_size = dir_size;
	ArchiveEntry* entry = NULL;
	for (uint32_t l = 0; l < numEntries(); l++)
	{
		entry = getEntry(l);
		total_size += 16;
		setEntryOffset(entry, total_size);
		if (update)
		{
			entry->setState(0);
			entry->exProp("Offset") = (int)total_size;
		}
		total_size += entry->getSize();
	}

	// Clear/init MemChunk
	mc.clear();
	mc.seek(0, SEEK_SET);
	mc.reSize(total_size);

	// Variables
	char type[5] = "RMAP";
	char name[9] = "resource";
	size_t size = wxINT32_SWAP_ON_BE(numEntries()<<4);


	// Write the resource map first
	mc.write(type, 4);
	mc.write(name, 8);
	mc.write(&size,4);
	for (uint32_t l = 0; l < numEntries(); l++)
	{
		entry = getEntry(l);
		for (int t = 0; t < 5; ++t) type[t] = 0;
		for (int n = 0; n < 9; ++n) name[n] = 0;
		size = wxINT32_SWAP_ON_BE(entry->getSize());
		wxFileName fn(entry->getName());

		for (size_t c = 0; c < fn.GetName().length() && c < 9; c++)
			name[c] = fn.GetName()[c];
		for (size_t c = 0; c < fn.GetExt().length() && c < 5; c++)
			type[c] = fn.GetExt()[c];

		mc.write(type, 4);
		mc.write(name, 8);
		mc.write(&size,4);
	}

	// Write the lumps
	for (uint32_t l = 0; l < numEntries(); l++)
	{
		entry = getEntry(l);
		for (int t = 0; t < 5; ++t) type[t] = 0;
		for (int n = 0; n < 9; ++n) name[n] = 0;
		size = wxINT32_SWAP_ON_BE(entry->getSize());
		wxFileName fn(entry->getName());

		for (size_t c = 0; c < fn.GetName().length() && c < 9; c++)
			name[c] = fn.GetName()[c];
		for (size_t c = 0; c < fn.GetExt().length() && c < 5; c++)
			type[c] = fn.GetExt()[c];

		mc.write(type, 4);
		mc.write(name, 8);
		mc.write(&size,4);
		mc.write(entry->getData(), entry->getSize());
	}

	return true;
}
Beispiel #25
0
// Return TRUE if the name database is empty
UtlBoolean OsNameDb::isEmpty(void)
{
    return (numEntries() == 0);
}
Beispiel #26
0
/* WadArchive::open
 * Reads wad format data from a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool WadArchive::open(MemChunk& mc)
{
	// Check data was given
	if (!mc.hasData())
		return false;

	// Read wad header
	uint32_t	num_lumps = 0;
	uint32_t	dir_offset = 0;
	char		wad_type[4] = "";
	mc.seek(0, SEEK_SET);
	mc.read(&wad_type, 4);		// Wad type
	mc.read(&num_lumps, 4);		// No. of lumps in wad
	mc.read(&dir_offset, 4);	// Offset to directory

	// Byteswap values for big endian if needed
	num_lumps = wxINT32_SWAP_ON_BE(num_lumps);
	dir_offset = wxINT32_SWAP_ON_BE(dir_offset);

	// Check the header
	if (wad_type[1] != 'W' || wad_type[2] != 'A' || wad_type[3] != 'D')
	{
		wxLogMessage("WadArchive::openFile: File %s has invalid header", filename);
		Global::error = "Invalid wad header";
		return false;
	}

	// Check for iwad
	if (wad_type[0] == 'I')
		iwad = true;

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	vector<uint32_t> offsets;

	// Read the directory
	mc.seek(dir_offset, SEEK_SET);
	theSplashWindow->setProgressMessage("Reading wad archive data");
	for (uint32_t d = 0; d < num_lumps; d++)
	{
		// Update splash window progress
		theSplashWindow->setProgress(((float)d / (float)num_lumps));

		// Read lump info
		char name[9] = "";
		uint32_t offset = 0;
		uint32_t size = 0;

		mc.read(&offset, 4);	// Offset
		mc.read(&size, 4);		// Size
		mc.read(name, 8);		// Name
		name[8] = '\0';

		// Byteswap values for big endian if needed
		offset = wxINT32_SWAP_ON_BE(offset);
		size = wxINT32_SWAP_ON_BE(size);

		// Check to catch stupid shit
		if (size > 0)
		{
			if (offset == 0)
			{
				LOG_MESSAGE(2, "No.");
				continue;
			}
			if (VECTOR_EXISTS(offsets, offset))
			{
				LOG_MESSAGE(1, "Ignoring entry %d: %s, is a clone of a previous entry", d, name);
				continue;
			}
			offsets.push_back(offset);
		}

		// Hack to open Operation: Rheingold WAD files
		if (size == 0 && offset > mc.getSize())
			offset = 0;

		// Is there a compression/encryption thing going on?
		bool jaguarencrypt = !!(name[0] & 0x80);	// look at high bit
		name[0] = name[0] & 0x7F;					// then strip it away

		// Look for encryption shenanigans
		size_t actualsize = size;
		if (jaguarencrypt)
		{
			if (d < num_lumps - 1)
			{
				size_t pos = mc.currentPos();
				uint32_t nextoffset = 0;
				for (int i = 0; i + d < num_lumps; ++i)
				{
					mc.read(&nextoffset, 4);
					if (nextoffset != 0) break;
					mc.seek(12, SEEK_CUR);
				}
				nextoffset = wxINT32_SWAP_ON_BE(nextoffset);
				if (nextoffset == 0) nextoffset = dir_offset;
				mc.seek(pos, SEEK_SET);
				actualsize = nextoffset - offset;
			}
			else
			{
				if (offset > dir_offset)
				{
					actualsize = mc.getSize() - offset;
				}
				else
				{
					actualsize = dir_offset - offset;
				}
			}
		}

		// If the lump data goes past the end of the file,
		// the wadfile is invalid
		if (offset + actualsize > mc.getSize())
		{
			wxLogMessage("WadArchive::open: Wad archive is invalid or corrupt");
			Global::error = S_FMT("Archive is invalid and/or corrupt (lump %d: %s data goes past end of file)", d, name);
			setMuted(false);
			return false;
		}

		// Create & setup lump
		ArchiveEntry* nlump = new ArchiveEntry(wxString::FromAscii(name), size);
		nlump->setLoaded(false);
		nlump->exProp("Offset") = (int)offset;
		nlump->setState(0);

		if (jaguarencrypt)
		{
			nlump->setEncryption(ENC_JAGUAR);
			nlump->exProp("FullSize") = (int)size;
		}

		// Add to entry list
		getRoot()->addEntry(nlump);
	}

	// Detect namespaces (needs to be done before type detection as some types
	// rely on being within certain namespaces)
	updateNamespaces();

	// Detect all entry types
	MemChunk edata;
	theSplashWindow->setProgressMessage("Detecting entry types");
	for (size_t a = 0; a < numEntries(); a++)
	{
		// Update splash window progress
		theSplashWindow->setProgress((((float)a / (float)numEntries())));

		// Get entry
		ArchiveEntry* entry = getEntry(a);

		// Read entry data if it isn't zero-sized
		if (entry->getSize() > 0)
		{
			// Read the entry data
			mc.exportMemChunk(edata, getEntryOffset(entry), entry->getSize());
			if (entry->isEncrypted())
			{
				if (entry->exProps().propertyExists("FullSize")
				        && (unsigned)(int)(entry->exProp("FullSize")) >  entry->getSize())
					edata.reSize((int)(entry->exProp("FullSize")), true);
				if (!JaguarDecode(edata))
					wxLogMessage("%i: %s (following %s), did not decode properly", a, entry->getName(), a>0?getEntry(a-1)->getName():"nothing");
			}
			entry->importMemChunk(edata);
		}

		// Detect entry type
		EntryType::detectEntryType(entry);

		// Unload entry data if needed
		if (!archive_load_data)
			entry->unloadData();

		// Set entry to unchanged
		entry->setState(0);
	}

	// Identify #included lumps (DECORATE, GLDEFS, etc.)
	detectIncludes();

	// Detect maps (will detect map entry types)
	theSplashWindow->setProgressMessage("Detecting maps");
	detectMaps();

	// Setup variables
	setMuted(false);
	setModified(false);
	//if (iwad && iwad_lock) read_only = true;
	announce("opened");

	theSplashWindow->setProgressMessage("");

	return true;
}
Beispiel #27
0
/* GZipArchive::write
 * Writes the gzip archive to a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool GZipArchive::write(MemChunk& mc, bool update)
{
	// Clear current data
	mc.clear();

	if (numEntries() == 1)
	{
		MemChunk stream;
		if (Compression::GZipDeflate(getEntry(0)->getMCData(), stream, 9))
		{
			const uint8_t* data = stream.getData();
			uint32_t working = 0;
			size_t size = stream.getSize();
			if (size < 18) return false;

			// zlib will have given us a minimal header, so we make our own
			uint8_t header[4];
			header[0] = GZIP_ID1; header[1] = GZIP_ID2;
			header[2] = GZIP_DEFLATE; header[3] = flags;
			mc.write(header, 4);

			// Update mtime if the file was modified
			if (getEntry(0)->getState())
			{
				mtime = ::wxGetLocalTime();
			}

			// Write mtime
			working = wxUINT32_SWAP_ON_BE(mtime);
			mc.write(&working, 4);

			// Write other stuff
			mc.write(&xfl, 1);
			mc.write(&os, 1);

			// Any extra content that may have been there
			if (flags & GZIP_FLG_FXTRA)
			{
				uint16_t xlen = wxUINT16_SWAP_ON_BE(xtra.getSize());
				mc.write(&xlen, 2);
				mc.write(xtra.getData(), xtra.getSize());
			}

			// File name, if not extrapolated from archive name
			if (flags & GZIP_FLG_FNAME)
			{
				mc.write(CHR(getEntry(0)->getName()), getEntry(0)->getName().length());
				uint8_t zero = 0; mc.write(&zero, 1);	// Terminate string
			}

			// Comment, if there were actually one
			if (flags & GZIP_FLG_FCMNT)
			{
				mc.write(CHR(comment), comment.length());
				uint8_t zero = 0; mc.write(&zero, 1);	// Terminate string
			}

			// And finally, the half CRC, which we recalculate
			if (flags & GZIP_FLG_FHCRC)
			{
				uint32_t fullcrc = Misc::crc(mc.getData(), mc.getSize());
				uint16_t hcrc = (fullcrc & 0x0000FFFF);
				hcrc = wxUINT16_SWAP_ON_BE(hcrc);
				mc.write(&hcrc, 2);
			}

			// Now that the pleasantries are dispensed with,
			// let's get with the meat of the matter
			return mc.write(data + 10, size - 10);
		}
	}
	return false;
}
// ---------------------------------------------------------------------------
// Continue Scanning for more files
// ---------------------------------------------------------------------------
//
TBool CMPXFolderScanner::DoScanL()
    {
    MPX_DEBUG1("CMPXFolderScanner::DoScanL <---");
    TBool done (EFalse);
    TBool blocked ( EFalse );

    // read successfully
    if ( iStatus == KErrNone || iStatus == KErrEof )
        {
        TBuf<KMaxFileName> buffer;
        const TEntry* entry = NULL;
        TInt numEntries( iCurDirQueueEntry->iEntryArray.Count() );

        // process the entry one by one
        while ( iCurDirQueueEntry->iPos < numEntries )
            {
            entry = iCurDirQueueEntry->NextEntry();
            buffer.Zero();

            // Generates the full name of the entry
            buffer.Append( *iCurFullPath );
            buffer.Append( entry->iName );

            if ( entry->IsDir() ) // entry is a directory
                {
                buffer.Append( KTxtBackSlash );

                blocked = iObserver.IsPathBlockedL( buffer );

                if ( !blocked )
                    {
                    CDirQueueEntry* newEntry = CDirQueueEntry::NewL( buffer );
                    TInt err = newEntry->iDir.Open( iFs,
                                                    buffer,
                                             KEntryAttNormal | KEntryAttDir );
                    if ( err == KErrNone )
                        {
                        CDirQueueEntry::PushL( iDirQueue, newEntry );
                        }
                    else
                        {
                        delete newEntry;
                        }
                    }
                }
            else // entry is a file
                {
                TInt index = iObserver.IsMediaFileL( buffer );
                if( KErrNotFound != index )
                    {
                    iObserver.HandleFileAdditionL( buffer, index );
                    }
                }
            if ( iCurDirQueueEntry->iPos % KFileNumBreakCount == 0 )
                {
                return done;
                }
            }
        }

    // this dir has other entries to read
    if ( iStatus == KErrNone )
        {
        iCurDirQueueEntry->ResetPosition();
        ReadDirEntry();
        }

    // there is nothing to read or some error has occured during reading,
    // try to move to next dir
    else
        {
        CDirQueueEntry::PopAndDestroy( iDirQueue );
        if ( iDirQueue.Count() || !SetupNextDriveToScanL() )
            {
            iCurDirQueueEntry = iDirQueue[ 0 ];
            iCurFullPath = iCurDirQueueEntry->iFullPath;
            ReadDirEntry();
            }
        else // there is nothing to scan
            {
            done = ETrue;
            }
        }
        
    MPX_DEBUG1("CMPXFolderScanner::DoScanL --->");
    return done;
    }
Beispiel #29
0
/* DatArchive::open
 * Reads wad format data from a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool DatArchive::open(MemChunk& mc)
{
	// Check data was given
	if (!mc.hasData())
		return false;

	const uint8_t* mcdata = mc.getData();

	// Read dat header
	mc.seek(0, SEEK_SET);
	uint16_t num_lumps;
	uint32_t dir_offset, unknown;
	mc.read(&num_lumps, 2);		// Size
	mc.read(&dir_offset, 4);	// Directory offset
	mc.read(&unknown, 4);		// Unknown value
	num_lumps	= wxINT16_SWAP_ON_BE(num_lumps);
	dir_offset	= wxINT32_SWAP_ON_BE(dir_offset);
	unknown		= wxINT32_SWAP_ON_BE(unknown);
	string lastname(wxString::FromAscii("-noname-"));
	size_t namecount = 0;

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	// Read the directory
	mc.seek(dir_offset, SEEK_SET);
	theSplashWindow->setProgressMessage("Reading dat archive data");
	for (uint32_t d = 0; d < num_lumps; d++)
	{
		// Update splash window progress
		theSplashWindow->setProgress(((float)d / (float)num_lumps));

		// Read lump info
		uint32_t offset = 0;
		uint32_t size = 0;
		uint16_t nameofs = 0;
		uint16_t flags = 0;

		mc.read(&offset,	4);		// Offset
		mc.read(&size,		4);		// Size
		mc.read(&nameofs,	2);		// Name offset
		mc.read(&flags,		2);		// Flags (only one: RLE encoded)

		// Byteswap values for big endian if needed
		offset = wxINT32_SWAP_ON_BE(offset);
		size = wxINT32_SWAP_ON_BE(size);
		nameofs = wxINT16_SWAP_ON_BE(nameofs);
		flags = wxINT16_SWAP_ON_BE(flags);

		// If the lump data goes past the directory,
		// the data file is invalid
		if (offset + size > mc.getSize())
		{
			wxLogMessage("DatArchive::open: Dat archive is invalid or corrupt at entry %i", d);
			Global::error = "Archive is invalid and/or corrupt";
			setMuted(false);
			return false;
		}

		string myname;
		if (nameofs != 0)
		{
			size_t len = 1;
			size_t start = nameofs+dir_offset;
			for (size_t i = start; mcdata[i] != 0; ++i) { ++len; }
			lastname = myname = wxString::FromAscii(mcdata+start, len);
			namecount = 0;
		}
		else
		{
			myname = S_FMT("%s+%d", lastname, ++namecount);
		}

		// Create & setup lump
		ArchiveEntry* nlump = new ArchiveEntry(myname, size);
		nlump->setLoaded(false);
		nlump->exProp("Offset") = (int)offset;
		nlump->setState(0);

		if (flags & 1) nlump->setEncryption(ENC_SCRLE0);

		// Check for markers
		if (!nlump->getName().Cmp("startflats"))
			flats[0] = d;
		if (!nlump->getName().Cmp("endflats"))
			flats[1] = d;
		if (!nlump->getName().Cmp("startsprites"))
			sprites[0] = d;
		if (!nlump->getName().Cmp("endmonsters"))
			sprites[1] = d;
		if (!nlump->getName().Cmp("startwalls"))
			walls[0] = d;
		if (!nlump->getName().Cmp("endwalls"))
			walls[1] = d;

		// Add to entry list
		getRoot()->addEntry(nlump);
	}

	// Detect all entry types
	MemChunk edata;
	theSplashWindow->setProgressMessage("Detecting entry types");
	for (size_t a = 0; a < numEntries(); a++)
	{
		// Update splash window progress
		theSplashWindow->setProgress((((float)a / (float)num_lumps)));

		// Get entry
		ArchiveEntry* entry = getEntry(a);

		// Read entry data if it isn't zero-sized
		if (entry->getSize() > 0)
		{
			// Read the entry data
			mc.exportMemChunk(edata, getEntryOffset(entry), entry->getSize());
			entry->importMemChunk(edata);
		}

		// Detect entry type
		EntryType::detectEntryType(entry);

		// Set entry to unchanged
		entry->setState(0);
	}

	// Detect maps (will detect map entry types)
	//theSplashWindow->setProgressMessage("Detecting maps");
	//detectMaps();

	// Setup variables
	setMuted(false);
	setModified(false);
	announce("opened");

	theSplashWindow->setProgressMessage("");

	return true;
}
Beispiel #30
0
/* HogArchive::open
 * Reads hog format data from a MemChunk
 * Returns true if successful, false otherwise
 *******************************************************************/
bool HogArchive::open(MemChunk& mc)
{
	// Check data was given
	if (!mc.hasData())
		return false;

	// Check size
	size_t archive_size = mc.getSize();
	if (archive_size < 3)
		return false;

	// Check magic header (DHF for "Descent Hog File")
	if (mc[0] != 'D' || mc[1] != 'H' || mc[2] != 'F')
		return false;

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	// Iterate through files to see if the size seems okay
	theSplashWindow->setProgressMessage("Reading hog archive data");
	size_t iter_offset = 3;
	uint32_t num_lumps = 0;
	while (iter_offset < archive_size)
	{
		// Update splash window progress
		theSplashWindow->setProgress(((float)iter_offset / (float)archive_size));

		// If the lump data goes past the end of the file,
		// the hogfile is invalid
		if (iter_offset + 17 > archive_size)
		{
			wxLogMessage("HogArchive::open: hog archive is invalid or corrupt");
			Global::error = "Archive is invalid and/or corrupt";
			setMuted(false);
			return false;
		}

		// Setup variables
		num_lumps++;
		size_t offset = iter_offset + 17;
		size_t size = READ_L32(mc, iter_offset + 13);
		char name[14] = "";
		mc.seek(iter_offset, SEEK_SET);
		mc.read(name, 13);
		name[13] = 0;

		// Create & setup lump
		ArchiveEntry* nlump = new ArchiveEntry(wxString::FromAscii(name), size);
		nlump->setLoaded(false);
		nlump->exProp("Offset") = (int)offset;
		nlump->setState(0);

		// Add to entry list
		getRoot()->addEntry(nlump);

		// Update entry size to compute next offset
		iter_offset = offset + size;
	}

	// Detect all entry types
	MemChunk edata;
	theSplashWindow->setProgressMessage("Detecting entry types");
	for (size_t a = 0; a < numEntries(); a++)
	{
		// Update splash window progress
		theSplashWindow->setProgress((((float)a / (float)num_lumps)));

		// Get entry
		ArchiveEntry* entry = getEntry(a);

		// Read entry data if it isn't zero-sized
		if (entry->getSize() > 0)
		{
			// Read the entry data
			mc.exportMemChunk(edata, getEntryOffset(entry), entry->getSize());
			entry->importMemChunk(edata);
		}

		// Detect entry type
		EntryType::detectEntryType(entry);

		// Unload entry data if needed
		if (!archive_load_data)
			entry->unloadData();

		// Set entry to unchanged
		entry->setState(0);
	}

	// Setup variables
	setMuted(false);
	setModified(false);
	announce("opened");

	theSplashWindow->setProgressMessage("");

	return true;
}