From 54915129055e90b8a1b70f379f9369c49cc35d45 Mon Sep 17 00:00:00 2001
From: Evil Eye <malusluminis@hotmail.com>
Date: Sun, 21 May 2023 16:39:32 +0200
Subject: [PATCH 1/4] Use string_view in more places and reduce the number of
 empty string literals

---
 apps/openmw/mwbase/dialoguemanager.hpp        |  4 +-
 apps/openmw/mwclass/esm4base.hpp              |  4 +-
 apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 16 +++++---
 apps/openmw/mwdialogue/dialoguemanagerimp.hpp |  2 +-
 apps/openmw/mwgui/alchemywindow.cpp           | 15 +++----
 apps/openmw/mwgui/birth.cpp                   | 12 +++---
 apps/openmw/mwgui/charactercreation.cpp       | 25 ++++--------
 apps/openmw/mwgui/class.cpp                   |  4 +-
 apps/openmw/mwgui/companionwindow.cpp         |  2 +-
 apps/openmw/mwgui/console.cpp                 |  8 ++--
 apps/openmw/mwgui/dialogue.cpp                | 21 +++++-----
 apps/openmw/mwgui/dialogue.hpp                | 12 +++---
 apps/openmw/mwgui/enchantingdialog.cpp        |  2 +-
 apps/openmw/mwgui/formatting.cpp              | 39 +++++++++++-------
 apps/openmw/mwgui/itemview.cpp                |  2 +-
 apps/openmw/mwgui/itemwidget.cpp              | 14 +++----
 apps/openmw/mwgui/journalbooks.cpp            | 24 +++++------
 apps/openmw/mwgui/levelupdialog.cpp           | 15 ++++---
 apps/openmw/mwgui/levelupdialog.hpp           |  2 +-
 apps/openmw/mwgui/loadingscreen.cpp           |  4 +-
 apps/openmw/mwgui/mainmenu.cpp                | 21 +++++-----
 apps/openmw/mwgui/mainmenu.hpp                |  2 +-
 apps/openmw/mwgui/mapwindow.cpp               |  6 +--
 apps/openmw/mwgui/postprocessorhud.cpp        |  2 +-
 apps/openmw/mwgui/resourceskin.cpp            | 12 +++---
 apps/openmw/mwgui/savegamedialog.cpp          | 15 ++++---
 apps/openmw/mwgui/settingswindow.cpp          | 18 ++++-----
 apps/openmw/mwgui/spellcreationdialog.cpp     |  6 +--
 apps/openmw/mwgui/spellview.cpp               |  4 +-
 apps/openmw/mwgui/spellwindow.cpp             |  2 +-
 apps/openmw/mwgui/statswindow.cpp             |  9 +++--
 apps/openmw/mwgui/tooltips.cpp                | 16 ++++----
 apps/openmw/mwgui/tradewindow.cpp             |  2 +-
 apps/openmw/mwgui/travelwindow.cpp            |  2 +-
 apps/openmw/mwgui/widgets.cpp                 |  8 ++--
 apps/openmw/mwgui/windowmanagerimp.cpp        |  7 ++--
 components/fontloader/fontloader.cpp          | 40 +++++++++----------
 components/fontloader/fontloader.hpp          |  2 +-
 components/interpreter/defines.cpp            |  6 +--
 components/interpreter/defines.hpp            |  6 +--
 components/resource/imagemanager.cpp          |  6 +--
 components/resource/imagemanager.hpp          |  2 +-
 components/sdlutil/sdlcursormanager.cpp       | 12 +++---
 components/sdlutil/sdlcursormanager.hpp       | 10 ++---
 components/widgets/imagebutton.cpp            |  2 +-
 45 files changed, 224 insertions(+), 221 deletions(-)

diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp
index 6792cae078..70887c69c1 100644
--- a/apps/openmw/mwbase/dialoguemanager.hpp
+++ b/apps/openmw/mwbase/dialoguemanager.hpp
@@ -41,7 +41,7 @@ namespace MWBase
         {
         public:
             virtual ~ResponseCallback() = default;
-            virtual void addResponse(const std::string& title, const std::string& text) = 0;
+            virtual void addResponse(std::string_view title, std::string_view text) = 0;
         };
 
         DialogueManager() {}
@@ -67,7 +67,7 @@ namespace MWBase
 
         virtual void say(const MWWorld::Ptr& actor, const ESM::RefId& topic) = 0;
 
-        virtual void keywordSelected(const std::string& keyword, ResponseCallback* callback) = 0;
+        virtual void keywordSelected(std::string_view keyword, ResponseCallback* callback) = 0;
         virtual void goodbyeSelected() = 0;
         virtual void questionAnswered(int answer, ResponseCallback* callback) = 0;
 
diff --git a/apps/openmw/mwclass/esm4base.hpp b/apps/openmw/mwclass/esm4base.hpp
index 9fd2f68249..6a28faf2f3 100644
--- a/apps/openmw/mwclass/esm4base.hpp
+++ b/apps/openmw/mwclass/esm4base.hpp
@@ -62,7 +62,7 @@ namespace MWClass
 
         bool hasToolTip(const MWWorld::ConstPtr& ptr) const override { return false; }
 
-        std::string_view getName(const MWWorld::ConstPtr& ptr) const override { return ""; }
+        std::string_view getName(const MWWorld::ConstPtr& ptr) const override { return {}; }
 
         std::string getModel(const MWWorld::ConstPtr& ptr) const override
         {
@@ -73,7 +73,7 @@ namespace MWClass
             // TODO: Figure out a better way find markers and LOD meshes; show LOD only outside of active grid.
             if (model.empty() || Misc::StringUtils::ciStartsWith(model, "meshes\\marker")
                 || Misc::StringUtils::ciEndsWith(model, "lod.nif"))
-                return "";
+                return {};
 
             return model;
         }
diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp
index 28771d8f1f..160af0f772 100644
--- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp
+++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp
@@ -174,7 +174,7 @@ namespace MWDialogue
                     }
 
                     MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(), mActor);
-                    callback->addResponse("", Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
+                    callback->addResponse({}, Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
                     executeScript(info->mResultScript, mActor);
                     mLastTopic = it->mId;
 
@@ -429,14 +429,14 @@ namespace MWDialogue
         return 0;
     }
 
-    void DialogueManager::keywordSelected(const std::string& keyword, ResponseCallback* callback)
+    void DialogueManager::keywordSelected(std::string_view keyword, ResponseCallback* callback)
     {
         if (!mIsInChoice)
         {
             const ESM::Dialogue* dialogue = searchDialogue(ESM::RefId::stringRefId(keyword));
             if (dialogue && dialogue->mType == ESM::Dialogue::Topic)
             {
-                executeTopic(ESM::RefId::stringRefId(keyword), callback);
+                executeTopic(dialogue->mId, callback);
             }
         }
     }
@@ -487,7 +487,7 @@ namespace MWDialogue
                     mChoices.clear();
 
                     MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(), mActor);
-                    callback->addResponse("", Interpreter::fixDefinesDialog(text, interpreterContext));
+                    callback->addResponse({}, Interpreter::fixDefinesDialog(text, interpreterContext));
 
                     if (dialogue->mType == ESM::Dialogue::Topic)
                     {
@@ -731,8 +731,12 @@ namespace MWDialogue
     int DialogueManager::getFactionReaction(const ESM::RefId& faction1, const ESM::RefId& faction2) const
     {
         ModFactionReactionMap::const_iterator map = mChangedFactionReaction.find(faction1);
-        if (map != mChangedFactionReaction.end() && map->second.find(faction2) != map->second.end())
-            return map->second.at(faction2);
+        if (map != mChangedFactionReaction.end())
+        {
+            auto it = map->second.find(faction2);
+            if (it != map->second.end())
+                return it->second;
+        }
 
         const ESM::Faction* faction = MWBase::Environment::get().getESMStore()->get<ESM::Faction>().find(faction1);
 
diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp
index dd5b347c93..c214106fdc 100644
--- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp
+++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp
@@ -103,7 +103,7 @@ namespace MWDialogue
         void say(const MWWorld::Ptr& actor, const ESM::RefId& topic) override;
 
         // calbacks for the GUI
-        void keywordSelected(const std::string& keyword, ResponseCallback* callback) override;
+        void keywordSelected(std::string_view keyword, ResponseCallback* callback) override;
         void goodbyeSelected() override;
         void questionAnswered(int answer, ResponseCallback* callback) override;
 
diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp
index 7e8b80bc5e..1eb41a2d86 100644
--- a/apps/openmw/mwgui/alchemywindow.cpp
+++ b/apps/openmw/mwgui/alchemywindow.cpp
@@ -267,16 +267,17 @@ namespace MWGui
         mNameEdit->setCaption({});
         mBrewCountEdit->setValue(1);
 
-        int index = 0;
-        for (MWMechanics::Alchemy::TToolsIterator iter(mAlchemy->beginTools());
-             iter != mAlchemy->endTools() && index < static_cast<int>(mApparatus.size()); ++iter, ++index)
+        size_t index = 0;
+        for (auto iter = mAlchemy->beginTools(); iter != mAlchemy->endTools() && index < mApparatus.size();
+             ++iter, ++index)
         {
-            mApparatus.at(index)->setItem(*iter);
-            mApparatus.at(index)->clearUserStrings();
+            const auto& widget = mApparatus[index];
+            widget->setItem(*iter);
+            widget->clearUserStrings();
             if (!iter->isEmpty())
             {
-                mApparatus.at(index)->setUserString("ToolTipType", "ItemPtr");
-                mApparatus.at(index)->setUserData(MWWorld::Ptr(*iter));
+                widget->setUserString("ToolTipType", "ItemPtr");
+                widget->setUserData(MWWorld::Ptr(*iter));
             }
         }
 
diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp
index 5e505b6cd3..d9f78366ab 100644
--- a/apps/openmw/mwgui/birth.cpp
+++ b/apps/openmw/mwgui/birth.cpp
@@ -225,15 +225,15 @@ namespace MWGui
         struct
         {
             const std::vector<ESM::RefId>& spells;
-            const char* label;
+            std::string_view label;
         } categories[3] = { { abilities, "sBirthsignmenu1" }, { powers, "sPowers" }, { spells, "sBirthsignmenu2" } };
 
-        for (int category = 0; category < 3; ++category)
+        for (size_t category = 0; category < 3; ++category)
         {
             if (!categories[category].spells.empty())
             {
-                MyGUI::TextBox* label = mSpellArea->createWidget<MyGUI::TextBox>(
-                    "SandBrightText", coord, MyGUI::Align::Default, std::string("Label"));
+                MyGUI::TextBox* label
+                    = mSpellArea->createWidget<MyGUI::TextBox>("SandBrightText", coord, MyGUI::Align::Default, "Label");
                 label->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString(
                     categories[category].label, {})));
                 mSpellItems.push_back(label);
@@ -243,8 +243,8 @@ namespace MWGui
                 for (it = categories[category].spells.begin(); it != end; ++it)
                 {
                     const ESM::RefId& spellId = *it;
-                    spellWidget = mSpellArea->createWidget<Widgets::MWSpell>("MW_StatName", coord,
-                        MyGUI::Align::Default, std::string("Spell") + MyGUI::utility::toString(i));
+                    spellWidget = mSpellArea->createWidget<Widgets::MWSpell>(
+                        "MW_StatName", coord, MyGUI::Align::Default, "Spell" + MyGUI::utility::toString(i));
                     spellWidget->setSpellId(spellId);
 
                     mSpellItems.push_back(spellWidget);
diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp
index 7a54f23825..65a1be9c51 100644
--- a/apps/openmw/mwgui/charactercreation.cpp
+++ b/apps/openmw/mwgui/charactercreation.cpp
@@ -103,27 +103,16 @@ namespace MWGui
 
     void CharacterCreation::setValue(std::string_view id, const MWMechanics::AttributeValue& value)
     {
-        static const char* ids[] = {
-            "AttribVal1",
-            "AttribVal2",
-            "AttribVal3",
-            "AttribVal4",
-            "AttribVal5",
-            "AttribVal6",
-            "AttribVal7",
-            "AttribVal8",
-            nullptr,
-        };
-
-        for (int i = 0; ids[i]; ++i)
+        std::string_view prefix = "AttribVal";
+        if (id.starts_with(prefix) && id.size() == prefix.size() + 1)
         {
-            if (ids[i] == id)
+            char index = id[prefix.size()];
+            auto attribute = static_cast<ESM::Attribute::AttributeID>(index - '0' - 1);
+            if (attribute >= ESM::Attribute::Strength && attribute < ESM::Attribute::Length)
             {
-                mPlayerAttributes[static_cast<ESM::Attribute::AttributeID>(i)] = value;
+                mPlayerAttributes[attribute] = value;
                 if (mReviewDialog)
-                    mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID>(i), value);
-
-                break;
+                    mReviewDialog->setAttribute(attribute, value);
             }
         }
     }
diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp
index 7385330333..110df15cf0 100644
--- a/apps/openmw/mwgui/class.cpp
+++ b/apps/openmw/mwgui/class.cpp
@@ -346,7 +346,7 @@ namespace MWGui
         for (const std::string& text : buttons)
         {
             button = mButtonBar->createWidget<MyGUI::Button>(
-                "MW_Button", coord, MyGUI::Align::Top | MyGUI::Align::HCenter, "");
+                "MW_Button", coord, MyGUI::Align::Top | MyGUI::Align::HCenter, {});
             button->getSubWidgetText()->setWordWrap(true);
             button->setCaption(text);
             fitToText(button);
@@ -386,7 +386,7 @@ namespace MWGui
     ClassChoiceDialog::ClassChoiceDialog()
         : InfoBoxDialog()
     {
-        setText("");
+        setText({});
         ButtonList buttons;
         buttons.emplace_back(
             MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu1", {}));
diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp
index 5f2bb85606..1aa00d87c9 100644
--- a/apps/openmw/mwgui/companionwindow.cpp
+++ b/apps/openmw/mwgui/companionwindow.cpp
@@ -153,7 +153,7 @@ namespace MWGui
             mProfitLabel->setCaptionWithReplacing("#{sProfitValue} " + MyGUI::utility::toString(getProfit(mPtr)));
         }
         else
-            mProfitLabel->setCaption("");
+            mProfitLabel->setCaption({});
     }
 
     void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp
index 1ac090b379..4affff459c 100644
--- a/apps/openmw/mwgui/console.cpp
+++ b/apps/openmw/mwgui/console.cpp
@@ -101,7 +101,7 @@ namespace MWGui
         if (mNames.empty())
         {
             // keywords
-            std::istringstream input("");
+            std::istringstream input;
 
             Compiler::Scanner scanner(*this, input, mCompilerContext.getExtensions());
 
@@ -312,7 +312,7 @@ namespace MWGui
             if (oldCaption == newCaption && !matches.empty())
             {
                 int i = 0;
-                printOK("");
+                printOK({});
                 for (std::string& match : matches)
                 {
                     if (i == 50)
@@ -377,7 +377,7 @@ namespace MWGui
         // Reset the command line before the command execution.
         // It prevents the re-triggering of the acceptCommand() event for the same command
         // during the actual command execution
-        mCommandLine->setCaption("");
+        mCommandLine->setCaption({});
 
         execute(cm);
     }
@@ -618,7 +618,7 @@ namespace MWGui
             if ((matches.front().find(' ') != std::string::npos))
             {
                 if (!has_front_quote)
-                    output.append(std::string("\""));
+                    output += '"';
                 return output.append(matches.front() + std::string("\" "));
             }
             else if (has_front_quote)
diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp
index 03a5fd9b7f..6b69404d29 100644
--- a/apps/openmw/mwgui/dialogue.cpp
+++ b/apps/openmw/mwgui/dialogue.cpp
@@ -32,7 +32,7 @@
 
 namespace MWGui
 {
-    void ResponseCallback::addResponse(const std::string& title, const std::string& text)
+    void ResponseCallback::addResponse(std::string_view title, std::string_view text)
     {
         mWindow->addResponse(title, text, mNeedMargin);
     }
@@ -150,7 +150,7 @@ namespace MWGui
 
     // --------------------------------------------------------------------------------------------------
 
-    Response::Response(const std::string& text, const std::string& title, bool needMargin)
+    Response::Response(std::string_view text, std::string_view title, bool needMargin)
         : mTitle(title)
         , mNeedMargin(needMargin)
     {
@@ -213,7 +213,7 @@ namespace MWGui
         {
             const TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours();
 
-            BookTypesetter::Style* style = typesetter->createStyle("", textColours.normal, false);
+            BookTypesetter::Style* style = typesetter->createStyle({}, textColours.normal, false);
             size_t formatted = 0; // points to the first character that is not laid out yet
             for (auto& hyperLink : hyperLinks)
             {
@@ -252,7 +252,7 @@ namespace MWGui
     {
         const TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours();
 
-        BookTypesetter::Style* style = typesetter->createStyle("", textColours.normal, false);
+        BookTypesetter::Style* style = typesetter->createStyle({}, textColours.normal, false);
 
         if (topicId)
             style = typesetter->createHotStyle(
@@ -260,7 +260,7 @@ namespace MWGui
         typesetter->write(style, begin, end);
     }
 
-    Message::Message(const std::string& text)
+    Message::Message(std::string_view text)
     {
         mText = text;
     }
@@ -269,7 +269,7 @@ namespace MWGui
         std::map<std::string, std::unique_ptr<Link>>& topicLinks) const
     {
         const MyGUI::Colour& textColour = MWBase::Environment::get().getWindowManager()->getTextColours().notify;
-        BookTypesetter::Style* title = typesetter->createStyle("", textColour, false);
+        BookTypesetter::Style* title = typesetter->createStyle({}, textColour, false);
         typesetter->sectionBreak(9);
         typesetter->write(title, to_utf8_span(mText));
     }
@@ -335,7 +335,8 @@ namespace MWGui
 
     void DialogueWindow::onTradeComplete()
     {
-        addResponse("", MyGUI::LanguageManager::getInstance().replaceTags("#{sBarterDialog5}"));
+        MyGUI::UString message = MyGUI::LanguageManager::getInstance().replaceTags("#{sBarterDialog5}");
+        addResponse({}, message.asUTF8());
     }
 
     bool DialogueWindow::exit()
@@ -611,7 +612,7 @@ namespace MWGui
         for (const auto& text : mHistoryContents)
             text->write(typesetter, &mKeywordSearch, mTopicLinks);
 
-        BookTypesetter::Style* body = typesetter->createStyle("", MyGUI::Colour::White, false);
+        BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::White, false);
 
         typesetter->sectionBreak(9);
         // choices
@@ -716,13 +717,13 @@ namespace MWGui
         mHistory->setPosition(0, static_cast<int>(pos) * -1);
     }
 
-    void DialogueWindow::addResponse(const std::string& title, const std::string& text, bool needMargin)
+    void DialogueWindow::addResponse(std::string_view title, std::string_view text, bool needMargin)
     {
         mHistoryContents.push_back(std::make_unique<Response>(text, title, needMargin));
         updateHistory();
     }
 
-    void DialogueWindow::addMessageBox(const std::string& text)
+    void DialogueWindow::addMessageBox(std::string_view text)
     {
         mHistoryContents.push_back(std::make_unique<Message>(text));
         updateHistory();
diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp
index d427d77f07..45e2578db7 100644
--- a/apps/openmw/mwgui/dialogue.hpp
+++ b/apps/openmw/mwgui/dialogue.hpp
@@ -35,7 +35,7 @@ namespace MWGui
         {
         }
 
-        void addResponse(const std::string& title, const std::string& text) override;
+        void addResponse(std::string_view title, std::string_view text) override;
 
         void updateTopics() const;
     };
@@ -112,7 +112,7 @@ namespace MWGui
 
     struct DialogueText
     {
-        virtual ~DialogueText() {}
+        virtual ~DialogueText() = default;
         virtual void write(BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch,
             std::map<std::string, std::unique_ptr<Link>>& topicLinks) const = 0;
         std::string mText;
@@ -120,7 +120,7 @@ namespace MWGui
 
     struct Response : DialogueText
     {
-        Response(const std::string& text, const std::string& title = "", bool needMargin = true);
+        Response(std::string_view text, std::string_view title = {}, bool needMargin = true);
         void write(BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch,
             std::map<std::string, std::unique_ptr<Link>>& topicLinks) const override;
         void addTopicLink(BookTypesetter::Ptr typesetter, intptr_t topicId, size_t begin, size_t end) const;
@@ -130,7 +130,7 @@ namespace MWGui
 
     struct Message : DialogueText
     {
-        Message(const std::string& text);
+        Message(std::string_view text);
         void write(BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch,
             std::map<std::string, std::unique_ptr<Link>>& topicLinks) const override;
     };
@@ -154,9 +154,9 @@ namespace MWGui
         /// @return true if stale keywords were updated successfully
         bool setKeywords(const std::list<std::string>& keyWord);
 
-        void addResponse(const std::string& title, const std::string& text, bool needMargin = true);
+        void addResponse(std::string_view title, std::string_view text, bool needMargin = true);
 
-        void addMessageBox(const std::string& text);
+        void addMessageBox(std::string_view text);
 
         void onFrame(float dt) override;
         void clear() override { resetReference(); }
diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp
index ece29a220f..bb11e9d47c 100644
--- a/apps/openmw/mwgui/enchantingdialog.cpp
+++ b/apps/openmw/mwgui/enchantingdialog.cpp
@@ -140,7 +140,7 @@ namespace MWGui
 
     void EnchantingDialog::setPtr(const MWWorld::Ptr& ptr)
     {
-        mName->setCaption("");
+        mName->setCaption({});
 
         if (ptr.getClass().isActor())
         {
diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp
index a124f0b8ba..f725801782 100644
--- a/apps/openmw/mwgui/formatting.cpp
+++ b/apps/openmw/mwgui/formatting.cpp
@@ -34,7 +34,7 @@ namespace MWGui::Formatting
             nullptr, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
         mText = Interpreter::fixDefinesBook(mText, interpreterContext);
 
-        Misc::StringUtils::replaceAll(mText, "\r", "");
+        Misc::StringUtils::replaceAll(mText, "\r", {});
 
         // vanilla game does not show any text after the last EOL tag.
         const std::string lowerText = Misc::StringUtils::lowerCase(mText);
@@ -82,9 +82,9 @@ namespace MWGui::Formatting
                 parseTag(mText.substr(tagStart, tagEnd - tagStart));
                 mIndex = tagEnd;
 
-                if (mTagTypes.find(mTag) != mTagTypes.end())
+                if (auto it = mTagTypes.find(mTag); it != mTagTypes.end())
                 {
-                    Events type = mTagTypes.at(mTag);
+                    Events type = it->second;
 
                     if (type == Event_BrTag || type == Event_PTag)
                     {
@@ -290,13 +290,19 @@ namespace MWGui::Formatting
                 {
                     const BookTextParser::Attributes& attr = parser.getAttributes();
 
-                    if (attr.find("src") == attr.end() || attr.find("width") == attr.end()
-                        || attr.find("height") == attr.end())
+                    auto srcIt = attr.find("src");
+                    if (srcIt == attr.end())
+                        continue;
+                    auto widthIt = attr.find("width");
+                    if (widthIt == attr.end())
+                        continue;
+                    auto heightIt = attr.find("height");
+                    if (heightIt == attr.end())
                         continue;
 
-                    std::string src = attr.at("src");
-                    int width = MyGUI::utility::parseInt(attr.at("width"));
-                    int height = MyGUI::utility::parseInt(attr.at("height"));
+                    const std::string& src = srcIt->second;
+                    int width = MyGUI::utility::parseInt(widthIt->second);
+                    int height = MyGUI::utility::parseInt(heightIt->second);
 
                     auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
                     std::string correctedSrc = Misc::ResourceHelpers::correctBookartPath(src, width, height, vfs);
@@ -349,10 +355,11 @@ namespace MWGui::Formatting
 
     void BookFormatter::handleDiv(const BookTextParser::Attributes& attr)
     {
-        if (attr.find("align") == attr.end())
+        auto it = attr.find("align");
+        if (it == attr.end())
             return;
 
-        std::string align = attr.at("align");
+        const std::string& align = it->second;
 
         if (Misc::StringUtils::ciEqual(align, "center"))
             mBlockStyle.mAlign = MyGUI::Align::HCenter;
@@ -364,19 +371,21 @@ namespace MWGui::Formatting
 
     void BookFormatter::handleFont(const BookTextParser::Attributes& attr)
     {
-        if (attr.find("color") != attr.end())
+        auto it = attr.find("color");
+        if (it != attr.end())
         {
-            auto& colorString = attr.at("color");
+            const auto& colorString = it->second;
             unsigned int color = 0;
             std::from_chars(colorString.data(), colorString.data() + colorString.size(), color, 16);
 
             mTextStyle.mColour
                 = MyGUI::Colour((color >> 16 & 0xFF) / 255.f, (color >> 8 & 0xFF) / 255.f, (color & 0xFF) / 255.f);
         }
-        if (attr.find("face") != attr.end())
+        it = attr.find("face");
+        if (it != attr.end())
         {
-            std::string face = attr.at("face");
-            std::string name = Gui::FontLoader::getFontForFace(face);
+            const std::string& face = it->second;
+            std::string name{ Gui::FontLoader::getFontForFace(face) };
 
             mTextStyle.mFont = "Journalbook " + name;
         }
diff --git a/apps/openmw/mwgui/itemview.cpp b/apps/openmw/mwgui/itemview.cpp
index e959847867..ff05a8b2d6 100644
--- a/apps/openmw/mwgui/itemview.cpp
+++ b/apps/openmw/mwgui/itemview.cpp
@@ -91,7 +91,7 @@ namespace MWGui
         mModel->update();
 
         MyGUI::Widget* dragArea = mScrollView->createWidget<MyGUI::Widget>(
-            "", 0, 0, mScrollView->getWidth(), mScrollView->getHeight(), MyGUI::Align::Stretch);
+            {}, 0, 0, mScrollView->getWidth(), mScrollView->getHeight(), MyGUI::Align::Stretch);
         dragArea->setNeedMouseFocus(true);
         dragArea->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemView::onSelectedBackground);
         dragArea->eventMouseWheel += MyGUI::newDelegate(this, &ItemView::onMouseWheelMoved);
diff --git a/apps/openmw/mwgui/itemwidget.cpp b/apps/openmw/mwgui/itemwidget.cpp
index 27895c54d0..49d47a8d54 100644
--- a/apps/openmw/mwgui/itemwidget.cpp
+++ b/apps/openmw/mwgui/itemwidget.cpp
@@ -23,7 +23,7 @@ namespace
         static const int fontHeight = MWBase::Environment::get().getWindowManager()->getFontHeight();
 
         if (count == 1)
-            return "";
+            return {};
 
         // With small text size we can use up to 4 characters, while with large ones - only up to 3.
         if (fontHeight > 16)
@@ -148,11 +148,11 @@ namespace MWGui
         if (ptr.isEmpty())
         {
             if (mFrame)
-                mFrame->setImageTexture("");
+                mFrame->setImageTexture({});
             if (mItemShadow)
-                mItemShadow->setImageTexture("");
-            mItem->setImageTexture("");
-            mText->setCaption("");
+                mItemShadow->setImageTexture({});
+            mItem->setImageTexture({});
+            mText->setCaption({});
             mCurrentIcon.clear();
             mCurrentFrame.clear();
             return;
@@ -175,7 +175,7 @@ namespace MWGui
         else if (state == Barter)
             backgroundTex += "_barter";
 
-        if (backgroundTex != "")
+        if (!backgroundTex.empty())
             backgroundTex += ".dds";
 
         float scale = 1.f;
@@ -210,7 +210,7 @@ namespace MWGui
         if (mFrame && !mCurrentFrame.empty())
         {
             mCurrentFrame.clear();
-            mFrame->setImageTexture("");
+            mFrame->setImageTexture({});
         }
         if (mCurrentIcon != icon)
         {
diff --git a/apps/openmw/mwgui/journalbooks.cpp b/apps/openmw/mwgui/journalbooks.cpp
index d77beef421..5163135cf9 100644
--- a/apps/openmw/mwgui/journalbooks.cpp
+++ b/apps/openmw/mwgui/journalbooks.cpp
@@ -168,8 +168,8 @@ namespace MWGui
     {
         BookTypesetter::Ptr typesetter = createTypesetter();
 
-        BookTypesetter::Style* header = typesetter->createStyle("", MyGUI::Colour(0.60f, 0.00f, 0.00f));
-        BookTypesetter::Style* body = typesetter->createStyle("", MyGUI::Colour::Black);
+        BookTypesetter::Style* header = typesetter->createStyle({}, MyGUI::Colour(0.60f, 0.00f, 0.00f));
+        BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
 
         typesetter->write(header, to_utf8_span("You have no journal entries!"));
         typesetter->lineBreak();
@@ -183,10 +183,10 @@ namespace MWGui
     {
         BookTypesetter::Ptr typesetter = createTypesetter();
 
-        BookTypesetter::Style* header = typesetter->createStyle("", MyGUI::Colour(0.60f, 0.00f, 0.00f));
-        BookTypesetter::Style* body = typesetter->createStyle("", MyGUI::Colour::Black);
+        BookTypesetter::Style* header = typesetter->createStyle({}, MyGUI::Colour(0.60f, 0.00f, 0.00f));
+        BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
 
-        mModel->visitJournalEntries("", AddJournalEntry(typesetter, body, header, true));
+        mModel->visitJournalEntries({}, AddJournalEntry(typesetter, body, header, true));
 
         return typesetter->complete();
     }
@@ -195,8 +195,8 @@ namespace MWGui
     {
         BookTypesetter::Ptr typesetter = createTypesetter();
 
-        BookTypesetter::Style* header = typesetter->createStyle("", MyGUI::Colour(0.60f, 0.00f, 0.00f));
-        BookTypesetter::Style* body = typesetter->createStyle("", MyGUI::Colour::Black);
+        BookTypesetter::Style* header = typesetter->createStyle({}, MyGUI::Colour(0.60f, 0.00f, 0.00f));
+        BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
 
         mModel->visitTopicName(topicId, AddTopicName(typesetter, header));
 
@@ -211,8 +211,8 @@ namespace MWGui
     {
         BookTypesetter::Ptr typesetter = createTypesetter();
 
-        BookTypesetter::Style* header = typesetter->createStyle("", MyGUI::Colour(0.60f, 0.00f, 0.00f));
-        BookTypesetter::Style* body = typesetter->createStyle("", MyGUI::Colour::Black);
+        BookTypesetter::Style* header = typesetter->createStyle({}, MyGUI::Colour(0.60f, 0.00f, 0.00f));
+        BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
 
         AddQuestName addName(typesetter, header);
         addName(to_utf8_span(questName));
@@ -243,7 +243,7 @@ namespace MWGui
         char ch = 'A';
         std::string buffer;
 
-        BookTypesetter::Style* body = typesetter->createStyle("", MyGUI::Colour::Black);
+        BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
         for (int i = 0; i < 26; ++i)
         {
             buffer = "( ";
@@ -272,7 +272,7 @@ namespace MWGui
 
         typesetter->setSectionAlignment(BookTypesetter::AlignCenter);
 
-        BookTypesetter::Style* body = typesetter->createStyle("", MyGUI::Colour::Black);
+        BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black);
 
         int fontHeight = MWBase::Environment::get().getWindowManager()->getFontHeight();
 
@@ -297,7 +297,7 @@ namespace MWGui
             buffer += ch[1];
             buffer += " )";
 
-            Utf8Stream stream((char*)ch);
+            Utf8Stream stream(ch, ch + 2);
             Utf8Stream::UnicodeChar first = stream.peek();
 
             const MWGui::TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours();
diff --git a/apps/openmw/mwgui/levelupdialog.cpp b/apps/openmw/mwgui/levelupdialog.cpp
index 2d0c6d372a..45ba20c597 100644
--- a/apps/openmw/mwgui/levelupdialog.cpp
+++ b/apps/openmw/mwgui/levelupdialog.cpp
@@ -107,7 +107,7 @@ namespace MWGui
     void LevelupDialog::assignCoins()
     {
         resetCoins();
-        for (unsigned int i = 0; i < mSpentAttributes.size(); ++i)
+        for (size_t i = 0; i < mSpentAttributes.size(); ++i)
         {
             MyGUI::ImageBox* image = mCoins[i];
             image->detachFromWidget();
@@ -115,7 +115,7 @@ namespace MWGui
 
             int attribute = mSpentAttributes[i];
 
-            int xdiff = mAttributeMultipliers[attribute]->getCaption() == "" ? 0 : 20;
+            int xdiff = mAttributeMultipliers[attribute]->getCaption().empty() ? 0 : 20;
 
             MyGUI::IntPoint pos = mAttributes[attribute]->getAbsolutePosition() - mAssignWidget->getAbsolutePosition()
                 - MyGUI::IntPoint(22 + xdiff, 0);
@@ -160,14 +160,17 @@ namespace MWGui
 
                 float mult = pcStats.getLevelupAttributeMultiplier(i);
                 mult = std::min(mult, 100 - pcStats.getAttribute(i).getBase());
-                text->setCaption(mult <= 1 ? "" : "x" + MyGUI::utility::toString(mult));
+                if (mult <= 1)
+                    text->setCaption({});
+                else
+                    text->setCaption("x" + MyGUI::utility::toString(mult));
             }
             else
             {
                 mAttributes[i]->setEnabled(false);
                 mAttributeValues[i]->setEnabled(false);
 
-                text->setCaption("");
+                text->setCaption({});
             }
         }
 
@@ -227,10 +230,10 @@ namespace MWGui
         assignCoins();
     }
 
-    std::string LevelupDialog::getLevelupClassImage(
+    std::string_view LevelupDialog::getLevelupClassImage(
         const int combatIncreases, const int magicIncreases, const int stealthIncreases)
     {
-        std::string ret = "acrobat";
+        std::string_view ret = "acrobat";
 
         int total = combatIncreases + magicIncreases + stealthIncreases;
         if (total == 0)
diff --git a/apps/openmw/mwgui/levelupdialog.hpp b/apps/openmw/mwgui/levelupdialog.hpp
index 2f7bf84089..790db888cb 100644
--- a/apps/openmw/mwgui/levelupdialog.hpp
+++ b/apps/openmw/mwgui/levelupdialog.hpp
@@ -40,7 +40,7 @@ namespace MWGui
 
         void setAttributeValues();
 
-        std::string getLevelupClassImage(
+        std::string_view getLevelupClassImage(
             const int combatIncreases, const int magicIncreases, const int stealthIncreases);
     };
 
diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp
index a91ce61ba7..f86fa5164c 100644
--- a/apps/openmw/mwgui/loadingscreen.cpp
+++ b/apps/openmw/mwgui/loadingscreen.cpp
@@ -226,7 +226,7 @@ namespace MWGui
             mSplashImage->setVisible(true);
             mSplashImage->setBackgroundImage(randomSplash, true, stretch);
         }
-        mSceneImage->setBackgroundImage("");
+        mSceneImage->setBackgroundImage({});
         mSceneImage->setVisible(false);
     }
 
@@ -313,7 +313,7 @@ namespace MWGui
         mViewer->getCamera()->addInitialDrawCallback(mCopyFramebufferToTextureCallback);
         mCopyFramebufferToTextureCallback->reset();
 
-        mSplashImage->setBackgroundImage("");
+        mSplashImage->setBackgroundImage({});
         mSplashImage->setVisible(false);
 
         mSceneImage->setRenderItemTexture(mGuiTexture.get());
diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp
index bca819facf..2ca4530b97 100644
--- a/apps/openmw/mwgui/mainmenu.cpp
+++ b/apps/openmw/mwgui/mainmenu.cpp
@@ -218,7 +218,7 @@ namespace MWGui
 
         if (!mButtonBox)
             mButtonBox
-                = mMainWidget->createWidget<MyGUI::Widget>("", MyGUI::IntCoord(0, 0, 0, 0), MyGUI::Align::Default);
+                = mMainWidget->createWidget<MyGUI::Widget>({}, MyGUI::IntCoord(0, 0, 0, 0), MyGUI::Align::Default);
 
         int curH = 0;
 
@@ -250,26 +250,24 @@ namespace MWGui
         buttons.emplace_back("exitgame");
 
         // Create new buttons if needed
-        std::vector<std::string> allButtons{ "return", "newgame", "savegame", "loadgame", "options", "credits",
-            "exitgame" };
-        for (std::string& buttonId : allButtons)
+        for (std::string_view id : { "return", "newgame", "savegame", "loadgame", "options", "credits", "exitgame" })
         {
-            if (mButtons.find(buttonId) == mButtons.end())
+            if (mButtons.find(id) == mButtons.end())
             {
                 Gui::ImageButton* button = mButtonBox->createWidget<Gui::ImageButton>(
                     "ImageBox", MyGUI::IntCoord(0, curH, 0, 0), MyGUI::Align::Default);
+                const std::string& buttonId = mButtons.emplace(id, button).first->first;
                 button->setProperty("ImageHighlighted", "textures\\menu_" + buttonId + "_over.dds");
                 button->setProperty("ImageNormal", "textures\\menu_" + buttonId + ".dds");
                 button->setProperty("ImagePushed", "textures\\menu_" + buttonId + "_pressed.dds");
                 button->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::onButtonClicked);
-                button->setUserData(std::string(buttonId));
-                mButtons[buttonId] = button;
+                button->setUserData(buttonId);
             }
         }
 
         // Start by hiding all buttons
         int maxwidth = 0;
-        for (auto& buttonPair : mButtons)
+        for (const auto& buttonPair : mButtons)
         {
             buttonPair.second->setVisible(false);
             MyGUI::IntSize requested = buttonPair.second->getRequestedSize();
@@ -278,10 +276,11 @@ namespace MWGui
         }
 
         // Now show and position the ones we want
-        for (std::string& buttonId : buttons)
+        for (const std::string& buttonId : buttons)
         {
-            assert(mButtons.find(buttonId) != mButtons.end());
-            Gui::ImageButton* button = mButtons[buttonId];
+            auto it = mButtons.find(buttonId);
+            assert(it != mButtons.end());
+            Gui::ImageButton* button = it->second;
             button->setVisible(true);
 
             // By default, assume that all menu buttons textures should have 64 height.
diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp
index 710a246653..ee6a5cdb16 100644
--- a/apps/openmw/mwgui/mainmenu.hpp
+++ b/apps/openmw/mwgui/mainmenu.hpp
@@ -51,7 +51,7 @@ namespace MWGui
         MyGUI::ImageBox* mVideoBackground;
         VideoWidget* mVideo; // For animated main menus
 
-        std::map<std::string, Gui::ImageButton*> mButtons;
+        std::map<std::string, Gui::ImageButton*, std::less<>> mButtons;
 
         void onButtonClicked(MyGUI::Widget* sender);
         void onNewGameConfirmed();
diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp
index f3d3b346e4..5ba47eae4a 100644
--- a/apps/openmw/mwgui/mapwindow.cpp
+++ b/apps/openmw/mwgui/mapwindow.cpp
@@ -252,7 +252,7 @@ namespace MWGui
         {
             for (auto& entry : mMaps)
             {
-                entry.mFogWidget->setImageTexture("");
+                entry.mFogWidget->setImageTexture({});
                 entry.mFogTexture.reset();
             }
         }
@@ -891,7 +891,7 @@ namespace MWGui
 
         mEditNoteDialog.setVisible(true);
         mEditNoteDialog.showDeleteButton(false);
-        mEditNoteDialog.setText("");
+        mEditNoteDialog.setText({});
     }
 
     void MapWindow::onMapZoomed(MyGUI::Widget* sender, int rel)
@@ -1122,7 +1122,7 @@ namespace MWGui
         if (!destNotes.empty())
         {
             MarkerUserData data(nullptr);
-            data.notes = destNotes;
+            std::swap(data.notes, destNotes);
             data.caption = markerWidget->getUserString("Caption_TextOneLine");
             markerWidget->setUserData(data);
             markerWidget->setUserString("ToolTipType", "MapMarker");
diff --git a/apps/openmw/mwgui/postprocessorhud.cpp b/apps/openmw/mwgui/postprocessorhud.cpp
index f90f96c250..e54704d6d4 100644
--- a/apps/openmw/mwgui/postprocessorhud.cpp
+++ b/apps/openmw/mwgui/postprocessorhud.cpp
@@ -81,7 +81,7 @@ namespace MWGui
 
         mConfigLayout->setVisibleVScroll(true);
 
-        mConfigArea = mConfigLayout->createWidget<MyGUI::Widget>("", {}, MyGUI::Align::Default);
+        mConfigArea = mConfigLayout->createWidget<MyGUI::Widget>({}, {}, MyGUI::Align::Default);
 
         mConfigLayout->eventMouseWheel += MyGUI::newDelegate(this, &PostProcessorHud::notifyMouseWheel);
         mConfigArea->eventMouseWheel += MyGUI::newDelegate(this, &PostProcessorHud::notifyMouseWheel);
diff --git a/apps/openmw/mwgui/resourceskin.cpp b/apps/openmw/mwgui/resourceskin.cpp
index b71355c3e6..ea081dd17a 100644
--- a/apps/openmw/mwgui/resourceskin.cpp
+++ b/apps/openmw/mwgui/resourceskin.cpp
@@ -33,9 +33,9 @@ namespace MWGui
             const std::string basisSkinType = basis->findAttribute("type");
             if (Misc::StringUtils::ciEqual(basisSkinType, "SimpleText"))
                 continue;
+            bool isTileRect = Misc::StringUtils::ciEqual(basisSkinType, "TileRect");
 
-            const std::string offset = basis->findAttribute("offset");
-            if (!offset.empty())
+            if (!basis->findAttribute("offset").empty())
                 continue;
 
             basis->addAttribute("offset", coord);
@@ -45,19 +45,17 @@ namespace MWGui
             {
                 if (state->getName() == "State")
                 {
-                    const std::string stateOffset = state->findAttribute("offset");
-                    if (!stateOffset.empty())
+                    if (!state->findAttribute("offset").empty())
                         continue;
 
                     state->addAttribute("offset", coord);
-                    if (Misc::StringUtils::ciEqual(basisSkinType, "TileRect"))
+                    if (isTileRect)
                     {
                         MyGUI::xml::ElementEnumerator property = state->getElementEnumerator();
                         bool hasTileSize = false;
                         while (property.next("Property"))
                         {
-                            const std::string key = property->findAttribute("key");
-                            if (key != "TileSize")
+                            if (property->findAttribute("key") != "TileSize")
                                 continue;
 
                             hasTileSize = true;
diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp
index 80029aa837..84b7240b2b 100644
--- a/apps/openmw/mwgui/savegamedialog.cpp
+++ b/apps/openmw/mwgui/savegamedialog.cpp
@@ -146,7 +146,7 @@ namespace MWGui
     {
         WindowModal::onOpen();
 
-        mSaveNameEdit->setCaption("");
+        mSaveNameEdit->setCaption({});
         if (mSaving)
             MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveNameEdit);
         else
@@ -154,7 +154,7 @@ namespace MWGui
 
         center();
 
-        mCharacterSelection->setCaption("");
+        mCharacterSelection->setCaption({});
         mCharacterSelection->removeAllItems();
         mCurrentCharacter = nullptr;
         mCurrentSlot = nullptr;
@@ -167,7 +167,7 @@ namespace MWGui
 
         mCurrentCharacter = mgr->getCurrentCharacter();
 
-        std::string directory = Misc::StringUtils::lowerCase(Settings::Manager::getString("character", "Saves"));
+        const std::string& directory = Settings::Manager::getString("character", "Saves");
 
         size_t selectedIndex = MyGUI::ITEM_NONE;
 
@@ -203,9 +203,8 @@ namespace MWGui
 
                 if (mCurrentCharacter == &*it
                     || (!mCurrentCharacter && !mSaving
-                        && directory
-                            == Misc::StringUtils::lowerCase(
-                                Files::pathToUnicodeString(it->begin()->mPath.parent_path().filename()))))
+                        && Misc::StringUtils::ciEqual(
+                            directory, Files::pathToUnicodeString(it->begin()->mPath.parent_path().filename()))))
                 {
                     mCurrentCharacter = &*it;
                     selectedIndex = mCharacterSelection->getItemCount() - 1;
@@ -389,8 +388,8 @@ namespace MWGui
         if (pos == MyGUI::ITEM_NONE || !mCurrentCharacter)
         {
             mCurrentSlot = nullptr;
-            mInfoText->setCaption("");
-            mScreenshot->setImageTexture("");
+            mInfoText->setCaption({});
+            mScreenshot->setImageTexture({});
             return;
         }
 
diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp
index aa37e2bd02..2ac12828a8 100644
--- a/apps/openmw/mwgui/settingswindow.cpp
+++ b/apps/openmw/mwgui/settingswindow.cpp
@@ -107,25 +107,25 @@ namespace
         return MyGUI::utility::toString(xaspect) + " : " + MyGUI::utility::toString(yaspect);
     }
 
-    const char* checkButtonType = "CheckButton";
-    const char* sliderType = "Slider";
+    const std::string_view checkButtonType = "CheckButton";
+    const std::string_view sliderType = "Slider";
 
-    std::string getSettingType(MyGUI::Widget* widget)
+    std::string_view getSettingType(MyGUI::Widget* widget)
     {
         return widget->getUserString("SettingType");
     }
 
-    std::string getSettingName(MyGUI::Widget* widget)
+    std::string_view getSettingName(MyGUI::Widget* widget)
     {
         return widget->getUserString("SettingName");
     }
 
-    std::string getSettingCategory(MyGUI::Widget* widget)
+    std::string_view getSettingCategory(MyGUI::Widget* widget)
     {
         return widget->getUserString("SettingCategory");
     }
 
-    std::string getSettingValueType(MyGUI::Widget* widget)
+    std::string_view getSettingValueType(MyGUI::Widget* widget)
     {
         return widget->getUserString("SettingValueType");
     }
@@ -165,7 +165,7 @@ namespace MWGui
         {
             MyGUI::Widget* current = widgets.current();
 
-            std::string type = getSettingType(current);
+            std::string_view type = getSettingType(current);
             if (type == checkButtonType)
             {
                 const std::string initialValue
@@ -179,7 +179,7 @@ namespace MWGui
             {
                 MyGUI::ScrollBar* scroll = current->castType<MyGUI::ScrollBar>();
                 std::string valueStr;
-                std::string valueType = getSettingValueType(current);
+                std::string_view valueType = getSettingValueType(current);
                 if (valueType == "Float" || valueType == "Integer" || valueType == "Cell")
                 {
                     // TODO: ScrollBar isn't meant for this. should probably use a dedicated FloatSlider widget
@@ -689,7 +689,7 @@ namespace MWGui
         if (getSettingType(scroller) == "Slider")
         {
             std::string valueStr;
-            std::string valueType = getSettingValueType(scroller);
+            std::string_view valueType = getSettingValueType(scroller);
             if (valueType == "Float" || valueType == "Integer" || valueType == "Cell")
             {
                 float value = pos / float(scroller->getScrollRange() - 1);
diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp
index 034ac25227..69eb0fbf46 100644
--- a/apps/openmw/mwgui/spellcreationdialog.cpp
+++ b/apps/openmw/mwgui/spellcreationdialog.cpp
@@ -366,7 +366,7 @@ namespace MWGui
     void SpellCreationDialog::setPtr(const MWWorld::Ptr& actor)
     {
         mPtr = actor;
-        mNameEdit->setCaption("");
+        mNameEdit->setCaption({});
 
         startEditing();
     }
@@ -384,7 +384,7 @@ namespace MWGui
             return;
         }
 
-        if (mNameEdit->getCaption() == "")
+        if (mNameEdit->getCaption().empty())
         {
             MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage10}");
             return;
@@ -700,7 +700,7 @@ namespace MWGui
             params.mIsConstant = mConstantEffect;
 
             MyGUI::Button* button = mUsedEffectsView->createWidget<MyGUI::Button>(
-                "", MyGUI::IntCoord(0, size.height, 0, 24), MyGUI::Align::Default);
+                {}, MyGUI::IntCoord(0, size.height, 0, 24), MyGUI::Align::Default);
             button->setUserData(i);
             button->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellCreationDialog::onEditEffect);
             button->setNeedMouseFocus(true);
diff --git a/apps/openmw/mwgui/spellview.cpp b/apps/openmw/mwgui/spellview.cpp
index 64af057d4d..39aa0eec06 100644
--- a/apps/openmw/mwgui/spellview.cpp
+++ b/apps/openmw/mwgui/spellview.cpp
@@ -100,7 +100,7 @@ namespace MWGui
             if (curType != spell.mType)
             {
                 if (spell.mType == Spell::Type_Power)
-                    addGroup("#{sPowers}", "");
+                    addGroup("#{sPowers}", {});
                 else if (spell.mType == Spell::Type_Spell)
                     addGroup("#{sSpells}", mShowCostColumn ? "#{sCostChance}" : "");
                 else
@@ -246,7 +246,7 @@ namespace MWGui
         groupWidget->setTextAlign(MyGUI::Align::Left);
         groupWidget->setNeedMouseFocus(false);
 
-        if (label2 != "")
+        if (!label2.empty())
         {
             MyGUI::TextBox* groupWidget2 = mScrollView->createWidget<Gui::TextBox>("SandBrightText",
                 MyGUI::IntCoord(0, 0, mScrollView->getWidth(), 24), MyGUI::Align::Left | MyGUI::Align::Top);
diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp
index 50a97c7d91..b136a3cad1 100644
--- a/apps/openmw/mwgui/spellwindow.cpp
+++ b/apps/openmw/mwgui/spellwindow.cpp
@@ -241,7 +241,7 @@ namespace MWGui
         if ((!godmode && stats.isParalyzed()) || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery())
             return;
 
-        mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), ""));
+        mSpellView->setModel(new SpellModel(MWMechanics::getPlayer()));
 
         SpellModel::ModelIndex selected = mSpellView->getModel()->getSelectedIndex();
         if (selected < 0)
diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp
index b016bceaf5..f00de27012 100644
--- a/apps/openmw/mwgui/statswindow.cpp
+++ b/apps/openmw/mwgui/statswindow.cpp
@@ -347,9 +347,12 @@ namespace MWGui
             float mult = PCstats.getLevelupAttributeMultiplier(attribute);
             mult = std::min(mult, 100 - PCstats.getAttribute(attribute).getBase());
             if (mult > 1)
-                detail << (detail.str().empty() ? "" : "\n") << "#{"
-                       << MyGUI::TextIterator::toTagsString(ESM::Attribute::sGmstAttributeIds[attribute]) << "} x"
-                       << MyGUI::utility::toString(mult);
+            {
+                if (!detail.view().empty())
+                    detail << '\n';
+                detail << "#{" << MyGUI::TextIterator::toTagsString(ESM::Attribute::sGmstAttributeIds[attribute])
+                       << "} x" << MyGUI::utility::toString(mult);
+            }
         }
         detailText = MyGUI::LanguageManager::getInstance().replaceTags(detail.str());
 
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index a0ae5942d7..84fb8157a3 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -169,9 +169,9 @@ namespace MWGui
                         return;
                 }
 
-                std::string type = focus->getUserString("ToolTipType");
+                std::string_view type = focus->getUserString("ToolTipType");
 
-                if (type == "")
+                if (type.empty())
                 {
                     return;
                 }
@@ -252,8 +252,8 @@ namespace MWGui
                         int school = MWMechanics::getSpellSchool(spell, player);
                         info.text = "#{sSchool}: " + sSchoolNames[school];
                     }
-                    std::string cost = focus->getUserString("SpellCost");
-                    if (cost != "" && cost != "0")
+                    const std::string& cost = focus->getUserString("SpellCost");
+                    if (!cost.empty() && cost != "0")
                         info.text
                             += MWGui::ToolTips::getValueString(MWMechanics::calcSpellCost(*spell), "#{sCastCost}");
                     info.effects = effects;
@@ -267,7 +267,7 @@ namespace MWGui
 
                     tooltip->setVisible(true);
 
-                    std::map<std::string, std::string> userStrings = focus->getUserStrings();
+                    const auto& userStrings = focus->getUserStrings();
                     for (auto& userStringPair : userStrings)
                     {
                         size_t underscorePos = userStringPair.first.find('_');
@@ -496,7 +496,7 @@ namespace MWGui
 
         if (!info.effects.empty())
         {
-            MyGUI::Widget* effectArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("",
+            MyGUI::Widget* effectArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>({},
                 MyGUI::IntCoord(padding.left, totalSize.height, 300 - padding.left, 300 - totalSize.height),
                 MyGUI::Align::Stretch);
 
@@ -518,7 +518,7 @@ namespace MWGui
 
         if (enchant)
         {
-            MyGUI::Widget* enchantArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("",
+            MyGUI::Widget* enchantArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>({},
                 MyGUI::IntCoord(padding.left, totalSize.height, 300 - padding.left, 300 - totalSize.height),
                 MyGUI::Align::Stretch);
 
@@ -932,7 +932,7 @@ namespace MWGui
 
     void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass)
     {
-        if (playerClass.mName == "")
+        if (playerClass.mName.empty())
             return;
 
         int spec = playerClass.mData.mSpecialization;
diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp
index a42ca35843..980e5b91f0 100644
--- a/apps/openmw/mwgui/tradewindow.cpp
+++ b/apps/openmw/mwgui/tradewindow.cpp
@@ -128,7 +128,7 @@ namespace MWGui
         setTitle(actor.getClass().getName(actor));
 
         onFilterChanged(mFilterAll);
-        mFilterEdit->setCaption("");
+        mFilterEdit->setCaption({});
     }
 
     void TradeWindow::onFrame(float dt)
diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp
index e5f840874d..c83caa0dc5 100644
--- a/apps/openmw/mwgui/travelwindow.cpp
+++ b/apps/openmw/mwgui/travelwindow.cpp
@@ -171,7 +171,7 @@ namespace MWGui
 
         MWBase::Environment::get().getWindowManager()->fadeScreenOut(1);
         ESM::Position pos = *_sender->getUserData<ESM::Position>();
-        const std::string& cellname = _sender->getUserString("Destination");
+        std::string_view cellname = _sender->getUserString("Destination");
         bool interior = _sender->getUserString("interior") == "y";
         if (mPtr.getCell()->isExterior())
         {
diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp
index c13dbd4da1..51d96c4cdd 100644
--- a/apps/openmw/mwgui/widgets.cpp
+++ b/apps/openmw/mwgui/widgets.cpp
@@ -62,7 +62,7 @@ namespace MWGui::Widgets
         {
             if (mSkillId == ESM::Skill::Length)
             {
-                mSkillNameWidget->setCaption("");
+                mSkillNameWidget->setCaption({});
             }
             else
             {
@@ -147,7 +147,7 @@ namespace MWGui::Widgets
         {
             if (mId < 0 || mId >= 8)
             {
-                mAttributeNameWidget->setCaption("");
+                mAttributeNameWidget->setCaption({});
             }
             else
             {
@@ -251,7 +251,7 @@ namespace MWGui::Widgets
             if (spell)
                 mSpellNameWidget->setCaption(spell->mName);
             else
-                mSpellNameWidget->setCaption("");
+                mSpellNameWidget->setCaption({});
         }
     }
 
@@ -371,7 +371,7 @@ namespace MWGui::Widgets
             mTextWidget->setCoord(sIconOffset / 2, mTextWidget->getCoord().top, mTextWidget->getCoord().width,
                 mTextWidget->getCoord().height); // Compensates for the missing image when effect is not known
             mRequestedWidth = mTextWidget->getTextSize().width + sIconOffset;
-            mImageWidget->setImageTexture("");
+            mImageWidget->setImageTexture({});
             return;
         }
 
diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp
index 2d4bffdfb9..20444e5e7e 100644
--- a/apps/openmw/mwgui/windowmanagerimp.cpp
+++ b/apps/openmw/mwgui/windowmanagerimp.cpp
@@ -212,7 +212,7 @@ namespace MWGui
             resourceSystem->getVFS(), mScalingFactor, "mygui", logpath / "MyGUI.log");
 
         mGui = std::make_unique<MyGUI::Gui>();
-        mGui->initialise("");
+        mGui->initialise({});
 
         createTextures();
 
@@ -517,7 +517,7 @@ namespace MWGui
         trackWindow(mPostProcessorHud, makePostprocessorWindowSettingValues());
 
         mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>(
-            "", 0, 0, w, h, MyGUI::Align::Stretch, "InputBlocker");
+            {}, 0, 0, w, h, MyGUI::Align::Stretch, "InputBlocker");
 
         mHud->setVisible(true);
 
@@ -796,7 +796,8 @@ namespace MWGui
     {
         if (getMode() == GM_Dialogue && showInDialogueMode != MWGui::ShowInDialogueMode_Never)
         {
-            mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(toUString(message)));
+            MyGUI::UString text = MyGUI::LanguageManager::getInstance().replaceTags(toUString(message));
+            mDialogueWindow->addMessageBox(text.asUTF8());
         }
         else if (showInDialogueMode != MWGui::ShowInDialogueMode_Only)
         {
diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp
index b5a4c48ad0..0c2b62f821 100644
--- a/components/fontloader/fontloader.cpp
+++ b/components/fontloader/fontloader.cpp
@@ -29,15 +29,13 @@
 
 namespace
 {
-    MyGUI::xml::ElementPtr getProperty(MyGUI::xml::ElementPtr resourceNode, const std::string propertyName)
+    MyGUI::xml::ElementPtr getProperty(MyGUI::xml::ElementPtr resourceNode, std::string_view propertyName)
     {
         MyGUI::xml::ElementPtr propertyNode = nullptr;
         MyGUI::xml::ElementEnumerator propertyIterator = resourceNode->getElementEnumerator();
         while (propertyIterator.next("Property"))
         {
-            std::string key = propertyIterator->findAttribute("key");
-
-            if (key == propertyName)
+            if (propertyIterator->findAttribute("key") == propertyName)
             {
                 propertyNode = propertyIterator.current();
                 break;
@@ -55,15 +53,15 @@ namespace
         MyGUI::xml::ElementEnumerator layersIterator = root->getElementEnumerator();
         while (layersIterator.next("Layer"))
         {
-            std::string name = layersIterator->findAttribute("name");
-
-            if (name == "JournalBooks")
+            if (layersIterator->findAttribute("name") == "JournalBooks")
             {
                 MyGUI::xml::ElementPtr sizeProperty = getProperty(layersIterator.current(), "Size");
-                const std::string& sizeValue
-                    = sizeProperty != nullptr ? sizeProperty->findAttribute("value") : std::string();
-                if (!sizeValue.empty())
-                    return MyGUI::IntSize::parse(sizeValue);
+                if (sizeProperty != nullptr)
+                {
+                    std::string sizeValue = sizeProperty->findAttribute("value");
+                    if (!sizeValue.empty())
+                        return MyGUI::IntSize::parse(sizeValue);
+                }
             }
         }
 
@@ -215,7 +213,7 @@ namespace
         }
     }
 
-    [[noreturn]] void fail(std::istream& stream, const std::string& fileName, const std::string& message)
+    [[noreturn]] void fail(std::istream& stream, std::string_view fileName, std::string_view message)
     {
         std::stringstream error;
         error << "Font loading error: " << message;
@@ -291,7 +289,7 @@ namespace Gui
         MyGUI::IntSize bookSize = getBookSize(layersStream.get());
         float bookScale = osgMyGUI::ScalingLayer::getScaleFactor(bookSize);
 
-        const auto oldDataPath = dataManager->getDataPath("");
+        const auto oldDataPath = dataManager->getDataPath({});
         dataManager->setResourcePath("fonts");
         std::unique_ptr<MyGUI::IDataStream> dataStream(dataManager->getData(fileName));
 
@@ -303,8 +301,7 @@ namespace Gui
         bool valid = false;
         if (resourceNode.next("Resource"))
         {
-            std::string type = resourceNode->findAttribute("type");
-            valid = (type == "ResourceTrueTypeFont");
+            valid = resourceNode->findAttribute("type") == "ResourceTrueTypeFont";
         }
 
         if (valid == false)
@@ -450,7 +447,7 @@ namespace Gui
         defaultHeight->addAttribute("value", fontSize);
         MyGUI::xml::ElementPtr source = root->createChild("Property");
         source->addAttribute("key", "Source");
-        source->addAttribute("value", std::string(bitmapFilename));
+        source->addAttribute("value", bitmapFilename);
         MyGUI::xml::ElementPtr codes = root->createChild("Codes");
 
         for (int i = 0; i < 256; i++)
@@ -532,12 +529,12 @@ namespace Gui
             additional.insert(std::make_pair(84, 0x2122)); // trademark sign
             additional.insert(std::make_pair(45, 0x2212)); // minus sign
 
-            for (std::multimap<int, int>::iterator it = additional.begin(); it != additional.end(); ++it)
+            for (const auto [key, value] : additional)
             {
-                if (it->first != i)
+                if (key != i)
                     continue;
                 code = codes->createChild("Code");
-                code->addAttribute("index", it->second);
+                code->addAttribute("index", value);
                 code->addAttribute("coord",
                     MyGUI::utility::toString(x1) + " " + MyGUI::utility::toString(y1) + " "
                         + MyGUI::utility::toString(w) + " " + MyGUI::utility::toString(h));
@@ -638,10 +635,9 @@ namespace Gui
         return mFontHeight;
     }
 
-    std::string FontLoader::getFontForFace(const std::string& face)
+    std::string_view FontLoader::getFontForFace(std::string_view face)
     {
-        const std::string lowerFace = Misc::StringUtils::lowerCase(face);
-        if (lowerFace == "daedric")
+        if (Misc::StringUtils::ciEqual(face, "daedric"))
             return "ScrollFont";
 
         return "DefaultFont";
diff --git a/components/fontloader/fontloader.hpp b/components/fontloader/fontloader.hpp
index 194c1a54f3..a5cb67b033 100644
--- a/components/fontloader/fontloader.hpp
+++ b/components/fontloader/fontloader.hpp
@@ -31,7 +31,7 @@ namespace Gui
 
         int getFontHeight();
 
-        static std::string getFontForFace(const std::string& face);
+        static std::string_view getFontForFace(std::string_view face);
 
     private:
         ToUTF8::FromType mEncoding;
diff --git a/components/interpreter/defines.cpp b/components/interpreter/defines.cpp
index 6216a5dc67..e7a8e35328 100644
--- a/components/interpreter/defines.cpp
+++ b/components/interpreter/defines.cpp
@@ -171,17 +171,17 @@ namespace
 
 namespace Interpreter
 {
-    std::string fixDefinesDialog(const std::string& text, Context& context)
+    std::string fixDefinesDialog(std::string_view text, Context& context)
     {
         return fixDefinesReal(text, true, context);
     }
 
-    std::string fixDefinesMsgBox(const std::string& text, Context& context)
+    std::string fixDefinesMsgBox(std::string_view text, Context& context)
     {
         return fixDefinesReal(text, false, context);
     }
 
-    std::string fixDefinesBook(const std::string& text, Context& context)
+    std::string fixDefinesBook(std::string_view text, Context& context)
     {
         return fixDefinesReal(text, false, context);
     }
diff --git a/components/interpreter/defines.hpp b/components/interpreter/defines.hpp
index e371c30ed5..3c897cf08a 100644
--- a/components/interpreter/defines.hpp
+++ b/components/interpreter/defines.hpp
@@ -6,9 +6,9 @@
 
 namespace Interpreter
 {
-    std::string fixDefinesDialog(const std::string& text, Context& context);
-    std::string fixDefinesMsgBox(const std::string& text, Context& context);
-    std::string fixDefinesBook(const std::string& text, Context& context);
+    std::string fixDefinesDialog(std::string_view text, Context& context);
+    std::string fixDefinesMsgBox(std::string_view text, Context& context);
+    std::string fixDefinesBook(std::string_view text, Context& context);
 }
 
 #endif
diff --git a/components/resource/imagemanager.cpp b/components/resource/imagemanager.cpp
index 917cdf802f..417b8079be 100644
--- a/components/resource/imagemanager.cpp
+++ b/components/resource/imagemanager.cpp
@@ -55,7 +55,7 @@ namespace Resource
 
     ImageManager::~ImageManager() {}
 
-    bool checkSupported(osg::Image* image, const std::string& filename)
+    bool checkSupported(osg::Image* image)
     {
         switch (image->getPixelFormat())
         {
@@ -83,7 +83,7 @@ namespace Resource
         return true;
     }
 
-    osg::ref_ptr<osg::Image> ImageManager::getImage(const std::string& filename, bool disableFlip)
+    osg::ref_ptr<osg::Image> ImageManager::getImage(std::string_view filename, bool disableFlip)
     {
         const std::string normalized = mVFS->normalizeFilename(filename);
 
@@ -149,7 +149,7 @@ namespace Resource
             osg::ref_ptr<osg::Image> image = result.getImage();
 
             image->setFileName(normalized);
-            if (!checkSupported(image, filename))
+            if (!checkSupported(image))
             {
                 static bool uncompress = (getenv("OPENMW_DECOMPRESS_TEXTURES") != nullptr);
                 if (!uncompress)
diff --git a/components/resource/imagemanager.hpp b/components/resource/imagemanager.hpp
index 32855d40df..ddb2fcc00c 100644
--- a/components/resource/imagemanager.hpp
+++ b/components/resource/imagemanager.hpp
@@ -28,7 +28,7 @@ namespace Resource
 
         /// Create or retrieve an Image
         /// Returns the dummy image if the given image is not found.
-        osg::ref_ptr<osg::Image> getImage(const std::string& filename, bool disableFlip = false);
+        osg::ref_ptr<osg::Image> getImage(std::string_view filename, bool disableFlip = false);
 
         osg::Image* getWarningImage();
 
diff --git a/components/sdlutil/sdlcursormanager.cpp b/components/sdlutil/sdlcursormanager.cpp
index 09e192ba16..aae6c2350a 100644
--- a/components/sdlutil/sdlcursormanager.cpp
+++ b/components/sdlutil/sdlcursormanager.cpp
@@ -66,20 +66,20 @@ namespace SDLUtil
         }
     }
 
-    void SDLCursorManager::cursorChanged(const std::string& name)
+    void SDLCursorManager::cursorChanged(std::string_view name)
     {
         mCurrentCursor = name;
-        _setGUICursor(name);
+        _setGUICursor(mCurrentCursor);
     }
 
-    void SDLCursorManager::_setGUICursor(const std::string& name)
+    void SDLCursorManager::_setGUICursor(std::string_view name)
     {
         auto it = mCursorMap.find(name);
         if (it != mCursorMap.end())
             SDL_SetCursor(it->second);
     }
 
-    void SDLCursorManager::createCursor(const std::string& name, int rotDegrees, osg::Image* image, Uint8 hotspot_x,
+    void SDLCursorManager::createCursor(std::string_view name, int rotDegrees, osg::Image* image, Uint8 hotspot_x,
         Uint8 hotspot_y, int cursorWidth, int cursorHeight)
     {
 #ifndef ANDROID
@@ -128,7 +128,7 @@ namespace SDLUtil
         return SDLUtil::SurfaceUniquePtr(targetSurface, SDL_FreeSurface);
     }
 
-    void SDLCursorManager::_createCursorFromResource(const std::string& name, int rotDegrees, osg::Image* image,
+    void SDLCursorManager::_createCursorFromResource(std::string_view name, int rotDegrees, osg::Image* image,
         Uint8 hotspot_x, Uint8 hotspot_y, int cursorWidth, int cursorHeight)
     {
         if (mCursorMap.find(name) != mCursorMap.end())
@@ -141,7 +141,7 @@ namespace SDLUtil
             // set the cursor and store it for later
             SDL_Cursor* curs = SDL_CreateColorCursor(surface.get(), hotspot_x, hotspot_y);
 
-            mCursorMap.insert(CursorMap::value_type(std::string(name), curs));
+            mCursorMap.emplace(name, curs);
         }
         catch (std::exception& e)
         {
diff --git a/components/sdlutil/sdlcursormanager.hpp b/components/sdlutil/sdlcursormanager.hpp
index 0815ff4f40..5040e85fc0 100644
--- a/components/sdlutil/sdlcursormanager.hpp
+++ b/components/sdlutil/sdlcursormanager.hpp
@@ -27,19 +27,19 @@ namespace SDLUtil
 
         /// \brief Tell the manager that the cursor has changed, giving the
         ///        name of the cursor we changed to ("arrow", "ibeam", etc)
-        virtual void cursorChanged(const std::string& name);
+        virtual void cursorChanged(std::string_view name);
 
-        virtual void createCursor(const std::string& name, int rotDegrees, osg::Image* image, Uint8 hotspot_x,
+        virtual void createCursor(std::string_view name, int rotDegrees, osg::Image* image, Uint8 hotspot_x,
             Uint8 hotspot_y, int cursorWidth, int cursorHeight);
 
     private:
-        void _createCursorFromResource(const std::string& name, int rotDegrees, osg::Image* image, Uint8 hotspot_x,
+        void _createCursorFromResource(std::string_view name, int rotDegrees, osg::Image* image, Uint8 hotspot_x,
             Uint8 hotspot_y, int cursorWidth, int cursorHeight);
         void _putPixel(SDL_Surface* surface, int x, int y, Uint32 pixel);
 
-        void _setGUICursor(const std::string& name);
+        void _setGUICursor(std::string_view name);
 
-        typedef std::map<std::string, SDL_Cursor*> CursorMap;
+        typedef std::map<std::string, SDL_Cursor*, std::less<>> CursorMap;
         CursorMap mCursorMap;
 
         std::string mCurrentCursor;
diff --git a/components/widgets/imagebutton.cpp b/components/widgets/imagebutton.cpp
index fc187a49bc..0eb193aea3 100644
--- a/components/widgets/imagebutton.cpp
+++ b/components/widgets/imagebutton.cpp
@@ -42,7 +42,7 @@ namespace Gui
             mImagePushed = _value;
         else if (_key == "ImageNormal")
         {
-            if (mImageNormal == "")
+            if (mImageNormal.empty())
             {
                 setImageTexture(_value);
             }

From 492e336c0c68a8f29679488ac7cee49a598afa0b Mon Sep 17 00:00:00 2001
From: Evil Eye <malusluminis@hotmail.com>
Date: Sun, 21 May 2023 18:14:12 +0200
Subject: [PATCH 2/4] Use string_view in more UI code

---
 apps/openmw/mwgui/draganddrop.cpp      |  2 +-
 apps/openmw/mwgui/inventorywindow.cpp  |  2 +-
 apps/openmw/mwgui/journalviewmodel.cpp |  8 ++++----
 apps/openmw/mwgui/settingswindow.cpp   |  8 ++++----
 apps/openmw/mwgui/spellview.cpp        |  2 +-
 apps/openmw/mwgui/windowmanagerimp.cpp | 27 +++++++++++++-------------
 components/translation/translation.cpp | 16 +++++++--------
 components/translation/translation.hpp | 10 +++++-----
 components/widgets/list.cpp            | 25 ++++++++++++------------
 components/widgets/list.hpp            |  6 +++---
 components/widgets/tags.cpp            | 18 ++++++++---------
 components/widgets/tags.hpp            |  5 ++---
 12 files changed, 64 insertions(+), 65 deletions(-)

diff --git a/apps/openmw/mwgui/draganddrop.cpp b/apps/openmw/mwgui/draganddrop.cpp
index 626148c8c3..c99e97e37d 100644
--- a/apps/openmw/mwgui/draganddrop.cpp
+++ b/apps/openmw/mwgui/draganddrop.cpp
@@ -47,7 +47,7 @@ namespace MWGui
             playerModel->update();
 
             ItemModel::ModelIndex newIndex = -1;
-            for (unsigned int i = 0; i < playerModel->getItemCount(); ++i)
+            for (size_t i = 0; i < playerModel->getItemCount(); ++i)
             {
                 if (playerModel->getItem(i).mBase == item)
                 {
diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp
index e3f209fa2e..d96db97353 100644
--- a/apps/openmw/mwgui/inventorywindow.cpp
+++ b/apps/openmw/mwgui/inventorywindow.cpp
@@ -779,7 +779,7 @@ namespace MWGui
         if (selected != -1)
             lastId = model.getItem(selected).mBase.getCellRef().getRefId();
         ItemModel::ModelIndex cycled = selected;
-        for (unsigned int i = 0; i < model.getItemCount(); ++i)
+        for (size_t i = 0; i < model.getItemCount(); ++i)
         {
             cycled += incr;
             cycled = (cycled + model.getItemCount()) % model.getItemCount();
diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp
index fd5f7b73c7..57c768aeac 100644
--- a/apps/openmw/mwgui/journalviewmodel.cpp
+++ b/apps/openmw/mwgui/journalviewmodel.cpp
@@ -116,10 +116,10 @@ namespace MWGui
                             std::string link = utf8text.substr(pos_begin + 1, pos_end - pos_begin - 1);
                             const char specialPseudoAsteriskCharacter = 127;
                             std::replace(link.begin(), link.end(), specialPseudoAsteriskCharacter, '*');
-                            std::string topicName = MWBase::Environment::get()
-                                                        .getWindowManager()
-                                                        ->getTranslationDataStorage()
-                                                        .topicStandardForm(link);
+                            std::string_view topicName = MWBase::Environment::get()
+                                                             .getWindowManager()
+                                                             ->getTranslationDataStorage()
+                                                             .topicStandardForm(link);
 
                             std::string displayName = link;
                             while (displayName[displayName.size() - 1] == '*')
diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp
index 2ac12828a8..76ef5c4cdb 100644
--- a/apps/openmw/mwgui/settingswindow.cpp
+++ b/apps/openmw/mwgui/settingswindow.cpp
@@ -472,7 +472,7 @@ namespace MWGui
 
     void SettingsWindow::onResolutionAccept()
     {
-        std::string resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected());
+        const std::string& resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected());
         int resX, resY;
         parseResolution(resX, resY, resStr);
 
@@ -844,7 +844,7 @@ namespace MWGui
             // check if this resolution is supported in fullscreen
             if (mResolutionList->getIndexSelected() != MyGUI::ITEM_NONE)
             {
-                std::string resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected());
+                const std::string& resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected());
                 int resX, resY;
                 parseResolution(resX, resY, resStr);
                 Settings::Manager::setInt("resolution x", "Video", resX);
@@ -853,9 +853,9 @@ namespace MWGui
 
             bool supported = false;
             int fallbackX = 0, fallbackY = 0;
-            for (unsigned int i = 0; i < mResolutionList->getItemCount(); ++i)
+            for (size_t i = 0; i < mResolutionList->getItemCount(); ++i)
             {
-                std::string resStr = mResolutionList->getItemNameAt(i);
+                const std::string& resStr = mResolutionList->getItemNameAt(i);
                 int resX, resY;
                 parseResolution(resX, resY, resStr);
 
diff --git a/apps/openmw/mwgui/spellview.cpp b/apps/openmw/mwgui/spellview.cpp
index 39aa0eec06..b60ec24440 100644
--- a/apps/openmw/mwgui/spellview.cpp
+++ b/apps/openmw/mwgui/spellview.cpp
@@ -162,7 +162,7 @@ namespace MWGui
 
                 // match model against line
                 // if don't match, then major change has happened, so do a full update
-                if (mModel->getItemCount() <= static_cast<unsigned>(spellIndex))
+                if (mModel->getItemCount() <= static_cast<size_t>(spellIndex))
                 {
                     fullUpdateRequired = true;
                     break;
diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp
index 20444e5e7e..4f2979b72b 100644
--- a/apps/openmw/mwgui/windowmanagerimp.cpp
+++ b/apps/openmw/mwgui/windowmanagerimp.cpp
@@ -1096,26 +1096,25 @@ namespace MWGui
 
     void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result)
     {
-        std::string tag(_tag);
+        std::string_view tag = _tag.asUTF8();
 
-        std::string MyGuiPrefix = "setting=";
-        size_t MyGuiPrefixLength = MyGuiPrefix.length();
+        std::string_view MyGuiPrefix = "setting=";
 
-        std::string tokenToFind = "sCell=";
-        size_t tokenLength = tokenToFind.length();
+        std::string_view tokenToFind = "sCell=";
 
-        if (tag.compare(0, MyGuiPrefixLength, MyGuiPrefix) == 0)
+        if (tag.starts_with(MyGuiPrefix))
         {
-            tag = tag.substr(MyGuiPrefixLength, tag.length());
+            tag = tag.substr(MyGuiPrefix.length());
             size_t comma_pos = tag.find(',');
-            std::string settingSection = tag.substr(0, comma_pos);
-            std::string settingTag = tag.substr(comma_pos + 1, tag.length());
+            std::string_view settingSection = tag.substr(0, comma_pos);
+            std::string_view settingTag = tag.substr(comma_pos + 1, tag.length());
 
             _result = Settings::Manager::getString(settingTag, settingSection);
         }
-        else if (tag.compare(0, tokenLength, tokenToFind) == 0)
+        else if (tag.starts_with(tokenToFind))
         {
-            _result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength));
+            std::string_view cellName = mTranslationDataStorage.translateCellName(tag.substr(tokenToFind.length()));
+            _result.assign(cellName.data(), cellName.size());
             _result = MyGUI::TextIterator::toTagsString(_result);
         }
         else if (Gui::replaceTag(tag, _result))
@@ -1125,7 +1124,7 @@ namespace MWGui
         else
         {
             std::vector<std::string> split;
-            Misc::StringUtils::split(tag, split, ":");
+            Misc::StringUtils::split(std::string{ tag }, split, ":");
 
             l10n::Manager& l10nManager = *MWBase::Environment::get().getL10nManager();
 
@@ -1141,7 +1140,7 @@ namespace MWGui
             {
                 Log(Debug::Error) << "Error: WindowManager::onRetrieveTag: no Store set up yet, can not replace '"
                                   << tag << "'";
-                _result = tag;
+                _result.assign(tag.data(), tag.size());
                 return;
             }
             const ESM::GameSetting* setting = mStore->get<ESM::GameSetting>().search(tag);
@@ -1149,7 +1148,7 @@ namespace MWGui
             if (setting && setting->mValue.getType() == ESM::VT_String)
                 _result = setting->mValue.getString();
             else
-                _result = tag;
+                _result.assign(tag.data(), tag.size());
         }
     }
 
diff --git a/components/translation/translation.cpp b/components/translation/translation.cpp
index 30ba12853f..517a60512f 100644
--- a/components/translation/translation.cpp
+++ b/components/translation/translation.cpp
@@ -9,7 +9,7 @@ namespace Translation
     {
     }
 
-    void Storage::loadTranslationData(const Files::Collections& dataFileCollections, const std::string& esmFileName)
+    void Storage::loadTranslationData(const Files::Collections& dataFileCollections, std::string_view esmFileName)
     {
         std::string esmNameNoExtension(Misc::StringUtils::lowerCase(esmFileName));
         // changing the extension
@@ -64,9 +64,9 @@ namespace Translation
         }
     }
 
-    std::string Storage::translateCellName(const std::string& cellName) const
+    std::string_view Storage::translateCellName(std::string_view cellName) const
     {
-        std::map<std::string, std::string>::const_iterator entry = mCellNamesTranslations.find(cellName);
+        auto entry = mCellNamesTranslations.find(cellName);
 
         if (entry == mCellNamesTranslations.end())
             return cellName;
@@ -74,12 +74,12 @@ namespace Translation
         return entry->second;
     }
 
-    std::string Storage::topicID(const std::string& phrase) const
+    std::string_view Storage::topicID(std::string_view phrase) const
     {
-        std::string result = topicStandardForm(phrase);
+        std::string_view result = topicStandardForm(phrase);
 
         // seeking for the topic ID
-        std::map<std::string, std::string>::const_iterator topicIDIterator = mTopicIDs.find(result);
+        auto topicIDIterator = mTopicIDs.find(result);
 
         if (topicIDIterator != mTopicIDs.end())
             result = topicIDIterator->second;
@@ -87,9 +87,9 @@ namespace Translation
         return result;
     }
 
-    std::string Storage::topicStandardForm(const std::string& phrase) const
+    std::string_view Storage::topicStandardForm(std::string_view phrase) const
     {
-        std::map<std::string, std::string>::const_iterator phraseFormsIterator = mPhraseForms.find(phrase);
+        auto phraseFormsIterator = mPhraseForms.find(phrase);
 
         if (phraseFormsIterator != mPhraseForms.end())
             return phraseFormsIterator->second;
diff --git a/components/translation/translation.hpp b/components/translation/translation.hpp
index ee679c4f9b..a7b6087ac7 100644
--- a/components/translation/translation.hpp
+++ b/components/translation/translation.hpp
@@ -11,20 +11,20 @@ namespace Translation
     public:
         Storage();
 
-        void loadTranslationData(const Files::Collections& dataFileCollections, const std::string& esmFileName);
+        void loadTranslationData(const Files::Collections& dataFileCollections, std::string_view esmFileName);
 
-        std::string translateCellName(const std::string& cellName) const;
-        std::string topicID(const std::string& phrase) const;
+        std::string_view translateCellName(std::string_view cellName) const;
+        std::string_view topicID(std::string_view phrase) const;
 
         // Standard form usually means nominative case
-        std::string topicStandardForm(const std::string& phrase) const;
+        std::string_view topicStandardForm(std::string_view phrase) const;
 
         void setEncoder(ToUTF8::Utf8Encoder* encoder);
 
         bool hasTranslation() const;
 
     private:
-        typedef std::map<std::string, std::string> ContainerType;
+        typedef std::map<std::string, std::string, std::less<>> ContainerType;
 
         void loadData(ContainerType& container, const std::string& fileNameNoExtension, const std::string& extension,
             const Files::Collections& dataFileCollections);
diff --git a/components/widgets/list.cpp b/components/widgets/list.cpp
index de1c160288..b4784299a5 100644
--- a/components/widgets/list.cpp
+++ b/components/widgets/list.cpp
@@ -36,7 +36,7 @@ namespace Gui
 
     void MWList::addSeparator()
     {
-        mItems.emplace_back("");
+        mItems.emplace_back(std::string{});
     }
 
     void MWList::adjustSize()
@@ -46,9 +46,9 @@ namespace Gui
 
     void MWList::redraw(bool scrollbarShown)
     {
-        const int _scrollBarWidth = 20; // fetch this from skin?
+        constexpr int _scrollBarWidth = 20; // fetch this from skin?
         const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
-        const int spacing = 3;
+        constexpr int spacing = 3;
         int viewPosition = -mScrollView->getViewOffset().top;
 
         while (mScrollView->getChildCount())
@@ -58,16 +58,16 @@ namespace Gui
 
         mItemHeight = 0;
         int i = 0;
-        for (std::vector<std::string>::const_iterator it = mItems.begin(); it != mItems.end(); ++it)
+        for (const auto& item : mItems)
         {
-            if (*it != "")
+            if (!item.empty())
             {
                 if (mListItemSkin.empty())
                     return;
                 MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(mListItemSkin,
                     MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24),
-                    MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it));
-                button->setCaption((*it));
+                    MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + item);
+                button->setCaption(item);
                 button->getSubWidgetText()->setWordWrap(true);
                 button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left);
                 button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheelMoved);
@@ -115,12 +115,12 @@ namespace Gui
             Base::setPropertyOverride(_key, _value);
     }
 
-    unsigned int MWList::getItemCount()
+    size_t MWList::getItemCount()
     {
-        return static_cast<unsigned int>(mItems.size());
+        return mItems.size();
     }
 
-    std::string MWList::getItemNameAt(unsigned int at)
+    const std::string& MWList::getItemNameAt(size_t at)
     {
         assert(at < mItems.size() && "List item out of bounds");
         return mItems[at];
@@ -134,8 +134,9 @@ namespace Gui
 
     void MWList::removeItem(const std::string& name)
     {
-        assert(std::find(mItems.begin(), mItems.end(), name) != mItems.end());
-        mItems.erase(std::find(mItems.begin(), mItems.end(), name));
+        auto it = std::find(mItems.begin(), mItems.end(), name);
+        assert(it != mItems.end());
+        mItems.erase(it);
     }
 
     void MWList::clear()
diff --git a/components/widgets/list.hpp b/components/widgets/list.hpp
index b9e397f1a8..217fb1370f 100644
--- a/components/widgets/list.hpp
+++ b/components/widgets/list.hpp
@@ -39,9 +39,9 @@ namespace Gui
         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
+        size_t getItemCount();
+        const std::string& getItemNameAt(size_t at); ///< \attention if there are separators, this method will return ""
+                                                     ///< at the place where the separator is
         void clear();
 
         MyGUI::Button* getItemWidget(std::string_view name);
diff --git a/components/widgets/tags.cpp b/components/widgets/tags.cpp
index 488913233c..3fe72480b7 100644
--- a/components/widgets/tags.cpp
+++ b/components/widgets/tags.cpp
@@ -7,17 +7,16 @@
 namespace Gui
 {
 
-    bool replaceTag(const MyGUI::UString& tag, MyGUI::UString& out)
+    bool replaceTag(std::string_view tag, MyGUI::UString& out)
     {
-        std::string fontcolour = "fontcolour=";
-        size_t fontcolourLength = fontcolour.length();
+        std::string_view fontcolour = "fontcolour=";
 
-        std::string fontcolourhtml = "fontcolourhtml=";
-        size_t fontcolourhtmlLength = fontcolourhtml.length();
+        std::string_view fontcolourhtml = "fontcolourhtml=";
 
-        if (tag.compare(0, fontcolourLength, fontcolour) == 0)
+        if (tag.starts_with(fontcolour))
         {
-            std::string fallbackName = "FontColor_color_" + tag.substr(fontcolourLength);
+            std::string fallbackName = "FontColor_color_";
+            fallbackName += tag.substr(fontcolour.length());
             std::string_view str = Fallback::Map::getString(fallbackName);
             if (str.empty())
                 throw std::runtime_error("Unknown fallback name: " + fallbackName);
@@ -36,9 +35,10 @@ namespace Gui
             out = col.print();
             return true;
         }
-        else if (tag.compare(0, fontcolourhtmlLength, fontcolourhtml) == 0)
+        else if (tag.starts_with(fontcolourhtml))
         {
-            std::string fallbackName = "FontColor_color_" + tag.substr(fontcolourhtmlLength);
+            std::string fallbackName = "FontColor_color_";
+            fallbackName += tag.substr(fontcolourhtml.length());
             std::string_view str = Fallback::Map::getString(fallbackName);
             if (str.empty())
                 throw std::runtime_error("Unknown fallback name: " + fallbackName);
diff --git a/components/widgets/tags.hpp b/components/widgets/tags.hpp
index 8999cfa960..26b6e708b9 100644
--- a/components/widgets/tags.hpp
+++ b/components/widgets/tags.hpp
@@ -2,14 +2,13 @@
 #define OPENMW_WIDGETS_TAGS_H
 
 #include <MyGUI_UString.h>
-#include <map>
-#include <string>
+#include <string_view>
 
 namespace Gui
 {
 
     /// Try to replace a tag. Returns true on success and writes the result to \a out.
-    bool replaceTag(const MyGUI::UString& tag, MyGUI::UString& out);
+    bool replaceTag(std::string_view tag, MyGUI::UString& out);
 
 }
 

From 4e05dd3cd36da029051e92203a2f9b20c8f3a472 Mon Sep 17 00:00:00 2001
From: Evil Eye <malusluminis@hotmail.com>
Date: Sun, 21 May 2023 18:21:42 +0200
Subject: [PATCH 3/4] Make FontWrapper conditional

---
 components/widgets/fontwrapper.hpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/components/widgets/fontwrapper.hpp b/components/widgets/fontwrapper.hpp
index e72b99a77b..6dd14596f4 100644
--- a/components/widgets/fontwrapper.hpp
+++ b/components/widgets/fontwrapper.hpp
@@ -1,6 +1,7 @@
 #ifndef OPENMW_WIDGETS_WRAPPER_H
 #define OPENMW_WIDGETS_WRAPPER_H
 
+#include <MyGUI_Prerequest.h>
 #include <components/settings/settings.hpp>
 
 #include <algorithm>
@@ -10,6 +11,7 @@ namespace Gui
     template <class T>
     class FontWrapper : public T
     {
+#if MYGUI_VERSION <= MYGUI_DEFINE_VERSION(3, 4, 2)
     public:
         void setFontName(const std::string& name) override
         {
@@ -22,6 +24,7 @@ namespace Gui
         {
             T::setPropertyOverride(_key, _value);
 
+            // https://github.com/MyGUI/mygui/issues/113
             // There is a bug in MyGUI: when it initializes the FontName property, it reset the font height.
             // We should restore it.
             if (_key == "FontName")
@@ -31,7 +34,7 @@ namespace Gui
         }
 
     private:
-        std::string getFontSize()
+        const std::string& getFontSize()
         {
             // Note: we can not use the FontLoader here, so there is a code duplication a bit.
             static const std::string fontSize
@@ -39,6 +42,7 @@ namespace Gui
             return fontSize;
         }
     };
+#endif
 }
 
 #endif

From ed7b6dc2a7c9f98f4d7b7ec642dc7e6d741b03b3 Mon Sep 17 00:00:00 2001
From: Evil Eye <malusluminis@hotmail.com>
Date: Sun, 21 May 2023 19:53:31 +0200
Subject: [PATCH 4/4] Clarify CharacterCreation::setValue

---
 apps/openmw/mwgui/charactercreation.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp
index 65a1be9c51..257c01d996 100644
--- a/apps/openmw/mwgui/charactercreation.cpp
+++ b/apps/openmw/mwgui/charactercreation.cpp
@@ -107,9 +107,10 @@ namespace MWGui
         if (id.starts_with(prefix) && id.size() == prefix.size() + 1)
         {
             char index = id[prefix.size()];
-            auto attribute = static_cast<ESM::Attribute::AttributeID>(index - '0' - 1);
-            if (attribute >= ESM::Attribute::Strength && attribute < ESM::Attribute::Length)
+            if (index >= '1' && index <= '8')
             {
+                // Match [AttribVal1-AttribVal8] to the corresponding AttributeID values [0-7]
+                auto attribute = static_cast<ESM::Attribute::AttributeID>(index - '0' - 1);
                 mPlayerAttributes[attribute] = value;
                 if (mReviewDialog)
                     mReviewDialog->setAttribute(attribute, value);