1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2024-12-29 03:19:44 +00:00

Cell names localization fix

This commit is contained in:
lazydev 2012-12-23 23:23:24 +04:00
parent 1cf019a007
commit 74ae479780
24 changed files with 339 additions and 183 deletions

View File

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

View File

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

View File

@ -8,6 +8,7 @@
#include <components/bsa/bsa_archive.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/translation_data/translation_data.hpp>
#include <components/nifoverrides/nifoverrides.hpp>
#include <components/nifbullet/bullet_nif_loader.hpp>
@ -334,12 +335,16 @@ void OMW::Engine::go()
mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster,
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
MWScript::registerExtensions (mExtensions);
mEnvironment.setWindowManager (new MWGui::WindowManager(
mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
mCfgMgr.getCachePath ().string(), mScriptConsoleMode));
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, translationDataStorage.release()));
// Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound));
@ -487,7 +492,7 @@ void OMW::Engine::showFPS(int level)
mFpsLevel = level;
}
void OMW::Engine::setEncoding(const std::string& encoding)
void OMW::Engine::setEncoding(const ToUTF8::FromType& encoding)
{
mEncoding = encoding;
}

View File

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

View File

@ -181,21 +181,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
// Font encoding settings
std::string encoding(variables["encoding"].as<std::string>());
if (encoding == "win1250")
{
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");
}
std::cout << ToUTF8::EncodingUsingMessage(encoding) << std::endl;
engine.setEncoding(ToUTF8::CalculateEncoding(encoding));
// directory settings
engine.enableFSStrict(variables["fs-strict"].as<bool>());

View File

@ -204,33 +204,10 @@ namespace MWClass
std::string text;
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
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"+dest;
text += "\n" + getDestination(*ref);
}
if (ref->mRef.mLockLevel > 0)
@ -246,6 +223,37 @@ namespace MWClass
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
Door::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{

View File

@ -31,6 +31,9 @@ namespace MWClass
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.
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;
///< Lock object

View File

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

View File

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

View File

@ -55,7 +55,8 @@ using namespace MWGui;
WindowManager::WindowManager(
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)
, mHud(NULL)
, mMap(NULL)
@ -104,6 +105,7 @@ WindowManager::WindowManager(
, mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD"))
, mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI"))
, mHudEnabled(true)
, mTranslationDataStorage(pTranslationDataStorage)
{
// Set up the GUI system
@ -612,7 +614,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
if (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
{
@ -722,13 +724,25 @@ void WindowManager::setDragDrop(bool dragDrop)
void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result)
{
const ESM::GameSetting *setting =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(_tag);
std::string tag(_tag);
if (setting && setting->mType == ESM::VT_String)
_result = setting->getString();
std::string tokenToFind = "sCell=";
size_t tokenLength = tokenToFind.length();
if (tag.substr(0, tokenLength) == tokenToFind)
{
_result = mTranslationDataStorage->translateCellName(tag.substr(tokenLength));
}
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)

View File

@ -14,6 +14,7 @@
#include <string>
#include <components/esm/loadclas.hpp>
#include <components/translation_data/translation_data.hpp>
#include "../mwbase/windowmanager.hpp"
@ -76,7 +77,8 @@ namespace MWGui
WindowManager(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& cacheDir, bool consoleOnlyScripts,
TranslationData::Storage* pTranslationDataStorage);
virtual ~WindowManager();
/**
@ -250,6 +252,7 @@ namespace MWGui
SpellCreationDialog* mSpellCreationDialog;
EnchantingDialog* mEnchantingDialog;
TrainingWindow* mTrainingWindow;
std::unique_ptr<TranslationData::Storage> mTranslationDataStorage;
CharacterCreation* mCharGen;

View File

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

View File

@ -1,62 +1,12 @@
#ifndef OPENMW_MWWORLD_RECORDCMP_H
#define OPENMW_MWWORLD_RECORDCMP_H
#include <string>
#include <cctype>
#include <algorithm>
#include <components/esm/records.hpp>
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
{
template <class T>
@ -67,17 +17,17 @@ namespace MWWorld
template <>
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 <>
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 <>
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

View File

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

View File

@ -11,6 +11,8 @@
#include "../mwrender/sky.hpp"
#include "../mwrender/player.hpp"
#include "../mwclass/door.hpp"
#include "player.hpp"
#include "manualref.hpp"
#include "cellfunctors.hpp"
@ -168,7 +170,7 @@ namespace MWWorld
World::World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections,
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),
mSky (true), mCells (mStore, mEsm),
mNumFacing(0)
@ -237,7 +239,7 @@ namespace MWWorld
MWWorld::Store<ESM::Region>::iterator it = regions.begin();
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);
}
@ -805,7 +807,7 @@ namespace MWWorld
{
bool update = false;
if (StringUtils::ciEqual(record.mId, "player"))
if (Misc::StringUtils::ciEqual(record.mId, "player"))
{
static const char *sRaces[] =
{
@ -816,7 +818,7 @@ namespace MWWorld
int i=0;
for (; sRaces[i]; ++i)
if (StringUtils::ciEqual (sRaces[i], record.mRace))
if (Misc::StringUtils::ciEqual (sRaces[i], record.mRace))
break;
mGlobalVariables->setInt ("pcrace", sRaces[i] ? i+1 : 0);
@ -825,9 +827,9 @@ namespace MWWorld
mPlayer->getPlayer().get<ESM::NPC>()->mBase;
update = record.isMale() != player->isMale() ||
!StringUtils::ciEqual(record.mRace, player->mRace) ||
!StringUtils::ciEqual(record.mHead, player->mHead) ||
!StringUtils::ciEqual(record.mHair, player->mHair);
!Misc::StringUtils::ciEqual(record.mRace, player->mRace) ||
!Misc::StringUtils::ciEqual(record.mHead, player->mHead) ||
!Misc::StringUtils::ciEqual(record.mHair, player->mHair);
}
const ESM::NPC *ret = mStore.insert(record);
if (update) {
@ -1080,28 +1082,7 @@ namespace MWWorld
if (ref.mRef.mTeleport)
{
World::DoorMarker newMarker;
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;
newMarker.name = MWClass::Door::getDestination(ref);
ESM::Position pos = ref.mData.getPosition ();

View File

@ -95,7 +95,7 @@ namespace MWWorld
World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections,
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();
@ -228,7 +228,7 @@ namespace MWWorld
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);
///< 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)
const;
@ -323,7 +323,7 @@ namespace MWWorld
}
virtual void renderPlayer();
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);
virtual int canRest();

View File

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

View File

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

View File

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

View File

@ -1,8 +1,58 @@
#ifndef MISC_STRINGOPS_H
#define MISC_STRINGOPS_H
#include <string>
#include <algorithm>
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
bool begins(const char* str1, const char* str2);

View File

@ -357,3 +357,23 @@ std::string ToUTF8::getLegacyEnc(ToUTF8::FromType to)
// Return a string
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.";
}

View File

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

View File

@ -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;
}
}

View File

@ -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