Cell names localization fix

actorid
lazydev 12 years ago
parent 1cf019a007
commit 74ae479780

@ -59,7 +59,7 @@ struct Arguments
std::string outname; std::string outname;
std::vector<std::string> types; std::vector<std::string> types;
ESMData data; ESMData data;
ESM::ESMReader reader; ESM::ESMReader reader;
ESM::ESMWriter writer; ESM::ESMWriter writer;
@ -74,7 +74,7 @@ bool parseOptions (int argc, char** argv, Arguments &info)
("version,v", "print version information and quit.") ("version,v", "print version information and quit.")
("raw,r", "Show an unformatted list of all records and subrecords.") ("raw,r", "Show an unformatted list of all records and subrecords.")
// The intention is that this option would interact better // The intention is that this option would interact better
// with other modes including clone, dump, and raw. // with other modes including clone, dump, and raw.
("type,t", bpo::value< std::vector<std::string> >(), ("type,t", bpo::value< std::vector<std::string> >(),
"Show only records of this type (four character record code). May " "Show only records of this type (four character record code). May "
"be specified multiple times. Only affects dump mode.") "be specified multiple times. Only affects dump mode.")
@ -262,7 +262,7 @@ void printRaw(ESM::ESMReader &esm)
int load(Arguments& info) int load(Arguments& info)
{ {
ESM::ESMReader& esm = info.reader; ESM::ESMReader& esm = info.reader;
esm.setEncoding(info.encoding); esm.setEncoding(ToUTF8::CalculateEncoding(info.encoding));
std::string filename = info.filename; std::string filename = info.filename;
std::cout << "Loading file: " << filename << std::endl; std::cout << "Loading file: " << filename << std::endl;
@ -321,7 +321,7 @@ int load(Arguments& info)
if (info.types.size() > 0) if (info.types.size() > 0)
{ {
std::vector<std::string>::iterator match; std::vector<std::string>::iterator match;
match = std::find(info.types.begin(), info.types.end(), match = std::find(info.types.begin(), info.types.end(),
n.toString()); n.toString());
if (match == info.types.end()) interested = false; if (match == info.types.end()) interested = false;
} }
@ -425,7 +425,7 @@ int clone(Arguments& info)
if (++i % 3 == 0) if (++i % 3 == 0)
std::cout << std::endl; std::cout << std::endl;
} }
if (i % 3 != 0) if (i % 3 != 0)
std::cout << std::endl; std::cout << std::endl;
@ -450,7 +450,7 @@ int clone(Arguments& info)
for (Records::iterator it = records.begin(); it != records.end() && i > 0; ++it) for (Records::iterator it = records.begin(); it != records.end() && i > 0; ++it)
{ {
EsmTool::RecordBase *record = *it; EsmTool::RecordBase *record = *it;
name.val = record->getType().val; name.val = record->getType().val;
esm.startRecord(name.toString(), record->getFlags()); esm.startRecord(name.toString(), record->getFlags());
@ -485,7 +485,7 @@ int clone(Arguments& info)
std::cerr << "\r" << perc << "%"; std::cerr << "\r" << perc << "%";
} }
} }
std::cout << "\rDone!" << std::endl; std::cout << "\rDone!" << std::endl;
esm.close(); esm.close();
@ -513,7 +513,7 @@ int comp(Arguments& info)
fileOne.encoding = info.encoding; fileOne.encoding = info.encoding;
fileTwo.encoding = info.encoding; fileTwo.encoding = info.encoding;
fileOne.filename = info.filename; fileOne.filename = info.filename;
fileTwo.filename = info.outname; fileTwo.filename = info.outname;
@ -534,9 +534,9 @@ int comp(Arguments& info)
std::cout << "Not equal, different amount of records." << std::endl; std::cout << "Not equal, different amount of records." << std::endl;
return 1; return 1;
} }
return 0; return 0;
} }

@ -272,7 +272,7 @@ void DataFilesModel::addMasters(const QString &path)
foreach (const QString &path, dir.entryList()) { foreach (const QString &path, dir.entryList()) {
try { try {
ESM::ESMReader fileReader; ESM::ESMReader fileReader;
fileReader.setEncoding(mEncoding.toStdString()); fileReader.setEncoding(ToUTF8::CalculateEncoding(mEncoding.toStdString()));
fileReader.open(dir.absoluteFilePath(path).toStdString()); fileReader.open(dir.absoluteFilePath(path).toStdString());
ESM::ESMReader::MasterList mlist = fileReader.getMasters(); ESM::ESMReader::MasterList mlist = fileReader.getMasters();
@ -335,7 +335,7 @@ void DataFilesModel::addPlugins(const QString &path)
try { try {
ESM::ESMReader fileReader; ESM::ESMReader fileReader;
fileReader.setEncoding(mEncoding.toStdString()); fileReader.setEncoding(ToUTF8::CalculateEncoding(mEncoding.toStdString()));
fileReader.open(dir.absoluteFilePath(path).toStdString()); fileReader.open(dir.absoluteFilePath(path).toStdString());
ESM::ESMReader::MasterList mlist = fileReader.getMasters(); ESM::ESMReader::MasterList mlist = fileReader.getMasters();

@ -8,6 +8,7 @@
#include <components/bsa/bsa_archive.hpp> #include <components/bsa/bsa_archive.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/translation_data/translation_data.hpp>
#include <components/nifoverrides/nifoverrides.hpp> #include <components/nifoverrides/nifoverrides.hpp>
#include <components/nifbullet/bullet_nif_loader.hpp> #include <components/nifbullet/bullet_nif_loader.hpp>
@ -334,12 +335,16 @@ void OMW::Engine::go()
mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster,
mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoding, mFallbackMap)); mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoding, mFallbackMap));
//Load translation data
std::unique_ptr<TranslationData::Storage> translationDataStorage(new TranslationData::Storage(mEncoding));
translationDataStorage->loadTranslationData(mFileCollections, mMaster);
// Create window manager - this manages all the MW-specific GUI windows // Create window manager - this manages all the MW-specific GUI windows
MWScript::registerExtensions (mExtensions); MWScript::registerExtensions (mExtensions);
mEnvironment.setWindowManager (new MWGui::WindowManager( mEnvironment.setWindowManager (new MWGui::WindowManager(
mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"), mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
mCfgMgr.getCachePath ().string(), mScriptConsoleMode)); mCfgMgr.getCachePath ().string(), mScriptConsoleMode, translationDataStorage.release()));
// Create sound system // Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound));
@ -487,7 +492,7 @@ void OMW::Engine::showFPS(int level)
mFpsLevel = level; mFpsLevel = level;
} }
void OMW::Engine::setEncoding(const std::string& encoding) void OMW::Engine::setEncoding(const ToUTF8::FromType& encoding)
{ {
mEncoding = encoding; mEncoding = encoding;
} }

@ -59,7 +59,7 @@ namespace OMW
class Engine : private Ogre::FrameListener class Engine : private Ogre::FrameListener
{ {
MWBase::Environment mEnvironment; MWBase::Environment mEnvironment;
std::string mEncoding; ToUTF8::FromType mEncoding;
Files::PathContainer mDataDirs; Files::PathContainer mDataDirs;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
OEngine::Render::OgreRenderer *mOgre; OEngine::Render::OgreRenderer *mOgre;
@ -154,7 +154,7 @@ namespace OMW
void setCompileAll (bool all); void setCompileAll (bool all);
/// Font encoding /// Font encoding
void setEncoding(const std::string& encoding); void setEncoding(const ToUTF8::FromType& encoding);
void setAnimationVerbose(bool animverbose); void setAnimationVerbose(bool animverbose);

@ -181,21 +181,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
// Font encoding settings // Font encoding settings
std::string encoding(variables["encoding"].as<std::string>()); std::string encoding(variables["encoding"].as<std::string>());
if (encoding == "win1250") std::cout << ToUTF8::EncodingUsingMessage(encoding) << std::endl;
{ engine.setEncoding(ToUTF8::CalculateEncoding(encoding));
std::cout << "Using Central and Eastern European font encoding." << std::endl;
engine.setEncoding(encoding);
}
else if (encoding == "win1251")
{
std::cout << "Using Cyrillic font encoding." << std::endl;
engine.setEncoding(encoding);
}
else
{
std::cout << "Using default (English) font encoding." << std::endl;
engine.setEncoding("win1252");
}
// directory settings // directory settings
engine.enableFSStrict(variables["fs-strict"].as<bool>()); engine.enableFSStrict(variables["fs-strict"].as<bool>());

@ -204,33 +204,10 @@ namespace MWClass
std::string text; std::string text;
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
if (ref->mRef.mTeleport) if (ref->mRef.mTeleport)
{ {
std::string dest;
if (ref->mRef.mDestCell != "")
{
// door leads to an interior, use interior name as tooltip
dest = ref->mRef.mDestCell;
}
else
{
// door leads to exterior, use cell name (if any), otherwise translated region name
int x,y;
MWBase::Environment::get().getWorld()->positionToIndex (ref->mRef.mDoorDest.pos[0], ref->mRef.mDoorDest.pos[1], x, y);
const ESM::Cell* cell = store.get<ESM::Cell>().find(x,y);
if (cell->mName != "")
dest = cell->mName;
else
{
const ESM::Region* region =
store.get<ESM::Region>().find(cell->mRegion);
dest = region->mName;
}
}
text += "\n#{sTo}"; text += "\n#{sTo}";
text += "\n"+dest; text += "\n" + getDestination(*ref);
} }
if (ref->mRef.mLockLevel > 0) if (ref->mRef.mLockLevel > 0)
@ -246,6 +223,37 @@ namespace MWClass
return info; return info;
} }
std::string Door::getDestination (const MWWorld::LiveCellRef<ESM::Door>& door)
{
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
std::string dest;
if (door.mRef.mDestCell != "")
{
// door leads to an interior, use interior name as tooltip
dest = door.mRef.mDestCell;
}
else
{
// door leads to exterior, use cell name (if any), otherwise translated region name
int x,y;
MWBase::Environment::get().getWorld()->positionToIndex (door.mRef.mDoorDest.pos[0], door.mRef.mDoorDest.pos[1], x, y);
const ESM::Cell* cell = store.get<ESM::Cell>().find(x,y);
if (cell->mName != "")
dest = cell->mName;
else
{
const ESM::Region* region =
store.get<ESM::Region>().find(cell->mRegion);
//name as is, not a token
return region->mName;
}
}
return "#{sCell=" + dest + "}";
}
MWWorld::Ptr MWWorld::Ptr
Door::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const Door::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{ {

@ -31,6 +31,9 @@ namespace MWClass
virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const;
///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
static std::string getDestination (const MWWorld::LiveCellRef<ESM::Door>& door);
///< @return destination cell name or token
virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const; virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const;
///< Lock object ///< Lock object

@ -319,7 +319,7 @@ void HUD::setCellName(const std::string& cellName)
mCellNameTimer = 5.0f; mCellNameTimer = 5.0f;
mCellName = cellName; mCellName = cellName;
mCellNameBox->setCaption(mCellName); mCellNameBox->setCaptionWithReplacing("#{sCell=" + mCellName + "}");
mCellNameBox->setVisible(mMapVisible); mCellNameBox->setVisible(mMapVisible);
} }
} }

@ -299,7 +299,7 @@ MapWindow::~MapWindow()
void MapWindow::setCellName(const std::string& cellName) void MapWindow::setCellName(const std::string& cellName)
{ {
setTitle(cellName); setTitle("#{sCell=" + cellName + "}");
} }
void MapWindow::addVisitedLocation(const std::string& name, int x, int y) void MapWindow::addVisitedLocation(const std::string& name, int x, int y)

@ -55,7 +55,8 @@ using namespace MWGui;
WindowManager::WindowManager( WindowManager::WindowManager(
const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre,
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts) const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts,
TranslationData::Storage* pTranslationDataStorage)
: mGuiManager(NULL) : mGuiManager(NULL)
, mHud(NULL) , mHud(NULL)
, mMap(NULL) , mMap(NULL)
@ -104,6 +105,7 @@ WindowManager::WindowManager(
, mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD"))
, mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI"))
, mHudEnabled(true) , mHudEnabled(true)
, mTranslationDataStorage(pTranslationDataStorage)
{ {
// Set up the GUI system // Set up the GUI system
@ -612,7 +614,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
if (cell->mCell->mName != "") if (cell->mCell->mName != "")
{ {
name = cell->mCell->mName; name = cell->mCell->mName;
mMap->addVisitedLocation (name, cell->mCell->getGridX (), cell->mCell->getGridY ()); mMap->addVisitedLocation ("#{sCell=" + name + "}", cell->mCell->getGridX (), cell->mCell->getGridY ());
} }
else else
{ {
@ -722,13 +724,25 @@ void WindowManager::setDragDrop(bool dragDrop)
void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result) void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result)
{ {
const ESM::GameSetting *setting = std::string tag(_tag);
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(_tag);
if (setting && setting->mType == ESM::VT_String) std::string tokenToFind = "sCell=";
_result = setting->getString(); size_t tokenLength = tokenToFind.length();
if (tag.substr(0, tokenLength) == tokenToFind)
{
_result = mTranslationDataStorage->translateCellName(tag.substr(tokenLength));
}
else else
_result = _tag; {
const ESM::GameSetting *setting =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(tag);
if (setting && setting->mType == ESM::VT_String)
_result = setting->getString();
else
_result = tag;
}
} }
void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed)

@ -14,6 +14,7 @@
#include <string> #include <string>
#include <components/esm/loadclas.hpp> #include <components/esm/loadclas.hpp>
#include <components/translation_data/translation_data.hpp>
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
@ -76,7 +77,8 @@ namespace MWGui
WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame,
OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath,
const std::string& cacheDir, bool consoleOnlyScripts); const std::string& cacheDir, bool consoleOnlyScripts,
TranslationData::Storage* pTranslationDataStorage);
virtual ~WindowManager(); virtual ~WindowManager();
/** /**
@ -250,6 +252,7 @@ namespace MWGui
SpellCreationDialog* mSpellCreationDialog; SpellCreationDialog* mSpellCreationDialog;
EnchantingDialog* mEnchantingDialog; EnchantingDialog* mEnchantingDialog;
TrainingWindow* mTrainingWindow; TrainingWindow* mTrainingWindow;
std::unique_ptr<TranslationData::Storage> mTranslationDataStorage;
CharacterCreation* mCharGen; CharacterCreation* mCharGen;

@ -6,7 +6,7 @@
#include <components/esm/records.hpp> #include <components/esm/records.hpp>
#include "store.hpp" #include "store.hpp"
namespace MWWorld namespace MWWorld
{ {
class ESMStore class ESMStore
{ {
@ -158,7 +158,7 @@ namespace MWWorld
std::ostringstream id; std::ostringstream id;
id << "$dynamic" << mDynamicCount++; id << "$dynamic" << mDynamicCount++;
record.mId = id.str(); record.mId = id.str();
T *ptr = store.insert(record); T *ptr = store.insert(record);
for (iterator it = mStores.begin(); it != mStores.end(); ++it) { for (iterator it = mStores.begin(); it != mStores.end(); ++it) {
if (it->second == &store) { if (it->second == &store) {
@ -179,7 +179,7 @@ namespace MWWorld
template <> template <>
inline const ESM::NPC *ESMStore::insert<ESM::NPC>(const ESM::NPC &npc) { inline const ESM::NPC *ESMStore::insert<ESM::NPC>(const ESM::NPC &npc) {
if (StringUtils::ciEqual(npc.mId, "player")) { if (Misc::StringUtils::ciEqual(npc.mId, "player")) {
return mNpcs.insert(npc); return mNpcs.insert(npc);
} else if (mNpcs.search(npc.mId) != 0) { } else if (mNpcs.search(npc.mId) != 0) {
std::ostringstream msg; std::ostringstream msg;
@ -191,7 +191,7 @@ namespace MWWorld
std::ostringstream id; std::ostringstream id;
id << "$dynamic" << mDynamicCount++; id << "$dynamic" << mDynamicCount++;
record.mId = id.str(); record.mId = id.str();
ESM::NPC *ptr = mNpcs.insert(record); ESM::NPC *ptr = mNpcs.insert(record);
mIds[ptr->mId] = ESM::REC_NPC_; mIds[ptr->mId] = ESM::REC_NPC_;
return ptr; return ptr;

@ -1,62 +1,12 @@
#ifndef OPENMW_MWWORLD_RECORDCMP_H #ifndef OPENMW_MWWORLD_RECORDCMP_H
#define OPENMW_MWWORLD_RECORDCMP_H #define OPENMW_MWWORLD_RECORDCMP_H
#include <string>
#include <cctype> #include <cctype>
#include <algorithm>
#include <components/esm/records.hpp> #include <components/esm/records.hpp>
namespace MWWorld namespace MWWorld
{ {
/// \todo move this to another location
class StringUtils
{
struct ci
{
bool operator()(int x, int y) const {
return std::tolower(x) < std::tolower(y);
}
};
public:
static bool ciLess(const std::string &x, const std::string &y) {
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci());
}
static bool ciEqual(const std::string &x, const std::string &y) {
if (x.size() != y.size()) {
return false;
}
std::string::const_iterator xit = x.begin();
std::string::const_iterator yit = y.begin();
for (; xit != x.end(); ++xit, ++yit) {
if (std::tolower(*xit) != std::tolower(*yit)) {
return false;
}
}
return true;
}
/// Transforms input string to lower case w/o copy
static std::string &toLower(std::string &inout) {
std::transform(
inout.begin(),
inout.end(),
inout.begin(),
(int (*)(int)) std::tolower
);
return inout;
}
/// Returns lower case copy of input string
static std::string lowerCase(const std::string &in)
{
std::string out = in;
return toLower(out);
}
};
struct RecordCmp struct RecordCmp
{ {
template <class T> template <class T>
@ -67,17 +17,17 @@ namespace MWWorld
template <> template <>
inline bool RecordCmp::operator()<ESM::Dialogue>(const ESM::Dialogue &x, const ESM::Dialogue &y) const { inline bool RecordCmp::operator()<ESM::Dialogue>(const ESM::Dialogue &x, const ESM::Dialogue &y) const {
return StringUtils::ciLess(x.mId, y.mId); return Misc::StringUtils::ciLess(x.mId, y.mId);
} }
template <> template <>
inline bool RecordCmp::operator()<ESM::Cell>(const ESM::Cell &x, const ESM::Cell &y) const { inline bool RecordCmp::operator()<ESM::Cell>(const ESM::Cell &x, const ESM::Cell &y) const {
return StringUtils::ciLess(x.mName, y.mName); return Misc::StringUtils::ciLess(x.mName, y.mName);
} }
template <> template <>
inline bool RecordCmp::operator()<ESM::Pathgrid>(const ESM::Pathgrid &x, const ESM::Pathgrid &y) const { inline bool RecordCmp::operator()<ESM::Pathgrid>(const ESM::Pathgrid &x, const ESM::Pathgrid &y) const {
return StringUtils::ciLess(x.mCell, y.mCell); return Misc::StringUtils::ciLess(x.mCell, y.mCell);
} }
} // end namespace } // end namespace

@ -105,12 +105,12 @@ namespace MWWorld
const T *search(const std::string &id) const { const T *search(const std::string &id) const {
T item; T item;
item.mId = StringUtils::lowerCase(id); item.mId = Misc::StringUtils::lowerCase(id);
typename std::vector<T>::const_iterator it = typename std::vector<T>::const_iterator it =
std::lower_bound(mStatic.begin(), mStatic.end(), item, RecordCmp()); std::lower_bound(mStatic.begin(), mStatic.end(), item, RecordCmp());
if (it != mStatic.end() && StringUtils::ciEqual(it->mId, id)) { if (it != mStatic.end() && Misc::StringUtils::ciEqual(it->mId, id)) {
return &(*it); return &(*it);
} }
@ -134,7 +134,7 @@ namespace MWWorld
void load(ESM::ESMReader &esm, const std::string &id) { void load(ESM::ESMReader &esm, const std::string &id) {
mStatic.push_back(T()); mStatic.push_back(T());
mStatic.back().mId = StringUtils::lowerCase(id); mStatic.back().mId = Misc::StringUtils::lowerCase(id);
mStatic.back().load(esm); mStatic.back().load(esm);
} }
@ -169,7 +169,7 @@ namespace MWWorld
} }
T *insert(const T &item) { T *insert(const T &item) {
std::string id = StringUtils::lowerCase(item.mId); std::string id = Misc::StringUtils::lowerCase(item.mId);
std::pair<typename Dynamic::iterator, bool> result = std::pair<typename Dynamic::iterator, bool> result =
mDynamic.insert(std::pair<std::string, T>(id, item)); mDynamic.insert(std::pair<std::string, T>(id, item));
T *ptr = &result.first->second; T *ptr = &result.first->second;
@ -182,7 +182,7 @@ namespace MWWorld
} }
bool erase(const std::string &id) { bool erase(const std::string &id) {
std::string key = StringUtils::lowerCase(id); std::string key = Misc::StringUtils::lowerCase(id);
typename Dynamic::iterator it = mDynamic.find(key); typename Dynamic::iterator it = mDynamic.find(key);
if (it == mDynamic.end()) { if (it == mDynamic.end()) {
return false; return false;
@ -213,7 +213,7 @@ namespace MWWorld
inline void Store<ESM::Script>::load(ESM::ESMReader &esm, const std::string &id) { inline void Store<ESM::Script>::load(ESM::ESMReader &esm, const std::string &id) {
mStatic.push_back(ESM::Script()); mStatic.push_back(ESM::Script());
mStatic.back().load(esm); mStatic.back().load(esm);
StringUtils::toLower(mStatic.back().mId); Misc::StringUtils::toLower(mStatic.back().mId);
} }
template <> template <>
@ -385,12 +385,12 @@ namespace MWWorld
const ESM::Cell *search(const std::string &id) const { const ESM::Cell *search(const std::string &id) const {
ESM::Cell cell; ESM::Cell cell;
cell.mName = StringUtils::lowerCase(id); cell.mName = Misc::StringUtils::lowerCase(id);
std::vector<ESM::Cell>::const_iterator it = std::vector<ESM::Cell>::const_iterator it =
std::lower_bound(mInt.begin(), mInt.end(), cell, RecordCmp()); std::lower_bound(mInt.begin(), mInt.end(), cell, RecordCmp());
if (it != mInt.end() && StringUtils::ciEqual(it->mName, id)) { if (it != mInt.end() && Misc::StringUtils::ciEqual(it->mName, id)) {
return &(*it); return &(*it);
} }
@ -490,7 +490,7 @@ namespace MWWorld
const ESM::Cell *searchExtByName(const std::string &id) const { const ESM::Cell *searchExtByName(const std::string &id) const {
std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin(); std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin();
for (; it != mSharedExt.end(); ++it) { for (; it != mSharedExt.end(); ++it) {
if (StringUtils::ciEqual((*it)->mName, id)) { if (Misc::StringUtils::ciEqual((*it)->mName, id)) {
return *it; return *it;
} }
} }
@ -501,7 +501,7 @@ namespace MWWorld
const ESM::Cell *searchExtByRegion(const std::string &id) const { const ESM::Cell *searchExtByRegion(const std::string &id) const {
std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin(); std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin();
for (; it != mSharedExt.end(); ++it) { for (; it != mSharedExt.end(); ++it) {
if (StringUtils::ciEqual((*it)->mRegion, id)) { if (Misc::StringUtils::ciEqual((*it)->mRegion, id)) {
return *it; return *it;
} }
} }
@ -541,7 +541,7 @@ namespace MWWorld
ptr = &result.first->second; ptr = &result.first->second;
mSharedExt.push_back(ptr); mSharedExt.push_back(ptr);
} else { } else {
std::string key = StringUtils::lowerCase(cell.mName); std::string key = Misc::StringUtils::lowerCase(cell.mName);
// duplicate insertions are avoided by search(ESM::Cell &) // duplicate insertions are avoided by search(ESM::Cell &)
std::pair<DynamicInt::iterator, bool> result = std::pair<DynamicInt::iterator, bool> result =
@ -561,7 +561,7 @@ namespace MWWorld
} }
bool erase(const std::string &id) { bool erase(const std::string &id) {
std::string key = StringUtils::lowerCase(id); std::string key = Misc::StringUtils::lowerCase(id);
DynamicInt::iterator it = mDynamicInt.find(key); DynamicInt::iterator it = mDynamicInt.find(key);
if (it == mDynamicInt.end()) { if (it == mDynamicInt.end()) {
@ -691,7 +691,7 @@ namespace MWWorld
pg.mCell = name; pg.mCell = name;
iterator it = std::lower_bound(mIntBegin, mIntEnd, pg, RecordCmp()); iterator it = std::lower_bound(mIntBegin, mIntEnd, pg, RecordCmp());
if (it != mIntEnd && StringUtils::ciEqual(it->mCell, name)) { if (it != mIntEnd && Misc::StringUtils::ciEqual(it->mCell, name)) {
return &(*it); return &(*it);
} }
return 0; return 0;

@ -11,6 +11,8 @@
#include "../mwrender/sky.hpp" #include "../mwrender/sky.hpp"
#include "../mwrender/player.hpp" #include "../mwrender/player.hpp"
#include "../mwclass/door.hpp"
#include "player.hpp" #include "player.hpp"
#include "manualref.hpp" #include "manualref.hpp"
#include "cellfunctors.hpp" #include "cellfunctors.hpp"
@ -168,7 +170,7 @@ namespace MWWorld
World::World (OEngine::Render::OgreRenderer& renderer, World::World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame,
const std::string& encoding, std::map<std::string,std::string> fallbackMap) const ToUTF8::FromType& encoding, std::map<std::string,std::string> fallbackMap)
: mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
mSky (true), mCells (mStore, mEsm), mSky (true), mCells (mStore, mEsm),
mNumFacing(0) mNumFacing(0)
@ -237,7 +239,7 @@ namespace MWWorld
MWWorld::Store<ESM::Region>::iterator it = regions.begin(); MWWorld::Store<ESM::Region>::iterator it = regions.begin();
for (; it != regions.end(); ++it) for (; it != regions.end(); ++it)
{ {
if (MWWorld::StringUtils::ciEqual(cellName, it->mName)) if (Misc::StringUtils::ciEqual(cellName, it->mName))
{ {
return mStore.get<ESM::Cell>().searchExtByRegion(it->mId); return mStore.get<ESM::Cell>().searchExtByRegion(it->mId);
} }
@ -805,7 +807,7 @@ namespace MWWorld
{ {
bool update = false; bool update = false;
if (StringUtils::ciEqual(record.mId, "player")) if (Misc::StringUtils::ciEqual(record.mId, "player"))
{ {
static const char *sRaces[] = static const char *sRaces[] =
{ {
@ -816,7 +818,7 @@ namespace MWWorld
int i=0; int i=0;
for (; sRaces[i]; ++i) for (; sRaces[i]; ++i)
if (StringUtils::ciEqual (sRaces[i], record.mRace)) if (Misc::StringUtils::ciEqual (sRaces[i], record.mRace))
break; break;
mGlobalVariables->setInt ("pcrace", sRaces[i] ? i+1 : 0); mGlobalVariables->setInt ("pcrace", sRaces[i] ? i+1 : 0);
@ -825,9 +827,9 @@ namespace MWWorld
mPlayer->getPlayer().get<ESM::NPC>()->mBase; mPlayer->getPlayer().get<ESM::NPC>()->mBase;
update = record.isMale() != player->isMale() || update = record.isMale() != player->isMale() ||
!StringUtils::ciEqual(record.mRace, player->mRace) || !Misc::StringUtils::ciEqual(record.mRace, player->mRace) ||
!StringUtils::ciEqual(record.mHead, player->mHead) || !Misc::StringUtils::ciEqual(record.mHead, player->mHead) ||
!StringUtils::ciEqual(record.mHair, player->mHair); !Misc::StringUtils::ciEqual(record.mHair, player->mHair);
} }
const ESM::NPC *ret = mStore.insert(record); const ESM::NPC *ret = mStore.insert(record);
if (update) { if (update) {
@ -1080,28 +1082,7 @@ namespace MWWorld
if (ref.mRef.mTeleport) if (ref.mRef.mTeleport)
{ {
World::DoorMarker newMarker; World::DoorMarker newMarker;
newMarker.name = MWClass::Door::getDestination(ref);
std::string dest;
if (ref.mRef.mDestCell != "")
{
// door leads to an interior, use interior name
dest = ref.mRef.mDestCell;
}
else
{
// door leads to exterior, use cell name (if any), otherwise translated region name
int x,y;
positionToIndex (ref.mRef.mDoorDest.pos[0], ref.mRef.mDoorDest.pos[1], x, y);
const ESM::Cell* cell = mStore.get<ESM::Cell>().find(x,y);
if (cell->mName != "")
dest = cell->mName;
else
{
dest = mStore.get<ESM::Region>().find(cell->mRegion)->mName;
}
}
newMarker.name = dest;
ESM::Position pos = ref.mData.getPosition (); ESM::Position pos = ref.mData.getPosition ();

@ -95,7 +95,7 @@ namespace MWWorld
World (OEngine::Render::OgreRenderer& renderer, World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame,
const std::string& encoding, std::map<std::string,std::string> fallbackMap); const ToUTF8::FromType& encoding, std::map<std::string,std::string> fallbackMap);
virtual ~World(); virtual ~World();
@ -228,7 +228,7 @@ namespace MWWorld
virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false); virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false);
virtual void safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos); virtual void safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos);
///< place an object in a "safe" location (ie not in the void, etc). Makes a copy of the Ptr. ///< place an object in a "safe" location (ie not in the void, etc). Makes a copy of the Ptr.
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
const; const;
@ -323,7 +323,7 @@ namespace MWWorld
} }
virtual void renderPlayer(); virtual void renderPlayer();
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);
virtual int canRest(); virtual int canRest();

@ -62,6 +62,10 @@ add_component_dir (interpreter
miscopcodes opcodes runtime scriptopcodes spatialopcodes types miscopcodes opcodes runtime scriptopcodes spatialopcodes types
) )
add_component_dir (translation_data
translation_data
)
include_directories(${BULLET_INCLUDE_DIRS}) include_directories(${BULLET_INCLUDE_DIRS})
add_library(components STATIC ${COMPONENT_FILES}) add_library(components STATIC ${COMPONENT_FILES})

@ -347,21 +347,9 @@ void ESMReader::fail(const std::string &msg)
throw std::runtime_error(ss.str()); throw std::runtime_error(ss.str());
} }
void ESMReader::setEncoding(const std::string& encoding) void ESMReader::setEncoding(const ToUTF8::FromType& encoding)
{ {
if (encoding == "win1250") mEncoding = encoding;
{
mEncoding = ToUTF8::WINDOWS_1250;
}
else if (encoding == "win1251")
{
mEncoding = ToUTF8::WINDOWS_1251;
}
else
{
// Default Latin encoding
mEncoding = ToUTF8::WINDOWS_1252;
}
} }
} }

@ -234,7 +234,7 @@ public:
void fail(const std::string &msg); void fail(const std::string &msg);
/// Sets font encoding for ESM strings /// Sets font encoding for ESM strings
void setEncoding(const std::string& encoding); void setEncoding(const ToUTF8::FromType& encoding);
private: private:
Ogre::DataStreamPtr mEsm; Ogre::DataStreamPtr mEsm;

@ -1,8 +1,58 @@
#ifndef MISC_STRINGOPS_H #ifndef MISC_STRINGOPS_H
#define MISC_STRINGOPS_H #define MISC_STRINGOPS_H
#include <string>
#include <algorithm>
namespace Misc namespace Misc
{ {
class StringUtils
{
struct ci
{
bool operator()(int x, int y) const {
return std::tolower(x) < std::tolower(y);
}
};
public:
static bool ciLess(const std::string &x, const std::string &y) {
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci());
}
static bool ciEqual(const std::string &x, const std::string &y) {
if (x.size() != y.size()) {
return false;
}
std::string::const_iterator xit = x.begin();
std::string::const_iterator yit = y.begin();
for (; xit != x.end(); ++xit, ++yit) {
if (std::tolower(*xit) != std::tolower(*yit)) {
return false;
}
}
return true;
}
/// Transforms input string to lower case w/o copy
static std::string &toLower(std::string &inout) {
std::transform(
inout.begin(),
inout.end(),
inout.begin(),
(int (*)(int)) std::tolower
);
return inout;
}
/// Returns lower case copy of input string
static std::string lowerCase(const std::string &in)
{
std::string out = in;
return toLower(out);
}
};
/// Returns true if str1 begins with substring str2 /// Returns true if str1 begins with substring str2
bool begins(const char* str1, const char* str2); bool begins(const char* str1, const char* str2);

@ -357,3 +357,23 @@ std::string ToUTF8::getLegacyEnc(ToUTF8::FromType to)
// Return a string // Return a string
return std::string(&output[0], outlen); return std::string(&output[0], outlen);
} }
ToUTF8::FromType ToUTF8::CalculateEncoding(const std::string& encodingName)
{
if (encodingName == "win1250")
return ToUTF8::WINDOWS_1250;
else if (encodingName == "win1251")
return ToUTF8::WINDOWS_1251;
else
return ToUTF8::WINDOWS_1252;
}
std::string ToUTF8::EncodingUsingMessage(const std::string& encodingName)
{
if (encodingName == "win1250")
return "Using Central and Eastern European font encoding.";
else if (encodingName == "win1251")
return "Using Cyrillic font encoding.";
else
return "Using default (English) font encoding.";
}

@ -22,6 +22,9 @@ namespace ToUTF8
// page. // page.
std::string getUtf8(FromType from); std::string getUtf8(FromType from);
std::string getLegacyEnc(FromType to); std::string getLegacyEnc(FromType to);
FromType CalculateEncoding(const std::string& encodingName);
std::string EncodingUsingMessage(const std::string& encodingName);
} }
#endif #endif

@ -0,0 +1,104 @@
#include "translation_data.hpp"
#include <components/misc/stringops.hpp>
#include <fstream>
namespace TranslationData
{
void Storage::loadTranslationData(const Files::Collections& dataFileCollections,
const std::string& esmFileName)
{
std::string esmNameNoExtension(Misc::StringUtils::lowerCase(esmFileName));
//changing the extension
size_t dotPos = esmNameNoExtension.rfind('.');
if (dotPos != std::string::npos)
esmNameNoExtension.resize(dotPos);
loadData(mCellNamesTranslations, esmNameNoExtension, ".cel", dataFileCollections);
loadData(mPhraseForms, esmNameNoExtension, ".top", dataFileCollections);
loadData(mTopicIDs, esmNameNoExtension, ".mrk", dataFileCollections);
}
void Storage::loadData(ContainerType& container,
const std::string& fileNameNoExtension,
const std::string& extension,
const Files::Collections& dataFileCollections)
{
std::string path;
try
{
path = dataFileCollections.getCollection(extension).getPath(fileNameNoExtension + extension).string();
}
catch(...)
{
//no file
return;
}
std::ifstream stream(path);
if (stream.is_open())
{
loadDataFromStream(container, stream);
stream.close();
}
}
void Storage::loadDataFromStream(ContainerType& container, std::istream& stream)
{
std::string line;
while (!stream.eof())
{
std::getline( stream, line );
if (!line.empty() && *line.rbegin() == '\r')
line.resize(line.size() - 1);
if (!line.empty())
{
char* buffer = ToUTF8::getBuffer(line.size() + 1);
//buffer has at least line.size() + 1 bytes, so it must be safe
strcpy(buffer, line.c_str());
line = ToUTF8::getUtf8(mEncoding);
size_t tab_pos = line.find('\t');
if (tab_pos != std::string::npos && tab_pos > 0 && tab_pos < line.size() - 1)
{
std::string key = line.substr(0, tab_pos);
std::string value = line.substr(tab_pos + 1);
if (!key.empty() && !value.empty())
container.insert(std::make_pair(key, value));
}
}
}
}
std::string Storage::translateCellName(const std::string& cellName) const
{
auto entry = mCellNamesTranslations.find(cellName);
if (entry == mCellNamesTranslations.end())
return cellName;
return entry->second;
}
std::string Storage::topicID(const std::string& phrase) const
{
std::string result;
//seeking for the standard phrase form
auto phraseFormsIterator = mPhraseForms.find(phrase);
if (phraseFormsIterator != mPhraseForms.end())
result = phraseFormsIterator->second;
else
result = phrase;
//seeking for the topic ID
auto topicIDIterator = mTopicIDs.find(result);
if (topicIDIterator != mTopicIDs.end())
result = topicIDIterator->second;
return result;
}
}

@ -0,0 +1,36 @@
#ifndef COMPONENTS_TRANSLATION_DATA_H
#define COMPONENTS_TRANSLATION_DATA_H
#include <components/to_utf8/to_utf8.hpp>
#include <components/files/collections.hpp>
namespace TranslationData
{
class Storage
{
public:
Storage(const ToUTF8::FromType& encoding) : mEncoding(encoding) {}
void loadTranslationData(const Files::Collections& dataFileCollections,
const std::string& esmFileName);
std::string translateCellName(const std::string& cellName) const;
std::string topicID(const std::string& phrase) const;
private:
typedef std::map<std::string, std::string> ContainerType;
void loadData(ContainerType& container,
const std::string& fileNameNoExtension,
const std::string& extension,
const Files::Collections& dataFileCollections);
void loadDataFromStream(ContainerType& container, std::istream& stream);
ToUTF8::FromType mEncoding;
std::map<std::string, std::string> mCellNamesTranslations, mTopicIDs, mPhraseForms;
};
}
#endif
Loading…
Cancel
Save