openclonk/src/c4group/C4ComponentHost.cpp

260 lines
7.4 KiB
C++
Raw Normal View History

2009-05-08 13:28:41 +00:00
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, 2004 Matthes Bender
* Copyright (c) 2002-2004 Peter Wortmann
* Copyright (c) 2005, 2007-2009 Günther Brammer
* Copyright (c) 2005, 2007 Sven Eberhardt
* Copyright (c) 2009 David Dormagen
* Copyright (c) 2010 Armin Burgmeier
2009-05-08 13:28:41 +00:00
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
/* Holds a single text file component from a group */
#include <C4Include.h>
#include <C4ComponentHost.h>
#include <C4Application.h>
#include <C4Language.h>
#include <StdRegistry.h>
C4ComponentHost::C4ComponentHost()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Default();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4ComponentHost::~C4ComponentHost()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Clear();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4ComponentHost::Default()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Data.Clear();
Name[0]=0;
Filename[0]=0;
FilePath[0]=0;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4ComponentHost::Clear()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Data.Clear();
OnLoad();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4ComponentHost::Load(const char *szName,
2010-03-28 18:58:01 +00:00
C4Group &hGroup,
const char *szFilename,
const char *szLanguage)
{
2009-05-08 13:28:41 +00:00
// Clear any old stuff
Clear();
// Store name & filename
SCopy(szName, Name);
SCopy(szFilename, Filename);
// Load component - try all segmented filenames
char strEntry[_MAX_FNAME+1], strEntryWithLanguage[_MAX_FNAME+1];
for (int iFilename = 0; SCopySegment(Filename, iFilename, strEntry, '|'); iFilename++)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Try to insert all language codes provided into the filename
char strCode[3] = "";
for (int iLang = 0; SCopySegment(szLanguage ? szLanguage : "", iLang, strCode, ',', 2); iLang++)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Insert language code
sprintf(strEntryWithLanguage, strEntry, strCode);
if (hGroup.LoadEntryString(strEntryWithLanguage, Data))
2010-03-28 18:58:01 +00:00
{
Data.EnsureUnicode();
// Skip those stupid "zero width no-break spaces" (also known as Byte Order Marks)
if (Data[0] == '\xEF' && Data[1] == '\xBB' && Data[2] == '\xBF')
2010-03-28 18:58:01 +00:00
{
Data.Move(3,Data.getSize()-3);
Data.Shrink(3);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Store actual filename
hGroup.FindEntry(strEntryWithLanguage, Filename);
CopyFilePathFromGroup(hGroup);
// Notify
OnLoad();
2009-05-08 13:28:41 +00:00
// Got it
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Couldn't insert language code anyway - no point in trying other languages
if (!SSearch(strEntry, "%s")) break;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Truncate any additional segments from stored filename
SReplaceChar(Filename, '|', 0);
CopyFilePathFromGroup(hGroup);
// Not loaded
return false;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4ComponentHost::Load(const char *szName,
2010-03-28 18:58:01 +00:00
C4GroupSet &hGroupSet,
const char *szFilename,
const char *szLanguage)
{
2009-05-08 13:28:41 +00:00
// Clear any old stuff
Clear();
// Store name & filename
SCopy(szName, Name);
SCopy(szFilename, Filename);
// Load component - try all segmented filenames
char strEntry[_MAX_FNAME+1], strEntryWithLanguage[_MAX_FNAME+1];
for (int iFilename = 0; SCopySegment(Filename, iFilename, strEntry, '|'); iFilename++)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Try to insert all language codes provided into the filename
char strCode[3] = "";
for (int iLang = 0; SCopySegment(szLanguage ? szLanguage : "", iLang, strCode, ',', 2); iLang++)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Insert language code
sprintf(strEntryWithLanguage, strEntry, strCode);
if (hGroupSet.LoadEntryString(strEntryWithLanguage, Data))
2010-03-28 18:58:01 +00:00
{
Data.EnsureUnicode();
2009-05-08 13:28:41 +00:00
// Store actual filename
C4Group *pGroup = hGroupSet.FindEntry(strEntryWithLanguage);
pGroup->FindEntry(strEntryWithLanguage, Filename);
CopyFilePathFromGroup(*pGroup);
// Notify
OnLoad();
2009-05-08 13:28:41 +00:00
// Got it
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Couldn't insert language code anyway - no point in trying other languages
if (!SSearch(strEntry, "%s")) break;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Truncate any additional segments from stored filename
SReplaceChar(Filename, '|', 0);
// skip full path (unknown)
FilePath[0] = 0;
2009-05-08 13:28:41 +00:00
// Not loaded
return false;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4ComponentHost::LoadEx(const char *szName,
2010-03-28 18:58:01 +00:00
C4Group &hGroup,
const char *szFilename,
const char *szLanguage)
2009-05-08 13:28:41 +00:00
{
// Load from a group set containing the provided group and
// alternative groups for cross-loading from a language pack
C4GroupSet hGroups;
hGroups.RegisterGroup(hGroup, false, 1000, C4GSCnt_Component); // Provided group gets highest priority
hGroups.RegisterGroups(Languages.GetPackGroups(pConfig->AtRelativePath(hGroup.GetFullName().getData())), C4GSCnt_Language);
// Load from group set
return Load(szName, hGroups, szFilename, szLanguage);
}
bool C4ComponentHost::LoadAppend(const char *szName,
2010-03-28 18:58:01 +00:00
C4Group &hGroup, const char *szFilename,
const char *szLanguage)
{
2009-05-08 13:28:41 +00:00
Clear();
// Store name & filename
SCopy(szName,Name);
SCopy(szFilename,Filename);
// Load component (segmented filename)
char str1[_MAX_FNAME+1],str2[_MAX_FNAME+1];
int iFileCnt = 0, iFileSizeSum = 0;
int cseg, clseg;
for (cseg=0; SCopySegment(Filename,cseg,str1,'|'); cseg++)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
char szLang[3] = "";
2010-03-28 18:58:01 +00:00
for (clseg=0; SCopySegment(szLanguage ? szLanguage : "", clseg, szLang, ',', 2); clseg++)
{
2009-05-08 13:28:41 +00:00
sprintf(str2,str1,szLang);
// Check existance
size_t iFileSize;
2010-03-28 18:58:01 +00:00
if (hGroup.FindEntry(str2, NULL, &iFileSize))
{
2009-05-08 13:28:41 +00:00
iFileCnt++;
iFileSizeSum += 1 + iFileSize;
break;
}
2010-03-28 18:58:01 +00:00
if (!SSearch(str1, "%s")) break;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// No matching files found?
2010-03-28 18:58:01 +00:00
if (!iFileCnt) return false;
2009-05-08 13:28:41 +00:00
// Allocate memory
Data.SetLength(iFileSizeSum);
// Search files to read contents
char *pPos = Data.getMData(); *pPos = 0;
for (cseg=0; SCopySegment(Filename,cseg,str1,'|'); cseg++)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
char szLang[3] = "";
2010-03-28 18:58:01 +00:00
for (clseg=0; SCopySegment(szLanguage ? szLanguage : "", clseg, szLang, ',', 2); clseg++)
{
2009-05-08 13:28:41 +00:00
sprintf(str2,str1,szLang);
// Load data
char *pTemp;
if (hGroup.LoadEntry(str2,&pTemp,NULL,1))
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
*pPos++ = '\n';
SCopy(pTemp, pPos, Data.getPtr(Data.getLength()) - pPos);
pPos += SLen(pPos);
delete[] pTemp;
break;
}
2010-03-28 18:58:01 +00:00
delete [] pTemp;
if (!SSearch(str1, "%s")) break;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
SReplaceChar(Filename,'|',0);
CopyFilePathFromGroup(hGroup);
OnLoad();
2009-05-08 13:28:41 +00:00
return !! iFileCnt;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Construct full path
void C4ComponentHost::CopyFilePathFromGroup(const C4Group &hGroup)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
SCopy(pConfig->AtRelativePath(hGroup.GetFullName().getData()), FilePath, _MAX_PATH - 1);
SAppendChar(DirectorySeparator, FilePath);
SAppend(Filename, FilePath, _MAX_PATH);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4ComponentHost::GetLanguageString(const char *szLanguage, StdStrBuf &rTarget)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
const char *cptr;
// No good parameters
if (!szLanguage || !Data) return false;
// Search for two-letter language identifier in text body, i.e. "DE:"
char langindex[4] = "";
2010-03-28 18:58:01 +00:00
for (int clseg=0; SCopySegment(szLanguage ? szLanguage : "", clseg, langindex, ',', 2); clseg++)
2009-05-08 13:28:41 +00:00
{
SAppend(":",langindex);
2010-01-25 04:00:59 +00:00
if ((cptr = SSearch(Data.getData(),langindex)))
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Return the according string
int iEndPos = SCharPos('\r', cptr);
if (iEndPos<0) iEndPos = SCharPos('\n', cptr);
if (iEndPos<0) iEndPos = strlen(cptr);
rTarget.Copy(cptr, iEndPos);
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
}
// Language string not found
return false;
2010-03-28 18:58:01 +00:00
}