summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rwxr-xr-xindra/llui/llbadgeowner.cpp45
-rwxr-xr-xindra/llui/llbadgeowner.h8
-rwxr-xr-xindra/llui/llbutton.cpp2
-rwxr-xr-xindra/llui/llchatentry.cpp10
-rwxr-xr-xindra/llui/llfloater.cpp2
-rwxr-xr-xindra/llui/llfloater.h2
-rwxr-xr-xindra/llui/llfolderview.cpp42
-rwxr-xr-xindra/llui/llfolderview.h2
-rwxr-xr-xindra/llui/llfolderviewmodel.h33
-rwxr-xr-xindra/llui/llkeywords.cpp508
-rwxr-xr-xindra/llui/llkeywords.h119
-rwxr-xr-xindra/llui/lllineeditor.cpp1
-rwxr-xr-xindra/llui/llmenubutton.cpp1
-rwxr-xr-xindra/llui/llmenugl.cpp1
-rwxr-xr-xindra/llui/llmenugl.h17
-rwxr-xr-xindra/llui/llnotifications.cpp1
-rwxr-xr-xindra/llui/llnotifications.h8
-rw-r--r--indra/llui/llnotificationslistener.cpp27
-rwxr-xr-xindra/llui/llscrolllistctrl.cpp1
-rwxr-xr-xindra/llui/lltabcontainer.cpp21
-rwxr-xr-xindra/llui/lltextbase.cpp59
-rwxr-xr-xindra/llui/lltextbase.h42
-rwxr-xr-xindra/llui/lltexteditor.cpp133
-rwxr-xr-xindra/llui/lltexteditor.h56
-rwxr-xr-xindra/llui/lltextutil.cpp4
-rwxr-xr-xindra/llui/lltextutil.h2
-rwxr-xr-xindra/llui/lltoolbar.cpp1
-rwxr-xr-xindra/llui/lltooltip.cpp3
-rwxr-xr-xindra/llui/llurlregistry.cpp11
-rwxr-xr-xindra/llui/llurlregistry.h4
-rwxr-xr-xindra/llui/llxuiparser.cpp2
31 files changed, 617 insertions, 551 deletions
diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp
index 1860a05edd..55e64bb940 100755
--- a/indra/llui/llbadgeowner.cpp
+++ b/indra/llui/llbadgeowner.cpp
@@ -35,8 +35,9 @@
//
LLBadgeOwner::LLBadgeOwner(LLHandle< LLView > viewHandle)
- : mBadge(NULL)
- , mBadgeOwnerView(viewHandle)
+ : mHasBadgeHolderParent(false),
+ mBadge(NULL),
+ mBadgeOwnerView(viewHandle)
{
}
@@ -45,31 +46,12 @@ void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p)
if (!p.equals(LLUICtrlFactory::getDefaultParams<LLBadge>()))
{
mBadge = createBadge(p);
- }
-}
-
-void LLBadgeOwner::setBadgeLabel(const LLStringExplicit& label)
-{
- if (mBadge == NULL)
- {
- mBadge = createBadge(LLUICtrlFactory::getDefaultParams<LLBadge>());
-
- addBadgeToParentPanel();
- }
-
- if (mBadge)
- {
- mBadge->setLabel(label);
-
- //
- // Push the badge to the front so it renders on top
- //
-
- LLView * parent = mBadge->getParent();
+ mHasBadgeHolderParent = false;
- if (parent)
+ LLView * owner_view = mBadgeOwnerView.get();
+ if (owner_view)
{
- parent->sendChildToFront(mBadge);
+ mBadge->addToView(owner_view);
}
}
}
@@ -82,10 +64,8 @@ void LLBadgeOwner::setBadgeVisibility(bool visible)
}
}
-bool LLBadgeOwner::addBadgeToParentPanel()
+void LLBadgeOwner::addBadgeToParentHolder()
{
- bool badge_added = false;
-
LLView * owner_view = mBadgeOwnerView.get();
if (mBadge && owner_view)
@@ -110,16 +90,9 @@ bool LLBadgeOwner::addBadgeToParentPanel()
if (badge_holder)
{
- badge_added = badge_holder->addBadge(mBadge);
- }
- else
- {
- // Badge parent is fallback badge owner if no valid holder exists in the hierarchy
- badge_added = mBadge->addToView(owner_view);
+ mHasBadgeHolderParent = badge_holder->addBadge(mBadge);
}
}
-
- return badge_added;
}
LLBadge* LLBadgeOwner::createBadge(const LLBadge::Params& p)
diff --git a/indra/llui/llbadgeowner.h b/indra/llui/llbadgeowner.h
index 8d03e30645..53c2de95c8 100755
--- a/indra/llui/llbadgeowner.h
+++ b/indra/llui/llbadgeowner.h
@@ -41,11 +41,9 @@ public:
LLBadgeOwner(LLHandle< LLView > viewHandle);
void initBadgeParams(const LLBadge::Params& p);
- bool addBadgeToParentPanel();
+ void addBadgeToParentHolder();
- bool badgeHasParent() const { return (mBadge && mBadge->getParent()); }
-
- void setBadgeLabel(const LLStringExplicit& label);
+ bool hasBadgeHolderParent() const { return mHasBadgeHolderParent; };
void setBadgeVisibility(bool visible);
private:
@@ -53,7 +51,7 @@ private:
LLBadge* createBadge(const LLBadge::Params& p);
private:
-
+ bool mHasBadgeHolderParent;
LLBadge* mBadge;
LLHandle< LLView > mBadgeOwnerView;
};
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 093d91d44d..ce8383857c 100755
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -384,7 +384,7 @@ BOOL LLButton::postBuild()
{
autoResize();
- addBadgeToParentPanel();
+ addBadgeToParentHolder();
return LLUICtrl::postBuild();
}
diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp
index c04b70eb64..dac001afab 100755
--- a/indra/llui/llchatentry.cpp
+++ b/indra/llui/llchatentry.cpp
@@ -51,6 +51,7 @@ LLChatEntry::LLChatEntry(const Params& p)
mCurrentHistoryLine = mLineHistory.begin();
mAutoIndent = false;
+ keepSelectionOnReturn(true);
}
LLChatEntry::~LLChatEntry()
@@ -179,15 +180,6 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
{
BOOL handled = FALSE;
- // In the case of a chat entry, pressing RETURN when something is selected
- // should NOT erase the selection (unlike a notecard, for example)
- if (key == KEY_RETURN)
- {
- endOfDoc();
- startSelection();
- endSelection();
- }
-
LLTextEditor::handleSpecialKey(key, mask);
switch(key)
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 62c923f6f0..3dbc9a5902 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1634,7 +1634,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
// virtual
-void LLFloater::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
+void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key)
{
LLMultiFloater* hostp = getHost();
if (hostp)
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 199db85747..ef7c6180d2 100755
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -311,7 +311,7 @@ public:
/*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override
void setFrontmost(BOOL take_focus = TRUE);
- virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
+ virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
// Defaults to false.
virtual BOOL canSaveAs() const { return FALSE; }
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 53f2e15ed0..cca26f335a 100755
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -227,10 +227,11 @@ LLFolderView::LLFolderView(const Params& p)
mStatusTextBox = LLUICtrlFactory::create<LLTextBox> (text_p);
mStatusTextBox->setFollowsLeft();
mStatusTextBox->setFollowsTop();
- //addChild(mStatusTextBox);
+ addChild(mStatusTextBox);
// make the popup menu available
+ llassert(LLMenuGL::sMenuContainer != NULL);
LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
if (!menu)
{
@@ -629,6 +630,8 @@ bool LLFolderView::startDrag()
void LLFolderView::commitRename( const LLSD& data )
{
finishRenamingItem();
+ arrange( NULL, NULL );
+
}
void LLFolderView::draw()
@@ -701,8 +704,9 @@ void LLFolderView::finishRenamingItem( void )
closeRenamer();
+ // This is moved to an inventory observer in llinventorybridge.cpp, to handle updating after operation completed in AISv3 (SH-4611).
// List is re-sorted alphabetically, so scroll to make sure the selected item is visible.
- scrollToShowSelection();
+ //scrollToShowSelection();
}
void LLFolderView::closeRenamer( void )
@@ -1126,18 +1130,18 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
if((mSelectedItems.size() > 0) && mScrollContainer)
{
LLFolderViewItem* last_selected = getCurSelectedItem();
+ BOOL shift_select = mask & MASK_SHIFT;
+ // don't shift select down to children of folders (they are implicitly selected through parent)
+ LLFolderViewItem* next = last_selected->getNextOpenNode(!shift_select);
- if (!mKeyboardSelection)
+ if (!mKeyboardSelection || (!shift_select && (!next || next == last_selected)))
{
setSelection(last_selected, FALSE, TRUE);
mKeyboardSelection = TRUE;
}
- LLFolderViewItem* next = NULL;
- if (mask & MASK_SHIFT)
+ if (shift_select)
{
- // don't shift select down to children of folders (they are implicitly selected through parent)
- next = last_selected->getNextOpenNode(FALSE);
if (next)
{
if (next->isSelected())
@@ -1154,7 +1158,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
}
else
{
- next = last_selected->getNextOpenNode();
if( next )
{
if (next == last_selected)
@@ -1190,18 +1193,18 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
if((mSelectedItems.size() > 0) && mScrollContainer)
{
LLFolderViewItem* last_selected = mSelectedItems.back();
+ BOOL shift_select = mask & MASK_SHIFT;
+ // don't shift select down to children of folders (they are implicitly selected through parent)
+ LLFolderViewItem* prev = last_selected->getPreviousOpenNode(!shift_select);
- if (!mKeyboardSelection)
+ if (!mKeyboardSelection || (!shift_select && prev == this))
{
setSelection(last_selected, FALSE, TRUE);
mKeyboardSelection = TRUE;
}
- LLFolderViewItem* prev = NULL;
- if (mask & MASK_SHIFT)
+ if (shift_select)
{
- // don't shift select down to children of folders (they are implicitly selected through parent)
- prev = last_selected->getPreviousOpenNode(FALSE);
if (prev)
{
if (prev->isSelected())
@@ -1218,7 +1221,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
}
else
{
- prev = last_selected->getPreviousOpenNode();
if( prev )
{
if (prev == this)
@@ -1606,19 +1608,21 @@ void LLFolderView::update()
return;
}
- if (getFolderViewModel()->getFilter().isModified() && getFolderViewModel()->getFilter().isNotDefault())
+ LLFolderViewFilter& filter_object = getFolderViewModel()->getFilter();
+
+ if (filter_object.isModified() && filter_object.isNotDefault())
{
mNeedsAutoSelect = TRUE;
}
// Filter to determine visibility before arranging
- filter(getFolderViewModel()->getFilter());
+ filter(filter_object);
// Clear the modified setting on the filter only if the filter finished after running the filter process
// Note: if the filter count has timed out, that means the filter halted before completing the entire set of items
- if (getFolderViewModel()->getFilter().isModified() && (!getFolderViewModel()->getFilter().isTimedOut()))
+ if (filter_object.isModified() && (!filter_object.isTimedOut()))
{
- getFolderViewModel()->getFilter().clearModified();
+ filter_object.clearModified();
}
// automatically show matching items, and select first one if we had a selection
@@ -1637,7 +1641,7 @@ void LLFolderView::update()
// Open filtered folders for folder views with mAutoSelectOverride=TRUE.
// Used by LLPlacesFolderView.
- if (getFolderViewModel()->getFilter().showAllResults())
+ if (filter_object.showAllResults())
{
// these are named variables to get around gcc not binding non-const references to rvalues
// and functor application is inherently non-const to allow for stateful functors
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index f188fdd0dc..08e0a6220a 100755
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -235,7 +235,7 @@ public:
virtual S32 notify(const LLSD& info) ;
bool useLabelSuffix() { return mUseLabelSuffix; }
- void updateMenu();
+ virtual void updateMenu();
// Note: We may eventually have to move that method up the hierarchy to LLFolderViewItem.
LLHandle<LLFolderView> getHandle() const { return getDerivedHandle<LLFolderView>(); }
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index c665dce509..8d98363c5f 100755
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -393,27 +393,36 @@ template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename
class LLFolderViewModel : public LLFolderViewModelCommon
{
public:
- LLFolderViewModel(){}
- virtual ~LLFolderViewModel() {}
-
typedef SORT_TYPE SortType;
typedef ITEM_TYPE ItemType;
typedef FOLDER_TYPE FolderType;
typedef FILTER_TYPE FilterType;
- virtual SortType& getSorter() { return mSorter; }
- virtual const SortType& getSorter() const { return mSorter; }
- virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); }
+ LLFolderViewModel(SortType* sorter, FilterType* filter)
+ : mSorter(sorter),
+ mFilter(filter)
+ {}
- virtual FilterType& getFilter() { return mFilter; }
- virtual const FilterType& getFilter() const { return mFilter; }
- virtual void setFilter(const FilterType& filter) { mFilter = filter; }
+ virtual ~LLFolderViewModel()
+ {
+ delete mSorter;
+ mSorter = NULL;
+ delete mFilter;
+ mFilter = NULL;
+ }
+
+ virtual SortType& getSorter() { return *mSorter; }
+ virtual const SortType& getSorter() const { return *mSorter; }
+ virtual void setSorter(const SortType& sorter) { mSorter = new SortType(sorter); requestSortAll(); }
+
+ virtual FilterType& getFilter() { return *mFilter; }
+ virtual const FilterType& getFilter() const { return *mFilter; }
+ virtual void setFilter(const FilterType& filter) { mFilter = new FilterType(filter); }
// By default, we assume the content is available. If a network fetch mechanism is implemented for the model,
// this method needs to be overloaded and return the relevant fetch status.
virtual bool contentsReady() { return true; }
-
struct ViewModelCompare
{
ViewModelCompare(const SortType& sorter)
@@ -445,8 +454,8 @@ public:
}
protected:
- SortType mSorter;
- FilterType mFilter;
+ SortType* mSorter;
+ FilterType* mFilter;
};
#endif // LLFOLDERVIEWMODEL_H
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index fcd7b274e8..75773d7dfd 100755
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llkeywords.cpp
* @brief Keyword list for LSL
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,49 +30,48 @@
#include <fstream>
#include "llkeywords.h"
+#include "llsdserialize.h"
#include "lltexteditor.h"
#include "llstl.h"
-#include <boost/tokenizer.hpp>
-
-const U32 KEYWORD_FILE_CURRENT_VERSION = 2;
-inline BOOL LLKeywordToken::isHead(const llwchar* s) const
+inline bool LLKeywordToken::isHead(const llwchar* s) const
{
// strncmp is much faster than string compare
- BOOL res = TRUE;
+ bool res = true;
const llwchar* t = mToken.c_str();
S32 len = mToken.size();
for (S32 i=0; i<len; i++)
{
if (s[i] != t[i])
{
- res = FALSE;
+ res = false;
break;
}
}
return res;
}
-LLKeywords::LLKeywords() : mLoaded(FALSE)
-{
-}
-
-inline BOOL LLKeywordToken::isTail(const llwchar* s) const
+inline bool LLKeywordToken::isTail(const llwchar* s) const
{
- BOOL res = TRUE;
+ bool res = true;
const llwchar* t = mDelimiter.c_str();
S32 len = mDelimiter.size();
for (S32 i=0; i<len; i++)
{
if (s[i] != t[i])
{
- res = FALSE;
+ res = false;
break;
}
}
return res;
}
+LLKeywords::LLKeywords()
+: mLoaded(false)
+{
+}
+
LLKeywords::~LLKeywords()
{
std::for_each(mWordTokenMap.begin(), mWordTokenMap.end(), DeletePairedPointer());
@@ -83,180 +82,307 @@ LLKeywords::~LLKeywords()
mDelimiterTokenList.clear();
}
-BOOL LLKeywords::loadFromFile( const std::string& filename )
+// Add the token as described
+void LLKeywords::addToken(LLKeywordToken::ETokenType type,
+ const std::string& key_in,
+ const LLColor4& color,
+ const std::string& tool_tip_in,
+ const std::string& delimiter_in)
{
- mLoaded = FALSE;
-
- ////////////////////////////////////////////////////////////
- // File header
-
- const S32 BUFFER_SIZE = 1024;
- char buffer[BUFFER_SIZE]; /* Flawfinder: ignore */
-
- llifstream file;
- file.open(filename); /* Flawfinder: ignore */
- if( file.fail() )
+ std::string tip_text = tool_tip_in;
+ LLStringUtil::replaceString(tip_text, "\\n", "\n" );
+ LLStringUtil::replaceString(tip_text, "\t", " " );
+ if (tip_text.empty())
{
- LL_INFOS() << "LLKeywords::loadFromFile() Unable to open file: " << filename << LL_ENDL;
- return mLoaded;
+ tip_text = "[no info]";
}
+ LLWString tool_tip = utf8str_to_wstring(tip_text);
- // Identifying string
- file >> buffer;
- if( strcmp( buffer, "llkeywords" ) )
- {
- LL_INFOS() << filename << " does not appear to be a keyword file" << LL_ENDL;
- return mLoaded;
- }
-
- // Check file version
- file >> buffer;
- U32 version_num;
- file >> version_num;
- if( strcmp(buffer, "version") || version_num != (U32)KEYWORD_FILE_CURRENT_VERSION )
+ LLWString key = utf8str_to_wstring(key_in);
+ LLWString delimiter = utf8str_to_wstring(delimiter_in);
+ switch(type)
{
- LL_INFOS() << filename << " does not appear to be a version " << KEYWORD_FILE_CURRENT_VERSION << " keyword file" << LL_ENDL;
- return mLoaded;
- }
+ case LLKeywordToken::TT_CONSTANT:
+ case LLKeywordToken::TT_CONTROL:
+ case LLKeywordToken::TT_EVENT:
+ case LLKeywordToken::TT_FUNCTION:
+ case LLKeywordToken::TT_LABEL:
+ case LLKeywordToken::TT_SECTION:
+ case LLKeywordToken::TT_TYPE:
+ case LLKeywordToken::TT_WORD:
+ mWordTokenMap[key] = new LLKeywordToken(type, color, key, tool_tip, LLWStringUtil::null);
+ break;
- // start of line (SOL)
- std::string SOL_COMMENT("#");
- std::string SOL_WORD("[word ");
- std::string SOL_LINE("[line ");
- std::string SOL_ONE_SIDED_DELIMITER("[one_sided_delimiter ");
- std::string SOL_TWO_SIDED_DELIMITER("[two_sided_delimiter ");
- std::string SOL_DOUBLE_QUOTATION_MARKS("[double_quotation_marks ");
+ case LLKeywordToken::TT_LINE:
+ mLineTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip, LLWStringUtil::null));
+ break;
- LLColor3 cur_color( 1, 0, 0 );
- LLKeywordToken::TOKEN_TYPE cur_type = LLKeywordToken::WORD;
+ case LLKeywordToken::TT_TWO_SIDED_DELIMITER:
+ case LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS:
+ case LLKeywordToken::TT_ONE_SIDED_DELIMITER:
+ mDelimiterTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip, delimiter));
+ break;
- while (!file.eof())
- {
- buffer[0] = 0;
- file.getline( buffer, BUFFER_SIZE );
- std::string line(buffer);
- if( line.find(SOL_COMMENT) == 0 )
- {
- continue;
- }
- else if( line.find(SOL_WORD) == 0 )
- {
- cur_color = readColor( line.substr(SOL_WORD.size()) );
- cur_type = LLKeywordToken::WORD;
- continue;
- }
- else if( line.find(SOL_LINE) == 0 )
- {
- cur_color = readColor( line.substr(SOL_LINE.size()) );
- cur_type = LLKeywordToken::LINE;
- continue;
- }
- else if( line.find(SOL_TWO_SIDED_DELIMITER) == 0 )
- {
- cur_color = readColor( line.substr(SOL_TWO_SIDED_DELIMITER.size()) );
- cur_type = LLKeywordToken::TWO_SIDED_DELIMITER;
- continue;
- }
- else if( line.find(SOL_DOUBLE_QUOTATION_MARKS) == 0 )
- {
- cur_color = readColor( line.substr(SOL_DOUBLE_QUOTATION_MARKS.size()) );
- cur_type = LLKeywordToken::DOUBLE_QUOTATION_MARKS;
- continue;
- }
- else if( line.find(SOL_ONE_SIDED_DELIMITER) == 0 )
- {
- cur_color = readColor( line.substr(SOL_ONE_SIDED_DELIMITER.size()) );
- cur_type = LLKeywordToken::ONE_SIDED_DELIMITER;
- continue;
- }
+ default:
+ llassert(0);
+ }
+}
- std::string token_buffer( line );
- LLStringUtil::trim(token_buffer);
-
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep_word("", " \t");
- tokenizer word_tokens(token_buffer, sep_word);
- tokenizer::iterator token_word_iter = word_tokens.begin();
+std::string LLKeywords::getArguments(LLSD& arguments)
+{
+ std::string argString = "";
- if( !token_buffer.empty() && token_word_iter != word_tokens.end() )
+ if (arguments.isArray())
+ {
+ U32 argsCount = arguments.size();
+ LLSD::array_iterator arrayIt = arguments.beginArray();
+ for ( ; arrayIt != arguments.endArray(); ++arrayIt)
{
- // first word is the keyword or a left delimiter
- std::string keyword = (*token_word_iter);
- LLStringUtil::trim(keyword);
-
- // second word may be a right delimiter
- std::string delimiter;
- if (cur_type == LLKeywordToken::TWO_SIDED_DELIMITER)
+ LLSD& args = (*arrayIt);
+ if (args.isMap())
{
- while (delimiter.length() == 0 && ++token_word_iter != word_tokens.end())
+ LLSD::map_iterator argsIt = args.beginMap();
+ for ( ; argsIt != args.endMap(); ++argsIt)
{
- delimiter = *token_word_iter;
- LLStringUtil::trim(delimiter);
+ argString += argsIt->second.get("type").asString() + " " + argsIt->first;
+ if (argsCount-- > 1)
+ {
+ argString += ", ";
+ }
}
}
- else if (cur_type == LLKeywordToken::DOUBLE_QUOTATION_MARKS)
+ else
{
- // Closing delimiter is identical to the opening one.
- delimiter = keyword;
+ LL_WARNS("SyntaxLSL") << "Argument array comtains a non-map element!" << LL_ENDL;
}
+ }
+ }
+ else if (!arguments.isUndefined())
+ {
+ LL_WARNS("SyntaxLSL") << "Not an array! Invalid arguments LLSD passed to function." << arguments << LL_ENDL;
+ }
+ return argString;
+}
- // following words are tooltip
- std::string tool_tip;
- while (++token_word_iter != word_tokens.end())
- {
- tool_tip += (*token_word_iter);
- }
- LLStringUtil::trim(tool_tip);
-
- if( !tool_tip.empty() )
+std::string LLKeywords::getAttribute(const std::string& key)
+{
+ attribute_iterator_t it = mAttributes.find(key);
+ return (it != mAttributes.end()) ? it->second : "";
+}
+
+LLColor4 LLKeywords::getColorGroup(const std::string& key_in)
+{
+ std::string color_group = "ScriptText";
+ if (key_in == "functions")
+ {
+ color_group = "SyntaxLslFunction";
+ }
+ else if (key_in == "controls")
+ {
+ color_group = "SyntaxLslControlFlow";
+ }
+ else if (key_in == "events")
+ {
+ color_group = "SyntaxLslEvent";
+ }
+ else if (key_in == "types")
+ {
+ color_group = "SyntaxLslDataType";
+ }
+ else if (key_in == "misc-flow-label")
+ {
+ color_group = "SyntaxLslControlFlow";
+ }
+ else if (key_in =="deprecated")
+ {
+ color_group = "SyntaxLslDeprecated";
+ }
+ else if (key_in =="god-mode")
+ {
+ color_group = "SyntaxLslGodMode";
+ }
+ else if (key_in == "constants"
+ || key_in == "constants-integer"
+ || key_in == "constants-float"
+ || key_in == "constants-string"
+ || key_in == "constants-key"
+ || key_in == "constants-rotation"
+ || key_in == "constants-vector")
+ {
+ color_group = "SyntaxLslConstant";
+ }
+ else
+ {
+ LL_WARNS("SyntaxLSL") << "Color key '" << key_in << "' not recognized." << LL_ENDL;
+ }
+
+ return LLUIColorTable::instance().getColor(color_group);
+}
+
+void LLKeywords::initialize(LLSD SyntaxXML)
+{
+ mSyntax = SyntaxXML;
+ mLoaded = true;
+}
+
+void LLKeywords::processTokens()
+{
+ if (!mLoaded)
+ {
+ return;
+ }
+
+ // Add 'standard' stuff: Quotes, Comments, Strings, Labels, etc. before processing the LLSD
+ std::string delimiter;
+ addToken(LLKeywordToken::TT_LABEL, "@", getColorGroup("misc-flow-label"), "Label\nTarget for jump statement", delimiter );
+ addToken(LLKeywordToken::TT_ONE_SIDED_DELIMITER, "//", LLUIColorTable::instance().getColor("SyntaxLslComment"), "Comment (single-line)\nNon-functional commentary or disabled code", delimiter );
+ addToken(LLKeywordToken::TT_TWO_SIDED_DELIMITER, "/*", LLUIColorTable::instance().getColor("SyntaxLslComment"), "Comment (multi-line)\nNon-functional commentary or disabled code", "*/" );
+ addToken(LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS, "\"", LLUIColorTable::instance().getColor("SyntaxLslStringLiteral"), "String literal", "\"" );
+
+ LLSD::map_iterator itr = mSyntax.beginMap();
+ for ( ; itr != mSyntax.endMap(); ++itr)
+ {
+ if (itr->first == "llsd-lsl-syntax-version")
+ {
+ // Skip over version key.
+ }
+ else
+ {
+ if (itr->second.isMap())
{
- // Replace : with \n for multi-line tool tips.
- LLStringUtil::replaceChar( tool_tip, ':', '\n' );
- addToken(cur_type, keyword, cur_color, tool_tip, delimiter );
+ processTokensGroup(itr->second, itr->first);
}
else
{
- addToken(cur_type, keyword, cur_color, LLStringUtil::null, delimiter );
+ LL_WARNS("LSL-Tokens-Processing") << "Map for " + itr->first + " entries is missing! Ignoring." << LL_ENDL;
}
}
}
-
- file.close();
-
- mLoaded = TRUE;
- return mLoaded;
+ LL_INFOS("SyntaxLSL") << "Finished processing tokens." << LL_ENDL;
}
-// Add the token as described
-void LLKeywords::addToken(LLKeywordToken::TOKEN_TYPE type,
- const std::string& key_in,
- const LLColor3& color,
- const std::string& tool_tip_in,
- const std::string& delimiter_in)
+void LLKeywords::processTokensGroup(const LLSD& tokens, const std::string& group)
{
- LLWString key = utf8str_to_wstring(key_in);
- LLWString tool_tip = utf8str_to_wstring(tool_tip_in);
- LLWString delimiter = utf8str_to_wstring(delimiter_in);
- switch(type)
+ LLColor4 color;
+ LLColor4 color_group;
+ LLColor4 color_deprecated = getColorGroup("deprecated");
+ LLColor4 color_god_mode = getColorGroup("god-mode");
+
+ LLKeywordToken::ETokenType token_type = LLKeywordToken::TT_UNKNOWN;
+ // If a new token type is added here, it must also be added to the 'addToken' method
+ if (group == "constants")
{
- case LLKeywordToken::WORD:
- mWordTokenMap[key] = new LLKeywordToken(type, color, key, tool_tip, LLWStringUtil::null);
- break;
+ token_type = LLKeywordToken::TT_CONSTANT;
+ }
+ else if (group == "controls")
+ {
+ token_type = LLKeywordToken::TT_CONTROL;
+ }
+ else if (group == "events")
+ {
+ token_type = LLKeywordToken::TT_EVENT;
+ }
+ else if (group == "functions")
+ {
+ token_type = LLKeywordToken::TT_FUNCTION;
+ }
+ else if (group == "label")
+ {
+ token_type = LLKeywordToken::TT_LABEL;
+ }
+ else if (group == "types")
+ {
+ token_type = LLKeywordToken::TT_TYPE;
+ }
- case LLKeywordToken::LINE:
- mLineTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip, LLWStringUtil::null));
- break;
+ color_group = getColorGroup(group);
+ LL_INFOS("SyntaxLSL") << "Group: '" << group << "', using color: '" << color_group << "'" << LL_ENDL;
- case LLKeywordToken::TWO_SIDED_DELIMITER:
- case LLKeywordToken::DOUBLE_QUOTATION_MARKS:
- case LLKeywordToken::ONE_SIDED_DELIMITER:
- mDelimiterTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip, delimiter));
- break;
+ if (tokens.isMap())
+ {
+ LLSD::map_const_iterator outer_itr = tokens.beginMap();
+ for ( ; outer_itr != tokens.endMap(); ++outer_itr )
+ {
+ if (outer_itr->second.isMap())
+ {
+ mAttributes.clear();
+ LLSD arguments = LLSD();
+ LLSD::map_const_iterator inner_itr = outer_itr->second.beginMap();
+ for ( ; inner_itr != outer_itr->second.endMap(); ++inner_itr )
+ {
+ if (inner_itr->first == "arguments")
+ {
+ if (inner_itr->second.isArray())
+ {
+ arguments = inner_itr->second;
+ }
+ }
+ else if (!inner_itr->second.isMap() && !inner_itr->second.isArray())
+ {
+ mAttributes[inner_itr->first] = inner_itr->second.asString();
+ }
+ else
+ {
+ LL_WARNS("SyntaxLSL") << "Not a valid attribute: " << inner_itr->first << LL_ENDL;
+ }
+ }
- default:
- llassert(0);
+ std::string tooltip = "";
+ switch (token_type)
+ {
+ case LLKeywordToken::TT_CONSTANT:
+ color_group = getColorGroup(group + "-" + getAttribute("type"));
+ tooltip = "Type: " + getAttribute("type") + ", Value: " + getAttribute("value");
+ break;
+ case LLKeywordToken::TT_EVENT:
+ tooltip = outer_itr->first + "(" + getArguments(arguments) + ")";
+ break;
+ case LLKeywordToken::TT_FUNCTION:
+ tooltip = getAttribute("return") + " " + outer_itr->first + "(" + getArguments(arguments) + ");";
+ tooltip.append("\nEnergy: ");
+ tooltip.append(getAttribute("energy").empty() ? "0.0" : getAttribute("energy"));
+ if (!getAttribute("sleep").empty())
+ {
+ tooltip += ", Sleep: " + getAttribute("sleep");
+ }
+ default:
+ break;
+ }
+
+ if (!getAttribute("tooltip").empty())
+ {
+ if (!tooltip.empty())
+ {
+ tooltip.append("\n");
+ }
+ tooltip.append(getAttribute("tooltip"));
+ }
+
+ color = getAttribute("deprecated") == "true" ? color_deprecated : color_group;
+
+ if (getAttribute("god-mode") == "true")
+ {
+ color = color_god_mode;
+ }
+
+ addToken(token_type, outer_itr->first, color, tooltip);
+ }
+ }
+ }
+ else if (tokens.isArray()) // Currently nothing should need this, but it's here for completeness
+ {
+ LL_INFOS("SyntaxLSL") << "Curious, shouldn't be an array here; adding all using color " << color << LL_ENDL;
+ for (S32 count = 0; count < tokens.size(); ++count)
+ {
+ addToken(token_type, tokens[count], color, "");
+ }
+ }
+ else
+ {
+ LL_WARNS("SyntaxLSL") << "Invalid map/array passed: '" << tokens << "'" << LL_ENDL;
}
}
+
LLKeywords::WStringMapIndex::WStringMapIndex(const WStringMapIndex& other)
{
if(other.mOwner)
@@ -276,15 +402,19 @@ LLKeywords::WStringMapIndex::WStringMapIndex(const LLWString& str)
copyData(str.data(), str.size());
}
-LLKeywords::WStringMapIndex::WStringMapIndex(const llwchar *start, size_t length):
-mData(start), mLength(length), mOwner(false)
+LLKeywords::WStringMapIndex::WStringMapIndex(const llwchar *start, size_t length)
+: mData(start)
+, mLength(length)
+, mOwner(false)
{
}
LLKeywords::WStringMapIndex::~WStringMapIndex()
{
- if(mOwner)
+ if (mOwner)
+ {
delete[] mData;
+ }
}
void LLKeywords::WStringMapIndex::copyData(const llwchar *start, size_t length)
@@ -301,13 +431,13 @@ bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &o
{
// NOTE: Since this is only used to organize a std::map, it doesn't matter if it uses correct collate order or not.
// The comparison only needs to strictly order all possible strings, and be stable.
-
+
bool result = false;
const llwchar* self_iter = mData;
const llwchar* self_end = mData + mLength;
const llwchar* other_iter = other.mData;
const llwchar* other_end = other.mData + other.mLength;
-
+
while(true)
{
if(other_iter >= other_end)
@@ -322,7 +452,7 @@ bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &o
{
// self is shorter than other.
result = true;
- break;
+ break;
}
else if(*self_iter != *other_iter)
{
@@ -334,20 +464,8 @@ bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &o
self_iter++;
other_iter++;
}
-
- return result;
-}
-LLColor3 LLKeywords::readColor( const std::string& s )
-{
- F32 r, g, b;
- r = g = b = 0.0f;
- S32 values_read = sscanf(s.c_str(), "%f, %f, %f]", &r, &g, &b );
- if( values_read != 3 )
- {
- LL_INFOS() << " poorly formed color in keyword file" << LL_ENDL;
- }
- return LLColor3( r, g, b );
+ return result;
}
LLTrace::BlockTimerStatHandle FTM_SYNTAX_COLORING("Syntax Coloring");
@@ -363,10 +481,10 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
{
return;
}
-
+
S32 text_len = wtext.size() + 1;
- seg_list->push_back( new LLNormalTextSegment( defaultColor, 0, text_len, editor ) );
+ seg_list->push_back( new LLNormalTextSegment( defaultColor, 0, text_len, editor ) );
const llwchar* base = wtext.c_str();
const llwchar* cur = base;
@@ -396,7 +514,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
continue;
}
- // cur is now at the first non-whitespace character of a new line
+ // cur is now at the first non-whitespace character of a new line
// Line start tokens
{
@@ -414,7 +532,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
cur++;
}
S32 seg_end = cur - base;
-
+
//create segments from seg_start to seg_end
insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor);
line_done = TRUE; // to break out of second loop.
@@ -459,14 +577,14 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
seg_start = cur - base;
cur += cur_delimiter->getLengthHead();
-
- LLKeywordToken::TOKEN_TYPE type = cur_delimiter->getType();
- if( type == LLKeywordToken::TWO_SIDED_DELIMITER || type == LLKeywordToken::DOUBLE_QUOTATION_MARKS )
+
+ LLKeywordToken::ETokenType type = cur_delimiter->getType();
+ if( type == LLKeywordToken::TT_TWO_SIDED_DELIMITER || type == LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS )
{
while( *cur && !cur_delimiter->isTail(cur))
{
// Check for an escape sequence.
- if (type == LLKeywordToken::DOUBLE_QUOTATION_MARKS && *cur == '\\')
+ if (type == LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS && *cur == '\\')
{
// Count the number of backslashes.
S32 num_backslashes = 0;
@@ -513,7 +631,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
}
else
{
- llassert( cur_delimiter->getType() == LLKeywordToken::ONE_SIDED_DELIMITER );
+ llassert( cur_delimiter->getType() == LLKeywordToken::TT_ONE_SIDED_DELIMITER );
// Left side is the delimiter. Right side is eol or eof.
while( *cur && ('\n' != *cur) )
{
@@ -555,11 +673,11 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
S32 seg_start = cur - base;
S32 seg_end = seg_start + seg_len;
- // LL_INFOS() << "Seg: [" << word.c_str() << "]" << LL_ENDL;
+ // llinfos << "Seg: [" << word.c_str() << "]" << llendl;
insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor);
}
- cur += seg_len;
+ cur += seg_len;
continue;
}
}
@@ -575,7 +693,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
void LLKeywords::insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, const LLColor4 &defaultColor, LLTextEditor& editor )
{
std::string::size_type pos = wtext.find('\n',seg_start);
-
+
while (pos!=-1 && pos < (std::string::size_type)seg_end)
{
if (pos!=seg_start)
@@ -622,10 +740,10 @@ void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSe
#ifdef _DEBUG
void LLKeywords::dump()
{
- LL_INFOS() << "LLKeywords" << LL_ENDL;
+ llinfos << "LLKeywords" << llendl;
- LL_INFOS() << "LLKeywords::sWordTokenMap" << LL_ENDL;
+ llinfos << "LLKeywords::sWordTokenMap" << llendl;
word_token_map_t::iterator word_token_iter = mWordTokenMap.begin();
while( word_token_iter != mWordTokenMap.end() )
{
@@ -634,7 +752,7 @@ void LLKeywords::dump()
++word_token_iter;
}
- LL_INFOS() << "LLKeywords::sLineTokenList" << LL_ENDL;
+ llinfos << "LLKeywords::sLineTokenList" << llendl;
for (token_list_t::iterator iter = mLineTokenList.begin();
iter != mLineTokenList.end(); ++iter)
{
@@ -643,7 +761,7 @@ void LLKeywords::dump()
}
- LL_INFOS() << "LLKeywords::sDelimiterTokenList" << LL_ENDL;
+ llinfos << "LLKeywords::sDelimiterTokenList" << llendl;
for (token_list_t::iterator iter = mDelimiterTokenList.begin();
iter != mDelimiterTokenList.end(); ++iter)
{
@@ -654,12 +772,12 @@ void LLKeywords::dump()
void LLKeywordToken::dump()
{
- LL_INFOS() << "[" <<
+ llinfos << "[" <<
mColor.mV[VX] << ", " <<
mColor.mV[VY] << ", " <<
mColor.mV[VZ] << "] [" <<
wstring_to_utf8str(mToken) << "]" <<
- LL_ENDL;
+ llendl;
}
#endif // DEBUG
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index ac34015393..18e2ed06c5 100755
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llkeywords.h
* @brief Keyword list for LSL
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -28,8 +28,10 @@
#define LL_LLKEYWORDS_H
+#include "lldir.h"
#include "llstring.h"
#include "v3color.h"
+#include "v4color.h"
#include <map>
#include <list>
#include <deque>
@@ -41,26 +43,35 @@ typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
class LLKeywordToken
{
public:
- /**
+ /**
* @brief Types of tokens/delimters being parsed.
*
* @desc Tokens/delimiters that need to be identified/highlighted. All are terminated if an EOF is encountered.
- * - WORD are keywords in the normal sense, i.e. constants, events, etc.
- * - LINE are for entire lines (currently only flow control labels use this).
- * - ONE_SIDED_DELIMITER are for open-ended delimiters which are terminated by EOL.
- * - TWO_SIDED_DELIMITER are for delimiters that end with a different delimiter than they open with.
- * - DOUBLE_QUOTATION_MARKS are for delimiting areas using the same delimiter to open and close.
+ * - TT_WORD are keywords in the normal sense, i.e. constants, events, etc.
+ * - TT_LINE are for entire lines (currently only flow control labels use this).
+ * - TT_ONE_SIDED_DELIMITER are for open-ended delimiters which are terminated by EOL.
+ * - TT_TWO_SIDED_DELIMITER are for delimiters that end with a different delimiter than they open with.
+ * - TT_DOUBLE_QUOTATION_MARKS are for delimiting areas using the same delimiter to open and close.
*/
- enum TOKEN_TYPE
+ typedef enum e_token_type
{
- WORD,
- LINE,
- TWO_SIDED_DELIMITER,
- ONE_SIDED_DELIMITER,
- DOUBLE_QUOTATION_MARKS
- };
-
- LLKeywordToken( TOKEN_TYPE type, const LLColor3& color, const LLWString& token, const LLWString& tool_tip, const LLWString& delimiter )
+ TT_UNKNOWN,
+ TT_WORD,
+ TT_LINE,
+ TT_TWO_SIDED_DELIMITER,
+ TT_ONE_SIDED_DELIMITER,
+ TT_DOUBLE_QUOTATION_MARKS,
+ // Following constants are more specific versions of the preceding ones
+ TT_CONSTANT, // WORD
+ TT_CONTROL, // WORD
+ TT_EVENT, // WORD
+ TT_FUNCTION, // WORD
+ TT_LABEL, // LINE
+ TT_SECTION, // WORD
+ TT_TYPE // WORD
+ } ETokenType;
+
+ LLKeywordToken( ETokenType type, const LLColor4& color, const LLWString& token, const LLWString& tool_tip, const LLWString& delimiter )
:
mType( type ),
mToken( token ),
@@ -72,11 +83,11 @@ public:
S32 getLengthHead() const { return mToken.size(); }
S32 getLengthTail() const { return mDelimiter.size(); }
- BOOL isHead(const llwchar* s) const;
- BOOL isTail(const llwchar* s) const;
+ bool isHead(const llwchar* s) const;
+ bool isTail(const llwchar* s) const;
const LLWString& getToken() const { return mToken; }
- const LLColor3& getColor() const { return mColor; }
- TOKEN_TYPE getType() const { return mType; }
+ const LLColor4& getColor() const { return mColor; }
+ ETokenType getType() const { return mType; }
const LLWString& getToolTip() const { return mToolTip; }
const LLWString& getDelimiter() const { return mDelimiter; }
@@ -85,9 +96,9 @@ public:
#endif
private:
- TOKEN_TYPE mType;
+ ETokenType mType;
LLWString mToken;
- LLColor3 mColor;
+ LLColor4 mColor;
LLWString mToolTip;
LLWString mDelimiter;
};
@@ -98,18 +109,24 @@ public:
LLKeywords();
~LLKeywords();
- BOOL loadFromFile(const std::string& filename);
- BOOL isLoaded() const { return mLoaded; }
+ void clearLoaded() { mLoaded = false; }
+ LLColor4 getColorGroup(const std::string& key_in);
+ bool isLoaded() const { return mLoaded; }
- void findSegments(std::vector<LLTextSegmentPtr> *seg_list, const LLWString& text, const LLColor4 &defaultColor, class LLTextEditor& editor );
+ void findSegments(std::vector<LLTextSegmentPtr> *seg_list,
+ const LLWString& text,
+ const LLColor4 &defaultColor,
+ class LLTextEditor& editor);
+ void initialize(LLSD SyntaxXML);
+ void processTokens();
// Add the token as described
- void addToken(LLKeywordToken::TOKEN_TYPE type,
+ void addToken(LLKeywordToken::ETokenType type,
const std::string& key,
- const LLColor3& color,
+ const LLColor4& color,
const std::string& tool_tip = LLStringUtil::null,
const std::string& delimiter = LLStringUtil::null);
-
+
// This class is here as a performance optimization.
// The word token map used to be defined as std::map<LLWString, LLKeywordToken*>.
// This worked, but caused a performance bottleneck due to memory allocation and string copies
@@ -133,6 +150,9 @@ public:
const llwchar *mData;
size_t mLength;
bool mOwner;
+
+
+ LLColor4 mColor;
};
typedef std::map<WStringMapIndex, LLKeywordToken*> word_token_map_t;
@@ -140,20 +160,43 @@ public:
keyword_iterator_t begin() const { return mWordTokenMap.begin(); }
keyword_iterator_t end() const { return mWordTokenMap.end(); }
+ typedef std::map<WStringMapIndex, LLColor4> group_color_map_t;
+ typedef group_color_map_t::const_iterator color_iterator_t;
+ group_color_map_t mColorGroupMap;
+
#ifdef _DEBUG
void dump();
#endif
-private:
- LLColor3 readColor(const std::string& s);
- void insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, class LLTextEditor& editor);
- void insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* token, S32 text_len, S32 seg_start, S32 seg_end, const LLColor4 &defaultColor, LLTextEditor& editor);
-
- BOOL mLoaded;
+protected:
+ void processTokensGroup(const LLSD& Tokens, const std::string& Group);
+ void insertSegment(std::vector<LLTextSegmentPtr>& seg_list,
+ LLTextSegmentPtr new_segment,
+ S32 text_len,
+ const LLColor4 &defaultColor,
+ class LLTextEditor& editor);
+ void insertSegments(const LLWString& wtext,
+ std::vector<LLTextSegmentPtr>& seg_list,
+ LLKeywordToken* token,
+ S32 text_len,
+ S32 seg_start,
+ S32 seg_end,
+ const LLColor4 &defaultColor,
+ LLTextEditor& editor);
+
+ bool mLoaded;
+ LLSD mSyntax;
word_token_map_t mWordTokenMap;
typedef std::deque<LLKeywordToken*> token_list_t;
token_list_t mLineTokenList;
token_list_t mDelimiterTokenList;
+
+ typedef std::map<std::string, std::string> element_attributes_t;
+ typedef element_attributes_t::const_iterator attribute_iterator_t;
+ element_attributes_t mAttributes;
+ std::string getAttribute(const std::string& key);
+
+ std::string getArguments(LLSD& arguments);
};
#endif // LL_LLKEYWORDS_H
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index d410a2de33..b09c927782 100755
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -192,6 +192,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
setPrevalidateInput(p.prevalidate_input_callback());
setPrevalidate(p.prevalidate_callback());
+ llassert(LLMenuGL::sMenuContainer != NULL);
LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>
("menu_text_editor.xml",
LLMenuGL::sMenuContainer,
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index 0609cd8b42..303afcda15 100755
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -93,6 +93,7 @@ void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition posit
return;
}
+ llassert(LLMenuGL::sMenuContainer != NULL);
LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
if (!menu)
{
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 7383a8c307..604dc92789 100755
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -63,6 +63,7 @@
// static
LLMenuHolderGL *LLMenuGL::sMenuContainer = NULL;
+view_listener_t::listener_map_t view_listener_t::sListeners;
S32 MENU_BAR_HEIGHT = 0;
S32 MENU_BAR_WIDTH = 0;
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index feafaab199..ae9b169691 100755
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -895,7 +895,8 @@ class view_listener_t : public boost::signals2::trackable
{
public:
virtual bool handleEvent(const LLSD& userdata) = 0;
- virtual ~view_listener_t() {}
+ view_listener_t() { sListeners.insert(this); }
+ virtual ~view_listener_t() { sListeners.erase(this); }
static void addEnable(view_listener_t* listener, const std::string& name)
{
@@ -913,6 +914,20 @@ public:
addEnable(listener, name);
addCommit(listener, name);
}
+
+ static void cleanup()
+ {
+ listener_vector_t listeners(sListeners.begin(), sListeners.end());
+ sListeners.clear();
+
+ std::for_each(listeners.begin(), listeners.end(), DeletePointer());
+ listeners.clear();
+ }
+
+private:
+ typedef std::set<view_listener_t*> listener_map_t;
+ typedef std::vector<view_listener_t*> listener_vector_t;
+ static listener_map_t sListeners;
};
#endif // LL_LLMENUGL_H
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 025cd81d92..de14391d1f 100755
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -1189,6 +1189,7 @@ void LLNotificationChannel::connectToChannel( const std::string& channel_name )
}
else
{
+ mParents.push_back(channel_name);
LLNotificationChannelPtr p = LLNotifications::instance().getChannel(channel_name);
p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1));
}
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index b0e8553a49..3cf432f330 100755
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -88,6 +88,7 @@
#include <boost/enable_shared_from_this.hpp>
#include <boost/type_traits.hpp>
#include <boost/signals2.hpp>
+#include <boost/range.hpp>
#include "llevents.h"
#include "llfunctorregistry.h"
@@ -840,6 +841,11 @@ public:
typedef LLNotificationSet::iterator Iterator;
std::string getName() const { return mName; }
+ typedef std::vector<std::string>::const_iterator parents_iter;
+ boost::iterator_range<parents_iter> getParents() const
+ {
+ return boost::iterator_range<parents_iter>(mParents);
+ }
void connectToChannel(const std::string& channel_name);
@@ -854,7 +860,7 @@ public:
private:
std::string mName;
- std::string mParent;
+ std::vector<std::string> mParents;
};
// An interface class to provide a clean linker seam to the LLNotifications class.
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp
index 9e8e943ee6..b6a32a0e78 100644
--- a/indra/llui/llnotificationslistener.cpp
+++ b/indra/llui/llnotificationslistener.cpp
@@ -32,6 +32,7 @@
#include "llnotificationtemplate.h"
#include "llsd.h"
#include "llui.h"
+#include <boost/foreach.hpp>
LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
LLEventAPI("LLNotifications",
@@ -42,11 +43,10 @@ LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications
"Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n"
"If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.",
&LLNotificationsListener::requestAdd);
- /* add("listChannels",
+ add("listChannels",
"Post to [\"reply\"] a map of info on existing channels",
&LLNotificationsListener::listChannels,
LLSD().with("reply", LLSD()));
- */
add("listChannelNotifications",
"Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]",
&LLNotificationsListener::listChannelNotifications,
@@ -117,26 +117,27 @@ void LLNotificationsListener::NotificationResponder(const std::string& reply_pum
reponse_event["response"] = response;
LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
}
-/*
+
void LLNotificationsListener::listChannels(const LLSD& params) const
{
LLReqID reqID(params);
LLSD response(reqID.makeResponse());
- for (LLNotifications::
-
-
-
- for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()),
- cmend(mNotifications.mChannels.end());
+ for (LLNotificationChannel::instance_iter cmi(LLNotificationChannel::beginInstances()),
+ cmend(LLNotificationChannel::endInstances());
cmi != cmend; ++cmi)
{
- LLSD channelInfo;
- channelInfo["parent"] = cmi->second->getParentChannelName();
- response[cmi->first] = channelInfo;
+ LLSD channelInfo, parents;
+ BOOST_FOREACH(const std::string& parent, cmi->getParents())
+ {
+ parents.append(parent);
+ }
+ channelInfo["parents"] = parents;
+ channelInfo["parent"] = parents.size()? parents[0] : "";
+ response[cmi->getName()] = channelInfo;
}
LLEventPumps::instance().obtain(params["reply"]).post(response);
}
-*/
+
void LLNotificationsListener::listChannelNotifications(const LLSD& params) const
{
LLReqID reqID(params);
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 3708071e11..5f72ee3ac6 100755
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1815,6 +1815,7 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
// create the context menu from the XUI file and display it
std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml";
delete mPopupMenu;
+ llassert(LLMenuGL::sMenuContainer != NULL);
mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
if (mPopupMenu)
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index ebc6183b8b..6f858cdeb3 100755
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1140,6 +1140,17 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
addChild( btn, 0 );
}
}
+ else
+ {
+ if (textbox)
+ {
+ LLUICtrl::addChild(textbox, 0);
+ }
+ if (btn)
+ {
+ LLUICtrl::addChild(btn, 0);
+ }
+ }
if (child)
{
@@ -1636,16 +1647,26 @@ void LLTabContainer::setTabImage(LLPanel* child, LLIconCtrl* icon)
{
LLTabTuple* tuple = getTabByPanel(child);
LLCustomButtonIconCtrl* button;
+ bool hasButton = false;
if(tuple)
{
button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
if(button)
{
+ hasButton = true;
button->setIcon(icon);
reshapeTuple(tuple);
}
}
+
+ if (!hasButton && (icon != NULL))
+ {
+ // It was assumed that the tab's button would take ownership of the icon pointer.
+ // But since the tab did not have a button, kill the icon to prevent the memory
+ // leak.
+ icon->die();
+ }
}
void LLTabContainer::reshapeTuple(LLTabTuple* tuple)
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 62edbadb07..71db0ac030 100755
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -70,43 +70,36 @@ bool LLTextBase::compare_segment_end::operator()(const LLTextSegmentPtr& a, cons
// helper functors
-struct LLTextBase::compare_bottom
+bool LLTextBase::compare_bottom::operator()(const S32& a, const LLTextBase::line_info& b) const
{
- bool operator()(const S32& a, const LLTextBase::line_info& b) const
- {
- return a > b.mRect.mBottom; // bottom of a is higher than bottom of b
- }
-
- bool operator()(const LLTextBase::line_info& a, const S32& b) const
- {
- return a.mRect.mBottom > b; // bottom of a is higher than bottom of b
- }
+ return a > b.mRect.mBottom; // bottom of a is higher than bottom of b
+}
- bool operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
- {
- return a.mRect.mBottom > b.mRect.mBottom; // bottom of a is higher than bottom of b
- }
+bool LLTextBase::compare_bottom::operator()(const LLTextBase::line_info& a, const S32& b) const
+{
+ return a.mRect.mBottom > b; // bottom of a is higher than bottom of b
+}
-};
+bool LLTextBase::compare_bottom::operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
+{
+ return a.mRect.mBottom > b.mRect.mBottom; // bottom of a is higher than bottom of b
+}
// helper functors
-struct LLTextBase::compare_top
+bool LLTextBase::compare_top::operator()(const S32& a, const LLTextBase::line_info& b) const
{
- bool operator()(const S32& a, const LLTextBase::line_info& b) const
- {
- return a > b.mRect.mTop; // top of a is higher than top of b
- }
+ return a > b.mRect.mTop; // top of a is higher than top of b
+}
- bool operator()(const LLTextBase::line_info& a, const S32& b) const
- {
- return a.mRect.mTop > b; // top of a is higher than top of b
- }
+bool LLTextBase::compare_top::operator()(const LLTextBase::line_info& a, const S32& b) const
+{
+ return a.mRect.mTop > b; // top of a is higher than top of b
+}
- bool operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
- {
- return a.mRect.mTop > b.mRect.mTop; // top of a is higher than top of b
- }
-};
+bool LLTextBase::compare_top::operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
+{
+ return a.mRect.mTop > b.mRect.mTop; // top of a is higher than top of b
+}
struct LLTextBase::line_end_compare
{
@@ -573,7 +566,8 @@ void LLTextBase::drawText()
if ( (getSpellCheck()) && (getWText().length() > 2) )
{
// Calculate start and end indices for the spell checking range
- S32 start = line_start, end = getLineEnd(last_line);
+ S32 start = line_start;
+ S32 end = getLineEnd(last_line);
if ( (mSpellCheckStart != start) || (mSpellCheckEnd != end) )
{
@@ -1955,6 +1949,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
// create and return the context menu from the XUI file
delete mPopupMenu;
+ llassert(LLMenuGL::sMenuContainer != NULL);
mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
LLMenuHolderGL::child_registry_t::instance());
if (mIsFriendSignal)
@@ -2037,7 +2032,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
LLUrlMatch match;
std::string text = new_text;
while ( LLUrlRegistry::instance().findUrl(text, match,
- boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) )
+ boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted()))
{
start = match.getStart();
end = match.getEnd()+1;
@@ -2074,7 +2069,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
}
}
- LLTextUtil::processUrlMatch(&match,this);
+ LLTextUtil::processUrlMatch(&match,this,isContentTrusted());
// move on to the rest of the text after the Url
if (end < (S32)text.length())
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index d1f66b6cfe..738b4d5b8e 100755
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -367,7 +367,9 @@ public:
bool getWordWrap() { return mWordWrap; }
bool getUseEllipses() { return mUseEllipses; }
bool truncate(); // returns true of truncation occurred
+
bool isContentTrusted() {return mTrustedContent;}
+ void setContentTrusted(bool trusted_content) { mTrustedContent = trusted_content; }
// TODO: move into LLTextSegment?
void createUrlContextMenu(S32 x, S32 y, const std::string &url); // create a popup context menu for the given Url
@@ -449,9 +451,31 @@ public:
LLScrollContainer* getScrollContainer() const { return mScroller; }
protected:
+ // protected member variables
+ // List of offsets and segment index of the start of each line. Always has at least one node (0).
+ struct line_info
+ {
+ line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num);
+ S32 mDocIndexStart;
+ S32 mDocIndexEnd;
+ LLRect mRect;
+ S32 mLineNum; // actual line count (ignoring soft newlines due to word wrap)
+ };
+ typedef std::vector<line_info> line_list_t;
+
// helper structs
- struct compare_bottom;
- struct compare_top;
+ struct compare_bottom
+ {
+ bool operator()(const S32& a, const line_info& b) const;
+ bool operator()(const line_info& a, const S32& b) const;
+ bool operator()(const line_info& a, const line_info& b) const;
+ };
+ struct compare_top
+ {
+ bool operator()(const S32& a, const line_info& b) const;
+ bool operator()(const line_info& a, const S32& b) const;
+ bool operator()(const line_info& a, const line_info& b) const;
+ };
struct line_end_compare;
typedef std::vector<LLTextSegmentPtr> segment_vec_t;
@@ -499,18 +523,6 @@ protected:
};
typedef std::multiset<LLTextSegmentPtr, compare_segment_end> segment_set_t;
- // protected member variables
- // List of offsets and segment index of the start of each line. Always has at least one node (0).
- struct line_info
- {
- line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num);
- S32 mDocIndexStart;
- S32 mDocIndexEnd;
- LLRect mRect;
- S32 mLineNum; // actual line count (ignoring soft newlines due to word wrap)
- };
- typedef std::vector<line_info> line_list_t;
-
// member functions
LLTextBase(const Params &p);
virtual ~LLTextBase();
@@ -520,7 +532,7 @@ protected:
virtual bool useLabel() const;
// draw methods
- void drawSelectionBackground(); // draws the black box behind the selected text
+ virtual void drawSelectionBackground(); // draws the black box behind the selected text
void drawCursor();
void drawText();
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 494666df8a..576e8f7600 100755
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -75,8 +75,6 @@ template class LLTextEditor* LLView::getChild<class LLTextEditor>(
//
// Constants
//
-const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32;
-const S32 UI_TEXTEDITOR_LINE_NUMBER_DIGITS = 4;
const S32 SPACES_PER_TAB = 4;
const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on
@@ -236,7 +234,6 @@ LLTextEditor::Params::Params()
prevalidate_callback("prevalidate_callback"),
embedded_items("embedded_items", false),
ignore_tab("ignore_tab", true),
- show_line_numbers("show_line_numbers", false),
auto_indent("auto_indent", true),
default_color("default_color"),
commit_on_focus_lost("commit_on_focus_lost", false),
@@ -252,8 +249,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mBaseDocIsPristine(TRUE),
mPristineCmd( NULL ),
mLastCmd( NULL ),
- mDefaultColor( p.default_color() ),
- mShowLineNumbers ( p.show_line_numbers ),
+ mDefaultColor( p.default_color() ),
mAutoIndent(p.auto_indent),
mCommitOnFocusLost( p.commit_on_focus_lost),
mAllowEmbeddedItems( p.embedded_items ),
@@ -264,7 +260,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mContextMenu(NULL),
mShowContextMenu(p.show_context_menu),
mEnableTooltipPaste(p.enable_tooltip_paste),
- mPassDelete(FALSE)
+ mPassDelete(FALSE),
+ mKeepSelectionOnReturn(false)
{
mSourceID.generate();
@@ -277,14 +274,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
params.visible = p.border_visible;
mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
addChild( mBorder );
-
setText(p.default_text());
-
- if (mShowLineNumbers)
- {
- mHPad += UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
- updateRects();
- }
mParseOnTheFly = TRUE;
}
@@ -1664,7 +1654,7 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask)
case KEY_RETURN:
if (mask == MASK_NONE)
{
- if( hasSelection() )
+ if( hasSelection() && !mKeepSelectionOnReturn )
{
deleteSelection(FALSE);
}
@@ -2031,6 +2021,7 @@ void LLTextEditor::showContextMenu(S32 x, S32 y)
{
if (!mContextMenu)
{
+ llassert(LLMenuGL::sMenuContainer != NULL);
mContextMenu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_text_editor.xml",
LLMenuGL::sMenuContainer,
LLMenuHolderGL::child_registry_t::instance());
@@ -2196,69 +2187,6 @@ void LLTextEditor::drawPreeditMarker()
}
}
-
-void LLTextEditor::drawLineNumbers()
-{
- LLGLSUIDefault gls_ui;
- LLRect scrolled_view_rect = getVisibleDocumentRect();
- LLRect content_rect = getVisibleTextRect();
- LLLocalClipRect clip(content_rect);
- S32 first_line = getFirstVisibleLine();
- S32 num_lines = getLineCount();
- if (first_line >= num_lines)
- {
- return;
- }
-
- S32 cursor_line = mLineInfoList[getLineNumFromDocIndex(mCursorPos)].mLineNum;
-
- if (mShowLineNumbers)
- {
- S32 left = 0;
- S32 top = getRect().getHeight();
- S32 bottom = 0;
-
- gl_rect_2d(left, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN, bottom, mReadOnlyBgColor.get() ); // line number area always read-only
- gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN-1, bottom, LLColor4::grey3); // separator
-
- S32 last_line_num = -1;
-
- for (S32 cur_line = first_line; cur_line < num_lines; cur_line++)
- {
- line_info& line = mLineInfoList[cur_line];
-
- if ((line.mRect.mTop - scrolled_view_rect.mBottom) < mVisibleTextRect.mBottom)
- {
- break;
- }
-
- S32 line_bottom = line.mRect.mBottom - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom;
- // draw the line numbers
- if(line.mLineNum != last_line_num && line.mRect.mTop <= scrolled_view_rect.mTop)
- {
- const LLFontGL *num_font = LLFontGL::getFontMonospace();
- const LLWString ltext = utf8str_to_wstring(llformat("%d", line.mLineNum ));
- BOOL is_cur_line = cursor_line == line.mLineNum;
- const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL;
- const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor;
- num_font->render(
- ltext, // string to draw
- 0, // begin offset
- UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2, // x
- line_bottom, // y
- fg_color,
- LLFontGL::RIGHT, // horizontal alignment
- LLFontGL::BOTTOM, // vertical alignment
- style,
- LLFontGL::NO_SHADOW,
- S32_MAX, // max chars
- UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2); // max pixels
- last_line_num = line.mLineNum;
- }
- }
- }
-}
-
void LLTextEditor::draw()
{
{
@@ -2270,7 +2198,6 @@ void LLTextEditor::draw()
}
LLTextBase::draw();
- drawLineNumbers();
drawPreeditMarker();
@@ -2338,7 +2265,8 @@ void LLTextEditor::autoIndent()
S32 i;
LLWString text = getWText();
- while( ' ' == text[line_start] )
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+ while(( ' ' == text[line_start] ) && (space_count < offset))
{
space_count++;
line_start++;
@@ -2511,53 +2439,6 @@ BOOL LLTextEditor::tryToRevertToPristineState()
return isPristine(); // TRUE => success
}
-
-static LLTrace::BlockTimerStatHandle FTM_SYNTAX_HIGHLIGHTING("Syntax Highlighting");
-void LLTextEditor::loadKeywords(const std::string& filename,
- const std::vector<std::string>& funcs,
- const std::vector<std::string>& tooltips,
- const LLColor3& color)
-{
- LL_RECORD_BLOCK_TIME(FTM_SYNTAX_HIGHLIGHTING);
- if(mKeywords.loadFromFile(filename))
- {
- S32 count = llmin(funcs.size(), tooltips.size());
- for(S32 i = 0; i < count; i++)
- {
- std::string name = utf8str_trim(funcs[i]);
- mKeywords.addToken(LLKeywordToken::WORD, name, color, tooltips[i] );
- }
- segment_vec_t segment_list;
- mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);
-
- mSegments.clear();
- segment_set_t::iterator insert_it = mSegments.begin();
- for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
- {
- insert_it = mSegments.insert(insert_it, *list_it);
- }
- }
-}
-
-void LLTextEditor::updateSegments()
-{
- if (mReflowIndex < S32_MAX && mKeywords.isLoaded() && mParseOnTheFly)
- {
- LL_RECORD_BLOCK_TIME(FTM_SYNTAX_HIGHLIGHTING);
- // HACK: No non-ascii keywords for now
- segment_vec_t segment_list;
- mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);
-
- clearSegments();
- for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
- {
- insertSegment(*list_it);
- }
- }
-
- LLTextBase::updateSegments();
-}
-
void LLTextEditor::updateLinkSegments()
{
LLWString wtext = getWText();
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 3a96d8ed24..f6bdf917b4 100755
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lltexteditor.h
* @brief LLTextEditor base class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,7 +30,6 @@
#define LL_LLTEXTEDITOR_H
#include "llrect.h"
-#include "llkeywords.h"
#include "llframetimer.h"
#include "llstyle.h"
#include "lleditmenuhandler.h"
@@ -43,7 +42,6 @@
class LLFontGL;
class LLScrollbar;
-class LLKeywordToken;
class TextCmd;
class LLUICtrlFactory;
class LLScrollContainer;
@@ -60,7 +58,6 @@ public:
Optional<bool> embedded_items,
ignore_tab,
- show_line_numbers,
commit_on_focus_lost,
show_context_menu,
enable_tooltip_paste,
@@ -131,7 +128,7 @@ public:
virtual BOOL canCopy() const;
virtual void paste();
virtual BOOL canPaste() const;
-
+
virtual void updatePrimary();
virtual void copyPrimary();
virtual void pastePrimary();
@@ -149,7 +146,7 @@ public:
void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE);
BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive);
-
+
// Undo/redo stack
void blockUndo();
@@ -186,13 +183,6 @@ public:
void getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap );
- void loadKeywords(const std::string& filename,
- const std::vector<std::string>& funcs,
- const std::vector<std::string>& tooltips,
- const LLColor3& func_color);
- LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); }
- LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); }
-
// Hacky methods to make it into a word-wrapping, potentially scrolling,
// read-only text box.
void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; }
@@ -204,7 +194,7 @@ public:
const LLUUID& getSourceID() const { return mSourceID; }
const LLTextSegmentPtr getPreviousSegment() const;
- void getSelectedSegments(segment_vec_t& segments) const;
+ void getSelectedSegments(segment_vec_t& segments) const;
void setShowContextMenu(bool show) { mShowContextMenu = show; }
bool getShowContextMenu() const { return mShowContextMenu; }
@@ -216,7 +206,7 @@ protected:
void drawPreeditMarker();
void assignEmbedded(const std::string &s);
-
+
void removeCharOrTab();
void indentSelectedLines( S32 spaces );
@@ -235,12 +225,12 @@ protected:
S32 nextWordPos(S32 cursorPos) const;
void autoIndent();
-
+
void findEmbeddedItemSegments(S32 start, S32 end);
void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const;
virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; }
-
+
// Here's the method that takes and applies text commands.
S32 execute(TextCmd* cmd);
@@ -254,7 +244,7 @@ protected:
S32 removeChar(S32 pos);
S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);
S32 remove(S32 pos, S32 length, bool group_with_next_op);
-
+
void focusLostHelper();
void updateAllowingLanguageInput();
BOOL hasPreeditString() const;
@@ -272,14 +262,14 @@ protected:
//
// Protected data
//
- // Probably deserves serious thought to hiding as many of these
+ // Probably deserves serious thought to hiding as many of these
// as possible behind protected accessor methods.
//
// Use these to determine if a click on an embedded item is a drag or not.
S32 mMouseDownX;
S32 mMouseDownY;
-
+
LLWString mPreeditWString;
LLWString mPreeditOverwrittenWString;
std::vector<S32> mPreeditPositions;
@@ -288,11 +278,12 @@ protected:
protected:
LLUIColor mDefaultColor;
- BOOL mShowLineNumbers;
bool mAutoIndent;
+ bool mParseOnTheFly;
- /*virtual*/ void updateSegments();
void updateLinkSegments();
+ void keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; }
+ class LLViewBorder* mBorder;
private:
//
@@ -302,23 +293,14 @@ private:
void cleanStringForPaste(LLWString & clean_string);
void pasteTextWithLinebreaks(LLWString & clean_string);
- void drawLineNumbers();
-
void onKeyStroke();
- //
- // Data
- //
- LLKeywords mKeywords;
-
// Concrete TextCmd sub-classes used by the LLTextEditor base class
class TextCmdInsert;
class TextCmdAddChar;
class TextCmdOverwriteChar;
class TextCmdRemove;
- class LLViewBorder* mBorder;
-
BOOL mBaseDocIsPristine;
TextCmd* mPristineCmd;
@@ -333,9 +315,9 @@ private:
BOOL mAllowEmbeddedItems;
bool mShowContextMenu;
- bool mParseOnTheFly;
bool mEnableTooltipPaste;
bool mPassDelete;
+ bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter
LLUUID mSourceID;
@@ -353,4 +335,4 @@ extern template class LLTextEditor* LLView::getChild<class LLTextEditor>(
const std::string& name, BOOL recurse) const;
#endif
-#endif // LL_TEXTEDITOR_
+#endif // LL_TEXTEDITOR_H
diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp
index 4df2c3363f..fff04b34f2 100755
--- a/indra/llui/lltextutil.cpp
+++ b/indra/llui/lltextutil.cpp
@@ -72,7 +72,7 @@ const std::string& LLTextUtil::formatPhoneNumber(const std::string& phone_str)
return formatted_phone_str;
}
-bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base)
+bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool is_content_trusted)
{
if (match == 0 || text_base == 0)
return false;
@@ -85,7 +85,7 @@ bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base)
}
// output an optional icon before the Url
- if (!match->getIcon().empty() )
+ if (is_content_trusted && !match->getIcon().empty() )
{
LLUIImagePtr image = LLUI::getUIImage(match->getIcon());
if (image)
diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h
index bf7dbb58ce..798f14d086 100755
--- a/indra/llui/lltextutil.h
+++ b/indra/llui/lltextutil.h
@@ -64,7 +64,7 @@ namespace LLTextUtil
*/
const std::string& formatPhoneNumber(const std::string& phone_str);
- bool processUrlMatch(LLUrlMatch* match,LLTextBase* text_base);
+ bool processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool is_content_trusted);
class TextHelpers
{
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index f9bdd87087..abc2b6e9ca 100755
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -148,6 +148,7 @@ void LLToolBar::createContextMenu()
enable_reg.add("Toolbars.CheckSetting", boost::bind(&LLToolBar::isSettingChecked, this, _2));
// Create the context menu
+ llassert(LLMenuGL::sMenuContainer != NULL);
LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_toolbars.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
if (menu)
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 5e1f12996e..7f2224870d 100755
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -477,7 +477,8 @@ void LLToolTipMgr::show(const std::string& msg)
void LLToolTipMgr::show(const LLToolTip::Params& params)
{
if (!params.styled_message.isProvided()
- && (!params.message.isProvided() || params.message().empty())) return;
+ && (!params.message.isProvided() || params.message().empty())
+ && !params.image.isProvided()) return;
// fill in default tooltip params from tool_tip.xml
LLToolTip::Params params_with_defaults(params);
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 523ee5d78c..bccc646821 100755
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -41,7 +41,8 @@ LLUrlRegistry::LLUrlRegistry()
// Urls are matched in the order that they were registered
registerUrl(new LLUrlEntryNoLink());
- registerUrl(new LLUrlEntryIcon());
+ mUrlEntryIcon = new LLUrlEntryIcon();
+ registerUrl(mUrlEntryIcon);
registerUrl(new LLUrlEntrySLURL());
registerUrl(new LLUrlEntryHTTP());
registerUrl(new LLUrlEntryHTTPLabel());
@@ -145,7 +146,7 @@ static bool stringHasUrl(const std::string &text)
text.find("<icon") != std::string::npos);
}
-bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
+bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted)
{
// avoid costly regexes if there is clearly no URL in the text
if (! stringHasUrl(text))
@@ -160,6 +161,12 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
std::vector<LLUrlEntryBase *>::iterator it;
for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
{
+ //Skip for url entry icon if content is not trusted
+ if(!is_content_trusted && (mUrlEntryIcon == *it))
+ {
+ continue;
+ }
+
LLUrlEntryBase *url_entry = *it;
U32 start = 0, end = 0;
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index da16171a97..6270df1bbb 100755
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -73,7 +73,8 @@ public:
/// get the next Url in an input string, starting at a given character offset
/// your callback is invoked if the matched Url's label changes in the future
bool findUrl(const std::string &text, LLUrlMatch &match,
- const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
+ const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback,
+ bool is_content_trusted = false);
/// a slightly less efficient version of findUrl for wide strings
bool findUrl(const LLWString &text, LLUrlMatch &match,
@@ -92,6 +93,7 @@ private:
friend class LLSingleton<LLUrlRegistry>;
std::vector<LLUrlEntryBase *> mUrlEntry;
+ LLUrlEntryBase* mUrlEntryIcon;
};
#endif
diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp
index 4390ca83e9..37d88cb9f9 100755
--- a/indra/llui/llxuiparser.cpp
+++ b/indra/llui/llxuiparser.cpp
@@ -30,7 +30,7 @@
#include "llxmlnode.h"
#include "llfasttimer.h"
-#ifdef LL_STANDALONE
+#ifdef LL_USESYSTEMLIBS
#include <expat.h>
#else
#include "expat/expat.h"