From 671978e3927bc3ba9fc34008bbb7efd6f07b6c81 Mon Sep 17 00:00:00 2001
From: Alexander Gavriliuk <alexandrgproductengine@lindenlab.com>
Date: Wed, 17 May 2023 14:28:36 +0200
Subject: SL-19575 Create emoji gallery (fix bug with drawing emojis in chat
 history)

---
 indra/llcommon/llstring.cpp                        | 13 ++++-
 indra/llui/llemojidictionary.cpp                   | 11 ++++
 indra/llui/llemojidictionary.h                     |  1 +
 indra/llui/lltextbase.cpp                          | 41 ++++++++------
 indra/llui/lltextbase.h                            |  2 +-
 indra/newview/llchathistory.cpp                    | 62 +++++++---------------
 indra/newview/llfloateremojipicker.cpp             | 38 +++++++++----
 indra/newview/llfloateremojipicker.h               |  2 +-
 indra/newview/llfloaterimsessiontab.cpp            | 50 ++++++++---------
 indra/newview/llfloaterimsessiontab.h              |  2 +-
 indra/newview/llscripteditor.cpp                   |  2 +-
 .../skins/default/xui/en/widgets/chat_history.xml  | 10 ++--
 12 files changed, 125 insertions(+), 109 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index cda1791e45..d68cbaa22c 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -837,10 +837,19 @@ std::string LLStringOps::sPM;
 // static
 bool LLStringOps::isEmoji(llwchar wch)
 {
-	switch (ublock_getCode(wch))
-	{
+	int ublock = ublock_getCode(wch);
+	switch (ublock)
+	{
+		case UBLOCK_GENERAL_PUNCTUATION:
+		case UBLOCK_LETTERLIKE_SYMBOLS:
+		case UBLOCK_ARROWS:
+		case UBLOCK_MISCELLANEOUS_TECHNICAL:
+		case UBLOCK_ENCLOSED_ALPHANUMERICS:
+		case UBLOCK_GEOMETRIC_SHAPES:
 		case UBLOCK_MISCELLANEOUS_SYMBOLS:
 		case UBLOCK_DINGBATS:
+		case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
+		case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS:
 		case UBLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS:
 		case UBLOCK_EMOTICONS:
 		case UBLOCK_TRANSPORT_AND_MAP_SYMBOLS:
diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp
index bb5c94689a..179c5d25bf 100644
--- a/indra/llui/llemojidictionary.cpp
+++ b/indra/llui/llemojidictionary.cpp
@@ -199,6 +199,17 @@ std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) const
 	return (mEmoji2Descr.end() != it) ? it->second->Name : LLStringUtil::null;
 }
 
+bool LLEmojiDictionary::isEmoji(llwchar ch) const
+{
+	// Currently used codes: A9,AE,203C,2049,2122,...,2B55,3030,303D,3297,3299,1F004,...,1FAF6
+	if (ch == 0xA9 || ch == 0xAE || (ch >= 0x2000 && ch < 0x3300) || (ch >= 0x1F000 && ch < 0x20000))
+	{
+		return mEmoji2Descr.find(ch) != mEmoji2Descr.end();
+	}
+
+	return false;
+}
+
 void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr)
 {
 	mEmojis.push_back(descr);
diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h
index 88ff5b8300..cc26f75ea3 100644
--- a/indra/llui/llemojidictionary.h
+++ b/indra/llui/llemojidictionary.h
@@ -68,6 +68,7 @@ public:
 	const LLEmojiDescriptor* getDescriptorFromEmoji(llwchar emoji) const;
 	const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const;
 	std::string getNameFromEmoji(llwchar ch) const;
+	bool isEmoji(llwchar ch) const;
 
 	const emoji2descr_map_t& getEmoji2Descr() const { return mEmoji2Descr; }
 	const code2descr_map_t& getShortCode2Descr() const { return mShortCode2Descr; }
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 0066e09cfc..e7273c96c1 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -29,6 +29,7 @@
 
 #include "lltextbase.h"
 
+#include "llemojidictionary.h"
 #include "llemojihelper.h"
 #include "lllocalcliprect.h"
 #include "llmenugl.h"
@@ -366,7 +367,7 @@ void LLTextBase::onValueChange(S32 start, S32 end)
 {
 }
 
-std::vector<LLRect> LLTextBase::getSelctionRects()
+std::vector<LLRect> LLTextBase::getSelectionRects()
 {
     // Nor supposed to be called without selection
     llassert(hasSelection());
@@ -463,7 +464,7 @@ void LLTextBase::drawSelectionBackground()
     // Draw selection even if we don't have keyboard focus for search/replace
     if (hasSelection() && !mLineInfoList.empty())
     {
-        std::vector<LLRect> selection_rects = getSelctionRects();
+        std::vector<LLRect> selection_rects = getSelectionRects();
 		
 		// Draw the selection box (we're using a box instead of reversing the colors on the selected text).
 		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -904,9 +905,12 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
 	// Insert special segments where necessary (insertSegment takes care of splitting normal text segments around them for us)
 	{
 		LLStyleSP emoji_style;
+		LLEmojiDictionary* ed = LLEmojiDictionary::instanceExists() ? LLEmojiDictionary::getInstance() : NULL;
 		for (S32 text_kitty = 0, text_len = wstr.size(); text_kitty < text_len; text_kitty++)
 		{
-			if (LLStringOps::isEmoji(wstr[text_kitty]))
+			llwchar code = wstr[text_kitty];
+			bool isEmoji = ed ? ed->isEmoji(code) : LLStringOps::isEmoji(code);
+			if (isEmoji)
 			{
 				if (!emoji_style)
 				{
@@ -2181,8 +2185,8 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
 		S32 start=0,end=0;
 		LLUrlMatch match;
 		std::string text = new_text;
-		while ( LLUrlRegistry::instance().findUrl(text, match,
-				boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted() || mAlwaysShowIcons))
+		while (LLUrlRegistry::instance().findUrl(text, match,
+				boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3), isContentTrusted() || mAlwaysShowIcons))
 		{
 			start = match.getStart();
 			end = match.getEnd()+1;
@@ -2430,18 +2434,18 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
 			LLStyle::Params normal_style_params(style_params);
 			normal_style_params.font.style("NORMAL");
 			LLStyleConstSP normal_sp(new LLStyle(normal_style_params));
-			segments.push_back(new LLOnHoverChangeableTextSegment(sp, normal_sp, segment_start, segment_end, *this ));
+			segments.push_back(new LLOnHoverChangeableTextSegment(sp, normal_sp, segment_start, segment_end, *this));
 		}
 		else
 		{
-		segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this ));
+			segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this));
 		}
 
 		insertStringNoUndo(getLength(), wide_text, &segments);
 	}
 
 	// Set the cursor and scroll position
-	if( selection_start != selection_end )
+	if (selection_start != selection_end)
 	{
 		mSelectionStart = selection_start;
 		mSelectionEnd = selection_end;
@@ -2449,7 +2453,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
 		mIsSelecting = was_selecting;
 		setCursorPos(cursor_pos);
 	}
-	else if( cursor_was_at_end )
+	else if (cursor_was_at_end)
 	{
 		setCursorPos(getLength());
 	}
@@ -2461,25 +2465,28 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
 
 void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only)
 {
-	if (new_text.empty()) return; 
+	if (new_text.empty())
+	{
+		return; 
+	}
 
 	std::string::size_type start = 0;
-	std::string::size_type pos = new_text.find("\n",start);
+	std::string::size_type pos = new_text.find("\n", start);
 	
-	while(pos!=-1)
+	while (pos != std::string::npos)
 	{
-		if(pos!=start)
+		if (pos != start)
 		{
 			std::string str = std::string(new_text,start,pos-start);
-			appendAndHighlightTextImpl(str,highlight_part, style_params, underline_on_hover_only);
+			appendAndHighlightTextImpl(str, highlight_part, style_params, underline_on_hover_only);
 		}
 		appendLineBreakSegment(style_params);
 		start = pos+1;
-		pos = new_text.find("\n",start);
+		pos = new_text.find("\n", start);
 	}
 
-	std::string str = std::string(new_text,start,new_text.length()-start);
-	appendAndHighlightTextImpl(str,highlight_part, style_params, underline_on_hover_only);
+	std::string str = std::string(new_text, start, new_text.length() - start);
+	appendAndHighlightTextImpl(str, highlight_part, style_params, underline_on_hover_only);
 }
 
 
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 9b3691e404..37ab798a1d 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -654,7 +654,7 @@ protected:
 		return mLabel.getString() + getToolTip();
 	}
 
-    std::vector<LLRect> getSelctionRects();
+    std::vector<LLRect> getSelectionRects();
 
 protected:
 	// text segmentation and flow
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index f4fa449ca2..f29d7ec29b 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -1215,9 +1215,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 
 	llassert(mEditor);
 	if (!mEditor)
-	{
 		return;
-	}
 
 	bool from_me = chat.mFromID == gAgent.getID();
 	mEditor->setPlainText(use_plain_text_chat_history);
@@ -1227,26 +1225,16 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		mUnreadChatSources.insert(chat.mFromName);
 		mMoreChatPanel->setVisible(TRUE);
 		std::string chatters;
-		for (unread_chat_source_t::iterator it = mUnreadChatSources.begin();
-			it != mUnreadChatSources.end();)
+		for (const std::string& source : mUnreadChatSources)
 		{
-			chatters += *it;
-			if (++it != mUnreadChatSources.end())
-			{
-				chatters += ", ";
-			}
+			chatters += chatters.size() ? ", " + source : source;
 		}
 		LLStringUtil::format_map_t args;
 		args["SOURCES"] = chatters;
 
-		if (mUnreadChatSources.size() == 1)
-		{
-			mMoreChatText->setValue(LLTrans::getString("unread_chat_single", args));
-		}
-		else
-		{
-			mMoreChatText->setValue(LLTrans::getString("unread_chat_multiple", args));
-		}
+		std::string xml_desc = mUnreadChatSources.size() == 1 ?
+			"unread_chat_single" : "unread_chat_multiple";
+		mMoreChatText->setValue(LLTrans::getString(xml_desc, args));
 		S32 height = mMoreChatText->getTextPixelHeight() + 5;
 		mMoreChatPanel->reshape(mMoreChatPanel->getRect().getWidth(), height);
 	}
@@ -1294,11 +1282,11 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		body_message_params.font.style = "ITALIC";
 	}
 
-	if(chat.mChatType == CHAT_TYPE_WHISPER)
+	if (chat.mChatType == CHAT_TYPE_WHISPER)
 	{
 		body_message_params.font.style = "ITALIC";
 	}
-	else if(chat.mChatType == CHAT_TYPE_SHOUT)
+	else if (chat.mChatType == CHAT_TYPE_SHOUT)
 	{
 		body_message_params.font.style = "BOLD";
 	}
@@ -1345,10 +1333,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		}
 
 		// names showing
-		if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0)
+		if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size())
 		{
 			// Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text.
-			if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull())
+			if (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull())
 			{
 				// for object IMs, create a secondlife:///app/objectim SLapp
 				std::string url = LLViewerChat::getSenderSLURL(chat, args);
@@ -1408,36 +1396,27 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 			&& mIsLastMessageFromLog == message_from_log)  //distinguish between current and previous chat session's histories
 		{
 			view = getSeparator();
-			p.top_pad = mTopSeparatorPad;
-			p.bottom_pad = mBottomSeparatorPad;
             if (!view)
             {
                 // Might be wiser to make this LL_ERRS, getSeparator() should work in case of correct instalation.
                 LL_WARNS() << "Failed to create separator from " << mMessageSeparatorFilename << ": can't append to history" << LL_ENDL;
                 return;
             }
+
+			p.top_pad = mTopSeparatorPad;
+			p.bottom_pad = mBottomSeparatorPad;
 		}
 		else
 		{
 			view = getHeader(chat, name_params, args);
-			if (mEditor->getLength() == 0)
-				p.top_pad = 0;
-			else
-				p.top_pad = mTopHeaderPad;
-            if (teleport_separator)
-            {
-                p.bottom_pad = mBottomSeparatorPad;
-            }
-            else
-            {
-                p.bottom_pad = mBottomHeaderPad;
-            }
-            if (!view)
-            {
-                LL_WARNS() << "Failed to create header from " << mMessageHeaderFilename << ": can't append to history" << LL_ENDL;
-                return;
-            }
+			if (!view)
+			{
+				LL_WARNS() << "Failed to create header from " << mMessageHeaderFilename << ": can't append to history" << LL_ENDL;
+				return;
+			}
 			
+			p.top_pad = mEditor->getLength() ? mTopHeaderPad : 0;
+			p.bottom_pad = teleport_separator ? mBottomSeparatorPad : mBottomHeaderPad;
 		}
 		p.view = view;
 
@@ -1510,11 +1489,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		}
 	}
 	// usual messages showing
-	else if(!teleport_separator)
+	else if (!teleport_separator)
 	{
 		std::string message = irc_me ? chat.mText.substr(3) : chat.mText;
 
-
 		//MESSAGE TEXT PROCESSING
 		//*HACK getting rid of redundant sender names in system notifications sent using sender name (see EXT-5010)
 		if (use_plain_text_chat_history && !from_me && chat.mFromID.notNull())
diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp
index 9d28f7d4dc..98fe1e7ca1 100644
--- a/indra/newview/llfloateremojipicker.cpp
+++ b/indra/newview/llfloateremojipicker.cpp
@@ -60,9 +60,25 @@ public:
 	{
 		LLScrollListItem::draw(rect, fg_color, hover_color, select_color, highlight_color, column_padding);
 
+		LLWString wstr(1, mEmoji);
 		S32 width = getColumn(0)->getWidth();
-		LLFontGL::getFontEmoji()->render(LLWString(1, mEmoji), 0, rect.mLeft + width / 2, rect.getCenterY(), LLColor4::white,
-			LLFontGL::HCENTER, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW_SOFT, 1, S32_MAX, nullptr, false, true);
+		F32 x = rect.mLeft + width / 2;
+		F32 y = rect.getCenterY();
+		LLFontGL::getFontEmoji()->render(
+			wstr,                       // wstr
+			0,                          // begin_offset
+			x,                          // x
+			y,                          // y
+			LLColor4::white,            // color
+			LLFontGL::HCENTER,          // halign
+			LLFontGL::VCENTER,          // valign
+			LLFontGL::NORMAL,           // style
+			LLFontGL::DROP_SHADOW_SOFT, // shadow
+			1,                          // max_chars
+			S32_MAX,                    // max_pixels
+			nullptr,                    // right_x
+			false,                      // use_ellipses
+			true);                      // use_color
 	}
 
 private:
@@ -101,13 +117,13 @@ BOOL LLFloaterEmojiPicker::postBuild()
 {
 	// Should be initialized first
 	mPreviewEmoji = getChild<LLButton>("PreviewEmoji");
-	mPreviewEmoji->setClickedCallback(boost::bind(&LLFloaterEmojiPicker::onPreviewEmojiClick, this));
+	mPreviewEmoji->setClickedCallback([this](LLUICtrl*, const LLSD&) { onPreviewEmojiClick(); });
 
 	mCategory = getChild<LLComboBox>("Category");
-	mCategory->setCommitCallback(boost::bind(&LLFloaterEmojiPicker::onCategoryCommit, this));
+	mCategory->setCommitCallback([this](LLUICtrl*, const LLSD&) { onCategoryCommit(); });
 	const LLEmojiDictionary::cat2descrs_map_t& cat2Descrs = LLEmojiDictionary::instance().getCategory2Descrs();
 	mCategory->clearRows();
-	for (const LLEmojiDictionary::cat2descrs_item_t& item : cat2Descrs)
+	for (const LLEmojiDictionary::cat2descrs_item_t item : cat2Descrs)
 	{
 		std::string value = item.first;
 		std::string name = value;
@@ -117,13 +133,13 @@ BOOL LLFloaterEmojiPicker::postBuild()
 	mCategory->setSelectedByValue(mSelectedCategory, true);
 
 	mSearch = getChild<LLLineEditor>("Search");
-	mSearch->setKeystrokeCallback(boost::bind(&LLFloaterEmojiPicker::onSearchKeystroke, this, _1, _2), NULL);
+	mSearch->setKeystrokeCallback([this](LLLineEditor*, void*) { onSearchKeystroke(); }, NULL);
 	mSearch->setFont(LLViewerChat::getChatFont());
 	mSearch->setText(mSearchPattern);
 
 	mEmojis = getChild<LLScrollListCtrl>("Emojis");
-	mEmojis->setCommitCallback(boost::bind(&LLFloaterEmojiPicker::onEmojiSelect, this));
-	mEmojis->setDoubleClickCallback(boost::bind(&LLFloaterEmojiPicker::onEmojiPick, this));
+	mEmojis->setCommitCallback([this](LLUICtrl*, const LLSD&) { onEmojiSelect(); });
+	mEmojis->setDoubleClickCallback([this]() { onEmojiPick(); });
 	fillEmojis();
 
 	return TRUE;
@@ -139,7 +155,7 @@ void LLFloaterEmojiPicker::fillEmojis()
 	mEmojis->clearRows();
 
 	const LLEmojiDictionary::emoji2descr_map_t& emoji2Descr = LLEmojiDictionary::instance().getEmoji2Descr();
-	for (const LLEmojiDictionary::emoji2descr_item_t& it : emoji2Descr)
+	for (const LLEmojiDictionary::emoji2descr_item_t it : emoji2Descr)
 	{
 		const LLEmojiDescriptor* descr = it.second;
 
@@ -150,6 +166,8 @@ void LLFloaterEmojiPicker::fillEmojis()
 			continue;
 
 		LLScrollListItem::Params params;
+		// The following line adds default monochrome view of the emoji (is shown as an example)
+		//params.columns.add().column("look").value(wstring_to_utf8str(LLWString(1, it.first)));
 		params.columns.add().column("name").value(descr->Name);
 		mEmojis->addRow(new LLEmojiScrollListItem(it.first, params), params);
 	}
@@ -194,7 +212,7 @@ void LLFloaterEmojiPicker::onCategoryCommit()
 	fillEmojis();
 }
 
-void LLFloaterEmojiPicker::onSearchKeystroke(LLLineEditor* caller, void* user_data)
+void LLFloaterEmojiPicker::onSearchKeystroke()
 {
 	mSearchPattern = mSearch->getText();
 	mSelectedEmojiIndex = 0;
diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h
index 01335bbb5b..7327fb945e 100644
--- a/indra/newview/llfloateremojipicker.h
+++ b/indra/newview/llfloateremojipicker.h
@@ -57,7 +57,7 @@ private:
 	bool matchesPattern(const LLEmojiDescriptor* descr);
 
 	void onCategoryCommit();
-	void onSearchKeystroke(class LLLineEditor* caller, void* user_data);
+	void onSearchKeystroke();
 	void onPreviewEmojiClick();
 	void onEmojiSelect();
 	void onEmojiEmpty();
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 0571a0d855..dbd2d71f94 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -435,8 +435,8 @@ void LLFloaterIMSessionTab::onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self)
 		if (!picker->isShown())
 		{
 			picker->show(
-				boost::bind(&LLFloaterIMSessionTab::onEmojiPicked, self, _1),
-				boost::bind(&LLFloaterIMSessionTab::onEmojiPickerClosed, self));
+				[self](llwchar emoji) { self->onEmojiPicked(emoji); },
+				[self]() { self->onEmojiPickerClosed(); });
 			if (LLFloater* root_floater = gFloaterView->getParentFloater(self))
 			{
 				root_floater->addDependentFloater(picker, TRUE, TRUE);
@@ -461,51 +461,43 @@ void LLFloaterIMSessionTab::onEmojiPickerClosed()
 
 std::string LLFloaterIMSessionTab::appendTime()
 {
-	time_t utc_time;
-	utc_time = time_corrected();
-	std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
-		+LLTrans::getString("TimeMin")+"]";
+	std::string timeStr = "[" + LLTrans::getString("TimeHour") + "]:"
+						  "[" + LLTrans::getString("TimeMin") + "]";
 
 	LLSD substitution;
-
-	substitution["datetime"] = (S32) utc_time;
-	LLStringUtil::format (timeStr, substitution);
+	substitution["datetime"] = (S32)time_corrected();
+	LLStringUtil::format(timeStr, substitution);
 
 	return timeStr;
 }
 
-void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args)
+void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD& args)
 {
+	if (chat.mMuted || !mChatHistory)
+		return;
 
 	// Update the participant activity time
 	LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();
 	if (im_box)
 	{
-		im_box->setTimeNow(mSessionID,chat.mFromID);
+		im_box->setTimeNow(mSessionID, chat.mFromID);
 	}
 	
-
 	LLChat& tmp_chat = const_cast<LLChat&>(chat);
 
-	if(tmp_chat.mTimeStr.empty())
+	if (tmp_chat.mTimeStr.empty())
 		tmp_chat.mTimeStr = appendTime();
 
-	if (!chat.mMuted)
-	{
-		tmp_chat.mFromName = chat.mFromName;
-		LLSD chat_args;
-		if (args) chat_args = args;
-		chat_args["use_plain_text_chat_history"] =
-				gSavedSettings.getBOOL("PlainTextChatHistory");
-		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime");
-		chat_args["show_names_for_p2p_conv"] =
-				!mIsP2PChat || gSavedSettings.getBOOL("IMShowNamesForP2PConv");
-
-		if (mChatHistory)
-		{
-			mChatHistory->appendMessage(chat, chat_args);
-		}
-	}
+	tmp_chat.mFromName = chat.mFromName;
+
+	LLSD chat_args = args;
+	chat_args["use_plain_text_chat_history"] =
+			gSavedSettings.getBOOL("PlainTextChatHistory");
+	chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime");
+	chat_args["show_names_for_p2p_conv"] = !mIsP2PChat ||
+			gSavedSettings.getBOOL("IMShowNamesForP2PConv");
+
+	mChatHistory->appendMessage(chat, chat_args);
 }
 
 static LLTrace::BlockTimerStatHandle FTM_BUILD_CONVERSATION_VIEW_PARTICIPANT("Build Conversation View");
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 3dcb767aa6..49be4f6bd1 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -140,7 +140,7 @@ protected:
 	/* virtual */ void onFocusReceived();
 
 	// prepare chat's params and out one message to chatHistory
-	void appendMessage(const LLChat& chat, const LLSD &args = 0);
+	void appendMessage(const LLChat& chat, const LLSD& args = LLSD());
 
 	std::string appendTime();
 	void assignResizeLimits();
diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp
index 140cbbedbe..3278bd3aa9 100644
--- a/indra/newview/llscripteditor.cpp
+++ b/indra/newview/llscripteditor.cpp
@@ -187,7 +187,7 @@ void LLScriptEditor::drawSelectionBackground()
 	// Draw selection even if we don't have keyboard focus for search/replace
 	if( hasSelection() && !mLineInfoList.empty())
 	{
-        std::vector<LLRect> selection_rects = getSelctionRects();
+        std::vector<LLRect> selection_rects = getSelectionRects();
 
 		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 		const LLColor4& color = mReadOnly ? mReadOnlyFgColor : mFgColor;
diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
index c0a948931c..c4300c9350 100644
--- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml
+++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
@@ -10,11 +10,11 @@
   bottom_separator_pad="1"
   top_header_pad="12"
   bottom_header_pad="5"
-	max_length="2147483647"
-	track_bottom="true"
-	name="chat_history"
-	type="string"
-	word_wrap="true"
+  max_length="2147483647"
+  track_bottom="true"
+  name="chat_history"
+  type="string"
+  word_wrap="true"
   line_spacing.multiple="1.0" 
   font="SansSerif">
   <more_chat_text
-- 
cgit v1.2.3