From 42c166e451d362609d83fb17261f9e8f344e974d Mon Sep 17 00:00:00 2001
From: "niel@nirvana-win7hp.planescape.home"
 <niel@nirvana-win7hp.planescape.home>
Date: Wed, 26 Oct 2011 01:38:29 +0100
Subject: [PATCH] STORM-959 Adding syntax highlighting for /* */ style comments

---
 doc/contributions.txt                   |  3 +
 indra/llui/llkeywords.cpp               | 81 +++++++++++++++++++------
 indra/llui/llkeywords.h                 | 33 ++++++++--
 indra/newview/app_settings/keywords.ini |  4 +-
 4 files changed, 96 insertions(+), 25 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index e85fc32f186..0ae6dc5c01e 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -481,6 +481,7 @@ Ima Mechanique
 	OPEN-50
 	OPEN-61
 	OPEN-76
+	STORM-959
 	STORM-1175
 Imnotgoing Sideways
 Inma Rau
@@ -651,6 +652,8 @@ Lilly Zenovka
 Lizzy Macarthur
 Luban Yiyuan
 Luc Starsider
+Luminous Luminos
+	STORM-959
 Lunita Savira
 Maccus McCullough
 maciek marksman
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index ceec9c7eb11..c1cd04186bd 100644
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -57,6 +57,22 @@ LLKeywords::LLKeywords() : mLoaded(FALSE)
 {
 }
 
+inline BOOL LLKeywordToken::isTail(const llwchar* s) const
+{
+	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;
+			break;
+		}
+	}
+	return res;
+}
+
 LLKeywords::~LLKeywords()
 {
 	std::for_each(mWordTokenMap.begin(), mWordTokenMap.end(), DeletePairedPointer());
@@ -106,6 +122,7 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
 	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 ");
 
 	LLColor3 cur_color( 1, 0, 0 );
 	LLKeywordToken::TOKEN_TYPE cur_type = LLKeywordToken::WORD;
@@ -137,6 +154,12 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
 			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()) );
@@ -154,10 +177,26 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
 
 		if( !token_buffer.empty() && token_word_iter != word_tokens.end() )
 		{
-			// first word is keyword
+			// 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)
+			{
+				while (delimiter.length() == 0 && ++token_word_iter != word_tokens.end())
+				{
+					delimiter = *token_word_iter;
+					LLStringUtil::trim(delimiter);
+				}
+			}
+			else if (cur_type == LLKeywordToken::DOUBLE_QUOTATION_MARKS)
+			{
+				// Closing delimiter is identical to the opening one.
+				delimiter = keyword;
+			}
+
 			// following words are tooltip
 			std::string tool_tip;
 			while (++token_word_iter != word_tokens.end())
@@ -170,11 +209,11 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
 			{
 				// Replace : with \n for multi-line tool tips.
 				LLStringUtil::replaceChar( tool_tip, ':', '\n' );
-				addToken(cur_type, keyword, cur_color, tool_tip );
+				addToken(cur_type, keyword, cur_color, tool_tip, delimiter );
 			}
 			else
 			{
-				addToken(cur_type, keyword, cur_color, LLStringUtil::null );
+				addToken(cur_type, keyword, cur_color, LLStringUtil::null, delimiter );
 			}
 		}
 	}
@@ -189,23 +228,26 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
 void LLKeywords::addToken(LLKeywordToken::TOKEN_TYPE type,
 						  const std::string& key_in,
 						  const LLColor3& color,
-						  const std::string& tool_tip_in )
+						  const std::string& tool_tip_in,
+						  const std::string& delimiter_in)
 {
 	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)
 	{
 	case LLKeywordToken::WORD:
-		mWordTokenMap[key] = new LLKeywordToken(type, color, key, tool_tip);
+		mWordTokenMap[key] = new LLKeywordToken(type, color, key, tool_tip, LLWStringUtil::null);
 		break;
 
 	case LLKeywordToken::LINE:
-		mLineTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip));
+		mLineTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip, LLWStringUtil::null));
 		break;
 
 	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));
+		mDelimiterTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip, delimiter));
 		break;
 
 	default:
@@ -357,7 +399,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
 			}
 
 			// cur is now at the first non-whitespace character of a new line	
-		
+
 			// Line start tokens
 			{
 				BOOL line_done = FALSE;
@@ -418,14 +460,15 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
 					S32 seg_end = 0;
 
 					seg_start = cur - base;
-					cur += cur_delimiter->getLength();
+					cur += cur_delimiter->getLengthHead();
 					
-					if( cur_delimiter->getType() == LLKeywordToken::TWO_SIDED_DELIMITER )
+					LLKeywordToken::TOKEN_TYPE type = cur_delimiter->getType();
+					if( type == LLKeywordToken::TWO_SIDED_DELIMITER || type == LLKeywordToken::DOUBLE_QUOTATION_MARKS )
 					{
-						while( *cur && !cur_delimiter->isHead(cur))
+						while( *cur && !cur_delimiter->isTail(cur))
 						{
 							// Check for an escape sequence.
-							if (*cur == '\\')
+							if (type == LLKeywordToken::DOUBLE_QUOTATION_MARKS && *cur == '\\')
 							{
 								// Count the number of backslashes.
 								S32 num_backslashes = 0;
@@ -435,10 +478,10 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
 									between_delimiters++;
 									cur++;
 								}
-								// Is the next character the end delimiter?
-								if (cur_delimiter->isHead(cur))
+								// If the next character is the end delimiter?
+								if (cur_delimiter->isTail(cur))
 								{
-									// Is there was an odd number of backslashes, then this delimiter
+									// If there was an odd number of backslashes, then this delimiter
 									// does not end the sequence.
 									if (num_backslashes % 2 == 1)
 									{
@@ -461,13 +504,13 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
 
 						if( *cur )
 						{
-							cur += cur_delimiter->getLength();
-							seg_end = seg_start + between_delimiters + 2 * cur_delimiter->getLength();
+							cur += cur_delimiter->getLengthHead();
+							seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead() + cur_delimiter->getLengthTail();
 						}
 						else
 						{
 							// eof
-							seg_end = seg_start + between_delimiters + cur_delimiter->getLength();
+							seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead();
 						}
 					}
 					else
@@ -479,7 +522,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
 							between_delimiters++;
 							cur++;
 						}
-						seg_end = seg_start + between_delimiters + cur_delimiter->getLength();
+						seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead();
 					}
 
 					insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, defaultColor, editor);
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index f6d75b7e755..d050cd7d7c8 100644
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -41,23 +41,44 @@ typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
 class LLKeywordToken
 {
 public:
-	enum TOKEN_TYPE { WORD, LINE, TWO_SIDED_DELIMITER, ONE_SIDED_DELIMITER };
+	/** 
+	 * @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.
+	 */
+	typedef enum 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 ) 
+	LLKeywordToken( TOKEN_TYPE type, const LLColor3& color, const LLWString& token, const LLWString& tool_tip, const LLWString& delimiter  ) 
 		:
 		mType( type ),
 		mToken( token ),
 		mColor( color ),
-		mToolTip( tool_tip )
+		mToolTip( tool_tip ),
+		mDelimiter( delimiter )		// right delimiter
 	{
 	}
 
-	S32					getLength() const		{ return mToken.size(); }
+	S32					getLengthHead() const	{ return mToken.size(); }
+	S32					getLengthTail() const	{ return mDelimiter.size(); }
 	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 LLWString&	getToolTip() const		{ return mToolTip; }
+	const LLWString&	getDelimiter() const	{ return mDelimiter; }
 
 #ifdef _DEBUG
 	void		dump();
@@ -68,6 +89,7 @@ class LLKeywordToken
 	LLWString	mToken;
 	LLColor3	mColor;
 	LLWString	mToolTip;
+	LLWString	mDelimiter;
 };
 
 class LLKeywords
@@ -85,7 +107,8 @@ class LLKeywords
 	void addToken(LLKeywordToken::TOKEN_TYPE type,
 					const std::string& key,
 					const LLColor3& color,
-					const std::string& tool_tip = LLStringUtil::null);
+					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*>.
diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini
index 9fa4046fdf1..810a10feec1 100644
--- a/indra/newview/app_settings/keywords.ini
+++ b/indra/newview/app_settings/keywords.ini
@@ -603,9 +603,11 @@ return				Leave current function or event handler
 # Comment
 [one_sided_delimiter .8, .3, .15]
 //					Comment:Non-functional commentary or disabled code
+[two_sided_delimiter .8, .3, .15]
+/* */				Comment:Non-functional commentary or disabled code
 
 # String literals
-[two_sided_delimiter 0, .2, 0]
+[double_quotation_marks 0, .2, 0]
 "					String literal
 
 #functions are supplied by the program now.
-- 
GitLab