mirror of
https://github.com/TES3MP/TES3MP.git
synced 2025-09-30 16:45:17 -04:00
Handle @# links in journal
This commit is contained in:
parent
d43adbaa7c
commit
1315432322
@ -11,6 +11,7 @@
|
|||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/journal.hpp"
|
#include "../mwbase/journal.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwdialogue/journalentry.hpp"
|
#include "../mwdialogue/journalentry.hpp"
|
||||||
|
|
||||||
#include "keywordsearch.hpp"
|
#include "keywordsearch.hpp"
|
||||||
@ -100,13 +101,50 @@ struct MWGui::JournalViewModelImpl : JournalViewModel
|
|||||||
mutable bool loaded;
|
mutable bool loaded;
|
||||||
mutable std::string utf8text;
|
mutable std::string utf8text;
|
||||||
|
|
||||||
|
typedef std::pair<size_t, size_t> Range;
|
||||||
|
|
||||||
|
// hyperlinks in @link# notation
|
||||||
|
mutable std::map<Range, intptr_t> mHyperLinks;
|
||||||
|
|
||||||
virtual std::string getText () const = 0;
|
virtual std::string getText () const = 0;
|
||||||
|
|
||||||
void ensureLoaded () const
|
void ensureLoaded () const
|
||||||
{
|
{
|
||||||
if (!loaded)
|
if (!loaded)
|
||||||
{
|
{
|
||||||
|
mModel->ensureKeyWordSearchLoaded ();
|
||||||
|
|
||||||
utf8text = getText ();
|
utf8text = getText ();
|
||||||
|
|
||||||
|
size_t pos_begin, pos_end;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
pos_begin = utf8text.find('@');
|
||||||
|
if (pos_begin != std::string::npos)
|
||||||
|
pos_end = utf8text.find('#', pos_begin);
|
||||||
|
|
||||||
|
if (pos_begin != std::string::npos && pos_end != std::string::npos)
|
||||||
|
{
|
||||||
|
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 displayName = link;
|
||||||
|
while (displayName[displayName.size()-1] == '*')
|
||||||
|
displayName.erase(displayName.size()-1, 1);
|
||||||
|
|
||||||
|
utf8text.replace(pos_begin, pos_end+1-pos_begin, displayName);
|
||||||
|
|
||||||
|
intptr_t value;
|
||||||
|
if (mModel->mKeywordSearch.containsKeyword(topicName, value))
|
||||||
|
mHyperLinks[std::make_pair(pos_begin, pos_begin+displayName.size())] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,22 +161,39 @@ struct MWGui::JournalViewModelImpl : JournalViewModel
|
|||||||
ensureLoaded ();
|
ensureLoaded ();
|
||||||
mModel->ensureKeyWordSearchLoaded ();
|
mModel->ensureKeyWordSearchLoaded ();
|
||||||
|
|
||||||
std::string::const_iterator i = utf8text.begin ();
|
if (mHyperLinks.size() && MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().hasTranslation())
|
||||||
|
|
||||||
KeywordSearchT::Match match;
|
|
||||||
|
|
||||||
while (i != utf8text.end () && mModel->mKeywordSearch.search (i, utf8text.end (), match))
|
|
||||||
{
|
{
|
||||||
if (i != match.mBeg)
|
size_t formatted = 0; // points to the first character that is not laid out yet
|
||||||
visitor (0, i - utf8text.begin (), match.mBeg - utf8text.begin ());
|
for (std::map<Range, intptr_t>::const_iterator it = mHyperLinks.begin(); it != mHyperLinks.end(); ++it)
|
||||||
|
{
|
||||||
visitor (match.mValue, match.mBeg - utf8text.begin (), match.mEnd - utf8text.begin ());
|
intptr_t topicId = it->second;
|
||||||
|
if (formatted < it->first.first)
|
||||||
i = match.mEnd;
|
visitor (0, formatted, it->first.first);
|
||||||
|
visitor (topicId, it->first.first, it->first.second);
|
||||||
|
formatted = it->first.second;
|
||||||
|
}
|
||||||
|
if (formatted < utf8text.size())
|
||||||
|
visitor (0, formatted, utf8text.size());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string::const_iterator i = utf8text.begin ();
|
||||||
|
|
||||||
if (i != utf8text.end ())
|
KeywordSearchT::Match match;
|
||||||
visitor (0, i - utf8text.begin (), utf8text.size ());
|
|
||||||
|
while (i != utf8text.end () && mModel->mKeywordSearch.search (i, utf8text.end (), match))
|
||||||
|
{
|
||||||
|
if (i != match.mBeg)
|
||||||
|
visitor (0, i - utf8text.begin (), match.mBeg - utf8text.begin ());
|
||||||
|
|
||||||
|
visitor (match.mValue, match.mBeg - utf8text.begin (), match.mEnd - utf8text.begin ());
|
||||||
|
|
||||||
|
i = match.mEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != utf8text.end ())
|
||||||
|
visitor (0, i - utf8text.begin (), utf8text.size ());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm> // std::reverse
|
#include <algorithm> // std::reverse
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
|
|
||||||
template <typename string_t, typename value_t>
|
template <typename string_t, typename value_t>
|
||||||
class KeywordSearch
|
class KeywordSearch
|
||||||
{
|
{
|
||||||
@ -32,6 +37,35 @@ public:
|
|||||||
mRoot.mKeyword.clear ();
|
mRoot.mKeyword.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool containsKeyword (string_t keyword, value_t& value)
|
||||||
|
{
|
||||||
|
typename Entry::childen_t::iterator current;
|
||||||
|
typename Entry::childen_t::iterator next;
|
||||||
|
|
||||||
|
current = mRoot.mChildren.find (std::tolower (*keyword.begin(), mLocale));
|
||||||
|
if (current == mRoot.mChildren.end())
|
||||||
|
return false;
|
||||||
|
else if (current->second.mKeyword.size() && Misc::StringUtils::ciEqual(current->second.mKeyword, keyword))
|
||||||
|
{
|
||||||
|
value = current->second.mValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Point i = ++keyword.begin(); i != keyword.end(); ++i)
|
||||||
|
{
|
||||||
|
next = current->second.mChildren.find(std::tolower (*i, mLocale));
|
||||||
|
if (next == current->second.mChildren.end())
|
||||||
|
return false;
|
||||||
|
if (Misc::StringUtils::ciEqual(next->second.mKeyword, keyword))
|
||||||
|
{
|
||||||
|
value = next->second.mValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool search (Point beg, Point end, Match & match)
|
bool search (Point beg, Point end, Match & match)
|
||||||
{
|
{
|
||||||
for (Point i = beg; i != end; ++i)
|
for (Point i = beg; i != end; ++i)
|
||||||
@ -160,4 +194,6 @@ private:
|
|||||||
std::locale mLocale;
|
std::locale mLocale;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user