Commits

Anonymous committed d4b9713 Merge

merge

  • Participants
  • Parent commits 877939d, 7caaf27

Comments (0)

Files changed (64)

indra/llui/lllineeditor.cpp

 	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()
 	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;
 }
 
 
+// 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;
 	return rv;
 }
 
+
 // static
 BOOL LLLineEditor::prevalidateASCII(const LLWString &str)
 {

indra/llui/lllineeditor.h

 	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);

indra/llui/lltextbase.cpp

 	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';
 }
 

indra/newview/app_settings/settings.xml

       <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>

indra/newview/llchannelmanager.cpp

 	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));

indra/newview/llfloatergodtools.cpp

 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");

indra/newview/llfloaterland.cpp

 {
 	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:");

indra/newview/llfloatermap.cpp

 {
 	mMap = getChild<LLNetMap>("Net Map");
 	mMap->setScale(gSavedSettings.getF32("MiniMapScale"));
-	mMap->setRotateMap(gSavedSettings.getBOOL( "MiniMapRotate" ));
 	mMap->setToolTipMsg(getString("ToolTipMsg"));	
 	sendChildToBack(mMap);
 	
 {
 	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] );

indra/newview/llfloaternamedesc.cpp

 	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);
 	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);

indra/newview/llfloaterproperties.cpp

 {
 	// 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));

indra/newview/llfolderview.cpp

 	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);

indra/newview/llimfloater.cpp

 
 void LLIMFloater::getAllowedRect(LLRect& rect)
 {
-	rect = gViewerWindow->getWorldViewRectRaw();
+	rect = gViewerWindow->getWorldViewRectScaled();
 }
 
 void LLIMFloater::setDocked(bool docked, bool pop_on_undock)

indra/newview/llimhandler.cpp

 //--------------------------------------------------------------------------
 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);
 }

indra/newview/llimview.cpp

-/** 
- * @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 "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();
+/** 
+ * @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 "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;