diff options
63 files changed, 2821 insertions, 2852 deletions
| diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 75905d0927..c2f91ff7e0 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 d3daa941cf..4474963b1a 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -235,8 +235,8 @@ public:  	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 caaf47240f..cd795282f9 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 94a2ca16f4..74ae8db0c7 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 3443d8b593..0aed5549a1 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -127,7 +127,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 886f5ec924..cd3432190b 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 015a947d91..22d6098d5b 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 3fe711a166..d18f127f85 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 b7296518d4..810761e034 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 e0d4a59d9d..ff9002787c 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 4192c6a586..955bc64e05 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 c2c83191e0..ab768bf236 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 524a889f97..c081af5879 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 dc32291714..ab8cc0bad7 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1,2555 +1,2555 @@ -/**  - * @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;
 +	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->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"); - +	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 9ca207a579..f30821cacf 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 bcaebb6bbb..8535d52015 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 90c009887d..5cd40273f6 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 16a47890c3..1567668813 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 6145588df2..234fe13217 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 7088ab3e70..3d7f3233ac 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -80,9 +80,7 @@ public:  	/*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 @@ private:  	LLUUID			mClosestAgentToCursor;  	LLUUID			mClosestAgentAtLastRightClick; -	BOOL			mRotateMap;  	std::string		mToolTipMsg;  }; diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 1f68c76bfc..5c11bc7310 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 26730e1f10..b7466ec6d4 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 94e733913d..598d021703 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 70b86e8b97..4be98201d1 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 60a27d5154..b962fa2184 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 1c2875bf46..a1d54367c9 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 b3e14eb2fb..78f3469f0e 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 1051326e72..0dc010e2e7 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 604faf8eb4..92bd4dc62b 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 7b3a20d102..49a2a3723d 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 ab9cfbf850..ce81077d80 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 2382befcfa..4e4711f8fb 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 7659c50ed3..d7fd252fb6 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 13d02b7dec..41cf402d6f 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 81eb133b07..d1cf4a0810 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 a3efea7b7e..ff6e2d7363 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 01c832d7d5..4396cce545 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 04ecf769d5..539536b527 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 e2ccc05e30..2320ae57df 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 44fb6e9271..26dbe6a489 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 49506db173..e7f904023a 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 5566fea89f..f3c64088c9 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 703a13976c..dbcf563010 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 c21c287fb6..db66faef81 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 ce71ef6173..517993182b 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -212,6 +212,8 @@ public:  	// 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 @@ protected:  	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.pngBinary files differ new file mode 100644 index 0000000000..75bd73cef1 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/MinusItem_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/MinusItem_Off.png b/indra/newview/skins/default/textures/icons/MinusItem_Off.pngBinary files differ new file mode 100644 index 0000000000..6f285f3546 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/MinusItem_Off.png diff --git a/indra/newview/skins/default/textures/icons/MinusItem_Press.png b/indra/newview/skins/default/textures/icons/MinusItem_Press.pngBinary files differ new file mode 100644 index 0000000000..50f65765d5 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/MinusItem_Press.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 8af65b25e9..f4a239be62 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_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index f553184c19..69f9f6a2f8 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_land_holdings.xml b/indra/newview/skins/default/xui/en/floater_land_holdings.xml index 2c04a94613..e3751f2bd9 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_test_line_editor.xml b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml index e017d404c6..0531b52e5a 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 bfbfe7de7c..a626e1b353 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 83570e2528..16f6e49092 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 5cbbd71bfe..8d0edf018d 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 56cb54c975..0d1ed6fc64 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 38294c907a..3ed91cb48f 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_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml index 962dad3363..5cefe3e4ab 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_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml index 63e60aab78..ccb57b6552 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 2ce156cfda..89cf9e006c 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="SansSerifSmallBold"    	     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 cbcc3f10ad..377d34cdcc 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 39cd75074e..0c605650fc 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 8eb2254112..7647be7830 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" | 
