diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index ba661093f..d1db582d2 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -52,19 +52,21 @@ namespace MWGui const MWWorld::ESMStore &esmStore = MWBase::Environment::get().getWorld()->getStore(); + std::string filter = Misc::StringUtils::lowerCaseUtf8(mFilter); + for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) { const ESM::Spell* spell = it->first; if (spell->mData.mType != ESM::Spell::ST_Power && spell->mData.mType != ESM::Spell::ST_Spell) continue; - std::string name = spell->mName; + std::string name = Misc::StringUtils::lowerCaseUtf8(spell->mName); - if (name.find(mFilter) == std::string::npos) + if (name.find(filter) == std::string::npos) continue; Spell newSpell; - newSpell.mName = name; + newSpell.mName = spell->mName; if (spell->mData.mType == ESM::Spell::ST_Spell) { newSpell.mType = Spell::Type_Spell; @@ -98,9 +100,9 @@ namespace MWGui if (enchant->mData.mType != ESM::Enchantment::WhenUsed && enchant->mData.mType != ESM::Enchantment::CastOnce) continue; - std::string name = item.getClass().getName(item); + std::string name = Misc::StringUtils::lowerCaseUtf8(item.getClass().getName(item)); - if (name.find(mFilter) == std::string::npos) + if (name.find(filter) == std::string::npos) continue; Spell newSpell; diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 10b4598ee..3fe171e4e 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -217,7 +217,7 @@ namespace MWGui if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery()) return; - mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), mFilterEdit->getCaption())); + mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), "")); SpellModel::ModelIndex selected = 0; for (SpellModel::ModelIndex i = 0; igetModel()->getItemCount()); ++i) diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index 9f4931d72..0fde1c96c 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -6,6 +6,8 @@ #include #include +#include "utf8stream.hpp" + namespace Misc { class StringUtils @@ -56,6 +58,70 @@ public: }; } + static Utf8Stream::UnicodeChar toLowerUtf8(Utf8Stream::UnicodeChar ch) + { + // Russian alphabet + if (ch >= 0x0410 && ch < 0x0430) + return ch += 0x20; + + // Cyrillic IO character + if (ch == 0x0401) + return ch += 0x50; + + // Latin alphabet + if (ch >= 0x41 && ch < 0x60) + return ch += 0x20; + + // Deutch characters + if (ch == 0xc4 || ch == 0xd6 || ch == 0xdc) + return ch += 0x20; + if (ch == 0x1e9e) + return 0xdf; + + // TODO: probably we will need to support characters from other languages + + return ch; + } + + static std::string lowerCaseUtf8(const std::string str) + { + if (str.empty()) + return str; + + // Decode string as utf8 characters, convert to lower case and pack them to string + std::string out; + Utf8Stream stream (str.c_str()); + while (!stream.eof ()) + { + Utf8Stream::UnicodeChar character = toLowerUtf8(stream.peek()); + + if (character <= 0x7f) + out.append(1, static_cast(character)); + else if (character <= 0x7ff) + { + out.append(1, static_cast(0xc0 | ((character >> 6) & 0x1f))); + out.append(1, static_cast(0x80 | (character & 0x3f))); + } + else if (character <= 0xffff) + { + out.append(1, static_cast(0xe0 | ((character >> 12) & 0x0f))); + out.append(1, static_cast(0x80 | ((character >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (character & 0x3f))); + } + else + { + out.append(1, static_cast(0xf0 | ((character >> 18) & 0x07))); + out.append(1, static_cast(0x80 | ((character >> 12) & 0x3f))); + out.append(1, static_cast(0x80 | ((character >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (character & 0x3f))); + } + + stream.consume(); + } + + return out; + } + static bool ciLess(const std::string &x, const std::string &y) { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci()); }