summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rwxr-xr-xindra/llui/llkeywords.cpp523
-rwxr-xr-xindra/llui/llkeywords.h103
-rwxr-xr-xindra/llui/lltextbase.cpp3
-rwxr-xr-xindra/llui/lltexteditor.cpp47
-rwxr-xr-xindra/llui/lltexteditor.h47
5 files changed, 435 insertions, 288 deletions
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index 39153977bf..07c84e57c0 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,338 @@ LLKeywords::~LLKeywords()
mDelimiterTokenList.clear();
}
-BOOL LLKeywords::loadFromFile( const std::string& filename )
+void LLKeywords::addColorGroup(const std::string key_in, const LLColor4 color)
{
- 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() )
- {
- llinfos << "LLKeywords::loadFromFile() Unable to open file: " << filename << llendl;
- return mLoaded;
- }
+ WStringMapIndex key ( utf8str_to_wstring(key_in) );
+ mColorGroupMap[key] = color;
+}
- // Identifying string
- file >> buffer;
- if( strcmp( buffer, "llkeywords" ) )
+// 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)
+{
+ std::string tip_text = tool_tip_in;
+ LLStringUtil::replaceString(tip_text, "\\n", "\n" );
+ LLStringUtil::replaceString(tip_text, "\t", " " );
+ if (tip_text == "")
{
- llinfos << filename << " does not appear to be a keyword file" << llendl;
- return mLoaded;
+ tip_text = "[no info]";
}
+ LLWString tool_tip = utf8str_to_wstring(tip_text);
- // 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)
{
- llinfos << filename << " does not appear to be a version " << KEYWORD_FILE_CURRENT_VERSION << " keyword file" << llendl;
- 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 == "" ? "" : 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 ColourGroup = "Black";
+ if (key_in == "constants-float")
+ {
+ ColourGroup = "SyntaxLslConstantFloat";
+ }
+ else if (key_in == "constants-integer")
+ {
+ ColourGroup = "SyntaxLslConstantInteger";
+ }
+ else if (key_in == "constants-key")
+ {
+ ColourGroup = "SyntaxLslConstantKey";
+ }
+ else if (key_in == "constants-rotation")
+ {
+ ColourGroup = "SyntaxLslConstantRotation";
+ }
+ else if (key_in == "constants-string")
+ {
+ ColourGroup = "SyntaxLslConstantString";
+ }
+ else if (key_in == "constants-vector")
+ {
+ ColourGroup = "SyntaxLslConstantVector";
+ }
+ else if (key_in == "misc-flow-label")
+ {
+ ColourGroup = "SyntaxLslControlFlow";
+ }
+ else if (key_in =="deprecated")
+ {
+ ColourGroup = "SyntaxLslDeprecated";
+ }
+ else if (key_in == "events")
+ {
+ ColourGroup = "SyntaxLslEvent";
+ }
+ else if (key_in == "functions")
+ {
+ ColourGroup = "SyntaxLslFunction";
+ }
+ else if (key_in =="god-mode")
+ {
+ ColourGroup = "SyntaxLslGodMode";
+ }
+ else if (key_in == "types")
+ {
+ ColourGroup = "SyntaxLslDataType";
+ }
+ else if (key_in == "sections")
+ {
+ ColourGroup = "SyntaxLslSection";
+ }
+ else if (key_in == "misc-double_quotation_marks")
+ {
+ ColourGroup = "SyntaxLslStringLiteral";
+ }
+ else if (key_in == "misc-comments_1_sided")
+ {
+ ColourGroup = "SyntaxLslComment1Sided";
+ }
+ else if (key_in == "misc-comments_2_sided")
+ {
+ ColourGroup = "SyntaxLslComment2Sided";
+ }
+ else
+ {
+ LL_WARNS("SyntaxLSL") << "Color key '" << key_in << "' not recognized!" << LL_ENDL;
+ }
+
+ return LLUIColorTable::instance().getColor(ColourGroup);
+}
+
+void LLKeywords::initialise(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, "//", getColorGroup("misc-comments_1_sided"), "Comment (single-line)\nNon-functional commentary or disabled code", delimiter );
+ addToken(LLKeywordToken::TT_TWO_SIDED_DELIMITER, "/*", getColorGroup("misc-comments_2_sided"), "Comment (multi-line)\nNon-functional commentary or disabled code", "*/" );
+ addToken(LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS, "\"", getColorGroup("misc-double_quotation_marks"), "String literal", "\"" );
+
+ LLSD::map_iterator outerIt = mSyntax.beginMap();
+ for ( ; outerIt != mSyntax.endMap(); ++outerIt)
+ {
+ if (outerIt->first == "llsd-lsl-syntax-version")
+ {
+ // Skip over version key.
+ }
+ else
+ {
+ if (outerIt->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(outerIt->second, outerIt->first);
}
else
{
- addToken(cur_type, keyword, cur_color, LLStringUtil::null, delimiter );
+ LL_WARNS("LSL-Tokens-Processing") << "Map for " + outerIt->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(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 ColorGroup;
+ LLColor4 ColorDeprecated = getColorGroup("deprecated");
+ LLColor4 ColorGM = 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;
+ ColorGroup = getColorGroup(Group);
+ LL_INFOS("Tokens") << "Group: '" << Group << "', using colour: '" << ColorGroup << "'" << 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_iterator outerIt = Tokens.beginMap();
+ for ( ; outerIt != Tokens.endMap(); ++outerIt)
+ {
+ if (outerIt->second.isMap())
+ {
+ mAttributes.clear();
+ LLSD arguments = LLSD ();
+ LLSD::map_iterator innerIt = outerIt->second.beginMap();
+ for ( ; innerIt != outerIt->second.endMap(); ++innerIt)
+ {
+ if (innerIt->first == "arguments")
+ {
+ if (innerIt->second.isArray())
+ {
+ arguments = innerIt->second;
+ }
+ }
+ else if (!innerIt->second.isMap() && !innerIt->second.isArray())
+ {
+ mAttributes[innerIt->first] = innerIt->second.asString();
+ }
+ else
+ {
+ LL_WARNS("SyntaxLSL") << "Not a valid attribute: " << innerIt->first << LL_ENDL;
+ }
+ }
- default:
- llassert(0);
+ std::string tooltip = "";
+ if (token_type == LLKeywordToken::TT_CONSTANT)
+ {
+ ColorGroup = getColorGroup(Group + "-" + getAttribute("type"));
+ tooltip = "Type: " + getAttribute("type") + ", Value: " + getAttribute("value");
+ }
+ else if (token_type == LLKeywordToken::TT_EVENT)
+ {
+ tooltip = outerIt->first + "(" + getArguments(arguments) + ")";
+ }
+ else if (token_type == LLKeywordToken::TT_FUNCTION)
+ {
+ tooltip = getAttribute("return") + " " + outerIt->first + "(" + getArguments(arguments) + ");";
+ tooltip += "\nEnergy: ";
+ tooltip += getAttribute("energy") == "" ? "0.0" : getAttribute("energy");
+ if (getAttribute("sleep") != "")
+ {
+ tooltip += ", Sleep: " + getAttribute("sleep");
+ }
+ }
+
+ if (getAttribute("tooltip") != "")
+ {
+ if (tooltip != "")
+ {
+ tooltip += "\n";
+ }
+ tooltip += getAttribute("tooltip");
+ }
+
+ Color = getAttribute("deprecated") == "true" ? ColorDeprecated : ColorGroup;
+
+ if (getAttribute("god-mode") == "true")
+ {
+ Color = ColorGM;
+ }
+
+ addToken(token_type, outerIt->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 (int count = 0; count < Tokens.size(); ++count)
+ {
+ addToken(token_type, Tokens[count], Color, "");
+ }
+ }
+ else
+ {
+ LL_WARNS("Tokens") << "Invalid map/array passed: '" << Tokens << "'" << LL_ENDL;
}
}
+
LLKeywords::WStringMapIndex::WStringMapIndex(const WStringMapIndex& other)
{
if(other.mOwner)
@@ -301,13 +458,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 +479,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,11 +491,11 @@ bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &o
self_iter++;
other_iter++;
}
-
+
return result;
}
-LLColor3 LLKeywords::readColor( const std::string& s )
+LLColor4 LLKeywords::readColor( const std::string& s )
{
F32 r, g, b;
r = g = b = 0.0f;
@@ -347,7 +504,23 @@ LLColor3 LLKeywords::readColor( const std::string& s )
{
llinfos << " poorly formed color in keyword file" << llendl;
}
- return LLColor3( r, g, b );
+ return LLColor4( r, g, b, 1.f);
+}
+
+LLColor4 LLKeywords::readColor(LLSD& sd)
+{
+ if (sd.isArray())
+ {
+ return LLColor4 (sd, 1.f);
+ }
+ else if (sd.isMap())
+ {
+ return LLColor4 ( sd.get("x").asReal(), sd.get("y").asReal(), sd.get("z").asReal(), 1.f );
+ }
+ else
+ {
+ return LLColor4::black;
+ }
}
LLFastTimer::DeclareTimer FTM_SYNTAX_COLORING("Syntax Coloring");
@@ -363,10 +536,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 +569,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 +587,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 +632,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 +686,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) )
{
@@ -559,7 +732,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor);
}
- cur += seg_len;
+ cur += seg_len;
continue;
}
}
@@ -575,7 +748,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)
@@ -654,7 +827,7 @@ void LLKeywords::dump()
void LLKeywordToken::dump()
{
- llinfos << "[" <<
+ llinfos << "[" <<
mColor.mV[VX] << ", " <<
mColor.mV[VY] << ", " <<
mColor.mV[VZ] << "] [" <<
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index ac34015393..69bc8919db 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,22 @@ public:
LLKeywords();
~LLKeywords();
- BOOL loadFromFile(const std::string& filename);
- BOOL isLoaded() const { return mLoaded; }
+ void addColorGroup(const std::string key_in, const LLColor4 color);
+ 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 initialise(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 +148,9 @@ public:
const llwchar *mData;
size_t mLength;
bool mOwner;
+
+
+ LLColor4 mColor;
};
typedef std::map<WStringMapIndex, LLKeywordToken*> word_token_map_t;
@@ -140,20 +158,37 @@ 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);
+protected:
+ void processTokensGroup(LLSD& Tokens, const std::string Group);
+ LLColor4 readColor(const std::string& s);
+ LLColor4 readColor(LLSD& sd);
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 mColors;
+ 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& args);
+
+private:
};
#endif // LL_LLKEYWORDS_H
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 4144a42fd6..c4664d6fe0 100755
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -573,7 +573,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) )
{
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 02c81c0744..b18c545f30 100755
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2511,53 +2511,6 @@ BOOL LLTextEditor::tryToRevertToPristineState()
return isPristine(); // TRUE => success
}
-
-static LLFastTimer::DeclareTimer 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)
-{
- LLFastTimer ft(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)
- {
- LLFastTimer ft(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 d3b7bc0eb7..6c14ad90a5 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 "lldarray.h"
#include "llstyle.h"
@@ -45,7 +44,6 @@
class LLFontGL;
class LLScrollbar;
-class LLKeywordToken;
class TextCmd;
class LLUICtrlFactory;
class LLScrollContainer;
@@ -133,7 +131,7 @@ public:
virtual BOOL canCopy() const;
virtual void paste();
virtual BOOL canPaste() const;
-
+
virtual void updatePrimary();
virtual void copyPrimary();
virtual void pastePrimary();
@@ -151,7 +149,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();
@@ -188,13 +186,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; }
@@ -206,7 +197,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; }
@@ -218,7 +209,7 @@ protected:
void drawPreeditMarker();
void assignEmbedded(const std::string &s);
-
+
void removeCharOrTab();
void indentSelectedLines( S32 spaces );
@@ -237,12 +228,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);
@@ -256,7 +247,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;
@@ -274,14 +265,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;
@@ -292,8 +283,8 @@ protected:
BOOL mShowLineNumbers;
bool mAutoIndent;
+ bool mParseOnTheFly;
- /*virtual*/ void updateSegments();
void updateLinkSegments();
private:
@@ -308,11 +299,6 @@ private:
void onKeyStroke();
- //
- // Data
- //
- LLKeywords mKeywords;
-
// Concrete TextCmd sub-classes used by the LLTextEditor base class
class TextCmdInsert;
class TextCmdAddChar;
@@ -335,7 +321,6 @@ private:
BOOL mAllowEmbeddedItems;
bool mShowContextMenu;
- bool mParseOnTheFly;
bool mEnableTooltipPaste;
bool mPassDelete;
@@ -355,4 +340,4 @@ extern template class LLTextEditor* LLView::getChild<class LLTextEditor>(
const std::string& name, BOOL recurse) const;
#endif
-#endif // LL_TEXTEDITOR_
+#endif // LL_TEXTEDITOR_H