From 0cded250338229dabeddb5a93fb6d45e5245a9e8 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 24 Aug 2022 20:38:52 +0200 Subject: [PATCH 1/3] Remove various string copies --- apps/openmw/mwclass/armor.cpp | 4 ++-- apps/openmw/mwclass/clothing.cpp | 2 +- apps/openmw/mwclass/container.cpp | 12 +++++------ apps/openmw/mwclass/creaturelevlist.cpp | 2 +- apps/openmw/mwclass/door.cpp | 21 ++++++++++---------- apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwdialogue/journalentry.cpp | 2 +- apps/openmw/mwdialogue/journalentry.hpp | 2 +- apps/openmw/mwdialogue/journalimp.cpp | 2 +- apps/openmw/mwdialogue/quest.cpp | 4 ++-- apps/openmw/mwdialogue/quest.hpp | 2 +- apps/openmw/mwdialogue/topic.cpp | 2 +- apps/openmw/mwdialogue/topic.hpp | 2 +- apps/openmw/mwgui/class.cpp | 5 ----- apps/openmw/mwgui/class.hpp | 1 - apps/openmw/mwgui/journalviewmodel.cpp | 12 +++++------ apps/openmw/mwgui/journalviewmodel.hpp | 4 ++-- apps/openmw/mwgui/journalwindow.cpp | 4 ++-- apps/openmw/mwmechanics/levelledlist.hpp | 16 +++++++-------- apps/openmw/mwscript/containerextensions.cpp | 2 +- apps/openmw/mwworld/containerstore.cpp | 4 ++-- apps/openmw/mwworld/containerstore.hpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 2 +- components/widgets/list.cpp | 10 ++++++---- components/widgets/list.hpp | 4 ++-- 25 files changed, 60 insertions(+), 65 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 0eb4ff3e59..a72f0e9faa 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -115,7 +115,7 @@ namespace MWClass { const MWWorld::LiveCellRef *ref = ptr.get(); - std::string typeGmst; + std::string_view typeGmst; switch (ref->mBase->mData.mType) { @@ -298,7 +298,7 @@ namespace MWClass if (npc.getClass().isNpc()) { - std::string npcRace = npc.get()->mBase->mRace; + const std::string& npcRace = npc.get()->mBase->mRace; // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 8d74f18eab..9a78968871 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -205,7 +205,7 @@ namespace MWClass if (npc.getClass().isNpc()) { - std::string npcRace = npc.get()->mBase->mRace; + const std::string& npcRace = npc.get()->mBase->mRace; // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index fe38c1da09..66e10c9341 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -147,8 +147,8 @@ namespace MWClass return action; } - const std::string lockedSound = "LockedChest"; - const std::string trapActivationSound = "Disarm Trap Fail"; + const std::string_view lockedSound = "LockedChest"; + const std::string_view trapActivationSound = "Disarm Trap Fail"; MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); MWWorld::InventoryStore& invStore = player.getClass().getInventoryStore(player); @@ -156,9 +156,9 @@ namespace MWClass bool isLocked = ptr.getCellRef().getLockLevel() > 0; bool isTrapped = !ptr.getCellRef().getTrap().empty(); bool hasKey = false; - std::string keyName; + std::string_view keyName; - const std::string keyId = ptr.getCellRef().getKey(); + const std::string& keyId = ptr.getCellRef().getKey(); if (!keyId.empty()) { MWWorld::Ptr keyPtr = invStore.search(keyId); @@ -171,7 +171,7 @@ namespace MWClass if (isLocked && hasKey) { - MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}"); + MWBase::Environment::get().getWindowManager ()->messageBox(std::string{keyName} + " #{sKeyUsed}"); ptr.getCellRef().unlock(); // using a key disarms the trap if(isTrapped) @@ -204,7 +204,7 @@ namespace MWClass } else { - std::unique_ptr action = std::make_unique(std::string(), ptr); + std::unique_ptr action = std::make_unique(std::string_view{}, ptr); action->setSound(lockedSound); return action; } diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index 822ced836d..41d6b9b280 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -132,7 +132,7 @@ namespace MWClass ptr.get(); auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - std::string id = MWMechanics::getLevelledItem(ref->mBase, true, prng); + std::string_view id = MWMechanics::getLevelledItem(ref->mBase, true, prng); if (!id.empty()) { diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 1f04db4582..8012e90382 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -118,18 +118,11 @@ namespace MWClass const std::string_view lockedSound = "LockedDoor"; const std::string_view trapActivationSound = "Disarm Trap Fail"; - MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor); - - bool isLocked = ptr.getCellRef().getLockLevel() > 0; - bool isTrapped = !ptr.getCellRef().getTrap().empty(); - bool hasKey = false; - std::string keyName; - // FIXME: If NPC activate teleporting door, it can lead to crash due to iterator invalidation in the Actors update. // Make such activation a no-op for now, like how it is in the vanilla game. if (actor != MWMechanics::getPlayer() && ptr.getCellRef().getTeleport()) { - std::unique_ptr action = std::make_unique(std::string(), ptr); + std::unique_ptr action = std::make_unique(std::string_view{}, ptr); action->setSound(lockedSound); return action; } @@ -150,7 +143,13 @@ namespace MWClass } } - const std::string keyId = ptr.getCellRef().getKey(); + MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor); + + bool isLocked = ptr.getCellRef().getLockLevel() > 0; + bool isTrapped = !ptr.getCellRef().getTrap().empty(); + bool hasKey = false; + std::string_view keyName; + const std::string& keyId = ptr.getCellRef().getKey(); if (!keyId.empty()) { MWWorld::Ptr keyPtr = invStore.search(keyId); @@ -164,7 +163,7 @@ namespace MWClass if (isLocked && hasKey) { if(actor == MWMechanics::getPlayer()) - MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}"); + MWBase::Environment::get().getWindowManager()->messageBox(std::string{keyName} + " #{sKeyUsed}"); ptr.getCellRef().unlock(); //Call the function here. because that makes sense. // using a key disarms the trap if(isTrapped) @@ -236,7 +235,7 @@ namespace MWClass else { // locked, and we can't open. - std::unique_ptr action = std::make_unique(std::string(), ptr); + std::unique_ptr action = std::make_unique(std::string_view{}, ptr); action->setSound(lockedSound); return action; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 9f44555c5a..8d1f455d1a 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1150,7 +1150,7 @@ namespace MWClass { MWBase::Environment::get().getWorld()->breakInvisibility(actor); MWMechanics::CastSpell cast(actor, actor); - std::string recordId = consumable.getCellRef().getRefId(); + const std::string& recordId = consumable.getCellRef().getRefId(); MWBase::Environment::get().getLuaManager()->itemConsumed(consumable, actor); actor.getClass().getContainerStore(actor).remove(consumable, 1, actor); return cast.cast(recordId); diff --git a/apps/openmw/mwdialogue/journalentry.cpp b/apps/openmw/mwdialogue/journalentry.cpp index 4b022c251e..961977ca03 100644 --- a/apps/openmw/mwdialogue/journalentry.cpp +++ b/apps/openmw/mwdialogue/journalentry.cpp @@ -45,7 +45,7 @@ namespace MWDialogue Entry::Entry (const ESM::JournalEntry& record) : mInfoId (record.mInfo), mText (record.mText), mActorName(record.mActorName) {} - std::string Entry::getText() const + const std::string& Entry::getText() const { return mText; } diff --git a/apps/openmw/mwdialogue/journalentry.hpp b/apps/openmw/mwdialogue/journalentry.hpp index 709f5627aa..c4b93de7c4 100644 --- a/apps/openmw/mwdialogue/journalentry.hpp +++ b/apps/openmw/mwdialogue/journalentry.hpp @@ -30,7 +30,7 @@ namespace MWDialogue Entry (const ESM::JournalEntry& record); - std::string getText() const; + const std::string& getText() const; void write (ESM::JournalEntry& entry) const; }; diff --git a/apps/openmw/mwdialogue/journalimp.cpp b/apps/openmw/mwdialogue/journalimp.cpp index c7ccb06f9a..906ae97363 100644 --- a/apps/openmw/mwdialogue/journalimp.cpp +++ b/apps/openmw/mwdialogue/journalimp.cpp @@ -96,7 +96,7 @@ namespace MWDialogue if(quest.addEntry(entry)) // we are doing slicing on purpose here { // Restart all "other" quests with the same name as well - std::string name = quest.getName(); + std::string_view name = quest.getName(); for(auto& it : mQuests) { if(it.second.isFinished() && Misc::StringUtils::ciEqual(it.second.getName(), name)) diff --git a/apps/openmw/mwdialogue/quest.cpp b/apps/openmw/mwdialogue/quest.cpp index ce05676965..e9b0166f9f 100644 --- a/apps/openmw/mwdialogue/quest.cpp +++ b/apps/openmw/mwdialogue/quest.cpp @@ -23,7 +23,7 @@ namespace MWDialogue : Topic (state.mTopic), mIndex (state.mState), mFinished (state.mFinished!=0) {} - std::string Quest::getName() const + std::string_view Quest::getName() const { const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().get().find (mTopic); @@ -33,7 +33,7 @@ namespace MWDialogue if (iter->mQuestStatus==ESM::DialInfo::QS_Name) return iter->mResponse; - return ""; + return {}; } int Quest::getIndex() const diff --git a/apps/openmw/mwdialogue/quest.hpp b/apps/openmw/mwdialogue/quest.hpp index 53b4d02f65..17ed62b8c9 100644 --- a/apps/openmw/mwdialogue/quest.hpp +++ b/apps/openmw/mwdialogue/quest.hpp @@ -24,7 +24,7 @@ namespace MWDialogue Quest (const ESM::QuestState& state); - std::string getName() const override; + std::string_view getName() const override; ///< May be an empty string int getIndex() const; diff --git a/apps/openmw/mwdialogue/topic.cpp b/apps/openmw/mwdialogue/topic.cpp index c9d9b2c9df..50316cfabf 100644 --- a/apps/openmw/mwdialogue/topic.cpp +++ b/apps/openmw/mwdialogue/topic.cpp @@ -44,7 +44,7 @@ namespace MWDialogue return mTopic; } - std::string Topic::getName() const + std::string_view Topic::getName() const { return mName; } diff --git a/apps/openmw/mwdialogue/topic.hpp b/apps/openmw/mwdialogue/topic.hpp index 4e5c936ecd..bf74b54e13 100644 --- a/apps/openmw/mwdialogue/topic.hpp +++ b/apps/openmw/mwdialogue/topic.hpp @@ -47,7 +47,7 @@ namespace MWDialogue std::string getTopic() const; - virtual std::string getName() const; + virtual std::string_view getName() const; void removeLastAddedResponse(std::string_view actorName); diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 830d9024ce..44624d6af4 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -55,11 +55,6 @@ namespace MWGui center(); } - std::string GenerateClassResultDialog::getClassId() const - { - return mClassName->getCaption(); - } - void GenerateClassResultDialog::setClassId(const std::string &classId) { mCurrentClassId = classId; diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index a927767d9a..6f45459ad7 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -71,7 +71,6 @@ namespace MWGui public: GenerateClassResultDialog(); - std::string getClassId() const; void setClassId(const std::string &classId); bool exit() override { return false; } diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 681398a06d..7e0832bb47 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -35,12 +35,12 @@ struct JournalViewModelImpl : JournalViewModel } /// \todo replace this nasty BS - static Utf8Span toUtf8Span (std::string const & str) + static Utf8Span toUtf8Span(std::string_view str) { if (str.size () == 0) return Utf8Span (Utf8Point (nullptr), Utf8Point (nullptr)); - Utf8Point point = reinterpret_cast (str.c_str ()); + Utf8Point point = reinterpret_cast(str.data()); return Utf8Span (point, point + str.size ()); } @@ -191,11 +191,11 @@ struct JournalViewModelImpl : JournalViewModel }; - void visitQuestNames (bool active_only, std::function visitor) const override + void visitQuestNames(bool active_only, std::function visitor) const override { MWBase::Journal * journal = MWBase::Environment::get ().getJournal (); - std::set visitedQuests; + std::set> visitedQuests; // Note that for purposes of the journal GUI, quests are identified by the name, not the ID, so several // different quest IDs can end up in the same quest log. A quest log should be considered finished @@ -225,7 +225,7 @@ struct JournalViewModelImpl : JournalViewModel visitor (quest.getName(), isFinished); - visitedQuests.insert(quest.getName()); + visitedQuests.emplace(quest.getName()); } } } @@ -305,7 +305,7 @@ struct JournalViewModelImpl : JournalViewModel visitor (toUtf8Span (topic.getName())); } - void visitTopicNamesStartingWith (Utf8Stream::UnicodeChar character, std::function < void (const std::string&) > visitor) const override + void visitTopicNamesStartingWith(Utf8Stream::UnicodeChar character, std::function < void (std::string_view) > visitor) const override { MWBase::Journal * journal = MWBase::Environment::get().getJournal(); diff --git a/apps/openmw/mwgui/journalviewmodel.hpp b/apps/openmw/mwgui/journalviewmodel.hpp index eda51b9300..c49ccf3e20 100644 --- a/apps/openmw/mwgui/journalviewmodel.hpp +++ b/apps/openmw/mwgui/journalviewmodel.hpp @@ -73,7 +73,7 @@ namespace MWGui virtual bool isEmpty () const = 0; /// walks the active and optionally completed, quests providing the name and completed status - virtual void visitQuestNames (bool active_only, std::function visitor) const = 0; + virtual void visitQuestNames(bool active_only, std::function visitor) const = 0; /// walks over the journal entries related to all quests with the given name /// If \a questName is empty, simply visits all journal entries @@ -83,7 +83,7 @@ namespace MWGui virtual void visitTopicName (TopicId topicId, std::function visitor) const = 0; /// walks over the topics whose names start with the character - virtual void visitTopicNamesStartingWith (Utf8Stream::UnicodeChar character, std::function < void (const std::string&) > visitor) const = 0; + virtual void visitTopicNamesStartingWith(Utf8Stream::UnicodeChar character, std::function < void (std::string_view) > visitor) const = 0; /// walks over the topic entries for the topic specified by its identifier virtual void visitTopicEntries (TopicId topicId, std::function visitor) const = 0; diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 908028e239..45d5b6aa80 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -518,7 +518,7 @@ namespace AddNamesToList(Gui::MWList* list) : mList(list) {} Gui::MWList* mList; - void operator () (const std::string& name, bool finished=false) + void operator() (std::string_view name, bool finished = false) { mList->addItem(name); } @@ -528,7 +528,7 @@ namespace SetNamesInactive(Gui::MWList* list) : mList(list) {} Gui::MWList* mList; - void operator () (const std::string& name, bool finished) + void operator() (std::string_view name, bool finished) { if (finished) { diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index be5c5962bb..57dca34cf0 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -19,7 +19,7 @@ namespace MWMechanics { /// @return ID of resulting item, or empty if none - inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng) + inline std::string_view getLevelledItem(const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng) { const std::vector& items = levItem->mList; @@ -27,9 +27,9 @@ namespace MWMechanics int playerLevel = player.getClass().getCreatureStats(player).getLevel(); if (Misc::Rng::roll0to99(prng) < levItem->mChanceNone) - return std::string(); + return {}; - std::vector candidates; + std::vector candidates; int highestLevel = 0; for (const auto& levelledItem : items) { @@ -42,7 +42,7 @@ namespace MWMechanics if (creature) allLevels = levItem->mFlags & ESM::CreatureLevList::AllLevels; - std::pair highest = std::make_pair(-1, ""); + std::pair highest = {-1, {}}; for (const auto& levelledItem : items) { if (playerLevel >= levelledItem.mLevel @@ -54,14 +54,14 @@ namespace MWMechanics } } if (candidates.empty()) - return std::string(); - std::string item = candidates[Misc::Rng::rollDice(candidates.size(), prng)]; + return {}; + std::string_view item = candidates[Misc::Rng::rollDice(candidates.size(), prng)]; // Vanilla doesn't fail on nonexistent items in levelled lists - if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item))) + if (!MWBase::Environment::get().getWorld()->getStore().find(item)) { Log(Debug::Warning) << "Warning: ignoring nonexistent item '" << item << "' in levelled list '" << levItem->mId << "'"; - return std::string(); + return {}; } // Is this another levelled item or a real item? diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 68d714d58b..2fc2e9294a 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -64,7 +64,7 @@ namespace else { auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - std::string itemId = MWMechanics::getLevelledItem(itemPtr.get()->mBase, false, prng); + std::string_view itemId = MWMechanics::getLevelledItem(itemPtr.get()->mBase, false, prng); if (itemId.empty()) return; MWWorld::ManualRef manualRef(MWBase::Environment::get().getWorld()->getStore(), itemId, 1); diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index e6a5581f44..ab55047756 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -543,7 +543,7 @@ void MWWorld::ContainerStore::fillNonRandom (const ESM::InventoryList& items, co mResolved = false; } -void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, int count, +void MWWorld::ContainerStore::addInitialItem(std::string_view id, const std::string& owner, int count, Misc::Rng::Generator* prng, bool topLevel) { if (count == 0) return; //Don't restock with nothing. @@ -584,7 +584,7 @@ void MWWorld::ContainerStore::addInitialItemImp(const MWWorld::Ptr& ptr, const s } else { - std::string itemId = MWMechanics::getLevelledItem(ptr.get()->mBase, false, *prng); + std::string_view itemId = MWMechanics::getLevelledItem(ptr.get()->mBase, false, *prng); if (itemId.empty()) return; addInitialItem(itemId, owner, count, prng, false); diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 74e46ea5f4..8bbd32af0d 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -126,7 +126,7 @@ namespace MWWorld std::weak_ptr mResolutionListener; ContainerStoreIterator addImp (const Ptr& ptr, int count, bool markModified = true); - void addInitialItem (const std::string& id, const std::string& owner, int count, Misc::Rng::Generator* prng, bool topLevel=true); + void addInitialItem(std::string_view id, const std::string& owner, int count, Misc::Rng::Generator* prng, bool topLevel=true); void addInitialItemImp (const MWWorld::Ptr& ptr, const std::string& owner, int count, Misc::Rng::Generator* prng, bool topLevel=true); template diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 18b33616cd..b39971c8e0 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3692,7 +3692,7 @@ namespace MWWorld for (int i=0; ifindWidget (getName() + "_item_" + name)->castType(); + std::string search = getName() + "_item_"; + search += name; + return mScrollView->findWidget(search)->castType(); } void MWList::scrollToTop() diff --git a/components/widgets/list.hpp b/components/widgets/list.hpp index be0339f33b..8d27d16ffa 100644 --- a/components/widgets/list.hpp +++ b/components/widgets/list.hpp @@ -36,14 +36,14 @@ namespace Gui */ void adjustSize(); - void addItem(const std::string& name); + void addItem(std::string_view name); void addSeparator(); ///< add a seperator between the current and the next item. void removeItem(const std::string& name); unsigned int getItemCount(); std::string getItemNameAt(unsigned int at); ///< \attention if there are separators, this method will return "" at the place where the separator is void clear(); - MyGUI::Button* getItemWidget(const std::string& name); + MyGUI::Button* getItemWidget(std::string_view name); ///< get widget for an item name, useful to set up tooltip void scrollToTop(); From 1d21330fcce3702b93d22539e31405557f7de278 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 24 Aug 2022 22:16:03 +0200 Subject: [PATCH 2/3] Return string_view from getGameSettingString --- apps/openmw/mwbase/windowmanager.hpp | 2 +- apps/openmw/mwclass/activator.cpp | 3 +- apps/openmw/mwclass/apparatus.cpp | 3 +- apps/openmw/mwclass/armor.cpp | 3 +- apps/openmw/mwclass/book.cpp | 3 +- apps/openmw/mwclass/clothing.cpp | 3 +- apps/openmw/mwclass/container.cpp | 3 +- apps/openmw/mwclass/creature.cpp | 3 +- apps/openmw/mwclass/door.cpp | 3 +- apps/openmw/mwclass/ingredient.cpp | 3 +- apps/openmw/mwclass/light.cpp | 3 +- apps/openmw/mwclass/lockpick.cpp | 3 +- apps/openmw/mwclass/misc.cpp | 3 +- apps/openmw/mwclass/npc.cpp | 3 +- apps/openmw/mwclass/potion.cpp | 3 +- apps/openmw/mwclass/probe.cpp | 3 +- apps/openmw/mwclass/repair.cpp | 3 +- apps/openmw/mwclass/weapon.cpp | 3 +- apps/openmw/mwgui/alchemywindow.cpp | 11 ++-- apps/openmw/mwgui/birth.cpp | 9 +-- apps/openmw/mwgui/class.cpp | 41 ++++++------ apps/openmw/mwgui/enchantingdialog.cpp | 11 ++-- apps/openmw/mwgui/itemchargeview.cpp | 3 +- apps/openmw/mwgui/layout.cpp | 8 ++- apps/openmw/mwgui/layout.hpp | 2 +- apps/openmw/mwgui/race.cpp | 7 ++- apps/openmw/mwgui/review.cpp | 15 ++--- apps/openmw/mwgui/review.hpp | 4 +- apps/openmw/mwgui/settingswindow.cpp | 5 +- apps/openmw/mwgui/spellcreationdialog.cpp | 4 +- apps/openmw/mwgui/spellicons.cpp | 44 ++++++++----- apps/openmw/mwgui/spellmodel.cpp | 16 +++-- apps/openmw/mwgui/spellwindow.cpp | 8 +-- apps/openmw/mwgui/statswindow.cpp | 11 ++-- apps/openmw/mwgui/statswindow.hpp | 4 +- apps/openmw/mwgui/textinput.cpp | 10 +-- apps/openmw/mwgui/textinput.hpp | 2 +- apps/openmw/mwgui/ustring.hpp | 15 +++++ apps/openmw/mwgui/widgets.cpp | 76 +++++++++++++++-------- apps/openmw/mwgui/widgets.hpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 5 +- apps/openmw/mwgui/windowmanagerimp.hpp | 2 +- apps/openmw/mwmechanics/npcstats.cpp | 4 +- apps/openmw/mwstate/statemanagerimp.cpp | 4 +- components/misc/strings/format.hpp | 4 +- 45 files changed, 227 insertions(+), 153 deletions(-) create mode 100644 apps/openmw/mwgui/ustring.hpp diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index d5bf6158fd..a972d2a320 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -260,7 +260,7 @@ namespace MWBase * @param id Identifier for the GMST setting, e.g. "aName" * @param default Default value if the GMST setting cannot be used. */ - virtual std::string getGameSettingString(const std::string &id, const std::string &default_) = 0; + virtual std::string_view getGameSettingString(std::string_view id, std::string_view default_) = 0; virtual void processChangedSettings(const std::set< std::pair >& changed) = 0; diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 767f0b3da0..525097f815 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -24,6 +24,7 @@ #include "../mwrender/vismask.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwmechanics/npcstats.hpp" @@ -96,7 +97,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); std::string text; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 41c69a0691..88dae17a63 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -15,6 +15,7 @@ #include "../mwrender/renderinginterface.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "classmodel.hpp" @@ -88,7 +89,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index a72f0e9faa..3abf2f6f57 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -23,6 +23,7 @@ #include "../mwmechanics/weapontype.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "classmodel.hpp" @@ -194,7 +195,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index ae31a69b80..dd8cef1d8a 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -18,6 +18,7 @@ #include "../mwrender/renderinginterface.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwmechanics/npcstats.hpp" @@ -105,7 +106,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 9a78968871..0ad6782011 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -15,6 +15,7 @@ #include "../mwworld/esmstore.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -152,7 +153,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 66e10c9341..b8bff50c27 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -22,6 +22,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/animation.hpp" #include "../mwrender/objects.hpp" @@ -246,7 +247,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)); std::string text; int lockLevel = ptr.getCellRef().getLockLevel(); diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index da105686f7..1be89c0c09 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -40,6 +40,7 @@ #include "../mwrender/objects.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "classmodel.hpp" @@ -589,7 +590,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)); std::string text; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 8012e90382..a990c1439a 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -24,6 +24,7 @@ #include "../mwworld/containerstore.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -267,7 +268,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)); std::string text; diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 0d4e98e5ac..e3f5c26899 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -14,6 +14,7 @@ #include "../mwworld/actioneat.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -100,7 +101,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index e4cbd3838f..3fd61ad995 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -19,6 +19,7 @@ #include "../mwphysics/physicssystem.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -151,7 +152,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index cbe251ebcb..8a9495d603 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -14,6 +14,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -99,7 +100,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 9c259b445f..b96d1a55fb 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -16,6 +16,7 @@ #include "../mwworld/actionsoulgem.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -142,7 +143,7 @@ namespace MWClass countString = " (" + std::to_string(count) + ")"; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 8d1f455d1a..0169e63950 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -55,6 +55,7 @@ #include "../mwrender/npcanimation.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" namespace { @@ -1118,7 +1119,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)); if(fullHelp && !ref->mBase->mName.empty() && ptr.getRefData().getCustomData() && ptr.getRefData().getCustomData()->asNpcCustomData().mNpcStats.isWerewolf()) { info.caption += " ("; diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index cf4b667488..a7920b553f 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -13,6 +13,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -92,7 +93,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 0383027f58..fd152c1906 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -14,6 +14,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -99,7 +100,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 0c2233cfdf..ce6a2fee4b 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -12,6 +12,7 @@ #include "../mwworld/actionrepair.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -101,7 +102,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index fd57b5df6b..464a331581 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -20,6 +20,7 @@ #include "../mwmechanics/weapontype.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwgui/ustring.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -149,7 +150,7 @@ namespace MWClass MWGui::ToolTipInfo info; std::string_view name = getName(ptr); - info.caption = MyGUI::TextIterator::toTagsString({name.data(), name.size()}) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 157567c404..557cb3df4a 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -24,6 +24,7 @@ #include "sortfilteritemmodel.hpp" #include "itemview.hpp" #include "itemwidget.hpp" +#include "ustring.hpp" #include "widgets.hpp" namespace MWGui @@ -151,10 +152,9 @@ namespace MWGui void AlchemyWindow::initFilter() { auto const& wm = MWBase::Environment::get().getWindowManager(); - auto const ingredient = wm->getGameSettingString("sIngredients", "Ingredients"); - auto const effect = wm->getGameSettingString("sMagicEffects", "Magic Effects"); + std::string_view ingredient = wm->getGameSettingString("sIngredients", "Ingredients"); - if (mFilterType->getCaption() == ingredient) + if (mFilterType->getCaption() == toUString(ingredient)) mCurrentFilter = FilterType::ByName; else mCurrentFilter = FilterType::ByEffect; @@ -166,13 +166,12 @@ namespace MWGui void AlchemyWindow::switchFilterType(MyGUI::Widget* _sender) { auto const& wm = MWBase::Environment::get().getWindowManager(); - auto const ingredient = wm->getGameSettingString("sIngredients", "Ingredients"); - auto const effect = wm->getGameSettingString("sMagicEffects", "Magic Effects"); + MyGUI::UString ingredient = toUString(wm->getGameSettingString("sIngredients", "Ingredients")); auto *button = _sender->castType(); if (button->getCaption() == ingredient) { - button->setCaption(effect); + button->setCaption(toUString(wm->getGameSettingString("sMagicEffects", "Magic Effects"))); mCurrentFilter = FilterType::ByEffect; } else diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 3dab0a7772..6022a8bf89 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -15,6 +15,7 @@ #include "../mwworld/esmstore.hpp" #include "../mwworld/player.hpp" +#include "ustring.hpp" #include "widgets.hpp" namespace @@ -51,7 +52,7 @@ namespace MWGui MyGUI::Button* okButton; getWidget(okButton, "OKButton"); - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked); updateBirths(); @@ -64,9 +65,9 @@ namespace MWGui getWidget(okButton, "OKButton"); if (shown) - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {}))); else - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); } void BirthDialog::onOpen() @@ -235,7 +236,7 @@ namespace MWGui if (!categories[category].spells.empty()) { MyGUI::TextBox* label = mSpellArea->createWidget("SandBrightText", coord, MyGUI::Align::Default, std::string("Label")); - label->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString(categories[category].label, "")); + label->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString(categories[category].label, {}))); mSpellItems.push_back(label); coord.top += lineHeight; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 44624d6af4..682ea31a0e 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -18,6 +18,7 @@ #include #include "tooltips.hpp" +#include "ustring.hpp" namespace { @@ -37,7 +38,7 @@ namespace MWGui GenerateClassResultDialog::GenerateClassResultDialog() : WindowModal("openmw_chargen_generate_class_result.layout") { - setText("ReflectT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sMessageQuestionAnswer1", "")); + setText("ReflectT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sMessageQuestionAnswer1", {})); getWidget(mClassImage, "ClassImage"); getWidget(mClassName, "ClassName"); @@ -123,9 +124,9 @@ namespace MWGui getWidget(okButton, "OKButton"); if (shown) - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {}))); else - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); } void PickClassDialog::onOpen() @@ -248,12 +249,12 @@ namespace MWGui ESM::Class::Specialization specialization = static_cast(klass->mData.mSpecialization); - static const char *specIds[3] = { + static const std::string_view specIds[3] = { "sSpecializationCombat", "sSpecializationMagic", "sSpecializationStealth" }; - std::string specName = MWBase::Environment::get().getWindowManager()->getGameSettingString(specIds[specialization], specIds[specialization]); + std::string specName{MWBase::Environment::get().getWindowManager()->getGameSettingString(specIds[specialization], specIds[specialization])}; mSpecializationName->setCaption(specName); ToolTips::createSpecializationToolTip(mSpecializationName, specName, specialization); @@ -383,10 +384,10 @@ namespace MWGui { setText(""); ButtonList buttons; - buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu1", "")); - buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu2", "")); - buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu3", "")); - buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sBack", "")); + buttons.emplace_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu1", {})); + buttons.emplace_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu2", {})); + buttons.emplace_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu3", {})); + buttons.emplace_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sBack", {})); setButtons(buttons); } @@ -410,8 +411,8 @@ namespace MWGui mFavoriteAttribute0->eventClicked += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked); mFavoriteAttribute1->eventClicked += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked); - setText("MajorSkillT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSkillClassMajor", "")); - setText("MinorSkillT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSkillClassMinor", "")); + setText("MajorSkillT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSkillClassMajor", {})); + setText("MinorSkillT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSkillClassMinor", {})); for(int i = 0; i < 5; i++) { char theIndex = '0'+i; @@ -426,7 +427,7 @@ namespace MWGui skill->eventClicked += MyGUI::newDelegate(this, &CreateClassDialog::onSkillClicked); } - setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sName", "")); + setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sName", {})); getWidget(mEditName, "EditName"); // Make sure the edit box has focus @@ -530,9 +531,9 @@ namespace MWGui getWidget(okButton, "OKButton"); if (shown) - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {}))); else - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); } // widget controls @@ -564,12 +565,12 @@ namespace MWGui void CreateClassDialog::setSpecialization(int id) { mSpecializationId = (ESM::Class::Specialization) id; - static const char *specIds[3] = { + static const std::string_view specIds[3] = { "sSpecializationCombat", "sSpecializationMagic", "sSpecializationStealth" }; - std::string specName = MWBase::Environment::get().getWindowManager()->getGameSettingString(specIds[mSpecializationId], specIds[mSpecializationId]); + std::string specName{MWBase::Environment::get().getWindowManager()->getGameSettingString(specIds[mSpecializationId], specIds[mSpecializationId])}; mSpecializationName->setCaption(specName); ToolTips::createSpecializationToolTip(mSpecializationName, specName, mSpecializationId); } @@ -669,9 +670,9 @@ namespace MWGui getWidget(mSpecialization0, "Specialization0"); getWidget(mSpecialization1, "Specialization1"); getWidget(mSpecialization2, "Specialization2"); - std::string combat = MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Combat], ""); - std::string magic = MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Magic], ""); - std::string stealth = MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Stealth], ""); + std::string combat{MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Combat], {})}; + std::string magic{MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Magic], {})}; + std::string stealth{MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Stealth], {})}; mSpecialization0->setCaption(combat); mSpecialization0->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); @@ -875,7 +876,7 @@ namespace MWGui MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked); - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sInputMenu1", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sInputMenu1", {}))); // Make sure the edit box has focus MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index dca0ac02fa..cb4203eb1c 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -25,6 +25,7 @@ #include "itemwidget.hpp" #include "sortfilteritemmodel.hpp" +#include "ustring.hpp" namespace MWGui { @@ -100,7 +101,7 @@ namespace MWGui else { std::string_view name = item.getClass().getName(item); - mName->setCaption({name.data(), name.size()}); + mName->setCaption(toUString(name)); mItemBox->setItem(item); mItemBox->setUserString ("ToolTipType", "ItemPtr"); mItemBox->setUserData(MWWorld::Ptr(item)); @@ -119,19 +120,19 @@ namespace MWGui switch(mEnchanting.getCastStyle()) { case ESM::Enchantment::CastOnce: - mTypeButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastOnce","Cast Once")); + mTypeButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastOnce", "Cast Once"))); setConstantEffect(false); break; case ESM::Enchantment::WhenStrikes: - mTypeButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastWhenStrikes", "When Strikes")); + mTypeButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastWhenStrikes", "When Strikes"))); setConstantEffect(false); break; case ESM::Enchantment::WhenUsed: - mTypeButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastWhenUsed", "When Used")); + mTypeButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastWhenUsed", "When Used"))); setConstantEffect(false); break; case ESM::Enchantment::ConstantEffect: - mTypeButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastConstant", "Cast Constant")); + mTypeButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastConstant", "Cast Constant"))); setConstantEffect(true); break; } diff --git a/apps/openmw/mwgui/itemchargeview.cpp b/apps/openmw/mwgui/itemchargeview.cpp index a8a0452d62..e2745003e7 100644 --- a/apps/openmw/mwgui/itemchargeview.cpp +++ b/apps/openmw/mwgui/itemchargeview.cpp @@ -17,6 +17,7 @@ #include "itemmodel.hpp" #include "itemwidget.hpp" +#include "ustring.hpp" namespace MWGui { @@ -170,7 +171,7 @@ namespace MWGui void ItemChargeView::updateLine(const ItemChargeView::Line& line) { std::string_view name = line.mItemPtr.getClass().getName(line.mItemPtr); - line.mText->setCaption({name.data(), name.size()}); + line.mText->setCaption(toUString(name)); line.mCharge->setVisible(false); switch (mDisplayMode) diff --git a/apps/openmw/mwgui/layout.cpp b/apps/openmw/mwgui/layout.cpp index 18c14f5eb9..2f763b6552 100644 --- a/apps/openmw/mwgui/layout.cpp +++ b/apps/openmw/mwgui/layout.cpp @@ -6,6 +6,8 @@ #include #include +#include "ustring.hpp" + namespace MWGui { void Layout::initialise(std::string_view _layout) @@ -45,17 +47,17 @@ namespace MWGui mMainWidget->setVisible(b); } - void Layout::setText(std::string_view name, const std::string &caption) + void Layout::setText(std::string_view name, std::string_view caption) { MyGUI::Widget* pt; getWidget(pt, name); - static_cast(pt)->setCaption(caption); + static_cast(pt)->setCaption(toUString(caption)); } void Layout::setTitle(std::string_view title) { MyGUI::Window* window = static_cast(mMainWidget); - MyGUI::UString uTitle{title.data(), title.size()}; + MyGUI::UString uTitle = toUString(title); if (window->getCaption() != uTitle) window->setCaptionWithReplacing(uTitle); diff --git a/apps/openmw/mwgui/layout.hpp b/apps/openmw/mwgui/layout.hpp index ee17bacc75..7239f6a80c 100644 --- a/apps/openmw/mwgui/layout.hpp +++ b/apps/openmw/mwgui/layout.hpp @@ -61,7 +61,7 @@ namespace MWGui virtual void setVisible(bool b); - void setText(std::string_view name, const std::string& caption); + void setText(std::string_view name, std::string_view caption); // NOTE: this assume that mMainWidget is of type Window. void setTitle(std::string_view title); diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index e1bacf4619..0c59d1a938 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -17,6 +17,7 @@ #include "../mwrender/characterpreview.hpp" #include "tooltips.hpp" +#include "ustring.hpp" namespace { @@ -105,7 +106,7 @@ namespace MWGui MyGUI::Button* okButton; getWidget(okButton, "OKButton"); - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked); updateRaces(); @@ -119,9 +120,9 @@ namespace MWGui getWidget(okButton, "OKButton"); if (shown) - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {}))); else - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); } void RaceDialog::onOpen() diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 77249948ab..b0f35640f1 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -14,6 +14,7 @@ #include "../mwmechanics/autocalcspell.hpp" #include "tooltips.hpp" +#include "ustring.hpp" namespace { @@ -58,15 +59,15 @@ namespace MWGui // Setup dynamic stats getWidget(mHealth, "Health"); - mHealth->setTitle(MWBase::Environment::get().getWindowManager()->getGameSettingString("sHealth", "")); + mHealth->setTitle(MWBase::Environment::get().getWindowManager()->getGameSettingString("sHealth", {})); mHealth->setValue(45, 45); getWidget(mMagicka, "Magicka"); - mMagicka->setTitle(MWBase::Environment::get().getWindowManager()->getGameSettingString("sMagic", "")); + mMagicka->setTitle(MWBase::Environment::get().getWindowManager()->getGameSettingString("sMagic", {})); mMagicka->setValue(50, 50); getWidget(mFatigue, "Fatigue"); - mFatigue->setTitle(MWBase::Environment::get().getWindowManager()->getGameSettingString("sFatigue", "")); + mFatigue->setTitle(MWBase::Environment::get().getWindowManager()->getGameSettingString("sFatigue", {})); mFatigue->setValue(160, 160); // Setup attributes @@ -250,11 +251,11 @@ namespace MWGui coord2.top += separator->getHeight(); } - void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) + void ReviewDialog::addGroup(std::string_view label, MyGUI::IntCoord& coord1, MyGUI::IntCoord& coord2) { MyGUI::TextBox* groupWidget = mSkillView->createWidget("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default); groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); - groupWidget->setCaption(label); + groupWidget->setCaption(toUString(label)); mSkillWidgets.push_back(groupWidget); int lineHeight = MWBase::Environment::get().getWindowManager()->getFontHeight() + 2; @@ -262,13 +263,13 @@ namespace MWGui coord2.top += lineHeight; } - MyGUI::TextBox* ReviewDialog::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) + MyGUI::TextBox* ReviewDialog::addValueItem(std::string_view text, const std::string& value, const std::string& state, MyGUI::IntCoord& coord1, MyGUI::IntCoord& coord2) { MyGUI::TextBox* skillNameWidget; MyGUI::TextBox* skillValueWidget; skillNameWidget = mSkillView->createWidget("SandText", coord1, MyGUI::Align::Default); - skillNameWidget->setCaption(text); + skillNameWidget->setCaption(toUString(text)); skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillValueWidget = mSkillView->createWidget("SandTextRight", coord2, MyGUI::Align::Default); diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index cf3d693e97..59a5daecac 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -76,8 +76,8 @@ namespace MWGui private: void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - MyGUI::TextBox* addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + void addGroup(std::string_view label, MyGUI::IntCoord& coord1, MyGUI::IntCoord& coord2); + MyGUI::TextBox* addValueItem(std::string_view text, const std::string& value, const std::string& state, MyGUI::IntCoord& coord1, MyGUI::IntCoord& coord2); void addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addItem(const ESM::Spell* spell, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void updateSkillArea(); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index a843991ea6..a646324c13 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -38,6 +38,7 @@ #include "../mwbase/windowmanager.hpp" #include "confirmationdialog.hpp" +#include "ustring.hpp" namespace { @@ -584,11 +585,11 @@ namespace MWGui void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) { - std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOn", "On"); - std::string off = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOff", "On"); + MyGUI::UString on = toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOn", "On")); bool newState; if (_sender->castType()->getCaption() == on) { + MyGUI::UString off = toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOff", "Off")); _sender->castType()->setCaption(off); newState = false; } diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 06ef66728e..02b6ab8db6 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -146,7 +146,7 @@ namespace MWGui mDurationValue->setCaption("1"); mMagnitudeMinValue->setCaption("1"); - const std::string to = MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "-"); + const std::string to{MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "-")}; mMagnitudeMaxValue->setCaption(to + " 1"); mAreaValue->setCaption("0"); @@ -314,7 +314,7 @@ namespace MWGui } mEffect.mMagnMax = pos+1; - const std::string to = MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "-"); + const std::string to{MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "-")}; mMagnitudeMaxValue->setCaption(to + " " + MyGUI::utility::toString(pos+1)); diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 0934feec1e..2f1da5857c 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -67,7 +67,7 @@ namespace MWGui for (const MagicEffectInfo& effectInfo : effectInfos) { if (addNewLine) - sourcesDescription += "\n"; + sourcesDescription += '\n'; // if at least one of the effect sources is permanent, the effect will never wear off if (effectInfo.mPermanent) @@ -84,18 +84,21 @@ namespace MWGui sourcesDescription += effectInfo.mSource; if (effect->mData.mFlags & ESM::MagicEffect::TargetSkill) - sourcesDescription += " (" + - MWBase::Environment::get().getWindowManager()->getGameSettingString( - ESM::Skill::sSkillNameIds[effectInfo.mKey.mArg], "") + ")"; + { + sourcesDescription += " ("; + sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Skill::sSkillNameIds[effectInfo.mKey.mArg], {}); + sourcesDescription += ')'; + } if (effect->mData.mFlags & ESM::MagicEffect::TargetAttribute) - sourcesDescription += " (" + - MWBase::Environment::get().getWindowManager()->getGameSettingString( - ESM::Attribute::sGmstAttributeIds[effectInfo.mKey.mArg], "") + ")"; - + { + sourcesDescription += " ("; + sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Attribute::sGmstAttributeIds[effectInfo.mKey.mArg], {}); + sourcesDescription += ')'; + } ESM::MagicEffect::MagnitudeDisplayType displayType = effect->getMagnitudeDisplayType(); if (displayType == ESM::MagicEffect::MDT_TimesInt) { - std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); + std::string_view timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", {}); std::stringstream formatter; formatter << std::fixed << std::setprecision(1) << " " << (effectInfo.mMagnitude / 10.0f) << timesInt; sourcesDescription += formatter.str(); @@ -105,20 +108,27 @@ namespace MWGui sourcesDescription += ": " + MyGUI::utility::toString(effectInfo.mMagnitude); if ( displayType == ESM::MagicEffect::MDT_Percentage ) - sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", ""); + sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", {}); else if ( displayType == ESM::MagicEffect::MDT_Feet ) - sourcesDescription += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", ""); + { + sourcesDescription += ' '; + sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", {}); + } else if ( displayType == ESM::MagicEffect::MDT_Level ) { - sourcesDescription += " " + ((effectInfo.mMagnitude > 1) ? - MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", "") : - MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", "") ); + sourcesDescription += ' '; + if (effectInfo.mMagnitude > 1) + sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", {}); + else + sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", {}); } else // ESM::MagicEffect::MDT_Points { - sourcesDescription += " " + ((effectInfo.mMagnitude > 1) ? - MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", "") : - MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", "") ); + sourcesDescription += ' '; + if (effectInfo.mMagnitude > 1) + sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", {}); + else + sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", {}); } } if (effectInfo.mRemainingTime > -1 && Settings::Manager::getBool("show effect duration","Game")) diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index fb7f4a718d..859410392d 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -21,11 +21,7 @@ namespace { if (left.mType != right.mType) return left.mType < right.mType; - - std::string leftName = Misc::StringUtils::lowerCase(left.mName); - std::string rightName = Misc::StringUtils::lowerCase(right.mName); - - return leftName.compare(rightName) < 0; + return Misc::StringUtils::ciLess(left.mName, right.mName); } } @@ -57,17 +53,19 @@ namespace MWGui { const ESM::MagicEffect *magicEffect = store.get().find(effectId); - std::string effectIDStr = ESM::MagicEffect::effectIdToString(effectId); - std::string fullEffectName = wm->getGameSettingString(effectIDStr, ""); + const std::string& effectIDStr = ESM::MagicEffect::effectIdToString(effectId); + std::string fullEffectName{wm->getGameSettingString(effectIDStr, {})}; if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill && effect.mSkill != -1) { - fullEffectName += " " + wm->getGameSettingString(ESM::Skill::sSkillNameIds[effect.mSkill], ""); + fullEffectName += ' '; + fullEffectName += wm->getGameSettingString(ESM::Skill::sSkillNameIds[effect.mSkill], {}); } if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute && effect.mAttribute != -1) { - fullEffectName += " " + wm->getGameSettingString(ESM::Attribute::sGmstAttributeIds[effect.mAttribute], ""); + fullEffectName += ' '; + fullEffectName += wm->getGameSettingString(ESM::Attribute::sGmstAttributeIds[effect.mAttribute], {}); } std::string convert = Utf8Stream::lowerCaseUtf8(fullEffectName); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index f210d0bb81..f5618abafb 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -158,17 +158,17 @@ namespace MWGui isInherent = sign->mPowers.exists(spell->mId); } + const auto windowManager = MWBase::Environment::get().getWindowManager(); if (isInherent) { - MWBase::Environment::get().getWindowManager()->messageBox("#{sDeleteSpellError}"); + windowManager->messageBox("#{sDeleteSpellError}"); } else { // ask for confirmation mSpellToDelete = spellId; - ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); - std::string question = MWBase::Environment::get().getWindowManager()->getGameSettingString("sQuestionDeleteSpell", "Delete %s?"); - question = Misc::StringUtils::format(question, spell->mName); + ConfirmationDialog* dialog = windowManager->getConfirmationDialog(); + std::string question = Misc::StringUtils::format(windowManager->getGameSettingString("sQuestionDeleteSpell", "Delete %s?"), spell->mName); dialog->askForConfirmation(question); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept); diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 208f0a8fda..1f7576d493 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -23,6 +23,7 @@ #include "../mwmechanics/actorutil.hpp" #include "tooltips.hpp" +#include "ustring.hpp" namespace MWGui { @@ -411,12 +412,12 @@ namespace MWGui coord2.top += separator->getHeight(); } - void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) + void StatsWindow::addGroup(std::string_view label, MyGUI::IntCoord& coord1, MyGUI::IntCoord& coord2) { MyGUI::TextBox* groupWidget = mSkillView->createWidget("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); - groupWidget->setCaption(label); + groupWidget->setCaption(toUString(label)); groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); mSkillWidgets.push_back(groupWidget); @@ -425,12 +426,12 @@ namespace MWGui coord2.top += lineHeight; } - std::pair StatsWindow::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) + std::pair StatsWindow::addValueItem(std::string_view text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox *skillNameWidget, *skillValueWidget; skillNameWidget = mSkillView->createWidget("SandText", coord1, MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); - skillNameWidget->setCaption(text); + skillNameWidget->setCaption(toUString(text)); skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); skillValueWidget = mSkillView->createWidget("SandTextRight", coord2, MyGUI::Align::Right | MyGUI::Align::Top); @@ -501,7 +502,7 @@ namespace MWGui esmStore.get().find(skill->mData.mAttribute); std::pair widgets = addValueItem(MWBase::Environment::get().getWindowManager()->getGameSettingString(skillNameId, skillNameId), - "", "normal", coord1, coord2); + {}, "normal", coord1, coord2); mSkillWidgetMap[skillId] = widgets; for (int i=0; i<2; ++i) diff --git a/apps/openmw/mwgui/statswindow.hpp b/apps/openmw/mwgui/statswindow.hpp index bf78cde34a..cc87ea9523 100644 --- a/apps/openmw/mwgui/statswindow.hpp +++ b/apps/openmw/mwgui/statswindow.hpp @@ -38,8 +38,8 @@ namespace MWGui private: void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - std::pair addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + void addGroup(std::string_view label, MyGUI::IntCoord& coord1, MyGUI::IntCoord& coord2); + std::pair addValueItem(std::string_view text, const std::string &value, const std::string& state, MyGUI::IntCoord& coord1, MyGUI::IntCoord& coord2); MyGUI::Widget* addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void setFactions (const FactionList& factions); diff --git a/apps/openmw/mwgui/textinput.cpp b/apps/openmw/mwgui/textinput.cpp index 54f2d3be9b..016e84ecf0 100644 --- a/apps/openmw/mwgui/textinput.cpp +++ b/apps/openmw/mwgui/textinput.cpp @@ -6,6 +6,8 @@ #include #include +#include "ustring.hpp" + namespace MWGui { @@ -32,12 +34,12 @@ namespace MWGui getWidget(okButton, "OKButton"); if (shown) - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {}))); else - okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); + okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); } - void TextInputDialog::setTextLabel(const std::string &label) + void TextInputDialog::setTextLabel(std::string_view label) { setText("LabelT", label); } @@ -53,7 +55,7 @@ namespace MWGui void TextInputDialog::onOkClicked(MyGUI::Widget* _sender) { - if (mTextEdit->getCaption() == "") + if (mTextEdit->getCaption().empty()) { MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}"); MWBase::Environment::get().getWindowManager()->setKeyFocusWidget (mTextEdit); diff --git a/apps/openmw/mwgui/textinput.hpp b/apps/openmw/mwgui/textinput.hpp index 4d365eb44c..3914d5119f 100644 --- a/apps/openmw/mwgui/textinput.hpp +++ b/apps/openmw/mwgui/textinput.hpp @@ -14,7 +14,7 @@ namespace MWGui void setTextInput(const std::string &text); void setNextButtonShow(bool shown); - void setTextLabel(const std::string &label); + void setTextLabel(std::string_view label); void onOpen() override; bool exit() override { return false; } diff --git a/apps/openmw/mwgui/ustring.hpp b/apps/openmw/mwgui/ustring.hpp new file mode 100644 index 0000000000..1d8ec3ba13 --- /dev/null +++ b/apps/openmw/mwgui/ustring.hpp @@ -0,0 +1,15 @@ +#ifndef MWGUI_USTRING_H +#define MWGUI_USTRING_H + +#include + +namespace MWGui +{ + // FIXME: Remove once we get a version of MyGUI that supports string_view + inline MyGUI::UString toUString(std::string_view string) + { + return {string.data(), string.size()}; + } +} + +#endif \ No newline at end of file diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 97d70240c0..2a27a976ee 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -17,6 +17,7 @@ #include "../mwworld/esmstore.hpp" #include "controllers.hpp" +#include "ustring.hpp" namespace MWGui::Widgets { @@ -61,7 +62,7 @@ namespace MWGui::Widgets } else { - const std::string &name = MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Skill::sSkillNameIds[mSkillId], ""); + MyGUI::UString name = toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Skill::sSkillNameIds[mSkillId], {})); mSkillNameWidget->setCaption(name); } } @@ -147,7 +148,7 @@ namespace MWGui::Widgets } else { - static const char *attributes[8] = { + static const std::string_view attributes[8] = { "sAttributeStrength", "sAttributeIntelligence", "sAttributeWillpower", @@ -157,7 +158,7 @@ namespace MWGui::Widgets "sAttributePersonality", "sAttributeLuck" }; - const std::string &name = MWBase::Environment::get().getWindowManager()->getGameSettingString(attributes[mId], ""); + MyGUI::UString name = toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString(attributes[mId], {})); mAttributeNameWidget->setCaption(name); } } @@ -390,32 +391,34 @@ namespace MWGui::Widgets assert(magicEffect); - std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); - std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); - std::string pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", ""); - std::string ft = MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", ""); - std::string lvl = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", ""); - std::string lvls = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", ""); - std::string to = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "") + " "; - std::string sec = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("ssecond", ""); - std::string secs = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sseconds", ""); + std::string_view pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", {}); + std::string_view pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", {}); + std::string_view pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", {}); + std::string_view ft = MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", {}); + std::string_view lvl = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", {}); + std::string_view lvls = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", {}); + std::string to = " " + std::string{MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", {})} + " "; + std::string sec = " " + std::string{MWBase::Environment::get().getWindowManager()->getGameSettingString("ssecond", {})}; + std::string secs = " " + std::string{MWBase::Environment::get().getWindowManager()->getGameSettingString("sseconds", {})}; - std::string effectIDStr = ESM::MagicEffect::effectIdToString(mEffectParams.mEffectID); - std::string spellLine = MWBase::Environment::get().getWindowManager()->getGameSettingString(effectIDStr, ""); + const std::string& effectIDStr = ESM::MagicEffect::effectIdToString(mEffectParams.mEffectID); + std::string spellLine{MWBase::Environment::get().getWindowManager()->getGameSettingString(effectIDStr, {})}; if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill && mEffectParams.mSkill != -1) { - spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Skill::sSkillNameIds[mEffectParams.mSkill], ""); + spellLine += ' '; + spellLine += MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Skill::sSkillNameIds[mEffectParams.mSkill], {}); } if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute && mEffectParams.mAttribute != -1) { - spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], ""); + spellLine += ' '; + spellLine += MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], {}); } if (mEffectParams.mMagnMin || mEffectParams.mMagnMax) { ESM::MagicEffect::MagnitudeDisplayType displayType = magicEffect->getMagnitudeDisplayType(); if ( displayType == ESM::MagicEffect::MDT_TimesInt ) { - std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); + std::string_view timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", {}); std::stringstream formatter; formatter << std::fixed << std::setprecision(1) << " " << (mEffectParams.mMagnMin / 10.0f); @@ -433,11 +436,26 @@ namespace MWGui::Widgets if ( displayType == ESM::MagicEffect::MDT_Percentage ) spellLine += pct; else if ( displayType == ESM::MagicEffect::MDT_Feet ) - spellLine += " " + ft; + { + spellLine += ' '; + spellLine += ft; + } else if ( displayType == ESM::MagicEffect::MDT_Level ) - spellLine += " " + ((mEffectParams.mMagnMin == mEffectParams.mMagnMax && std::abs(mEffectParams.mMagnMin) == 1) ? lvl : lvls ); + { + spellLine += ' '; + if (mEffectParams.mMagnMin == mEffectParams.mMagnMax && std::abs(mEffectParams.mMagnMin) == 1) + spellLine += lvl; + else + spellLine += lvls; + } else // ESM::MagicEffect::MDT_Points - spellLine += " " + ((mEffectParams.mMagnMin == mEffectParams.mMagnMax && std::abs(mEffectParams.mMagnMin) == 1) ? pt : pts ); + { + spellLine += ' '; + if (mEffectParams.mMagnMin == mEffectParams.mMagnMax && std::abs(mEffectParams.mMagnMin) == 1) + spellLine += pt; + else + spellLine += pts; + } } } @@ -449,7 +467,9 @@ namespace MWGui::Widgets if (mEffectParams.mDuration > 0 && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) { - spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sfor", "") + " " + MyGUI::utility::toString(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs); + spellLine += ' '; + spellLine += MWBase::Environment::get().getWindowManager()->getGameSettingString("sfor", {}); + spellLine += ' ' + MyGUI::utility::toString(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs); } if (mEffectParams.mArea > 0) @@ -460,13 +480,15 @@ namespace MWGui::Widgets // potions have no target if (!mEffectParams.mNoTarget) { - std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sonword", ""); + spellLine += ' '; + spellLine += MWBase::Environment::get().getWindowManager()->getGameSettingString("sonword", {}); + spellLine += ' '; if (mEffectParams.mRange == ESM::RT_Self) - spellLine += " " + on + " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sRangeSelf", ""); + spellLine += MWBase::Environment::get().getWindowManager()->getGameSettingString("sRangeSelf", {}); else if (mEffectParams.mRange == ESM::RT_Touch) - spellLine += " " + on + " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sRangeTouch", ""); + spellLine += MWBase::Environment::get().getWindowManager()->getGameSettingString("sRangeTouch", {}); else if (mEffectParams.mRange == ESM::RT_Target) - spellLine += " " + on + " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sRangeTarget", ""); + spellLine += MWBase::Environment::get().getWindowManager()->getGameSettingString("sRangeTarget", {}); } } @@ -517,10 +539,10 @@ namespace MWGui::Widgets mBarTextWidget->setCaption(out.str().c_str()); } } - void MWDynamicStat::setTitle(const std::string& text) + void MWDynamicStat::setTitle(std::string_view text) { if (mTextWidget) - mTextWidget->setCaption(text); + mTextWidget->setCaption(toUString(text)); } MWDynamicStat::~MWDynamicStat() diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 61d1ced750..af83daf34c 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -282,7 +282,7 @@ namespace MWGui MWDynamicStat(); void setValue(int value, int max); - void setTitle(const std::string& text); + void setTitle(std::string_view text); int getValue() const { return mValue; } int getMax() const { return mMax; } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 2c1edbdd0c..0c4d36a185 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -124,6 +124,7 @@ #include "itemchargeview.hpp" #include "keyboardnavigation.hpp" #include "resourceskin.hpp" +#include "ustring.hpp" namespace MWGui { @@ -752,7 +753,7 @@ namespace MWGui void WindowManager::messageBox(std::string_view message, enum MWGui::ShowInDialogueMode showInDialogueMode) { if (getMode() == GM_Dialogue && showInDialogueMode != MWGui::ShowInDialogueMode_Never) { - mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags({message.data(), message.size()})); + mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(toUString(message))); } else if (showInDialogueMode != MWGui::ShowInDialogueMode_Only) { mMessageBoxManager->createMessageBox(message); } @@ -783,7 +784,7 @@ namespace MWGui return mMessageBoxManager->readPressedButton(); } - std::string WindowManager::getGameSettingString(const std::string &id, const std::string &default_) + std::string_view WindowManager::getGameSettingString(std::string_view id, std::string_view default_) { const ESM::GameSetting *setting = mStore->get().search(id); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 4f97c1d07f..ad15831098 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -289,7 +289,7 @@ namespace MWGui * @param id Identifier for the GMST setting, e.g. "aName" * @param default Default value if the GMST setting cannot be used. */ - std::string getGameSettingString(const std::string &id, const std::string &default_) override; + std::string_view getGameSettingString(std::string_view id, std::string_view default_) override; void processChangedSettings(const Settings::CategorySettingVector& changed) override; diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 5d81390a77..89b10b2bf0 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -267,8 +267,8 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas /// \todo check if character is the player, if levelling is ever implemented for NPCs MWBase::Environment::get().getWindowManager()->playSound("skillraise"); - std::string message = MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", ""); - message = Misc::StringUtils::format(message, ("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}"), static_cast(base)); + std::string message = Misc::StringUtils::format(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNotifyMessage39", {}), + ("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}"), static_cast(base)); if (readBook) message = "#{sBookSkillMessage}\n" + message; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index fdb1ff277f..b6fb8c61e3 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -124,8 +124,8 @@ void MWState::StateManager::askLoadRecent() std::vector buttons; buttons.emplace_back("#{sYes}"); buttons.emplace_back("#{sNo}"); - std::string tag("%s"); - std::string message = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLoadLastSaveMsg", tag); + std::string_view tag = "%s"; + std::string message{MWBase::Environment::get().getWindowManager()->getGameSettingString("sLoadLastSaveMsg", tag)}; size_t pos = message.find(tag); message.replace(pos, tag.length(), lastSave.mProfile.mDescription); MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons); diff --git a/components/misc/strings/format.hpp b/components/misc/strings/format.hpp index 420a1161c4..4104082e63 100644 --- a/components/misc/strings/format.hpp +++ b/components/misc/strings/format.hpp @@ -51,9 +51,9 @@ namespace Misc::StringUtils } template - std::string format(const std::string& fmt, Args const & ... args) + std::string format(std::string_view fmt, Args const & ... args) { - return format(fmt.c_str(), args ...); + return format(fmt.data(), args ...); } } From 4e2e5ad002481caeb608205b9c9c7a95d6045563 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 24 Aug 2022 23:10:05 +0200 Subject: [PATCH 3/3] Revert format change and ensure string_view args are null-terminated --- apps/openmw/mwgui/spellwindow.cpp | 3 ++- apps/openmw/mwmechanics/npcstats.cpp | 4 ++-- components/misc/strings/format.hpp | 20 +++++++++++++------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index f5618abafb..c39341aeb4 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -168,7 +168,8 @@ namespace MWGui // ask for confirmation mSpellToDelete = spellId; ConfirmationDialog* dialog = windowManager->getConfirmationDialog(); - std::string question = Misc::StringUtils::format(windowManager->getGameSettingString("sQuestionDeleteSpell", "Delete %s?"), spell->mName); + std::string question{windowManager->getGameSettingString("sQuestionDeleteSpell", "Delete %s?")}; + question = Misc::StringUtils::format(question, spell->mName); dialog->askForConfirmation(question); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept); diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 89b10b2bf0..a89e01259c 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -267,8 +267,8 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas /// \todo check if character is the player, if levelling is ever implemented for NPCs MWBase::Environment::get().getWindowManager()->playSound("skillraise"); - std::string message = Misc::StringUtils::format(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNotifyMessage39", {}), - ("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}"), static_cast(base)); + std::string message{MWBase::Environment::get().getWindowManager()->getGameSettingString("sNotifyMessage39", {})}; + message = Misc::StringUtils::format(message, ("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}"), static_cast(base)); if (readBook) message = "#{sBookSkillMessage}\n" + message; diff --git a/components/misc/strings/format.hpp b/components/misc/strings/format.hpp index 4104082e63..7b5de50fb4 100644 --- a/components/misc/strings/format.hpp +++ b/components/misc/strings/format.hpp @@ -7,11 +7,14 @@ #include #include #include +#include namespace Misc::StringUtils { - namespace Details + struct Details { + std::vector mMemorySafety; + // Allow to convert complex arguments to C-style strings for format() function template T argument(T value) noexcept @@ -22,7 +25,9 @@ namespace Misc::StringUtils template T const * argument(std::basic_string_view const & value) noexcept { - return value.data(); + // TODO: switch to a format function that doesn't require null termination + auto& inserted = mMemorySafety.emplace_back(value); + return inserted.c_str(); } template @@ -30,7 +35,7 @@ namespace Misc::StringUtils { return value.c_str(); } - } + }; // Requires some C++11 features: // 1. std::string needs to be contiguous @@ -39,21 +44,22 @@ namespace Misc::StringUtils template std::string format(const char* fmt, Args const & ... args) { - const int size = std::snprintf(nullptr, 0, fmt, Details::argument(args) ...); + Details details; + const int size = std::snprintf(nullptr, 0, fmt, details.argument(args) ...); if (size < 0) throw std::runtime_error(std::string("Failed to compute resulting string size: ") + std::strerror(errno)); // Note: sprintf also writes a trailing null character. We should remove it. std::string ret(static_cast(size) + 1, '\0'); - if (std::sprintf(ret.data(), fmt, Details::argument(args) ...) < 0) + if (std::sprintf(ret.data(), fmt, details.argument(args) ...) < 0) throw std::runtime_error(std::string("Failed to format string: ") + std::strerror(errno)); ret.erase(static_cast(size)); return ret; } template - std::string format(std::string_view fmt, Args const & ... args) + std::string format(const std::string& fmt, Args const & ... args) { - return format(fmt.data(), args ...); + return format(fmt.c_str(), args ...); } }