diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 9ef9b4bbec52009154b042ca52bfbfb095065a54..663749b98378265865d72c53045650abd82c0a6e 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -60,7 +60,8 @@ void NotificationPriorityValues::declareValues()
 }
 
 LLNotificationForm::FormElementBase::FormElementBase()
-:	name("name")
+:	name("name"),
+	enabled("enabled", true)
 {}
 
 LLNotificationForm::FormIgnore::FormIgnore()
@@ -210,6 +211,14 @@ LLNotificationForm::LLNotificationForm()
 {
 }
 
+LLNotificationForm::LLNotificationForm( const LLNotificationForm& other )
+{
+	mFormData 	   = other.mFormData;
+	mIgnore 	   = other.mIgnore;
+	mIgnoreMsg 	   = other.mIgnoreMsg;
+	mIgnoreSetting = other.mIgnoreSetting;
+	mInvertSetting = other.mInvertSetting;
+}
 
 LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p) 
 :	mIgnore(IGNORE_NO),
@@ -300,7 +309,7 @@ LLSD LLNotificationForm::getElement(const std::string& element_name)
 }
 
 
-bool LLNotificationForm::hasElement(const std::string& element_name)
+bool LLNotificationForm::hasElement(const std::string& element_name) const
 {
 	for (LLSD::array_const_iterator it = mFormData.beginArray();
 		it != mFormData.endArray();
@@ -311,7 +320,36 @@ bool LLNotificationForm::hasElement(const std::string& element_name)
 	return false;
 }
 
-void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value)
+bool LLNotificationForm::getElementEnabled(const std::string& element_name) const
+{
+	for (LLSD::array_const_iterator it = mFormData.beginArray();
+		it != mFormData.endArray();
+		++it)
+	{
+		if ((*it)["name"].asString() == element_name)
+		{
+			return (*it)["enabled"].asBoolean();
+		}
+	}
+
+	return false;
+}
+
+void LLNotificationForm::setElementEnabled(const std::string& element_name, bool enabled)
+{
+	for (LLSD::array_iterator it = mFormData.beginArray();
+		it != mFormData.endArray();
+		++it)
+	{
+		if ((*it)["name"].asString() == element_name)
+		{
+			(*it)["enabled"] = enabled;
+		}
+	}
+}
+
+
+void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value, bool enabled)
 {
 	LLSD element;
 	element["type"] = type;
@@ -319,6 +357,7 @@ void LLNotificationForm::addElement(const std::string& type, const std::string&
 	element["text"] = name;
 	element["value"] = value;
 	element["index"] = mFormData.size();
+	element["enabled"] = enabled;
 	mFormData.append(element);
 }
 
@@ -412,7 +451,8 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par
 	mPersist(p.persist),
 	mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()),
 	mLogToChat(p.log_to_chat),
-	mLogToIM(p.log_to_im)
+	mLogToIM(p.log_to_im),
+	mShowToast(p.show_toast)
 {
 	if (p.sound.isProvided()
 		&& LLUI::sSettingGroups["config"]->controlExists(p.sound))
@@ -571,7 +611,6 @@ void LLNotification::updateFrom(LLNotificationPtr other)
 	mRespondedTo = other->mRespondedTo;
 	mResponse = other->mResponse;
 	mTemporaryResponder = other->mTemporaryResponder;
-	mIsReusable = other->isReusable();
 
 	update();
 }
@@ -670,7 +709,7 @@ void LLNotification::respond(const LLSD& response)
 		return;
 	}
 
-	if (mTemporaryResponder && !isReusable())
+	if (mTemporaryResponder)
 	{
 		LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);
 		mResponseFunctorName = "";
@@ -899,6 +938,11 @@ bool LLNotification::canLogToIM() const
 	return mTemplatep->mLogToIM;
 }
 
+bool LLNotification::canShowToast() const
+{
+	return mTemplatep->mShowToast;
+}
+
 bool LLNotification::hasFormElements() const
 {
 	return mTemplatep->mForm->getNumElements() != 0;
@@ -909,6 +953,17 @@ LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const
 	return mTemplatep->mCombineBehavior;
 }
 
+void LLNotification::updateForm( const LLNotificationFormPtr& form )
+{
+	mForm = form;
+}
+
+void LLNotification::repost()
+{
+	mRespondedTo = false;
+	LLNotifications::instance().update(shared_from_this());
+}
+
 
 
 // =========================================================
@@ -1065,12 +1120,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
 		if (wasFound)
 		{
 			abortProcessing = mChanged(payload);
-			// do not delete the notification to make LLChatHistory::appendMessage add notification panel to IM window
-			if( ! pNotification->isReusable() )
-			{
-				mItems.erase(pNotification);
-				onDelete(pNotification);
-			}
+			mItems.erase(pNotification);
+			onDelete(pNotification);
 		}
 	}
 	return abortProcessing;
@@ -1207,7 +1258,15 @@ bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif)
 		if (pNotif != existing_notification 
 			&& pNotif->isEquivalentTo(existing_notification))
 		{
-			return false;
+			if (pNotif->getCombineBehavior() == LLNotification::CANCEL_OLD)
+			{
+				cancel(existing_notification);
+				return true;
+			}
+			else
+			{
+				return false;
+			}
 		}
 	}
 
@@ -1247,26 +1306,35 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload)
 		return false;
 	}
 
-	if (pNotif->getCombineBehavior() == LLNotification::USE_NEWEST)
-	{
-	// Update the existing unique notification with the data from this particular instance...
-	// This guarantees that duplicate notifications will be collapsed to the one
-	// most recently triggered
-	for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
-		existing_it != mUniqueNotifications.end();
-		++existing_it)
+	switch(pNotif->getCombineBehavior())
 	{
-		LLNotificationPtr existing_notification = existing_it->second;
-		if (pNotif != existing_notification 
-			&& pNotif->isEquivalentTo(existing_notification))
+	case  LLNotification::REPLACE_WITH_NEW:
+		// Update the existing unique notification with the data from this particular instance...
+		// This guarantees that duplicate notifications will be collapsed to the one
+		// most recently triggered
+		for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
+			existing_it != mUniqueNotifications.end();
+			++existing_it)
 		{
-			// copy notification instance data over to oldest instance
-			// of this unique notification and update it
-			existing_notification->updateFrom(pNotif);
-			// then delete the new one
-			cancel(pNotif);
+			LLNotificationPtr existing_notification = existing_it->second;
+			if (pNotif != existing_notification 
+				&& pNotif->isEquivalentTo(existing_notification))
+			{
+				// copy notification instance data over to oldest instance
+				// of this unique notification and update it
+				existing_notification->updateFrom(pNotif);
+				// then delete the new one
+				cancel(pNotif);
+			}
 		}
-	}
+		break;
+	case LLNotification::KEEP_OLD:
+		break;
+	case LLNotification::CANCEL_OLD:
+		// already handled by filter logic
+		break;
+	default:
+		break;
 	}
 
 	return false;
@@ -1594,12 +1662,11 @@ void LLNotifications::cancel(LLNotificationPtr pNotif)
 	if (pNotif == NULL || pNotif->isCancelled()) return;
 
 	LLNotificationSet::iterator it=mItems.find(pNotif);
-	if (it == mItems.end())
+	if (it != mItems.end())
 	{
-		llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl;
+		pNotif->cancel();
+		updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);
 	}
-	pNotif->cancel();
-	updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);
 }
 
 void LLNotifications::cancelByName(const std::string& name)
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 21a4318aabd780e0b970a0aee901f8628586fcff..e9449eae696d7bba8ee4fa5a9eef0a9f89c7bcfc 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -165,6 +165,7 @@ class LLNotificationForm
 	struct FormElementBase : public LLInitParam::Block<FormElementBase>
 	{
 		Optional<std::string>	name;
+		Optional<bool>			enabled;
 
 		FormElementBase();
 	};
@@ -234,16 +235,20 @@ class LLNotificationForm
 	} EIgnoreType;
 
 	LLNotificationForm();
+	LLNotificationForm(const LLNotificationForm&);
 	LLNotificationForm(const LLSD& sd);
 	LLNotificationForm(const std::string& name, const Params& p);
 
+	void fromLLSD(const LLSD& sd);
 	LLSD asLLSD() const;
 
 	S32 getNumElements() { return mFormData.size(); }
 	LLSD getElement(S32 index) { return mFormData.get(index); }
 	LLSD getElement(const std::string& element_name);
-	bool hasElement(const std::string& element_name);
-	void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD());
+	bool hasElement(const std::string& element_name) const;
+	bool getElementEnabled(const std::string& element_name) const;
+	void setElementEnabled(const std::string& element_name, bool enabled);
+	void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true);
 	void formatElements(const LLSD& substitutions);
 	// appends form elements from another form serialized as LLSD
 	void append(const LLSD& sub_form);
@@ -450,6 +455,11 @@ friend class LLNotifications;
 	// ["responseFunctor"] = name of registered functor that handles responses to notification;
 	LLSD asLLSD();
 
+	const LLNotificationFormPtr getForm();
+	void updateForm(const LLNotificationFormPtr& form);
+
+	void repost();
+
 	void respond(const LLSD& sd);
 	void respondWithDefault();
 
@@ -517,16 +527,18 @@ friend class LLNotifications;
     S32 getURLOpenExternally() const;
 	bool canLogToChat() const;
 	bool canLogToIM() const;
+	bool canShowToast() const;
 	bool hasFormElements() const;
 
 	typedef enum e_combine_behavior
 	{
-		USE_NEWEST,
-		USE_OLDEST
+		REPLACE_WITH_NEW,
+		KEEP_OLD,
+		CANCEL_OLD
+
 	} ECombineBehavior;
 	
 	ECombineBehavior getCombineBehavior() const;
-	const LLNotificationFormPtr getForm();
 
 	const LLDate getExpiration() const
 	{
@@ -545,8 +557,6 @@ friend class LLNotifications;
 
 	bool isReusable() { return mIsReusable; }
 
-	void setReusable(bool reusable) { mIsReusable = reusable; }
-	
 	// comparing two notifications normally means comparing them by UUID (so we can look them
 	// up quickly this way)
 	bool operator<(const LLNotification& rhs) const
diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h
index f7d08ae1f4c1bbe6a85c2e8b3f13e71bfcb303d3..ca9c4294c1b57a3f5701f528c1435133d68adde3 100644
--- a/indra/llui/llnotificationtemplate.h
+++ b/indra/llui/llnotificationtemplate.h
@@ -66,8 +66,9 @@ struct LLNotificationTemplate
 	{
 		static void declareValues()
 		{
-			declare("newest", LLNotification::USE_NEWEST);
-			declare("oldest", LLNotification::USE_OLDEST);
+			declare("replace_with_new", LLNotification::REPLACE_WITH_NEW);
+			declare("keep_old", LLNotification::KEEP_OLD);
+			declare("cancel_old", LLNotification::CANCEL_OLD);
 		}
 	};
 
@@ -109,7 +110,7 @@ struct LLNotificationTemplate
 
 		UniquenessConstraint()
 		:	contexts("context"),
-			combine("combine", LLNotification::USE_NEWEST),
+			combine("combine", LLNotification::REPLACE_WITH_NEW),
 			dummy_val("")
 		{}
 	};
@@ -185,6 +186,7 @@ struct LLNotificationTemplate
 		Mandatory<std::string>			name;
 		Optional<bool>					persist,
 										log_to_im,
+										show_toast,
 										log_to_chat;
 		Optional<std::string>			functor,
 										icon,
@@ -206,6 +208,7 @@ struct LLNotificationTemplate
 		:	name("name"),
 			persist("persist", false),
 			log_to_im("log_to_im", false),
+			show_toast("show_toast", true),
 			log_to_chat("log_to_chat", true),
 			functor("functor"),
 			icon("icon"),
@@ -313,6 +316,7 @@ struct LLNotificationTemplate
 	// inject these notifications into chat/IM streams
 	bool mLogToChat;
 	bool mLogToIM;
+	bool mShowToast;
 };
 
 #endif //LL_LLNOTIFICATION_TEMPLATE_H
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index ac14ec2cc082a240cbba4044336fb2291f7a2386..aa626a9a30073ee8c5eaee083ef4423dad93f13e 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -1024,7 +1024,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri
 
 	LLSD payload;
 	payload["from_id"] = target_id;
-	payload["SUPPRESS_TOAST"] = true;
 	LLNotificationsUtil::add("FriendshipOffered", args, payload);
 }
 
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 0d55c4429af2e38700f3e567f8b24bc849a6ee14..60d60abd45d9408af62c1988fc377eaa2a0bc4c2 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -54,6 +54,7 @@
 #include "llresmgr.h"
 #include "llslurl.h"
 #include "llimview.h"
+#include "lltrans.h"
 #include "llviewercontrol.h"
 #include "llviewernetwork.h"
 #include "llviewerobjectlist.h"
@@ -723,12 +724,13 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,
 	// Use display name only because this user is your friend
 	LLSD args;
 	args["NAME"] = av_name.mDisplayName;
+	args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus");
 
 	LLNotificationPtr notification;
 	if (online)
 	{
 		notification =
-			LLNotificationsUtil::add("FriendOnline",
+			LLNotificationsUtil::add("FriendOnlineOffline",
 									 args,
 									 payload.with("respond_on_mousedown", TRUE),
 									 boost::bind(&LLAvatarActions::startIM, agent_id));
@@ -736,7 +738,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,
 	else
 	{
 		notification =
-			LLNotificationsUtil::add("FriendOffline", args, payload);
+			LLNotificationsUtil::add("FriendOnlineOffline", args, payload);
 	}
 
 	// If there's an open IM session with this agent, send a notification there too.
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 5bdfb5adbcebacb2dde482da237396e3a46dda53..3da868945be07e37c48a19dfe9eb3457b1e832b1 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -877,35 +877,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		if (notification != NULL)
 		{
 			LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel(
-					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history);
-			//we can't set follows in xml since it broke toasts behavior
-			notify_box->setFollowsLeft();
-			notify_box->setFollowsRight();
-			notify_box->setFollowsTop();
-
-			ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList();
-			S32 offset = 0;
-			// Children were added by addChild() which uses push_front to insert them into list,
-			// so to get buttons in correct order reverse iterator is used (EXT-5906) 
-			for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++)
-			{
-				LLButton * button = dynamic_cast<LLButton*> (*it);
-				if (button != NULL)
-				{
-					button->setOrigin( offset,
-							button->getRect().mBottom);
-					button->setLeftHPad(2 * HPAD);
-					button->setRightHPad(2 * HPAD);
-					// set zero width before perform autoResize()
-					button->setRect(LLRect(button->getRect().mLeft,
-							button->getRect().mTop, button->getRect().mLeft,
-							button->getRect().mBottom));
-					button->setAutoResize(true);
-					button->autoResize();
-					offset += HPAD + button->getRect().getWidth();
-					button->setFollowsNone();
-				}
-			}
+					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor);
 
 			//Prepare the rect for the view
 			LLRect target_rect = mEditor->getDocumentView()->getRect();
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index 9a84280f258f7be30c1763d1882c88943cdec6ae..7477fbd6568048c13326c39326c5863b2e465815 100644
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -372,7 +372,6 @@ void LLNearbyChatToastPanel::draw()
 		}
 		mIsDirty = false;
 	}
-	LLToastPanelBase::draw();
 }
 
 
diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h
index 1d700dcedefd0abbfd52c421852e6b2e9f9d1485..89b0c4f37a6ba88a00de85f7d6eb76dba91d6fe7 100644
--- a/indra/newview/llchatitemscontainerctrl.h
+++ b/indra/newview/llchatitemscontainerctrl.h
@@ -40,7 +40,7 @@ typedef enum e_show_item_header
 	CHATITEMHEADER_SHOW_BOTH
 } EShowItemHeader;
 
-class LLNearbyChatToastPanel: public LLToastPanelBase
+class LLNearbyChatToastPanel : public LLPanel
 {
 protected:
         LLNearbyChatToastPanel()
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index f67464078b20d085aa6331608f69d1af2a8d6f32..724ae3c25e956bda436ce71f4956cb42e7971980 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -56,6 +56,7 @@
 #include "llrootview.h"
 #include "llspeakers.h"
 #include "llviewerchat.h"
+#include "llnotificationmanager.h"
 
 
 LLIMFloater::LLIMFloater(const LLUUID& session_id)
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index 4d9db01e0d6e2daae1d179de1b91dce18be55604..f26cc850197d93281d187d322e15f7bbe42479e1 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -1,6 +1,6 @@
 /** 
  * @file LLNearbyChatHandler.cpp
- * @brief Nearby chat notification managment
+ * @brief Nearby chat chat managment
  *
  * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -47,15 +47,17 @@
 //add LLNearbyChatHandler to LLNotificationsUI namespace
 using namespace LLNotificationsUI;
 
-//-----------------------------------------------------------------------------------------------
-//LLNearbyChatScreenChannel
-//-----------------------------------------------------------------------------------------------	
-LLToastPanelBase* createToastPanel()
+static LLNearbyChatToastPanel* createToastPanel()
 {
 	LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance();
 	return item;
 }
 
+
+//-----------------------------------------------------------------------------------------------
+//LLNearbyChatScreenChannel
+//-----------------------------------------------------------------------------------------------	
+
 class LLNearbyChatScreenChannel: public LLScreenChannelBase
 {
 	LOG_CLASS(LLNearbyChatScreenChannel);
@@ -81,10 +83,10 @@ class LLNearbyChatScreenChannel: public LLScreenChannelBase
 		}
 	}
 
-	void addNotification	(LLSD& notification);
+	void addChat	(LLSD& chat);
 	void arrangeToasts		();
 	
-	typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t;
+	typedef boost::function<LLNearbyChatToastPanel* (void )> create_toast_panel_callback_t;
 	void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;}
 
 	void onToastDestroyed	(LLToast* toast, bool app_quitting);
@@ -152,6 +154,8 @@ class LLNearbyChatScreenChannel: public LLScreenChannelBase
 	bool	mChannelRect;
 };
 
+
+
 //-----------------------------------------------------------------------------------------------
 // LLNearbyChatToast
 //-----------------------------------------------------------------------------------------------
@@ -255,7 +259,7 @@ void LLNearbyChatScreenChannel::updateToastFadingTime()
 
 bool	LLNearbyChatScreenChannel::createPoolToast()
 {
-	LLToastPanelBase* panel= m_create_toast_panel_callback_t();
+	LLNearbyChatToastPanel* panel= m_create_toast_panel_callback_t();
 	if(!panel)
 		return false;
 	
@@ -277,7 +281,7 @@ bool	LLNearbyChatScreenChannel::createPoolToast()
 	return true;
 }
 
-void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
+void LLNearbyChatScreenChannel::addChat(LLSD& chat)
 {
 	//look in pool. if there is any message
 	if(mStopProcessing)
@@ -289,8 +293,8 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
 
 	if(m_active_toasts.size())
 	{
-		LLUUID fromID = notification["from_id"].asUUID();		// agent id or object id
-		std::string from = notification["from"].asString();
+		LLUUID fromID = chat["from_id"].asUUID();		// agent id or object id
+		std::string from = chat["from"].asString();
 		LLToast* toast = m_active_toasts[0].get();
 		if (toast)
 		{
@@ -298,7 +302,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
   
 			if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText())
 			{
-				panel->addMessage(notification);
+				panel->addMessage(chat);
 				toast->reshapeToPanel();
 				toast->startTimer();
 	  
@@ -316,11 +320,11 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
 		LL_DEBUGS("NearbyChat") << "Empty pool" << llendl;
 		if(!createPoolToast())//created toast will go to pool. so next call will find it
 			return;
-		addNotification(notification);
+		addChat(chat);
 		return;
 	}
 
-	int chat_type = notification["chat_type"].asInteger();
+	int chat_type = chat["chat_type"].asInteger();
 	
 	if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG))
 	{
@@ -339,10 +343,10 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
 	m_toast_pool.pop_back();
 
 
-	LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel());
+	LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());
 	if(!panel)
 		return;
-	panel->init(notification);
+	panel->init(chat);
 
 	toast->reshapeToPanel();
 	toast->startTimer();
@@ -488,23 +492,23 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,
 	LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat");
 
 	// Build notification data 
-	LLSD notification;
-	notification["message"] = chat_msg.mText;
-	notification["from"] = chat_msg.mFromName;
-	notification["from_id"] = chat_msg.mFromID;
-	notification["time"] = chat_msg.mTime;
-	notification["source"] = (S32)chat_msg.mSourceType;
-	notification["chat_type"] = (S32)chat_msg.mChatType;
-	notification["chat_style"] = (S32)chat_msg.mChatStyle;
+	LLSD chat;
+	chat["message"] = chat_msg.mText;
+	chat["from"] = chat_msg.mFromName;
+	chat["from_id"] = chat_msg.mFromID;
+	chat["time"] = chat_msg.mTime;
+	chat["source"] = (S32)chat_msg.mSourceType;
+	chat["chat_type"] = (S32)chat_msg.mChatType;
+	chat["chat_style"] = (S32)chat_msg.mChatStyle;
 	// Pass sender info so that it can be rendered properly (STORM-1021).
-	notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);
+	chat["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);
 
 	if (chat_msg.mChatType == CHAT_TYPE_DIRECT &&
 		chat_msg.mText.length() > 0 &&
 		chat_msg.mText[0] == '@')
 	{
 		// Send event on to LLEventStream and exit
-		sChatWatcher->post(notification);
+		sChatWatcher->post(chat);
 		return;
 	}
 
@@ -551,7 +555,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,
 	}
 
 	// Send event on to LLEventStream
-	sChatWatcher->post(notification);
+	sChatWatcher->post(chat);
 
 
 	if( !chat_bar->isMinimized()
@@ -602,16 +606,16 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,
 		// Add a nearby chat toast.
 		LLUUID id;
 		id.generate();
-		notification["id"] = id;
+		chat["id"] = id;
 		std::string r_color_name = "White";
 		F32 r_color_alpha = 1.0f; 
 		LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha);
 		
-		notification["text_color"] = r_color_name;
-		notification["color_alpha"] = r_color_alpha;
-		notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ;
-		notification["message"] = toast_msg;
-		channel->addNotification(notification);	
+		chat["text_color"] = r_color_name;
+		chat["color_alpha"] = r_color_alpha;
+		chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ;
+		chat["message"] = toast_msg;
+		channel->addChat(chat);	
 	}
 }
 
diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp
index 6946b78cbf628c66d3fd38c6e0746376ebb17084..18cd94e6855ff516cf743d65355db1dbc13790cf 100644
--- a/indra/newview/llnotificationgrouphandler.cpp
+++ b/indra/newview/llnotificationgrouphandler.cpp
@@ -44,7 +44,6 @@ LLGroupHandler::LLGroupHandler()
 	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();
 	if(channel)
 	{
-		channel->addOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1));
 		mChannel = channel->getHandle();
 	}
 }
@@ -94,16 +93,6 @@ bool LLGroupHandler::processNotification(const LLNotificationPtr& notification)
 	return false;
 }
 
-//--------------------------------------------------------------------------
-void LLGroupHandler::onRejectToast(LLUUID& id)
-{
-	LLNotificationPtr notification = LLNotifications::instance().find(id);
-
-	if (notification && mItems.find(notification) != mItems.end())
-	{
-		LLNotifications::instance().cancel(notification);
-	}
-}
 
 //--------------------------------------------------------------------------
 
diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
index 83d228e79954e2d5cd6e960817398076992f19dd..4d54bb78fc53a6778424482ef71534d038d012ad 100644
--- a/indra/newview/llnotificationhandler.h
+++ b/indra/newview/llnotificationhandler.h
@@ -95,16 +95,9 @@ class LLSysHandler : public LLEventHandler, public LLNotificationChannel
 	// base interface functions
 	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); }
 	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); }
-	/*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->killToastByNotificationID(p->getID());}
+	/*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());}
 
 	virtual bool processNotification(const LLNotificationPtr& notify)=0;
-
-protected :
-	static void init();
-	void removeExclusiveNotifications(const LLNotificationPtr& notif);
-
-	typedef std::list< std::set<std::string> > exclusive_notif_sets;
-	static exclusive_notif_sets sExclusiveNotificationGroups;
 };
 
 /**
@@ -148,7 +141,6 @@ class LLTipHandler : public LLSysHandler
 	/*virtual*/ bool processNotification(const LLNotificationPtr& p);
 
 protected:
-	/*virtual*/ void onRejectToast(const LLUUID& id);
 	/*virtual*/ void initChannel();
 };
 
@@ -169,9 +161,6 @@ class LLScriptHandler : public LLSysHandler
 protected:
 	/*virtual*/ void onDeleteToast(LLToast* toast);
 	/*virtual*/ void initChannel();
-
-	// own handlers
-	void onRejectToast(LLUUID& id);
 };
 
 
@@ -190,9 +179,6 @@ class LLGroupHandler : public LLSysHandler
 
 protected:
 	virtual void initChannel();
-
-	// own handlers
-	void onRejectToast(LLUUID& id);
 };
 
 /**
@@ -225,15 +211,12 @@ class LLOfferHandler : public LLSysHandler
 	virtual ~LLOfferHandler();
 
 	// base interface functions
-	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); }
+	/*virtual*/ void onChange(LLNotificationPtr p);
 	/*virtual*/ void onDelete(LLNotificationPtr notification);
 	/*virtual*/ bool processNotification(const LLNotificationPtr& p);
 
 protected:
 	/*virtual*/ void initChannel();
-
-	// own handlers
-	void onRejectToast(LLUUID& id);
 };
 
 /**
diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp
index 1494ac6b5ccc24ff5032489f6118f744ff81342e..cba22b233b78ade6109e77e0884201d92662beb9 100644
--- a/indra/newview/llnotificationhandlerutil.cpp
+++ b/indra/newview/llnotificationhandlerutil.cpp
@@ -41,75 +41,9 @@
 
 using namespace LLNotificationsUI;
 
-// static
-std::list< std::set<std::string> > LLSysHandler::sExclusiveNotificationGroups;
-
-// static
-void LLSysHandler::init()
-{
-	std::set<std::string> online_offline_group;
-	online_offline_group.insert("FriendOnline");
-	online_offline_group.insert("FriendOffline");
-
-	sExclusiveNotificationGroups.push_back(online_offline_group);
-}
-
 LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type)
 :	LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type))
-{
-	if(sExclusiveNotificationGroups.empty())
-	{
-		init();
-	}
-}
-
-void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif)
-{
-	LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel.get());
-	if (channel == NULL)
-	{
-		return;
-	}
-
-	class ExclusiveMatcher: public LLScreenChannel::Matcher
-	{
-	public:
-		ExclusiveMatcher(const std::set<std::string>& excl_group,
-				const std::string& from_name) :
-			mExclGroup(excl_group), mFromName(from_name)
-		{
-		}
-		bool matches(const LLNotificationPtr notification) const
-		{
-			for (std::set<std::string>::const_iterator it = mExclGroup.begin(); it
-					!= mExclGroup.end(); it++)
-			{
-				std::string from_name = LLHandlerUtil::getSubstitutionName(notification);
-				if (notification->getName() == *it && from_name == mFromName)
-				{
-					return true;
-				}
-			}
-			return false;
-		}
-	private:
-		const std::set<std::string>& mExclGroup;
-		const std::string& mFromName;
-	};
-
-
-	for (exclusive_notif_sets::iterator it = sExclusiveNotificationGroups.begin(); it
-			!= sExclusiveNotificationGroups.end(); it++)
-	{
-		std::set<std::string> group = *it;
-		std::set<std::string>::iterator g_it = group.find(notif->getName());
-		if (g_it != group.end())
-		{
-			channel->killMatchedToasts(ExclusiveMatcher(group,
-					LLHandlerUtil::getSubstitutionName(notif)));
-		}
-	}
-}
+{}
 
 // static
 bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification)
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
index 2112b0d35eef9ae60bfb396a9aafcd6868744254..6e641575fa913ffe11e53fbfe907db4fd14236bc 100644
--- a/indra/newview/llnotificationofferhandler.cpp
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -48,7 +48,6 @@ LLOfferHandler::LLOfferHandler()
 	if(channel)
 	{
 		channel->setControlHovering(true);
-		channel->addOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1));
 		mChannel = channel->getHandle();
 	}
 }
@@ -81,92 +80,95 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification)
 	}
 
 
-		if( notification->getPayload().has("give_inventory_notification")
+	if( notification->getPayload().has("give_inventory_notification")
 		&& notification->getPayload()["give_inventory_notification"].asBoolean() == false)
-		{
-			// This is an original inventory offer, so add a script floater
-			LLScriptFloaterManager::instance().onAddNotification(notification->getID());
-		}
-		else
-		{
+	{
+		// This is an original inventory offer, so add a script floater
+		LLScriptFloaterManager::instance().onAddNotification(notification->getID());
+	}
+	else
+	{
 		bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements();
 
-		notification->setReusable(add_notif_to_im);
-
-			LLUUID session_id;
 		if (add_notif_to_im)
-			{
-				const std::string name = LLHandlerUtil::getSubstitutionName(notification);
+		{
+			const std::string name = LLHandlerUtil::getSubstitutionName(notification);
 
-				LLUUID from_id = notification->getPayload()["from_id"];
+			LLUUID from_id = notification->getPayload()["from_id"];
 
-				session_id = LLHandlerUtil::spawnIMSession(name, from_id);
-				LLHandlerUtil::addNotifPanelToIM(notification);
-			}
+			LLHandlerUtil::spawnIMSession(name, from_id);
+			LLHandlerUtil::addNotifPanelToIM(notification);
+		}
 
-			if (notification->getPayload().has("SUPPRESS_TOAST")
-						&& notification->getPayload()["SUPPRESS_TOAST"])
-			{
-				LLNotificationsUtil::cancel(notification);
-			}
+		if (!notification->canShowToast())
+		{
+			LLNotificationsUtil::cancel(notification);
+		}
 		else if(!notification->canLogToIM() || !LLHandlerUtil::isIMFloaterOpened(notification))
-			{
-				LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
-				// don't close notification on panel destroy since it will be used by IM floater
-			notify_box->setCloseNotificationOnDestroy(!add_notif_to_im);
-				LLToast::Params p;
-				p.notif_id = notification->getID();
-				p.notification = notification;
-				p.panel = notify_box;
-				// we not save offer notifications to the syswell floater that should be added to the IM floater
+		{
+			LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
+			LLToast::Params p;
+			p.notif_id = notification->getID();
+			p.notification = notification;
+			p.panel = notify_box;
+			// we not save offer notifications to the syswell floater that should be added to the IM floater
 			p.can_be_stored = !add_notif_to_im;
 
-				LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get());
-				if(channel)
-					channel->addToast(p);
-			}
+			LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get());
+			if(channel)
+				channel->addToast(p);
+		}
 
 		if (notification->canLogToIM())
-			{
-				// log only to file if notif panel can be embedded to IM and IM is opened
+		{
+			// log only to file if notif panel can be embedded to IM and IM is opened
 			bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification);
 			LLHandlerUtil::logToIMP2P(notification, file_only);
-				}
-				}
+		}
+	}
 
 	return false;
-			}
+}
 
-/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification)
+/*virtual*/ void LLOfferHandler::onChange(LLNotificationPtr p)
+{
+	LLToastNotifyPanel* panelp = LLToastNotifyPanel::getInstance(p->getID());
+	if (panelp)
 	{
-		if( notification->getPayload().has("give_inventory_notification")
-			&& !notification->getPayload()["give_inventory_notification"] )
+		//
+		// HACK: if we're dealing with a notification embedded in IM, update it
+		// otherwise remove its toast
+		//
+		if (dynamic_cast<LLIMToastNotifyPanel*>(panelp))
 		{
-			// Remove original inventory offer script floater
-			LLScriptFloaterManager::instance().onRemoveNotification(notification->getID());
+			panelp->updateNotification();
 		}
 		else
 		{
-		if (notification->canLogToIM() 
-			&& notification->hasFormElements()
-					&& !LLHandlerUtil::isIMFloaterOpened(notification))
-			{
-				LLHandlerUtil::decIMMesageCounter(notification);
-			}
-			mChannel.get()->killToastByNotificationID(notification->getID());
+			// if notification has changed, hide it
+			mChannel.get()->removeToastByNotificationID(p->getID());
 		}
 	}
+}
 
-//--------------------------------------------------------------------------
-void LLOfferHandler::onRejectToast(LLUUID& id)
-{
-	LLNotificationPtr notification = LLNotifications::instance().find(id);
 
-	if (notification
-		&& mItems.find(notification) != mItems.end()
-					// don't delete notification since it may be used by IM floater
-		&& (!notification->canLogToIM() || !notification->hasFormElements()))
+/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification)
+{
+	if( notification->getPayload().has("give_inventory_notification")
+		&& !notification->getPayload()["give_inventory_notification"] )
+	{
+		// Remove original inventory offer script floater
+		LLScriptFloaterManager::instance().onRemoveNotification(notification->getID());
+	}
+	else
 	{
-		LLNotifications::instance().cancel(notification);
+		if (notification->canLogToIM() 
+			&& notification->hasFormElements()
+			&& !LLHandlerUtil::isIMFloaterOpened(notification))
+		{
+			LLHandlerUtil::decIMMesageCounter(notification);
+		}
+		mChannel.get()->removeToastByNotificationID(notification->getID());
 	}
 }
+
diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp
index 8472f9b2aea6c6c8835cde68d7fecdae1aaa8e6c..9f7d0cc2f59d8ddedd1c0a252c5edf79a29161b5 100644
--- a/indra/newview/llnotificationscripthandler.cpp
+++ b/indra/newview/llnotificationscripthandler.cpp
@@ -46,7 +46,6 @@ LLScriptHandler::LLScriptHandler()
 	if(channel)
 	{
 		channel->setControlHovering(true);
-		channel->addOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1));
 		mChannel = channel->getHandle();
 	}
 }
@@ -116,7 +115,7 @@ void LLScriptHandler::onDelete( LLNotificationPtr notification )
 		}
 		else
 		{
-			mChannel.get()->killToastByNotificationID(notification->getID());
+			mChannel.get()->removeToastByNotificationID(notification->getID());
 		}
 	}
 
@@ -135,19 +134,6 @@ void LLScriptHandler::onDeleteToast(LLToast* toast)
 	}
 }
 
-//--------------------------------------------------------------------------
-void LLScriptHandler::onRejectToast(LLUUID& id)
-{
-	LLNotificationPtr notification = LLNotifications::instance().find(id);
-
-	if (notification && mItems.find(notification) != mItems.end())
-	{
-		LLNotifications::instance().cancel(notification);
-	}
-}
-
-//--------------------------------------------------------------------------
-
 
 
 
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index 3588721849b361fd463bc9144caafef109c73a58..a1d5db2e27c09bf87e697f491f35f641425d7f34 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -48,7 +48,6 @@ LLTipHandler::LLTipHandler()
 	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();
 	if(channel)
 	{
-		channel->addOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1));
 		mChannel = channel->getHandle();
 	}
 }
@@ -127,22 +126,8 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification)
 	p.is_tip = true;
 	p.can_be_stored = false;
 		
-	removeExclusiveNotifications(notification);
-
 	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get());
 	if(channel)
 		channel->addToast(p);
 	return false;
 }
-
-//--------------------------------------------------------------------------
-
-void LLTipHandler::onRejectToast(const LLUUID& id)
-{
-	LLNotificationPtr notification = LLNotifications::instance().find(id);
-
-	if (notification && mItems.find(notification) != mItems.end())
-	{
-		LLNotifications::instance().cancel(notification);
-	}
-}
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 003b53b28c309576b053572009bd188139c53554..839ca0f9c528567bb2543d36722390f7aa784817 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -265,7 +265,14 @@ void LLScreenChannel::addToast(const LLToast::Params& p)
 
 	if(!show_toast && !store_toast)
 	{
-		mRejectToastSignal(p.notif_id);
+		LLNotificationPtr notification = LLNotifications::instance().find(p.notif_id);
+
+		if (notification &&
+			(!notification->canLogToIM() || !notification->hasFormElements()))
+		{
+			// only cancel notification if it isn't being used in IM session
+			LLNotifications::instance().cancel(notification);
+		}
 		return;
 	}
 
@@ -431,35 +438,13 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
 	redrawToasts();
 }
 
-//--------------------------------------------------------------------------
-void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id)
-{
-	// *TODO: may be remove this function
-	std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
-
-	if( it == mStoredToastList.end() )
-		return;
-
-	const LLToast* toast = it->getToast();
-	if (toast)
-	{
-		mRejectToastSignal(toast->getNotificationID());
-	}
-
-	// Call find() once more, because the mStoredToastList could have been changed
-	// in mRejectToastSignal callback and the iterator could have become invalid.
-	it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
-	if (it != mStoredToastList.end())
-	{
-	mStoredToastList.erase(it);
-	}
-}
-
 //--------------------------------------------------------------------------
 void LLScreenChannel::killToastByNotificationID(LLUUID id)
 {
 	// searching among toasts on a screen
 	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id);
+	LLNotificationPtr notification = LLNotifications::instance().find(id);
+	if (!notification) return;
 	
 	if( it != mToastList.end())
 	{
@@ -472,42 +457,67 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)
 		//			the toast will be destroyed.
 		if(toast && toast->isNotificationValid())
 		{
-			mRejectToastSignal(toast->getNotificationID());
+			if (!notification->canLogToIM() || !notification->hasFormElements())
+			{
+				// only cancel notification if it isn't being used in IM session
+				LLNotifications::instance().cancel(notification);
+			}
 		}
 		else
 		{
-
-			deleteToast(toast);
-			mToastList.erase(it);
-			redrawToasts();
+			removeToastByNotificationID(id);
 		}
-		return;
 	}
-
-	// searching among stored toasts
-	it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
-
-	if( it != mStoredToastList.end() )
+	else
 	{
-		LLToast* toast = it->getToast();
-		if (toast)
+		// searching among stored toasts
+		it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
+
+		if( it != mStoredToastList.end() )
+		{
+			LLToast* toast = it->getToast();
+			if (toast)
+			{
+				if (!notification->canLogToIM() || !notification->hasFormElements())
+				{
+					// only cancel notification if it isn't being used in IM session
+					LLNotifications::instance().cancel(notification);
+				}
+				deleteToast(toast);
+			}
+		}
+	
+		// Call find() once more, because the mStoredToastList could have been changed
+		// via notification cancellation and the iterator could have become invalid.
+		it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
+		if (it != mStoredToastList.end())
 		{
-		// send signal to a listener to let him perform some action on toast rejecting
-		mRejectToastSignal(toast->getNotificationID());
-		deleteToast(toast);
+			mStoredToastList.erase(it);
+		}
 	}
 }
 
-	// Call find() once more, because the mStoredToastList could have been changed
-	// in mRejectToastSignal callback and the iterator could have become invalid.
-	it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
-	if (it != mStoredToastList.end())
+void LLScreenChannel::removeToastByNotificationID(LLUUID id)
+{
+	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id);
+	if( it != mToastList.end())
 	{
-		mStoredToastList.erase(it);
+		deleteToast(it->getToast());
+		mToastList.erase(it);
+		redrawToasts();
+	}
+	else
+	{
+		it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
+		if (it != mStoredToastList.end())
+		{
+			deleteToast(it->getToast());
+			mStoredToastList.erase(it);
+		}
 	}
-
 }
 
+
 void LLScreenChannel::killMatchedToasts(const Matcher& matcher)
 {
 	std::list<const LLToast*> to_delete = findToasts(matcher);
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index eaff61a0f41610cadd2e260568952f27a47288fc..e5f4807ab7ca5131599d47da28a3a4cce2e51a7f 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -84,6 +84,7 @@ class LLScreenChannelBase : public LLUICtrl
 	// kill or modify a toast by its ID
 	virtual void		killToastByNotificationID(LLUUID id) {};
 	virtual void		modifyToastNotificationByID(LLUUID id, LLSD data) {};
+	virtual void		removeToastByNotificationID(LLUUID id){};
 	
 	// hide all toasts from screen, but not remove them from a channel
 	virtual void		hideToastsFromScreen() {};
@@ -175,6 +176,7 @@ class LLScreenChannel : public LLScreenChannelBase
 	void		addToast(const LLToast::Params& p);
 	// kill or modify a toast by its ID
 	void		killToastByNotificationID(LLUUID id);
+	void		removeToastByNotificationID(LLUUID id);
 	void		killMatchedToasts(const Matcher& matcher);
 	void		modifyToastByNotificationID(LLUUID id, LLPanel* panel);
 	// hide all toasts from screen, but not remove them from a channel
@@ -195,8 +197,6 @@ class LLScreenChannel : public LLScreenChannelBase
 	void		loadStoredToastsToChannel();
 	// finds a toast among stored by its Notification ID and throws it on a screen to a channel
 	void		loadStoredToastByNotificationIDToChannel(LLUUID id);
-	// removes a toast from stored finding it by its Notification ID 
-	void		removeStoredToastByNotificationID(LLUUID id);
 	// removes from channel all toasts that belongs to the certain IM session 
 	void		removeToastsBySessionID(LLUUID id);
 	// remove all storable toasts from screen and store them
@@ -229,13 +229,9 @@ class LLScreenChannel : public LLScreenChannelBase
 	// signal on storing of faded toasts event
 	typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_toast_signal_t;
 	boost::signals2::connection addOnStoreToastCallback(store_toast_signal_t::slot_type cb) { return mOnStoreToast.connect(cb); }
-	// signal on rejecting of a toast event
-	typedef boost::signals2::signal<void (LLUUID id)> reject_toast_signal_t;
-	boost::signals2::connection addOnRejectToastCallback(reject_toast_signal_t::slot_type cb) { return mRejectToastSignal.connect(cb); }
 
 private:
 	store_toast_signal_t mOnStoreToast;	
-	reject_toast_signal_t mRejectToastSignal; 
 
 	class ToastElem
 	{
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index e1d99b1bcba9afd2abde97820bf5a13b841e6443..ea62f758f87a3967da7f388a82fc02fc0c696571 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -169,6 +169,7 @@ class LLToast : public LLModalDialog, public LLInstanceTracker<LLToast>
 	// get/set Toast's flags or states
 	// get information whether the notification corresponding to the toast is valid or not
 	bool isNotificationValid();
+
 	// get toast's Notification ID
 	const LLUUID getNotificationID() const { return mNotificationID;}
 	// get toast's Session ID
@@ -212,7 +213,7 @@ class LLToast : public LLModalDialog, public LLInstanceTracker<LLToast>
 
 	//LLRootHandle<LLToast>	mHandle;
 		
-	LLPanel* mWrapperPanel;
+	LLPanel*	 mWrapperPanel;
 
 	// timer counts a lifetime of a toast
 	std::auto_ptr<LLToastLifeTimer> mTimer;
@@ -220,8 +221,8 @@ class LLToast : public LLModalDialog, public LLInstanceTracker<LLToast>
 	F32			mToastLifetime; // in seconds
 	F32			mToastFadingTime; // in seconds
 	
-	LLPanel*		mPanel;
-	LLButton*		mHideBtn;
+	LLPanel*	mPanel;
+	LLButton*	mHideBtn;
 
 	LLColor4	mBgColor;
 	bool		mCanFade;
diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h
index a803387576c5076455537aa3a83555a76b8bcb04..279dd69bc71ad8e15fd730ce8e37b3600e39493b 100644
--- a/indra/newview/lltoastimpanel.h
+++ b/indra/newview/lltoastimpanel.h
@@ -41,11 +41,11 @@ class LLToastIMPanel: public LLToastPanel
 	struct Params
 	{
 		LLNotificationPtr	notification;
-		LLUUID				avatar_id;
-		LLUUID				session_id;
-		std::string			from;
-		std::string			time;
-		std::string			message;
+		LLUUID				avatar_id,
+							session_id;
+		std::string			from,
+							time,
+							message;
 
 		Params() {}
 	};
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index dc5cc88dc4f57c0a4be6c3f59d296eed6e3716be..77a5a5d17dd7994651d6de1c04aeb4dc746a1b68 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -45,6 +45,9 @@
 const S32 BOTTOM_PAD = VPAD * 3;
 const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding
 S32 BUTTON_WIDTH = 90;
+// *TODO: magic numbers(???) - copied from llnotify.cpp(250)
+const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; 
+
 
 //static
 const LLFontGL* LLToastNotifyPanel::sFont = NULL;
@@ -52,171 +55,24 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
 
 LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal;
 
-LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : 
-LLToastPanel(notification),
-mTextBox(NULL),
-mInfoPanel(NULL),
-mControlPanel(NULL),
-mNumOptions(0),
-mNumButtons(0),
-mAddedDefaultBtn(false),
-mCloseNotificationOnDestroy(true)
+LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) 
+:	LLToastPanel(notification),
+	LLInstanceTracker(notification->getID())
 {
-	buildFromFile( "panel_notification.xml");
-	if(rect != LLRect::null)
-	{
-		this->setShape(rect);
-	}		 
-	mInfoPanel = getChild<LLPanel>("info_panel");
-	mControlPanel = getChild<LLPanel>("control_panel");
-	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth");
-	// customize panel's attributes
-	// is it intended for displaying a tip?
-	mIsTip = notification->getType() == "notifytip";
-	// is it a script dialog?
-	mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup");
-	// is it a caution?
-	//
-	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the
-	// notify xml template specifies that it is a caution
-	// tip-style notification handle 'caution' differently -they display the tip in a different color
-	mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH;
+	init(rect, show_images);
 
-	// setup parameters
-	// get a notification message
-	mMessage = notification->getMessage();
-	// init font variables
-	if (!sFont)
-	{
-		sFont = LLFontGL::getFontSansSerif();
-		sFontSmall = LLFontGL::getFontSansSerifSmall();
-	}
-	// initialize
-	setFocusRoot(!mIsTip);
-	// get a form for the notification
-	LLNotificationFormPtr form(notification->getForm());
-	// get number of elements
-	mNumOptions = form->getNumElements();
 
-	// customize panel's outfit
-	// preliminary adjust panel's layout
-	//move to the end 
-	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form);
-
-	// adjust text options according to the notification type
-	// add a caution textbox at the top of a caution notification
-	if (mIsCaution && !mIsTip)
-	{
-		mTextBox = getChild<LLTextBox>("caution_text_box");
-	}
-	else
-	{
-		mTextBox = getChild<LLTextEditor>("text_editor_box"); 
-	}
-
-	// *TODO: magic numbers(???) - copied from llnotify.cpp(250)
-	const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; 
-
-	mTextBox->setMaxTextLength(MAX_LENGTH);
-	mTextBox->setVisible(TRUE);
-	mTextBox->setPlainText(!show_images);
-	mTextBox->setValue(notification->getMessage());
-
-	// add buttons for a script notification
-	if (mIsTip)
-	{
-		adjustPanelForTipNotice();
-	}
-	else
-	{
-		std::vector<index_button_pair_t> buttons;
-		buttons.reserve(mNumOptions);
-		S32 buttons_width = 0;
-		// create all buttons and accumulate they total width to reshape mControlPanel
-		for (S32 i = 0; i < mNumOptions; i++)
-		{
-			LLSD form_element = form->getElement(i);
-			if (form_element["type"].asString() != "button")
-			{
-				// not a button.
-				continue;
-			}
-			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN)
-			{
-				// a textbox pretending to be a button.
-				continue;
-			}
-			LLButton* new_button = createButton(form_element, TRUE);
-			buttons_width += new_button->getRect().getWidth();
-			S32 index = form_element["index"].asInteger();
-			buttons.push_back(index_button_pair_t(index,new_button));
-		}
-		if (buttons.empty())
-		{
-			addDefaultButton();
-		}
-		else
-		{
-			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel
-			S32 button_panel_height = mControlPanel->getRect().getHeight();
-			//try get an average h_pad to spread out buttons
-			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size()));
-			if(h_pad < 2*HPAD)
-			{
-				/*
-				 * Probably it is a scriptdialog toast
-				 * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons.
-				 * In last case set default h_pad to avoid heaping of buttons 
-				 */
-				S32 button_per_row = button_panel_width / BUTTON_WIDTH;
-				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row   
-				if(h_pad < 2*HPAD) // still not enough space between buttons ?
-				{
-					h_pad = 2*HPAD;
-				}
-			}
-			if (mIsScriptDialog)
-			{
-				// we are using default width for script buttons so we can determinate button_rows
-				//to get a number of rows we divide the required width of the buttons to button_panel_width
-				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width);
-				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width;
-				//reserve one row for the ignore_btn
-				button_rows++;
-				//calculate required panel height for scripdialog notification.
-				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD;
-			}
-			else
-			{
-				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width
-				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width);
-				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width);
-				//calculate required panel height 
-				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD;
-			}
-		
-			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed
-			adjustPanelForScriptNotice(button_panel_width, button_panel_height);
-			updateButtonsLayout(buttons, h_pad);
-			// save buttons for later use in disableButtons()
-			mButtons.assign(buttons.begin(), buttons.end());
-		}
-	}
-	// adjust panel's height to the text size
-	mInfoPanel->setFollowsAll();
-	snapToMessageHeight(mTextBox, MAX_LENGTH);
-
-	if(notification->isReusable())
-	{
-		mButtonClickConnection = sButtonClickSignal.connect(
-			boost::bind(&LLToastNotifyPanel::onToastPanelButtonClicked, this, _1, _2));
-
-		if(notification->isRespondedTo())
-		{
-			// User selected an option in toast, now disable required buttons in IM window
-			disableRespondedOptions(notification);
-		}
-	}
+	//if(notification->isRespondedTo())
+	//{
+	//	// User selected an option in toast, now disable required buttons in IM window
+	//	disableRespondedOptions(notification);
+	//}
+	//
+	//if(notification->isReusable())
+	//{
+	//	mButtonClickConnection = sButtonClickSignal.connect(
+	//		boost::bind(&LLToastNotifyPanel::disableRespondedOptions, this, notification));
+	//}
 }
 void LLToastNotifyPanel::addDefaultButton()
 {
@@ -235,7 +91,6 @@ void LLToastNotifyPanel::addDefaultButton()
 }
 LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option)
 {
-
 	InstanceAndS32* userdata = new InstanceAndS32;
 	userdata->mSelf = this;
 	userdata->mButtonName = is_option ? form_element["name"].asString() : "";
@@ -245,14 +100,15 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt
 	LLButton::Params p;
 	bool is_ignore_btn = form_element["index"].asInteger() == -1;
 	const LLFontGL* font = is_ignore_btn ? sFontSmall: sFont; // for ignore button in script dialog
-	p.name(form_element["name"].asString());
-	p.label(form_element["text"].asString());
-	p.font(font);
+	p.name = form_element["name"].asString();
+	p.label = form_element["text"].asString();
+	p.font = font;
 	p.rect.height = BTN_HEIGHT;
 	p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));
 	p.rect.width = BUTTON_WIDTH;
 	p.auto_resize = false;
 	p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
+	p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean();
 	if (mIsCaution)
 	{
 		p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor"));
@@ -287,14 +143,9 @@ LLToastNotifyPanel::~LLToastNotifyPanel()
 	mButtonClickConnection.disconnect();
 
 	std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer());
-	if (mCloseNotificationOnDestroy && LLNotificationsUtil::find(mNotification->getID()) != NULL)
+	if (mIsTip)
 	{
-		// let reusable notification be deleted
-		mNotification->setReusable(false);
-		if (!mNotification->isPersistent())
-		{
-			LLNotifications::getInstance()->cancel(mNotification);
-		}
+		LLNotifications::getInstance()->cancel(mNotification);
 	}
 }
 
@@ -393,103 +244,103 @@ void LLToastNotifyPanel::adjustPanelForTipNotice()
 	}
 }
 
-typedef std::set<std::string> button_name_set_t;
-typedef std::map<std::string, button_name_set_t> disable_button_map_t;
-
-disable_button_map_t initUserGiveItemDisableButtonMap()
-{
-	// see EXT-5905 for disable rules
-
-	disable_button_map_t disable_map;
-	button_name_set_t buttons;
-
-	buttons.insert("Show");
-	disable_map.insert(std::make_pair("Show", buttons));
-
-	buttons.insert("Discard");
-	disable_map.insert(std::make_pair("Discard", buttons));
-
-	buttons.insert("Mute");
-	disable_map.insert(std::make_pair("Mute", buttons));
-
-	return disable_map;
-}
-
-disable_button_map_t initTeleportOfferedDisableButtonMap()
-{
-	disable_button_map_t disable_map;
-	button_name_set_t buttons;
-
-	buttons.insert("Teleport");
-	buttons.insert("Cancel");
-
-	disable_map.insert(std::make_pair("Teleport", buttons));
-	disable_map.insert(std::make_pair("Cancel", buttons));
-
-	return disable_map;
-}
-
-disable_button_map_t initFriendshipOfferedDisableButtonMap()
-{
-	disable_button_map_t disable_map;
-	button_name_set_t buttons;
-
-	buttons.insert("Accept");
-	buttons.insert("Decline");
-
-	disable_map.insert(std::make_pair("Accept", buttons));
-	disable_map.insert(std::make_pair("Decline", buttons));
-
-	return disable_map;
-}
-
-button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name)
-{
-	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap();
-	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap();
-	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap();
-
-	disable_button_map_t::const_iterator it;
-	disable_button_map_t::const_iterator it_end;
-	disable_button_map_t search_map;
-
-	if("UserGiveItem" == notification_name)
-	{
-		search_map = user_give_item_disable_map;
-	}
-	else if("TeleportOffered" == notification_name)
-	{
-		search_map = teleport_offered_disable_map;
-	}
-	else if("OfferFriendship" == notification_name)
-	{
-		search_map = friendship_offered_disable_map;
-	}
-
-	it = search_map.find(button_name);
-	it_end = search_map.end();
-
-	if(it_end != it)
-	{
-		return it->second;
-	}
-	return button_name_set_t();
-}
-
-void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button)
-{
-	button_name_set_t buttons = getButtonDisableList(notification_name, selected_button);
-
-	std::vector<index_button_pair_t>::const_iterator it = mButtons.begin();
-	for ( ; it != mButtons.end(); it++)
-	{
-		LLButton* btn = it->second;
-		if(buttons.find(btn->getName()) != buttons.end())
-		{
-			btn->setEnabled(FALSE);
-		}
-	}
-}
+//typedef std::set<std::string> button_name_set_t;
+//typedef std::map<std::string, button_name_set_t> disable_button_map_t;
+//
+//disable_button_map_t initUserGiveItemDisableButtonMap()
+//{
+//	// see EXT-5905 for disable rules
+//
+//	disable_button_map_t disable_map;
+//	button_name_set_t buttons;
+//
+//	buttons.insert("Show");
+//	disable_map.insert(std::make_pair("Show", buttons));
+//
+//	buttons.insert("Discard");
+//	disable_map.insert(std::make_pair("Discard", buttons));
+//
+//	buttons.insert("Mute");
+//	disable_map.insert(std::make_pair("Mute", buttons));
+//
+//	return disable_map;
+//}
+//
+//disable_button_map_t initTeleportOfferedDisableButtonMap()
+//{
+//	disable_button_map_t disable_map;
+//	button_name_set_t buttons;
+//
+//	buttons.insert("Teleport");
+//	buttons.insert("Cancel");
+//
+//	disable_map.insert(std::make_pair("Teleport", buttons));
+//	disable_map.insert(std::make_pair("Cancel", buttons));
+//
+//	return disable_map;
+//}
+//
+//disable_button_map_t initFriendshipOfferedDisableButtonMap()
+//{
+//	disable_button_map_t disable_map;
+//	button_name_set_t buttons;
+//
+//	buttons.insert("Accept");
+//	buttons.insert("Decline");
+//
+//	disable_map.insert(std::make_pair("Accept", buttons));
+//	disable_map.insert(std::make_pair("Decline", buttons));
+//
+//	return disable_map;
+//}
+//
+//button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name)
+//{
+//	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap();
+//	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap();
+//	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap();
+//
+//	disable_button_map_t::const_iterator it;
+//	disable_button_map_t::const_iterator it_end;
+//	disable_button_map_t search_map;
+//
+//	if("UserGiveItem" == notification_name)
+//	{
+//		search_map = user_give_item_disable_map;
+//	}
+//	else if("TeleportOffered" == notification_name)
+//	{
+//		search_map = teleport_offered_disable_map;
+//	}
+//	else if("OfferFriendship" == notification_name)
+//	{
+//		search_map = friendship_offered_disable_map;
+//	}
+//
+//	it = search_map.find(button_name);
+//	it_end = search_map.end();
+//
+//	if(it_end != it)
+//	{
+//		return it->second;
+//	}
+//	return button_name_set_t();
+//}
+
+//void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button)
+//{
+	//button_name_set_t buttons = getButtonDisableList(notification_name, selected_button);
+
+	//std::vector<index_button_pair_t>::const_iterator it = mButtons.begin();
+	//for ( ; it != mButtons.end(); it++)
+	//{
+	//	LLButton* btn = it->second;
+	//	if(buttons.find(btn->getName()) != buttons.end())
+	//	{
+	//		btn->setEnabled(FALSE);
+	//	}
+	//}
+//}
 
 // static
 void LLToastNotifyPanel::onClickButton(void* data)
@@ -515,88 +366,263 @@ void LLToastNotifyPanel::onClickButton(void* data)
 		self->mNotification->setResponder(new_info);
 	}
 
+	// disable all buttons
+	self->mControlPanel->setEnabled(FALSE);
+
+	// this might repost notification with new form data/enabled buttons
 	self->mNotification->respond(response);
+}
 
-	if(is_reusable)
+void LLToastNotifyPanel::init( LLRect rect, bool show_images )
+{
+	deleteAllChildren();
+
+	mTextBox = NULL;
+	mInfoPanel = NULL;
+	mControlPanel = NULL;
+	mNumOptions = 0;
+	mNumButtons = 0;
+	mAddedDefaultBtn = false;
+
+	buildFromFile( "panel_notification.xml");
+	if(rect != LLRect::null)
 	{
-		sButtonClickSignal(self->mNotification->getID(), button_name);
+		this->setShape(rect);
+	}		 
+	mInfoPanel = getChild<LLPanel>("info_panel");
+	mInfoPanel->setFollowsAll();
+
+	mControlPanel = getChild<LLPanel>("control_panel");
+	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth");
+	// customize panel's attributes
+	// is it intended for displaying a tip?
+	mIsTip = mNotification->getType() == "notifytip";
+	// is it a script dialog?
+	mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup");
+	// is it a caution?
+	//
+	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the
+	// notify xml template specifies that it is a caution
+	// tip-style notification handle 'caution' differently -they display the tip in a different color
+	mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH;
+
+	// setup parameters
+	// get a notification message
+	mMessage = mNotification->getMessage();
+	// init font variables
+	if (!sFont)
+	{
+		sFont = LLFontGL::getFontSansSerif();
+		sFontSmall = LLFontGL::getFontSansSerifSmall();
+	}
+	// initialize
+	setFocusRoot(!mIsTip);
+	// get a form for the notification
+	LLNotificationFormPtr form(mNotification->getForm());
+	// get number of elements
+	mNumOptions = form->getNumElements();
+
+	// customize panel's outfit
+	// preliminary adjust panel's layout
+	//move to the end 
+	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form);
+
+	// adjust text options according to the notification type
+	// add a caution textbox at the top of a caution notification
+	if (mIsCaution && !mIsTip)
+	{
+		mTextBox = getChild<LLTextBox>("caution_text_box");
 	}
 	else
 	{
-		// disable all buttons
-		self->mControlPanel->setEnabled(FALSE);
+		mTextBox = getChild<LLTextEditor>("text_editor_box"); 
 	}
-}
 
-void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name)
-{
-	if(mNotification->getID() == notification_id)
+	mTextBox->setMaxTextLength(MAX_LENGTH);
+	mTextBox->setVisible(TRUE);
+	mTextBox->setPlainText(!show_images);
+	mTextBox->setValue(mNotification->getMessage());
+
+	// add buttons for a script notification
+	if (mIsTip)
 	{
-		disableButtons(mNotification->getName(), btn_name);
+		adjustPanelForTipNotice();
 	}
-}
-
-void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification)
-{
-	LLSD response = notification->getResponse();
-	for (LLSD::map_const_iterator response_it = response.beginMap(); 
-		response_it != response.endMap(); ++response_it)
+	else
 	{
-		if (response_it->second.isBoolean() && response_it->second.asBoolean())
+		std::vector<index_button_pair_t> buttons;
+		buttons.reserve(mNumOptions);
+		S32 buttons_width = 0;
+		// create all buttons and accumulate they total width to reshape mControlPanel
+		for (S32 i = 0; i < mNumOptions; i++)
 		{
-			// that after multiple responses there can be many pressed buttons
-			// need to process them all
-			disableButtons(notification->getName(), response_it->first);
+			LLSD form_element = form->getElement(i);
+			if (form_element["type"].asString() != "button")
+			{
+				// not a button.
+				continue;
+			}
+			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN)
+			{
+				// a textbox pretending to be a button.
+				continue;
+			}
+			LLButton* new_button = createButton(form_element, TRUE);
+			buttons_width += new_button->getRect().getWidth();
+			S32 index = form_element["index"].asInteger();
+			buttons.push_back(index_button_pair_t(index,new_button));
+		}
+		if (buttons.empty())
+		{
+			addDefaultButton();
+		}
+		else
+		{
+			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel
+			S32 button_panel_height = mControlPanel->getRect().getHeight();
+			//try get an average h_pad to spread out buttons
+			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size()));
+			if(h_pad < 2*HPAD)
+			{
+				/*
+				* Probably it is a scriptdialog toast
+				* for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons.
+				* In last case set default h_pad to avoid heaping of buttons 
+				*/
+				S32 button_per_row = button_panel_width / BUTTON_WIDTH;
+				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row   
+				if(h_pad < 2*HPAD) // still not enough space between buttons ?
+				{
+					h_pad = 2*HPAD;
+				}
+			}
+			if (mIsScriptDialog)
+			{
+				// we are using default width for script buttons so we can determinate button_rows
+				//to get a number of rows we divide the required width of the buttons to button_panel_width
+				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width);
+				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width;
+				//reserve one row for the ignore_btn
+				button_rows++;
+				//calculate required panel height for scripdialog notification.
+				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD;
+			}
+			else
+			{
+				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width
+				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width);
+				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width);
+				//calculate required panel height 
+				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD;
+			}
+
+			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed
+			adjustPanelForScriptNotice(button_panel_width, button_panel_height);
+			updateButtonsLayout(buttons, h_pad);
+			// save buttons for later use in disableButtons()
+			//mButtons.assign(buttons.begin(), buttons.end());
 		}
 	}
+	// adjust panel's height to the text size
+	snapToMessageHeight(mTextBox, MAX_LENGTH);
 }
 
 
+
+//void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name)
+//{
+//	if(mNotification->getID() == notification_id)
+//	{
+//		disableButtons(mNotification->getName(), btn_name);
+//	}
+//}
+
+//void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification)
+//{
+//	LLSD response = notification->getResponse();
+//	for (LLSD::map_const_iterator response_it = response.beginMap(); 
+//		response_it != response.endMap(); ++response_it)
+//	{
+//		if (response_it->second.isBoolean() && response_it->second.asBoolean())
+//		{
+//			// that after multiple responses there can be many pressed buttons
+//			// need to process them all
+//			disableButtons(notification->getName(), response_it->first);
+//		}
+//	}
+//}
+
+
 //////////////////////////////////////////////////////////////////////////
 
 LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */,
-										   bool show_images /* = true */)
- : mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images)
+										   bool show_images /* = true */, LLTextBase* parent_text)
+:	mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images),
+	mParentText(parent_text)
 {
-	mTextBox->setFollowsAll();
+	compactButtons();
 }
 
 LLIMToastNotifyPanel::~LLIMToastNotifyPanel()
 {
-	// We shouldn't delete notification when IM floater exists
-	// since that notification will be reused by IM floater.
-	// This may happened when IM floater reloads messages, exactly when user
-	// changes layout of IM chat log(disable/enable plaintext mode).
-	// See EXT-6500
-	LLIMFloater* im_floater = LLIMFloater::findInstance(mSessionID);
-	if (im_floater != NULL && !im_floater->isDead())
-	{
-		mCloseNotificationOnDestroy = false;
-	}
 }
 
 void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
 {
-	S32 text_height = mTextBox->getTextBoundingRect().getHeight();
-	S32 widget_height = mTextBox->getRect().getHeight();
-	S32 delta = text_height - widget_height;
-	LLRect rc = getRect();
+	LLToastPanel::reshape(width, height, called_from_parent);
 
-	rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height + delta);
-	height = rc.getHeight();
-	width = rc.getWidth();
+	snapToMessageHeight(mTextBox, MAX_LENGTH);
+}
 
-	bool is_width_changed = width != getRect().getWidth();
+void LLIMToastNotifyPanel::compactButtons()
+{
+	mTextBox->setFollowsAll();
 
-	LLToastPanel::reshape(width, height, called_from_parent);
+	//we can't set follows in xml since it broke toasts behavior
+	setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP);
 
-	// Notification height required to display the text message depends on
-	// the width of the text box thus if panel width is changed the text box
-	// width is also changed then reshape() is called to adjust proper height.
-	if (is_width_changed)
+	const child_list_t* children = getControlPanel()->getChildList();
+	S32 offset = 0;
+	// Children were added by addChild() which uses push_front to insert them into list,
+	// so to get buttons in correct order reverse iterator is used (EXT-5906) 
+	for (child_list_t::const_reverse_iterator it = children->rbegin(); it != children->rend(); it++)
 	{
-		reshape(width, height, called_from_parent);
+		LLButton * button = dynamic_cast<LLButton*> (*it);
+		if (button != NULL)
+		{
+			button->setOrigin( offset,button->getRect().mBottom);
+			button->setLeftHPad(2 * HPAD);
+			button->setRightHPad(2 * HPAD);
+			// set zero width before perform autoResize()
+			button->setRect(LLRect(button->getRect().mLeft,
+				button->getRect().mTop, 
+				button->getRect().mLeft,
+				button->getRect().mBottom));
+			button->setAutoResize(true);
+			button->autoResize();
+			offset += HPAD + button->getRect().getWidth();
+			button->setFollowsNone();
+		}
 	}
+
+	if (mParentText)
+	{
+		mParentText->needsReflow();
+	}
+}
+
+void LLIMToastNotifyPanel::updateNotification()
+{
+	init(LLRect(), true);
+}
+
+void LLIMToastNotifyPanel::init( LLRect rect, bool show_images )
+{
+	LLToastNotifyPanel::init(LLRect(), show_images);
+
+	compactButtons();
 }
 
+
 // EOF
+
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
index db517ec8581d8dfd189c55e09216860312b564bb..f93c7745af1ff2ae9d1eaadea10d6bae3be8eea2 100644
--- a/indra/newview/lltoastnotifypanel.h
+++ b/indra/newview/lltoastnotifypanel.h
@@ -47,7 +47,7 @@ class LLNotificationForm;
  * @deprecated this class will be removed after all toast panel types are
  *  implemented in separate classes.
  */
-class LLToastNotifyPanel: public LLToastPanel 
+class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID>
 {
 public:
 	/**
@@ -61,10 +61,14 @@ class LLToastNotifyPanel: public LLToastPanel
 	 * implement right class for desired toast panel. @see LLGenericTipPanel as example.
 	 */
 	LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true);
+
+	virtual void init( LLRect rect, bool show_images );
+
 	virtual ~LLToastNotifyPanel();
 	LLPanel * getControlPanel() { return mControlPanel; }
 
-	void setCloseNotificationOnDestroy(bool close) { mCloseNotificationOnDestroy = close; }
+	virtual void updateNotification() {}
+
 protected:
 	LLButton* createButton(const LLSD& form_element, BOOL is_option);
 
@@ -76,8 +80,6 @@ class LLToastNotifyPanel: public LLToastPanel
 	};
 	std::vector<InstanceAndS32*> mBtnCallbackData;
 
-	bool mCloseNotificationOnDestroy;
-
 	typedef std::pair<int,LLButton*> index_button_pair_t; 
 	void adjustPanelForScriptNotice(S32 max_width, S32 max_height);
 	void adjustPanelForTipNotice();
@@ -93,9 +95,9 @@ class LLToastNotifyPanel: public LLToastPanel
 	/**
 	 * Disable specific button(s) based on notification name and clicked button
 	 */
-	void disableButtons(const std::string& notification_name, const std::string& selected_button);
+	//void disableButtons(const std::string& notification_name, const std::string& selected_button);
 
-	std::vector<index_button_pair_t> mButtons;
+	//std::vector<index_button_pair_t> mButtons;
 
 	// panel elements
 	LLTextBase*		mTextBox;
@@ -118,7 +120,7 @@ class LLToastNotifyPanel: public LLToastPanel
 	/**
 	 * Process response data. Will disable selected options
 	 */
-	void disableRespondedOptions(const LLNotificationPtr& notification);
+	//void disableRespondedOptions(const LLNotificationPtr& notification);
 
 	bool mIsTip;
 	bool mAddedDefaultBtn;
@@ -137,13 +139,23 @@ class LLIMToastNotifyPanel : public LLToastNotifyPanel
 {
 public:
 
-	LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect = LLRect::null, bool show_images = true);
+	LLIMToastNotifyPanel(LLNotificationPtr& pNotification, 
+						const LLUUID& session_id, 
+						const LLRect& rect = LLRect::null, 
+						bool show_images = true, 
+						LLTextBase* parent_text = NULL);
+
+	void compactButtons();
+
+	virtual void updateNotification();
+	virtual void init( LLRect rect, bool show_images );
 
 	~LLIMToastNotifyPanel();
 
 	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
 
 protected:
+	LLTextBase* mParentText;
 	LLUUID	mSessionID;
 };
 
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index d2a4ce8745a27f655a2a11200d313aebd180a60d..e20d516392c4f53849383f53178e4ff143a1382b 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -78,11 +78,14 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)
 		S32 requiredTextHeight = message->getTextBoundingRect().getHeight();
 		S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight);
 
-		//Calculate last delta height deducting previous heightDelta 
-		heightDelta = newTextHeight - oldTextHeight - heightDelta;
+		heightDelta = newTextHeight - oldTextHeight;
+		S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT);
 
 		//reshape the panel with new height
-		reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT));
+		if (new_panel_height != getRect().getHeight())
+		{
+			reshape( getRect().getWidth(), new_panel_height);
+		}
 	}
 }
 
@@ -96,7 +99,7 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification(
 	if ("notifytip" == notification->getType())
 	{
 		// if it is online/offline notification
-		if ("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName())
+		if ("FriendOnlineOffline" == notification->getName())
 		{
 			res = new LLPanelOnlineStatus(notification);
 		}
diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h
index 346e014d7373641aacecc32f5c23cfd3142a8019..c22557206b705639d8609600f195d59828ce9483 100644
--- a/indra/newview/lltoastpanel.h
+++ b/indra/newview/lltoastpanel.h
@@ -33,19 +33,13 @@
 
 #include <string>
 
-class LLToastPanelBase: public LLPanel 
-{
-public:
-	virtual void init(LLSD& data){};
-};
-
 /**
  * Base class for all panels that can be added to the toast.
  * All toast panels should contain necessary logic for representing certain notification
  * but shouldn't contain logic related to this panel lifetime control and positioning
  * on the parent view.
  */
-class LLToastPanel: public LLPanel {
+class LLToastPanel : public LLPanel {
 public:
 	LLToastPanel(const LLNotificationPtr&);
 	virtual ~LLToastPanel() = 0;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index c2bafd043d40574154b5f151fdfa56e54c017d4e..cefd9ef91d44adad8b23ed2879180de8bb60bd63 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -179,6 +179,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	LLMessageSystem* msg = gMessageSystem;
 	const LLSD& payload = notification["payload"];
+	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());
 
 	// add friend to recent people list
 	LLRecentPeople::instance().add(payload["from_id"]);
@@ -204,7 +205,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
 		msg->sendReliable(LLHost(payload["sender"].asString()));
 
 		LLSD payload = notification["payload"];
-		payload["SUPPRESS_TOAST"] = true;
 		LLNotificationsUtil::add("FriendshipAcceptedByMe",
 				notification["substitutions"], payload);
 		break;
@@ -212,7 +212,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
 	case 1: // Decline
 	{
 		LLSD payload = notification["payload"];
-		payload["SUPPRESS_TOAST"] = true;
 		LLNotificationsUtil::add("FriendshipDeclinedByMe",
 				notification["substitutions"], payload);
 	}
@@ -241,6 +240,12 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
 		break;
 	}
 
+	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm()));
+	modified_form->setElementEnabled("Accept", false);
+	modified_form->setElementEnabled("Decline", false);
+	notification_ptr->updateForm(modified_form);
+	notification_ptr->repost();
+
 	return false;
 }
 static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback);
@@ -1471,16 +1476,16 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 		itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);
 	}
 	 
+	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());
+	llassert(notification_ptr != NULL);
+	
 	// For muting, we need to add the mute, then decline the offer.
 	// This must be done here because:
 	// * callback may be called immediately,
 	// * adding the mute sends a message,
 	// * we can't build two messages at once.
-	if (2 == button) // Block
+	if (IOR_MUTE == button) // Block
 	{
-		LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());
-
-		llassert(notification_ptr != NULL);
 		if (notification_ptr != NULL)
 		{
 			gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3));
@@ -1495,6 +1500,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 	
 	bool busy = gAgent.getBusy();
 	
+	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm()));
+
 	switch(button)
 	{
 	case IOR_SHOW:
@@ -1538,6 +1545,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 			LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
 			break;
 		}
+
+		modified_form->setElementEnabled("Show", false);
 		break;
 		// end switch (mIM)
 			
@@ -1550,9 +1559,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 			args["MESSAGE"] = log_message;
 			LLNotificationsUtil::add("SystemMessageTip", args);
 		}
+
 		break;
 
 	case IOR_MUTE:
+		modified_form->setElementEnabled("Mute", false);
 		// MUTE falls through to decline
 	case IOR_DECLINE:
 		{
@@ -1588,6 +1599,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 			{
 				busy_message(gMessageSystem, mFromID);
 			}
+
+			modified_form->setElementEnabled("Show", false);
+			modified_form->setElementEnabled("Discard", false);
+
 			break;
 		}
 	default:
@@ -1607,6 +1622,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 	{
 		delete this;
 	}
+
+	notification_ptr->updateForm(modified_form);
+	notification_ptr->repost();
+
 	return false;
 }
 
@@ -1984,6 +2003,15 @@ bool lure_callback(const LLSD& notification, const LLSD& response)
 					   lure_id);
 		break;
 	}
+
+	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());
+
+	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm()));
+	modified_form->setElementEnabled("Teleport", false);
+	modified_form->setElementEnabled("Cancel", false);
+	notification_ptr->updateForm(modified_form);
+	notification_ptr->repost();
+
 	return false;
 }
 static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback);
@@ -6394,7 +6422,6 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)
 				
 				//*TODO please rewrite all keys to the same case, lower or upper
 				payload["from_id"] = target_id;
-				payload["SUPPRESS_TOAST"] = true;
 				LLNotificationsUtil::add("TeleportOfferSent", args, payload);
 
 				// Add the recepient to the recent people list.
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index d35cebbd167a4dcaaee6b3e649b10d4ccf50739a..5b7222c1809cd2e0df83762e940c1f494c85b6fc 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5208,20 +5208,14 @@ Topic: [SUBJECT], Message: [MESSAGE]
 
   <notification
    icon="notifytip.tga"
-   name="FriendOnline"
+   name="FriendOnlineOffline"
    log_to_chat="false"
    type="notifytip">
     <tag>friendship</tag>
-&lt;nolink&gt;[NAME]&lt;/nolink&gt; is Online
-  </notification>
-
-  <notification
-   icon="notifytip.tga"
-   name="FriendOffline"
-   log_to_chat="false"
-   type="notifytip">
-    <tag>friendship</tag>
-&lt;nolink&gt;[NAME]&lt;/nolink&gt; is Offline
+&lt;nolink&gt;[NAME]&lt;/nolink&gt; is [STATUS]
+    <unique combine="cancel_old">
+      <context>NAME</context>
+    </unique>
   </notification>
 
   <notification
@@ -6160,7 +6154,8 @@ Your object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; has given you th
   <notification
    icon="notify.tga"
    name="TeleportOfferSent"
-   log_to_im="true"   
+   log_to_im="true"
+   show_toast="false"
    type="offer">
 	Teleport offer sent to [TO_NAME]
   </notification>
@@ -6213,6 +6208,7 @@ Your object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; has given you th
    icon="notify.tga"
    name="FriendshipOffered"
    log_to_im="true"   
+   show_toast="false"   
    type="offer">
     <tag>friendship</tag>
 	You have offered friendship to [TO_NAME]
@@ -6262,6 +6258,7 @@ Your object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; has given you th
    icon="notify.tga"
    name="FriendshipAcceptedByMe"
    log_to_im="true"   
+   show_toast="false"
    type="offer">
     <tag>friendship</tag>
 Friendship offer accepted.
@@ -6271,6 +6268,7 @@ Friendship offer accepted.
    icon="notify.tga"
    name="FriendshipDeclinedByMe"
    log_to_im="true"   
+   show_toast="false"   
    type="offer">
     <tag>friendship</tag>
 Friendship offer declined.
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 97526526794d8f7044523b93e2c15230729df61e..e9323106223d978869a4c6a9b86899cce9c140ac 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3242,6 +3242,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 	<string name="IM_moderator_label">(Moderator)</string>
 	<string name="Saved_message">(Saved [LONG_TIMESTAMP])</string>
 	<string name="IM_unblock_only_groups_friends">To see this message, you must uncheck &apos;Only friends and groups can call or IM me&apos; in Preferences/Privacy.</string>
+  <string name="OnlineStatus">Online</string>
+  <string name="OfflineStatus">Offline</string>
 
 	<!-- voice calls -->
 	<string name="answered_call">Your call has been answered</string>