diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 82ec02d2ebc66df50590332039ae8ef11a294cb2..ce068618e20c5caf1fe891456b9d4d04472362ee 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -26,6 +26,8 @@ include_directories(
     )
 
 set(llui_SOURCE_FILES
+    llaccordionctrl.cpp
+    llaccordionctrltab.cpp
     llbutton.cpp
     llcheckboxctrl.cpp
     llclipboard.cpp
@@ -111,6 +113,8 @@ set(llui_SOURCE_FILES
 set(llui_HEADER_FILES
     CMakeLists.txt
 
+    llaccordionctrl.h
+    llaccordionctrltab.h
     llbutton.h
     llcallbackmap.h
     llcheckboxctrl.h
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b5e870228ad68f9ab140abf6b99773e725cc3d29
--- /dev/null
+++ b/indra/llui/llaccordionctrl.cpp
@@ -0,0 +1,578 @@
+/** 
+ * @file llaccordionctrl.cpp
+ * @brief Accordion panel  implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 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 "linden_common.h"
+
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
+
+#include "lluictrlfactory.h" // builds floaters from XML
+
+#include "llwindow.h"
+#include "llfocusmgr.h"
+#include "lllocalcliprect.h"
+
+#include "boost/bind.hpp"
+
+static const S32 DRAGGER_BAR_MARGIN = 4;
+static const S32 DRAGGER_BAR_HEIGHT = 5;
+static const S32 BORDER_MARGIN = 2;
+static const S32 PARENT_BORDER_MARGIN = 5;
+
+static const S32 panel_delta = DRAGGER_BAR_MARGIN;  // Distanse between two panels 
+
+static const S32 HORIZONTAL_MULTIPLE = 8;
+static const S32 VERTICAL_MULTIPLE = 16;
+static const F32 MIN_AUTO_SCROLL_RATE = 120.f;
+static const F32 MAX_AUTO_SCROLL_RATE = 500.f;
+static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f;
+
+
+// LLAccordionCtrl =================================================================|
+
+static LLDefaultChildRegistry::Register<LLAccordionCtrl>	t2("accordion");
+
+
+LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)
+ , mFitParent(params.fit_parent)
+{
+  mSingleExpansion = params.single_expansion;
+	if(mFitParent && !mSingleExpansion)
+	{
+		llinfos << "fit_parent works best when combined with single_expansion" << llendl;
+	}
+}
+
+LLAccordionCtrl::LLAccordionCtrl() : LLPanel()
+{
+	mSingleExpansion = false;
+	mFitParent = false;
+	LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml");	
+}
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::draw()
+{
+	LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
+	
+	LLLocalClipRect clip(local_rect);
+	
+	LLPanel::draw();
+}
+
+
+//---------------------------------------------------------------------------------
+BOOL LLAccordionCtrl::postBuild()
+{
+	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+	LLRect scroll_rect;
+	scroll_rect.setOriginAndSize( 
+		getRect().getWidth() - scrollbar_size,
+		1,
+		scrollbar_size,
+		getRect().getHeight() - 1);
+	
+
+	LLScrollbar::Params sbparams;
+	sbparams.name("scrollable vertical");
+	sbparams.rect(scroll_rect);
+	sbparams.orientation(LLScrollbar::VERTICAL);
+	sbparams.doc_size(mInnerRect.getHeight());
+	sbparams.doc_pos(0);
+	sbparams.page_size(mInnerRect.getHeight());
+	sbparams.step_size(VERTICAL_MULTIPLE);
+	sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
+	sbparams.change_callback(boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2));
+	
+	mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
+	LLView::addChild( mScrollbar );
+	mScrollbar->setVisible( false );
+	mScrollbar->setFollowsRight();
+	mScrollbar->setFollowsTop();
+	mScrollbar->setFollowsBottom();
+
+	//if it was created from xml...
+	std::vector<LLUICtrl*> accordion_tabs;
+	for(child_list_const_iter_t it = getChildList()->begin(); 
+		getChildList()->end() != it; ++it)
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*it);
+		if(accordion_tab == NULL)
+			continue;
+		if(std::find(mAccordionTabs.begin(),mAccordionTabs.end(),accordion_tab) == mAccordionTabs.end())
+		{
+			accordion_tabs.push_back(accordion_tab);
+		}
+	}
+
+	for(std::vector<LLUICtrl*>::reverse_iterator it = accordion_tabs.rbegin();it!=accordion_tabs.rend();++it)
+		addCollapsibleCtrl(*it);
+
+	arrange	();
+
+	if(mSingleExpansion)
+	{
+		if(!mAccordionTabs[0]->getDisplayChildren())
+			mAccordionTabs[0]->setDisplayChildren(true);
+		for(size_t i=1;i<mAccordionTabs.size();++i)
+		{
+			if(mAccordionTabs[i]->getDisplayChildren())
+				mAccordionTabs[i]->setDisplayChildren(false);
+		}
+	}
+
+	return TRUE;
+}
+
+
+//---------------------------------------------------------------------------------
+LLAccordionCtrl::~LLAccordionCtrl()
+{
+  mAccordionTabs.clear();
+}
+
+//---------------------------------------------------------------------------------
+
+void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+	// adjust our rectangle
+	LLRect rcLocal = getRect();
+	rcLocal.mRight = rcLocal.mLeft + width;
+	rcLocal.mTop = rcLocal.mBottom + height;
+
+	setRect(rcLocal);
+
+	arrange();
+}
+
+//---------------------------------------------------------------------------------
+BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+	return LLPanel::handleRightMouseDown(x, y, mask);
+}
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta)
+{
+	for(size_t i = panel_num; i < mAccordionTabs.size(); i++ )
+	{
+		ctrlShiftVertical(mAccordionTabs[i],delta);
+	}	
+}
+
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) 
+{
+	if(mSingleExpansion)
+	{
+		for(size_t i=0;i<mAccordionTabs.size();++i)
+		{
+			if(i==panel_num)
+				continue;
+			if(mAccordionTabs[i]->getDisplayChildren())
+				mAccordionTabs[i]->setDisplayChildren(false);
+		}
+
+	}
+	arrange();
+}
+
+void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height)
+{
+	calcRecuiredHeight();
+	if(getRecuiredHeight() > height )
+		showScrollbar(width,height);
+	else
+		hideScrollbar(width,height);
+}
+
+void	LLAccordionCtrl::showScrollbar(S32 width, S32 height)
+{
+	bool was_visible = mScrollbar->getVisible();
+
+	mScrollbar->setVisible(true);
+	
+	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+	ctrlSetLeftTopAndSize(mScrollbar
+		,width-scrollbar_size - PARENT_BORDER_MARGIN/2
+		,height-PARENT_BORDER_MARGIN
+		,scrollbar_size
+		,height-2*PARENT_BORDER_MARGIN);
+	
+	mScrollbar->setPageSize(height);
+	mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos());
+
+	if(was_visible)
+	{
+		S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1);
+		mScrollbar->setDocPos(scroll_pos);
+	}
+}
+
+void	LLAccordionCtrl::hideScrollbar( S32 width, S32 height )
+{
+	if(mScrollbar->getVisible() == false)
+		return;
+	mScrollbar->setVisible(false);
+
+	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+	S32 panel_width = width - 2*BORDER_MARGIN;
+
+	//reshape all accordeons and shift all draggers
+	for(size_t i=0;i<mAccordionTabs.size();++i)
+	{
+		LLRect panel_rect = mAccordionTabs[i]->getRect();
+		ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_rect.mTop,panel_width,panel_rect.getHeight());
+	}
+
+	mScrollbar->setDocPos(0);
+
+	if(mAccordionTabs.size()>0)
+	{
+		S32 panel_top = height - BORDER_MARGIN;		  // Top coordinate of the first panel
+		S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop;
+		shiftAccordionTabs(0,diff);
+	}
+}
+
+
+//---------------------------------------------------------------------------------
+S32 LLAccordionCtrl::calcRecuiredHeight()
+{
+	S32 rec_height = 0;
+	
+	std::vector<LLAccordionCtrlTab*>::iterator panel;
+	for(panel=mAccordionTabs.begin(); panel!=mAccordionTabs.end(); ++panel)
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*panel);
+		if(accordion_tab && accordion_tab->getVisible())
+		{
+			rec_height += accordion_tab->getRect().getHeight();
+		}
+	}
+
+	mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN);
+
+	return mInnerRect.getHeight();
+}
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height)
+{
+	if(!panel)
+		return;
+	LLRect panel_rect = panel->getRect();
+	panel_rect.setLeftTopAndSize( left, top, width, height);
+	panel->reshape( width, height, 1);
+	panel->setRect(panel_rect);
+}
+
+void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta)
+{
+	if(!panel)
+		return;
+	panel->translate(0,delta);
+}
+
+//---------------------------------------------------------------------------------
+
+void LLAccordionCtrl::addCollapsibleCtrl(LLView* view)
+{
+	LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(view);
+	if(!accordion_tab)
+		return;
+	if(std::find(getChildList()->begin(),getChildList()->end(),accordion_tab) == getChildList()->end())
+		addChild(accordion_tab);
+	mAccordionTabs.push_back(accordion_tab);
+	
+	accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, mAccordionTabs.size() - 1) );
+
+}
+
+
+void LLAccordionCtrl::arrange()
+{
+	if( mAccordionTabs.size() == 0)
+	{
+		//We do not arrange if we do not have what should be arranged
+		return;
+	}
+
+	//Calculate params	
+	S32 panel_left = BORDER_MARGIN;	  // Margin from left side of Splitter
+	S32 panel_top = getRect().getHeight() - BORDER_MARGIN;		  // Top coordinate of the first panel
+	S32 panel_width = getRect().getWidth() - 4;		  // Top coordinate of the first panel
+
+	
+	if(mAccordionTabs.size() == 1)
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]);
+		
+		LLRect panel_rect = accordion_tab->getRect();
+		
+		S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
+
+		ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
+		
+		show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
+		return;
+
+	}
+
+	for(size_t i = 0; i < mAccordionTabs.size(); i++ )
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+		
+		if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
+			continue;
+		
+		if(!accordion_tab->isExpanded() )
+		{
+			ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight());
+			panel_top-=mAccordionTabs[i]->getRect().getHeight();
+		}
+		else
+		{
+			S32 panel_height = accordion_tab->getRect().getHeight();
+			
+			if(mFitParent)
+			{
+				// all expanded tabs will have equal height
+				panel_height = calcExpandedTabHeight(i, panel_top);
+				ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height);
+
+				// try to make accordion tab fit accordion view height.
+				// Accordion View should implement getRequiredRect() and provide valid height
+				S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight();
+				optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN;
+				if(optimal_height < panel_height)
+				{
+					panel_height = optimal_height;
+				}
+
+				// minimum tab height is equal to header height
+				if(mAccordionTabs[i]->getHeaderHeight() > panel_height)
+				{
+					panel_height = mAccordionTabs[i]->getHeaderHeight();
+				}
+			}
+			
+			ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height);
+			panel_top-=panel_height;
+			
+		}
+	}	
+
+	show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
+
+	updateLayout(getRect().getWidth(),getRect().getHeight());
+
+}
+
+//---------------------------------------------------------------------------------
+
+BOOL LLAccordionCtrl::handleScrollWheel		( S32 x, S32 y, S32 clicks )
+{
+	if(LLPanel::handleScrollWheel(x,y,clicks))
+		return TRUE;
+	if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) )
+		return TRUE;
+	return false;
+
+}
+
+BOOL LLAccordionCtrl::handleKeyHere			(KEY key, MASK mask)
+{
+	if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) )
+		return TRUE;
+	return LLPanel::handleKeyHere(key,mask);
+}
+
+void	LLAccordionCtrl::updateLayout	(S32 width, S32 height)
+{
+	S32 panel_top = height - BORDER_MARGIN ;
+	if(mScrollbar->getVisible())
+		panel_top+=mScrollbar->getDocPos();
+
+	S32 panel_width = width - 2*BORDER_MARGIN;
+
+	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+	if(mScrollbar->getVisible())
+		panel_width-=scrollbar_size;
+
+	//set sizes for first panels and dragbars
+	for(size_t i=0;i<mAccordionTabs.size();++i)
+	{
+		if(!mAccordionTabs[i]->getVisible())
+			continue;
+		LLRect panel_rect = mAccordionTabs[i]->getRect();
+		ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight());
+		panel_top-=panel_rect.getHeight();
+	}
+}
+
+void	LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*)
+{
+	updateLayout(getRect().getWidth(),getRect().getHeight());
+}
+void	LLAccordionCtrl::onOpen		(const LLSD& key)
+{
+	for(size_t i=0;i<mAccordionTabs.size();++i)
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+		LLPanel* panel = dynamic_cast<LLPanel*>(accordion_tab->getAccordionView());
+		if(panel!=NULL)
+		{
+			panel->onOpen(key);
+		}
+	}
+}
+S32	LLAccordionCtrl::notifyParent(const LLSD& info)
+{
+	if(info.has("action"))
+	{
+		std::string str_action = info["action"];
+		if(str_action == "size_changes")
+		{
+			//
+			arrange();
+			return 1;
+		}
+		else if(str_action == "select_next")
+		{
+			for(size_t i=0;i<mAccordionTabs.size();++i)
+			{
+				LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+				if(accordion_tab->hasFocus())
+				{
+					while(++i<mAccordionTabs.size())
+					{
+						if(mAccordionTabs[i]->getVisible())
+							break;
+					}
+					if(i<mAccordionTabs.size())
+					{
+						accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+						accordion_tab->notify(LLSD().with("action","select_first"));
+						return 1;
+					}
+					break;
+				}
+			}
+			return 0;
+		}
+		else if(str_action == "select_prev")
+		{
+			for(size_t i=0;i<mAccordionTabs.size();++i)
+			{
+				LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+				if(accordion_tab->hasFocus() && i>0)
+				{
+					while(i>0)
+					{
+						if(mAccordionTabs[--i]->getVisible())
+							break;
+					}
+					
+					accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+					accordion_tab->notify(LLSD().with("action","select_last"));
+					return 1;
+				}
+			}
+			return 0;
+		}
+	}
+	else if (info.has("scrollToShowRect"))
+	{
+		LLRect screen_rc, local_rc;
+		screen_rc.setValue(info["scrollToShowRect"]);
+		screenRectToLocal(screen_rc, &local_rc);
+
+		// Translate to parent coordinatess to check if we are in visible rectangle
+		local_rc.translate( getRect().mLeft, getRect().mBottom );
+
+		if ( !getRect().contains (local_rc) )
+		{
+			// Back to local coords and calculate position for scroller
+			S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom;
+			S32 top = mScrollbar->getDocPos() - local_rc.mTop + getRect().mTop;
+
+			S32 scroll_pos = llclamp(mScrollbar->getDocPos(),
+									 bottom, // min vertical scroll
+									 top); // max vertical scroll 
+
+			mScrollbar->setDocPos( scroll_pos );
+		}
+		return 1;
+	}
+	return LLPanel::notifyParent(info);
+}
+void	LLAccordionCtrl::reset		()
+{
+	if(mScrollbar)
+		mScrollbar->setDocPos(0);
+}
+
+S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */)
+{
+	if(tab_index < 0)
+	{
+		return available_height;
+	}
+
+	S32 collapsed_tabs_height = 0;
+	S32 num_expanded = 0;
+
+	for(size_t n = tab_index; n < mAccordionTabs.size(); ++n)
+	{
+		if(!mAccordionTabs[n]->isExpanded())
+		{
+			collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight();
+		}
+		else
+		{
+			++num_expanded;
+		}
+	}
+
+	if(0 == num_expanded)
+	{
+		return available_height;
+	}
+
+	S32 expanded_tab_height = available_height - collapsed_tabs_height - BORDER_MARGIN; // top BORDER_MARGIN is added in arrange(), here we add bottom BORDER_MARGIN
+	expanded_tab_height /= num_expanded;
+	return expanded_tab_height;
+}
diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h
new file mode 100644
index 0000000000000000000000000000000000000000..4cb0f382813ab9ef14fba7f462ab451751c91606
--- /dev/null
+++ b/indra/llui/llaccordionctrl.h
@@ -0,0 +1,123 @@
+/** 
+ * @file LLAccordionCtrl.h
+ * @brief Accordion Panel implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * 
+ * Copyright (c) 2004-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$
+ */
+
+#ifndef LL_ACCORDIONCTRL_H
+#define LL_ACCORDIONCTRL_H
+
+#include "llpanel.h"
+#include "llscrollbar.h"
+
+#include <vector>
+#include <algorithm>
+#include <string>
+
+class LLAccordionCtrlTab;
+
+class LLAccordionCtrl: public LLPanel
+{
+private:
+
+	std::vector<LLAccordionCtrlTab*> mAccordionTabs;
+
+	void ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height);
+	void ctrlShiftVertical(LLView* panel,S32 delta);
+	
+	void onCollapseCtrlCloseOpen(S16 panel_num); 
+	void shiftAccordionTabs(S16 panel_num, S32 delta);
+
+
+public:
+	struct Params 
+		: public LLInitParam::Block<Params, LLPanel::Params>
+	{
+		Optional<bool>			single_expansion,
+								fit_parent; /* Accordion will fit its parent size, controls that are placed into 
+								accordion tabs are responsible for scrolling their content.
+								*NOTE fit_parent works best when combined with single_expansion.
+								Accordion view should implement getRequiredRect() and provide valid height*/
+
+		Params()
+			: single_expansion("single_expansion",false)
+			, fit_parent("fit_parent", false)
+		{};
+	};
+
+	LLAccordionCtrl(const Params& params);
+
+    LLAccordionCtrl();
+    virtual ~LLAccordionCtrl();
+
+	virtual BOOL postBuild();
+	
+	virtual BOOL handleRightMouseDown	( S32 x, S32 y, MASK mask); 
+	virtual BOOL handleScrollWheel		( S32 x, S32 y, S32 clicks );
+	virtual BOOL handleKeyHere			(KEY key, MASK mask);
+	//
+
+	// Call reshape after changing splitter's size
+	virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+	void addCollapsibleCtrl(LLView* view);
+	void arrange();
+
+
+	void	draw();
+	
+	void	onScrollPosChangeCallback(S32, LLScrollbar*);
+
+	void	onOpen		(const LLSD& key);
+	S32		notifyParent(const LLSD& info);
+
+	void	reset		();
+
+private:
+	// Calc Splitter's height that is necessary to display all child content
+	S32		calcRecuiredHeight();
+	S32		getRecuiredHeight() const { return mInnerRect.getHeight(); }
+	S32		calcExpandedTabHeight(S32 tab_index = 0, S32 available_height = 0);
+
+	void	updateLayout			(S32 width, S32 height);
+
+	void	show_hide_scrollbar		(S32 width, S32 height);
+
+	void	showScrollbar			(S32 width, S32 height);
+	void	hideScrollbar			(S32 width, S32 height);
+
+private:
+	LLRect			mInnerRect;
+	LLScrollbar*	mScrollbar;
+	bool			mSingleExpansion;
+	bool			mFitParent;
+};
+
+
+#endif // LL_LLSPLITTER_H
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d6ba57c29a21a1f3ee8a7cbbaecbc28aacc01e6
--- /dev/null
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -0,0 +1,599 @@
+/** 
+ * @file LLAccordionCtrlTab.cpp
+ * @brief Collapsible control implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 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 "linden_common.h"
+
+#include "lluictrl.h"
+
+#include "llaccordionctrltab.h"
+
+#include "lltextbox.h"
+
+static const std::string DD_BUTTON_NAME = "dd_button";
+static const std::string DD_TEXTBOX_NAME = "dd_textbox";
+static const std::string DD_HEADER_NAME = "dd_header";
+
+static const S32 HEADER_HEIGHT = 20;
+static const S32 HEADER_IMAGE_LEFT_OFFSET = 5;
+static const S32 HEADER_TEXT_LEFT_OFFSET = 30;
+
+static LLDefaultChildRegistry::Register<LLAccordionCtrlTab> t1("accordion_tab");
+
+class LLAccordionCtrlTab::LLAccordionCtrlTabHeader : public LLUICtrl
+{
+public:
+	friend class LLUICtrlFactory;
+
+	struct Params : public LLInitParam::Block<Params, LLAccordionCtrlTab::Params>
+	{
+		Params();
+	};
+
+	LLAccordionCtrlTabHeader(const LLAccordionCtrlTabHeader::Params& p);
+	
+	virtual ~LLAccordionCtrlTabHeader();
+
+	virtual void draw();
+
+	virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+	virtual BOOL postBuild();
+
+	void	setTitle(const std::string& title);
+
+	virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+	virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+	virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+private:
+
+	LLTextBox* mHeaderTextbox;
+
+	// Overlay images (arrows)
+	LLPointer<LLUIImage> mImageCollapsed;
+	LLPointer<LLUIImage> mImageExpanded;
+	LLPointer<LLUIImage> mImageCollapsedPressed;
+	LLPointer<LLUIImage> mImageExpandedPressed;
+
+	// Background images
+	LLPointer<LLUIImage> mImageHeader;
+	LLPointer<LLUIImage> mImageHeaderOver;
+	LLPointer<LLUIImage> mImageHeaderPressed;
+	LLPointer<LLUIImage> mImageHeaderFocused;
+
+	LLUIColor mHeaderBGColor;
+
+	bool mNeedsHighlight;
+};
+
+LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params()
+{
+}
+
+LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader(
+	const LLAccordionCtrlTabHeader::Params& p)
+: LLUICtrl(p)
+, mHeaderBGColor(p.header_bg_color())
+,mNeedsHighlight(false),
+	mImageCollapsed(p.header_collapse_img),
+	mImageCollapsedPressed(p.header_collapse_img_pressed),
+	mImageExpanded(p.header_expand_img),
+	mImageExpandedPressed(p.header_expand_img_pressed),
+	mImageHeader(p.header_image),
+	mImageHeaderOver(p.header_image_over),
+	mImageHeaderPressed(p.header_image_pressed),
+	mImageHeaderFocused(p.header_image_focused)
+{
+	LLTextBox::Params textboxParams;
+	textboxParams.name(DD_TEXTBOX_NAME);
+	textboxParams.initial_value(p.title());
+	textboxParams.text_color(p.header_text_color());
+	textboxParams.follows.flags(FOLLOWS_NONE);
+	textboxParams.font( p.font() );
+	textboxParams.font_shadow(LLFontGL::NO_SHADOW);
+	textboxParams.use_ellipses = true;
+	textboxParams.bg_visible = false;
+	textboxParams.mouse_opaque = false;
+	mHeaderTextbox = LLUICtrlFactory::create<LLTextBox>(textboxParams);
+	addChild(mHeaderTextbox);
+}
+
+LLAccordionCtrlTab::LLAccordionCtrlTabHeader::~LLAccordionCtrlTabHeader()
+{
+}
+
+BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild()
+{
+	return TRUE;
+}
+
+void	LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title)
+{
+	if(mHeaderTextbox)
+		mHeaderTextbox->setText(title);
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw()
+{
+	S32 width = getRect().getWidth();
+	S32 height = getRect().getHeight();
+
+	gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get(),true);
+
+	LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent());
+	bool collapsible = (parent && parent->getCollapsible());
+	bool expanded = (parent && parent->getDisplayChildren());
+
+	// Handle overlay images, if needed
+	// Only show green "focus" background image if the accordion is open,
+	// because the user's mental model of focus is that it goes away after
+	// the accordion is closed.
+	if (getParent()->hasFocus()
+		&& !(collapsible && !expanded))
+	{
+		mImageHeaderFocused->draw(0,0,width,height);
+	}
+	else
+	{
+		mImageHeader->draw(0,0,width,height);
+	}
+
+	if(mNeedsHighlight)
+	{
+		mImageHeaderOver->draw(0,0,width,height);
+	}
+	
+
+	if(collapsible)
+	{
+		LLPointer<LLUIImage> overlay_image;
+		if(expanded)
+		{
+			overlay_image = mImageExpanded;
+		}
+		else
+		{
+			overlay_image = mImageCollapsed;
+		}
+		overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET,
+							(height - overlay_image->getHeight()) / 2);
+	}
+	
+	LLUICtrl::draw();
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
+{
+	S32 header_height = mHeaderTextbox->getTextPixelHeight();
+
+	LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET,(height+header_height)/2 ,width,(height-header_height)/2);
+	mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight());
+	mHeaderTextbox->setRect(textboxRect);
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+	LLUICtrl::onMouseEnter(x, y, mask);
+	mNeedsHighlight = true;
+}
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+	LLUICtrl::onMouseLeave(x, y, mask);
+	mNeedsHighlight = false;
+}
+BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+	if ( ( key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE)
+	{
+		return getParent()->handleKey(key, mask, called_from_parent);
+	}
+	return LLUICtrl::handleKey(key, mask, called_from_parent);
+}
+
+
+LLAccordionCtrlTab::Params::Params()
+	: title("title")
+	,display_children("expanded", true)
+	,header_height("header_height", HEADER_HEIGHT),
+	min_width("min_width", 0),
+	min_height("min_height", 0)
+	,collapsible("collapsible", true)
+	,header_bg_color("header_bg_color")
+	,dropdown_bg_color("dropdown_bg_color")
+	,header_visible("header_visible",true)
+	,padding_left("padding_left",2)
+	,padding_right("padding_right",2)
+	,padding_top("padding_top",2)
+	,padding_bottom("padding_bottom",2)
+	,header_expand_img("header_expand_img")
+	,header_expand_img_pressed("header_expand_img_pressed")
+	,header_collapse_img("header_collapse_img")
+	,header_collapse_img_pressed("header_collapse_img_pressed")
+	,header_image("header_image")
+	,header_image_over("header_image_over")
+	,header_image_pressed("header_image_pressed")
+	,header_image_focused("header_image_focused")
+	,header_text_color("header_text_color")
+{
+	mouse_opaque(false);
+}
+
+LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p)
+	: LLUICtrl(p)
+	,mDisplayChildren(p.display_children)
+	,mCollapsible(p.collapsible)
+	,mExpandedHeight(0)
+	,mDropdownBGColor(p.dropdown_bg_color())
+	,mHeaderVisible(p.header_visible)
+	,mPaddingLeft(p.padding_left)
+	,mPaddingRight(p.padding_right)
+	,mPaddingTop(p.padding_top)
+	,mPaddingBottom(p.padding_bottom)
+	,mCanOpenClose(true)
+{
+	mStoredOpenCloseState = false;
+	mWasStateStored = false;
+	
+	mDropdownBGColor = LLColor4::white;
+	LLAccordionCtrlTabHeader::Params headerParams;
+	headerParams.name(DD_HEADER_NAME);
+	headerParams.title(p.title);
+	mHeader = LLUICtrlFactory::create<LLAccordionCtrlTabHeader>(headerParams);
+	addChild(mHeader, 1);
+
+	reshape(100, 200,FALSE);
+}
+
+LLAccordionCtrlTab::~LLAccordionCtrlTab()
+{
+}
+
+
+void LLAccordionCtrlTab::setDisplayChildren(bool display)
+{
+	mDisplayChildren = display;
+	LLRect rect = getRect();
+
+	rect.mBottom = rect.mTop - (getDisplayChildren() ? 
+		mExpandedHeight : HEADER_HEIGHT);
+	setRect(rect);
+
+	for(child_list_const_iter_t it = getChildList()->begin();
+		getChildList()->end() != it; ++it)
+	{
+		LLView* child = *it;
+		if(DD_HEADER_NAME == child->getName())
+			continue;
+
+		child->setVisible(getDisplayChildren());
+	}
+}
+
+void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
+{
+	LLRect headerRect;
+
+	LLUICtrl::reshape(width, height, TRUE);
+
+	headerRect.setLeftTopAndSize(
+		0,height,width,HEADER_HEIGHT);
+	mHeader->setRect(headerRect);
+	mHeader->reshape(headerRect.getWidth(), headerRect.getHeight());
+
+	for(child_list_const_iter_t it = getChildList()->begin(); 
+		getChildList()->end() != it; ++it)
+	{
+		LLView* child = *it;
+		if(DD_HEADER_NAME == child->getName())
+			continue;
+		if(!child->getVisible())
+			continue;
+
+		LLRect childRect = child->getRect();
+		S32 childWidth = width - getPaddingLeft() - getPaddingRight();
+		S32 childHeight = height - getHeaderHeight() - getPaddingTop() - getPaddingBottom();
+
+		child->reshape(childWidth,childHeight);
+		
+		childRect.setLeftTopAndSize(
+			getPaddingLeft(),
+			childHeight + getPaddingBottom(),
+			childWidth, 
+			childHeight);
+
+		child->setRect(childRect);
+		
+		break;//suppose that there is only one panel
+	}
+
+}
+
+void LLAccordionCtrlTab::changeOpenClose(bool is_open)
+{
+	if(is_open)
+		mExpandedHeight = getRect().getHeight();
+
+	setDisplayChildren(!is_open);
+	reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
+	if (mCommitSignal)
+	{
+		(*mCommitSignal)(this, getDisplayChildren());
+	}
+}
+
+BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+	if(mCollapsible && mHeaderVisible && mCanOpenClose)
+	{
+		if(y >= (getRect().getHeight() - HEADER_HEIGHT) )
+		{
+			LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
+			header->setFocus(true);
+			changeOpenClose(getDisplayChildren());
+
+			//reset stored state
+			mWasStateStored = false;
+			return TRUE;
+		}
+	}
+	return LLUICtrl::handleMouseDown(x,y,mask);
+}
+
+BOOL LLAccordionCtrlTab::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+	return LLUICtrl::handleMouseUp(x,y,mask);
+}
+
+boost::signals2::connection LLAccordionCtrlTab::setDropDownStateChangedCallback(commit_callback_t cb)
+{
+	return setCommitCallback(cb);
+}
+
+bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group)
+{
+	if(DD_HEADER_NAME != child->getName())
+	{
+		reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT );
+		mExpandedHeight = getRect().getHeight();
+	}
+
+	bool res = LLUICtrl::addChild(child, tab_group);
+
+	if(DD_HEADER_NAME != child->getName())
+	{
+		if(!mCollapsible)
+			setDisplayChildren(true);
+		else
+			setDisplayChildren(getDisplayChildren());	
+	}
+
+	return res;
+}
+
+void LLAccordionCtrlTab::setAccordionView(LLView* panel)
+{
+	addChild(panel,0);
+}
+
+
+LLView*	LLAccordionCtrlTab::getAccordionView()
+{
+	for(child_list_const_iter_t it = getChildList()->begin(); 
+		getChildList()->end() != it; ++it)
+	{
+		LLView* child = *it;
+		if(DD_HEADER_NAME == child->getName())
+			continue;
+		if(!child->getVisible())
+			continue;
+		return child;
+	}
+	return NULL;
+}
+
+
+S32 LLAccordionCtrlTab::getHeaderHeight()
+{
+	return mHeaderVisible?HEADER_HEIGHT:0; 
+}
+
+void LLAccordionCtrlTab::setHeaderVisible(bool value) 
+{
+	if(mHeaderVisible == value)
+		return;
+	mHeaderVisible = value;
+	if(mHeader)
+		mHeader->setVisible(value);
+	reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
+};
+
+//vurtual
+BOOL LLAccordionCtrlTab::postBuild()
+{
+	mHeader->setVisible(mHeaderVisible);
+	return LLUICtrl::postBuild();
+}
+bool	LLAccordionCtrlTab::notifyChildren	(const LLSD& info)
+{
+	if(info.has("action"))
+	{
+		std::string str_action = info["action"];
+		if(str_action == "store_state")
+		{
+			storeOpenCloseState();
+			return true;
+		}
+		if(str_action == "restore_state")
+		{
+			restoreOpenCloseState();
+			return true;
+		}
+	}	
+	return LLUICtrl::notifyChildren(info);
+}
+
+S32	LLAccordionCtrlTab::notifyParent(const LLSD& info)
+{
+	if(info.has("action"))
+	{
+		std::string str_action = info["action"];
+		if(str_action == "size_changes")
+		{
+			//
+			S32 height = info["height"];
+			height = llmax(height,10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom();
+			
+			mExpandedHeight = height;
+			
+			if(isExpanded())
+			{
+				LLRect panel_rect = getRect();
+				panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height);
+				reshape(getRect().getWidth(),height);
+				setRect(panel_rect);
+			}
+			
+			//LLAccordionCtrl should rearrange accodion tab if one of accordion change its size
+			getParent()->notifyParent(info);
+			return 1;
+		}
+		else if(str_action == "select_prev") 
+		{
+			showAndFocusHeader();
+			return 1;
+		}
+	}
+	return LLUICtrl::notifyParent(info);
+}
+
+S32 LLAccordionCtrlTab::notify(const LLSD& info)
+{
+	if(info.has("action"))
+	{
+		std::string str_action = info["action"];
+		if(str_action == "select_first")
+		{
+			showAndFocusHeader();
+			return 1;
+		}
+		else if( str_action == "select_last" )
+		{
+			if(getDisplayChildren() == false)
+			{
+				showAndFocusHeader();
+			}
+			else
+			{
+				LLView* view = getAccordionView();
+				if(view)
+					view->notify(LLSD().with("action","select_last"));
+			}
+		}
+	}
+	return 0;
+}
+
+BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+	LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);	
+	if( !header->hasFocus() )
+		return LLUICtrl::handleKey(key, mask, called_from_parent);
+
+	if ( (key == KEY_ADD || key == KEY_RIGHT)&& mask == MASK_NONE)
+	{
+		if(getDisplayChildren() == false)
+		{
+			changeOpenClose(getDisplayChildren());
+			return TRUE;
+		}
+	}
+	if ( (key == KEY_SUBTRACT || key == KEY_LEFT)&& mask == MASK_NONE)
+	{
+		if(getDisplayChildren() == true)
+		{
+			changeOpenClose(getDisplayChildren());
+			return TRUE;
+		}
+	}
+
+	if ( key == KEY_DOWN && mask == MASK_NONE)
+	{
+		//if collapsed go to the next accordion
+		if(getDisplayChildren() == false)
+			//we processing notifyParent so let call parent directly
+			getParent()->notifyParent(LLSD().with("action","select_next"));
+		else
+		{
+			getAccordionView()->notify(LLSD().with("action","select_first"));
+		}
+		return TRUE;
+	}
+
+	if ( key == KEY_UP && mask == MASK_NONE)
+	{
+		//go to the previous accordion
+
+		//we processing notifyParent so let call parent directly
+		getParent()->notifyParent(LLSD().with("action","select_prev"));
+		return TRUE;
+	}
+
+	return LLUICtrl::handleKey(key, mask, called_from_parent);
+}
+
+void LLAccordionCtrlTab::showAndFocusHeader()
+{
+	LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);	
+	header->setFocus(true);
+
+	LLRect screen_rc;
+	LLRect selected_rc = header->getRect();
+	localRectToScreen(selected_rc, &screen_rc);
+	notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
+
+}
+void    LLAccordionCtrlTab::storeOpenCloseState()
+{
+	if(mWasStateStored)
+		return;
+	mStoredOpenCloseState = getDisplayChildren();
+	mWasStateStored = true;
+}
+void   LLAccordionCtrlTab::restoreOpenCloseState()
+{
+	if(!mWasStateStored)
+		return;
+	if(getDisplayChildren() != mStoredOpenCloseState)
+	{
+		changeOpenClose(getDisplayChildren());
+	}
+	mWasStateStored = false;
+}
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
new file mode 100644
index 0000000000000000000000000000000000000000..b200d43438b5e2f4920a51a95965075a9a90c312
--- /dev/null
+++ b/indra/llui/llaccordionctrltab.h
@@ -0,0 +1,191 @@
+/** 
+ * @file LLAccordionCtrlTab.h
+ * @brief Collapsible box control implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * 
+ * Copyright (c) 2004-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$
+ */
+
+#ifndef LL_ACCORDIONCTRLTAB_H_
+#define LL_ACCORDIONCTRLTAB_H_
+
+#include <string>
+#include "llrect.h"
+
+class LLUICtrl;
+class LLUICtrlFactory;
+class LLUIImage;
+class LLButton;
+class LLTextBox;
+
+
+
+// LLAccordionCtrlTab is a container for other controls. 
+// It has a Header, by clicking on which hosted controls are shown or hidden.
+// When hosted controls are show - LLAccordionCtrlTab is expanded.
+// When hosted controls are hidden - LLAccordionCtrlTab is collapsed.
+
+class LLAccordionCtrlTab : public LLUICtrl
+{
+// Interface
+public:
+
+	struct Params 
+	 : public LLInitParam::Block<Params, LLUICtrl::Params>
+	{
+		Optional<bool>			display_children, //expanded or collapsed after initialization
+								collapsible;
+
+		Optional<std::string>	title;
+
+		Optional<S32>			header_height,
+								min_width,
+								min_height;
+
+		// Overlay images (arrows on the left)
+		Mandatory<LLUIImage*>	header_expand_img,
+								header_expand_img_pressed,
+								header_collapse_img,
+								header_collapse_img_pressed;
+
+		// Background images for the accordion tabs
+		Mandatory<LLUIImage*>	header_image,
+								header_image_over,
+								header_image_pressed,
+								header_image_focused;
+
+		Optional<LLUIColor>		header_bg_color,
+								header_text_color,
+								dropdown_bg_color;
+
+		Optional<bool>			header_visible;
+
+		Optional<S32>			padding_left;
+		Optional<S32>			padding_right;
+		Optional<S32>			padding_top;
+		Optional<S32>			padding_bottom;
+
+		Params();
+	};
+
+	typedef LLDefaultChildRegistry child_registry_t;
+
+	virtual ~LLAccordionCtrlTab();
+	
+	// Registers callback for expand/collapse events.
+	boost::signals2::connection setDropDownStateChangedCallback(commit_callback_t cb);
+
+	// Changes expand/collapse state
+	virtual void setDisplayChildren(bool display);
+
+	// Returns expand/collapse state
+	virtual bool getDisplayChildren() const {return mDisplayChildren;};
+
+	//set LLAccordionCtrlTab panel
+	void		setAccordionView(LLView* panel);
+	LLView*		getAccordionView();
+
+	bool getCollapsible() {return mCollapsible;};
+
+	void setCollapsible(bool collapsible) {mCollapsible = collapsible;};
+	void changeOpenClose(bool is_open);
+
+	void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;};
+
+	virtual BOOL postBuild();
+
+	S32	notifyParent(const LLSD& info);
+	S32 notify(const LLSD& info);
+	bool notifyChildren(const LLSD& info);
+
+	void    storeOpenCloseState		();
+	void    restoreOpenCloseState	();
+
+protected:
+	LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&);
+	friend class LLUICtrlFactory;
+
+// Overrides
+public:
+
+	// Call reshape after changing size
+	virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+	// Changes expand/collapse state and triggers expand/collapse callbacks
+	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+	virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+	virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+
+	virtual bool addChild(LLView* child, S32 tab_group);
+
+	bool isExpanded() { return mDisplayChildren; }
+
+	S32 getHeaderHeight();
+
+	// Min size functions
+
+	void setHeaderVisible(bool value);
+
+	bool getHeaderVisible() { return mHeaderVisible;}
+
+	S32 mExpandedHeight; // Height of expanded ctrl.
+						 // Used to restore height after expand.
+
+	S32	getPaddingLeft() const { return mPaddingLeft;}
+	S32	getPaddingRight() const { return mPaddingRight;}
+	S32	getPaddingTop() const { return mPaddingTop;}
+	S32	getPaddingBottom() const { return mPaddingBottom;}
+
+	void showAndFocusHeader();
+
+private:
+
+	
+
+	class LLAccordionCtrlTabHeader;
+	LLAccordionCtrlTabHeader* mHeader; //Header
+
+	bool mDisplayChildren; //Expanded/collapsed
+	bool mCollapsible;
+	bool mHeaderVisible;
+
+	bool mCanOpenClose;
+
+	S32	mPaddingLeft;
+	S32	mPaddingRight;
+	S32	mPaddingTop;
+	S32	mPaddingBottom;
+
+	bool mStoredOpenCloseState;
+	bool mWasStateStored;
+
+
+	LLUIColor mDropdownBGColor;
+};
+
+#endif
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index db3288243828de36db4ab1582df7c34b63c511f0..143f19eea61494a12127a4fee328a43c36d3375e 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -43,6 +43,7 @@
 #include "llerror.h"
 #include "lltimer.h"
 
+#include "llaccordionctrltab.h"
 #include "llbutton.h"
 #include "llmenugl.h"
 //#include "llstatusbar.h"
@@ -851,14 +852,26 @@ static LLPanel *childGetVisibleTabWithHelp(LLView *parent)
 	// look through immediate children first for an active tab with help
 	for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
 	{
+		LLPanel *curTabPanel = NULL;
+
+		// do we have a tab container?
 		LLTabContainer *tab = dynamic_cast<LLTabContainer *>(child);
 		if (tab && tab->getVisible())
 		{
-			LLPanel *curTabPanel = tab->getCurrentPanel();
-			if (curTabPanel && !curTabPanel->getHelpTopic().empty())
-			{
-				return curTabPanel;
-			}
+			curTabPanel = tab->getCurrentPanel();
+		}
+
+		// do we have an accordion tab?
+		LLAccordionCtrlTab* accordion = dynamic_cast<LLAccordionCtrlTab *>(child);
+		if (accordion && accordion->getDisplayChildren())
+		{
+			curTabPanel = dynamic_cast<LLPanel *>(accordion->getAccordionView());
+		}
+
+		// if we found a valid tab, does it have a help topic?
+		if (curTabPanel && !curTabPanel->getHelpTopic().empty())
+		{
+			return curTabPanel;
 		}
 	}
 
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index f7528bc62ab331e9776eca2aec819d6f2e657cda..1b6dd1b2641967f18af68f9de3138f0f4f8a7732 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -101,7 +101,7 @@ std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url)
 	{
 		start++;
 	}
-	return url.substr(start, url.size()-start-1);
+	return unescapeUrl(url.substr(start, url.size()-start-1));
 }
 
 std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string)
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 128cd134c138b0346de6d45a36d442d471d134f9..38cf7124ceadd0c041d89da30911bd329d76736d 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -545,4 +545,50 @@ namespace tut
 				  "XXX [secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern] YYY",
 				  "[secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern]");
 	}
+
+	template<> template<>
+	void object::test<11>()
+	{
+		//
+		// test LLUrlEntryHTTPNoProtocol - general URLs without a protocol
+		//
+		LLUrlEntryHTTPNoProtocol url;
+		boost::regex r = url.getPattern();
+
+		testRegex("naked .com URL", r,
+				  "see google.com",
+				  "google.com");
+
+		testRegex("naked .org URL", r,
+				  "see en.wikipedia.org for details",
+				  "en.wikipedia.org");
+
+		testRegex("naked .net URL", r,
+				  "example.net",
+				  "example.net");
+
+		testRegex("naked .edu URL (2 instances)", r,
+				  "MIT web site is at web.mit.edu and also www.mit.edu",
+				  "web.mit.edu");
+
+		testRegex("invalid .com URL [1]", r,
+				  "..com",
+				  "");
+
+		testRegex("invalid .com URL [2]", r,
+				  "you.come",
+				  "");
+
+		testRegex("invalid .com URL [3]", r,
+				  "recommended",
+				  "");
+
+		testRegex("invalid .edu URL", r,
+				  "hi there scheduled maitenance has begun",
+				  "");
+
+		testRegex("invalid .net URL", r,
+				  "foo.netty",
+				  "");
+	}
 }
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 8918fc301893315dc178ac5868a64052f2c2bc87..62cb8380c08ab49a9667fcde2c37443ae68a56e3 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -63,8 +63,6 @@ include_directories(
     )
 
 set(viewer_SOURCE_FILES
-    llaccordionctrl.cpp
-    llaccordionctrltab.cpp
     llagent.cpp
     llagentaccess.cpp
     llagentdata.cpp
@@ -569,8 +567,6 @@ endif (LINUX)
 set(viewer_HEADER_FILES
     CMakeLists.txt
     ViewerInstall.cmake
-    llaccordionctrl.h
-    llaccordionctrltab.h
     llagent.h
     llagentaccess.h
     llagentdata.h
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index f49f8620455061fb783ce9d54a5c7517c1f4f54a..10a2dd132ad965ddc812d0be00dfd1425732fa4f 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -95,19 +95,38 @@ public:
 	enum ELibraryOutfitFetchStep {
 		LOFS_FOLDER = 0,
 		LOFS_OUTFITS,
+		LOFS_LIBRARY,
+		LOFS_IMPORTED,
 		LOFS_CONTENTS
 	};
-	LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) {}
+	LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) 
+	{
+		mMyOutfitsID = LLUUID::null;
+		mClothingID = LLUUID::null;
+		mLibraryClothingID = LLUUID::null;
+		mImportedClothingID = LLUUID::null;
+		mImportedClothingName = "Imported Library Clothing";
+	}
 	~LLLibraryOutfitsFetch() {}
-	virtual void done();	
+	virtual void done();
 	void doneIdle();
+	LLUUID mMyOutfitsID;
+	void importedFolderFetch();
 protected:
 	void folderDone(void);
 	void outfitsDone(void);
+	void libraryDone(void);
+	void importedFolderDone(void);
 	void contentsDone(void);
 	enum ELibraryOutfitFetchStep mCurrFetchStep;
-	std::vector< std::pair< LLUUID, std::string > > mOutfits;
+	typedef std::vector< std::pair< LLUUID, std::string > > cloth_folder_vec_t;
+	cloth_folder_vec_t mLibraryClothingFolders;
+	cloth_folder_vec_t mImportedClothingFolders;
 	bool mOutfitsPopulated;
+	LLUUID mClothingID;
+	LLUUID mLibraryClothingID;
+	LLUUID mImportedClothingID;
+	std::string mImportedClothingName;
 };
 
 LLAgentWearables gAgentWearables;
@@ -2126,11 +2145,15 @@ void LLAgentWearables::populateMyOutfitsFolder(void)
 	// Get the complete information on the items in the inventory and 
 	// setup an observer that will wait for that to happen.
 	LLInventoryFetchDescendentsObserver::folder_ref_t folders;
-	const LLUUID my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+	outfits->mMyOutfitsID = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
 
-	folders.push_back(my_outfits_id);
+	folders.push_back(outfits->mMyOutfitsID);
 	gInventory.addObserver(outfits);
 	outfits->fetchDescendents(folders);
+	if (outfits->isEverythingComplete())
+	{
+		outfits->done();
+	}
 }
 
 void LLLibraryOutfitsFetch::done()
@@ -2144,13 +2167,24 @@ void LLLibraryOutfitsFetch::done()
 void LLLibraryOutfitsFetch::doneIdle()
 {
 	gInventory.addObserver(this); // Add this back in since it was taken out during ::done()
+	
 	switch (mCurrFetchStep)
 	{
 		case LOFS_FOLDER:
 			folderDone();
+			mCurrFetchStep = LOFS_OUTFITS;
 			break;
 		case LOFS_OUTFITS:
 			outfitsDone();
+			mCurrFetchStep = LOFS_LIBRARY;
+			break;
+		case LOFS_LIBRARY:
+			libraryDone();
+			mCurrFetchStep = LOFS_IMPORTED;
+			break;
+		case LOFS_IMPORTED:
+			importedFolderDone();
+			mCurrFetchStep = LOFS_CONTENTS;
 			break;
 		case LOFS_CONTENTS:
 			contentsDone();
@@ -2172,67 +2206,217 @@ void LLLibraryOutfitsFetch::doneIdle()
 
 void LLLibraryOutfitsFetch::folderDone(void)
 {
-	// Early out if we already have items in My Outfits.
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t wearable_array;
-	gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, 
+	gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array, 
 								  LLInventoryModel::EXCLUDE_TRASH);
+	
+	// Early out if we already have items in My Outfits.
 	if (cat_array.count() > 0 || wearable_array.count() > 0)
 	{
 		mOutfitsPopulated = true;
 		return;
 	}
 	
-	// Get the UUID of the library's clothing folder
-	const LLUUID library_clothing_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true);
+	mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
+	mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true);
 	
 	mCompleteFolders.clear();
 	
 	// Get the complete information on the items in the inventory.
 	LLInventoryFetchDescendentsObserver::folder_ref_t folders;
-	folders.push_back(library_clothing_id);
-	mCurrFetchStep = LOFS_OUTFITS;
+	folders.push_back(mClothingID);
+	folders.push_back(mLibraryClothingID);
 	fetchDescendents(folders);
+	if (isEverythingComplete())
+	{
+		done();
+	}
 }
 
 void LLLibraryOutfitsFetch::outfitsDone(void)
 {
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t wearable_array;
-	gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, 
-								  LLInventoryModel::EXCLUDE_TRASH);
-	
 	LLInventoryFetchDescendentsObserver::folder_ref_t folders;
 	
+	// Collect the contents of the Library's Clothing folder
+	gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array, 
+								  LLInventoryModel::EXCLUDE_TRASH);
+	
 	llassert(cat_array.count() > 0);
 	for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
 		 iter != cat_array.end();
 		 ++iter)
 	{
 		const LLViewerInventoryCategory *cat = iter->get();
+		
+		// Get the names and id's of every outfit in the library, except for ruth and other "misc" outfits.
 		if (cat->getName() != "More Outfits" && cat->getName() != "Ruth")
 		{
+			// Get the name of every outfit in the library 
 			folders.push_back(cat->getUUID());
-			mOutfits.push_back(std::make_pair(cat->getUUID(), cat->getName()));
+			mLibraryClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName()));
+		}
+	}
+	
+	// Collect the contents of your Inventory Clothing folder
+	cat_array.clear();
+	wearable_array.clear();
+	gInventory.collectDescendents(mClothingID, cat_array, wearable_array, 
+								  LLInventoryModel::EXCLUDE_TRASH);
+
+	// Check if you already have an "Imported Library Clothing" folder
+	for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
+		 iter != cat_array.end();
+		 ++iter)
+	{
+		const LLViewerInventoryCategory *cat = iter->get();
+		if (cat->getName() == mImportedClothingName)
+		{
+			mImportedClothingID = cat->getUUID();
 		}
 	}
+	
 	mCompleteFolders.clear();
+	
+	fetchDescendents(folders);
+	if (isEverythingComplete())
+	{
+		done();
+	}
+}
+
+class LLLibraryOutfitsCopyDone: public LLInventoryCallback
+{
+public:
+	LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher):
+	mFireCount(0), mLibraryOutfitsFetcher(fetcher)
+	{
+	}
+	
+	virtual ~LLLibraryOutfitsCopyDone()
+	{
+		if (mLibraryOutfitsFetcher)
+		{
+			gInventory.addObserver(mLibraryOutfitsFetcher);
+			mLibraryOutfitsFetcher->done();
+		}
+	}
+	
+	/* virtual */ void fire(const LLUUID& inv_item)
+	{
+		mFireCount++;
+	}
+private:
+	U32 mFireCount;
+	LLLibraryOutfitsFetch * mLibraryOutfitsFetcher;
+};
 
-	mCurrFetchStep = LOFS_CONTENTS;
+void LLLibraryOutfitsFetch::libraryDone(void)
+{
+	// Copy the clothing folders from the library into the imported clothing folder if necessary.
+	if (mImportedClothingID == LLUUID::null)
+	{
+		gInventory.removeObserver(this);
+		LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this);
+		mImportedClothingID = gInventory.createNewCategory(mClothingID,
+														   LLFolderType::FT_NONE,
+														   mImportedClothingName);
+		
+		for (cloth_folder_vec_t::const_iterator iter = mLibraryClothingFolders.begin();
+			 iter != mLibraryClothingFolders.end();
+			 ++iter)
+		{
+			LLUUID folder_id = gInventory.createNewCategory(mImportedClothingID,
+															LLFolderType::FT_NONE,
+															iter->second);
+			LLAppearanceManager::getInstance()->shallowCopyCategory(iter->first, folder_id, copy_waiter);
+		}
+	}
+	else
+	{
+		// Skip straight to fetching the contents of the imported folder
+		importedFolderFetch();
+	}
+}
+
+void LLLibraryOutfitsFetch::importedFolderFetch(void)
+{
+	// Fetch the contents of the Imported Clothing Folder
+	LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+	folders.push_back(mImportedClothingID);
+	
+	mCompleteFolders.clear();
+	
 	fetchDescendents(folders);
+	if (isEverythingComplete())
+	{
+		done();
+	}
 }
 
-void LLLibraryOutfitsFetch::contentsDone(void)
+void LLLibraryOutfitsFetch::importedFolderDone(void)
 {
-	for(S32 i = 0; i < (S32)mOutfits.size(); ++i)
+	LLInventoryModel::cat_array_t cat_array;
+	LLInventoryModel::item_array_t wearable_array;
+	LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+	
+	// Collect the contents of the Imported Clothing folder
+	gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array, 
+								  LLInventoryModel::EXCLUDE_TRASH);
+	
+	for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
+		 iter != cat_array.end();
+		 ++iter)
+	{
+		const LLViewerInventoryCategory *cat = iter->get();
+		
+		// Get the name of every imported outfit
+		folders.push_back(cat->getUUID());
+		mImportedClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName()));
+	}
+	
+	mCompleteFolders.clear();
+	fetchDescendents(folders);
+	if (isEverythingComplete())
+	{
+		done();
+	}
+}
+
+void LLLibraryOutfitsFetch::contentsDone(void)
+{		
+	LLInventoryModel::cat_array_t cat_array;
+	LLInventoryModel::item_array_t wearable_array;
+	
+	for (cloth_folder_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin();
+		 folder_iter != mImportedClothingFolders.end();
+		 ++folder_iter)
 	{
 		// First, make a folder in the My Outfits directory.
-		const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-		LLUUID folder_id = gInventory.createNewCategory(parent_id,
-														LLFolderType::FT_OUTFIT,
-														mOutfits[i].second);
-		LLAppearanceManager::getInstance()->shallowCopyCategory(mOutfits[i].first, folder_id, NULL);
+		LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, folder_iter->second);
+		
+		cat_array.clear();
+		wearable_array.clear();
+		// Collect the contents of each imported clothing folder, so we can create new outfit links for it
+		gInventory.collectDescendents(folder_iter->first, cat_array, wearable_array, 
+									  LLInventoryModel::EXCLUDE_TRASH);
+		
+		for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin();
+			 wearable_iter != wearable_array.end();
+			 ++wearable_iter)
+		{
+			const LLViewerInventoryItem *item = wearable_iter->get();
+			link_inventory_item(gAgent.getID(),
+								item->getLinkedUUID(),
+								new_outfit_folder_id,
+								item->getName(),
+								LLAssetType::AT_LINK,
+								NULL);
+		}
 	}
+
 	mOutfitsPopulated = true;
 }
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e0356bc091af11c9f975a1d4e7303ef05068fcc3..fb1bded7959638c978ff5595d2f1a7c243066b3a 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -313,6 +313,7 @@ void init_default_trans_args()
 {
 	default_trans_args.insert("SECOND_LIFE"); // World
 	default_trans_args.insert("APP_NAME");
+	default_trans_args.insert("CAPITALIZED_APP_NAME");
 	default_trans_args.insert("SECOND_LIFE_GRID");
 	default_trans_args.insert("SUPPORT_SITE");
 }
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index dac328057527d6c041a3f1ffd96c6f8b12f22689..cda3e3a4191c6e6eb80ef9ded69ffc2c82b1a752 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -576,10 +576,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_
 		style_params.font.style = "ITALIC";
 
 		if (chat.mFromName.size() > 0)
-			mEditor->appendText(chat.mFromName + " ", TRUE, style_params);
+			mEditor->appendText(chat.mFromName, TRUE, style_params);
 		// Ensure that message ends with NewLine, to avoid losing of new lines
 		// while copy/paste from text chat. See EXT-3263.
-		mEditor->appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params);
+		mEditor->appendText(chat.mText.substr(3) + NEW_LINE, FALSE, style_params);
 	}
 	else
 	{
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index 60a37ac4af96f923a6b3067ff72980b72542d2b8..9ce3f29853a9a7df264039eb1edba2911c350a65 100644
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -170,10 +170,7 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
 
 	std::string str_sender;
 	
-	if(gAgentID != mFromID)
-		str_sender = fromName;
-	else
-		str_sender = LLTrans::getString("You");
+	str_sender = fromName;
 
 	str_sender+=" ";
 
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 3042fbc6ec16dad5ad5aa8b1c1d50c78825ecc55..0964ad7f917cc88ea10eac2abce6a965f378534c 100644
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -64,6 +64,8 @@
 // summary which only shows available & correct information
 #define USE_SIMPLE_SUMMARY
 
+const S32 SIZE_OF_ONE_KB = 1024;
+
 LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed)
 	: LLFloater(seed)
 {
@@ -130,7 +132,6 @@ void LLFloaterScriptLimits::refresh()
 	}
 }
 
-
 ///----------------------------------------------------------------------------
 // Base class for panels
 ///----------------------------------------------------------------------------
@@ -331,6 +332,57 @@ void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::stri
 	llerrs << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
 }
 
+// callback from the name cache with an owner name to add to the list
+void LLPanelScriptLimitsRegionMemory::onNameCache(
+						 const LLUUID& id,
+						 const std::string& first_name,
+						 const std::string& last_name)
+{
+	std::string name = first_name + " " + last_name;
+
+	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");	
+	std::vector<LLSD>::iterator id_itor;
+	for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
+	{
+		LLSD element = *id_itor;
+		if(element["owner_id"].asUUID() == id)
+		{
+			LLScrollListItem* item = list->getItem(element["id"].asUUID());
+
+			if(item)
+			{
+				item->getColumn(2)->setValue(LLSD(name));
+				element["columns"][2]["value"] = name;
+			}
+		}
+	}
+
+	// fill in the url's tab if needed, all urls must have memory so we can do it all here
+	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+	if(instance)
+	{
+		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+		LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+
+		LLScrollListCtrl *list = panel->getChild<LLScrollListCtrl>("scripts_list");	
+		std::vector<LLSD>::iterator id_itor;
+		for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
+		{
+			LLSD element = *id_itor;
+			if(element["owner_id"].asUUID() == id)
+			{
+				LLScrollListItem* item = list->getItem(element["id"].asUUID());
+
+				if(item)
+				{
+					item->getColumn(2)->setValue(LLSD(name));
+					element["columns"][2]["value"] = name;
+				}
+			}
+		}
+	}
+}
+
 void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
 {
 	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
@@ -345,22 +397,40 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
 	S32 total_objects = 0;
 	S32 total_size = 0;
 
+	std::vector<LLUUID> names_requested;
+
 	for(S32 i = 0; i < number_parcels; i++)
 	{
 		std::string parcel_name = content["parcels"][i]["name"].asString();
-		
+		LLUUID parcel_id = content["parcels"][i]["id"].asUUID();
 		S32 number_objects = content["parcels"][i]["objects"].size();
 		for(S32 j = 0; j < number_objects; j++)
 		{
-			S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / 1024;
+			S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB;
 			total_size += size;
 			
 			std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
 			LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
+			LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID();
+			
+			std::string owner_buf;
+			
+			BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf);
+			if(!name_is_cached)
+			{
+				if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end())
+				{
+					names_requested.push_back(owner_id);
+					gCacheName->get(owner_id, TRUE,
+					boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache,
+						this, _1, _2, _3));
+				}
+			}
 
 			LLSD element;
 
 			element["id"] = task_id;
+			element["owner_id"] = owner_id;
 			element["columns"][0]["column"] = "size";
 			element["columns"][0]["value"] = llformat("%d", size);
 			element["columns"][0]["font"] = "SANSSERIF";
@@ -368,18 +438,18 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
 			element["columns"][1]["value"] = name_buf;
 			element["columns"][1]["font"] = "SANSSERIF";
 			element["columns"][2]["column"] = "owner";
-			element["columns"][2]["value"] = "";
+			element["columns"][2]["value"] = owner_buf;
 			element["columns"][2]["font"] = "SANSSERIF";
 			element["columns"][3]["column"] = "location";
 			element["columns"][3]["value"] = parcel_name;
 			element["columns"][3]["font"] = "SANSSERIF";
 
-			list->addElement(element);
-			mObjectListIDs.push_back(task_id);
+			list->addElement(element, ADD_SORTED);
+			mObjectListItems.push_back(element);
 			total_objects++;
 		}
 	}
-	
+
 	mParcelMemoryUsed =total_size;
 	mGotParcelMemoryUsed = TRUE;
 	populateParcelMemoryText();
@@ -556,7 +626,7 @@ void LLPanelScriptLimitsRegionMemory::clearList()
 	childSetValue("memory_used", LLSD(msg_empty_string));
 	childSetValue("parcels_listed", LLSD(msg_empty_string));
 
-	mObjectListIDs.clear();
+	mObjectListItems.clear();
 }
 
 // static
@@ -728,7 +798,7 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content)
 
 	S32 total_objects = 0;
 	S32 total_size = 0;
-
+	
 	for(S32 i = 0; i < number_parcels; i++)
 	{
 		std::string parcel_name = content["parcels"][i]["name"].asString();
@@ -744,6 +814,10 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content)
 				
 				std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
 				LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
+				LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID();
+
+				std::string owner_buf;
+				gCacheName->getFullName(owner_id, owner_buf); //dont care if this fails as the memory tab will request and fill the field
 
 				LLSD element;
 
@@ -755,14 +829,14 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content)
 				element["columns"][1]["value"] = name_buf;
 				element["columns"][1]["font"] = "SANSSERIF";
 				element["columns"][2]["column"] = "owner";
-				element["columns"][2]["value"] = "";
+				element["columns"][2]["value"] = owner_buf;
 				element["columns"][2]["font"] = "SANSSERIF";
 				element["columns"][3]["column"] = "location";
 				element["columns"][3]["value"] = parcel_name;
 				element["columns"][3]["font"] = "SANSSERIF";
 
 				list->addElement(element);
-				mObjectListIDs.push_back(task_id);
+				mObjectListItems.push_back(element);
 				total_objects++;
 			}
 		}
@@ -868,7 +942,7 @@ void LLPanelScriptLimitsRegionURLs::clearList()
 	childSetValue("urls_used", LLSD(msg_empty_string));
 	childSetValue("parcels_listed", LLSD(msg_empty_string));
 
-	mObjectListIDs.clear();
+	mObjectListItems.clear();
 }
 
 // static
@@ -982,7 +1056,7 @@ void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content)
 			S32 size = 0;
 			if(content["attachments"][i]["objects"][j]["resources"].has("memory"))
 			{
-				size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger();
+				size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB;
 			}
 			S32 urls = 0;
 			if(content["attachments"][i]["objects"][j]["resources"].has("urls"))
@@ -1059,3 +1133,4 @@ void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
 		return;
 	}
 }
+
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
index 88239136e3738e9fd5b59af209cc6c4b13149c93..7e2b536eb6b15aacf2740b0f20dc9df4852d473b 100644
--- a/indra/newview/llfloaterscriptlimits.h
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -54,12 +54,12 @@ public:
 
 	// from LLPanel
 	virtual void refresh();
-	
+
 private:
-	
+
 	LLFloaterScriptLimits(const LLSD& seed);
 	~LLFloaterScriptLimits();
-	
+
 protected:
 
 	LLTabContainer* mTab;
@@ -167,13 +167,17 @@ public:
 
 private:
 
+	void onNameCache(	 const LLUUID& id,
+						 const std::string& first_name,
+						 const std::string& last_name);
+
 	LLUUID mParcelId;
 	BOOL mGotParcelMemoryUsed;
 	BOOL mGotParcelMemoryMax;
 	S32 mParcelMemoryMax;
 	S32 mParcelMemoryUsed;
 	
-	std::vector<LLUUID> mObjectListIDs;
+	std::vector<LLSD> mObjectListItems;
 		
 protected:
 
@@ -218,7 +222,7 @@ private:
 	S32 mParcelURLsMax;
 	S32 mParcelURLsUsed;
 	
-	std::vector<LLUUID> mObjectListIDs;
+	std::vector<LLSD> mObjectListItems;
 		
 protected:
 	
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index c6d9fee6305aeaa54e72daac0c07eab6e32806bb..a7401fdb6f26f4ebd3c670917a08b8a5e1b39722 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -32,6 +32,9 @@
  */
 
 #include "llviewerprecompiledheaders.h"
+
+#include "llcommandhandler.h"
+#include "llfloaterreg.h"
 #include "llfloatersearch.h"
 #include "llmediactrl.h"
 #include "lllogininstance.h"
@@ -41,6 +44,42 @@
 #include "llviewercontrol.h"
 #include "llweb.h"
 
+// support secondlife:///app/search/{CATEGORY}/{QUERY} SLapps
+class LLSearchHandler : public LLCommandHandler
+{
+public:
+	// requires trusted browser to trigger
+	LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { }
+	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
+	{
+		const size_t parts = tokens.size();
+
+		// get the (optional) category for the search
+		std::string category;
+		if (parts > 0)
+		{
+			category = tokens[0].asString();
+		}
+
+		// get the (optional) search string
+		std::string search_text;
+		if (parts > 1)
+		{
+			search_text = tokens[1].asString();
+		}
+
+		// create the LLSD arguments for the search floater
+		LLSD args;
+		args["category"] = category;
+		args["id"] = LLURI::unescape(search_text);
+
+		// open the search floater and perform the requested search
+		LLFloaterReg::showInstance("search", args);
+		return true;
+	}
+};
+LLSearchHandler gSearchHandler;
+
 LLFloaterSearch::LLFloaterSearch(const LLSD& key) :
 	LLFloater(key),
 	LLViewerMediaObserver(),
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 41f4d1a663ccd6b3fc03ecd6b1a36b6f535cb2fa..1ea5868491ed80fcb71a9a3a6caa84ad00aa3af2 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -820,10 +820,11 @@ void LLFolderView::clearSelection()
 	mSelectThisID.setNull();
 }
 
-BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection)
+BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection) const
 {
-	selected_items_t::iterator item_it;
-	for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
+	for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); 
+		 item_it != mSelectedItems.end(); 
+		 ++item_it)
 	{
 		selection.insert((*item_it)->getListener()->getUUID());
 	}
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 2598af4df4bc954fe20b242b14ce032b9fbd4c6c..89e1865e3539451703ca16c7f393c2e038123753 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -162,7 +162,7 @@ public:
 
 	virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items);
 
-	virtual BOOL getSelectionList(std::set<LLUUID> &selection);
+	virtual BOOL getSelectionList(std::set<LLUUID> &selection) const;
 
 	// make sure if ancestor is selected, descendents are not
 	void sanitizeSelection();
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 6f8c738a59694c2ece01d71ace288b728a0f8ba5..03bb296d29a21ee0206b93c4e3122fd0b8766fbe 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -237,7 +237,7 @@ public:
 	virtual void recursiveDeselect(BOOL deselect_self);
 
 	// gets multiple-element selection
-	virtual BOOL getSelectionList(std::set<LLUUID> &selection){return TRUE;}
+	virtual BOOL getSelectionList(std::set<LLUUID> &selection) const {return TRUE;}
 
 	// Returns true is this object and all of its children can be removed (deleted by user)
 	virtual BOOL isRemovable();
@@ -304,7 +304,7 @@ public:
 	// Show children (unfortunate that this is called "open")
 	virtual void setOpen(BOOL open = TRUE) {};
 
-	virtual BOOL isOpen() { return FALSE; }
+	virtual BOOL isOpen() const { return FALSE; }
 
 	virtual LLFolderView*	getRoot();
 	BOOL			isDescendantOf( const LLFolderViewFolder* potential_ancestor );
@@ -499,7 +499,7 @@ public:
 	virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO);
 
 	// Get the current state of the folder.
-	virtual BOOL isOpen() { return mIsOpen; }
+	virtual BOOL isOpen() const { return mIsOpen; }
 
 	// special case if an object is dropped on the child.
 	BOOL handleDragAndDropFromChild(MASK mask,
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index fdc5d14d9763cb94b273ce4afa58b2861b99bb22..b05568f353f07dd9fd966785e9b26bc103aec941 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -595,7 +595,7 @@ void LLIMFloater::updateMessages()
 
 			std::string time = msg["time"].asString();
 			LLUUID from_id = msg["from_id"].asUUID();
-			std::string from = from_id != gAgentID ? msg["from"].asString() : LLTrans::getString("You");
+			std::string from = msg["from"].asString();
 			std::string message = msg["message"].asString();
 
 			LLChat chat;
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 72994a4371e95aea4f66bd5d5cf003361a2ed723..a2b3a54f51f80f920705557a5d812acf8106d18c 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -278,7 +278,7 @@ void LLInspectAvatar::onOpen(const LLSD& data)
 	
 	getChild<LLUICtrl>("gear_self_btn")->setVisible(self);
 	getChild<LLUICtrl>("gear_btn")->setVisible(!self);
-	
+
 	// Position the inspector relative to the mouse cursor
 	// Similar to how tooltips are positioned
 	// See LLToolTipMgr::createToolTip
@@ -518,13 +518,17 @@ void LLInspectAvatar::updateVolumeSlider()
 	bool is_muted = LLMuteList::getInstance()->
 						isMuted(mAvatarID, LLMute::flagVoiceChat);
 	bool voice_enabled = gVoiceClient->getVoiceEnabled(mAvatarID);
+	bool is_self = (mAvatarID == gAgent.getID());
 
 	LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn");
 	mute_btn->setEnabled( voice_enabled );
 	mute_btn->setValue( is_muted );
+	mute_btn->setVisible( voice_enabled && !is_self );
 
 	LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider");
 	volume_slider->setEnabled( voice_enabled && !is_muted );
+	volume_slider->setVisible( voice_enabled && !is_self );
+
 	const F32 DEFAULT_VOLUME = 0.5f;
 	F32 volume;
 	if (is_muted)
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 2a395d79dcdd990a09ae69c3180ac30c9a2b68e1..20d7f5214bec3472ac0a37e09e1a6b9d79f55462 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2074,7 +2074,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
 {
 	if ("open" == action)
 	{
-		openItem();
+		LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(folder->getItemByID(mUUID));
+		if (f)
+		{
+			f->setOpen(TRUE);
+		}
+		
 		return;
 	}
 	else if ("paste" == action)
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index fc9654e9adbe3999f5ec1ef8510ac9c1e464f5d5..92f19c9232e3029d0cc30987aaa9594f8536280a 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -59,9 +59,6 @@ const static std::string NEW_LINE_SPACE_PREFIX("\n ");
 const static std::string TWO_SPACES("  ");
 const static std::string MULTI_LINE_PREFIX(" ");
 
-//viewer 1.23 may have used "You" for Agent's entries
-const static std::string YOU("You");
-
 /**
  *  Chat log lines - timestamp and name are optional but message text is mandatory.
  *
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index e7043b2d00c742af4ba4ea94d7fce6f876d1cbef..fc0e51b76d1c082d0b16206257c9307d31f8e6de 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -178,7 +178,7 @@ void	LLNearbyChat::addMessage(const LLChat& chat,bool archive)
 	
 	if (!chat.mMuted)
 	{
-		tmp_chat.mFromName = chat.mFromID != gAgentID ? chat.mFromName : LLTrans::getString("You");
+		tmp_chat.mFromName = chat.mFromName;
 
 		if (chat.mChatStyle == CHAT_STYLE_IRC)
 		{
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index f3d6dbbb464cf0d1d3f01e196a1f6d857c3912df..fb898f7cdf6110826e6c0b23daad32d9efb35ab7 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -594,8 +594,8 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g
 		if (it != mGroups.begin())
 			groups += ", ";
 
-		
-		std::string group_url="[secondlife:///app/group/" + it->second.asString() + "/about " + it->first + "]";
+		std::string group_name = LLURI::escape(it->first);
+		std::string group_url="[secondlife:///app/group/" + it->second.asString() + "/about " + group_name + "]";
 		groups += group_url;
 	}
 
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index a1c12412b5ddf8e6ec5a9e4e8daca670cb7bf4e3..550fee71bf51dcd6505c185da94d9b2996c91bdf 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -181,6 +181,10 @@ void LLPanelOutfitsInventory::onNew()
 {
 	const std::string& outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT);
 	LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name);
+	if (mAppearanceTabs)
+	{
+		mAppearanceTabs->selectTabByName("outfitslist_tab");
+	}
 }
 
 void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
@@ -412,8 +416,7 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
 		return (getCorrectListenerForAction() != NULL) && hasItemsSelected();
 	}
 	
-	if (command_name == "wear" ||
-		command_name == "make_outfit")
+	if (command_name == "wear")
 	{
 		const BOOL is_my_outfits = (mActivePanel->getName() == "outfitslist_tab");
 		if (!is_my_outfits)
@@ -421,6 +424,10 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
 			return FALSE;
 		}
 	}
+	if (command_name == "make_outfit")
+	{
+		return TRUE;
+	}
    
 	if (command_name == "edit" || 
 		command_name == "add"
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 5e4dd8ff304a317017cce2094e0dd7b4a4c3ebfc..b103c48bd85a591f19de075548424847373823cc 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -123,7 +123,10 @@ class LLViewerMediaImpl
 {
 	LOG_CLASS(LLViewerMediaImpl);
 public:
-
+	
+	friend class LLViewerMedia;
+	friend class LLMimeDiscoveryResponder;
+	
 	LLViewerMediaImpl(
 		const LLUUID& texture_id,
 		S32 media_width, 
@@ -202,11 +205,15 @@ public:
 	bool isMediaPaused();
 	bool hasMedia() const;
 	bool isMediaFailed() const { return mMediaSourceFailed; };
+	void setMediaFailed(bool val) { mMediaSourceFailed = val; }
 	void resetPreviousMediaState();
 	
 	void setDisabled(bool disabled);
 	bool isMediaDisabled() const { return mIsDisabled; };
-
+	
+	void setInNearbyMediaList(bool in_list) { mInNearbyMediaList = in_list; }
+	bool getInNearbyMediaList() { return mInNearbyMediaList; }
+	
 	// returns true if this instance should not be loaded (disabled, muted object, crashed, etc.)
 	bool isForcedUnloaded() const;
 	
@@ -311,7 +318,7 @@ public:
 	void setNavState(EMediaNavState state);
 	
 	void cancelMimeTypeProbe();
-public:
+private:
 	// a single media url with some data and an impl.
 	LLPluginClassMedia* mMediaSource;
 	LLUUID mTextureId;
diff --git a/indra/newview/llviewerparcelmediaautoplay.cpp b/indra/newview/llviewerparcelmediaautoplay.cpp
index 1b79b4790551f5254c4028232352fcc40a767738..ad2723b66b242f2798ca9fcfeef40446ea6bfed6 100644
--- a/indra/newview/llviewerparcelmediaautoplay.cpp
+++ b/indra/newview/llviewerparcelmediaautoplay.cpp
@@ -35,6 +35,7 @@
 #include "llviewerparcelmedia.h"
 #include "llviewercontrol.h"
 #include "llviewermedia.h"
+#include "llviewerregion.h"
 #include "llparcel.h"
 #include "llviewerparcelmgr.h"
 #include "lluuid.h"
@@ -48,6 +49,8 @@ const F32 AUTOPLAY_SPEED = 0.1f;        // how slow should the agent be moving t
 
 LLViewerParcelMediaAutoPlay::LLViewerParcelMediaAutoPlay() :
 	LLEventTimer(1),
+	
+	mLastParcelID(-1),
 	mPlayed(FALSE),
 	mTimeInParcel(0)
 {
@@ -81,9 +84,18 @@ void LLViewerParcelMediaAutoPlay::playStarted()
 BOOL LLViewerParcelMediaAutoPlay::tick()
 {
 	LLParcel *this_parcel = NULL;
+	LLViewerRegion *this_region = NULL;
 	std::string this_media_url;
 	LLUUID this_media_texture_id;
 	S32 this_parcel_id = 0;
+	LLUUID this_region_id;
+
+	this_region = gAgent.getRegion();
+	
+	if (this_region)
+	{
+		this_region_id = this_region->getRegionID();
+	}
 
 	this_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
 
@@ -96,12 +108,14 @@ BOOL LLViewerParcelMediaAutoPlay::tick()
 		this_parcel_id = this_parcel->getLocalID();
 	}
 
-	if (this_parcel_id != mLastParcelID)
+	if (this_parcel_id != mLastParcelID ||
+	    this_region_id != mLastRegionID)
 	{
 		// we've entered a new parcel
 		mPlayed    = FALSE;                   // we haven't autoplayed yet
 		mTimeInParcel = 0;                    // reset our timer
 		mLastParcelID = this_parcel_id;
+		mLastRegionID = this_region_id;
 	}
 
 	mTimeInParcel += mPeriod;                 // increase mTimeInParcel by the amount of time between ticks
diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h
index 16279e7f1fc40f5df9fcc8b276d69f8960b7e45f..1d80b4756cad6e9b918703cdfb77d8d4c6260ae1 100644
--- a/indra/newview/llviewerparcelmediaautoplay.h
+++ b/indra/newview/llviewerparcelmediaautoplay.h
@@ -34,6 +34,7 @@
 #define LLVIEWERPARCELMEDIAAUTOPLAY_H
 
 #include "lltimer.h"
+#include "lluuid.h"
 
 // timer to automatically play media
 class LLViewerParcelMediaAutoPlay : LLEventTimer
@@ -47,6 +48,7 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer
 
  private:
 	S32 mLastParcelID;
+	LLUUID mLastRegionID;
 	BOOL mPlayed;
 	F32 mTimeInParcel;
 };
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index f825eaa8ab654e9312b39f0ae185747bc162a311..1edaeec848e914b0f8c402999a84023507e98d85 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -3007,7 +3007,7 @@ void LLViewerMediaTexture::addFace(LLFace* facep)
 	LLViewerTexture::addFace(facep) ;
 
 	const LLTextureEntry* te = facep->getTextureEntry() ;
-	if(te)
+	if(te && te->getID().notNull())
 	{
 		LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
 		if(tex)
@@ -3024,7 +3024,10 @@ void LLViewerMediaTexture::addFace(LLFace* facep)
 		return ;
 	}
 	
-	llerrs << "The face does not have a valid texture before media texture." << llendl ;
+	if(te && te->getID().notNull()) //should have a texture
+	{
+		llerrs << "The face does not have a valid texture before media texture." << llendl ;
+	}
 }
 
 //virtual 
@@ -3033,7 +3036,7 @@ void LLViewerMediaTexture::removeFace(LLFace* facep)
 	LLViewerTexture::removeFace(facep) ;
 
 	const LLTextureEntry* te = facep->getTextureEntry() ;
-	if(te)
+	if(te && te->getID().notNull())
 	{
 		LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
 		if(tex)
@@ -3094,7 +3097,10 @@ void LLViewerMediaTexture::removeFace(LLFace* facep)
 		}
 	}
 
-	llerrs << "mTextureList texture reference number is corrupted." << llendl ;
+	if(te && te->getID().notNull()) //should have a texture
+	{
+		llerrs << "mTextureList texture reference number is corrupted." << llendl ;
+	}
 }
 
 void LLViewerMediaTexture::stopPlaying()
@@ -3130,11 +3136,15 @@ void LLViewerMediaTexture::switchTexture(LLFace* facep)
 			const LLTextureEntry* te = facep->getTextureEntry() ;
 			if(te)
 			{
-				LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
+				LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ;
 				if(!tex && te->getID() != mID)//try parcel media.
 				{
 					tex = gTextureList.findImage(mID) ;
 				}
+				if(!tex)
+				{
+					tex = LLViewerFetchedTexture::sDefaultImagep ;
+				}
 				facep->switchTexture(tex) ;
 			}
 		}
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 55609621b3ac967bd94bc1f44ed8a6c16b27a084..d23bcf9006fbd64ded0e5a6f38428a4899e141b8 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1852,12 +1852,22 @@ void LLVOVolume::mediaNavigateBounceBack(U8 texture_index)
 	if (mep && impl)
 	{
         std::string url = mep->getCurrentURL();
-        if (url.empty())
+		// If the url we're trying to "bounce back" to is either empty or not
+		// allowed by the whitelist, try the home url.  If *that* doesn't work,
+		// set the media as failed and unload it
+        if (url.empty() || !mep->checkCandidateUrl(url))
         {
             url = mep->getHomeURL();
         }
-        if (! url.empty())
-        {
+        if (url.empty() || !mep->checkCandidateUrl(url))
+		{
+			// The url to navigate back to is not good, and we have nowhere else
+			// to go.
+			LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL;
+			impl->setMediaFailed(true);
+		}
+		else {
+			// Okay, navigate now
             LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL;
             impl->navigateTo(url, "", false, true);
         }
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 2ff99dcf5acfff1939d3bc55a05b551775f7667d..fac7aef690dbb5b037cca946b90b44f0994e4a3d 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -6,7 +6,7 @@
  name="floater_about"
  help_topic="floater_about"
  save_rect="true"
- title="ABOUT [APP_NAME]"
+ title="ABOUT [CAPITALIZED_APP_NAME]"
  width="470">
   <floater.string
      name="AboutHeader">
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
index 953bd08dd41ace4a534528f1de45ddd1e2099eec..f59badfcb4513c7d299d954e6417fc01d0956914 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
@@ -47,7 +47,7 @@
          label="Search"
          layout="topleft"
          left="6"
-         help_topic="avatarpicker_search_tab"
+         help_topic="avatarpicker"
          name="SearchPanel"
          top="150"
          width="132">
@@ -98,7 +98,7 @@
          label="Friends"
          layout="topleft"
          left="6"
-         help_topic="avatarpicker_friends_tab"
+         help_topic="avatarpicker"
          name="FriendsPanel"
          top="150"
          width="132">
@@ -144,7 +144,7 @@
          label="Near Me"
          layout="topleft"
          left="6"
-         help_topic="avatarpicker_near_me_tab"
+         help_topic="avatarpicker"
          name="NearMePanel"
          top="150"
          width="132">
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index a4ef807f069117e696f81d666fcbeb8883a939b2..b9649e9c577bcdd42d31015d466fb1d63f073e3b 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -8,6 +8,7 @@
  min_height="122"
  min_width="190"
  name="floater_voice_controls"
+ help_topic="floater_voice_controls"
  title="Voice Controls"
  save_visibility="true"
  single_instance="true"
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 690167bc33bab99f25dda03265682d8914dcff5c..a0dec346a4fd4eb5aea8bbfedb02aebe19a1727f 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -223,6 +223,7 @@
            parameter="test_inspectors" />
         </menu_item_call>
       </menu>
+<!--
       <menu_item_check
          label="Reg In Client Test (restart)"
          name="Reg In Client Test (restart)">
@@ -232,6 +233,7 @@
                function="ToggleControl"
                parameter="RegInClient" />
       </menu_item_check>
+-->
       <menu_item_separator />
       <menu_item_call
        label="Set Window Size..."
diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
index 970a2e6a8a5a7bf26a23e76e3871c704fe467aa2..003e1baa7ebcde478f9c677f93510ff8d6ae6fd8 100644
--- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
@@ -5,6 +5,7 @@
  height="305"
  layout="topleft"
  name="block_list_panel"
+ help_topic="blocked_list"
  min_height="350"
  min_width="240"
  width="280">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 447901f9842b656d6173f8d9b30b96789d4f7ac7..f2f23a3847dc2d6ab8c0b92e04a596d2ee94d793 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -8,6 +8,7 @@
 	<!-- Default Args - these arguments will be replaced in all strings -->
 	<string name="SECOND_LIFE">Second Life</string>
 	<string name="APP_NAME">Second Life</string>
+	<string name="CAPITALIZED_APP_NAME">SECOND LIFE</string>
 	<string name="SECOND_LIFE_GRID">Second Life Grid</string>
 	<string name="SUPPORT_SITE">Second Life Support Portal</string>