Handle @# links in journal

actorid
scrawl 12 years ago
parent d43adbaa7c
commit 1315432322

@ -11,6 +11,7 @@
#include "../mwbase/world.hpp"
#include "../mwbase/journal.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwdialogue/journalentry.hpp"
#include "keywordsearch.hpp"
@ -100,13 +101,50 @@ struct MWGui::JournalViewModelImpl : JournalViewModel
mutable bool loaded;
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;
void ensureLoaded () const
{
if (!loaded)
{
mModel->ensureKeyWordSearchLoaded ();
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;
}
}
@ -123,22 +161,39 @@ struct MWGui::JournalViewModelImpl : JournalViewModel
ensureLoaded ();
mModel->ensureKeyWordSearchLoaded ();
std::string::const_iterator i = utf8text.begin ();
if (mHyperLinks.size() && MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().hasTranslation())
{
size_t formatted = 0; // points to the first character that is not laid out yet
for (std::map<Range, intptr_t>::const_iterator it = mHyperLinks.begin(); it != mHyperLinks.end(); ++it)
{
intptr_t topicId = it->second;
if (formatted < it->first.first)
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 ();
KeywordSearchT::Match match;
KeywordSearchT::Match match;
while (i != utf8text.end () && mModel->mKeywordSearch.search (i, utf8text.end (), match))
{
if (i != match.mBeg)
visitor (0, i - utf8text.begin (), match.mBeg - utf8text.begin ());
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 ());
visitor (match.mValue, match.mBeg - utf8text.begin (), match.mEnd - utf8text.begin ());
i = match.mEnd;
}
i = match.mEnd;
}
if (i != utf8text.end ())
visitor (0, i - utf8text.begin (), utf8text.size ());
if (i != utf8text.end ())
visitor (0, i - utf8text.begin (), utf8text.size ());
}
}
};

@ -7,6 +7,11 @@
#include <vector>
#include <algorithm> // std::reverse
#include <components/misc/stringops.hpp>
namespace MWGui
{
template <typename string_t, typename value_t>
class KeywordSearch
{
@ -32,6 +37,35 @@ public:
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)
{
for (Point i = beg; i != end; ++i)
@ -160,4 +194,6 @@ private:
std::locale mLocale;
};
}
#endif

Loading…
Cancel
Save