2009-05-08 13:28:41 +00:00
|
|
|
/*
|
|
|
|
* OpenClonk, http://www.openclonk.org
|
|
|
|
*
|
2013-12-17 20:01:09 +00:00
|
|
|
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
|
|
|
|
* Copyright (c) 2009-2013, The OpenClonk Team and contributors
|
2009-05-08 13:28:41 +00:00
|
|
|
*
|
2013-12-17 20:01:09 +00:00
|
|
|
* Distributed under the terms of the ISC license; see accompanying file
|
|
|
|
* "COPYING" for details.
|
2009-05-08 13:28:41 +00:00
|
|
|
*
|
2013-12-17 20:01:09 +00:00
|
|
|
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
|
|
|
* See accompanying file "TRADEMARK" for details.
|
2009-05-08 13:28:41 +00:00
|
|
|
*
|
2013-12-17 20:01:09 +00:00
|
|
|
* To redistribute this file separately, substitute the full license texts
|
|
|
|
* for the above references.
|
2009-05-08 13:28:41 +00:00
|
|
|
*/
|
|
|
|
// Loads StringTbl* and replaces $..$-strings by localized versions
|
|
|
|
|
2011-03-14 15:32:01 +00:00
|
|
|
#include "C4Include.h"
|
|
|
|
|
2009-11-25 18:38:54 +00:00
|
|
|
#include <utility>
|
2009-10-25 23:09:34 +00:00
|
|
|
#include <vector>
|
2011-03-14 15:32:01 +00:00
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
#include "C4LangStringTable.h"
|
2009-08-13 23:46:32 +00:00
|
|
|
#include "C4InputValidation.h"
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2015-08-20 17:14:34 +00:00
|
|
|
C4LangStringTable::C4LangStringTable() : ref_count(1) {}
|
2009-11-12 15:57:37 +00:00
|
|
|
|
|
|
|
bool C4LangStringTable::HasTranslation(const std::string &text) const
|
|
|
|
{
|
|
|
|
if (strings.empty())
|
|
|
|
PopulateStringTable();
|
|
|
|
return strings.find(text) != strings.end();
|
|
|
|
}
|
|
|
|
|
2013-10-19 17:28:54 +00:00
|
|
|
const std::string &C4LangStringTable::Translate(const std::string &text) const
|
2009-11-12 15:57:37 +00:00
|
|
|
{
|
|
|
|
if (strings.empty())
|
|
|
|
PopulateStringTable();
|
|
|
|
Table::const_iterator it = strings.find(text);
|
|
|
|
if (it == strings.end())
|
2009-05-08 13:28:41 +00:00
|
|
|
{
|
2009-11-12 15:57:37 +00:00
|
|
|
throw NoSuchTranslation(text);
|
|
|
|
}
|
|
|
|
return it->second;
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2009-11-12 15:57:37 +00:00
|
|
|
void C4LangStringTable::PopulateStringTable() const
|
|
|
|
{
|
|
|
|
assert(strings.empty());
|
2010-03-28 18:58:01 +00:00
|
|
|
|
2009-11-12 15:57:37 +00:00
|
|
|
strings.clear();
|
|
|
|
std::string key, value;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2009-11-12 15:57:37 +00:00
|
|
|
// read table
|
|
|
|
const char *data = GetData();
|
|
|
|
if (!data || !*data)
|
|
|
|
return;
|
|
|
|
|
|
|
|
enum { PSTS_Key, PSTS_Val } state = PSTS_Key;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (state == PSTS_Key)
|
|
|
|
{
|
|
|
|
if (*data == '=')
|
|
|
|
{
|
|
|
|
state = PSTS_Val;
|
|
|
|
}
|
|
|
|
else if (*data == '\0' || *data == '\n' || *data == '\r')
|
|
|
|
{
|
2010-01-03 16:29:40 +00:00
|
|
|
if (!key.empty() && key[0]!='#')
|
2011-03-14 20:04:27 +00:00
|
|
|
LogF("%s: string table entry without a value: \"%s\"", GetFilePath() ? GetFilePath() : "<unknown>", key.c_str());
|
2009-11-12 15:57:37 +00:00
|
|
|
key.clear();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
key.push_back(*data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (*data == '\0' || *data == '\n' || *data == '\r')
|
|
|
|
{
|
|
|
|
strings.insert(std::make_pair(key, value));
|
|
|
|
key.clear(); value.clear();
|
|
|
|
state = PSTS_Key;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value.push_back(*data);
|
|
|
|
}
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
|
|
|
while (*data++);
|
2009-11-12 15:57:37 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2011-03-05 00:05:36 +00:00
|
|
|
void C4LangStringTable::ReplaceStrings(const StdStrBuf &rBuf, StdStrBuf &rTarget)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!rBuf.getLength())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// grab char ptr from buf
|
|
|
|
const char *Data = rBuf.getData();
|
|
|
|
|
|
|
|
// Find Replace Positions
|
|
|
|
int iScriptLen = SLen(Data);
|
2009-11-12 15:57:37 +00:00
|
|
|
struct RP { const char *Pos; std::string String; unsigned int Len; RP *Next; } *pRPList = NULL, *pRPListEnd = NULL;
|
2010-03-28 18:58:01 +00:00
|
|
|
for (const char *pPos = SSearch(Data, "$"); pPos; pPos = SSearch(pPos, "$"))
|
2009-05-08 13:28:41 +00:00
|
|
|
{
|
|
|
|
// Get name
|
|
|
|
char szStringName[C4MaxName + 1];
|
|
|
|
SCopyUntil(pPos, szStringName, '$', C4MaxName); pPos += SLen(szStringName) + 1;
|
2010-03-28 18:58:01 +00:00
|
|
|
if (*(pPos-1) != '$') continue;
|
2009-05-08 13:28:41 +00:00
|
|
|
// valid?
|
|
|
|
const char *pPos2 = szStringName;
|
|
|
|
while (*pPos2)
|
2010-03-28 18:58:01 +00:00
|
|
|
if (!IsIdentifier(*(pPos2++)))
|
2009-05-08 13:28:41 +00:00
|
|
|
break;
|
2010-03-28 18:58:01 +00:00
|
|
|
if (*pPos2) continue;
|
2009-05-08 13:28:41 +00:00
|
|
|
// check termination
|
2009-11-12 15:57:37 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
// search in string table
|
|
|
|
std::string pStrTblEntry = Translate(szStringName);
|
|
|
|
// add new replace-position entry
|
|
|
|
RP *pnRP = new RP;
|
|
|
|
pnRP->Pos = pPos - SLen(szStringName) - 2;
|
|
|
|
pnRP->String = pStrTblEntry;
|
|
|
|
pnRP->Len = SLen(szStringName) + 2;
|
|
|
|
pnRP->Next = NULL;
|
|
|
|
pRPListEnd = (pRPListEnd ? pRPListEnd->Next : pRPList) = pnRP;
|
|
|
|
// calculate new script length
|
|
|
|
iScriptLen += pStrTblEntry.size() - pnRP->Len;
|
|
|
|
}
|
|
|
|
catch (NoSuchTranslation &)
|
|
|
|
{
|
2011-03-14 20:04:27 +00:00
|
|
|
LogF("%s: string table entry not found: \"%s\"", GetFilePath() ? GetFilePath() : "<unknown>", szStringName);
|
2009-11-12 15:57:37 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
|
|
|
// Alloc new Buffer
|
|
|
|
char *pNewBuf;
|
|
|
|
StdStrBuf sNewBuf;
|
|
|
|
sNewBuf.SetLength(iScriptLen);
|
|
|
|
pNewBuf = sNewBuf.getMData();
|
|
|
|
// Copy data
|
|
|
|
const char *pRPos = Data; char *pWPos = pNewBuf;
|
2010-03-28 18:58:01 +00:00
|
|
|
for (RP *pRPPos = pRPList; pRPPos; pRPPos = pRPPos->Next)
|
2009-05-08 13:28:41 +00:00
|
|
|
{
|
|
|
|
// copy preceding string data
|
|
|
|
SCopy(pRPos, pWPos, pRPPos->Pos - pRPos);
|
|
|
|
pWPos += pRPPos->Pos - pRPos;
|
|
|
|
// copy string
|
2009-11-12 15:57:37 +00:00
|
|
|
SCopyUntil(pRPPos->String.c_str(), pWPos, '\n');
|
2009-05-08 13:28:41 +00:00
|
|
|
SReplaceChar(pWPos, '\r', '\0');
|
|
|
|
// advance
|
|
|
|
pRPos = pRPPos->Pos + pRPPos->Len;
|
|
|
|
pWPos += SLen(pWPos);
|
|
|
|
}
|
|
|
|
SCopy(pRPos, pWPos);
|
|
|
|
|
2010-03-28 18:58:01 +00:00
|
|
|
while (pRPList)
|
2009-05-08 13:28:41 +00:00
|
|
|
{
|
|
|
|
RP *pRP = pRPList;
|
|
|
|
pRPList = pRP->Next;
|
|
|
|
delete pRP;
|
|
|
|
}
|
|
|
|
|
|
|
|
// assign this buf
|
|
|
|
rTarget.Clear();
|
2009-11-25 18:38:54 +00:00
|
|
|
rTarget.Take(std::move(sNewBuf));
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4LangStringTable::ReplaceStrings(StdStrBuf &rBuf)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2011-03-05 00:05:36 +00:00
|
|
|
ReplaceStrings(rBuf, rBuf);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2013-10-29 20:36:38 +00:00
|
|
|
|
|
|
|
C4LangStringTable C4LangStringTable::system_string_table;
|