From 8ecd0b82a4604d7bc5e34b663c218c9c005dd34b Mon Sep 17 00:00:00 2001
From: Capostrophic <alexdobrohotov@yandex.ru>
Date: Sat, 23 Feb 2019 00:14:07 +0300
Subject: [PATCH] Replace Boost format and replace_all where possible

---
 apps/openmw/mwgui/enchantingdialog.cpp       |  3 +--
 apps/openmw/mwgui/formatting.cpp             |  4 +--
 apps/openmw/mwgui/recharge.cpp               |  5 ++--
 apps/openmw/mwgui/settingswindow.cpp         |  3 ++-
 apps/openmw/mwgui/spellwindow.cpp            |  5 ++--
 apps/openmw/mwgui/tradewindow.cpp            |  3 +--
 apps/openmw/mwmechanics/disease.hpp          |  3 +--
 apps/openmw/mwmechanics/npcstats.cpp         | 14 ++++-------
 apps/openmw/mwmechanics/repair.cpp           |  5 ++--
 apps/openmw/mwmechanics/spellcasting.cpp     |  4 +--
 apps/openmw/mwscript/containerextensions.cpp | 12 ++++-----
 components/misc/stringops.hpp                | 26 ++++++++++++++++++++
 12 files changed, 49 insertions(+), 38 deletions(-)

diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp
index af6567afb..fbdc1bf80 100644
--- a/apps/openmw/mwgui/enchantingdialog.cpp
+++ b/apps/openmw/mwgui/enchantingdialog.cpp
@@ -348,8 +348,7 @@ namespace MWGui
                 if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(item.getCellRef().getRefId(), mPtr))
                 {
                     std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->mValue.getString();
-                    if (msg.find("%s") != std::string::npos)
-                        msg.replace(msg.find("%s"), 2, item.getClass().getName(item));
+                    Misc::StringUtils::replace(msg, "%s", item.getClass().getName(item).c_str(), 2);
                     MWBase::Environment::get().getWindowManager()->messageBox(msg);
 
                     MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, item, mPtr, 1);
diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp
index d4d6a0af5..fca05b05c 100644
--- a/apps/openmw/mwgui/formatting.cpp
+++ b/apps/openmw/mwgui/formatting.cpp
@@ -9,8 +9,6 @@
 #include "../mwbase/environment.hpp"
 #include "../mwbase/windowmanager.hpp"
 
-#include <boost/algorithm/string/replace.hpp>
-
 #include <components/debug/debuglog.hpp>
 #include <components/interpreter/defines.hpp>
 #include <components/misc/stringops.hpp>
@@ -28,7 +26,7 @@ namespace MWGui
             MWScript::InterpreterContext interpreterContext(nullptr, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
             mText = Interpreter::fixDefinesBook(mText, interpreterContext);
 
-            boost::algorithm::replace_all(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);
diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp
index 56bd97d5e..e42db715b 100644
--- a/apps/openmw/mwgui/recharge.cpp
+++ b/apps/openmw/mwgui/recharge.cpp
@@ -1,7 +1,5 @@
 #include "recharge.hpp"
 
-#include <boost/format.hpp>
-
 #include <MyGUI_ScrollView.h>
 #include <MyGUI_Gui.h>
 
@@ -179,7 +177,8 @@ void Recharge::onItemClicked(MyGUI::Widget *sender, const MWWorld::Ptr& item)
     if (gem.getRefData().getCount() == 0)
     {
         std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage51")->mValue.getString();
-        message = boost::str(boost::format(message) % gem.getClass().getName(gem));
+        Misc::StringUtils::replace(message, "%s", gem.getClass().getName(gem).c_str(), 2);
+
         MWBase::Environment::get().getWindowManager()->messageBox(message);
 
         // special case: readd Azura's Star
diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp
index 6e6924f28..c41d43b31 100644
--- a/apps/openmw/mwgui/settingswindow.cpp
+++ b/apps/openmw/mwgui/settingswindow.cpp
@@ -13,6 +13,7 @@
 #include <SDL_video.h>
 
 #include <components/debug/debuglog.hpp>
+#include <components/misc/stringops.hpp>
 #include <components/widgets/sharedstatebutton.hpp>
 #include <components/settings/settings.hpp>
 
@@ -159,7 +160,7 @@ namespace MWGui
             MyGUI::TextBox* textBox;
             getWidget(textBox, labelWidgetName);
             std::string labelCaption = scroller->getUserString("SettingLabelCaption");
-            boost::algorithm::replace_all(labelCaption, "%s", value);
+            Misc::StringUtils::replaceAll(labelCaption, "%s", value.c_str(), 2);
             textBox->setCaptionWithReplacing(labelCaption);
         }
     }
diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp
index 2177e9e2a..254e731d0 100644
--- a/apps/openmw/mwgui/spellwindow.cpp
+++ b/apps/openmw/mwgui/spellwindow.cpp
@@ -1,10 +1,9 @@
 #include "spellwindow.hpp"
 
-#include <boost/format.hpp>
-
 #include <MyGUI_EditBox.h>
 #include <MyGUI_InputManager.h>
 
+#include <components/misc/stringops.hpp>
 #include <components/settings/settings.hpp>
 
 #include "../mwbase/windowmanager.hpp"
@@ -157,7 +156,7 @@ namespace MWGui
             mSpellToDelete = spellId;
             ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
             std::string question = MWBase::Environment::get().getWindowManager()->getGameSettingString("sQuestionDeleteSpell", "Delete %s?");
-            question = boost::str(boost::format(question) % spell->mName);
+            Misc::StringUtils::replace(question, "%s", spell->mName.c_str(), 2);
             dialog->askForConfirmation(question);
             dialog->eventOkClicked.clear();
             dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept);
diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp
index 90698dfc4..b21257eaf 100644
--- a/apps/openmw/mwgui/tradewindow.cpp
+++ b/apps/openmw/mwgui/tradewindow.cpp
@@ -311,8 +311,7 @@ namespace MWGui
             if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(it->mBase.getCellRef().getRefId(), mPtr))
             {
                 std::string msg = gmst.find("sNotifyMessage49")->mValue.getString();
-                if (msg.find("%s") != std::string::npos)
-                    msg.replace(msg.find("%s"), 2, it->mBase.getClass().getName(it->mBase));
+                Misc::StringUtils::replace(msg, "%s", it->mBase.getClass().getName(it->mBase).c_str(), 2);
                 MWBase::Environment::get().getWindowManager()->messageBox(msg);
 
                 MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, it->mBase, mPtr, it->mCount);
diff --git a/apps/openmw/mwmechanics/disease.hpp b/apps/openmw/mwmechanics/disease.hpp
index fec3bdd37..8bca9f9b5 100644
--- a/apps/openmw/mwmechanics/disease.hpp
+++ b/apps/openmw/mwmechanics/disease.hpp
@@ -60,8 +60,7 @@ namespace MWMechanics
 
                 std::string msg = "sMagicContractDisease";
                 msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(msg)->mValue.getString();
-                if (msg.find("%s") != std::string::npos)
-                    msg.replace(msg.find("%s"), 2, spell->mName);
+                Misc::StringUtils::replace(msg, "%s", spell->mName.c_str(), 2);
                 MWBase::Environment::get().getWindowManager()->messageBox(msg);
             }
         }
diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp
index 70c2004f0..df61ee93b 100644
--- a/apps/openmw/mwmechanics/npcstats.cpp
+++ b/apps/openmw/mwmechanics/npcstats.cpp
@@ -2,8 +2,6 @@
 
 #include <iomanip>
 
-#include <boost/format.hpp>
-
 #include <components/esm/loadclas.hpp>
 #include <components/esm/loadgmst.hpp>
 #include <components/esm/loadfact.hpp>
@@ -251,16 +249,14 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
     /// \todo check if character is the player, if levelling is ever implemented for NPCs
     MWBase::Environment::get().getWindowManager()->playSound("skillraise");
 
-    std::stringstream message;
+    std::string message = MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", "");
+    Misc::StringUtils::replace(message, "%s", ("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}").c_str(), 2);
+    Misc::StringUtils::replace(message, "%d", std::to_string(base).c_str(), 2);
 
     if (readBook)
-        message << std::string("#{sBookSkillMessage}\n");
-
-    message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", ""))
-               % std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}")
-               % static_cast<int> (base);
+        message = "#{sBookSkillMessage}\n" + message;
     
-    MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), MWGui::ShowInDialogueMode_Never);
+    MWBase::Environment::get().getWindowManager ()->messageBox(message, MWGui::ShowInDialogueMode_Never);
 
     if (mLevelProgress >= gmst.find("iLevelUpTotal")->mValue.getInteger())
     {
diff --git a/apps/openmw/mwmechanics/repair.cpp b/apps/openmw/mwmechanics/repair.cpp
index 8ab3c605d..28dfab0cd 100644
--- a/apps/openmw/mwmechanics/repair.cpp
+++ b/apps/openmw/mwmechanics/repair.cpp
@@ -1,7 +1,5 @@
 #include "repair.hpp"
 
-#include <boost/format.hpp>
-
 #include <components/misc/rng.hpp>
 
 #include "../mwbase/world.hpp"
@@ -85,8 +83,9 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
 
         std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
                 .find("sNotifyMessage51")->mValue.getString();
+        Misc::StringUtils::replace(message, "%s", mTool.getClass().getName(mTool).c_str(), 2);
 
-        MWBase::Environment::get().getWindowManager()->messageBox((boost::format(message) % mTool.getClass().getName(mTool)).str());
+        MWBase::Environment::get().getWindowManager()->messageBox(message);
 
         // try to find a new tool of the same ID
         for (MWWorld::ContainerStoreIterator iter (store.begin());
diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp
index 2a359cb52..7b406cf9a 100644
--- a/apps/openmw/mwmechanics/spellcasting.cpp
+++ b/apps/openmw/mwmechanics/spellcasting.cpp
@@ -3,8 +3,6 @@
 #include <limits>
 #include <iomanip>
 
-#include <boost/format.hpp>
-
 #include <components/misc/rng.hpp>
 #include <components/settings/settings.hpp>
 
@@ -1015,7 +1013,7 @@ namespace MWMechanics
         {
             // "X has no effect on you"
             std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage50")->mValue.getString();
-            message = boost::str(boost::format(message) % ingredient->mName);
+            Misc::StringUtils::replace(message, "%s", ingredient->mName.c_str(), 2);
             MWBase::Environment::get().getWindowManager()->messageBox(message);
             return false;
         }
diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp
index 7d555e632..47c46d65e 100644
--- a/apps/openmw/mwscript/containerextensions.cpp
+++ b/apps/openmw/mwscript/containerextensions.cpp
@@ -2,8 +2,6 @@
 
 #include <stdexcept>
 
-#include <boost/format.hpp>
-
 #include <MyGUI_LanguageManager.h>
 
 #include <components/debug/debuglog.hpp>
@@ -85,13 +83,13 @@ namespace MWScript
                         if (count == 1)
                         {
                             msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage60}");
-                            msgBox = boost::str(boost::format(msgBox) % itemName);
                         }
                         else
                         {
                             msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage61}");
-                            msgBox = boost::str(boost::format(msgBox) % count % itemName);
+                            Misc::StringUtils::replace(msgBox, "%d", std::to_string(count).c_str(), 2);
                         }
+                        Misc::StringUtils::replace(msgBox, "%s", itemName.c_str(), 2);
                         MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only);
                     }
                 }
@@ -170,16 +168,16 @@ namespace MWScript
                         // The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory
                         std::string msgBox;
 
-                        if(numRemoved > 1)
+                        if (numRemoved > 1)
                         {
                             msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}");
-                            msgBox = boost::str (boost::format(msgBox) % numRemoved % itemName);
+                            Misc::StringUtils::replace(msgBox, "%d", std::to_string(numRemoved).c_str(), 2);
                         }
                         else
                         {
                             msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}");
-                            msgBox = boost::str (boost::format(msgBox) % itemName);
                         }
+                        Misc::StringUtils::replace(msgBox, "%s", itemName.c_str(), 2);
                         MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only);
                     }
                 }
diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp
index 76a585d61..58e1651b8 100644
--- a/components/misc/stringops.hpp
+++ b/components/misc/stringops.hpp
@@ -240,6 +240,32 @@ public:
         }
         return str;
     }
+
+    /** @brief Replaces the first occurrence of a string in another string.
+     *
+     * @param str The string to operate on.
+     * @param what The string to replace.
+     * @param with The replacement string.
+     * @param whatLen The length of the string to replace.
+     * @param withLen The length of the replacement string.
+     *
+     * @return A reference to the string passed in @p str.
+     */
+    static std::string &replace(std::string &str, const char *what, const char *with,
+                                std::size_t whatLen=std::string::npos, std::size_t withLen=std::string::npos)
+    {
+        if (whatLen == std::string::npos)
+            whatLen = strlen(what);
+
+        if (withLen == std::string::npos)
+            withLen = strlen(with);
+
+        std::size_t found;
+        if ((found = str.find(what)) != std::string::npos)
+            str.replace(found, whatLen, with, withLen);
+
+        return str;
+    }
 };
 
 }