From 7b2737e0e14f815e69da7114dda693cdaea2c341 Mon Sep 17 00:00:00 2001 From: Martin Reddy Date: Thu, 24 Sep 2009 10:41:08 +0000 Subject: EXT-944 EXT-1026: cleaning up my quick fix for these issues. I've now added an explicit LLUrlRegistry::findUrl() method for LLWStrings. This deals with correcting the start/end range for the url appropriately. Now the API can be used without worrying about utf8/utf32 character offset issues. Internal JIRAs: DEV-40127 DEV-39966. --- indra/llui/lltextbox.cpp | 15 +++++++-------- indra/llui/llurlregistry.cpp | 28 ++++++++++++++++++++++++++++ indra/llui/llurlregistry.h | 6 +++++- 3 files changed, 40 insertions(+), 9 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index d6ae9e063e..132bef0296 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -302,11 +302,10 @@ LLWString LLTextBox::getWrappedText(const LLStringExplicit& in_text, F32 max_wid // find the next Url in the text string LLUrlMatch match; - while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(wtext), match)) + while ( LLUrlRegistry::instance().findUrl(wtext, match)) { - LLWString wurl = utf8str_to_wstring(match.getUrl()); - S32 start = wtext.find(wurl); - S32 end = start + wurl.size(); + S32 start = match.getStart(); + S32 end = match.getEnd() + 1; // perform word wrap on the text before the Url final_wtext += wrapText(wtext.substr(0, start), hoffset, line_num, max_width); @@ -579,14 +578,14 @@ void LLTextBox::updateDisplayTextAndSegments() LLWString text = mText.getWString(); // find the next Url in the text string - while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(text), match, + while ( LLUrlRegistry::instance().findUrl(text, match, boost::bind(&LLTextBox::onUrlLabelUpdated, this, _1, _2)) ) { // work out the char offset for the start/end of the url - LLWString wurl = utf8str_to_wstring(match.getUrl()); - S32 url_start = text.find(wurl); - S32 url_end = url_start + wurl.size() - 1; + S32 url_start = match.getStart(); + S32 url_end = match.getEnd(); + // and the char offset for the label in the display text S32 seg_start = mDisplayText.size(); S32 start = seg_start + url_start; S32 end = start + match.getLabel().size(); diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index f2d340deb7..6f5c694b1b 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -162,3 +162,31 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL return false; } + +bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUrlLabelCallback &cb) +{ + // boost::regex_search() only works on char or wchar_t + // types, but wchar_t is only 2-bytes on Win32 (not 4). + // So we use UTF-8 to make this work the same everywhere. + std::string utf8_text = wstring_to_utf8str(text); + if (findUrl(utf8_text, match, cb)) + { + // we cannot blindly return the start/end offsets from + // the UTF-8 string because it is a variable-length + // character encoding, so we need to update the start + // and end values to be correct for the wide string. + LLWString wurl = utf8str_to_wstring(match.getUrl()); + S32 start = text.find(wurl); + if (start == std::string::npos) + { + return false; + } + S32 end = start + wurl.size() - 1; + + match.setValues(start, end, match.getUrl(), match.getLabel(), + match.getTooltip(), match.getIcon(), + match.getMenuName(), match.getLocation()); + return true; + } + return false; +} diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 84b033036c..85e934e4b5 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -37,10 +37,10 @@ #include "llurlentry.h" #include "llurlmatch.h" #include "llsingleton.h" +#include "llstring.h" #include #include -#include /// This default callback for findUrl() simply ignores any label updates void LLUrlRegistryNullCallback(const std::string &url, const std::string &label); @@ -77,6 +77,10 @@ public: bool findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback); + /// a slightly less efficient version of findUrl for wide strings + bool findUrl(const LLWString &text, LLUrlMatch &match, + const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback); + private: LLUrlRegistry(); friend class LLSingleton; -- cgit v1.2.3