diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 75905d092740d4e838eb12e53a83b00e7d5f9f6f..c2f91ff7e01a365b7ea576d245933a66a0711421 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -84,8 +84,8 @@ void LLLineEditor::PrevalidateNamedFuncs::declareValues()
 	declare("non_negative_s32", LLLineEditor::prevalidateNonNegativeS32);
 	declare("alpha_num", LLLineEditor::prevalidateAlphaNum);
 	declare("alpha_num_space", LLLineEditor::prevalidateAlphaNumSpace);
-	declare("printable_not_pipe", LLLineEditor::prevalidatePrintableNotPipe);
-	declare("printable_no_space", LLLineEditor::prevalidatePrintableNoSpace);
+	declare("ascii_printable_no_pipe", LLLineEditor::prevalidateASCIIPrintableNoPipe);
+	declare("ascii_printable_no_space", LLLineEditor::prevalidateASCIIPrintableNoSpace);
 }
 
 LLLineEditor::Params::Params()
@@ -2186,20 +2186,28 @@ BOOL LLLineEditor::prevalidateAlphaNumSpace(const LLWString &str)
 	return rv;
 }
 
+// Used for most names of things stored on the server, due to old file-formats
+// that used the pipe (|) for multiline text storage.  Examples include
+// inventory item names, parcel names, object names, etc.
 // static
-BOOL LLLineEditor::prevalidatePrintableNotPipe(const LLWString &str)
+BOOL LLLineEditor::prevalidateASCIIPrintableNoPipe(const LLWString &str)
 {
 	BOOL rv = TRUE;
 	S32 len = str.length();
 	if(len == 0) return rv;
 	while(len--)
 	{
-		if('|' == str[len])
+		llwchar wc = str[len];
+		if (wc < 0x20
+			|| wc > 0x7f
+			|| wc == '|')
 		{
 			rv = FALSE;
 			break;
 		}
-		if(!((' ' == str[len]) || LLStringOps::isAlnum((char)str[len]) || LLStringOps::isPunct((char)str[len])))
+		if(!(wc == ' '
+			 || LLStringOps::isAlnum((char)wc)
+			 || LLStringOps::isPunct((char)wc) ) )
 		{
 			rv = FALSE;
 			break;
@@ -2209,15 +2217,19 @@ BOOL LLLineEditor::prevalidatePrintableNotPipe(const LLWString &str)
 }
 
 
+// Used for avatar names
 // static
-BOOL LLLineEditor::prevalidatePrintableNoSpace(const LLWString &str)
+BOOL LLLineEditor::prevalidateASCIIPrintableNoSpace(const LLWString &str)
 {
 	BOOL rv = TRUE;
 	S32 len = str.length();
 	if(len == 0) return rv;
 	while(len--)
 	{
-		if(LLStringOps::isSpace(str[len]))
+		llwchar wc = str[len];
+		if (wc < 0x20
+			|| wc > 0x7f
+			|| LLStringOps::isSpace(wc))
 		{
 			rv = FALSE;
 			break;
@@ -2232,6 +2244,7 @@ BOOL LLLineEditor::prevalidatePrintableNoSpace(const LLWString &str)
 	return rv;
 }
 
+
 // static
 BOOL LLLineEditor::prevalidateASCII(const LLWString &str)
 {
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index d3daa941cfe929d09ff6bbd228d17b17fb8089e4..4474963b1aff534468df87306f18ccb4f8dfd9dc 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -235,8 +235,8 @@ class LLLineEditor
 	static BOOL		prevalidateNonNegativeS32(const LLWString &str);
 	static BOOL		prevalidateAlphaNum(const LLWString &str );
 	static BOOL		prevalidateAlphaNumSpace(const LLWString &str );
-	static BOOL		prevalidatePrintableNotPipe(const LLWString &str); 
-	static BOOL		prevalidatePrintableNoSpace(const LLWString &str);
+	static BOOL		prevalidateASCIIPrintableNoPipe(const LLWString &str); 
+	static BOOL		prevalidateASCIIPrintableNoSpace(const LLWString &str);
 	static BOOL		prevalidateASCII(const LLWString &str);
 
 	static BOOL		postvalidateFloat(const std::string &str);
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index caaf47240fbf1f97e63428f21b3d17e36d1617a0..cd795282f91207c18eec85ffb8ed5eacd0c4578d 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -2380,6 +2380,14 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
 	width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
 	// if last character is a newline, then return true, forcing line break
 	llwchar last_char = text[mStart + first_char + num_chars - 1];
+
+	LLUIImagePtr image = mStyle->getImage();
+	if( image.notNull())
+	{
+		width += image->getWidth();
+		height = llmax(height, image->getHeight());
+	}
+
 	return num_chars >= 1 && last_char == '\n';
 }
 
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 94a2ca16f4300f1025633c08d4e649b2bcdaac83..74ae8db0c7ad026f2000f95cb253630703ae60c1 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -9645,116 +9645,6 @@
       <key>Value</key>
       <string>00000000-0000-0000-0000-000000000000</string>
     </map>
-    <key>UISndPieMenuAppear</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for opening pie menu (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>8eaed61f-92ff-6485-de83-4dcc938a478e</string>
-    </map>
-    <key>UISndPieMenuHide</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for closing pie menu (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>00000000-0000-0000-0000-000000000000</string>
-    </map>
-    <key>UISndPieMenuSliceHighlight0</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for selecting pie menu item 0 (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>d9f73cf8-17b4-6f7a-1565-7951226c305d</string>
-    </map>
-    <key>UISndPieMenuSliceHighlight1</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for selecting pie menu item 1 (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>f6ba9816-dcaf-f755-7b67-51b31b6233e5</string>
-    </map>
-    <key>UISndPieMenuSliceHighlight2</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for selecting pie menu item 2 (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>7aff2265-d05b-8b72-63c7-dbf96dc2f21f</string>
-    </map>
-    <key>UISndPieMenuSliceHighlight3</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for selecting pie menu item 3 (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>09b2184e-8601-44e2-afbb-ce37434b8ba1</string>
-    </map>
-    <key>UISndPieMenuSliceHighlight4</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for selecting pie menu item 4 (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>bbe4c7fc-7044-b05e-7b89-36924a67593c</string>
-    </map>
-    <key>UISndPieMenuSliceHighlight5</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for selecting pie menu item 5 (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>d166039b-b4f5-c2ec-4911-c85c727b016c</string>
-    </map>
-    <key>UISndPieMenuSliceHighlight6</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for selecting pie menu item 6 (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>242af82b-43c2-9a3b-e108-3b0c7e384981</string>
-    </map>
-    <key>UISndPieMenuSliceHighlight7</key>
-    <map>
-      <key>Comment</key>
-      <string>Sound file for selecting pie menu item 7 (uuid for sound asset)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>c1f334fb-a5be-8fe7-22b3-29631c21cf0b</string>
-    </map>
     <key>UISndSnapshot</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index aa584b3ae8295eca29c27e1720f6c5cba882f98e..94c303a30f797313138a6011ab837bbf97fe12ea 100644
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -126,7 +126,7 @@ void LLChannelManager::onLoginCompleted()
 	gViewerWindow->getRootView()->addChild(mStartUpChannel);
 
 	// init channel's position and size
-	S32 channel_right_bound = gViewerWindow->getWorldViewRectRaw().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
+	S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
 	S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
 	mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
 	mStartUpChannel->setMouseDownCallback(boost::bind(&LLSysWellWindow::onStartUpToastClick, LLFloaterReg::getTypedInstance<LLSysWellWindow>("syswell_window"), _2, _3, _4));
diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp
index 886f5ec9249c58b9010c5f89b3375268d6a3ce2c..cd3432190b7f4ea43531f7e15e817f53788a3db0 100644
--- a/indra/newview/llfloatergodtools.cpp
+++ b/indra/newview/llfloatergodtools.cpp
@@ -415,7 +415,7 @@ LLPanelRegionTools::LLPanelRegionTools()
 BOOL LLPanelRegionTools::postBuild()
 {
 	getChild<LLLineEditor>("region name")->setKeystrokeCallback(onChangeSimName, this);
-	childSetPrevalidate("region name", &LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("region name", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	childSetPrevalidate("estate", &LLLineEditor::prevalidatePositiveS32);
 	childSetPrevalidate("parentestate", &LLLineEditor::prevalidatePositiveS32);
 	childDisable("parentestate");
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 015a947d9179a730f4b993a650c256e9907bbd14..22d6098d5bc3706c5227f3551f71ef2288b1a095 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -347,13 +347,14 @@ BOOL LLPanelLandGeneral::postBuild()
 {
 	mEditName = getChild<LLLineEditor>("Name");
 	mEditName->setCommitCallback(onCommitAny, this);	
-	childSetPrevalidate("Name", LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("Name", LLLineEditor::prevalidateASCIIPrintableNoPipe);
 
 	mEditDesc = getChild<LLTextEditor>("Description");
 	mEditDesc->setCommitOnFocusLost(TRUE);
 	mEditDesc->setCommitCallback(onCommitAny, this);	
-	childSetPrevalidate("Description", LLLineEditor::prevalidatePrintableNotPipe);
-
+	// No prevalidate function - historically the prevalidate function was broken,
+	// allowing residents to put in characters like U+2661 WHITE HEART SUIT, so
+	// preserve that ability.
 	
 	mTextSalePending = getChild<LLTextBox>("SalePending");
 	mTextOwnerLabel = getChild<LLTextBox>("Owner:");
diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp
index 3fe711a1664d4f1c972271a7755b33033cfe7afe..d18f127f851ff3d45c2a5656186821ad4dbaa264 100644
--- a/indra/newview/llfloatermap.cpp
+++ b/indra/newview/llfloatermap.cpp
@@ -83,7 +83,6 @@ BOOL LLFloaterMap::postBuild()
 {
 	mMap = getChild<LLNetMap>("Net Map");
 	mMap->setScale(gSavedSettings.getF32("MiniMapScale"));
-	mMap->setRotateMap(gSavedSettings.getBOOL( "MiniMapRotate" ));
 	mMap->setToolTipMsg(getString("ToolTipMsg"));	
 	sendChildToBack(mMap);
 	
@@ -178,7 +177,8 @@ void LLFloaterMap::draw()
 {
 	F32 rotation = 0;
 
-	if( mMap->getRotateMap() )
+	static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
+	if( rotate_map )
 	{
 		// rotate subsequent draws to agent rotation
 		rotation = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index b7296518d460dddc3066068cb8171b8c7ea908c1..810761e034d4b4e694e21aed522cd841addffc97 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -111,7 +111,7 @@ BOOL LLFloaterNameDesc::postBuild()
 	if (NameEditor)
 	{
 		NameEditor->setMaxTextLength(DB_INV_ITEM_NAME_STR_LEN);
-		NameEditor->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe);
+		NameEditor->setPrevalidate(&LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	}
 
 	y -= llfloor(PREVIEW_LINE_HEIGHT * 1.2f);
@@ -123,7 +123,7 @@ BOOL LLFloaterNameDesc::postBuild()
 	if (DescEditor)
 	{
 		DescEditor->setMaxTextLength(DB_INV_ITEM_DESC_STR_LEN);
-		DescEditor->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe);
+		DescEditor->setPrevalidate(&LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	}
 
 	y -= llfloor(PREVIEW_LINE_HEIGHT * 1.2f);
diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp
index e0d4a59d9d6f6050a904d5bf565206225a864696..ff9002787ce859df3a36e5ce54cefd15c770bfa1 100644
--- a/indra/newview/llfloaterproperties.cpp
+++ b/indra/newview/llfloaterproperties.cpp
@@ -130,9 +130,9 @@ BOOL LLFloaterProperties::postBuild()
 {
 	// build the UI
 	// item name & description
-	childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitName,this));
-	childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLFloaterProperties:: onCommitDescription, this));
 	// Creator information
 	getChild<LLUICtrl>("BtnCreator")->setCommitCallback(boost::bind(&LLFloaterProperties::onClickCreator,this));
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 4192c6a586202736c6fb222f5ac9d7ad0d8a2e4a..955bc64e05dfe91f96ad171a73232e819d1ecbb1 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -220,7 +220,7 @@ LLFolderView::LLFolderView(const Params& p)
 	params.font(getLabelFontForStyle(LLFontGL::NORMAL));
 	params.max_length_bytes(DB_INV_ITEM_NAME_STR_LEN);
 	params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2));
-	params.prevalidate_callback(&LLLineEditor::prevalidatePrintableNotPipe);
+	params.prevalidate_callback(&LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	params.commit_on_focus_lost(true);
 	params.visible(false);
 	mRenamer = LLUICtrlFactory::create<LLLineEditor> (params);
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 1f8054379100fc78a4aa60c40e7f1b891484aa15..dbbf98ad08aefdf75d1b2d81ea5f45d4dec39d9e 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -358,7 +358,7 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
 
 void LLIMFloater::getAllowedRect(LLRect& rect)
 {
-	rect = gViewerWindow->getWorldViewRectRaw();
+	rect = gViewerWindow->getWorldViewRectScaled();
 }
 
 void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp
index 524a889f972754372cbdfcbd00a91534adb7bbb7..c081af587938c392a3c556ffe932919c972a3bf7 100644
--- a/indra/newview/llimhandler.cpp
+++ b/indra/newview/llimhandler.cpp
@@ -58,7 +58,7 @@ LLIMHandler::~LLIMHandler()
 //--------------------------------------------------------------------------
 void LLIMHandler::initChannel()
 {
-	S32 channel_right_bound = gViewerWindow->getWorldViewRectRaw().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
+	S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
 	S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
 	mChannel->init(channel_right_bound - channel_width, channel_right_bound);
 }
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index dd78bb631fd7b5994cb0f183a65bb846f87c1619..ad80e7ed61098ff244c78c858a39d18f17981b5b 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -1,2556 +1,2556 @@
-/** 
- * @file LLIMMgr.cpp
- * @brief Container for Instant Messaging
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
- * Copyright (c) 2001-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llimview.h"
-
-#include "llfloaterreg.h"
-#include "llfontgl.h"
-#include "llrect.h"
-#include "llerror.h"
-#include "llbutton.h"
-#include "llhttpclient.h"
-#include "llsdutil_math.h"
-#include "llstring.h"
-#include "lluictrlfactory.h"
-
-#include "llagent.h"
-#include "llavatariconctrl.h"
-#include "llbottomtray.h"
-#include "llcallingcard.h"
-#include "llchat.h"
+/** 
+ * @file LLIMMgr.cpp
+ * @brief Container for Instant Messaging
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llimview.h"
+
+#include "llfloaterreg.h"
+#include "llfontgl.h"
+#include "llrect.h"
+#include "llerror.h"
+#include "llbutton.h"
+#include "llhttpclient.h"
+#include "llsdutil_math.h"
+#include "llstring.h"
+#include "lluictrlfactory.h"
+
+#include "llagent.h"
+#include "llavatariconctrl.h"
+#include "llbottomtray.h"
+#include "llcallingcard.h"
+#include "llchat.h"
 #include "llchiclet.h"
-#include "llresmgr.h"
-#include "llfloaterchat.h"
-#include "llfloaterchatterbox.h"
-#include "llavataractions.h"
-#include "llhttpnode.h"
-#include "llimfloater.h"
-#include "llimpanel.h"
-#include "llresizebar.h"
-#include "lltabcontainer.h"
-#include "llviewercontrol.h"
-#include "llfloater.h"
-#include "llmutelist.h"
-#include "llresizehandle.h"
-#include "llkeyboard.h"
-#include "llui.h"
-#include "llviewermenu.h"
-#include "llcallingcard.h"
-#include "lltoolbar.h"
-#include "llviewermessage.h"
-#include "llviewerwindow.h"
-#include "llnotify.h"
-#include "llviewerregion.h"
-#include "llvoicechannel.h"
-#include "lltrans.h"
-#include "llrecentpeople.h"
-#include "llsyswellwindow.h"
-
-#include "llfirstuse.h"
-#include "llagentui.h"
-
-//
-// Globals
-//
-LLIMMgr* gIMMgr = NULL;
-
-//
-// Statics
-//
-// *FIXME: make these all either UIStrings or Strings
-
-const static std::string IM_SEPARATOR(": ");
-
-
-void toast_callback(const LLSD& msg){
-	// do not show toast in busy mode or it goes from agent
-	if (gAgent.getBusy() || gAgent.getID() == msg["from_id"])
-	{
-		return;
-	}
-
-	// check whether incoming IM belongs to an active session or not
-	if (LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"])
-	{
-		return;
-	}
-
-	// Skip toasting for system messages
-	if (msg["from_id"].asUUID() == LLUUID::null)
-	{
-		return;
-	}
-
-	LLSD args;
-	args["MESSAGE"] = msg["message"];
-	args["TIME"] = msg["time"];
-	args["FROM"] = msg["from"];
-	args["FROM_ID"] = msg["from_id"];
-	args["SESSION_ID"] = msg["session_id"];
-
-	LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
-}
-
-void LLIMModel::setActiveSessionID(const LLUUID& session_id)
-{
-	// check if such an ID really exists
-	if (!findIMSession(session_id))
-	{
-		llwarns << "Trying to set as active a non-existent session!" << llendl;
-		return;
-	}
-
-	mActiveSessionID = session_id;
-}
-
-LLIMModel::LLIMModel() 
-{
-	addNewMsgCallback(LLIMFloater::newIMCallback);
-	addNewMsgCallback(toast_callback);
-}
-
-LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
-:	mSessionID(session_id),
-	mName(name),
-	mType(type),
-	mNumUnread(0),
-	mOtherParticipantID(other_participant_id),
-	mInitialTargetIDs(ids),
-	mVoiceChannel(NULL),
-	mSpeakers(NULL),
-	mSessionInitialized(false),
-	mCallBackEnabled(true),
-	mTextIMPossible(true),
-	mOtherParticipantIsAvatar(true)
-{
-	if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type)
-	{
-		mVoiceChannel  = new LLVoiceChannelP2P(session_id, name, other_participant_id);
-	}
-	else
-	{
-		mVoiceChannel = new LLVoiceChannelGroup(session_id, name);
-	}
-	mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);
-
-	// All participants will be added to the list of people we've recently interacted with.
-	mSpeakers->addListener(&LLRecentPeople::instance(), "add");
-
-	//we need to wait for session initialization for outgoing ad-hoc and group chat session
-	//correct session id for initiated ad-hoc chat will be received from the server
-	if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID, 
-		mInitialTargetIDs, mType))
-	{
-		//we don't need to wait for any responses
-		//so we're already initialized
-		mSessionInitialized = true;
-	}
-
-	if (IM_NOTHING_SPECIAL == type)
-	{
-		mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionID);
-		mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID);
-		mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID);
-	}
-
-	if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
-		LLLogChat::loadHistory(mName, &chatFromLogFile, (void *)this);
-}
-
-LLIMModel::LLIMSession::~LLIMSession()
-{
-	delete mSpeakers;
-	mSpeakers = NULL;
-
-	// End the text IM session if necessary
-	if(gVoiceClient && mOtherParticipantID.notNull())
-	{
-		switch(mType)
-		{
-		case IM_NOTHING_SPECIAL:
-		case IM_SESSION_P2P_INVITE:
-			gVoiceClient->endUserIMSession(mOtherParticipantID);
-			break;
-
-		default:
-			// Appease the linux compiler
-			break;
-		}
-	}
-
-	// HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point).
-	mVoiceChannel->deactivate();
-	
-	delete mVoiceChannel;
-	mVoiceChannel = NULL;
-}
-
-void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_id)
-{
-	mSessionInitialized = true;
-
-	if (new_session_id != mSessionID)
-	{
-		mSessionID = new_session_id;
-		mVoiceChannel->updateSessionID(new_session_id);
-	}
-}
-
-void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time)
-{
-	LLSD message;
-	message["from"] = from;
-	message["from_id"] = from_id;
-	message["message"] = utf8_text;
-	message["time"] = time; 
-	message["index"] = (LLSD::Integer)mMsgs.size(); 
-
-	mMsgs.push_front(message); 
-
-	if (mSpeakers && from_id.notNull())
-	{
-		mSpeakers->speakerChatted(from_id);
-		mSpeakers->setSpeakerTyping(from_id, FALSE);
-	}
-}
-
-void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata)
-{
-	if (!userdata) return;
-
-	LLIMSession* self = (LLIMSession*) userdata;
-
-	if (type == LLLogChat::LOG_LINE)
-	{
-		self->addMessage("", LLSD(), msg["message"].asString(), "");
-	}
-	else if (type == LLLogChat::LOG_LLSD)
-	{
-		self->addMessage(msg["from"].asString(), msg["from_id"].asUUID(), msg["message"].asString(), msg["time"].asString());
-	}
-}
-
-LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
-{
-	return get_if_there(mId2SessionMap, session_id,
-		(LLIMModel::LLIMSession*) NULL);
-}
-
-void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)
-{
-	LLIMSession* session = findIMSession(old_session_id);
-	if (session)
-	{
-		session->sessionInitReplyReceived(new_session_id);
-
-		if (old_session_id != new_session_id)
-		{
-			mId2SessionMap.erase(old_session_id);
-			mId2SessionMap[new_session_id] = session;
-
-			gIMMgr->notifyObserverSessionIDUpdated(old_session_id, new_session_id);
-		}
-
-		LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id);
-		if (im_floater)
-		{
-			im_floater->sessionInitReplyReceived(new_session_id);
-		}
-	}
-
-	//*TODO remove this "floater" stuff when Communicate Floater is gone
-	LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(old_session_id);
-	if (floater)
-	{
-		floater->sessionInitReplyReceived(new_session_id);
-	}
-}
-
-void LLIMModel::testMessages()
-{
-	LLUUID bot1_id("d0426ec6-6535-4c11-a5d9-526bb0c654d9");
-	LLUUID bot1_session_id;
-	std::string from = "IM Tester";
-
-	bot1_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot1_id);
-	newSession(bot1_session_id, from, IM_NOTHING_SPECIAL, bot1_id);
-	addMessage(bot1_session_id, from, bot1_id, "Test Message: Hi from testerbot land!");
-
-	LLUUID bot2_id;
-	std::string firstname[] = {"Roflcopter", "Joe"};
-	std::string lastname[] = {"Linden", "Tester", "Resident", "Schmoe"};
-
-	S32 rand1 = ll_rand(sizeof firstname)/(sizeof firstname[0]);
-	S32 rand2 = ll_rand(sizeof lastname)/(sizeof lastname[0]);
-	
-	from = firstname[rand1] + " " + lastname[rand2];
-	bot2_id.generate(from);
-	LLUUID bot2_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot2_id);
-	newSession(bot2_session_id, from, IM_NOTHING_SPECIAL, bot2_id);
-	addMessage(bot2_session_id, from, bot2_id, "Test Message: Hello there, I have a question. Can I bother you for a second? ");
-	addMessage(bot2_session_id, from, bot2_id, "Test Message: OMGWTFBBQ.");
-}
-
-
-bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, 
-						   const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
-{
-	if (findIMSession(session_id))
-	{
-		llwarns << "IM Session " << session_id << " already exists" << llendl;
-		return false;
-	}
-
-	LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids);
-	mId2SessionMap[session_id] = session;
-
-	LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, name, other_participant_id);
-
-	return true;
-
-}
-
-bool LLIMModel::clearSession(const LLUUID& session_id)
-{
-	if (mId2SessionMap.find(session_id) == mId2SessionMap.end()) return false;
-	delete (mId2SessionMap[session_id]);
-	mId2SessionMap.erase(session_id);
-	return true;
-}
-
-void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
-{
-	LLIMSession* session = findIMSession(session_id);
-	if (!session) 
-	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
-		return;
-	}
-
-	int i = session->mMsgs.size() - start_index;
-
-	for (std::list<LLSD>::iterator iter = session->mMsgs.begin(); 
-		iter != session->mMsgs.end() && i > 0;
-		iter++)
-	{
-		LLSD msg;
-		msg = *iter;
-		messages.push_back(*iter);
-		i--;
-	}
-
-	session->mNumUnread = 0;
-	
-	LLSD arg;
-	arg["session_id"] = session_id;
-	arg["num_unread"] = 0;
-	mNoUnreadMsgsSignal(arg);
-}
-
-bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {
-	
-	LLIMSession* session = findIMSession(session_id);
-
-	if (!session) 
-	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
-		return false;
-	}
-
-	session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false)); //might want to add date separately
-
-	return true;
-}
-
-bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
-{
-	S32 im_log_option =  gSavedPerAccountSettings.getS32("IMLogOptions");
-	if (im_log_option != LOG_CHAT)
-	{
-		if(im_log_option == LOG_BOTH_TOGETHER)
-		{
-			LLLogChat::saveHistory(std::string("chat"), from, from_id, utf8_text);
-			return true;
-		}
-		else
-		{
-			LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), from, from_id, utf8_text);
-			return true;
-		}
-	}
-	return false;
-}
-
-bool LLIMModel::proccessOnlineOfflineNotification(
-	const LLUUID& session_id, 
-	const std::string& utf8_text)
-{
-	// Add message to old one floater
-	LLFloaterIMPanel *floater = gIMMgr->findFloaterBySession(session_id);
-	if ( floater )
-	{
-		if ( !utf8_text.empty() )
-		{
-			floater->addHistoryLine(utf8_text, LLUIColorTable::instance().getColor("SystemChatColor"));
-		}
-	}
-	// Add system message to history
-	return addMessage(session_id, SYSTEM_FROM, LLUUID::null, utf8_text);
-}
-
-bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, 
-						   const std::string& utf8_text, bool log2file /* = true */) { 
-	LLIMSession* session = findIMSession(session_id);
-
-	if (!session) 
-	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
-		return false;
-	}
-
-	addToHistory(session_id, from, from_id, utf8_text);
-	if (log2file) logToFile(session_id, from, from_id, utf8_text);
-
-	session->mNumUnread++;
-
-	// notify listeners
-	LLSD arg;
-	arg["session_id"] = session_id;
-	arg["num_unread"] = session->mNumUnread;
-	arg["message"] = utf8_text;
-	arg["from"] = from;
-	arg["from_id"] = from_id;
-	arg["time"] = LLLogChat::timestamp(false);
-	mNewMsgSignal(arg);
-
-	return true;
-}
-
-
-const std::string& LLIMModel::getName(const LLUUID& session_id) const
-{
-	LLIMSession* session = findIMSession(session_id);
-
-	if (!session) 
-	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
-		return LLStringUtil::null;
-	}
-
-	return session->mName;
-}
-
-const S32 LLIMModel::getNumUnread(const LLUUID& session_id) const
-{
-	LLIMSession* session = findIMSession(session_id);
-	if (!session)
-	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
-		return -1;
-	}
-
-	return session->mNumUnread;
-}
-
-const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const
-{
-	LLIMSession* session = findIMSession(session_id);
-	if (!session)
-	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
-		return LLUUID::null;
-	}
-
-	return session->mOtherParticipantID;
-}
-
-EInstantMessage LLIMModel::getType(const LLUUID& session_id) const
-{
-	LLIMSession* session = findIMSession(session_id);
-	if (!session)
-	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
-		return IM_COUNT;
-	}
-
-	return session->mType;
-}
-
-LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id ) const
-{
-	LLIMSession* session = findIMSession(session_id);
-	if (!session)
-	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
-		return NULL;
-	}
-
-	return session->mVoiceChannel;
-}
-
-LLIMSpeakerMgr* LLIMModel::getSpeakerManager( const LLUUID& session_id ) const
-{
-	LLIMSession* session = findIMSession(session_id);
-	if (!session)
-	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
-		return NULL;
-	}
-
-	return session->mSpeakers;
-}
-
-
-// TODO get rid of other participant ID
-void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing) 
-{
-	std::string name;
-	LLAgentUI::buildFullname(name);
-
-	pack_instant_message(
-		gMessageSystem,
-		gAgent.getID(),
-		FALSE,
-		gAgent.getSessionID(),
-		other_participant_id,
-		name,
-		std::string("typing"),
-		IM_ONLINE,
-		(typing ? IM_TYPING_START : IM_TYPING_STOP),
-		session_id);
-	gAgent.sendReliableMessage();
-}
-
-void LLIMModel::sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id)
-{
-	if(session_id.notNull())
-	{
-		std::string name;
-		LLAgentUI::buildFullname(name);
-		pack_instant_message(
-			gMessageSystem,
-			gAgent.getID(),
-			FALSE,
-			gAgent.getSessionID(),
-			other_participant_id,
-			name, 
-			LLStringUtil::null,
-			IM_ONLINE,
-			IM_SESSION_LEAVE,
-			session_id);
-		gAgent.sendReliableMessage();
-	}
-}
-
-//*TODO this method is better be moved to the LLIMMgr
-void LLIMModel::sendMessage(const std::string& utf8_text,
-					 const LLUUID& im_session_id,
-					 const LLUUID& other_participant_id,
-					 EInstantMessage dialog)
-{
-	std::string name;
-	bool sent = false;
-	LLAgentUI::buildFullname(name);
-
-	const LLRelationship* info = NULL;
-	info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
-	
-	U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
-	
-	if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
-	{
-		// User is online through the OOW connector, but not with a regular viewer.  Try to send the message via SLVoice.
-		sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text);
-	}
-	
-	if(!sent)
-	{
-		// Send message normally.
-
-		// default to IM_SESSION_SEND unless it's nothing special - in
-		// which case it's probably an IM to everyone.
-		U8 new_dialog = dialog;
-
-		if ( dialog != IM_NOTHING_SPECIAL )
-		{
-			new_dialog = IM_SESSION_SEND;
-		}
-		pack_instant_message(
-			gMessageSystem,
-			gAgent.getID(),
-			FALSE,
-			gAgent.getSessionID(),
-			other_participant_id,
-			name.c_str(),
-			utf8_text.c_str(),
-			offline,
-			(EInstantMessage)new_dialog,
-			im_session_id);
-		gAgent.sendReliableMessage();
-	}
-
-	// If there is a mute list and this is not a group chat...
-	if ( LLMuteList::getInstance() )
-	{
-		// ... the target should not be in our mute list for some message types.
-		// Auto-remove them if present.
-		switch( dialog )
-		{
-		case IM_NOTHING_SPECIAL:
-		case IM_GROUP_INVITATION:
-		case IM_INVENTORY_OFFERED:
-		case IM_SESSION_INVITE:
-		case IM_SESSION_P2P_INVITE:
-		case IM_SESSION_CONFERENCE_START:
-		case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing.
-		case IM_LURE_USER:
-		case IM_GODLIKE_LURE_USER:
-		case IM_FRIENDSHIP_OFFERED:
-			LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM);
-			break;
-		default: ; // do nothing
-		}
-	}
-
-	if((dialog == IM_NOTHING_SPECIAL) && 
-	   (other_participant_id.notNull()))
-	{
-		// Do we have to replace the /me's here?
-		std::string from;
-		LLAgentUI::buildFullname(from);
-		LLIMModel::getInstance()->addMessage(im_session_id, from, gAgentID, utf8_text);
-
-		//local echo for the legacy communicate panel
-		std::string history_echo;
-		LLAgentUI::buildFullname(history_echo);
-
-		history_echo += ": " + utf8_text;
-
-		LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(im_session_id);
-		if (floater) floater->addHistoryLine(history_echo, LLUIColorTable::instance().getColor("IMChatColor"), true, gAgent.getID());
-
-		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(im_session_id);
-		if (speaker_mgr)
-		{
-			speaker_mgr->speakerChatted(gAgentID);
-			speaker_mgr->setSpeakerTyping(gAgentID, FALSE);
-		}
-	}
-
-	// Add the recipient to the recent people list.
-	LLRecentPeople::instance().add(other_participant_id);
-}
-
-void session_starter_helper(
-	const LLUUID& temp_session_id,
-	const LLUUID& other_participant_id,
-	EInstantMessage im_type)
-{
-	LLMessageSystem *msg = gMessageSystem;
-
-	msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
-	msg->nextBlockFast(_PREHASH_MessageBlock);
-	msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
-	msg->addUUIDFast(_PREHASH_ToAgentID, other_participant_id);
-	msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
-	msg->addU8Fast(_PREHASH_Dialog, im_type);
-	msg->addUUIDFast(_PREHASH_ID, temp_session_id);
-	msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
-
-	std::string name;
-	LLAgentUI::buildFullname(name);
-
-	msg->addStringFast(_PREHASH_FromAgentName, name);
-	msg->addStringFast(_PREHASH_Message, LLStringUtil::null);
-	msg->addU32Fast(_PREHASH_ParentEstateID, 0);
-	msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
-	msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
-}
-
-void start_deprecated_conference_chat(
-	const LLUUID& temp_session_id,
-	const LLUUID& creator_id,
-	const LLUUID& other_participant_id,
-	const LLSD& agents_to_invite)
-{
-	U8* bucket;
-	U8* pos;
-	S32 count;
-	S32 bucket_size;
-
-	// *FIX: this could suffer from endian issues
-	count = agents_to_invite.size();
-	bucket_size = UUID_BYTES * count;
-	bucket = new U8[bucket_size];
-	pos = bucket;
-
-	for(S32 i = 0; i < count; ++i)
-	{
-		LLUUID agent_id = agents_to_invite[i].asUUID();
-		
-		memcpy(pos, &agent_id, UUID_BYTES);
-		pos += UUID_BYTES;
-	}
-
-	session_starter_helper(
-		temp_session_id,
-		other_participant_id,
-		IM_SESSION_CONFERENCE_START);
-
-	gMessageSystem->addBinaryDataFast(
-		_PREHASH_BinaryBucket,
-		bucket,
-		bucket_size);
-
-	gAgent.sendReliableMessage();
- 
-	delete[] bucket;
-}
-
-class LLStartConferenceChatResponder : public LLHTTPClient::Responder
-{
-public:
-	LLStartConferenceChatResponder(
-		const LLUUID& temp_session_id,
-		const LLUUID& creator_id,
-		const LLUUID& other_participant_id,
-		const LLSD& agents_to_invite)
-	{
-		mTempSessionID = temp_session_id;
-		mCreatorID = creator_id;
-		mOtherParticipantID = other_participant_id;
-		mAgents = agents_to_invite;
-	}
-
-	virtual void error(U32 statusNum, const std::string& reason)
-	{
-		//try an "old school" way.
-		if ( statusNum == 400 )
-		{
-			start_deprecated_conference_chat(
-				mTempSessionID,
-				mCreatorID,
-				mOtherParticipantID,
-				mAgents);
-		}
-
-		//else throw an error back to the client?
-		//in theory we should have just have these error strings
-		//etc. set up in this file as opposed to the IMMgr,
-		//but the error string were unneeded here previously
-		//and it is not worth the effort switching over all
-		//the possible different language translations
-	}
-
-private:
-	LLUUID mTempSessionID;
-	LLUUID mCreatorID;
-	LLUUID mOtherParticipantID;
-
-	LLSD mAgents;
-};
-
-// Returns true if any messages were sent, false otherwise.
-// Is sort of equivalent to "does the server need to do anything?"
-bool LLIMModel::sendStartSession(
-	const LLUUID& temp_session_id,
-	const LLUUID& other_participant_id,
-	const std::vector<LLUUID>& ids,
-	EInstantMessage dialog)
-{
-	if ( dialog == IM_SESSION_GROUP_START )
-	{
-		session_starter_helper(
-			temp_session_id,
-			other_participant_id,
-			dialog);
-		gMessageSystem->addBinaryDataFast(
-				_PREHASH_BinaryBucket,
-				EMPTY_BINARY_BUCKET,
-				EMPTY_BINARY_BUCKET_SIZE);
-		gAgent.sendReliableMessage();
-
-		return true;
-	}
-	else if ( dialog == IM_SESSION_CONFERENCE_START )
-	{
-		LLSD agents;
-		for (int i = 0; i < (S32) ids.size(); i++)
-		{
-			agents.append(ids[i]);
-		}
-
-		//we have a new way of starting conference calls now
-		LLViewerRegion* region = gAgent.getRegion();
-		if (region)
-		{
-			std::string url = region->getCapability(
-				"ChatSessionRequest");
-			LLSD data;
-			data["method"] = "start conference";
-			data["session-id"] = temp_session_id;
-
-			data["params"] = agents;
-
-			LLHTTPClient::post(
-				url,
-				data,
-				new LLStartConferenceChatResponder(
-					temp_session_id,
-					gAgent.getID(),
-					other_participant_id,
-					data["params"]));
-		}
-		else
-		{
-			start_deprecated_conference_chat(
-				temp_session_id,
-				gAgent.getID(),
-				other_participant_id,
-				agents);
-		}
-
-		//we also need to wait for reply from the server in case of ad-hoc chat (we'll get new session id)
-		return true;
-	}
-
-	return false;
-}
-
-// static
-void LLIMModel::sendSessionInitialized(const LLUUID &session_id)
-{
-	LLIMSession* session = getInstance()->findIMSession(session_id);
-	if (session)
-	{
-		LLSD arg;
-		arg["session_id"] = session_id;
-		getInstance()->mSessionInitializedSignal(arg);
-	}
-}
-
-//
-// Helper Functions
-//
-
-class LLViewerChatterBoxInvitationAcceptResponder :
-	public LLHTTPClient::Responder
-{
-public:
-	LLViewerChatterBoxInvitationAcceptResponder(
-		const LLUUID& session_id,
-		LLIMMgr::EInvitationType invitation_type)
-	{
-		mSessionID = session_id;
-		mInvitiationType = invitation_type;
-	}
-
-	void result(const LLSD& content)
-	{
-		if ( gIMMgr)
-		{
-			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
-			if (speaker_mgr)
-			{
-				//we've accepted our invitation
-				//and received a list of agents that were
-				//currently in the session when the reply was sent
-				//to us.  Now, it is possible that there were some agents
-				//to slip in/out between when that message was sent to us
-				//and now.
-
-				//the agent list updates we've received have been
-				//accurate from the time we were added to the session
-				//but unfortunately, our base that we are receiving here
-				//may not be the most up to date.  It was accurate at
-				//some point in time though.
-				speaker_mgr->setSpeakers(content);
-
-				//we now have our base of users in the session
-				//that was accurate at some point, but maybe not now
-				//so now we apply all of the udpates we've received
-				//in case of race conditions
-				speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(mSessionID));
-			}
-
-			if (LLIMMgr::INVITATION_TYPE_VOICE == mInvitiationType)
-			{
-				gIMMgr->startCall(mSessionID);
-			}
-
-			if ((mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE 
-				|| mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE)
-				&& LLIMModel::getInstance()->findIMSession(mSessionID))
-			{
-				// always open IM window when connecting to voice
-				LLIMFloater::show(mSessionID);
-			}
-
-			gIMMgr->clearPendingAgentListUpdates(mSessionID);
-			gIMMgr->clearPendingInvitation(mSessionID);
-		}
-	}
-
-	void error(U32 statusNum, const std::string& reason)
-	{		
-		//throw something back to the viewer here?
-		if ( gIMMgr )
-		{
-			gIMMgr->clearPendingAgentListUpdates(mSessionID);
-			gIMMgr->clearPendingInvitation(mSessionID);
-			if ( 404 == statusNum )
-			{
-				std::string error_string;
-				error_string = "does not exist";
-				gIMMgr->showSessionStartError(error_string, mSessionID);
-			}
-		}
-	}
-
-private:
-	LLUUID mSessionID;
-	LLIMMgr::EInvitationType mInvitiationType;
-};
-
-
-// the other_participant_id is either an agent_id, a group_id, or an inventory
-// folder item_id (collection of calling cards)
-
-// static
-LLUUID LLIMMgr::computeSessionID(
-	EInstantMessage dialog,
-	const LLUUID& other_participant_id)
-{
-	LLUUID session_id;
-	if (IM_SESSION_GROUP_START == dialog)
-	{
-		// slam group session_id to the group_id (other_participant_id)
-		session_id = other_participant_id;
-	}
-	else if (IM_SESSION_CONFERENCE_START == dialog)
-	{
-		session_id.generate();
-	}
-	else if (IM_SESSION_INVITE == dialog)
-	{
-		// use provided session id for invites
-		session_id = other_participant_id;
-	}
-	else
-	{
-		LLUUID agent_id = gAgent.getID();
-		if (other_participant_id == agent_id)
-		{
-			// if we try to send an IM to ourselves then the XOR would be null
-			// so we just make the session_id the same as the agent_id
-			session_id = agent_id;
-		}
-		else
-		{
-			// peer-to-peer or peer-to-asset session_id is the XOR
-			session_id = other_participant_id ^ agent_id;
-		}
-	}
-	return session_id;
-}
-
-inline LLFloater* getFloaterBySessionID(const LLUUID session_id)
-{
-	LLFloater* floater = NULL;
-	if ( gIMMgr )
-	{
-		floater = dynamic_cast < LLFloater* >
-			( gIMMgr->findFloaterBySession(session_id) );
-	}
-	if ( !floater )
-	{
-		floater = dynamic_cast < LLFloater* >
-			( LLIMFloater::findInstance(session_id) );
-	}
-	return floater;
-}
-
-void
-LLIMMgr::showSessionStartError(
-	const std::string& error_string,
-	const LLUUID session_id)
-{
-	const LLFloater* floater = getFloaterBySessionID (session_id);
-	if (!floater) return;
-
-	LLSD args;
-	args["REASON"] = LLTrans::getString(error_string);
-	args["RECIPIENT"] = floater->getTitle();
-
-	LLSD payload;
-	payload["session_id"] = session_id;
-
-	LLNotifications::instance().add(
-		"ChatterBoxSessionStartError",
-		args,
-		payload,
-		LLIMMgr::onConfirmForceCloseError);
-}
-
-void
-LLIMMgr::showSessionEventError(
-	const std::string& event_string,
-	const std::string& error_string,
-	const LLUUID session_id)
-{
-	const LLFloater* floater = getFloaterBySessionID (session_id);
-	if (!floater) return;
-
-	LLSD args;
-	args["REASON"] =
-		LLTrans::getString(error_string);
-	args["EVENT"] =
-		LLTrans::getString(event_string);
-	args["RECIPIENT"] = floater->getTitle();
-
-	LLNotifications::instance().add(
-		"ChatterBoxSessionEventError",
-		args);
-}
-
-void
-LLIMMgr::showSessionForceClose(
-	const std::string& reason_string,
-	const LLUUID session_id)
-{
-	const LLFloater* floater = getFloaterBySessionID (session_id);
-	if (!floater) return;
-
-	LLSD args;
-
-	args["NAME"] = floater->getTitle();
-	args["REASON"] = LLTrans::getString(reason_string);
-
-	LLSD payload;
-	payload["session_id"] = session_id;
-
-	LLNotifications::instance().add(
-		"ForceCloseChatterBoxSession",
-		args,
-		payload,
-		LLIMMgr::onConfirmForceCloseError);
-}
-
-//static
-bool
-LLIMMgr::onConfirmForceCloseError(
-	const LLSD& notification,
-	const LLSD& response)
-{
-	//only 1 option really
-	LLUUID session_id = notification["payload"]["session_id"];
-
-	LLFloater* floater = getFloaterBySessionID (session_id);
-	if ( floater )
-	{
-		floater->closeFloater(FALSE);
-	}
-	return false;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLOutgoingCallDialog
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LLOutgoingCallDialog::LLOutgoingCallDialog(const LLSD& payload) :
-	LLDockableFloater(NULL, false, payload),
-	mPayload(payload)
-{
-}
-
-void LLOutgoingCallDialog::getAllowedRect(LLRect& rect)
-{
-	rect = gViewerWindow->getWorldViewRectRaw();
-}
-
-void LLOutgoingCallDialog::onOpen(const LLSD& key)
-{
-	// tell the user which voice channel they are leaving
-	if (!mPayload["old_channel_name"].asString().empty())
-	{
-		childSetTextArg("leaving", "[CURRENT_CHAT]", mPayload["old_channel_name"].asString());
-	}
-	else
-	{
-		childSetTextArg("leaving", "[CURRENT_CHAT]", getString("localchat"));
-	}
-
-	std::string callee_name = mPayload["session_name"].asString();
-	if (callee_name == "anonymous")
-	{
-		callee_name = getString("anonymous");
-	}
-	
-	setTitle(callee_name);
-
-	LLSD callee_id = mPayload["other_user_id"];
-	childSetTextArg("calling", "[CALLEE_NAME]", callee_name);
-	childSetTextArg("connecting", "[CALLEE_NAME]", callee_name);
-	LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
-	icon->setValue(callee_id);
-}
-
-
-//static
-void LLOutgoingCallDialog::onCancel(void* user_data)
-{
-	LLOutgoingCallDialog* self = (LLOutgoingCallDialog*)user_data;
-
-	if (!gIMMgr)
-		return;
-
-	LLUUID session_id = self->mPayload["session_id"].asUUID();
-	gIMMgr->endCall(session_id);
-	
-	self->closeFloater();
-}
-
-
-BOOL LLOutgoingCallDialog::postBuild()
-{
-	BOOL success = LLDockableFloater::postBuild();
-
-	childSetAction("Cancel", onCancel, this);
-
-	// dock the dialog to the sys well, where other sys messages appear
-	setDockControl(new LLDockControl(LLBottomTray::getInstance()->getSysWell(),
-					 this, getDockTongue(), LLDockControl::TOP,
-					 boost::bind(&LLOutgoingCallDialog::getAllowedRect, this, _1)));
-
-	return success;
-}
-
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLIncomingCallDialog
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) :
-	LLDockableFloater(NULL, false, payload),
-	mPayload(payload)
-{
-}
-
-BOOL LLIncomingCallDialog::postBuild()
-{
-	LLDockableFloater::postBuild();
-
-	LLSD caller_id = mPayload["caller_id"];
-	EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger();
-
-	std::string call_type = getString("VoiceInviteP2P");
-	std::string caller_name = mPayload["caller_name"].asString();
-	if (caller_name == "anonymous")
-	{
-		caller_name = getString("anonymous");
-	}
-	
-	setTitle(caller_name + " " + call_type);
-	
-	// If it is not a P2P invite, then it's an AdHoc invite
-	if ( type != IM_SESSION_P2P_INVITE )
-	{
-		call_type = getString("VoiceInviteAdHoc");
-	}
-
-	// check to see if this is an Avaline call
-	LLUUID session_id = mPayload["session_id"].asUUID();
-	bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id);
-	childSetVisible("Start IM", is_avatar); // no IM for avaline
-
-	LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
-	caller_name_widget->setValue(caller_name + " " + call_type);
-	LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
-	icon->setValue(caller_id);
-
-	childSetAction("Accept", onAccept, this);
-	childSetAction("Reject", onReject, this);
-	childSetAction("Start IM", onStartIM, this);
-	childSetFocus("Accept");
-
-	return TRUE;
-}
-
-void LLIncomingCallDialog::getAllowedRect(LLRect& rect)
-{
-	rect = gViewerWindow->getWorldViewRectRaw();
-}
-
-void LLIncomingCallDialog::onOpen(const LLSD& key)
-{
-	// tell the user which voice channel they would be leaving
-	LLVoiceChannel *voice = LLVoiceChannel::getCurrentVoiceChannel();
-	if (voice && !voice->getSessionName().empty())
-	{
-		childSetTextArg("question", "[CURRENT_CHAT]", voice->getSessionName());
-	}
-	else
-	{
-		childSetTextArg("question", "[CURRENT_CHAT]", getString("localchat"));
-	}
-
-	// dock the dialog to the sys well, where other sys messages appear
-	setDockControl(new LLDockControl(LLBottomTray::getInstance()->getSysWell(),
-									 this, getDockTongue(), LLDockControl::TOP,
-									 boost::bind(&LLIncomingCallDialog::getAllowedRect, this, _1)));
-}
-
-//static
-void LLIncomingCallDialog::onAccept(void* user_data)
-{
-	LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
-	self->processCallResponse(0);
-	self->closeFloater();
-}
-
-//static
-void LLIncomingCallDialog::onReject(void* user_data)
-{
-	LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
-	self->processCallResponse(1);
-	self->closeFloater();
-}
-
-//static
-void LLIncomingCallDialog::onStartIM(void* user_data)
-{
-	LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
-	self->processCallResponse(2);
-	self->closeFloater();
-}
-
-void LLIncomingCallDialog::processCallResponse(S32 response)
-{
-	if (!gIMMgr)
-		return;
-
-	LLUUID session_id = mPayload["session_id"].asUUID();
-	EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger();
-	LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)mPayload["inv_type"].asInteger();
-	bool voice = true;
-	switch(response)
-	{
-	case 2: // start IM: just don't start the voice chat
-	{
-		voice = false;
-		/* FALLTHROUGH */
-	}
-	case 0: // accept
-	{
-		if (type == IM_SESSION_P2P_INVITE)
-		{
-			// create a normal IM session
-			session_id = gIMMgr->addP2PSession(
-				mPayload["session_name"].asString(),
-				mPayload["caller_id"].asUUID(),
-				mPayload["session_handle"].asString());
-
-			if (voice)
-			{
-				if (gIMMgr->startCall(session_id))
-				{
-					// always open IM window when connecting to voice
-					LLIMFloater::show(session_id);
-				}
-			}
-
-			gIMMgr->clearPendingAgentListUpdates(session_id);
-			gIMMgr->clearPendingInvitation(session_id);
-		}
-		else
-		{
-			LLUUID session_id = gIMMgr->addSession(
-				mPayload["session_name"].asString(),
-				type,
-				session_id);
-			if (session_id != LLUUID::null)
-			{
-				LLIMFloater::show(session_id);
-			}
-
-			std::string url = gAgent.getRegion()->getCapability(
-				"ChatSessionRequest");
-
-			if (voice)
-			{
-				LLSD data;
-				data["method"] = "accept invitation";
-				data["session-id"] = session_id;
-				LLHTTPClient::post(
-					url,
-					data,
-					new LLViewerChatterBoxInvitationAcceptResponder(
-						session_id,
-						inv_type));
-			}
-		}
-		if (voice)
-		{
-			break;
-		}
-	}
-	case 1: // decline
-	{
-		if (type == IM_SESSION_P2P_INVITE)
-		{
-			if(gVoiceClient)
-			{
-				std::string s = mPayload["session_handle"].asString();
-				gVoiceClient->declineInvite(s);
-			}
-		}
-		else
-		{
-			std::string url = gAgent.getRegion()->getCapability(
-				"ChatSessionRequest");
-
-			LLSD data;
-			data["method"] = "decline invitation";
-			data["session-id"] = session_id;
-			LLHTTPClient::post(
-				url,
-				data,
-				NULL);
-		}
-	}
-
-	gIMMgr->clearPendingAgentListUpdates(session_id);
-	gIMMgr->clearPendingInvitation(session_id);
-	}
-}
-
-bool inviteUserResponse(const LLSD& notification, const LLSD& response)
-{
-	if (!gIMMgr)
-		return false;
-
-	const LLSD& payload = notification["payload"];
-	LLUUID session_id = payload["session_id"].asUUID();
-	EInstantMessage type = (EInstantMessage)payload["type"].asInteger();
-	LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)payload["inv_type"].asInteger();
-	S32 option = LLNotification::getSelectedOption(notification, response);
-	switch(option) 
-	{
-	case 0: // accept
-		{
-			if (type == IM_SESSION_P2P_INVITE)
-			{
-				// create a normal IM session
-				session_id = gIMMgr->addP2PSession(
-					payload["session_name"].asString(),
-					payload["caller_id"].asUUID(),
-					payload["session_handle"].asString(),
-					payload["session_uri"].asString());
-
-				if (gIMMgr->startCall(session_id))
-				{
-					// always open IM window when connecting to voice
-					LLIMFloater::show(session_id);
-				}
-
-				gIMMgr->clearPendingAgentListUpdates(session_id);
-				gIMMgr->clearPendingInvitation(session_id);
-			}
-			else
-			{
-				LLUUID session_id = gIMMgr->addSession(
-					payload["session_name"].asString(),
-					type,
-					session_id);
-				if (session_id != LLUUID::null)
-				{
-					LLIMFloater::show(session_id);
-				}
-
-				std::string url = gAgent.getRegion()->getCapability(
-					"ChatSessionRequest");
-
-				LLSD data;
-				data["method"] = "accept invitation";
-				data["session-id"] = session_id;
-				LLHTTPClient::post(
-					url,
-					data,
-					new LLViewerChatterBoxInvitationAcceptResponder(
-						session_id,
-						inv_type));
-			}
-		}
-		break;
-	case 2: // mute (also implies ignore, so this falls through to the "ignore" case below)
-	{
-		// mute the sender of this invite
-		if (!LLMuteList::getInstance()->isMuted(payload["caller_id"].asUUID()))
-		{
-			LLMute mute(payload["caller_id"].asUUID(), payload["caller_name"].asString(), LLMute::AGENT);
-			LLMuteList::getInstance()->add(mute);
-		}
-	}
-	/* FALLTHROUGH */
-	
-	case 1: // decline
-	{
-		if (type == IM_SESSION_P2P_INVITE)
-		{
-			if(gVoiceClient)
-			{
-				std::string s = payload["session_handle"].asString();
-				gVoiceClient->declineInvite(s);
-			}
-		}
-		else
-		{
-			std::string url = gAgent.getRegion()->getCapability(
-				"ChatSessionRequest");
-
-			LLSD data;
-			data["method"] = "decline invitation";
-			data["session-id"] = session_id;
-			LLHTTPClient::post(
-				url,
-				data,
-				NULL);				
-		}
-	}
-
-	gIMMgr->clearPendingAgentListUpdates(session_id);
-	gIMMgr->clearPendingInvitation(session_id);
-	break;
-	}
-	
-	return false;
-}
-
-//
-// Member Functions
-//
-
-LLIMMgr::LLIMMgr() :
-	mIMReceived(FALSE)
-{
-	mPendingInvitations = LLSD::emptyMap();
-	mPendingAgentListUpdates = LLSD::emptyMap();
-}
-
-// Add a message to a session. 
-void LLIMMgr::addMessage(
-	const LLUUID& session_id,
-	const LLUUID& target_id,
-	const std::string& from,
-	const std::string& msg,
-	const std::string& session_name,
-	EInstantMessage dialog,
-	U32 parent_estate_id,
-	const LLUUID& region_id,
-	const LLVector3& position,
-	bool link_name) // If this is true, then we insert the name and link it to a profile
-{
-	LLUUID other_participant_id = target_id;
-
-	// don't process muted IMs
-	if (LLMuteList::getInstance()->isMuted(
-			other_participant_id,
-			LLMute::flagTextChat) && !LLMuteList::getInstance()->isLinden(from))
-	{
-		return;
-	}
-
-	LLFloaterIMPanel* floater;
-	LLUUID new_session_id = session_id;
-	if (new_session_id.isNull())
-	{
-		//no session ID...compute new one
-		new_session_id = computeSessionID(dialog, other_participant_id);
-	}
-
-	//*NOTE session_name is empty in case of incoming P2P sessions
-	std::string fixed_session_name = from;
-	if(!session_name.empty() && session_name.size()>1)
-	{
-		fixed_session_name = session_name;
-	}
-
-	bool new_session = !hasSession(new_session_id);
-	if (new_session)
-	{
-		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id);
-	}
-
-	floater = findFloaterBySession(new_session_id);
-	if (!floater)
-	{
-		floater = findFloaterBySession(other_participant_id);
-		if (floater)
-		{
-			llinfos << "found the IM session " << session_id 
-				<< " by participant " << other_participant_id << llendl;
-		}
-	}
-
-	// create IM window as necessary
-	if(!floater)
-	{
-		floater = createFloater(
-			new_session_id,
-			other_participant_id,
-			fixed_session_name,
-			dialog,
-			FALSE);
-	}
-
-	if (new_session)
-	{
-		// When we get a new IM, and if you are a god, display a bit
-		// of information about the source. This is to help liaisons
-		// when answering questions.
-		if(gAgent.isGodlike())
-		{
-			// *TODO:translate (low priority, god ability)
-			std::ostringstream bonus_info;
-			bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + ":" + " "
-				<< parent_estate_id
-				<< ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
-				<< ((parent_estate_id == 5) ? "," + LLTrans::getString ("IMTeen") : "");
-
-			// once we have web-services (or something) which returns
-			// information about a region id, we can print this out
-			// and even have it link to map-teleport or something.
-			//<< "*** region_id: " << region_id << std::endl
-			//<< "*** position: " << position << std::endl;
-
-			floater->addHistoryLine(bonus_info.str(), LLUIColorTable::instance().getColor("SystemChatColor"));
-			LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str());
-		}
-
-		make_ui_sound("UISndNewIncomingIMSession");
-	}
-
-	// now add message to floater
-	bool is_from_system = target_id.isNull() || (from == SYSTEM_FROM);
-	const LLColor4& color = ( is_from_system ? 
-							  LLUIColorTable::instance().getColor("SystemChatColor") : 
-							  LLUIColorTable::instance().getColor("IMChatColor"));
-	if ( !link_name )
-	{
-		floater->addHistoryLine(msg,color); // No name to prepend, so just add the message normally
-	}
-	else
-	{
-		floater->addHistoryLine(msg, color, true, other_participant_id, from); // Insert linked name to front of message
-	}
-
-	LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
-
-	if( !LLFloaterReg::instanceVisible("communicate") && !floater->getVisible())
-	{
-		LLFloaterChatterBox* chat_floater = LLFloaterChatterBox::getInstance();
-		
-		//if the IM window is not open and the floater is not visible (i.e. not torn off)
-		LLFloater* previouslyActiveFloater = chat_floater->getActiveFloater();
-
-		// select the newly added floater (or the floater with the new line added to it).
-		// it should be there.
-		chat_floater->selectFloater(floater);
-
-		//there was a previously unseen IM, make that old tab flashing
-		//it is assumed that the most recently unseen IM tab is the one current selected/active
-		if ( previouslyActiveFloater && getIMReceived() )
-		{
-			chat_floater->setFloaterFlashing(previouslyActiveFloater, TRUE);
-		}
-
-		//notify of a new IM
-		notifyNewIM();
-	}
-}
-
-void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args)
-{
-	LLUIString message;
-	
-	// null session id means near me (chat history)
-	if (session_id.isNull())
-	{
-		message = LLTrans::getString(message_name);
-		message.setArgs(args);
-
-		LLChat chat(message);
-		chat.mSourceType = CHAT_SOURCE_SYSTEM;
-		LLFloaterChat::addChatHistory(chat);
-	}
-	else // going to IM session
-	{
-		if (hasSession(session_id))
-		{
-			message = LLTrans::getString(message_name + "-im");
-			message.setArgs(args);
-			gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString());
-		}
-	}
-}
-
-void LLIMMgr::notifyNewIM()
-{
-	if(!LLFloaterReg::instanceVisible("communicate"))
-	{
-		mIMReceived = TRUE;
-	}
-}
-
-S32 LLIMMgr::getNumberOfUnreadIM()
-{
-	std::map<LLUUID, LLIMModel::LLIMSession*>::iterator it;
-	
-	S32 num = 0;
-	for(it = LLIMModel::getInstance()->mId2SessionMap.begin(); it != LLIMModel::getInstance()->mId2SessionMap.end(); ++it)
-	{
-		num += (*it).second->mNumUnread;
-	}
-
-	return num;
-}
-
-void LLIMMgr::clearNewIMNotification()
-{
-	mIMReceived = FALSE;
-}
-
-BOOL LLIMMgr::getIMReceived() const
-{
-	return mIMReceived;
-}
-
-LLUUID LLIMMgr::addP2PSession(const std::string& name,
-							const LLUUID& other_participant_id,
-							const std::string& voice_session_handle,
-							const std::string& caller_uri)
-{
-	LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id);
-	if (session_id != LLUUID::null)
-	{
-		LLIMFloater::show(session_id);
-	}
-
-	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
-	if (speaker_mgr)
-	{
-		LLVoiceChannelP2P* voice_channel = dynamic_cast<LLVoiceChannelP2P*>(speaker_mgr->getVoiceChannel());
-		if (voice_channel)
-		{
-			voice_channel->setSessionHandle(voice_session_handle, caller_uri);
-		}
-	}
-	return session_id;
-}
-
-// This adds a session to the talk view. The name is the local name of
-// the session, dialog specifies the type of session. If the session
-// exists, it is brought forward.  Specifying id = NULL results in an
-// im session to everyone. Returns the uuid of the session.
-LLUUID LLIMMgr::addSession(
-	const std::string& name,
-	EInstantMessage dialog,
-	const LLUUID& other_participant_id)
-{
-	LLDynamicArray<LLUUID> ids;
-	ids.put(other_participant_id);
-	return addSession(name, dialog, other_participant_id, ids);
-}
-
-// Adds a session using the given session_id.  If the session already exists 
-// the dialog type is assumed correct. Returns the uuid of the session.
-LLUUID LLIMMgr::addSession(
-	const std::string& name,
-	EInstantMessage dialog,
-	const LLUUID& other_participant_id,
-	const LLDynamicArray<LLUUID>& ids)
-{
-	if (0 == ids.getLength())
-	{
-		return LLUUID::null;
-	}
-
-	LLUUID session_id = computeSessionID(dialog,other_participant_id);
-
-	bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);
-
-	if (new_session)
-	{
-		LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids);
-	}
-
-
-	//*TODO remove this "floater" thing when Communicate Floater's gone
-	LLFloaterIMPanel* floater = findFloaterBySession(session_id);
-	if(!floater)
-	{
-		// On creation, use the first element of ids as the
-		// "other_participant_id"
-		floater = createFloater(
-			session_id,
-			other_participant_id,
-			name,
-			dialog,
-			TRUE,
-			ids);
-	}
-
-	//we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions
-	if (!new_session) return session_id;
-	
-	noteOfflineUsers(session_id, floater, ids);
-
-	// Only warn for regular IMs - not group IMs
-	if( dialog == IM_NOTHING_SPECIAL )
-	{
-		noteMutedUsers(session_id, floater, ids);
-	}
-
-	return session_id;
-}
-
-bool LLIMMgr::leaveSession(const LLUUID& session_id)
-{
-	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
-	if (!im_session) return false;
-
-	LLIMModel::getInstance()->sendLeaveSession(session_id, im_session->mOtherParticipantID);
-	gIMMgr->removeSession(session_id);
-	return true;
-}
-
-// Removes data associated with a particular session specified by session_id
-void LLIMMgr::removeSession(const LLUUID& session_id)
-{
-	llassert_always(hasSession(session_id));
-	
-	//*TODO remove this floater thing when Communicate Floater is being deleted (IB)
-	LLFloaterIMPanel* floater = findFloaterBySession(session_id);
-	if(floater)
-	{
-		mFloaters.erase(floater->getHandle());
-		LLFloaterChatterBox::getInstance()->removeFloater(floater);
-	}
-
-	clearPendingInvitation(session_id);
-	clearPendingAgentListUpdates(session_id);
-
-	LLIMModel::getInstance()->clearSession(session_id);
-
-	notifyObserverSessionRemoved(session_id);
-}
-
-void LLIMMgr::inviteToSession(
-	const LLUUID& session_id, 
-	const std::string& session_name, 
-	const LLUUID& caller_id, 
-	const std::string& caller_name,
-	EInstantMessage type,
-	EInvitationType inv_type,
-	const std::string& session_handle,
-	const std::string& session_uri)
-{
-	//ignore invites from muted residents
-	if (LLMuteList::getInstance()->isMuted(caller_id))
-	{
-		return;
-	}
-
-	std::string notify_box_type;
-
-	BOOL ad_hoc_invite = FALSE;
-	if(type == IM_SESSION_P2P_INVITE)
-	{
-		//P2P is different...they only have voice invitations
-		notify_box_type = "VoiceInviteP2P";
-	}
-	else if ( gAgent.isInGroup(session_id) )
-	{
-		//only really old school groups have voice invitations
-		notify_box_type = "VoiceInviteGroup";
-	}
-	else if ( inv_type == INVITATION_TYPE_VOICE )
-	{
-		//else it's an ad-hoc
-		//and a voice ad-hoc
-		notify_box_type = "VoiceInviteAdHoc";
-		ad_hoc_invite = TRUE;
-	}
-	else if ( inv_type == INVITATION_TYPE_IMMEDIATE )
-	{
-		notify_box_type = "InviteAdHoc";
-		ad_hoc_invite = TRUE;
-	}
-
-	LLSD payload;
-	payload["session_id"] = session_id;
-	payload["session_name"] = session_name;
-	payload["caller_id"] = caller_id;
-	payload["caller_name"] = caller_name;
-	payload["type"] = type;
-	payload["inv_type"] = inv_type;
-	payload["session_handle"] = session_handle;
-	payload["session_uri"] = session_uri;
-	payload["notify_box_type"] = notify_box_type;
-	
-	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(session_id);
-	if (channelp && channelp->callStarted())
-	{
-		// you have already started a call to the other user, so just accept the invite
-		LLNotifications::instance().forceResponse(LLNotification::Params("VoiceInviteP2P").payload(payload), 0);
-		return;
-	}
-
-	if (type == IM_SESSION_P2P_INVITE || ad_hoc_invite)
-	{
-		// is the inviter a friend?
-		if (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)
-		{
-			// if not, and we are ignoring voice invites from non-friends
-			// then silently decline
-			if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
-			{
-				// invite not from a friend, so decline
-				LLNotifications::instance().forceResponse(LLNotification::Params("VoiceInviteP2P").payload(payload), 1);
-				return;
-			}
-		}
-	}
-
-	if ( !mPendingInvitations.has(session_id.asString()) )
-	{
-		if (caller_name.empty())
-		{
-			gCacheName->get(caller_id, FALSE, boost::bind(&LLIMMgr::onInviteNameLookup, payload, _1, _2, _3, _4));
-		}
-		else
-		{
-			if (notify_box_type == "VoiceInviteP2P" || notify_box_type == "VoiceInviteAdHoc")
-			{
-				LLFloaterReg::showInstance("incoming_call", payload, TRUE);
-			}
-			else
-			{
-				LLSD args;
-				args["NAME"] = caller_name;
-				args["GROUP"] = session_name;
-
-				LLNotifications::instance().add(notify_box_type, args, payload, &inviteUserResponse);
-			}
-		}
-		mPendingInvitations[session_id.asString()] = LLSD();
-	}
-}
-
-void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
-{
-	payload["caller_name"] = first + " " + last;
-	payload["session_name"] = payload["caller_name"].asString();
-
-	std::string notify_box_type = payload["notify_box_type"].asString();
-
-	if (notify_box_type == "VoiceInviteP2P" || notify_box_type == "VoiceInviteAdHoc")
-	{
-		LLFloaterReg::showInstance("incoming_call", payload, TRUE);
-	}
-	else
-	{
-		LLSD args;
-		args["NAME"] = payload["caller_name"].asString();
-	
-		LLNotifications::instance().add(
-			payload["notify_box_type"].asString(),
-			args, 
-			payload,
-			&inviteUserResponse);
-	}
-}
-
-void LLIMMgr::disconnectAllSessions()
-{
-	LLFloaterIMPanel* floater = NULL;
-	std::set<LLHandle<LLFloater> >::iterator handle_it;
-	for(handle_it = mFloaters.begin();
-		handle_it != mFloaters.end();
-		)
-	{
-		floater = (LLFloaterIMPanel*)handle_it->get();
-
-		// MUST do this BEFORE calling floater->onClose() because that may remove the item from the set, causing the subsequent increment to crash.
-		++handle_it;
-
-		if (floater)
-		{
-			floater->setEnabled(FALSE);
-			floater->closeFloater(TRUE);
-		}
-	}
-}
-
-
-// This method returns the im panel corresponding to the uuid
-// provided. The uuid can either be a session id or an agent
-// id. Returns NULL if there is no matching panel.
-LLFloaterIMPanel* LLIMMgr::findFloaterBySession(const LLUUID& session_id)
-{
-	LLFloaterIMPanel* rv = NULL;
-	std::set<LLHandle<LLFloater> >::iterator handle_it;
-	for(handle_it = mFloaters.begin();
-		handle_it != mFloaters.end();
-		++handle_it)
-	{
-		rv = (LLFloaterIMPanel*)handle_it->get();
-		if(rv && session_id == rv->getSessionID())
-		{
-			break;
-		}
-		rv = NULL;
-	}
-	return rv;
-}
-
-
-BOOL LLIMMgr::hasSession(const LLUUID& session_id)
-{
-	return LLIMModel::getInstance()->findIMSession(session_id) != NULL;
-}
-
-void LLIMMgr::clearPendingInvitation(const LLUUID& session_id)
-{
-	if ( mPendingInvitations.has(session_id.asString()) )
-	{
-		mPendingInvitations.erase(session_id.asString());
-	}
-}
-
-void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body)
-{
-	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
-	if ( im_floater )
-	{
-		im_floater->processAgentListUpdates(body);
-	}
-	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
-	if (speaker_mgr)
-	{
-		speaker_mgr->updateSpeakers(body);
-	}
-	else
-	{
-		//we don't have a speaker manager yet..something went wrong
-		//we are probably receiving an update here before
-		//a start or an acceptance of an invitation.  Race condition.
-		gIMMgr->addPendingAgentListUpdates(
-			session_id,
-			body);
-	}
-}
-
-LLSD LLIMMgr::getPendingAgentListUpdates(const LLUUID& session_id)
-{
-	if ( mPendingAgentListUpdates.has(session_id.asString()) )
-	{
-		return mPendingAgentListUpdates[session_id.asString()];
-	}
-	else
-	{
-		return LLSD();
-	}
-}
-
-void LLIMMgr::addPendingAgentListUpdates(
-	const LLUUID& session_id,
-	const LLSD& updates)
-{
-	LLSD::map_const_iterator iter;
-
-	if ( !mPendingAgentListUpdates.has(session_id.asString()) )
-	{
-		//this is a new agent list update for this session
-		mPendingAgentListUpdates[session_id.asString()] = LLSD::emptyMap();
-	}
-
-	if (
-		updates.has("agent_updates") &&
-		updates["agent_updates"].isMap() &&
-		updates.has("updates") &&
-		updates["updates"].isMap() )
-	{
-		//new school update
-		LLSD update_types = LLSD::emptyArray();
-		LLSD::array_iterator array_iter;
-
-		update_types.append("agent_updates");
-		update_types.append("updates");
-
-		for (
-			array_iter = update_types.beginArray();
-			array_iter != update_types.endArray();
-			++array_iter)
-		{
-			//we only want to include the last update for a given agent
-			for (
-				iter = updates[array_iter->asString()].beginMap();
-				iter != updates[array_iter->asString()].endMap();
-				++iter)
-			{
-				mPendingAgentListUpdates[session_id.asString()][array_iter->asString()][iter->first] =
-					iter->second;
-			}
-		}
-	}
-	else if (
-		updates.has("updates") &&
-		updates["updates"].isMap() )
-	{
-		//old school update where the SD contained just mappings
-		//of agent_id -> "LEAVE"/"ENTER"
-
-		//only want to keep last update for each agent
-		for (
-			iter = updates["updates"].beginMap();
-			iter != updates["updates"].endMap();
-			++iter)
-		{
-			mPendingAgentListUpdates[session_id.asString()]["updates"][iter->first] =
-				iter->second;
-		}
-	}
-}
-
-void LLIMMgr::clearPendingAgentListUpdates(const LLUUID& session_id)
-{
-	if ( mPendingAgentListUpdates.has(session_id.asString()) )
-	{
-		mPendingAgentListUpdates.erase(session_id.asString());
-	}
-}
-
-void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
-{
-	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
-	{
-		(*it)->sessionAdded(session_id, name, other_participant_id);
-	}
-}
-
-void LLIMMgr::notifyObserverSessionRemoved(const LLUUID& session_id)
-{
-	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
-	{
-		(*it)->sessionRemoved(session_id);
-	}
-}
-
-void LLIMMgr::notifyObserverSessionIDUpdated( const LLUUID& old_session_id, const LLUUID& new_session_id )
-{
-	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
-	{
-		(*it)->sessionIDUpdated(old_session_id, new_session_id);
-	}
-
-}
-
-void LLIMMgr::addSessionObserver(LLIMSessionObserver *observer)
-{
-	mSessionObservers.push_back(observer);
-}
-
-void LLIMMgr::removeSessionObserver(LLIMSessionObserver *observer)
-{
-	mSessionObservers.remove(observer);
-}
-
-bool LLIMMgr::startCall(const LLUUID& session_id)
-{
-	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
-	if (!voice_channel) return false;
-	
-	voice_channel->activate();
-	return true;
-}
-
-bool LLIMMgr::endCall(const LLUUID& session_id)
-{
-	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
-	if (!voice_channel) return false;
-
-	voice_channel->deactivate();
-	return true;
-}
-
-// create a floater and update internal representation for
-// consistency. Returns the pointer, caller (the class instance since
-// it is a private method) is not responsible for deleting the
-// pointer.  Add the floater to this but do not select it.
-LLFloaterIMPanel* LLIMMgr::createFloater(
-	const LLUUID& session_id,
-	const LLUUID& other_participant_id,
-	const std::string& session_label,
-	EInstantMessage dialog,
-	BOOL user_initiated,
-	const LLDynamicArray<LLUUID>& ids)
-{
-	if (session_id.isNull())
-	{
-		llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl;
-	}
-
-	llinfos << "LLIMMgr::createFloater: from " << other_participant_id 
-			<< " in session " << session_id << llendl;
-	LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label,
-													 session_id,
-													 other_participant_id,
-													 ids,
-													 dialog);
-	LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
-	LLFloaterChatterBox::getInstance()->addFloater(floater, FALSE, i_pt);
-	mFloaters.insert(floater->getHandle());
-	return floater;
-}
-
-void LLIMMgr::noteOfflineUsers(
-	const LLUUID& session_id,
-	LLFloaterIMPanel* floater,
-	const LLDynamicArray<LLUUID>& ids)
-{
-	S32 count = ids.count();
-	if(count == 0)
-	{
-		const std::string& only_user = LLTrans::getString("only_user_message");
-		if (floater)
-		{
-			floater->addHistoryLine(only_user, LLUIColorTable::instance().getColor("SystemChatColor"));
-		}
-		LLIMModel::getInstance()->addMessage(session_id, SYSTEM_FROM, LLUUID::null, only_user);
-	}
-	else
-	{
-		const LLRelationship* info = NULL;
-		LLAvatarTracker& at = LLAvatarTracker::instance();
-		LLIMModel& im_model = LLIMModel::instance();
-		for(S32 i = 0; i < count; ++i)
-		{
-			info = at.getBuddyInfo(ids.get(i));
-			std::string first, last;
-			if(info && !info->isOnline()
-			   && gCacheName->getName(ids.get(i), first, last))
-			{
-				LLUIString offline = LLTrans::getString("offline_message");
-				offline.setArg("[FIRST]", first);
-				offline.setArg("[LAST]", last);
-				im_model.proccessOnlineOfflineNotification(session_id, offline);
-			}
-		}
-	}
-}
-
-void LLIMMgr::noteMutedUsers(const LLUUID& session_id, LLFloaterIMPanel* floater,
-								  const LLDynamicArray<LLUUID>& ids)
-{
-	// Don't do this if we don't have a mute list.
-	LLMuteList *ml = LLMuteList::getInstance();
-	if( !ml )
-	{
-		return;
-	}
-
-	S32 count = ids.count();
-	if(count > 0)
-	{
-		LLIMModel* im_model = LLIMModel::getInstance();
-		
-		for(S32 i = 0; i < count; ++i)
-		{
-			if( ml->isMuted(ids.get(i)) )
-			{
-				LLUIString muted = LLTrans::getString("muted_message");
-
-				//*TODO remove this "floater" thing when Communicate Floater's gone
-				floater->addHistoryLine(muted);
-
-				im_model->addMessage(session_id, SYSTEM_FROM, LLUUID::null, muted);
-				break;
-			}
-		}
-	}
-}
-
-void LLIMMgr::processIMTypingStart(const LLIMInfo* im_info)
-{
-	processIMTypingCore(im_info, TRUE);
-}
-
-void LLIMMgr::processIMTypingStop(const LLIMInfo* im_info)
-{
-	processIMTypingCore(im_info, FALSE);
-}
-
-void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)
-{
-	LLUUID session_id = computeSessionID(im_info->mIMType, im_info->mFromID);
-	LLFloaterIMPanel* floater = findFloaterBySession(session_id);
-	if (floater)
-	{
-		floater->processIMTyping(im_info, typing);
-	}
-
-	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
-	if ( im_floater )
-	{
-		im_floater->processIMTyping(im_info, typing);
-	}
-}
-
-class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
-{
-public:
-	virtual void describe(Description& desc) const
-	{
-		desc.shortInfo("Used for receiving a reply to a request to initialize an ChatterBox session");
-		desc.postAPI();
-		desc.input(
-			"{\"client_session_id\": UUID, \"session_id\": UUID, \"success\" boolean, \"reason\": string");
-		desc.source(__FILE__, __LINE__);
-	}
-
-	virtual void post(ResponsePtr response,
-					  const LLSD& context,
-					  const LLSD& input) const
-	{
-		LLSD body;
-		LLUUID temp_session_id;
-		LLUUID session_id;
-		bool success;
-
-		body = input["body"];
-		success = body["success"].asBoolean();
-		temp_session_id = body["temp_session_id"].asUUID();
-
-		if ( success )
-		{
-			session_id = body["session_id"].asUUID();
-
-			LLIMModel::getInstance()->processSessionInitializedReply(temp_session_id, session_id);
-
-			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
-			if (speaker_mgr)
-			{
-				speaker_mgr->setSpeakers(body);
-				speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(session_id));
-			}
-
-			LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
-			if (floaterp)
-			{
-				if ( body.has("session_info") )
-				{
-					floaterp->processSessionUpdate(body["session_info"]);
-				}
-			}
-
-			LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
-			if ( im_floater )
-			{
-				if ( body.has("session_info") )
-				{
-					im_floater->processSessionUpdate(body["session_info"]);
-				}
-			}
-
-			gIMMgr->clearPendingAgentListUpdates(session_id);
-		}
-		else
-		{
-			//throw an error dialog and close the temp session's floater
-			gIMMgr->showSessionStartError(body["error"].asString(), temp_session_id);
-		}
-
-		gIMMgr->clearPendingAgentListUpdates(session_id);
-	}
-};
-
-class LLViewerChatterBoxSessionEventReply : public LLHTTPNode
-{
-public:
-	virtual void describe(Description& desc) const
-	{
-		desc.shortInfo("Used for receiving a reply to a ChatterBox session event");
-		desc.postAPI();
-		desc.input(
-			"{\"event\": string, \"reason\": string, \"success\": boolean, \"session_id\": UUID");
-		desc.source(__FILE__, __LINE__);
-	}
-
-	virtual void post(ResponsePtr response,
-					  const LLSD& context,
-					  const LLSD& input) const
-	{
-		LLUUID session_id;
-		bool success;
-
-		LLSD body = input["body"];
-		success = body["success"].asBoolean();
-		session_id = body["session_id"].asUUID();
-
-		if ( !success )
-		{
-			//throw an error dialog
-			gIMMgr->showSessionEventError(
-				body["event"].asString(),
-				body["error"].asString(),
-				session_id);
-		}
-	}
-};
-
-class LLViewerForceCloseChatterBoxSession: public LLHTTPNode
-{
-public:
-	virtual void post(ResponsePtr response,
-					  const LLSD& context,
-					  const LLSD& input) const
-	{
-		LLUUID session_id;
-		std::string reason;
-
-		session_id = input["body"]["session_id"].asUUID();
-		reason = input["body"]["reason"].asString();
-
-		gIMMgr->showSessionForceClose(reason, session_id);
-	}
-};
-
-class LLViewerChatterBoxSessionAgentListUpdates : public LLHTTPNode
-{
-public:
-	virtual void post(
-		ResponsePtr responder,
-		const LLSD& context,
-		const LLSD& input) const
-	{
-		const LLUUID& session_id = input["body"]["session_id"].asUUID();
-		gIMMgr->processAgentListUpdates(session_id, input["body"]);
-	}
-};
-
-class LLViewerChatterBoxSessionUpdate : public LLHTTPNode
-{
-public:
-	virtual void post(
-		ResponsePtr responder,
-		const LLSD& context,
-		const LLSD& input) const
-	{
-		LLUUID session_id = input["body"]["session_id"].asUUID();
-		LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
-		if (floaterp)
-		{
-			floaterp->processSessionUpdate(input["body"]["info"]);
-		}
-		LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
-		if ( im_floater )
-		{
-			im_floater->processSessionUpdate(input["body"]["info"]);
-		}
-	}
-};
-
-
-class LLViewerChatterBoxInvitation : public LLHTTPNode
-{
-public:
-
-	virtual void post(
-		ResponsePtr response,
-		const LLSD& context,
-		const LLSD& input) const
-	{
-		//for backwards compatiblity reasons...we need to still
-		//check for 'text' or 'voice' invitations...bleh
-		if ( input["body"].has("instantmessage") )
-		{
-			LLSD message_params =
-				input["body"]["instantmessage"]["message_params"];
-
-			//do something here to have the IM invite behave
-			//just like a normal IM
-			//this is just replicated code from process_improved_im
-			//and should really go in it's own function -jwolk
-			if (gNoRender)
-			{
-				return;
-			}
-			LLChat chat;
-
-			std::string message = message_params["message"].asString();
-			std::string name = message_params["from_name"].asString();
-			LLUUID from_id = message_params["from_id"].asUUID();
-			LLUUID session_id = message_params["id"].asUUID();
-			std::vector<U8> bin_bucket = message_params["data"]["binary_bucket"].asBinary();
-			U8 offline = (U8)message_params["offline"].asInteger();
-			
-			time_t timestamp =
-				(time_t) message_params["timestamp"].asInteger();
-
-			BOOL is_busy = gAgent.getBusy();
-			BOOL is_muted = LLMuteList::getInstance()->isMuted(
-				from_id,
-				name,
-				LLMute::flagTextChat);
-
-			BOOL is_linden = LLMuteList::getInstance()->isLinden(name);
-			std::string separator_string(": ");
-			
-			chat.mMuted = is_muted && !is_linden;
-			chat.mFromID = from_id;
-			chat.mFromName = name;
-
-			if (!is_linden && (is_busy || is_muted))
-			{
-				return;
-			}
-
-			// standard message, not from system
-			std::string saved;
-			if(offline == IM_OFFLINE)
-			{
-				saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
-			}
-			std::string buffer = saved + message;
-
-			BOOL is_this_agent = FALSE;
-			if(from_id == gAgentID)
-			{
-				is_this_agent = TRUE;
-			}
-			gIMMgr->addMessage(
-				session_id,
-				from_id,
-				name,
-				buffer,
-				std::string((char*)&bin_bucket[0]),
-				IM_SESSION_INVITE,
-				message_params["parent_estate_id"].asInteger(),
-				message_params["region_id"].asUUID(),
-				ll_vector3_from_sd(message_params["position"]),
-				true);
-
-			chat.mText = std::string("IM: ") + name + separator_string + saved + message;
-			LLFloaterChat::addChat(chat, TRUE, is_this_agent);
-
-			//K now we want to accept the invitation
-			std::string url = gAgent.getRegion()->getCapability(
-				"ChatSessionRequest");
-
-			if ( url != "" )
-			{
-				LLSD data;
-				data["method"] = "accept invitation";
-				data["session-id"] = session_id;
-				LLHTTPClient::post(
-					url,
-					data,
-					new LLViewerChatterBoxInvitationAcceptResponder(
-						session_id,
-						LLIMMgr::INVITATION_TYPE_INSTANT_MESSAGE));
-			}
-		} //end if invitation has instant message
-		else if ( input["body"].has("voice") )
-		{
-			if (gNoRender)
-			{
-				return;
-			}
-			
-			if(!LLVoiceClient::voiceEnabled())
-			{
-				// Don't display voice invites unless the user has voice enabled.
-				return;
-			}
-
-			gIMMgr->inviteToSession(
-				input["body"]["session_id"].asUUID(), 
-				input["body"]["session_name"].asString(), 
-				input["body"]["from_id"].asUUID(),
-				input["body"]["from_name"].asString(),
-				IM_SESSION_INVITE,
-				LLIMMgr::INVITATION_TYPE_VOICE);
-		}
-		else if ( input["body"].has("immediate") )
-		{
-			gIMMgr->inviteToSession(
-				input["body"]["session_id"].asUUID(), 
-				input["body"]["session_name"].asString(), 
-				input["body"]["from_id"].asUUID(),
-				input["body"]["from_name"].asString(),
-				IM_SESSION_INVITE,
-				LLIMMgr::INVITATION_TYPE_IMMEDIATE);
-		}
-	}
-};
-
-LLHTTPRegistration<LLViewerChatterBoxSessionStartReply>
-   gHTTPRegistrationMessageChatterboxsessionstartreply(
-	   "/message/ChatterBoxSessionStartReply");
-
-LLHTTPRegistration<LLViewerChatterBoxSessionEventReply>
-   gHTTPRegistrationMessageChatterboxsessioneventreply(
-	   "/message/ChatterBoxSessionEventReply");
-
-LLHTTPRegistration<LLViewerForceCloseChatterBoxSession>
-    gHTTPRegistrationMessageForceclosechatterboxsession(
-		"/message/ForceCloseChatterBoxSession");
-
-LLHTTPRegistration<LLViewerChatterBoxSessionAgentListUpdates>
-    gHTTPRegistrationMessageChatterboxsessionagentlistupdates(
-	    "/message/ChatterBoxSessionAgentListUpdates");
-
-LLHTTPRegistration<LLViewerChatterBoxSessionUpdate>
-    gHTTPRegistrationMessageChatterBoxSessionUpdate(
-	    "/message/ChatterBoxSessionUpdate");
-
-LLHTTPRegistration<LLViewerChatterBoxInvitation>
-    gHTTPRegistrationMessageChatterBoxInvitation(
-		"/message/ChatterBoxInvitation");
-
+#include "llresmgr.h"
+#include "llfloaterchat.h"
+#include "llfloaterchatterbox.h"
+#include "llavataractions.h"
+#include "llhttpnode.h"
+#include "llimfloater.h"
+#include "llimpanel.h"
+#include "llresizebar.h"
+#include "lltabcontainer.h"
+#include "llviewercontrol.h"
+#include "llfloater.h"
+#include "llmutelist.h"
+#include "llresizehandle.h"
+#include "llkeyboard.h"
+#include "llui.h"
+#include "llviewermenu.h"
+#include "llcallingcard.h"
+#include "lltoolbar.h"
+#include "llviewermessage.h"
+#include "llviewerwindow.h"
+#include "llnotify.h"
+#include "llviewerregion.h"
+#include "llvoicechannel.h"
+#include "lltrans.h"
+#include "llrecentpeople.h"
+#include "llsyswellwindow.h"
+
+#include "llfirstuse.h"
+#include "llagentui.h"
+
+//
+// Globals
+//
+LLIMMgr* gIMMgr = NULL;
+
+//
+// Statics
+//
+// *FIXME: make these all either UIStrings or Strings
+
+const static std::string IM_SEPARATOR(": ");
+
+
+void toast_callback(const LLSD& msg){
+	// do not show toast in busy mode or it goes from agent
+	if (gAgent.getBusy() || gAgent.getID() == msg["from_id"])
+	{
+		return;
+	}
+
+	// check whether incoming IM belongs to an active session or not
+	if (LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"])
+	{
+		return;
+	}
+
+	// Skip toasting for system messages
+	if (msg["from_id"].asUUID() == LLUUID::null)
+	{
+		return;
+	}
+
+	LLSD args;
+	args["MESSAGE"] = msg["message"];
+	args["TIME"] = msg["time"];
+	args["FROM"] = msg["from"];
+	args["FROM_ID"] = msg["from_id"];
+	args["SESSION_ID"] = msg["session_id"];
+
+	LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
+}
+
+void LLIMModel::setActiveSessionID(const LLUUID& session_id)
+{
+	// check if such an ID really exists
+	if (!findIMSession(session_id))
+	{
+		llwarns << "Trying to set as active a non-existent session!" << llendl;
+		return;
+	}
+
+	mActiveSessionID = session_id;
+}
+
+LLIMModel::LLIMModel() 
+{
+	addNewMsgCallback(LLIMFloater::newIMCallback);
+	addNewMsgCallback(toast_callback);
+}
+
+LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
+:	mSessionID(session_id),
+	mName(name),
+	mType(type),
+	mNumUnread(0),
+	mOtherParticipantID(other_participant_id),
+	mInitialTargetIDs(ids),
+	mVoiceChannel(NULL),
+	mSpeakers(NULL),
+	mSessionInitialized(false),
+	mCallBackEnabled(true),
+	mTextIMPossible(true),
+	mOtherParticipantIsAvatar(true)
+{
+	if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type)
+	{
+		mVoiceChannel  = new LLVoiceChannelP2P(session_id, name, other_participant_id);
+	}
+	else
+	{
+		mVoiceChannel = new LLVoiceChannelGroup(session_id, name);
+	}
+	mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);
+
+	// All participants will be added to the list of people we've recently interacted with.
+	mSpeakers->addListener(&LLRecentPeople::instance(), "add");
+
+	//we need to wait for session initialization for outgoing ad-hoc and group chat session
+	//correct session id for initiated ad-hoc chat will be received from the server
+	if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID, 
+		mInitialTargetIDs, mType))
+	{
+		//we don't need to wait for any responses
+		//so we're already initialized
+		mSessionInitialized = true;
+	}
+
+	if (IM_NOTHING_SPECIAL == type)
+	{
+		mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionID);
+		mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID);
+		mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID);
+	}
+
+	if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+		LLLogChat::loadHistory(mName, &chatFromLogFile, (void *)this);
+}
+
+LLIMModel::LLIMSession::~LLIMSession()
+{
+	delete mSpeakers;
+	mSpeakers = NULL;
+
+	// End the text IM session if necessary
+	if(gVoiceClient && mOtherParticipantID.notNull())
+	{
+		switch(mType)
+		{
+		case IM_NOTHING_SPECIAL:
+		case IM_SESSION_P2P_INVITE:
+			gVoiceClient->endUserIMSession(mOtherParticipantID);
+			break;
+
+		default:
+			// Appease the linux compiler
+			break;
+		}
+	}
+
+	// HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point).
+	mVoiceChannel->deactivate();
+	
+	delete mVoiceChannel;
+	mVoiceChannel = NULL;
+}
+
+void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_id)
+{
+	mSessionInitialized = true;
+
+	if (new_session_id != mSessionID)
+	{
+		mSessionID = new_session_id;
+		mVoiceChannel->updateSessionID(new_session_id);
+	}
+}
+
+void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time)
+{
+	LLSD message;
+	message["from"] = from;
+	message["from_id"] = from_id;
+	message["message"] = utf8_text;
+	message["time"] = time; 
+	message["index"] = (LLSD::Integer)mMsgs.size(); 
+
+	mMsgs.push_front(message); 
+
+	if (mSpeakers && from_id.notNull())
+	{
+		mSpeakers->speakerChatted(from_id);
+		mSpeakers->setSpeakerTyping(from_id, FALSE);
+	}
+}
+
+void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata)
+{
+	if (!userdata) return;
+
+	LLIMSession* self = (LLIMSession*) userdata;
+
+	if (type == LLLogChat::LOG_LINE)
+	{
+		self->addMessage("", LLSD(), msg["message"].asString(), "");
+	}
+	else if (type == LLLogChat::LOG_LLSD)
+	{
+		self->addMessage(msg["from"].asString(), msg["from_id"].asUUID(), msg["message"].asString(), msg["time"].asString());
+	}
+}
+
+LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
+{
+	return get_if_there(mId2SessionMap, session_id,
+		(LLIMModel::LLIMSession*) NULL);
+}
+
+void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)
+{
+	LLIMSession* session = findIMSession(old_session_id);
+	if (session)
+	{
+		session->sessionInitReplyReceived(new_session_id);
+
+		if (old_session_id != new_session_id)
+		{
+			mId2SessionMap.erase(old_session_id);
+			mId2SessionMap[new_session_id] = session;
+
+			gIMMgr->notifyObserverSessionIDUpdated(old_session_id, new_session_id);
+		}
+
+		LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id);
+		if (im_floater)
+		{
+			im_floater->sessionInitReplyReceived(new_session_id);
+		}
+	}
+
+	//*TODO remove this "floater" stuff when Communicate Floater is gone
+	LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(old_session_id);
+	if (floater)
+	{
+		floater->sessionInitReplyReceived(new_session_id);
+	}
+}
+
+void LLIMModel::testMessages()
+{
+	LLUUID bot1_id("d0426ec6-6535-4c11-a5d9-526bb0c654d9");
+	LLUUID bot1_session_id;
+	std::string from = "IM Tester";
+
+	bot1_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot1_id);
+	newSession(bot1_session_id, from, IM_NOTHING_SPECIAL, bot1_id);
+	addMessage(bot1_session_id, from, bot1_id, "Test Message: Hi from testerbot land!");
+
+	LLUUID bot2_id;
+	std::string firstname[] = {"Roflcopter", "Joe"};
+	std::string lastname[] = {"Linden", "Tester", "Resident", "Schmoe"};
+
+	S32 rand1 = ll_rand(sizeof firstname)/(sizeof firstname[0]);
+	S32 rand2 = ll_rand(sizeof lastname)/(sizeof lastname[0]);
+	
+	from = firstname[rand1] + " " + lastname[rand2];
+	bot2_id.generate(from);
+	LLUUID bot2_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot2_id);
+	newSession(bot2_session_id, from, IM_NOTHING_SPECIAL, bot2_id);
+	addMessage(bot2_session_id, from, bot2_id, "Test Message: Hello there, I have a question. Can I bother you for a second? ");
+	addMessage(bot2_session_id, from, bot2_id, "Test Message: OMGWTFBBQ.");
+}
+
+
+bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, 
+						   const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
+{
+	if (findIMSession(session_id))
+	{
+		llwarns << "IM Session " << session_id << " already exists" << llendl;
+		return false;
+	}
+
+	LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids);
+	mId2SessionMap[session_id] = session;
+
+	LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, name, other_participant_id);
+
+	return true;
+
+}
+
+bool LLIMModel::clearSession(const LLUUID& session_id)
+{
+	if (mId2SessionMap.find(session_id) == mId2SessionMap.end()) return false;
+	delete (mId2SessionMap[session_id]);
+	mId2SessionMap.erase(session_id);
+	return true;
+}
+
+void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
+{
+	LLIMSession* session = findIMSession(session_id);
+	if (!session) 
+	{
+		llwarns << "session " << session_id << "does not exist " << llendl;
+		return;
+	}
+
+	int i = session->mMsgs.size() - start_index;
+
+	for (std::list<LLSD>::iterator iter = session->mMsgs.begin(); 
+		iter != session->mMsgs.end() && i > 0;
+		iter++)
+	{
+		LLSD msg;
+		msg = *iter;
+		messages.push_back(*iter);
+		i--;
+	}
+
+	session->mNumUnread = 0;
+	
+	LLSD arg;
+	arg["session_id"] = session_id;
+	arg["num_unread"] = 0;
+	mNoUnreadMsgsSignal(arg);
+}
+
+bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {
+	
+	LLIMSession* session = findIMSession(session_id);
+
+	if (!session) 
+	{
+		llwarns << "session " << session_id << "does not exist " << llendl;
+		return false;
+	}
+
+	session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false)); //might want to add date separately
+
+	return true;
+}
+
+bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
+{
+	S32 im_log_option =  gSavedPerAccountSettings.getS32("IMLogOptions");
+	if (im_log_option != LOG_CHAT)
+	{
+		if(im_log_option == LOG_BOTH_TOGETHER)
+		{
+			LLLogChat::saveHistory(std::string("chat"), from, from_id, utf8_text);
+			return true;
+		}
+		else
+		{
+			LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), from, from_id, utf8_text);
+			return true;
+		}
+	}
+	return false;
+}
+
+bool LLIMModel::proccessOnlineOfflineNotification(
+	const LLUUID& session_id, 
+	const std::string& utf8_text)
+{
+	// Add message to old one floater
+	LLFloaterIMPanel *floater = gIMMgr->findFloaterBySession(session_id);
+	if ( floater )
+	{
+		if ( !utf8_text.empty() )
+		{
+			floater->addHistoryLine(utf8_text, LLUIColorTable::instance().getColor("SystemChatColor"));
+		}
+	}
+	// Add system message to history
+	return addMessage(session_id, SYSTEM_FROM, LLUUID::null, utf8_text);
+}
+
+bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, 
+						   const std::string& utf8_text, bool log2file /* = true */) { 
+	LLIMSession* session = findIMSession(session_id);
+
+	if (!session) 
+	{
+		llwarns << "session " << session_id << "does not exist " << llendl;
+		return false;
+	}
+
+	addToHistory(session_id, from, from_id, utf8_text);
+	if (log2file) logToFile(session_id, from, from_id, utf8_text);
+
+	session->mNumUnread++;
+
+	// notify listeners
+	LLSD arg;
+	arg["session_id"] = session_id;
+	arg["num_unread"] = session->mNumUnread;
+	arg["message"] = utf8_text;
+	arg["from"] = from;
+	arg["from_id"] = from_id;
+	arg["time"] = LLLogChat::timestamp(false);
+	mNewMsgSignal(arg);
+
+	return true;
+}
+
+
+const std::string& LLIMModel::getName(const LLUUID& session_id) const
+{
+	LLIMSession* session = findIMSession(session_id);
+
+	if (!session) 
+	{
+		llwarns << "session " << session_id << "does not exist " << llendl;
+		return LLStringUtil::null;
+	}
+
+	return session->mName;
+}
+
+const S32 LLIMModel::getNumUnread(const LLUUID& session_id) const
+{
+	LLIMSession* session = findIMSession(session_id);
+	if (!session)
+	{
+		llwarns << "session " << session_id << "does not exist " << llendl;
+		return -1;
+	}
+
+	return session->mNumUnread;
+}
+
+const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const
+{
+	LLIMSession* session = findIMSession(session_id);
+	if (!session)
+	{
+		llwarns << "session " << session_id << "does not exist " << llendl;
+		return LLUUID::null;
+	}
+
+	return session->mOtherParticipantID;
+}
+
+EInstantMessage LLIMModel::getType(const LLUUID& session_id) const
+{
+	LLIMSession* session = findIMSession(session_id);
+	if (!session)
+	{
+		llwarns << "session " << session_id << "does not exist " << llendl;
+		return IM_COUNT;
+	}
+
+	return session->mType;
+}
+
+LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id ) const
+{
+	LLIMSession* session = findIMSession(session_id);
+	if (!session)
+	{
+		llwarns << "session " << session_id << "does not exist " << llendl;
+		return NULL;
+	}
+
+	return session->mVoiceChannel;
+}
+
+LLIMSpeakerMgr* LLIMModel::getSpeakerManager( const LLUUID& session_id ) const
+{
+	LLIMSession* session = findIMSession(session_id);
+	if (!session)
+	{
+		llwarns << "session " << session_id << "does not exist " << llendl;
+		return NULL;
+	}
+
+	return session->mSpeakers;
+}
+
+
+// TODO get rid of other participant ID
+void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing) 
+{
+	std::string name;
+	LLAgentUI::buildFullname(name);
+
+	pack_instant_message(
+		gMessageSystem,
+		gAgent.getID(),
+		FALSE,
+		gAgent.getSessionID(),
+		other_participant_id,
+		name,
+		std::string("typing"),
+		IM_ONLINE,
+		(typing ? IM_TYPING_START : IM_TYPING_STOP),
+		session_id);
+	gAgent.sendReliableMessage();
+}
+
+void LLIMModel::sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id)
+{
+	if(session_id.notNull())
+	{
+		std::string name;
+		LLAgentUI::buildFullname(name);
+		pack_instant_message(
+			gMessageSystem,
+			gAgent.getID(),
+			FALSE,
+			gAgent.getSessionID(),
+			other_participant_id,
+			name, 
+			LLStringUtil::null,
+			IM_ONLINE,
+			IM_SESSION_LEAVE,
+			session_id);
+		gAgent.sendReliableMessage();
+	}
+}
+
+//*TODO this method is better be moved to the LLIMMgr
+void LLIMModel::sendMessage(const std::string& utf8_text,
+					 const LLUUID& im_session_id,
+					 const LLUUID& other_participant_id,
+					 EInstantMessage dialog)
+{
+	std::string name;
+	bool sent = false;
+	LLAgentUI::buildFullname(name);
+
+	const LLRelationship* info = NULL;
+	info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
+	
+	U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
+	
+	if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
+	{
+		// User is online through the OOW connector, but not with a regular viewer.  Try to send the message via SLVoice.
+		sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text);
+	}
+	
+	if(!sent)
+	{
+		// Send message normally.
+
+		// default to IM_SESSION_SEND unless it's nothing special - in
+		// which case it's probably an IM to everyone.
+		U8 new_dialog = dialog;
+
+		if ( dialog != IM_NOTHING_SPECIAL )
+		{
+			new_dialog = IM_SESSION_SEND;
+		}
+		pack_instant_message(
+			gMessageSystem,
+			gAgent.getID(),
+			FALSE,
+			gAgent.getSessionID(),
+			other_participant_id,
+			name.c_str(),
+			utf8_text.c_str(),
+			offline,
+			(EInstantMessage)new_dialog,
+			im_session_id);
+		gAgent.sendReliableMessage();
+	}
+
+	// If there is a mute list and this is not a group chat...
+	if ( LLMuteList::getInstance() )
+	{
+		// ... the target should not be in our mute list for some message types.
+		// Auto-remove them if present.
+		switch( dialog )
+		{
+		case IM_NOTHING_SPECIAL:
+		case IM_GROUP_INVITATION:
+		case IM_INVENTORY_OFFERED:
+		case IM_SESSION_INVITE:
+		case IM_SESSION_P2P_INVITE:
+		case IM_SESSION_CONFERENCE_START:
+		case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing.
+		case IM_LURE_USER:
+		case IM_GODLIKE_LURE_USER:
+		case IM_FRIENDSHIP_OFFERED:
+			LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM);
+			break;
+		default: ; // do nothing
+		}
+	}
+
+	if((dialog == IM_NOTHING_SPECIAL) && 
+	   (other_participant_id.notNull()))
+	{
+		// Do we have to replace the /me's here?
+		std::string from;
+		LLAgentUI::buildFullname(from);
+		LLIMModel::getInstance()->addMessage(im_session_id, from, gAgentID, utf8_text);
+
+		//local echo for the legacy communicate panel
+		std::string history_echo;
+		LLAgentUI::buildFullname(history_echo);
+
+		history_echo += ": " + utf8_text;
+
+		LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(im_session_id);
+		if (floater) floater->addHistoryLine(history_echo, LLUIColorTable::instance().getColor("IMChatColor"), true, gAgent.getID());
+
+		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(im_session_id);
+		if (speaker_mgr)
+		{
+			speaker_mgr->speakerChatted(gAgentID);
+			speaker_mgr->setSpeakerTyping(gAgentID, FALSE);
+		}
+	}
+
+	// Add the recipient to the recent people list.
+	LLRecentPeople::instance().add(other_participant_id);
+}
+
+void session_starter_helper(
+	const LLUUID& temp_session_id,
+	const LLUUID& other_participant_id,
+	EInstantMessage im_type)
+{
+	LLMessageSystem *msg = gMessageSystem;
+
+	msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
+	msg->nextBlockFast(_PREHASH_AgentData);
+	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+	msg->nextBlockFast(_PREHASH_MessageBlock);
+	msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
+	msg->addUUIDFast(_PREHASH_ToAgentID, other_participant_id);
+	msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
+	msg->addU8Fast(_PREHASH_Dialog, im_type);
+	msg->addUUIDFast(_PREHASH_ID, temp_session_id);
+	msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
+
+	std::string name;
+	LLAgentUI::buildFullname(name);
+
+	msg->addStringFast(_PREHASH_FromAgentName, name);
+	msg->addStringFast(_PREHASH_Message, LLStringUtil::null);
+	msg->addU32Fast(_PREHASH_ParentEstateID, 0);
+	msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
+	msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
+}
+
+void start_deprecated_conference_chat(
+	const LLUUID& temp_session_id,
+	const LLUUID& creator_id,
+	const LLUUID& other_participant_id,
+	const LLSD& agents_to_invite)
+{
+	U8* bucket;
+	U8* pos;
+	S32 count;
+	S32 bucket_size;
+
+	// *FIX: this could suffer from endian issues
+	count = agents_to_invite.size();
+	bucket_size = UUID_BYTES * count;
+	bucket = new U8[bucket_size];
+	pos = bucket;
+
+	for(S32 i = 0; i < count; ++i)
+	{
+		LLUUID agent_id = agents_to_invite[i].asUUID();
+		
+		memcpy(pos, &agent_id, UUID_BYTES);
+		pos += UUID_BYTES;
+	}
+
+	session_starter_helper(
+		temp_session_id,
+		other_participant_id,
+		IM_SESSION_CONFERENCE_START);
+
+	gMessageSystem->addBinaryDataFast(
+		_PREHASH_BinaryBucket,
+		bucket,
+		bucket_size);
+
+	gAgent.sendReliableMessage();
+ 
+	delete[] bucket;
+}
+
+class LLStartConferenceChatResponder : public LLHTTPClient::Responder
+{
+public:
+	LLStartConferenceChatResponder(
+		const LLUUID& temp_session_id,
+		const LLUUID& creator_id,
+		const LLUUID& other_participant_id,
+		const LLSD& agents_to_invite)
+	{
+		mTempSessionID = temp_session_id;
+		mCreatorID = creator_id;
+		mOtherParticipantID = other_participant_id;
+		mAgents = agents_to_invite;
+	}
+
+	virtual void error(U32 statusNum, const std::string& reason)
+	{
+		//try an "old school" way.
+		if ( statusNum == 400 )
+		{
+			start_deprecated_conference_chat(
+				mTempSessionID,
+				mCreatorID,
+				mOtherParticipantID,
+				mAgents);
+		}
+
+		//else throw an error back to the client?
+		//in theory we should have just have these error strings
+		//etc. set up in this file as opposed to the IMMgr,
+		//but the error string were unneeded here previously
+		//and it is not worth the effort switching over all
+		//the possible different language translations
+	}
+
+private:
+	LLUUID mTempSessionID;
+	LLUUID mCreatorID;
+	LLUUID mOtherParticipantID;
+
+	LLSD mAgents;
+};
+
+// Returns true if any messages were sent, false otherwise.
+// Is sort of equivalent to "does the server need to do anything?"
+bool LLIMModel::sendStartSession(
+	const LLUUID& temp_session_id,
+	const LLUUID& other_participant_id,
+	const std::vector<LLUUID>& ids,
+	EInstantMessage dialog)
+{
+	if ( dialog == IM_SESSION_GROUP_START )
+	{
+		session_starter_helper(
+			temp_session_id,
+			other_participant_id,
+			dialog);
+		gMessageSystem->addBinaryDataFast(
+				_PREHASH_BinaryBucket,
+				EMPTY_BINARY_BUCKET,
+				EMPTY_BINARY_BUCKET_SIZE);
+		gAgent.sendReliableMessage();
+
+		return true;
+	}
+	else if ( dialog == IM_SESSION_CONFERENCE_START )
+	{
+		LLSD agents;
+		for (int i = 0; i < (S32) ids.size(); i++)
+		{
+			agents.append(ids[i]);
+		}
+
+		//we have a new way of starting conference calls now
+		LLViewerRegion* region = gAgent.getRegion();
+		if (region)
+		{
+			std::string url = region->getCapability(
+				"ChatSessionRequest");
+			LLSD data;
+			data["method"] = "start conference";
+			data["session-id"] = temp_session_id;
+
+			data["params"] = agents;
+
+			LLHTTPClient::post(
+				url,
+				data,
+				new LLStartConferenceChatResponder(
+					temp_session_id,
+					gAgent.getID(),
+					other_participant_id,
+					data["params"]));
+		}
+		else
+		{
+			start_deprecated_conference_chat(
+				temp_session_id,
+				gAgent.getID(),
+				other_participant_id,
+				agents);
+		}
+
+		//we also need to wait for reply from the server in case of ad-hoc chat (we'll get new session id)
+		return true;
+	}
+
+	return false;
+}
+
+// static
+void LLIMModel::sendSessionInitialized(const LLUUID &session_id)
+{
+	LLIMSession* session = getInstance()->findIMSession(session_id);
+	if (session)
+	{
+		LLSD arg;
+		arg["session_id"] = session_id;
+		getInstance()->mSessionInitializedSignal(arg);
+	}
+}
+
+//
+// Helper Functions
+//
+
+class LLViewerChatterBoxInvitationAcceptResponder :
+	public LLHTTPClient::Responder
+{
+public:
+	LLViewerChatterBoxInvitationAcceptResponder(
+		const LLUUID& session_id,
+		LLIMMgr::EInvitationType invitation_type)
+	{
+		mSessionID = session_id;
+		mInvitiationType = invitation_type;
+	}
+
+	void result(const LLSD& content)
+	{
+		if ( gIMMgr)
+		{
+			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+			if (speaker_mgr)
+			{
+				//we've accepted our invitation
+				//and received a list of agents that were
+				//currently in the session when the reply was sent
+				//to us.  Now, it is possible that there were some agents
+				//to slip in/out between when that message was sent to us
+				//and now.
+
+				//the agent list updates we've received have been
+				//accurate from the time we were added to the session
+				//but unfortunately, our base that we are receiving here
+				//may not be the most up to date.  It was accurate at
+				//some point in time though.
+				speaker_mgr->setSpeakers(content);
+
+				//we now have our base of users in the session
+				//that was accurate at some point, but maybe not now
+				//so now we apply all of the udpates we've received
+				//in case of race conditions
+				speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(mSessionID));
+			}
+
+			if (LLIMMgr::INVITATION_TYPE_VOICE == mInvitiationType)
+			{
+				gIMMgr->startCall(mSessionID);
+			}
+
+			if ((mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE 
+				|| mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE)
+				&& LLIMModel::getInstance()->findIMSession(mSessionID))
+			{
+				// always open IM window when connecting to voice
+				LLIMFloater::show(mSessionID);
+			}
+
+			gIMMgr->clearPendingAgentListUpdates(mSessionID);
+			gIMMgr->clearPendingInvitation(mSessionID);
+		}
+	}
+
+	void error(U32 statusNum, const std::string& reason)
+	{		
+		//throw something back to the viewer here?
+		if ( gIMMgr )
+		{
+			gIMMgr->clearPendingAgentListUpdates(mSessionID);
+			gIMMgr->clearPendingInvitation(mSessionID);
+			if ( 404 == statusNum )
+			{
+				std::string error_string;
+				error_string = "does not exist";
+				gIMMgr->showSessionStartError(error_string, mSessionID);
+			}
+		}
+	}
+
+private:
+	LLUUID mSessionID;
+	LLIMMgr::EInvitationType mInvitiationType;
+};
+
+
+// the other_participant_id is either an agent_id, a group_id, or an inventory
+// folder item_id (collection of calling cards)
+
+// static
+LLUUID LLIMMgr::computeSessionID(
+	EInstantMessage dialog,
+	const LLUUID& other_participant_id)
+{
+	LLUUID session_id;
+	if (IM_SESSION_GROUP_START == dialog)
+	{
+		// slam group session_id to the group_id (other_participant_id)
+		session_id = other_participant_id;
+	}
+	else if (IM_SESSION_CONFERENCE_START == dialog)
+	{
+		session_id.generate();
+	}
+	else if (IM_SESSION_INVITE == dialog)
+	{
+		// use provided session id for invites
+		session_id = other_participant_id;
+	}
+	else
+	{
+		LLUUID agent_id = gAgent.getID();
+		if (other_participant_id == agent_id)
+		{
+			// if we try to send an IM to ourselves then the XOR would be null
+			// so we just make the session_id the same as the agent_id
+			session_id = agent_id;
+		}
+		else
+		{
+			// peer-to-peer or peer-to-asset session_id is the XOR
+			session_id = other_participant_id ^ agent_id;
+		}
+	}
+	return session_id;
+}
+
+inline LLFloater* getFloaterBySessionID(const LLUUID session_id)
+{
+	LLFloater* floater = NULL;
+	if ( gIMMgr )
+	{
+		floater = dynamic_cast < LLFloater* >
+			( gIMMgr->findFloaterBySession(session_id) );
+	}
+	if ( !floater )
+	{
+		floater = dynamic_cast < LLFloater* >
+			( LLIMFloater::findInstance(session_id) );
+	}
+	return floater;
+}
+
+void
+LLIMMgr::showSessionStartError(
+	const std::string& error_string,
+	const LLUUID session_id)
+{
+	const LLFloater* floater = getFloaterBySessionID (session_id);
+	if (!floater) return;
+
+	LLSD args;
+	args["REASON"] = LLTrans::getString(error_string);
+	args["RECIPIENT"] = floater->getTitle();
+
+	LLSD payload;
+	payload["session_id"] = session_id;
+
+	LLNotifications::instance().add(
+		"ChatterBoxSessionStartError",
+		args,
+		payload,
+		LLIMMgr::onConfirmForceCloseError);
+}
+
+void
+LLIMMgr::showSessionEventError(
+	const std::string& event_string,
+	const std::string& error_string,
+	const LLUUID session_id)
+{
+	const LLFloater* floater = getFloaterBySessionID (session_id);
+	if (!floater) return;
+
+	LLSD args;
+	args["REASON"] =
+		LLTrans::getString(error_string);
+	args["EVENT"] =
+		LLTrans::getString(event_string);
+	args["RECIPIENT"] = floater->getTitle();
+
+	LLNotifications::instance().add(
+		"ChatterBoxSessionEventError",
+		args);
+}
+
+void
+LLIMMgr::showSessionForceClose(
+	const std::string& reason_string,
+	const LLUUID session_id)
+{
+	const LLFloater* floater = getFloaterBySessionID (session_id);
+	if (!floater) return;
+
+	LLSD args;
+
+	args["NAME"] = floater->getTitle();
+	args["REASON"] = LLTrans::getString(reason_string);
+
+	LLSD payload;
+	payload["session_id"] = session_id;
+
+	LLNotifications::instance().add(
+		"ForceCloseChatterBoxSession",
+		args,
+		payload,
+		LLIMMgr::onConfirmForceCloseError);
+}
+
+//static
+bool
+LLIMMgr::onConfirmForceCloseError(
+	const LLSD& notification,
+	const LLSD& response)
+{
+	//only 1 option really
+	LLUUID session_id = notification["payload"]["session_id"];
+
+	LLFloater* floater = getFloaterBySessionID (session_id);
+	if ( floater )
+	{
+		floater->closeFloater(FALSE);
+	}
+	return false;
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLOutgoingCallDialog
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LLOutgoingCallDialog::LLOutgoingCallDialog(const LLSD& payload) :
+	LLDockableFloater(NULL, false, payload),
+	mPayload(payload)
+{
+}
+
+void LLOutgoingCallDialog::getAllowedRect(LLRect& rect)
+{
+	rect = gViewerWindow->getWorldViewRectScaled();
+}
+
+void LLOutgoingCallDialog::onOpen(const LLSD& key)
+{
+	// tell the user which voice channel they are leaving
+	if (!mPayload["old_channel_name"].asString().empty())
+	{
+		childSetTextArg("leaving", "[CURRENT_CHAT]", mPayload["old_channel_name"].asString());
+	}
+	else
+	{
+		childSetTextArg("leaving", "[CURRENT_CHAT]", getString("localchat"));
+	}
+
+	std::string callee_name = mPayload["session_name"].asString();
+	if (callee_name == "anonymous")
+	{
+		callee_name = getString("anonymous");
+	}
+	
+	setTitle(callee_name);
+
+	LLSD callee_id = mPayload["other_user_id"];
+	childSetTextArg("calling", "[CALLEE_NAME]", callee_name);
+	childSetTextArg("connecting", "[CALLEE_NAME]", callee_name);
+	LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+	icon->setValue(callee_id);
+}
+
+
+//static
+void LLOutgoingCallDialog::onCancel(void* user_data)
+{
+	LLOutgoingCallDialog* self = (LLOutgoingCallDialog*)user_data;
+
+	if (!gIMMgr)
+		return;
+
+	LLUUID session_id = self->mPayload["session_id"].asUUID();
+	gIMMgr->endCall(session_id);
+	
+	self->closeFloater();
+}
+
+
+BOOL LLOutgoingCallDialog::postBuild()
+{
+	BOOL success = LLDockableFloater::postBuild();
+
+	childSetAction("Cancel", onCancel, this);
+
+	// dock the dialog to the sys well, where other sys messages appear
+	setDockControl(new LLDockControl(LLBottomTray::getInstance()->getSysWell(),
+					 this, getDockTongue(), LLDockControl::TOP,
+					 boost::bind(&LLOutgoingCallDialog::getAllowedRect, this, _1)));
+
+	return success;
+}
+
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLIncomingCallDialog
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) :
+	LLDockableFloater(NULL, false, payload),
+	mPayload(payload)
+{
+}
+
+BOOL LLIncomingCallDialog::postBuild()
+{
+	LLDockableFloater::postBuild();
+
+	LLSD caller_id = mPayload["caller_id"];
+	EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger();
+
+	std::string call_type = getString("VoiceInviteP2P");
+	std::string caller_name = mPayload["caller_name"].asString();
+	if (caller_name == "anonymous")
+	{
+		caller_name = getString("anonymous");
+	}
+	
+	setTitle(caller_name + " " + call_type);
+	
+	// If it is not a P2P invite, then it's an AdHoc invite
+	if ( type != IM_SESSION_P2P_INVITE )
+	{
+		call_type = getString("VoiceInviteAdHoc");
+	}
+
+	// check to see if this is an Avaline call
+	LLUUID session_id = mPayload["session_id"].asUUID();
+	bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id);
+	childSetVisible("Start IM", is_avatar); // no IM for avaline
+
+	LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
+	caller_name_widget->setValue(caller_name + " " + call_type);
+	LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+	icon->setValue(caller_id);
+
+	childSetAction("Accept", onAccept, this);
+	childSetAction("Reject", onReject, this);
+	childSetAction("Start IM", onStartIM, this);
+	childSetFocus("Accept");
+
+	return TRUE;
+}
+
+void LLIncomingCallDialog::getAllowedRect(LLRect& rect)
+{
+	rect = gViewerWindow->getWorldViewRectScaled();
+}
+
+void LLIncomingCallDialog::onOpen(const LLSD& key)
+{
+	// tell the user which voice channel they would be leaving
+	LLVoiceChannel *voice = LLVoiceChannel::getCurrentVoiceChannel();
+	if (voice && !voice->getSessionName().empty())
+	{
+		childSetTextArg("question", "[CURRENT_CHAT]", voice->getSessionName());
+	}
+	else
+	{
+		childSetTextArg("question", "[CURRENT_CHAT]", getString("localchat"));
+	}
+
+	// dock the dialog to the sys well, where other sys messages appear
+	setDockControl(new LLDockControl(LLBottomTray::getInstance()->getSysWell(),
+									 this, getDockTongue(), LLDockControl::TOP,
+									 boost::bind(&LLIncomingCallDialog::getAllowedRect, this, _1)));
+}
+
+//static
+void LLIncomingCallDialog::onAccept(void* user_data)
+{
+	LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
+	self->processCallResponse(0);
+	self->closeFloater();
+}
+
+//static
+void LLIncomingCallDialog::onReject(void* user_data)
+{
+	LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
+	self->processCallResponse(1);
+	self->closeFloater();
+}
+
+//static
+void LLIncomingCallDialog::onStartIM(void* user_data)
+{
+	LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
+	self->processCallResponse(2);
+	self->closeFloater();
+}
+
+void LLIncomingCallDialog::processCallResponse(S32 response)
+{
+	if (!gIMMgr)
+		return;
+
+	LLUUID session_id = mPayload["session_id"].asUUID();
+	EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger();
+	LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)mPayload["inv_type"].asInteger();
+	bool voice = true;
+	switch(response)
+	{
+	case 2: // start IM: just don't start the voice chat
+	{
+		voice = false;
+		/* FALLTHROUGH */
+	}
+	case 0: // accept
+	{
+		if (type == IM_SESSION_P2P_INVITE)
+		{
+			// create a normal IM session
+			session_id = gIMMgr->addP2PSession(
+				mPayload["session_name"].asString(),
+				mPayload["caller_id"].asUUID(),
+				mPayload["session_handle"].asString());
+
+			if (voice)
+			{
+				if (gIMMgr->startCall(session_id))
+				{
+					// always open IM window when connecting to voice
+					LLIMFloater::show(session_id);
+				}
+			}
+
+			gIMMgr->clearPendingAgentListUpdates(session_id);
+			gIMMgr->clearPendingInvitation(session_id);
+		}
+		else
+		{
+			LLUUID session_id = gIMMgr->addSession(
+				mPayload["session_name"].asString(),
+				type,
+				session_id);
+			if (session_id != LLUUID::null)
+			{
+				LLIMFloater::show(session_id);
+			}
+
+			std::string url = gAgent.getRegion()->getCapability(
+				"ChatSessionRequest");
+
+			if (voice)
+			{
+				LLSD data;
+				data["method"] = "accept invitation";
+				data["session-id"] = session_id;
+				LLHTTPClient::post(
+					url,
+					data,
+					new LLViewerChatterBoxInvitationAcceptResponder(
+						session_id,
+						inv_type));
+			}
+		}
+		if (voice)
+		{
+			break;
+		}
+	}
+	case 1: // decline
+	{
+		if (type == IM_SESSION_P2P_INVITE)
+		{
+			if(gVoiceClient)
+			{
+				std::string s = mPayload["session_handle"].asString();
+				gVoiceClient->declineInvite(s);
+			}
+		}
+		else
+		{
+			std::string url = gAgent.getRegion()->getCapability(
+				"ChatSessionRequest");
+
+			LLSD data;
+			data["method"] = "decline invitation";
+			data["session-id"] = session_id;
+			LLHTTPClient::post(
+				url,
+				data,
+				NULL);
+		}
+	}
+
+	gIMMgr->clearPendingAgentListUpdates(session_id);
+	gIMMgr->clearPendingInvitation(session_id);
+	}
+}
+
+bool inviteUserResponse(const LLSD& notification, const LLSD& response)
+{
+	if (!gIMMgr)
+		return false;
+
+	const LLSD& payload = notification["payload"];
+	LLUUID session_id = payload["session_id"].asUUID();
+	EInstantMessage type = (EInstantMessage)payload["type"].asInteger();
+	LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)payload["inv_type"].asInteger();
+	S32 option = LLNotification::getSelectedOption(notification, response);
+	switch(option) 
+	{
+	case 0: // accept
+		{
+			if (type == IM_SESSION_P2P_INVITE)
+			{
+				// create a normal IM session
+				session_id = gIMMgr->addP2PSession(
+					payload["session_name"].asString(),
+					payload["caller_id"].asUUID(),
+					payload["session_handle"].asString(),
+					payload["session_uri"].asString());
+
+				if (gIMMgr->startCall(session_id))
+				{
+					// always open IM window when connecting to voice
+					LLIMFloater::show(session_id);
+				}
+
+				gIMMgr->clearPendingAgentListUpdates(session_id);
+				gIMMgr->clearPendingInvitation(session_id);
+			}
+			else
+			{
+				LLUUID session_id = gIMMgr->addSession(
+					payload["session_name"].asString(),
+					type,
+					session_id);
+				if (session_id != LLUUID::null)
+				{
+					LLIMFloater::show(session_id);
+				}
+
+				std::string url = gAgent.getRegion()->getCapability(
+					"ChatSessionRequest");
+
+				LLSD data;
+				data["method"] = "accept invitation";
+				data["session-id"] = session_id;
+				LLHTTPClient::post(
+					url,
+					data,
+					new LLViewerChatterBoxInvitationAcceptResponder(
+						session_id,
+						inv_type));
+			}
+		}
+		break;
+	case 2: // mute (also implies ignore, so this falls through to the "ignore" case below)
+	{
+		// mute the sender of this invite
+		if (!LLMuteList::getInstance()->isMuted(payload["caller_id"].asUUID()))
+		{
+			LLMute mute(payload["caller_id"].asUUID(), payload["caller_name"].asString(), LLMute::AGENT);
+			LLMuteList::getInstance()->add(mute);
+		}
+	}
+	/* FALLTHROUGH */
+	
+	case 1: // decline
+	{
+		if (type == IM_SESSION_P2P_INVITE)
+		{
+			if(gVoiceClient)
+			{
+				std::string s = payload["session_handle"].asString();
+				gVoiceClient->declineInvite(s);
+			}
+		}
+		else
+		{
+			std::string url = gAgent.getRegion()->getCapability(
+				"ChatSessionRequest");
+
+			LLSD data;
+			data["method"] = "decline invitation";
+			data["session-id"] = session_id;
+			LLHTTPClient::post(
+				url,
+				data,
+				NULL);				
+		}
+	}
+
+	gIMMgr->clearPendingAgentListUpdates(session_id);
+	gIMMgr->clearPendingInvitation(session_id);
+	break;
+	}
+	
+	return false;
+}
+
+//
+// Member Functions
+//
+
+LLIMMgr::LLIMMgr() :
+	mIMReceived(FALSE)
+{
+	mPendingInvitations = LLSD::emptyMap();
+	mPendingAgentListUpdates = LLSD::emptyMap();
+}
+
+// Add a message to a session. 
+void LLIMMgr::addMessage(
+	const LLUUID& session_id,
+	const LLUUID& target_id,
+	const std::string& from,
+	const std::string& msg,
+	const std::string& session_name,
+	EInstantMessage dialog,
+	U32 parent_estate_id,
+	const LLUUID& region_id,
+	const LLVector3& position,
+	bool link_name) // If this is true, then we insert the name and link it to a profile
+{
+	LLUUID other_participant_id = target_id;
+
+	// don't process muted IMs
+	if (LLMuteList::getInstance()->isMuted(
+			other_participant_id,
+			LLMute::flagTextChat) && !LLMuteList::getInstance()->isLinden(from))
+	{
+		return;
+	}
+
+	LLFloaterIMPanel* floater;
+	LLUUID new_session_id = session_id;
+	if (new_session_id.isNull())
+	{
+		//no session ID...compute new one
+		new_session_id = computeSessionID(dialog, other_participant_id);
+	}
+
+	//*NOTE session_name is empty in case of incoming P2P sessions
+	std::string fixed_session_name = from;
+	if(!session_name.empty() && session_name.size()>1)
+	{
+		fixed_session_name = session_name;
+	}
+
+	bool new_session = !hasSession(new_session_id);
+	if (new_session)
+	{
+		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id);
+	}
+
+	floater = findFloaterBySession(new_session_id);
+	if (!floater)
+	{
+		floater = findFloaterBySession(other_participant_id);
+		if (floater)
+		{
+			llinfos << "found the IM session " << session_id 
+				<< " by participant " << other_participant_id << llendl;
+		}
+	}
+
+	// create IM window as necessary
+	if(!floater)
+	{
+		floater = createFloater(
+			new_session_id,
+			other_participant_id,
+			fixed_session_name,
+			dialog,
+			FALSE);
+	}
+
+	if (new_session)
+	{
+		// When we get a new IM, and if you are a god, display a bit
+		// of information about the source. This is to help liaisons
+		// when answering questions.
+		if(gAgent.isGodlike())
+		{
+			// *TODO:translate (low priority, god ability)
+			std::ostringstream bonus_info;
+			bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + ":" + " "
+				<< parent_estate_id
+				<< ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
+				<< ((parent_estate_id == 5) ? "," + LLTrans::getString ("IMTeen") : "");
+
+			// once we have web-services (or something) which returns
+			// information about a region id, we can print this out
+			// and even have it link to map-teleport or something.
+			//<< "*** region_id: " << region_id << std::endl
+			//<< "*** position: " << position << std::endl;
+
+			floater->addHistoryLine(bonus_info.str(), LLUIColorTable::instance().getColor("SystemChatColor"));
+			LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str());
+		}
+
+		make_ui_sound("UISndNewIncomingIMSession");
+	}
+
+	// now add message to floater
+	bool is_from_system = target_id.isNull() || (from == SYSTEM_FROM);
+	const LLColor4& color = ( is_from_system ? 
+							  LLUIColorTable::instance().getColor("SystemChatColor") : 
+							  LLUIColorTable::instance().getColor("IMChatColor"));
+	if ( !link_name )
+	{
+		floater->addHistoryLine(msg,color); // No name to prepend, so just add the message normally
+	}
+	else
+	{
+		floater->addHistoryLine(msg, color, true, other_participant_id, from); // Insert linked name to front of message
+	}
+
+	LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
+
+	if( !LLFloaterReg::instanceVisible("communicate") && !floater->getVisible())
+	{
+		LLFloaterChatterBox* chat_floater = LLFloaterChatterBox::getInstance();
+		
+		//if the IM window is not open and the floater is not visible (i.e. not torn off)
+		LLFloater* previouslyActiveFloater = chat_floater->getActiveFloater();
+
+		// select the newly added floater (or the floater with the new line added to it).
+		// it should be there.
+		chat_floater->selectFloater(floater);
+
+		//there was a previously unseen IM, make that old tab flashing
+		//it is assumed that the most recently unseen IM tab is the one current selected/active
+		if ( previouslyActiveFloater && getIMReceived() )
+		{
+			chat_floater->setFloaterFlashing(previouslyActiveFloater, TRUE);
+		}
+
+		//notify of a new IM
+		notifyNewIM();
+	}
+}
+
+void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args)
+{
+	LLUIString message;
+	
+	// null session id means near me (chat history)
+	if (session_id.isNull())
+	{
+		message = LLTrans::getString(message_name);
+		message.setArgs(args);
+
+		LLChat chat(message);
+		chat.mSourceType = CHAT_SOURCE_SYSTEM;
+		LLFloaterChat::addChatHistory(chat);
+	}
+	else // going to IM session
+	{
+		if (hasSession(session_id))
+		{
+			message = LLTrans::getString(message_name + "-im");
+			message.setArgs(args);
+			gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString());
+		}
+	}
+}
+
+void LLIMMgr::notifyNewIM()
+{
+	if(!LLFloaterReg::instanceVisible("communicate"))
+	{
+		mIMReceived = TRUE;
+	}
+}
+
+S32 LLIMMgr::getNumberOfUnreadIM()
+{
+	std::map<LLUUID, LLIMModel::LLIMSession*>::iterator it;
+	
+	S32 num = 0;
+	for(it = LLIMModel::getInstance()->mId2SessionMap.begin(); it != LLIMModel::getInstance()->mId2SessionMap.end(); ++it)
+	{
+		num += (*it).second->mNumUnread;
+	}
+
+	return num;
+}
+
+void LLIMMgr::clearNewIMNotification()
+{
+	mIMReceived = FALSE;
+}
+
+BOOL LLIMMgr::getIMReceived() const
+{
+	return mIMReceived;
+}
+
+LLUUID LLIMMgr::addP2PSession(const std::string& name,
+							const LLUUID& other_participant_id,
+							const std::string& voice_session_handle,
+							const std::string& caller_uri)
+{
+	LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id);
+	if (session_id != LLUUID::null)
+	{
+		LLIMFloater::show(session_id);
+	}
+
+	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+	if (speaker_mgr)
+	{
+		LLVoiceChannelP2P* voice_channel = dynamic_cast<LLVoiceChannelP2P*>(speaker_mgr->getVoiceChannel());
+		if (voice_channel)
+		{
+			voice_channel->setSessionHandle(voice_session_handle, caller_uri);
+		}
+	}
+	return session_id;
+}
+
+// This adds a session to the talk view. The name is the local name of
+// the session, dialog specifies the type of session. If the session
+// exists, it is brought forward.  Specifying id = NULL results in an
+// im session to everyone. Returns the uuid of the session.
+LLUUID LLIMMgr::addSession(
+	const std::string& name,
+	EInstantMessage dialog,
+	const LLUUID& other_participant_id)
+{
+	LLDynamicArray<LLUUID> ids;
+	ids.put(other_participant_id);
+	return addSession(name, dialog, other_participant_id, ids);
+}
+
+// Adds a session using the given session_id.  If the session already exists 
+// the dialog type is assumed correct. Returns the uuid of the session.
+LLUUID LLIMMgr::addSession(
+	const std::string& name,
+	EInstantMessage dialog,
+	const LLUUID& other_participant_id,
+	const LLDynamicArray<LLUUID>& ids)
+{
+	if (0 == ids.getLength())
+	{
+		return LLUUID::null;
+	}
+
+	LLUUID session_id = computeSessionID(dialog,other_participant_id);
+
+	bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);
+
+	if (new_session)
+	{
+		LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids);
+	}
+
+
+	//*TODO remove this "floater" thing when Communicate Floater's gone
+	LLFloaterIMPanel* floater = findFloaterBySession(session_id);
+	if(!floater)
+	{
+		// On creation, use the first element of ids as the
+		// "other_participant_id"
+		floater = createFloater(
+			session_id,
+			other_participant_id,
+			name,
+			dialog,
+			TRUE,
+			ids);
+	}
+
+	//we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions
+	if (!new_session) return session_id;
+	
+	noteOfflineUsers(session_id, floater, ids);
+
+	// Only warn for regular IMs - not group IMs
+	if( dialog == IM_NOTHING_SPECIAL )
+	{
+		noteMutedUsers(session_id, floater, ids);
+	}
+
+	return session_id;
+}
+
+bool LLIMMgr::leaveSession(const LLUUID& session_id)
+{
+	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
+	if (!im_session) return false;
+
+	LLIMModel::getInstance()->sendLeaveSession(session_id, im_session->mOtherParticipantID);
+	gIMMgr->removeSession(session_id);
+	return true;
+}
+
+// Removes data associated with a particular session specified by session_id
+void LLIMMgr::removeSession(const LLUUID& session_id)
+{
+	llassert_always(hasSession(session_id));
+	
+	//*TODO remove this floater thing when Communicate Floater is being deleted (IB)
+	LLFloaterIMPanel* floater = findFloaterBySession(session_id);
+	if(floater)
+	{
+		mFloaters.erase(floater->getHandle());
+		LLFloaterChatterBox::getInstance()->removeFloater(floater);
+	}
+
+	clearPendingInvitation(session_id);
+	clearPendingAgentListUpdates(session_id);
+
+	LLIMModel::getInstance()->clearSession(session_id);
+
+	notifyObserverSessionRemoved(session_id);
+}
+
+void LLIMMgr::inviteToSession(
+	const LLUUID& session_id, 
+	const std::string& session_name, 
+	const LLUUID& caller_id, 
+	const std::string& caller_name,
+	EInstantMessage type,
+	EInvitationType inv_type,
+	const std::string& session_handle,
+	const std::string& session_uri)
+{
+	//ignore invites from muted residents
+	if (LLMuteList::getInstance()->isMuted(caller_id))
+	{
+		return;
+	}
+
+	std::string notify_box_type;
+
+	BOOL ad_hoc_invite = FALSE;
+	if(type == IM_SESSION_P2P_INVITE)
+	{
+		//P2P is different...they only have voice invitations
+		notify_box_type = "VoiceInviteP2P";
+	}
+	else if ( gAgent.isInGroup(session_id) )
+	{
+		//only really old school groups have voice invitations
+		notify_box_type = "VoiceInviteGroup";
+	}
+	else if ( inv_type == INVITATION_TYPE_VOICE )
+	{
+		//else it's an ad-hoc
+		//and a voice ad-hoc
+		notify_box_type = "VoiceInviteAdHoc";
+		ad_hoc_invite = TRUE;
+	}
+	else if ( inv_type == INVITATION_TYPE_IMMEDIATE )
+	{
+		notify_box_type = "InviteAdHoc";
+		ad_hoc_invite = TRUE;
+	}
+
+	LLSD payload;
+	payload["session_id"] = session_id;
+	payload["session_name"] = session_name;
+	payload["caller_id"] = caller_id;
+	payload["caller_name"] = caller_name;
+	payload["type"] = type;
+	payload["inv_type"] = inv_type;
+	payload["session_handle"] = session_handle;
+	payload["session_uri"] = session_uri;
+	payload["notify_box_type"] = notify_box_type;
+	
+	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(session_id);
+	if (channelp && channelp->callStarted())
+	{
+		// you have already started a call to the other user, so just accept the invite
+		LLNotifications::instance().forceResponse(LLNotification::Params("VoiceInviteP2P").payload(payload), 0);
+		return;
+	}
+
+	if (type == IM_SESSION_P2P_INVITE || ad_hoc_invite)
+	{
+		// is the inviter a friend?
+		if (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)
+		{
+			// if not, and we are ignoring voice invites from non-friends
+			// then silently decline
+			if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
+			{
+				// invite not from a friend, so decline
+				LLNotifications::instance().forceResponse(LLNotification::Params("VoiceInviteP2P").payload(payload), 1);
+				return;
+			}
+		}
+	}
+
+	if ( !mPendingInvitations.has(session_id.asString()) )
+	{
+		if (caller_name.empty())
+		{
+			gCacheName->get(caller_id, FALSE, boost::bind(&LLIMMgr::onInviteNameLookup, payload, _1, _2, _3, _4));
+		}
+		else
+		{
+			if (notify_box_type == "VoiceInviteP2P" || notify_box_type == "VoiceInviteAdHoc")
+			{
+				LLFloaterReg::showInstance("incoming_call", payload, TRUE);
+			}
+			else
+			{
+				LLSD args;
+				args["NAME"] = caller_name;
+				args["GROUP"] = session_name;
+
+				LLNotifications::instance().add(notify_box_type, args, payload, &inviteUserResponse);
+			}
+		}
+		mPendingInvitations[session_id.asString()] = LLSD();
+	}
+}
+
+void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+{
+	payload["caller_name"] = first + " " + last;
+	payload["session_name"] = payload["caller_name"].asString();
+
+	std::string notify_box_type = payload["notify_box_type"].asString();
+
+	if (notify_box_type == "VoiceInviteP2P" || notify_box_type == "VoiceInviteAdHoc")
+	{
+		LLFloaterReg::showInstance("incoming_call", payload, TRUE);
+	}
+	else
+	{
+		LLSD args;
+		args["NAME"] = payload["caller_name"].asString();
+	
+		LLNotifications::instance().add(
+			payload["notify_box_type"].asString(),
+			args, 
+			payload,
+			&inviteUserResponse);
+	}
+}
+
+void LLIMMgr::disconnectAllSessions()
+{
+	LLFloaterIMPanel* floater = NULL;
+	std::set<LLHandle<LLFloater> >::iterator handle_it;
+	for(handle_it = mFloaters.begin();
+		handle_it != mFloaters.end();
+		)
+	{
+		floater = (LLFloaterIMPanel*)handle_it->get();
+
+		// MUST do this BEFORE calling floater->onClose() because that may remove the item from the set, causing the subsequent increment to crash.
+		++handle_it;
+
+		if (floater)
+		{
+			floater->setEnabled(FALSE);
+			floater->closeFloater(TRUE);
+		}
+	}
+}
+
+
+// This method returns the im panel corresponding to the uuid
+// provided. The uuid can either be a session id or an agent
+// id. Returns NULL if there is no matching panel.
+LLFloaterIMPanel* LLIMMgr::findFloaterBySession(const LLUUID& session_id)
+{
+	LLFloaterIMPanel* rv = NULL;
+	std::set<LLHandle<LLFloater> >::iterator handle_it;
+	for(handle_it = mFloaters.begin();
+		handle_it != mFloaters.end();
+		++handle_it)
+	{
+		rv = (LLFloaterIMPanel*)handle_it->get();
+		if(rv && session_id == rv->getSessionID())
+		{
+			break;
+		}
+		rv = NULL;
+	}
+	return rv;
+}
+
+
+BOOL LLIMMgr::hasSession(const LLUUID& session_id)
+{
+	return LLIMModel::getInstance()->findIMSession(session_id) != NULL;
+}
+
+void LLIMMgr::clearPendingInvitation(const LLUUID& session_id)
+{
+	if ( mPendingInvitations.has(session_id.asString()) )
+	{
+		mPendingInvitations.erase(session_id.asString());
+	}
+}
+
+void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body)
+{
+	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+	if ( im_floater )
+	{
+		im_floater->processAgentListUpdates(body);
+	}
+	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+	if (speaker_mgr)
+	{
+		speaker_mgr->updateSpeakers(body);
+	}
+	else
+	{
+		//we don't have a speaker manager yet..something went wrong
+		//we are probably receiving an update here before
+		//a start or an acceptance of an invitation.  Race condition.
+		gIMMgr->addPendingAgentListUpdates(
+			session_id,
+			body);
+	}
+}
+
+LLSD LLIMMgr::getPendingAgentListUpdates(const LLUUID& session_id)
+{
+	if ( mPendingAgentListUpdates.has(session_id.asString()) )
+	{
+		return mPendingAgentListUpdates[session_id.asString()];
+	}
+	else
+	{
+		return LLSD();
+	}
+}
+
+void LLIMMgr::addPendingAgentListUpdates(
+	const LLUUID& session_id,
+	const LLSD& updates)
+{
+	LLSD::map_const_iterator iter;
+
+	if ( !mPendingAgentListUpdates.has(session_id.asString()) )
+	{
+		//this is a new agent list update for this session
+		mPendingAgentListUpdates[session_id.asString()] = LLSD::emptyMap();
+	}
+
+	if (
+		updates.has("agent_updates") &&
+		updates["agent_updates"].isMap() &&
+		updates.has("updates") &&
+		updates["updates"].isMap() )
+	{
+		//new school update
+		LLSD update_types = LLSD::emptyArray();
+		LLSD::array_iterator array_iter;
+
+		update_types.append("agent_updates");
+		update_types.append("updates");
+
+		for (
+			array_iter = update_types.beginArray();
+			array_iter != update_types.endArray();
+			++array_iter)
+		{
+			//we only want to include the last update for a given agent
+			for (
+				iter = updates[array_iter->asString()].beginMap();
+				iter != updates[array_iter->asString()].endMap();
+				++iter)
+			{
+				mPendingAgentListUpdates[session_id.asString()][array_iter->asString()][iter->first] =
+					iter->second;
+			}
+		}
+	}
+	else if (
+		updates.has("updates") &&
+		updates["updates"].isMap() )
+	{
+		//old school update where the SD contained just mappings
+		//of agent_id -> "LEAVE"/"ENTER"
+
+		//only want to keep last update for each agent
+		for (
+			iter = updates["updates"].beginMap();
+			iter != updates["updates"].endMap();
+			++iter)
+		{
+			mPendingAgentListUpdates[session_id.asString()]["updates"][iter->first] =
+				iter->second;
+		}
+	}
+}
+
+void LLIMMgr::clearPendingAgentListUpdates(const LLUUID& session_id)
+{
+	if ( mPendingAgentListUpdates.has(session_id.asString()) )
+	{
+		mPendingAgentListUpdates.erase(session_id.asString());
+	}
+}
+
+void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
+{
+	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
+	{
+		(*it)->sessionAdded(session_id, name, other_participant_id);
+	}
+}
+
+void LLIMMgr::notifyObserverSessionRemoved(const LLUUID& session_id)
+{
+	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
+	{
+		(*it)->sessionRemoved(session_id);
+	}
+}
+
+void LLIMMgr::notifyObserverSessionIDUpdated( const LLUUID& old_session_id, const LLUUID& new_session_id )
+{
+	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
+	{
+		(*it)->sessionIDUpdated(old_session_id, new_session_id);
+	}
+
+}
+
+void LLIMMgr::addSessionObserver(LLIMSessionObserver *observer)
+{
+	mSessionObservers.push_back(observer);
+}
+
+void LLIMMgr::removeSessionObserver(LLIMSessionObserver *observer)
+{
+	mSessionObservers.remove(observer);
+}
+
+bool LLIMMgr::startCall(const LLUUID& session_id)
+{
+	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
+	if (!voice_channel) return false;
+	
+	voice_channel->activate();
+	return true;
+}
+
+bool LLIMMgr::endCall(const LLUUID& session_id)
+{
+	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
+	if (!voice_channel) return false;
+
+	voice_channel->deactivate();
+	return true;
+}
+
+// create a floater and update internal representation for
+// consistency. Returns the pointer, caller (the class instance since
+// it is a private method) is not responsible for deleting the
+// pointer.  Add the floater to this but do not select it.
+LLFloaterIMPanel* LLIMMgr::createFloater(
+	const LLUUID& session_id,
+	const LLUUID& other_participant_id,
+	const std::string& session_label,
+	EInstantMessage dialog,
+	BOOL user_initiated,
+	const LLDynamicArray<LLUUID>& ids)
+{
+	if (session_id.isNull())
+	{
+		llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl;
+	}
+
+	llinfos << "LLIMMgr::createFloater: from " << other_participant_id 
+			<< " in session " << session_id << llendl;
+	LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label,
+													 session_id,
+													 other_participant_id,
+													 ids,
+													 dialog);
+	LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
+	LLFloaterChatterBox::getInstance()->addFloater(floater, FALSE, i_pt);
+	mFloaters.insert(floater->getHandle());
+	return floater;
+}
+
+void LLIMMgr::noteOfflineUsers(
+	const LLUUID& session_id,
+	LLFloaterIMPanel* floater,
+	const LLDynamicArray<LLUUID>& ids)
+{
+	S32 count = ids.count();
+	if(count == 0)
+	{
+		const std::string& only_user = LLTrans::getString("only_user_message");
+		if (floater)
+		{
+			floater->addHistoryLine(only_user, LLUIColorTable::instance().getColor("SystemChatColor"));
+		}
+		LLIMModel::getInstance()->addMessage(session_id, SYSTEM_FROM, LLUUID::null, only_user);
+	}
+	else
+	{
+		const LLRelationship* info = NULL;
+		LLAvatarTracker& at = LLAvatarTracker::instance();
+		LLIMModel& im_model = LLIMModel::instance();
+		for(S32 i = 0; i < count; ++i)
+		{
+			info = at.getBuddyInfo(ids.get(i));
+			std::string first, last;
+			if(info && !info->isOnline()
+			   && gCacheName->getName(ids.get(i), first, last))
+			{
+				LLUIString offline = LLTrans::getString("offline_message");
+				offline.setArg("[FIRST]", first);
+				offline.setArg("[LAST]", last);
+				im_model.proccessOnlineOfflineNotification(session_id, offline);
+			}
+		}
+	}
+}
+
+void LLIMMgr::noteMutedUsers(const LLUUID& session_id, LLFloaterIMPanel* floater,
+								  const LLDynamicArray<LLUUID>& ids)
+{
+	// Don't do this if we don't have a mute list.
+	LLMuteList *ml = LLMuteList::getInstance();
+	if( !ml )
+	{
+		return;
+	}
+
+	S32 count = ids.count();
+	if(count > 0)
+	{
+		LLIMModel* im_model = LLIMModel::getInstance();
+		
+		for(S32 i = 0; i < count; ++i)
+		{
+			if( ml->isMuted(ids.get(i)) )
+			{
+				LLUIString muted = LLTrans::getString("muted_message");
+
+				//*TODO remove this "floater" thing when Communicate Floater's gone
+				floater->addHistoryLine(muted);
+
+				im_model->addMessage(session_id, SYSTEM_FROM, LLUUID::null, muted);
+				break;
+			}
+		}
+	}
+}
+
+void LLIMMgr::processIMTypingStart(const LLIMInfo* im_info)
+{
+	processIMTypingCore(im_info, TRUE);
+}
+
+void LLIMMgr::processIMTypingStop(const LLIMInfo* im_info)
+{
+	processIMTypingCore(im_info, FALSE);
+}
+
+void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)
+{
+	LLUUID session_id = computeSessionID(im_info->mIMType, im_info->mFromID);
+	LLFloaterIMPanel* floater = findFloaterBySession(session_id);
+	if (floater)
+	{
+		floater->processIMTyping(im_info, typing);
+	}
+
+	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+	if ( im_floater )
+	{
+		im_floater->processIMTyping(im_info, typing);
+	}
+}
+
+class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
+{
+public:
+	virtual void describe(Description& desc) const
+	{
+		desc.shortInfo("Used for receiving a reply to a request to initialize an ChatterBox session");
+		desc.postAPI();
+		desc.input(
+			"{\"client_session_id\": UUID, \"session_id\": UUID, \"success\" boolean, \"reason\": string");
+		desc.source(__FILE__, __LINE__);
+	}
+
+	virtual void post(ResponsePtr response,
+					  const LLSD& context,
+					  const LLSD& input) const
+	{
+		LLSD body;
+		LLUUID temp_session_id;
+		LLUUID session_id;
+		bool success;
+
+		body = input["body"];
+		success = body["success"].asBoolean();
+		temp_session_id = body["temp_session_id"].asUUID();
+
+		if ( success )
+		{
+			session_id = body["session_id"].asUUID();
+
+			LLIMModel::getInstance()->processSessionInitializedReply(temp_session_id, session_id);
+
+			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+			if (speaker_mgr)
+			{
+				speaker_mgr->setSpeakers(body);
+				speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(session_id));
+			}
+
+			LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
+			if (floaterp)
+			{
+				if ( body.has("session_info") )
+				{
+					floaterp->processSessionUpdate(body["session_info"]);
+				}
+			}
+
+			LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+			if ( im_floater )
+			{
+				if ( body.has("session_info") )
+				{
+					im_floater->processSessionUpdate(body["session_info"]);
+				}
+			}
+
+			gIMMgr->clearPendingAgentListUpdates(session_id);
+		}
+		else
+		{
+			//throw an error dialog and close the temp session's floater
+			gIMMgr->showSessionStartError(body["error"].asString(), temp_session_id);
+		}
+
+		gIMMgr->clearPendingAgentListUpdates(session_id);
+	}
+};
+
+class LLViewerChatterBoxSessionEventReply : public LLHTTPNode
+{
+public:
+	virtual void describe(Description& desc) const
+	{
+		desc.shortInfo("Used for receiving a reply to a ChatterBox session event");
+		desc.postAPI();
+		desc.input(
+			"{\"event\": string, \"reason\": string, \"success\": boolean, \"session_id\": UUID");
+		desc.source(__FILE__, __LINE__);
+	}
+
+	virtual void post(ResponsePtr response,
+					  const LLSD& context,
+					  const LLSD& input) const
+	{
+		LLUUID session_id;
+		bool success;
+
+		LLSD body = input["body"];
+		success = body["success"].asBoolean();
+		session_id = body["session_id"].asUUID();
+
+		if ( !success )
+		{
+			//throw an error dialog
+			gIMMgr->showSessionEventError(
+				body["event"].asString(),
+				body["error"].asString(),
+				session_id);
+		}
+	}
+};
+
+class LLViewerForceCloseChatterBoxSession: public LLHTTPNode
+{
+public:
+	virtual void post(ResponsePtr response,
+					  const LLSD& context,
+					  const LLSD& input) const
+	{
+		LLUUID session_id;
+		std::string reason;
+
+		session_id = input["body"]["session_id"].asUUID();
+		reason = input["body"]["reason"].asString();
+
+		gIMMgr->showSessionForceClose(reason, session_id);
+	}
+};
+
+class LLViewerChatterBoxSessionAgentListUpdates : public LLHTTPNode
+{
+public:
+	virtual void post(
+		ResponsePtr responder,
+		const LLSD& context,
+		const LLSD& input) const
+	{
+		const LLUUID& session_id = input["body"]["session_id"].asUUID();
+		gIMMgr->processAgentListUpdates(session_id, input["body"]);
+	}
+};
+
+class LLViewerChatterBoxSessionUpdate : public LLHTTPNode
+{
+public:
+	virtual void post(
+		ResponsePtr responder,
+		const LLSD& context,
+		const LLSD& input) const
+	{
+		LLUUID session_id = input["body"]["session_id"].asUUID();
+		LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
+		if (floaterp)
+		{
+			floaterp->processSessionUpdate(input["body"]["info"]);
+		}
+		LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+		if ( im_floater )
+		{
+			im_floater->processSessionUpdate(input["body"]["info"]);
+		}
+	}
+};
+
+
+class LLViewerChatterBoxInvitation : public LLHTTPNode
+{
+public:
+
+	virtual void post(
+		ResponsePtr response,
+		const LLSD& context,
+		const LLSD& input) const
+	{
+		//for backwards compatiblity reasons...we need to still
+		//check for 'text' or 'voice' invitations...bleh
+		if ( input["body"].has("instantmessage") )
+		{
+			LLSD message_params =
+				input["body"]["instantmessage"]["message_params"];
+
+			//do something here to have the IM invite behave
+			//just like a normal IM
+			//this is just replicated code from process_improved_im
+			//and should really go in it's own function -jwolk
+			if (gNoRender)
+			{
+				return;
+			}
+			LLChat chat;
+
+			std::string message = message_params["message"].asString();
+			std::string name = message_params["from_name"].asString();
+			LLUUID from_id = message_params["from_id"].asUUID();
+			LLUUID session_id = message_params["id"].asUUID();
+			std::vector<U8> bin_bucket = message_params["data"]["binary_bucket"].asBinary();
+			U8 offline = (U8)message_params["offline"].asInteger();
+			
+			time_t timestamp =
+				(time_t) message_params["timestamp"].asInteger();
+
+			BOOL is_busy = gAgent.getBusy();
+			BOOL is_muted = LLMuteList::getInstance()->isMuted(
+				from_id,
+				name,
+				LLMute::flagTextChat);
+
+			BOOL is_linden = LLMuteList::getInstance()->isLinden(name);
+			std::string separator_string(": ");
+			
+			chat.mMuted = is_muted && !is_linden;
+			chat.mFromID = from_id;
+			chat.mFromName = name;
+
+			if (!is_linden && (is_busy || is_muted))
+			{
+				return;
+			}
+
+			// standard message, not from system
+			std::string saved;
+			if(offline == IM_OFFLINE)
+			{
+				saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
+			}
+			std::string buffer = saved + message;
+
+			BOOL is_this_agent = FALSE;
+			if(from_id == gAgentID)
+			{
+				is_this_agent = TRUE;
+			}
+			gIMMgr->addMessage(
+				session_id,
+				from_id,
+				name,
+				buffer,
+				std::string((char*)&bin_bucket[0]),
+				IM_SESSION_INVITE,
+				message_params["parent_estate_id"].asInteger(),
+				message_params["region_id"].asUUID(),
+				ll_vector3_from_sd(message_params["position"]),
+				true);
+
+			chat.mText = std::string("IM: ") + name + separator_string + saved + message;
+			LLFloaterChat::addChat(chat, TRUE, is_this_agent);
+
+			//K now we want to accept the invitation
+			std::string url = gAgent.getRegion()->getCapability(
+				"ChatSessionRequest");
+
+			if ( url != "" )
+			{
+				LLSD data;
+				data["method"] = "accept invitation";
+				data["session-id"] = session_id;
+				LLHTTPClient::post(
+					url,
+					data,
+					new LLViewerChatterBoxInvitationAcceptResponder(
+						session_id,
+						LLIMMgr::INVITATION_TYPE_INSTANT_MESSAGE));
+			}
+		} //end if invitation has instant message
+		else if ( input["body"].has("voice") )
+		{
+			if (gNoRender)
+			{
+				return;
+			}
+			
+			if(!LLVoiceClient::voiceEnabled())
+			{
+				// Don't display voice invites unless the user has voice enabled.
+				return;
+			}
+
+			gIMMgr->inviteToSession(
+				input["body"]["session_id"].asUUID(), 
+				input["body"]["session_name"].asString(), 
+				input["body"]["from_id"].asUUID(),
+				input["body"]["from_name"].asString(),
+				IM_SESSION_INVITE,
+				LLIMMgr::INVITATION_TYPE_VOICE);
+		}
+		else if ( input["body"].has("immediate") )
+		{
+			gIMMgr->inviteToSession(
+				input["body"]["session_id"].asUUID(), 
+				input["body"]["session_name"].asString(), 
+				input["body"]["from_id"].asUUID(),
+				input["body"]["from_name"].asString(),
+				IM_SESSION_INVITE,
+				LLIMMgr::INVITATION_TYPE_IMMEDIATE);
+		}
+	}
+};
+
+LLHTTPRegistration<LLViewerChatterBoxSessionStartReply>
+   gHTTPRegistrationMessageChatterboxsessionstartreply(
+	   "/message/ChatterBoxSessionStartReply");
+
+LLHTTPRegistration<LLViewerChatterBoxSessionEventReply>
+   gHTTPRegistrationMessageChatterboxsessioneventreply(
+	   "/message/ChatterBoxSessionEventReply");
+
+LLHTTPRegistration<LLViewerForceCloseChatterBoxSession>
+    gHTTPRegistrationMessageForceclosechatterboxsession(
+		"/message/ForceCloseChatterBoxSession");
+
+LLHTTPRegistration<LLViewerChatterBoxSessionAgentListUpdates>
+    gHTTPRegistrationMessageChatterboxsessionagentlistupdates(
+	    "/message/ChatterBoxSessionAgentListUpdates");
+
+LLHTTPRegistration<LLViewerChatterBoxSessionUpdate>
+    gHTTPRegistrationMessageChatterBoxSessionUpdate(
+	    "/message/ChatterBoxSessionUpdate");
+
+LLHTTPRegistration<LLViewerChatterBoxInvitation>
+    gHTTPRegistrationMessageChatterBoxInvitation(
+		"/message/ChatterBoxInvitation");
+
diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp
index 9ca207a579fe0e888f36f14056ebfcbf0efe6983..f30821cacf08bb990f6d69581e73598347ef2d70 100644
--- a/indra/newview/llmanip.cpp
+++ b/indra/newview/llmanip.cpp
@@ -265,8 +265,8 @@ BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVect
 	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		BOOL result = FALSE;
-		F32 mouse_x = ((F32)x / gViewerWindow->getWindowWidthScaled() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom;
-		F32 mouse_y = ((F32)y / gViewerWindow->getWindowHeightScaled() - 0.5f) / gAgent.mHUDCurZoom;
+		F32 mouse_x = ((F32)x / gViewerWindow->getWorldViewWidthScaled() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom;
+		F32 mouse_y = ((F32)y / gViewerWindow->getWorldViewHeightScaled() - 0.5f) / gAgent.mHUDCurZoom;
 
 		LLVector3 origin_agent = gAgent.getPosAgentFromGlobal(origin);
 		LLVector3 mouse_pos = LLVector3(0.f, -mouse_x, mouse_y);
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index bcaebb6bbb96d6af297fb25fee3e1a4dc17c52b3..8535d52015a2988189c6a47fccf3bd6e447fa693 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -1107,8 +1107,11 @@ BOOL LLManipRotate::updateVisiblity()
 		mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag;
 		mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm;
 
-		mCenterScreen.set((S32)((0.5f - mRotationCenter.mdV[VY]) / gAgent.mHUDCurZoom * gViewerWindow->getWorldViewWidthRaw()),
-							(S32)((mRotationCenter.mdV[VZ] + 0.5f) / gAgent.mHUDCurZoom * gViewerWindow->getWorldViewHeightRaw()));
+		// x axis range is (-aspect * 0.5f, +aspect * 0.5)
+		// y axis range is (-0.5, 0.5)
+		// so use getWorldViewHeightRaw as scale factor when converting to pixel coordinates
+		mCenterScreen.set((S32)((0.5f - center.mV[VY]) / gAgent.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled()),
+							(S32)((center.mV[VZ] + 0.5f) / gAgent.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled()));
 		visible = TRUE;
 	}
 	else
@@ -1624,8 +1627,8 @@ void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_
 {
 	if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD)
 	{
-		F32 mouse_x = (((F32)x / gViewerWindow->getWorldViewWidthRaw()) - 0.5f) / gAgent.mHUDCurZoom;
-		F32 mouse_y = ((((F32)y) / gViewerWindow->getWorldViewHeightRaw()) - 0.5f) / gAgent.mHUDCurZoom;
+		F32 mouse_x = (((F32)x / gViewerWindow->getWorldViewRectScaled().getWidth()) - 0.5f) / gAgent.mHUDCurZoom;
+		F32 mouse_y = ((((F32)y) / gViewerWindow->getWorldViewRectScaled().getHeight()) - 0.5f) / gAgent.mHUDCurZoom;
 
 		*ray_pt = LLVector3(-1.f, -mouse_x, mouse_y);
 		*ray_dir = LLVector3(1.f, 0.f, 0.f);
@@ -1699,7 +1702,7 @@ void LLManipRotate::highlightManipulators( S32 x, S32 y )
 	F32 dist_y = mouse_dir_y.normVec();
 	F32 dist_z = mouse_dir_z.normVec();
 
-	F32 distance_threshold = (MAX_MANIP_SELECT_DISTANCE * mRadiusMeters) / gViewerWindow->getWorldViewHeightRaw();
+	F32 distance_threshold = (MAX_MANIP_SELECT_DISTANCE * mRadiusMeters) / gViewerWindow->getWorldViewHeightScaled();
 
 	if (llabs(dist_x - mRadiusMeters) * llmax(0.05f, proj_rot_x_axis) < distance_threshold)
 	{
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 90c009887da24975f3293e64bc933b98603ccbe6..5cd40273f61aee5bdb928b765ffa7f96a9b70932 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -102,17 +102,17 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
 		setCaretColor( (unsigned int)color.mV[0], (unsigned int)color.mV[1], (unsigned int)color.mV[2] );
 	}
 
-	setIgnoreUIScale(p.ignore_ui_scale());
+	setIgnoreUIScale(p.ignore_ui_scale);
 	
-	setHomePageUrl(p.start_url());
+	setHomePageUrl(p.start_url);
 	
-	setBorderVisible(p.border_visible());
+	setBorderVisible(p.border_visible);
 	
-	mHideLoading = p.hide_loading();
+	mHideLoading = p.hide_loading;
 	
-	setDecoupleTextureSize(p.decouple_texture_size());
+	setDecoupleTextureSize(p.decouple_texture_size);
 	
-	setTextureSize(p.texture_width(), p.texture_height());
+	setTextureSize(p.texture_width, p.texture_height);
 
 	if(!getDecoupleTextureSize())
 	{
@@ -735,13 +735,13 @@ void LLMediaCtrl::draw()
 				{
 					// max width, adjusted height
 					width = r.getWidth();
-					height = llmin(llmax(S32(width / media_aspect), 0), r.getHeight());
+					height = llmin(llmax(llround(width / media_aspect), 0), r.getHeight());
 				}
 				else
 				{
 					// max height, adjusted width
 					height = r.getHeight();
-					width = llmin(llmax(S32(height * media_aspect), 0), r.getWidth());
+					width = llmin(llmax(llround(height * media_aspect), 0), r.getWidth());
 				}
 			}
 			else
@@ -759,6 +759,14 @@ void LLMediaCtrl::draw()
 		x_offset = (r.getWidth() - width) / 2;
 		y_offset = (r.getHeight() - height) / 2;		
 
+		if(mIgnoreUIScale)
+		{
+			x_offset = llround((F32)x_offset * LLUI::sGLScaleFactor.mV[VX]);
+			y_offset = llround((F32)y_offset * LLUI::sGLScaleFactor.mV[VY]);
+			width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]);
+			height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]);
+		}
+
 		// draw the browser
 		gGL.setSceneBlendType(LLRender::BT_REPLACE);
 		gGL.begin( LLRender::QUADS );
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 1f984e3af87cd6a2a6137e19a04bd2c5fee8c67b..09fd9b29490cb224874a70bce0aea7be9381cc12 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -222,5 +222,5 @@ void LLNearbyChat::setRect	(const LLRect &rect)
 
 void LLNearbyChat::getAllowedRect(LLRect& rect)
 {
-	rect = gViewerWindow->getWorldViewRectRaw();
+	rect = gViewerWindow->getWorldViewRectScaled();
 }
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 6145588df285092709f34af3b37b9918418b69e6..234fe13217f935efba7c0151a149d326418aed4e 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -92,7 +92,6 @@ LLNetMap::LLNetMap (const Params & p)
 	mObjectImagep(),
 	mClosestAgentToCursor(),
 	mClosestAgentAtLastRightClick(),
-	mRotateMap(FALSE),
 	mToolTipMsg()
 {
 	mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);
@@ -175,7 +174,8 @@ void LLNetMap::draw()
 
 		gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f);
 
-		if( mRotateMap )
+		static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
+		if( rotate_map )
 		{
 			// rotate subsequent draws to agent rotation
 			rotation = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
@@ -408,7 +408,7 @@ void LLNetMap::draw()
 
 		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 
-		if( mRotateMap )
+		if( rotate_map )
 		{
 			gGL.color4fv((map_frustum_color()).mV);
 
@@ -454,7 +454,8 @@ LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos )
 	pos_local.mV[VY] *= mPixelsPerMeter;
 	// leave Z component in meters
 
-	if( mRotateMap )
+	static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
+	if( rotate_map )
 	{
 		F32 radians = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
 		LLQuaternion rot(radians, LLVector3(0.f, 0.f, 1.f));
@@ -502,7 +503,8 @@ LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y )
 
 	F32 radians = - atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
 
-	if( mRotateMap )
+	static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
+	if( rotate_map )
 	{
 		LLQuaternion rot(radians, LLVector3(0.f, 0.f, 1.f));
 		pos_local.rotVec( rot );
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index 7088ab3e70c08c965b8fec78e8845e831b81e909..3d7f3233acb2a55806010a35aad96c0774247bf5 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -80,9 +80,7 @@ class LLNetMap : public LLUICtrl
 	/*virtual*/ void	reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
 	
 	void			setScale( F32 scale );
-	void			setRotateMap( BOOL b ) { mRotateMap = b; }
 	void			setToolTipMsg(const std::string& msg) { mToolTipMsg = msg; }
-	BOOL			getRotateMap( ) { return mRotateMap; }
 	void			renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius );
 	
 private:
@@ -122,7 +120,6 @@ class LLNetMap : public LLUICtrl
 	LLUUID			mClosestAgentToCursor;
 	LLUUID			mClosestAgentAtLastRightClick;
 
-	BOOL			mRotateMap;
 	std::string		mToolTipMsg;
 };
 
diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp
index 1f68c76bfc3503672bebe6c3f037a4781d3dd054..5c11bc7310a3c64db6aae4c6369e3878d71200ce 100644
--- a/indra/newview/llnotificationalerthandler.cpp
+++ b/indra/newview/llnotificationalerthandler.cpp
@@ -66,7 +66,7 @@ LLAlertHandler::~LLAlertHandler()
 //--------------------------------------------------------------------------
 void LLAlertHandler::initChannel()
 {
-	S32 channel_right_bound = gViewerWindow->getWorldViewRectRaw().getWidth() / 2;
+	S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().getWidth() / 2;
 	mChannel->init(channel_right_bound, channel_right_bound);
 }
 
diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp
index 26730e1f108093fb093a6874779629d8de4ae020..b7466ec6d4f199e8a72b3b642e2a8d53dff0ebed 100644
--- a/indra/newview/llnotificationgrouphandler.cpp
+++ b/indra/newview/llnotificationgrouphandler.cpp
@@ -61,7 +61,7 @@ LLGroupHandler::~LLGroupHandler()
 //--------------------------------------------------------------------------
 void LLGroupHandler::initChannel()
 {
-	S32 channel_right_bound = gViewerWindow->getWorldViewRectRaw().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
+	S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
 	S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
 	mChannel->init(channel_right_bound - channel_width, channel_right_bound);
 }
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
index 94e733913d4acaf41f2965ea5dfbdfa947243d5e..598d0217039afa41b2ed7428f200f90a96822d15 100644
--- a/indra/newview/llnotificationofferhandler.cpp
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -65,7 +65,7 @@ LLOfferHandler::~LLOfferHandler()
 //--------------------------------------------------------------------------
 void LLOfferHandler::initChannel()
 {
-	S32 channel_right_bound = gViewerWindow->getWorldViewRectRaw().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
+	S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
 	S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
 	mChannel->init(channel_right_bound - channel_width, channel_right_bound);
 }
diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp
index 70b86e8b976e3c69fed1dce6efb4d38307516ea6..4be98201d114c425f7f3dbc233616bf90f5699d2 100644
--- a/indra/newview/llnotificationscripthandler.cpp
+++ b/indra/newview/llnotificationscripthandler.cpp
@@ -64,7 +64,7 @@ LLScriptHandler::~LLScriptHandler()
 //--------------------------------------------------------------------------
 void LLScriptHandler::initChannel()
 {
-	S32 channel_right_bound = gViewerWindow->getWorldViewRectRaw().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
+	S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
 	S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
 	mChannel->init(channel_right_bound - channel_width, channel_right_bound);
 }
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index 60a27d51544dff805a151b0d6f29eaf923915f82..b962fa218401d820afd6d1ce81c758ca9e3bc7aa 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -60,7 +60,7 @@ LLTipHandler::~LLTipHandler()
 //--------------------------------------------------------------------------
 void LLTipHandler::initChannel()
 {
-	S32 channel_right_bound = gViewerWindow->getWorldViewRectRaw().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
+	S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
 	S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
 	mChannel->init(channel_right_bound - channel_width, channel_right_bound);
 }
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 1c2875bf467ee3314012f381a928054e5157353c..a1d54367c983910b595b521e01d07eb98bae4208 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -213,6 +213,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group)
 	}
 	mFounderName = panel_group->getChild<LLNameBox>("founder_name");
 	mGroupNameEditor = panel_group->getChild<LLLineEditor>("group_name_editor");
+	mGroupNameEditor->setPrevalidate( LLLineEditor::prevalidateASCII );
 }
 
 // static
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index b3e14eb2fb8cb5f83291a8164e7776776a4d5157..78f3469f0e767585a9b150e34b09241b61b2b5d1 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -210,8 +210,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 	}
 
 #if !USE_VIEWER_AUTH
-	childSetPrevalidate("first_name_edit", LLLineEditor::prevalidatePrintableNoSpace);
-	childSetPrevalidate("last_name_edit", LLLineEditor::prevalidatePrintableNoSpace);
+	childSetPrevalidate("first_name_edit", LLLineEditor::prevalidateASCIIPrintableNoSpace);
+	childSetPrevalidate("last_name_edit", LLLineEditor::prevalidateASCIIPrintableNoSpace);
 
 	childSetCommitCallback("password_edit", mungePassword, this);
 	getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp
index 1051326e72e9df716612db2c466fc21c85b51147..0dc010e2e746009e2ecc6baeb5b38952eb5898d0 100644
--- a/indra/newview/llpanelpermissions.cpp
+++ b/indra/newview/llpanelpermissions.cpp
@@ -80,9 +80,9 @@ LLPanelPermissions::LLPanelPermissions() :
 BOOL LLPanelPermissions::postBuild()
 {
 	childSetCommitCallback("Object Name",LLPanelPermissions::onCommitName,this);
-	childSetPrevalidate("Object Name",LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("Object Name",LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	childSetCommitCallback("Object Description",LLPanelPermissions::onCommitDesc,this);
-	childSetPrevalidate("Object Description",LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("Object Description",LLLineEditor::prevalidateASCIIPrintableNoPipe);
 
 	
 	getChild<LLUICtrl>("button set group")->setCommitCallback(boost::bind(&LLPanelPermissions::onClickGroup,this));
diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp
index 604faf8eb4b26ff08132a96008da0e81bc6425b3..92bd4dc62b11eba1e3ad289477eae69092b12838 100644
--- a/indra/newview/llpreviewanim.cpp
+++ b/indra/newview/llpreviewanim.cpp
@@ -79,7 +79,7 @@ BOOL LLPreviewAnim::postBuild()
 	childSetAction("Anim audition btn",auditionAnim, this);
 
 	childSetCommitCallback("desc", LLPreview::onText, this);
-	childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	
 	return LLPreview::postBuild();
 }
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 7b3a20d1020edf7323f7760f4c74edbb377cf9ae..49a2a3723d214b688a116250373371028612b6f7 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -493,7 +493,7 @@ BOOL LLPreviewGesture::postBuild()
 	{
 		childSetCommitCallback("desc", LLPreview::onText, this);
 		childSetText("desc", item->getDescription());
-		childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
+		childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	}
 
 	return LLPreview::postBuild();
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index ab9cfbf85064b7b0a3fda13e1db168f0f76c2e3b..ce81077d802fd492160a51bd7c3f1de59f13c200 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -96,7 +96,7 @@ BOOL LLPreviewNotecard::postBuild()
 	childSetCommitCallback("desc", LLPreview::onText, this);
 	if (item)
 		childSetText("desc", item->getDescription());
-	childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
 
 	return LLPreview::postBuild();
 }
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 2382befcfa7144435ad602aee25fd1b95e30589d..4e4711f8fbdd9729cc72a9ff6065b227d8b4ab6c 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -956,7 +956,7 @@ BOOL LLPreviewLSL::postBuild()
 
 	childSetCommitCallback("desc", LLPreview::onText, this);
 	childSetText("desc", item->getDescription());
-	childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
 
 	return LLPreview::postBuild();
 }
diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp
index 7659c50ed3153ecc7bc831f8c2b017b7b08e68dc..d7fd252fb67f26e2bb9b6dddb6e1a261e94f420b 100644
--- a/indra/newview/llpreviewsound.cpp
+++ b/indra/newview/llpreviewsound.cpp
@@ -75,7 +75,7 @@ BOOL	LLPreviewSound::postBuild()
 	button->setSoundFlags(LLView::SILENT);
 
 	childSetCommitCallback("desc", LLPreview::onText, this);
-	childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);	
+	childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);	
 
 	return LLPreview::postBuild();
 }
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 13d02b7dec021ae00f11fc8489b141707ebf2201..41cf402d6f4bc6b05b5e97bb887ae0907d4e85cd 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -152,7 +152,7 @@ BOOL LLPreviewTexture::postBuild()
 		{
 			childSetCommitCallback("desc", LLPreview::onText, this);
 			childSetText("desc", item->getDescription());
-			childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
+			childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
 		}
 	}
 	
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 81eb133b07fcfc6875190c4d8fa8e8ad27ed9fdc..d1cf4a081033463e1797313fbd7e46a1c3513672 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -103,8 +103,8 @@ void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect ne
 
 void LLScreenChannelBase::init(S32 channel_left, S32 channel_right)
 {
-	S32 channel_top = gViewerWindow->getWorldViewRectRaw().getHeight();
-	S32 channel_bottom = gViewerWindow->getWorldViewRectRaw().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");
+	S32 channel_top = gViewerWindow->getWorldViewRectScaled().getHeight();
+	S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");
 	setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom));
 	setVisible(TRUE);
 }
@@ -710,7 +710,7 @@ void LLScreenChannel::updateShowToastsState()
 	// for Message Well floater showed in a docked state - adjust channel's height
 	if(dynamic_cast<LLSysWellWindow*>(floater))
 	{
-		S32 channel_bottom = gViewerWindow->getWorldViewRectRaw().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;
+		S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;
 		LLRect this_rect = getRect();
 		if(floater->getVisible() && floater->isDocked())
 		{
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index a3efea7b7e29588537dffa1eb1801b020b61312d..ff6e2d7363c05e005c24654b3af4b6eec2ced153 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -111,9 +111,9 @@ BOOL LLSidepanelItemInfo::postBuild()
 
 	// build the UI
 	// item name & description
-	childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	//getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitName,this));
-	childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidateASCIIPrintableNoPipe);
 	//getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLSidepanelItemInfo:: onCommitDescription, this));
 
 	// Creator information
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
index 01c832d7d565c7b0db37b8eb29702b7161fffc44..4396cce545142f7646ca6bf0eb66e2fc2a0f73a3 100644
--- a/indra/newview/llsidepaneltaskinfo.cpp
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -100,8 +100,8 @@ BOOL LLSidepanelTaskInfo::postBuild()
 	mBuyBtn = getChild<LLButton>("buy_btn");
 	mBuyBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onBuyButtonClicked, this));
 
-	childSetPrevalidate("Object Name",LLLineEditor::prevalidatePrintableNotPipe);
-	childSetPrevalidate("Object Description",LLLineEditor::prevalidatePrintableNotPipe);
+	childSetPrevalidate("Object Name",LLLineEditor::prevalidateASCIIPrintableNoPipe);
+	childSetPrevalidate("Object Description",LLLineEditor::prevalidateASCIIPrintableNoPipe);
 
 //	getChild<LLUICtrl>("button set group")->setCommitCallback(boost::bind(&LLSidepanelTaskInfo::onClickGroup,this));
 //	childSetAction("button deed",LLSidepanelTaskInfo::onClickDeedToGroup,this);
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 04ecf769d5514405252d6cd347b096a51317eaa7..539536b52770cff3292f38553bd807772ecf1b4b 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -238,7 +238,7 @@ void LLSysWellWindow::initChannel()
 //---------------------------------------------------------------------------------
 void LLSysWellWindow::getAllowedRect(LLRect& rect)
 {
-	rect = gViewerWindow->getWorldViewRectRaw();
+	rect = gViewerWindow->getWorldViewRectScaled();
 }
 
 //---------------------------------------------------------------------------------
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index e2ccc05e30f3e75358c655993906a8d12acfaab9..2320ae57df34c5437dd772ad3c058affca910ff5 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -365,7 +365,7 @@ BOOL LLToolCamera::handleHover(S32 x, S32 y, MASK mask)
 			// Orbit tool
 			if (hasMouseCapture())
 			{
-				const F32 RADIANS_PER_PIXEL = 360.f * DEG_TO_RAD / gViewerWindow->getWorldViewWidthRaw();
+				const F32 RADIANS_PER_PIXEL = 360.f * DEG_TO_RAD / gViewerWindow->getWorldViewWidthScaled();
 
 				if (dx != 0)
 				{
@@ -393,7 +393,7 @@ BOOL LLToolCamera::handleHover(S32 x, S32 y, MASK mask)
 				F32 dist = (F32) camera_to_focus.normVec();
 
 				// Fudge factor for pan
-				F32 meters_per_pixel = 3.f * dist / gViewerWindow->getWorldViewWidthRaw();
+				F32 meters_per_pixel = 3.f * dist / gViewerWindow->getWorldViewWidthScaled();
 
 				if (dx != 0)
 				{
@@ -415,7 +415,7 @@ BOOL LLToolCamera::handleHover(S32 x, S32 y, MASK mask)
 			if (hasMouseCapture())
 			{
 
-				const F32 RADIANS_PER_PIXEL = 360.f * DEG_TO_RAD / gViewerWindow->getWorldViewWidthRaw();
+				const F32 RADIANS_PER_PIXEL = 360.f * DEG_TO_RAD / gViewerWindow->getWorldViewWidthScaled();
 
 				if (dx != 0)
 				{
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index 44fb6e92715f38a2e9523568202358610b970ca5..26dbe6a489066456d7b89d33121deb6227f8c25b 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -510,8 +510,8 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 	const F32 RADIANS_PER_PIXEL_X = 0.01f;
 	const F32 RADIANS_PER_PIXEL_Y = 0.01f;
 
-	S32 dx = x - (gViewerWindow->getWorldViewWidthRaw() / 2);
-	S32 dy = y - (gViewerWindow->getWorldViewHeightRaw() / 2);
+	S32 dx = x - (gViewerWindow->getWorldViewWidthScaled() / 2);
+	S32 dy = y - (gViewerWindow->getWorldViewHeightScaled() / 2);
 
 	if (dx != 0 || dy != 0)
 	{
@@ -631,10 +631,10 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 			// Handle auto-rotation at screen edge.
 			LLVector3 grab_pos_agent = gAgent.getPosAgentFromGlobal( grab_point_global );
 
-			LLCoordGL grab_center_gl( gViewerWindow->getWorldViewWidthRaw() / 2, gViewerWindow->getWorldViewHeightRaw() / 2);
+			LLCoordGL grab_center_gl( gViewerWindow->getWorldViewWidthScaled() / 2, gViewerWindow->getWorldViewHeightScaled() / 2);
 			LLViewerCamera::getInstance()->projectPosAgentToScreen(grab_pos_agent, grab_center_gl);
 
-			const S32 ROTATE_H_MARGIN = gViewerWindow->getWorldViewWidthRaw() / 20;
+			const S32 ROTATE_H_MARGIN = gViewerWindow->getWorldViewWidthScaled() / 20;
 			const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
 			const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
 			// ...build mode moves camera about focus point
@@ -649,7 +649,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 					gAgent.cameraOrbitAround(rotate_angle);
 				}
 			}
-			else if (grab_center_gl.mX > gViewerWindow->getWorldViewWidthRaw() - ROTATE_H_MARGIN)
+			else if (grab_center_gl.mX > gViewerWindow->getWorldViewWidthScaled() - ROTATE_H_MARGIN)
 			{
 				if (gAgent.getFocusOnAvatar())
 				{
@@ -662,7 +662,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 			}
 
 			// Don't move above top of screen or below bottom
-			if ((grab_center_gl.mY < gViewerWindow->getWorldViewHeightRaw() - 6)
+			if ((grab_center_gl.mY < gViewerWindow->getWorldViewHeightScaled() - 6)
 				&& (grab_center_gl.mY > 24))
 			{
 				// Transmit update to simulator
@@ -893,7 +893,7 @@ void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask)
 				gAgent.yaw(rotate_angle);
 				//gAgent.setControlFlags(AGENT_CONTROL_YAW_POS);
 			}
-			else if (x == (gViewerWindow->getWorldViewWidthRaw() - 1) )
+			else if (x == (gViewerWindow->getWorldViewWidthScaled() - 1) )
 			{
 				gAgent.yaw(-rotate_angle);
 				//gAgent.setControlFlags(AGENT_CONTROL_YAW_NEG);
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index 49506db17381180475eadae67ac121da98ef9b3b..e7f904023a69ae3f79a69d9a26c1868689d46184 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -86,16 +86,6 @@ void init_audio()
 		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectDelete")));
 		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectRezIn")));
 		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectRezOut")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuAppear")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuHide")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight0")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight1")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight2")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight3")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight4")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight5")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight6")));
-		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight7")));
 		gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndSnapshot")));
 		//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndStartAutopilot")));
 		//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndStartFollowpilot")));
@@ -231,9 +221,9 @@ void audio_update_wind(bool force_update)
 			}
 		}
 		// this line rotates the wind vector to be listener (agent) relative
-		// unfortunately we have to pre-translate to undo the translation that
-		// occurs in the transform call
-		gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal(gWindVec - gAgent.getVelocity());
+		// Only use the agent's motion to compute wind noise, otherwise the world
+		// feels desolate on login when you are standing still.
+		gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal( -gAgent.getVelocity() );
 
 		// don't use the setter setMaxWindGain() because we don't
 		// want to screw up the fade-in on startup by setting actual source gain
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index 5566fea89f2217b32f3681bdb17513d87e727698..f3c64088c9b1be29477f3e63983afcf62a9bcbb5 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -485,7 +485,7 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
 		y /= gViewerWindow->getDisplayScale().mV[VY];
 
 		// should now have the x,y coords of grab_point in screen space
-		LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled();
+		LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
 
 		// convert to pixel coordinates
 		S32 int_x = lltrunc(x);
@@ -495,14 +495,14 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
 
 		if (clamp)
 		{
-			if (int_x < world_view_rect.mLeft)
+			if (int_x < world_rect.mLeft)
 			{
-				out_point.mX = world_view_rect.mLeft;
+				out_point.mX = world_rect.mLeft;
 				valid = FALSE;
 			}
-			else if (int_x > world_view_rect.mRight)
+			else if (int_x > world_rect.mRight)
 			{
-				out_point.mX = world_view_rect.mRight;
+				out_point.mX = world_rect.mRight;
 				valid = FALSE;
 			}
 			else
@@ -510,14 +510,14 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
 				out_point.mX = int_x;
 			}
 
-			if (int_y < world_view_rect.mBottom)
+			if (int_y < world_rect.mBottom)
 			{
-				out_point.mY = world_view_rect.mBottom;
+				out_point.mY = world_rect.mBottom;
 				valid = FALSE;
 			}
-			else if (int_y > world_view_rect.mTop)
+			else if (int_y > world_rect.mTop)
 			{
-				out_point.mY = world_view_rect.mTop;
+				out_point.mY = world_rect.mTop;
 				valid = FALSE;
 			}
 			else
@@ -531,19 +531,19 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
 			out_point.mX = int_x;
 			out_point.mY = int_y;
 
-			if (int_x < world_view_rect.mLeft)
+			if (int_x < world_rect.mLeft)
 			{
 				valid = FALSE;
 			}
-			else if (int_x > world_view_rect.mRight)
+			else if (int_x > world_rect.mRight)
 			{
 				valid = FALSE;
 			}
-			if (int_y < world_view_rect.mBottom)
+			if (int_y < world_rect.mBottom)
 			{
 				valid = FALSE;
 			}
-			else if (int_y > world_view_rect.mTop)
+			else if (int_y > world_rect.mTop)
 			{
 				valid = FALSE;
 			}
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 703a13976cfc7aa080e39a590532785a12603347..dbcf5630102c514dc6653c912f8cba0c8934c57d 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1467,14 +1467,14 @@ struct UIImageDeclaration : public LLInitParam::Block<UIImageDeclaration>
 	Mandatory<std::string>	name;
 	Optional<std::string>	file_name;
 	Optional<bool>			preload;
-	Optional<LLRect>		scale_rect;
+	Optional<LLRect>		scale;
 	Optional<bool>			use_mips;
 
 	UIImageDeclaration()
 	:	name("name"),
 		file_name("file_name"),
 		preload("preload", false),
-		scale_rect("scale"),
+		scale("scale"),
 		use_mips("use_mips", false)
 	{}
 };
@@ -1564,7 +1564,7 @@ bool LLUIImageList::initFromFile()
 			{
 				continue;
 			}
-			preloadUIImage(image_it->name, file_name, image_it->use_mips, image_it->scale_rect);
+			preloadUIImage(image_it->name, file_name, image_it->use_mips, image_it->scale);
 		}
 
 		if (cur_pass == PASS_DECODE_NOW && !gSavedSettings.getBOOL("NoPreload"))
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index c21c287fb6d6cd27010c5d1e63668f3ab28e9f24..db66faef8139a56c344335e92aa6221604f2300c 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2278,7 +2278,7 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
 
 	// Zoom the camera in and out behavior
 
-	if(top_ctrl == 0 && mWorldViewRectRaw.pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) )
+	if(top_ctrl == 0 && getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) )
 		gAgent.handleScrollWheel(clicks);
 
 	return;
@@ -2286,8 +2286,8 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
 
 void LLViewerWindow::moveCursorToCenter()
 {
-	S32 x = mWorldViewRectRaw.getWidth() / 2;
-	S32 y = mWorldViewRectRaw.getHeight() / 2;
+	S32 x = getWorldViewWidthScaled() / 2;
+	S32 y = getWorldViewHeightScaled() / 2;
 	
 	//on a forced move, all deltas get zeroed out to prevent jumping
 	mCurrentMousePoint.set(x,y);
@@ -2858,6 +2858,11 @@ void LLViewerWindow::updateWorldViewRect(bool use_full_window)
 		// clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers
 		new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1);
 		new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1);
+
+		new_world_rect.mLeft = llround((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]);
+		new_world_rect.mRight = llround((F32)new_world_rect.mRight * mDisplayScale.mV[VX]);
+		new_world_rect.mBottom = llround((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]);
+		new_world_rect.mTop = llround((F32)new_world_rect.mTop * mDisplayScale.mV[VY]);
 	}
 
 	if (mWorldViewRectRaw != new_world_rect)
@@ -2869,6 +2874,12 @@ void LLViewerWindow::updateWorldViewRect(bool use_full_window)
 		gResizeScreenTexture = TRUE;
 		LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
 		LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
+
+		mWorldViewRectScaled = mWorldViewRectRaw;
+		mWorldViewRectScaled.mLeft = llround((F32)mWorldViewRectScaled.mLeft / mDisplayScale.mV[VX]);
+		mWorldViewRectScaled.mRight = llround((F32)mWorldViewRectScaled.mRight / mDisplayScale.mV[VX]);
+		mWorldViewRectScaled.mBottom = llround((F32)mWorldViewRectScaled.mBottom / mDisplayScale.mV[VY]);
+		mWorldViewRectScaled.mTop = llround((F32)mWorldViewRectScaled.mTop / mDisplayScale.mV[VY]);
 	}
 }
 
@@ -3140,10 +3151,10 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback
 	{
 		mPickScreenRegion.setCenterAndSize(x, y_from_bot, PICK_DIAMETER, PICK_DIAMETER);
 
-		if (mPickScreenRegion.mLeft < mWorldViewRectRaw.mLeft) mPickScreenRegion.translate(mWorldViewRectRaw.mLeft - mPickScreenRegion.mLeft, 0);
-		if (mPickScreenRegion.mBottom < mWorldViewRectRaw.mBottom) mPickScreenRegion.translate(0, mWorldViewRectRaw.mBottom - mPickScreenRegion.mBottom);
-		if (mPickScreenRegion.mRight > mWorldViewRectRaw.mRight ) mPickScreenRegion.translate(mWorldViewRectRaw.mRight - mPickScreenRegion.mRight, 0);
-		if (mPickScreenRegion.mTop > mWorldViewRectRaw.mTop ) mPickScreenRegion.translate(0, mWorldViewRectRaw.mTop - mPickScreenRegion.mTop);
+		if (mPickScreenRegion.mLeft < mWorldViewRectScaled.mLeft) mPickScreenRegion.translate(mWorldViewRectScaled.mLeft - mPickScreenRegion.mLeft, 0);
+		if (mPickScreenRegion.mBottom < mWorldViewRectScaled.mBottom) mPickScreenRegion.translate(0, mWorldViewRectScaled.mBottom - mPickScreenRegion.mBottom);
+		if (mPickScreenRegion.mRight > mWorldViewRectScaled.mRight ) mPickScreenRegion.translate(mWorldViewRectScaled.mRight - mPickScreenRegion.mRight, 0);
+		if (mPickScreenRegion.mTop > mWorldViewRectScaled.mTop ) mPickScreenRegion.translate(0, mWorldViewRectScaled.mTop - mPickScreenRegion.mTop);
 	}
 
 	// set frame buffer region for picking results
@@ -3349,11 +3360,11 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
 	F32			fov = LLViewerCamera::getInstance()->getView();
 
 	// find world view center in scaled ui coordinates
-	F32			center_x = (F32)getWorldViewRectRaw().getCenterX() / mDisplayScale.mV[VX];
-	F32			center_y = (F32)getWorldViewRectRaw().getCenterY() / mDisplayScale.mV[VY];
+	F32			center_x = getWorldViewRectScaled().getCenterX();
+	F32			center_y = getWorldViewRectScaled().getCenterY();
 
 	// calculate pixel distance to screen
-	F32			distance = ((F32)getWorldViewHeightRaw() / (mDisplayScale.mV[VY] * 2.f)) / (tan(fov / 2.f));
+	F32			distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f));
 
 	// calculate click point relative to middle of screen
 	F32			click_x = x - center_x;
@@ -3372,11 +3383,11 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
 LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
 {
 	// find screen resolution
-	S32			height = llround((F32)getWorldViewHeightRaw() / mDisplayScale.mV[VY]);
+	S32			height = getWorldViewHeightScaled();
 
 	// find world view center
-	F32			center_x = (F32)getWorldViewRectRaw().getCenterX() / mDisplayScale.mV[VX];
-	F32			center_y = (F32)getWorldViewRectRaw().getCenterY() / mDisplayScale.mV[VY];
+	F32			center_x = getWorldViewRectScaled().getCenterX();
+	F32			center_y = getWorldViewRectScaled().getCenterY();
 
 	// remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
 	F32 hud_x = -((F32)x - center_x)  / height;
@@ -3394,12 +3405,12 @@ LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const
 	F32			fov_width = fov_height * LLViewerCamera::getInstance()->getAspect();
 
 	// find screen resolution
-	S32			height = llround((F32)getWorldViewHeightRaw() / mDisplayScale.mV[VY]);
-	S32			width = llround((F32)getWorldViewWidthRaw() / mDisplayScale.mV[VX]);
+	S32			height = getWorldViewHeightScaled();
+	S32			width = getWorldViewWidthScaled();
 
 	// find world view center
-	F32			center_x = (F32)getWorldViewRectRaw().getCenterX() / mDisplayScale.mV[VX];
-	F32			center_y = (F32)getWorldViewRectRaw().getCenterY() / mDisplayScale.mV[VY];
+	F32			center_x = getWorldViewRectScaled().getCenterX();
+	F32			center_y = getWorldViewRectScaled().getCenterY();
 
 	// calculate click point relative to middle of screen
 	F32			click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f;
@@ -4166,14 +4177,20 @@ LLRootView*	LLViewerWindow::getRootView() const
 
 LLRect LLViewerWindow::getWorldViewRectScaled() const
 {
-	LLRect world_view_rect = mWorldViewRectRaw;
-	world_view_rect.mLeft = llround((F32)world_view_rect.mLeft / mDisplayScale.mV[VX]);
-	world_view_rect.mRight = llround((F32)world_view_rect.mRight / mDisplayScale.mV[VX]);
-	world_view_rect.mBottom = llround((F32)world_view_rect.mBottom / mDisplayScale.mV[VY]);
-	world_view_rect.mTop = llround((F32)world_view_rect.mTop / mDisplayScale.mV[VY]);
-	return world_view_rect;
+	return mWorldViewRectScaled;
+}
+
+S32 LLViewerWindow::getWorldViewHeightScaled() const
+{
+	return mWorldViewRectScaled.getHeight();
 }
 
+S32 LLViewerWindow::getWorldViewWidthScaled() const
+{
+	return mWorldViewRectScaled.getWidth();
+}
+
+
 S32 LLViewerWindow::getWorldViewHeightRaw() const
 {
 	return mWorldViewRectRaw.getHeight(); 
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index ce71ef6173d84a0551732b5656d9a8cd86ae390c..517993182beb17063f57f3e26631c4190eef5135 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -212,6 +212,8 @@ class LLViewerWindow : public LLWindowCallbacks
 
 	// 3D world area in scaled pixels (via UI scale), use for most UI computations
 	LLRect			getWorldViewRectScaled() const;
+	S32				getWorldViewHeightScaled() const;
+	S32				getWorldViewWidthScaled() const;
 
 	// 3D world area, in raw unscaled pixels
 	LLRect			getWorldViewRectRaw() const		{ return mWorldViewRectRaw; }
@@ -415,6 +417,7 @@ class LLViewerWindow : public LLWindowCallbacks
 	LLRect			mWindowRectRaw;				// whole window, including UI
 	LLRect			mWindowRectScaled;			// whole window, scaled by UI size
 	LLRect			mWorldViewRectRaw;			// area of screen for 3D world
+	LLRect			mWorldViewRectScaled;		// area of screen for 3D world scaled by UI size
 	LLRootView*		mRootView;					// a view of size mWindowRectRaw, containing all child views
 	LLVector2		mDisplayScale;
 
diff --git a/indra/newview/skins/default/textures/icons/MinusItem_Disabled.png b/indra/newview/skins/default/textures/icons/MinusItem_Disabled.png
new file mode 100644
index 0000000000000000000000000000000000000000..75bd73cef1a3a49574463ab5aab0f705ce02228a
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/MinusItem_Disabled.png differ
diff --git a/indra/newview/skins/default/textures/icons/MinusItem_Off.png b/indra/newview/skins/default/textures/icons/MinusItem_Off.png
new file mode 100644
index 0000000000000000000000000000000000000000..6f285f35462906c83fd74f5177f995f5ba7fda2c
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/MinusItem_Off.png differ
diff --git a/indra/newview/skins/default/textures/icons/MinusItem_Press.png b/indra/newview/skins/default/textures/icons/MinusItem_Press.png
new file mode 100644
index 0000000000000000000000000000000000000000..50f65765d5f705920468233ed5bd85e683600cff
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/MinusItem_Press.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 8af65b25e9815f4ded75e5dbeeefca77752cd6cf..f4a239be62145f3ba0db0c15ceed6d9f149941ef 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -1,3 +1,33 @@
+<!--
+This file contains metadata about how to load, display, and scale textures for rendering in the UI.
+Images do *NOT* have to appear in this file in order to use them as textures in the UI...simply refer 
+to them by filename (relative to textures directory).
+NOTE: if you want to reuse an image file with different metadata, simply create a new texture entry 
+with the same filename but different name
+
+<texture
+  name="MyTexture" (mandatory)
+    - this is the name you reference the texture by in XUI.  For example, <button image_unselected="MyTexture"/>
+  file_name="images/my_texture.png" (optional)
+    - this is the path to the actual file asset, relative to the current skins "textures" directory.  
+      If not supplied, the filename will be taken from the texture name itself, "MyTexture" in this case.  
+      NOTE: you need to provide an extension on the filename (".png", ".tga", ".jpg") for us to decode the image properly
+  preload="true" (optional, false by default)
+    - If true, we will attempt to load the image before displaying any UI.  
+      If false, we will load in the background after initializing the UI.
+  use_mips="true" (currently unused)
+  scale.left="1"
+  scale.bottom="1"
+  scale.top="15"
+  scale.right="31"
+    - Specifies the segmentation for 9-slice image scaling.  Specifically, the pixel offsets from the LOWER LEFT corner
+      that define the region of the image that is stretched to make the whole image fit in the required space.
+      In this example, if the source image is 32x16 pixels, we have defined a center region that starts one pixel up
+      and to the right from the bottom left corner and extends to 31 pixels right and 15 pixels up from the bottom left 
+      corner.  The end result is that the image will keep a 1 pixel border all around while stretching to fit the required 
+      region.
+-->
+
 <textures version="101">
   <!-- Please add new files alphabetically to prevent merge conflicts. JC -->
   <texture name="Accordion_ArrowClosed_Off" file_name="containers/Accordion_ArrowClosed_Off.png" preload="false" />
@@ -106,7 +136,6 @@
   <texture name="DropDown_Press" file_name="widgets/DropDown_Press.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
   <texture name="DropDown_Selected" file_name="widgets/DropDown_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
   <texture name="DropDown_Off" file_name="widgets/DropDown_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
-  <texture name="DropDown_On" file_name="widgets/DropDown_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
 
   <texture name="DropTarget" file_name="widgets/DropTarget.png" preload="false" />
 
@@ -231,6 +260,10 @@
   <texture name="Microphone_Mute" file_name="icons/Microphone_Mute.png" preload="false" />
   <texture name="Microphone_On" file_name="icons/Microphone_On.png" preload="false" />
 
+  <texture name="MinusItem_Disabled" file_name="icons/MinusItem_Disabled.png" preload="false" />
+  <texture name="MinusItem_Off" file_name="icons/MinusItem_Off.png" preload="false" />
+  <texture name="MinusItem_Press" file_name="icons/MinusItem_Press.png" preload="false" />
+
   <texture name="menu_separator" file_name="navbar/FileMenu_Divider.png" scale.left="4" scale.top="166" scale.right="0" scale.bottom="0" />
 
   <texture name="Move_Fly_Disabled" file_name="bottomtray/Move_Fly_Disabled.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml
index e4ab533bc59229da24bddc1c6854b6ad1fa6eba3..4bbd5618827fe48d4fb324c6d6bfe8f40d01f15b 100644
--- a/indra/newview/skins/default/xui/en/floater_aaa.xml
+++ b/indra/newview/skins/default/xui/en/floater_aaa.xml
@@ -5,6 +5,6 @@
  name="floater_aaa"
  can_resize="true" 
  width="1024">
- <string name="Nudge Parabuild">1</string>
+ <string name="Nudge Parabuild">2</string>
   <panel filename="main_view.xml" follows="all" width="1024" height="768" top="0"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml
index f553184c19a12fe6e374e0133467af32eb4791b2..69f9f6a2f874df5642d0095cd3ff21b4e8751f9d 100644
--- a/indra/newview/skins/default/xui/en/floater_camera.xml
+++ b/indra/newview/skins/default/xui/en/floater_camera.xml
@@ -87,9 +87,9 @@
            <button
               follows="top|left"
               height="18"
-              image_disabled="AddItem_Disabled"
-              image_selected="AddItem_Press"
-              image_unselected="AddItem_Off"
+              image_disabled="MinusItem_Disabled"
+              image_selected="MinusItem_Press"
+              image_unselected="MinusItem_Off"
               layout="topleft"
               name="zoom_minus_btn"
               top_pad="0"
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 4792a1a476026a246f46bc9cbbe804df18098adf..e972cf39bf7459e239ed470da405923d9d81a996 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -8,67 +8,71 @@
  left="0"
  name="panel_im"
  top="0"
- can_close="false"
+ can_close="true"
  can_dock="true"
- can_minimize="false"
+ can_minimize="true"
  visible="true"
- width="320"
+ width="350"
  can_resize="true"
  min_width="300"
  min_height="350">
-  <layout_stack follows="all"
-                height="350"
-                width="300"
-                layout="topleft"
-                orientation="horizontal"
-                name="im_panels"
-                top="20"
-                left="0">
+  <layout_stack
+  follows="all"
+  height="350"
+  width="300"
+  layout="topleft"
+  orientation="horizontal"
+  name="im_panels"
+  top="20"
+  left="0">
     <layout_panel
       name="panel_im_control_panel"
       layout="topleft"
-      top_delta="-3"
-      height="350"
       follows="left"
       label="IM Control Panel"
       auto_resize="false"
       user_resize="false" />
-    <layout_panel height="350"
-                  width=""
-                  left_delta="110"
-                  top="0"
-                  user_resize="false">
-      <button height="20"
-      	      follows="left|top"
-              top="0"
-              image_overlay="TabIcon_Open_Off"
-              layout="topleft"
-              width="25"
-              name="slide_left_btn" />
-      <button height="20"
-      	      follows="left|top"
-              top="0"
-              image_overlay="TabIcon_Close_Off"
-              width="25"
-              name="slide_right_btn" />
-      <chat_history
-       length="1"
-       follows="all"
-       height="275"
-       layout="topleft"
-       name="chat_history"
-       parse_highlights="true"
-       allow_html="true"
-       width="160">
-      </chat_history>
-      <line_editor
-       follows="left|right"
-       height="20"
-       label="To"
-       layout="topleft"
-       name="chat_editor"
-       width="160">
-      </line_editor>
+    <layout_panel
+       left="0"
+       top="0"
+       user_resize="false">
+        <button
+          height="20"
+          follows="left|top"
+          top="0"
+          left="2"
+          image_overlay="TabIcon_Open_Off"
+          layout="topleft"
+          width="25"
+          name="slide_left_btn" />
+         <button
+          height="20"
+          follows="left|top"
+          top="0"
+          left="2"
+          image_overlay="TabIcon_Close_Off"
+          width="25"
+          name="slide_right_btn" />
+        <chat_history
+         length="1"
+	 font="SansSerifSmall"
+         follows="left|right|top"
+         height="280"
+         name="chat_history"
+         parse_highlights="true"
+         allow_html="true"
+        left="1"
+         width="180">
+        </chat_history>
+        <line_editor
+         follows="left|right|top"
+	 font="SansSerifSmall"
+         height="20"
+         label="To"
+         name="chat_editor"
+         top_pad="1"
+         width="180">
+        </line_editor>
     </layout_panel>
   </layout_stack>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_land_holdings.xml b/indra/newview/skins/default/xui/en/floater_land_holdings.xml
index 2c04a946131d1427ff80089b8d8dee86091db739..e3751f2bd992340d576264a9c2abac859e895efe 100644
--- a/indra/newview/skins/default/xui/en/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/en/floater_land_holdings.xml
@@ -42,7 +42,7 @@
     </scroll_list>
     <button
      height="23"
-     font="SansSerifBold"
+     font="SansSerif"
      label="Teleport"
      label_selected="Teleport"
      layout="topleft"
@@ -53,7 +53,7 @@
      width="80" />
     <button
      height="23"
-     font="SansSerifBold"
+     font="SansSerif"
      label="Map"
      label_selected="Map"
      layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index 69b015a727ed0b5fc80099a482f38eebcf9923a2..d8534bfe0ba02716e4975284357f1ee66f7f1aa6 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -5,7 +5,7 @@
  can_tear_off="false"
  can_resize="true"
  can_drag_on_left="false"
- can_close="false"
+ can_close="true"
  can_dock="true"
  bevel_style="in"
  height="300"
diff --git a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
index 6faab84159d3d520ae73dd60cb3afba814c6a4f0..4909b8988f995d2aac00bc96e84f1f5af71c2098 100644
--- a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
@@ -22,10 +22,10 @@
          height="16"
          label="Share with group"
          layout="topleft"
-         left_delta="-250"
+         left="10"
          name="share_with_group"
-         top_delta="2"
-         width="106" />
+         top="5"
+         width="150" />
         <check_box
          control_name="EveryoneCopy"
          height="16"
@@ -33,8 +33,8 @@
          layout="topleft"
          left_delta="0"
          name="everyone_copy"
-         top_pad="16"
-         width="130" />
+         top_pad="5"
+         width="150" />
         <text
          type="string"
          length="1"
@@ -43,8 +43,8 @@
          layout="topleft"
          left_delta="0"
          name="NextOwnerLabel"
-         top_pad="16"
-         width="88">
+         top_pad="5"
+         width="150">
             Next owner can:
         </text>
         <check_box
@@ -54,17 +54,17 @@
          layout="topleft"
          left_delta="0"
          name="next_owner_modify"
-         top_pad="14"
-         width="78" />
+         top_pad="5"
+         width="150" />
         <check_box
          control_name="NextOwnerCopy"
          height="16"
          label="Copy"
          layout="topleft"
-         left_delta="78"
+         left_delta="0"
          name="next_owner_copy"
-         top_delta="0"
-         width="88" >
+         top_pad="5"
+         width="150" >
 		    <check_box.commit_callback
 			function="Perms.Copy" />
 		</check_box>
@@ -76,10 +76,10 @@
          initial_value="true"
          label="Resell/Give away"
          layout="topleft"
-         left_delta="88"
+         left_delta="0"
          name="next_owner_transfer"
-         top_delta="0"
-         width="106" />
+         top_pad="5"
+         width="150" />
     </panel>
     <button
      height="20"
diff --git a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
index e017d404c61a1b62f2bff133c1c3c1de4b3e9dd2..0531b52e5a04f77205acd9c259861642431a5aa0 100644
--- a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
@@ -18,7 +18,18 @@
     Enabled line editor
   </line_editor>
   <line_editor
-    enabled="false"
+   height="20"
+   layout="topleft"
+   left_delta="0"
+   name="ascii_line_editor"
+   prevalidate_callback="ascii"
+   tool_tip="ascii line editor"
+   top_pad="10" 
+   width="200">
+    ASCII only line editor
+  </line_editor>
+  <line_editor
+   enabled="false"
    height="20"
    layout="topleft"
    left_delta="0"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index bfbfe7de7caa221eae6ae385654ae24698e4003f..a626e1b3537af82545b30e9546ea5b66f5b2adea 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -811,11 +811,8 @@
                 Mixed Sale
             </panel.string>
             <text
-             type="string"
-             length="1"
              follows="left|top"
              height="10"
-             layout="topleft"
              left="10"
              name="Name:"
              top="0"
@@ -825,7 +822,6 @@
             <line_editor
              follows="left|top|right"
              height="19"
-             layout="topleft"
              left_pad="0"
              max_length="63"
              name="Object Name"
@@ -833,11 +829,8 @@
              top_delta="0"
              width="170" />
             <text
-             type="string"
-             length="1"
              follows="left|top"
              height="10"
-             layout="topleft"
              left="10"
              name="Description:"
              top_pad="3"
@@ -847,7 +840,6 @@
             <line_editor
              follows="left|top|right"
              height="19"
-             layout="topleft"
              left_pad="0"
              max_length="127"
              name="Object Description"
diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml
index 83570e25288e0088ba55e9cb16ea58204f1bfe47..16f6e49092ecdb98ce2c6cad643b10d6948f1a2e 100644
--- a/indra/newview/skins/default/xui/en/inspect_object.xml
+++ b/indra/newview/skins/default/xui/en/inspect_object.xml
@@ -38,14 +38,14 @@ owner [OWNER]
      width="220" />
   <text
    follows="all"
-   height="30"
+   height="33"
    left="8"
    name="object_creator"
    top_pad="0"
    use_ellipses="true"
    width="220">
-by Longavatarname Johnsonlongstonnammer
-owner James Linden
+    by secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
   </text>
   <!-- *TODO: Replace this icon -->
   <icon
@@ -54,7 +54,7 @@ owner James Linden
   right="-5"
   width="16"
   height="16"
-  top="50"
+  top="56"
   follows="left|top"
   />
   <text
@@ -66,7 +66,7 @@ owner James Linden
    left="5"
    name="price_text"
    text_color="white"
-   top="53"
+   top="58"
    font_shadow="none"
    width="196">
 L$300,000
diff --git a/indra/newview/skins/default/xui/en/menu_mini_map.xml b/indra/newview/skins/default/xui/en/menu_mini_map.xml
index 5cbbd71bfeba4fcad48eafd5a625d2d2b6d58f0f..8d0edf018d4162d97f950404de1e6670f66cce25 100644
--- a/indra/newview/skins/default/xui/en/menu_mini_map.xml
+++ b/indra/newview/skins/default/xui/en/menu_mini_map.xml
@@ -10,7 +10,6 @@
  width="128">
     <menu_item_call
      label="Zoom Close"
-     layout="topleft"
      name="Zoom Close">
         <menu_item_call.on_click
          function="Minimap.Zoom"
@@ -18,7 +17,6 @@
     </menu_item_call>
     <menu_item_call
      label="Zoom Medium"
-     layout="topleft"
      name="Zoom Medium">
         <menu_item_call.on_click
          function="Minimap.Zoom"
@@ -26,29 +24,31 @@
     </menu_item_call>
     <menu_item_call
      label="Zoom Far"
-     layout="topleft"
      name="Zoom Far">
         <menu_item_call.on_click
          function="Minimap.Zoom"
          parameter="far" />
     </menu_item_call>
-    <menu_item_separator
-     layout="topleft"
-     name="Tracking Separator" />
+    <menu_item_check
+       label="Rotate Map"
+       name="Rotate Map">
+          <menu_item_check.on_check
+             control="MiniMapRotate" />
+          <menu_item_check.on_click
+             function="ToggleControl"
+             parameter="MiniMapRotate" />
+    </menu_item_check>
+    <menu_item_separator />
     <menu_item_call
      label="Stop Tracking"
-     layout="topleft"
      name="Stop Tracking">
         <menu_item_call.on_click
          function="Minimap.Tracker"
          parameter="task_properties" />
     </menu_item_call>
-    <menu_item_separator
-     layout="topleft"
-     name="Tracking Separator" />
+    <menu_item_separator />
     <menu_item_call
      label="World Map"
-     layout="topleft"
      name="World Map">
         <menu_item_call.on_click
          function="ShowFloater"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 56cb54c97537f8f42fb21f1ea12f01a70f706fdc..0d1ed6fc649d06b1d4d83b3de0eaf21cb3b6dcaa 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5747,7 +5747,7 @@ Are you sure you want to delete your teleport history?
    name="BottomTrayButtonCanNotBeShown"
    type="alert">
 Selected button can not be shown right now.
-The button will be shown when there is enough space for it.
+The button will be shown when there is enough space for it.
   </notification>
 
 
diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
index 38294c907a3fab60aad946015d2c9812ffcc8a50..3ed91cb48f8f479d975ffa9e02db0642b0aa15a5 100644
--- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
@@ -7,8 +7,8 @@
 	left="0"
 	height="35"
 	width="318"
-  background_opaque="false"
-  background_visible="true"
+  background_opaque="false"
+  background_visible="true"
   bg_alpha_color="0.0 0.0 0.0 0.0" >
   <chiclet_im_p2p
 		name="p2p_chiclet"
diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml
index 323ee957e734f5d54c140b4074f403e53b7bea3e..7a3eae35a92d9866be5cecb2a9f0a513de93d0d1 100644
--- a/indra/newview/skins/default/xui/en/panel_chat_header.xml
+++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml
@@ -3,13 +3,13 @@
       background_visible="true"
      bevel_style="in"
      bg_alpha_color="black"
-     follows="top"
+     follows="top|left|right"
      height="24"
- label="im_header"
- layout="topleft"
- name="im_header"
- width="300">
-             <avatar_icon
+     label="im_header"
+     layout="topleft"
+     name="im_header"
+     width="300">
+            <avatar_icon
          follows="left"
          height="18"
          image_name="Generic_Person"
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
index 9573904c93e113840e1be30cd5f0c5256592b80f..73d843e6dd4821f3977d5d5b1c127bd84c4b13d3 100644
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -38,28 +38,29 @@
      label="Teleport"
      name="teleport_btn"
      width="100" />
-    <button
+  <!--  <button
      follows="left|top"
      height="20"
      label="Share"
      name="share_btn"
-     width="100" />
-    <button
+     width="100" />-->
+     <!--Removing pay button to save space - will update spec - verified by Erica/Steve -->
+ <!--   <button
      follows="left|top"
      height="20"
      label="Pay"
      name="pay_btn"
-     width="100" />
+     width="100" />-->
     <panel
      background_visible="true"
      bg_alpha_color="DkGray2"
      border="false"
-     follows="left|top"
+     top_pad="10"
+     follows="left|bottom"
      height="70"
-     left="0"
-     left_pad="0"
+     left="1"
      name="panel_call_buttons"
-     width="110">
+     width="109">
         <button
          bottom="10"
          height="20"
diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml
index 962dad33633750ae2b42756385b78a3df4177a58..5cefe3e4ab58b4b0fb686b60831ca039921722dd 100644
--- a/indra/newview/skins/default/xui/en/panel_picks.xml
+++ b/indra/newview/skins/default/xui/en/panel_picks.xml
@@ -131,7 +131,7 @@
        <button
          enabled="false"
          follows="bottom|left"
-         font="SansSerifSmallBold"
+         font="SansSerifSmall"
          height="25"
          label="Info"
          layout="topleft"
@@ -143,7 +143,7 @@
         <button
          enabled="false"
          follows="bottom|left"
-         font="SansSerifSmallBold"
+         font="SansSerifSmall"
          height="25"
          label="Teleport"
          layout="topleft"
@@ -155,7 +155,7 @@
         <button
          enabled="false"
          follows="bottom|left"
-         font="SansSerifSmallBold"
+         font="SansSerifSmall"
          height="25"
          label="Map"
          layout="topleft"
@@ -167,7 +167,7 @@
         <button
          enabled="false"
          follows="bottom|right"
-         font="SansSerifSmallBold"
+         font="SansSerifSmall"
          height="25"
          label="â–¼"
          layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index 8fc78c670195d4b858b56db1d46c4c15b54a1852..b1afe76500d14d840a0549e8eae1b304ecc64008 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -48,38 +48,40 @@
      image_unselected="BuyArrow_Off"
      image_pressed="BuyArrow_Press"
      height="16"
-     left="-245"
+     left="-200"
      name="buycurrency"
-     pad_right="22px"
+     pad_right="20px"
      tool_tip="My Balance: Click to buy more L$"
      top="1"
-     width="117" />
-    <button
-     follows="right|bottom"
-     height="16"
-     image_selected="parcel_drk_VoiceNo"
-     image_unselected="parcel_drk_Voice"
-     is_toggle="true"
-     left_pad="15"
-     top="1"
-     name="volume_btn"
-     width="16" />
+     width="90" />
     <text
      type="string"
      length="1"
+     font="SansSerifSmall"
      text_readonly_color="TimeTextColor"
      follows="right|bottom"
      halign="right"
      height="16"
      top="5"
      layout="topleft"
-     left_pad="7"
+     left_pad="-5"
      name="TimeText"
      text_color="TimeTextColor"
      tool_tip="Current time (Pacific)"
      width="80">
         12:00 AM
     </text>
+    <button
+     follows="right|bottom"
+     height="16"
+     image_selected="parcel_drk_VoiceNo"
+     image_unselected="parcel_drk_Voice"
+     is_toggle="true"
+     left_pad="5"
+     top="1"
+     name="volume_btn"
+     tool_tip="Global Volume Control"
+     width="16" />
     <text
      enabled="true"
      follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
index 63e60aab784d7be42230dc9a429e8a0c5346567c..ccb57b65526f0ce6f3a483e0c4e4dcf7d28540f5 100644
--- a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
@@ -10,8 +10,8 @@
   height="35"
   layout="topleft"
   follows="left|right"
-  background_opaque="false"
-  background_visible="true"
+  background_opaque="false"
+  background_visible="true"
   bg_alpha_color="0.0 0.0 0.0 0.0" >
   <text
     top="2"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
index 2ce156cfda77ed082354911e67c7310036121c43..041297a542fead2d38855d796af1cb12b70874a0 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
@@ -62,7 +62,7 @@
   	     width="313" />
     <button
   	     follows="bottom|left"
-  	     font="SansSerifSmallBold"
+     font="SansSerifSmall"
   	     height="25"
   	     label="Wear"
   	     layout="topleft"
@@ -72,7 +72,7 @@
        	 width="80" />
     <button
     	 follows="bottom|left"
-  	     font="SansSerifSmallBold"
+     font="SansSerifSmall"
   	     height="25"
   	     label="New Outfit"
   	     layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index cbcc3f10ad2a7828edf69a0f7d1a8f646a3f2db8..377d34cdcc05e58a23b58e794a23a5c0e0c88e85 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -41,7 +41,7 @@
 			<button
 				 enabled="true"
 				 follows="bottom|left"
-				 font="SansSerifSmallBold"
+				 font="SansSerifSmall"
 				 height="25"
 				 label="Info"
 				 layout="topleft"
@@ -52,7 +52,7 @@
 			<button
 				 enabled="true"
 				 follows="bottom|left"
-				 font="SansSerifSmallBold"
+				 font="SansSerifSmall"
 				 height="25"
 				 label="Share"
 				 layout="topleft"
@@ -63,7 +63,7 @@
 			<button
 				 enabled="false"
 				 follows="bottom|left"
-				 font="SansSerifSmallBold"
+				 font="SansSerifSmall"
 				 height="25"
 				 label="Wear"
 				 layout="topleft"
@@ -74,7 +74,7 @@
 			<button
 				 enabled="false"
 				 follows="bottom|left"
-				 font="SansSerifSmallBold"
+				 font="SansSerifSmall"
 				 height="25"
 				 label="Play"
 				 layout="topleft"
@@ -85,7 +85,7 @@
 			<button
 				 enabled="false"
 				 follows="bottom|left"
-				 font="SansSerifSmallBold"
+				 font="SansSerifSmall"
 				 height="25"
 				 label="Teleport"
 				 layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
index 39cd75074e566795af344c8f71a1066e712ac167..0c605650fc9a1f5c7a1e592ed2cbd3caadc6f1ce 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
@@ -479,7 +479,7 @@
 		 width="313">
 	    <button
 		     follows="bottom|left"
-		     font="SansSerifSmallBold"
+		     font="SansSerifSmall"
 		     height="25"
 		     label="Edit"
 		     layout="topleft"
@@ -489,7 +489,7 @@
 		     width="50" />
 	    <button
 		     follows="bottom|right"
-		     font="SansSerifSmallBold"
+		     font="SansSerifSmall"
 		     height="25"
 		     label="Cancel"
 		     layout="topleft"
@@ -499,7 +499,7 @@
 		     width="70" />
 	    <button
 		     follows="bottom|right"
-		     font="SansSerifSmallBold"
+		     font="SansSerifSmall"
 		     height="25"
 		     label="Save"
 		     layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
index 8eb22541126304100d4f973b00110174e5ffd11a..7647be78306361411e3b37272029fe26d356a0a3 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
@@ -485,7 +485,7 @@
 		 width="313">
 	    <button
 		     follows="bottom|left"
-		     font="SansSerifSmallBold"
+		     font="SansSerifSmall"
 		     height="25"
 		     label="Edit"
 		     layout="topleft"
@@ -495,7 +495,7 @@
 		     width="50" />
 	    <button
 		     follows="bottom|left"
-		     font="SansSerifSmallBold"
+		     font="SansSerifSmall"
 		     height="25"
 		     label="Open"
 		     layout="topleft"
@@ -505,7 +505,7 @@
 		     width="60" />
 	    <button
 		     follows="bottom|left"
-		     font="SansSerifSmallBold"
+		     font="SansSerifSmall"
 		     height="25"
 		     label="Pay"
 		     layout="topleft"
@@ -515,7 +515,7 @@
 		     width="50" />
 	    <button
 		     follows="bottom|left"
-		     font="SansSerifSmallBold"
+		     font="SansSerifSmall"
 		     height="25"
 		     label="Buy"
 		     layout="topleft"
@@ -525,7 +525,7 @@
 		     width="60" />
 	    <button
 		     follows="bottom|right"
-		     font="SansSerifSmallBold"
+		     font="SansSerifSmall"
 		     height="25"
 		     label="Cancel"
 		     layout="topleft"
@@ -535,7 +535,7 @@
 		     width="70" />
 	    <button
 		     follows="bottom|right"
-		     font="SansSerifSmallBold"
+		     font="SansSerifSmall"
 		     height="25"
 		     label="Save"
 		     layout="topleft"