diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h
index 1a5678dde1340fc0c78d2d1d178418c7cf0214c1..e0565204d43dfec74324a2437abe23d2299d5e7f 100644
--- a/indra/llcommon/stdenums.h
+++ b/indra/llcommon/stdenums.h
@@ -119,8 +119,8 @@ enum EObjectPropertiesExtraID
 enum EAddPosition
 {
 	ADD_TOP,
-	ADD_SORTED,
-	ADD_BOTTOM
+	ADD_BOTTOM,
+	ADD_DEFAULT
 };
 
 enum LLGroupChange
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index d6c062fc5e0e924fca449204b352bff2ce9164c1..849318ccee992636240f48c919616dec09609209 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -983,37 +983,43 @@ LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
 //static
 LLFontGL* LLFontGL::getFontMonospace()
 {
-	return getFont(LLFontDescriptor("Monospace","Monospace",0));
+	static LLFontGL* fontp = getFont(LLFontDescriptor("Monospace","Monospace",0));
+	return fontp;
 }
 
 //static
 LLFontGL* LLFontGL::getFontSansSerifSmall()
 {
-	return getFont(LLFontDescriptor("SansSerif","Small",0));
+	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",0));
+	return fontp;
 }
 
 //static
 LLFontGL* LLFontGL::getFontSansSerif()
 {
-	return getFont(LLFontDescriptor("SansSerif","Medium",0));
+	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",0));
+	return fontp;
 }
 
 //static
 LLFontGL* LLFontGL::getFontSansSerifBig()
 {
-	return getFont(LLFontDescriptor("SansSerif","Large",0));
+	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
+	return fontp;
 }
 
 //static 
 LLFontGL* LLFontGL::getFontSansSerifHuge()
 {
-	return getFont(LLFontDescriptor("SansSerif","Huge",0));
+	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
+	return fontp;
 }
 
 //static 
 LLFontGL* LLFontGL::getFontSansSerifBold()
 {
-	return getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
+	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
+	return fontp;
 }
 
 //static
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 64238b2008d1c06687214a5e58e00162764fb2d2..eb2c54198d6a062ba5f10053b91d6a6e3c71ab0d 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -901,7 +901,7 @@ LLVector3 LLRender::getUITranslation()
 {
 	if (mUIOffset.empty())
 	{
-		llerrs << "UI offset stack empty." << llendl;
+		return LLVector3::zero;
 	}
 	return mUIOffset.back();
 }
@@ -910,7 +910,7 @@ LLVector3 LLRender::getUIScale()
 {
 	if (mUIScale.empty())
 	{
-		llerrs << "UI scale stack empty." << llendl;
+		return LLVector3(1.f, 1.f, 1.f);
 	}
 	return mUIScale.back();
 }
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index bb43c19c2c22dd9126247a7e8f8c1a43a3672033..d356f061f93ce12a6adad2588232f8f205125e24 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -543,23 +543,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
 			setNeedsSort();
 			break;
 	
-		case ADD_SORTED:
-			{
-				// sort by column 0, in ascending order
-				std::vector<sort_column_t> single_sort_column;
-				single_sort_column.push_back(std::make_pair(0, TRUE));
-
-				mItemList.push_back(item);
-				std::stable_sort(
-					mItemList.begin(), 
-					mItemList.end(), 
-					SortScrollListItem(single_sort_column,mSortCallback));
-				
-				// ADD_SORTED just sorts by first column...
-				// this might not match user sort criteria, so flag list as being in unsorted state
-				setNeedsSort();
-				break;
-			}	
+		case ADD_DEFAULT:
 		case ADD_BOTTOM:
 			mItemList.push_back(item);
 			setNeedsSort();
@@ -2770,9 +2754,10 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name)
 	return NULL;
 }
 
-
+LLFastTimer::DeclareTimer FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item");
 LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)
 {
+	LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
 	LLScrollListItem::Params item_params;
 	LLParamSDParser::instance().readSD(element, item_params);
 	item_params.userdata = userdata;
@@ -2781,12 +2766,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition
 
 LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos)
 {
+	LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
 	LLScrollListItem *new_item = new LLScrollListItem(item_p);
 	return addRow(new_item, item_p, pos);
 }
 
 LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos)
 {
+	LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
 	if (!item_p.validateBlock() || !new_item) return NULL;
 	new_item->setNumColumns(mColumns.size());
 
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
index 4bb45a3065fc7c745f3579e737219514e59d7612..7d37127584901977c4271661c3304f7612fb501e 100644
--- a/indra/llui/llsdparam.cpp
+++ b/indra/llui/llsdparam.cpp
@@ -43,33 +43,16 @@ LLParamSDParser::LLParamSDParser()
 {
 	using boost::bind;
 
-	registerParserFuncs<S32>(bind(&LLParamSDParser::readTypedValue<S32>, this, _1, &LLSD::asInteger),
-							bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2));
-	registerParserFuncs<U32>(bind(&LLParamSDParser::readTypedValue<U32>, this, _1, &LLSD::asInteger),
-							bind(&LLParamSDParser::writeU32Param, this, _1, _2));
-	registerParserFuncs<F32>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asReal),
-							bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
-	registerParserFuncs<F64>(bind(&LLParamSDParser::readTypedValue<F64>, this, _1, &LLSD::asReal),
-							bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2));
-	registerParserFuncs<bool>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asBoolean),
-							bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
-	registerParserFuncs<std::string>(bind(&LLParamSDParser::readTypedValue<std::string>, this, _1, &LLSD::asString),
-							bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2));
-	registerParserFuncs<LLUUID>(bind(&LLParamSDParser::readTypedValue<LLUUID>, this, _1, &LLSD::asUUID),
-							bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2));
-	registerParserFuncs<LLDate>(bind(&LLParamSDParser::readTypedValue<LLDate>, this, _1, &LLSD::asDate),
-							bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2));
-	registerParserFuncs<LLURI>(bind(&LLParamSDParser::readTypedValue<LLURI>, this, _1, &LLSD::asURI),
-							bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2));
-	registerParserFuncs<LLSD>(bind(&LLParamSDParser::readSDParam, this, _1),
-							bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2));
-}
-
-bool LLParamSDParser::readSDParam(void* value_ptr)
-{
-	if (!mCurReadSD) return false;
-	*((LLSD*)value_ptr) = *mCurReadSD;
-	return true;
+	registerParserFuncs<S32>(readS32, bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2));
+	registerParserFuncs<U32>(readU32, bind(&LLParamSDParser::writeU32Param, this, _1, _2));
+	registerParserFuncs<F32>(readF32, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
+	registerParserFuncs<F64>(readF64, bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2));
+	registerParserFuncs<bool>(readBool, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
+	registerParserFuncs<std::string>(readString, bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2));
+	registerParserFuncs<LLUUID>(readUUID, bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2));
+	registerParserFuncs<LLDate>(readDate, bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2));
+	registerParserFuncs<LLURI>(readURI, bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2));
+	registerParserFuncs<LLSD>(readSD, bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2));
 }
 
 // special case handling of U32 due to ambiguous LLSD::assign overload
@@ -148,3 +131,82 @@ LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack)
 	return mWriteSD;
 }
 
+bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((S32*)val_ptr) = self.mCurReadSD->asInteger();
+    return true;
+}
+
+bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((U32*)val_ptr) = self.mCurReadSD->asInteger();
+    return true;
+}
+
+bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((F32*)val_ptr) = self.mCurReadSD->asReal();
+    return true;
+}
+
+bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((F64*)val_ptr) = self.mCurReadSD->asReal();
+    return true;
+}
+
+bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((bool*)val_ptr) = self.mCurReadSD->asBoolean();
+    return true;
+}
+
+bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((std::string*)val_ptr) = self.mCurReadSD->asString();
+    return true;
+}
+
+bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
+    return true;
+}
+
+bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((LLDate*)val_ptr) = self.mCurReadSD->asDate();
+    return true;
+}
+
+bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((LLURI*)val_ptr) = self.mCurReadSD->asURI();
+    return true;
+}
+
+bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((LLSD*)val_ptr) = *self.mCurReadSD;
+    return true;
+}
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
index 12f28f876faa980bd12e9f475e72714130f6be1c..71b0a4563005dded1355fed1c91daa883e6288bf 100644
--- a/indra/llui/llsdparam.h
+++ b/indra/llui/llsdparam.h
@@ -79,9 +79,19 @@ typedef LLInitParam::Parser parser_t;
 
 	LLSD* getSDWriteNode(const parser_t::name_stack_t& name_stack);
 
-	bool readSDParam(void* value_ptr);
 	bool writeU32Param(const void* value_ptr, const parser_t::name_stack_t& name_stack);
 
+	static bool readS32(Parser& parser, void* val_ptr);
+	static bool readU32(Parser& parser, void* val_ptr);
+	static bool readF32(Parser& parser, void* val_ptr);
+	static bool readF64(Parser& parser, void* val_ptr);
+	static bool readBool(Parser& parser, void* val_ptr);
+	static bool readString(Parser& parser, void* val_ptr);
+	static bool readUUID(Parser& parser, void* val_ptr);
+	static bool readDate(Parser& parser, void* val_ptr);
+	static bool readURI(Parser& parser, void* val_ptr);
+	static bool readSD(Parser& parser, void* val_ptr);
+
 	Parser::name_stack_t	mNameStack;
 	const LLSD*				mCurReadSD;
 	LLSD*					mWriteSD;
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index a46d961709f9f98d41b2b6e18d07ee3ad7fe9501..c5bd6c7fce6c2c33b4e2b10183a5d7f0ffa3b757 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -99,10 +99,11 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa
 	std::string filename = std::string("widgets") + gDirUtilp->getDirDelimiter() + widget_tag + ".xml";
 	LLXMLNodePtr root_node;
 
-	if (LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
+	std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), filename);
+	if (!full_filename.empty())
 	{
-		LLUICtrlFactory::instance().pushFileName(filename);
-		LLXUIParser::instance().readXUI(root_node, block, filename);
+		LLUICtrlFactory::instance().pushFileName(full_filename);
+		LLSimpleXUIParser::instance().readXUI(full_filename, block);
 		LLUICtrlFactory::instance().popFileName();
 	}
 }
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index ac9e71665f5170aacc9ed4aa22b303896e27a100..e343df0063d85b41fe2d2875c1044dfe01354b96 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -40,7 +40,7 @@ LLFastTimer::DeclareTimer FTM_UI_STRING("UI String");
 
 LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args)
 :	mOrig(instring),
-	mArgs(args)
+	mArgs(new LLStringUtil::format_map_t(args))
 {
 	dirty();
 }
@@ -54,7 +54,7 @@ void LLUIString::assign(const std::string& s)
 void LLUIString::setArgList(const LLStringUtil::format_map_t& args)
 
 {
-	mArgs = args;
+	getArgs() = args;
 	dirty();
 }
 
@@ -74,7 +74,7 @@ void LLUIString::setArgs(const LLSD& sd)
 
 void LLUIString::setArg(const std::string& key, const std::string& replacement)
 {
-	mArgs[key] = replacement;
+	getArgs()[key] = replacement;
 	dirty();
 }
 
@@ -135,14 +135,14 @@ void LLUIString::updateResult() const
 	mResult = mOrig;
 	
 	// get the defailt args + local args
-	if (mArgs.empty())
+	if (!mArgs || mArgs->empty())
 	{
 		LLStringUtil::format(mResult, LLTrans::getDefaultArgs());
 	}
 	else
 	{
 		LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs();
-		combined_args.insert(mArgs.begin(), mArgs.end());
+		combined_args.insert(mArgs->begin(), mArgs->end());
 		LLStringUtil::format(mResult, combined_args);
 	}
 }
@@ -153,3 +153,12 @@ void LLUIString::updateWResult() const
 
 	mWResult = utf8str_to_wstring(getUpdatedResult());
 }
+
+LLStringUtil::format_map_t& LLUIString::getArgs()
+{
+	if (!mArgs)
+	{
+		mArgs = new LLStringUtil::format_map_t;
+	}
+	return *mArgs;
+}
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index 32cfc0d9cd708838cd670c1ab4af0f16c1fdca29..3f91856e261541e7a7fa10606abc5b729cb0f2ff 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -64,9 +64,9 @@ class LLUIString
 public:
 	// These methods all perform appropriate argument substitution
 	// and modify mOrig where appropriate
-        LLUIString() : mNeedsResult(false), mNeedsWResult(false) {}
+        LLUIString() : mArgs(NULL), mNeedsResult(false), mNeedsWResult(false) {}
 	LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args);
-	LLUIString(const std::string& instring) { assign(instring); }
+	LLUIString(const std::string& instring) : mArgs(NULL) { assign(instring); }
 
 	void assign(const std::string& instring);
 	LLUIString& operator=(const std::string& s) { assign(s); return *this; }
@@ -86,7 +86,7 @@ class LLUIString
 	S32 length() const { return getUpdatedWResult().size(); }
 
 	void clear();
-	void clearArgs() { mArgs.clear(); }
+	void clearArgs() { if (mArgs) mArgs->clear(); }
 	
 	// These utility functions are included for text editing.
 	// They do not affect mOrig and do not perform argument substitution
@@ -105,11 +105,12 @@ class LLUIString
 	// do actual work of updating strings (non-inlined)
 	void updateResult() const;
 	void updateWResult() const;
+	LLStringUtil::format_map_t& getArgs();
 	
 	std::string mOrig;
 	mutable std::string mResult;
 	mutable LLWString mWResult; // for displaying
-	LLStringUtil::format_map_t mArgs;
+	LLStringUtil::format_map_t* mArgs;
 
 	// controls lazy evaluation
 	mutable bool	mNeedsResult;
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index b645c4be7c80636926848906bcec52c9cfa8698c..9890bacea4f7bea1a49215014d2fd2ca2906ac65 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -40,6 +40,7 @@ f * @file llinitparam.h
 #include <boost/function.hpp>
 #include <boost/bind.hpp>
 #include <boost/type_traits/is_convertible.hpp>
+#include <boost/unordered_map.hpp>
 #include "llregistry.h"
 #include "llmemory.h"
 
@@ -202,7 +203,7 @@ namespace LLInitParam
 		typedef std::pair<name_stack_t::const_iterator, name_stack_t::const_iterator>	name_stack_range_t;
 		typedef std::vector<std::string>							possible_values_t;
 
-		typedef boost::function<bool (void*)>															parser_read_func_t;
+		typedef bool (*parser_read_func_t)(Parser& parser, void* output);
 		typedef boost::function<bool (const void*, const name_stack_t&)>								parser_write_func_t;
 		typedef boost::function<void (const name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
 
@@ -221,7 +222,7 @@ namespace LLInitParam
 		    parser_read_func_map_t::iterator found_it = mParserReadFuncs.find(&typeid(T));
 		    if (found_it != mParserReadFuncs.end())
 		    {
-			    return found_it->second((void*)&param);
+			    return found_it->second(*this, (void*)&param);
 		    }
 		    return false;
 	    }
@@ -386,7 +387,7 @@ namespace LLInitParam
 		void aggregateBlockData(BlockDescriptor& src_block_data);
 
 	public:
-		typedef std::map<const std::string, ParamDescriptor*> param_map_t; // references param descriptors stored in mAllParams
+		typedef boost::unordered_map<const std::string, ParamDescriptor*> param_map_t; // references param descriptors stored in mAllParams
 		typedef std::vector<ParamDescriptor*> param_list_t; 
 
 		typedef std::list<ParamDescriptor> all_params_list_t;// references param descriptors stored in mAllParams
diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp
index dbc20a5a1e2f79f0d487914776021ad8b9300cc1..d856efb008110a8e7a8d3ff2b81bc20c5ad5eee1 100644
--- a/indra/llxuixml/llxuiparser.cpp
+++ b/indra/llxuixml/llxuiparser.cpp
@@ -35,11 +35,16 @@
 #include "llxuiparser.h"
 
 #include "llxmlnode.h"
+#include "expat/expat.h"
 #include <fstream>
 #include <boost/tokenizer.hpp>
+//#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/classic_core.hpp>
 
 #include "lluicolor.h"
 
+using namespace BOOST_SPIRIT_CLASSIC_NS;
+
 const S32 MAX_STRING_ATTRIBUTE_SIZE = 40;
 
 //
@@ -370,34 +375,20 @@ LLXUIParser::LLXUIParser()
 :	mLastWriteGeneration(-1),
 	mCurReadDepth(0)
 {
-	registerParserFuncs<bool>(boost::bind(&LLXUIParser::readBoolValue, this, _1),
-								boost::bind(&LLXUIParser::writeBoolValue, this, _1, _2));
-	registerParserFuncs<std::string>(boost::bind(&LLXUIParser::readStringValue, this, _1),
-								boost::bind(&LLXUIParser::writeStringValue, this, _1, _2));
-	registerParserFuncs<U8>(boost::bind(&LLXUIParser::readU8Value, this, _1),
-								boost::bind(&LLXUIParser::writeU8Value, this, _1, _2));
-	registerParserFuncs<S8>(boost::bind(&LLXUIParser::readS8Value, this, _1),
-								boost::bind(&LLXUIParser::writeS8Value, this, _1, _2));
-	registerParserFuncs<U16>(boost::bind(&LLXUIParser::readU16Value, this, _1),
-								boost::bind(&LLXUIParser::writeU16Value, this, _1, _2));
-	registerParserFuncs<S16>(boost::bind(&LLXUIParser::readS16Value, this, _1),
-								boost::bind(&LLXUIParser::writeS16Value, this, _1, _2));
-	registerParserFuncs<U32>(boost::bind(&LLXUIParser::readU32Value, this, _1),
-								boost::bind(&LLXUIParser::writeU32Value, this, _1, _2));
-	registerParserFuncs<S32>(boost::bind(&LLXUIParser::readS32Value, this, _1),
-								boost::bind(&LLXUIParser::writeS32Value, this, _1, _2));
-	registerParserFuncs<F32>(boost::bind(&LLXUIParser::readF32Value, this, _1),
-								boost::bind(&LLXUIParser::writeF32Value, this, _1, _2));
-	registerParserFuncs<F64>(boost::bind(&LLXUIParser::readF64Value, this, _1),
-								boost::bind(&LLXUIParser::writeF64Value, this, _1, _2));
-	registerParserFuncs<LLColor4>(boost::bind(&LLXUIParser::readColor4Value, this, _1),
-								boost::bind(&LLXUIParser::writeColor4Value, this, _1, _2));
-	registerParserFuncs<LLUIColor>(boost::bind(&LLXUIParser::readUIColorValue, this, _1),
-								boost::bind(&LLXUIParser::writeUIColorValue, this, _1, _2));
-	registerParserFuncs<LLUUID>(boost::bind(&LLXUIParser::readUUIDValue, this, _1),
-								boost::bind(&LLXUIParser::writeUUIDValue, this, _1, _2));
-	registerParserFuncs<LLSD>(boost::bind(&LLXUIParser::readSDValue, this, _1),
-								boost::bind(&LLXUIParser::writeSDValue, this, _1, _2));
+	registerParserFuncs<bool>(readBoolValue, boost::bind(&LLXUIParser::writeBoolValue, this, _1, _2));
+	registerParserFuncs<std::string>(readStringValue, boost::bind(&LLXUIParser::writeStringValue, this, _1, _2));
+	registerParserFuncs<U8>(readU8Value, boost::bind(&LLXUIParser::writeU8Value, this, _1, _2));
+	registerParserFuncs<S8>(readS8Value, boost::bind(&LLXUIParser::writeS8Value, this, _1, _2));
+	registerParserFuncs<U16>(readU16Value, boost::bind(&LLXUIParser::writeU16Value, this, _1, _2));
+	registerParserFuncs<S16>(readS16Value, boost::bind(&LLXUIParser::writeS16Value, this, _1, _2));
+	registerParserFuncs<U32>(readU32Value, boost::bind(&LLXUIParser::writeU32Value, this, _1, _2));
+	registerParserFuncs<S32>(readS32Value, boost::bind(&LLXUIParser::writeS32Value, this, _1, _2));
+	registerParserFuncs<F32>(readF32Value, boost::bind(&LLXUIParser::writeF32Value, this, _1, _2));
+	registerParserFuncs<F64>(readF64Value, boost::bind(&LLXUIParser::writeF64Value, this, _1, _2));
+	registerParserFuncs<LLColor4>(readColor4Value, boost::bind(&LLXUIParser::writeColor4Value, this, _1, _2));
+	registerParserFuncs<LLUIColor>(readUIColorValue, boost::bind(&LLXUIParser::writeUIColorValue, this, _1, _2));
+	registerParserFuncs<LLUUID>(readUUIDValue, boost::bind(&LLXUIParser::writeUUIDValue, this, _1, _2));
+	registerParserFuncs<LLSD>(readSDValue, boost::bind(&LLXUIParser::writeSDValue, this, _1, _2));
 }
 
 static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing");
@@ -621,10 +612,11 @@ LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack)
 }
 
 
-bool LLXUIParser::readBoolValue(void* val_ptr)
+bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr)
 {
 	S32 value;
-	bool success = mCurReadNode->getBoolValue(1, &value);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	bool success = self.mCurReadNode->getBoolValue(1, &value);
 	*((bool*)val_ptr) = (value != FALSE);
 	return success;
 }
@@ -640,9 +632,10 @@ bool LLXUIParser::writeBoolValue(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readStringValue(void* val_ptr)
+bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr)
 {
-	*((std::string*)val_ptr) = mCurReadNode->getSanitizedValue();
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	*((std::string*)val_ptr) = self.mCurReadNode->getSanitizedValue();
 	return true;
 }
 
@@ -677,9 +670,10 @@ bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stac
 	return false;
 }
 
-bool LLXUIParser::readU8Value(void* val_ptr)
+bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr)
 {
-	return mCurReadNode->getByteValue(1, (U8*)val_ptr);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getByteValue(1, (U8*)val_ptr);
 }
 
 bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack)
@@ -693,10 +687,11 @@ bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readS8Value(void* val_ptr)
+bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr)
 {
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	S32 value;
-	if(mCurReadNode->getIntValue(1, &value))
+	if(self.mCurReadNode->getIntValue(1, &value))
 	{
 		*((S8*)val_ptr) = value;
 		return true;
@@ -715,10 +710,11 @@ bool LLXUIParser::writeS8Value(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readU16Value(void* val_ptr)
+bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr)
 {
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	U32 value;
-	if(mCurReadNode->getUnsignedValue(1, &value))
+	if(self.mCurReadNode->getUnsignedValue(1, &value))
 	{
 		*((U16*)val_ptr) = value;
 		return true;
@@ -737,10 +733,11 @@ bool LLXUIParser::writeU16Value(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readS16Value(void* val_ptr)
+bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr)
 {
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	S32 value;
-	if(mCurReadNode->getIntValue(1, &value))
+	if(self.mCurReadNode->getIntValue(1, &value))
 	{
 		*((S16*)val_ptr) = value;
 		return true;
@@ -759,9 +756,10 @@ bool LLXUIParser::writeS16Value(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readU32Value(void* val_ptr)
+bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr)
 {
-	return mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
 }
 
 bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack)
@@ -775,9 +773,10 @@ bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readS32Value(void* val_ptr)
+bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr)
 {
-	return mCurReadNode->getIntValue(1, (S32*)val_ptr);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getIntValue(1, (S32*)val_ptr);
 }
 
 bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack)
@@ -791,9 +790,10 @@ bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readF32Value(void* val_ptr)
+bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr)
 {
-	return mCurReadNode->getFloatValue(1, (F32*)val_ptr);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr);
 }
 
 bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack)
@@ -807,9 +807,10 @@ bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readF64Value(void* val_ptr)
+bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr)
 {
-	return mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
 }
 
 bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack)
@@ -823,10 +824,11 @@ bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readColor4Value(void* val_ptr)
+bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)
 {
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLColor4* colorp = (LLColor4*)val_ptr;
-	if(mCurReadNode->getFloatValue(4, colorp->mV) >= 3)
+	if(self.mCurReadNode->getFloatValue(4, colorp->mV) >= 3)
 	{
 		return true;
 	}
@@ -846,11 +848,12 @@ bool LLXUIParser::writeColor4Value(const void* val_ptr, const name_stack_t& stac
 	return false;
 }
 
-bool LLXUIParser::readUIColorValue(void* val_ptr)
+bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
 {
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLUIColor* param = (LLUIColor*)val_ptr;
 	LLColor4 color;
-	bool success =  mCurReadNode->getFloatValue(4, color.mV) >= 3;
+	bool success =  self.mCurReadNode->getFloatValue(4, color.mV) >= 3;
 	if (success)
 	{
 		param->set(color);
@@ -874,11 +877,12 @@ bool LLXUIParser::writeUIColorValue(const void* val_ptr, const name_stack_t& sta
 	return false;
 }
 
-bool LLXUIParser::readUUIDValue(void* val_ptr)
+bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
 {
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLUUID temp_id;
 	// LLUUID::set is destructive, so use temporary value
-	if (temp_id.set(mCurReadNode->getSanitizedValue()))
+	if (temp_id.set(self.mCurReadNode->getSanitizedValue()))
 	{
 		*(LLUUID*)(val_ptr) = temp_id;
 		return true;
@@ -897,9 +901,10 @@ bool LLXUIParser::writeUUIDValue(const void* val_ptr, const name_stack_t& stack)
 	return false;
 }
 
-bool LLXUIParser::readSDValue(void* val_ptr)
+bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr)
 {
-	*((LLSD*)val_ptr) = LLSD(mCurReadNode->getSanitizedValue());
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	*((LLSD*)val_ptr) = LLSD(self.mCurReadNode->getSanitizedValue());
 	return true;
 }
 
@@ -968,3 +973,411 @@ void LLXUIParser::parserError(const std::string& message)
 	Parser::parserError(message);
 #endif
 }
+
+
+//
+// LLSimpleXUIParser
+//
+
+struct ScopedFile
+{
+	ScopedFile( const std::string& filename, const char* accessmode )
+	{
+		mFile = LLFile::fopen(filename, accessmode);
+	}
+
+	~ScopedFile()
+	{
+		fclose(mFile);
+		mFile = NULL;
+	}
+
+	S32 getRemainingBytes()
+	{
+		if (!isOpen()) return 0;
+
+		S32 cur_pos = ftell(mFile);
+		fseek(mFile, 0L, SEEK_END);
+		S32 file_size = ftell(mFile);
+		fseek(mFile, cur_pos, SEEK_SET);
+		return file_size - cur_pos;
+	}
+
+	bool isOpen() { return mFile != NULL; }
+
+	LLFILE* mFile;
+};
+
+LLSimpleXUIParser::LLSimpleXUIParser()
+:	mLastWriteGeneration(-1),
+	mCurReadDepth(0)
+{
+	registerParserFuncs<bool>(readBoolValue, NULL);
+	registerParserFuncs<std::string>(readStringValue, NULL);
+	registerParserFuncs<U8>(readU8Value, NULL);
+	registerParserFuncs<S8>(readS8Value, NULL);
+	registerParserFuncs<U16>(readU16Value, NULL);
+	registerParserFuncs<S16>(readS16Value, NULL);
+	registerParserFuncs<U32>(readU32Value, NULL);
+	registerParserFuncs<S32>(readS32Value, NULL);
+	registerParserFuncs<F32>(readF32Value, NULL);
+	registerParserFuncs<F64>(readF64Value, NULL);
+	registerParserFuncs<LLColor4>(readColor4Value, NULL);
+	registerParserFuncs<LLUIColor>(readUIColorValue, NULL);
+	registerParserFuncs<LLUUID>(readUUIDValue, NULL);
+	registerParserFuncs<LLSD>(readSDValue, NULL);
+}
+
+LLSimpleXUIParser::~LLSimpleXUIParser()
+{
+}
+
+
+bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent)
+{
+	LLFastTimer timer(FTM_PARSE_XUI);
+
+	mParser = XML_ParserCreate(NULL);
+	XML_SetUserData(mParser, this);
+	XML_SetElementHandler(			mParser,	startElementHandler, endElementHandler);
+	XML_SetCharacterDataHandler(	mParser,	characterDataHandler);
+
+	mBlock = &block;
+	mNameStack.clear();
+	mCurFileName = filename;
+	mCurReadDepth = 0;
+	setParseSilently(silent);
+
+	ScopedFile file(filename, "rb");
+	if( !file.isOpen() )
+	{
+		LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL;
+		return false;
+	}
+
+	S32 bytes_read = 0;
+	
+	S32 buffer_size = file.getRemainingBytes();
+	void* buffer = XML_GetBuffer(mParser, buffer_size);
+	if( !buffer ) 
+	{
+		LL_WARNS("ReadXUI") << "Unable to allocate XML buffer while reading file " << filename << LL_ENDL;
+		XML_ParserFree( mParser );
+		return false;
+	}
+
+	bytes_read = (S32)fread(buffer, 1, buffer_size, file.mFile);
+	if( bytes_read <= 0 )
+	{
+		LL_WARNS("ReadXUI") << "Error while reading file  " << filename << LL_ENDL;
+		XML_ParserFree( mParser );
+		return false;
+	}
+	
+	if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) )
+	{
+		LL_WARNS("ReadXUI") << "Error while parsing file  " << filename << LL_ENDL;
+		XML_ParserFree( mParser );
+		return false;
+	}
+
+	XML_ParserFree( mParser );
+	return true;
+}
+
+void LLSimpleXUIParser::startElementHandler(void *userData, const char *name, const char **atts)
+{
+	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
+	self->startElement(name, atts);
+}
+
+void LLSimpleXUIParser::endElementHandler(void *userData, const char *name)
+{
+	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
+	self->endElement(name);
+}
+
+void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int len)
+{
+	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
+	self->characterData(s, len);
+}
+
+void LLSimpleXUIParser::startElement(const char *name, const char **atts)
+{
+	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+	boost::char_separator<char> sep(".");
+
+	mCurReadDepth++;
+	S32 num_tokens_pushed = 0;
+	std::string child_name(name);
+
+	if (mCurReadDepth > 1)
+	{
+		// for non "dotted" child nodes	check to see if child node maps to another widget type
+		// and if not, treat as a child element of the current node
+		// e.g. <button><rect left="10"/></button> will interpret <rect> as "button.rect"
+		// since there is no widget named "rect"
+		if (child_name.find(".") == std::string::npos) 
+		{
+			mNameStack.push_back(std::make_pair(child_name, newParseGeneration()));
+			num_tokens_pushed++;
+			mScope.push_back(child_name);
+		}
+		else
+		{
+			// parse out "dotted" name into individual tokens
+			tokenizer name_tokens(child_name, sep);
+
+			tokenizer::iterator name_token_it = name_tokens.begin();
+			if(name_token_it == name_tokens.end()) 
+			{
+				return;
+			}
+
+			// check for proper nesting
+			if(!mScope.empty() && *name_token_it != mScope.back())
+			{
+				return;
+			}
+
+			// now ignore first token
+			++name_token_it; 
+
+			// copy remaining tokens on to our running token list
+			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
+			{
+				mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+				num_tokens_pushed++;
+			}
+			mScope.push_back(mNameStack.back().first);
+		}
+	}
+	else
+	{
+		mScope.push_back(child_name);
+	}
+
+	mTokenSizeStack.push_back(num_tokens_pushed);
+	readAttributes(atts);
+}
+
+bool LLSimpleXUIParser::readAttributes(const char **atts)
+{
+	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+	boost::char_separator<char> sep(".");
+
+	bool any_parsed = false;
+	for(S32 i = 0; atts[i] && atts[i+1]; i += 2 )
+	{
+		std::string attribute_name(atts[i]);
+		mCurAttributeValueBegin = atts[i+1];
+		
+		S32 num_tokens_pushed = 0;
+		tokenizer name_tokens(attribute_name, sep);
+		// copy remaining tokens on to our running token list
+		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
+		{
+			mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+			num_tokens_pushed++;
+		}
+
+		// child nodes are not necessarily valid attributes, so don't complain once we've recursed
+		bool silent = mCurReadDepth > 1;
+		any_parsed |= mBlock->submitValue(mNameStack, *this, silent);
+		
+		while(num_tokens_pushed-- > 0)
+		{
+			mNameStack.pop_back();
+		}
+	}
+	return any_parsed;
+}
+
+
+void LLSimpleXUIParser::endElement(const char *name)
+{
+	if (!mTextContents.empty())
+	{
+		LLStringUtil::trim(mTextContents);
+		if (!mTextContents.empty())
+		{
+			mNameStack.push_back(std::make_pair(std::string("value"), newParseGeneration()));
+			mCurAttributeValueBegin = mTextContents.c_str();
+			mBlock->submitValue(mNameStack, *this, false);
+			mNameStack.pop_back();
+			mTextContents.clear();
+		}
+	}
+	mCurReadDepth--;
+	S32 num_tokens_to_pop = mTokenSizeStack.back();
+	mTokenSizeStack.pop_back();
+	while(num_tokens_to_pop-- > 0)
+	{
+		mNameStack.pop_back();
+	}
+	mScope.pop_back();
+}
+
+void LLSimpleXUIParser::characterData(const char *s, int len)
+{
+	mTextContents += std::string(s, len);
+}
+
+
+/*virtual*/ std::string LLSimpleXUIParser::getCurrentElementName()
+{
+	std::string full_name;
+	for (name_stack_t::iterator it = mNameStack.begin();	
+		it != mNameStack.end();
+		++it)
+	{
+		full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
+	}
+
+	return full_name;
+}
+
+const S32 LINE_NUMBER_HERE = 0;
+
+void LLSimpleXUIParser::parserWarning(const std::string& message)
+{
+#ifdef LL_WINDOWS
+	// use Visual Studo friendly formatting of output message for easy access to originating xml
+	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str());
+	utf16str += '\n';
+	OutputDebugString(utf16str.c_str());
+#else
+	Parser::parserWarning(message);
+#endif
+}
+
+void LLSimpleXUIParser::parserError(const std::string& message)
+{
+#ifdef LL_WINDOWS
+	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str());
+	utf16str += '\n';
+	OutputDebugString(utf16str.c_str());
+#else
+	Parser::parserError(message);
+#endif
+}
+
+bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	if (!strcmp(self.mCurAttributeValueBegin, "true")) 
+	{
+		*((bool*)val_ptr) = true;
+		return true;
+	}
+	else if (!strcmp(self.mCurAttributeValueBegin, "false"))
+	{
+		*((bool*)val_ptr) = false;
+		return true;
+	}
+
+	return false;
+}
+
+bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	*((std::string*)val_ptr) = self.mCurAttributeValueBegin;
+	return true;
+}
+
+bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full;
+}
+	
+bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	LLColor4 value;
+
+	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
+	{
+		*(LLColor4*)(val_ptr) = value;
+		return true;
+	}
+	return false;
+}
+
+bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	LLColor4 value;
+	LLUIColor* colorp = (LLUIColor*)val_ptr;
+
+	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
+	{
+		colorp->set(value);
+		return true;
+	}
+	return false;
+}
+
+bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	LLUUID temp_id;
+	// LLUUID::set is destructive, so use temporary value
+	if (temp_id.set(std::string(self.mCurAttributeValueBegin)))
+	{
+		*(LLUUID*)(val_ptr) = temp_id;
+		return true;
+	}
+	return false;
+}
+
+bool LLSimpleXUIParser::readSDValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	*((LLSD*)val_ptr) = LLSD(self.mCurAttributeValueBegin);
+	return true;
+}
diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h
index 884f4f75780c1b5a60155abbfc9fcd5813be25b7..eb7147f49ea71f25f8ce77c6fdc0266f97e90a3e 100644
--- a/indra/llxuixml/llxuiparser.h
+++ b/indra/llxuixml/llxuiparser.h
@@ -120,26 +120,24 @@ LOG_CLASS(LLXUIParser);
 	void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL);
 
 private:
-	typedef std::list<std::pair<std::string, bool> >	token_list_t;
-
 	bool readXUIImpl(LLXMLNodePtr node, const std::string& scope, LLInitParam::BaseBlock& block);
 	bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block);
 
 	//reader helper functions
-	bool readBoolValue(void* val_ptr);
-	bool readStringValue(void* val_ptr);
-	bool readU8Value(void* val_ptr);
-	bool readS8Value(void* val_ptr);
-	bool readU16Value(void* val_ptr);
-	bool readS16Value(void* val_ptr);
-	bool readU32Value(void* val_ptr);
-	bool readS32Value(void* val_ptr);
-	bool readF32Value(void* val_ptr);
-	bool readF64Value(void* val_ptr);
-	bool readColor4Value(void* val_ptr);
-	bool readUIColorValue(void* val_ptr);
-	bool readUUIDValue(void* val_ptr);
-	bool readSDValue(void* val_ptr);
+	static bool readBoolValue(Parser& parser, void* val_ptr);
+	static bool readStringValue(Parser& parser, void* val_ptr);
+	static bool readU8Value(Parser& parser, void* val_ptr);
+	static bool readS8Value(Parser& parser, void* val_ptr);
+	static bool readU16Value(Parser& parser, void* val_ptr);
+	static bool readS16Value(Parser& parser, void* val_ptr);
+	static bool readU32Value(Parser& parser, void* val_ptr);
+	static bool readS32Value(Parser& parser, void* val_ptr);
+	static bool readF32Value(Parser& parser, void* val_ptr);
+	static bool readF64Value(Parser& parser, void* val_ptr);
+	static bool readColor4Value(Parser& parser, void* val_ptr);
+	static bool readUIColorValue(Parser& parser, void* val_ptr);
+	static bool readUUIDValue(Parser& parser, void* val_ptr);
+	static bool readSDValue(Parser& parser, void* val_ptr);
 
 	//writer helper functions
 	bool writeBoolValue(const void* val_ptr, const name_stack_t&);
@@ -173,5 +171,74 @@ LOG_CLASS(LLXUIParser);
 	std::string						mCurFileName;
 };
 
+// LLSimpleXUIParser is a streamlined SAX-based XUI parser that does not support localization 
+// or parsing of a tree of independent param blocks, such as child widgets.
+// Use this for reading non-localized files that only need a single param block as a result.
+//
+// NOTE: In order to support nested block parsing, we need callbacks for start element that
+// push new blocks contexts on the mScope stack.
+// NOTE: To support localization without building a DOM, we need to enforce consistent 
+// ordering of child elements from base file to localized diff file.  Then we can use a pair
+// of coroutines to perform matching of xml nodes during parsing.  Not sure if the overhead
+// of coroutines would offset the gain from SAX parsing
+
+class LLSimpleXUIParser : public LLInitParam::Parser, public LLSingleton<LLSimpleXUIParser>
+{
+LOG_CLASS(LLSimpleXUIParser);
+
+protected:
+	LLSimpleXUIParser();
+	virtual ~LLSimpleXUIParser();
+	friend class LLSingleton<LLSimpleXUIParser>;
+public:
+	typedef LLInitParam::Parser::name_stack_t name_stack_t;
+
+	/*virtual*/ std::string getCurrentElementName();
+	/*virtual*/ void parserWarning(const std::string& message);
+	/*virtual*/ void parserError(const std::string& message);
+
+	bool readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent=false);
+	void setBlock(LLInitParam::BaseBlock* block);
+
+private:
+	//reader helper functions
+	static bool readBoolValue(Parser&, void* val_ptr);
+	static bool readStringValue(Parser&, void* val_ptr);
+	static bool readU8Value(Parser&, void* val_ptr);
+	static bool readS8Value(Parser&, void* val_ptr);
+	static bool readU16Value(Parser&, void* val_ptr);
+	static bool readS16Value(Parser&, void* val_ptr);
+	static bool readU32Value(Parser&, void* val_ptr);
+	static bool readS32Value(Parser&, void* val_ptr);
+	static bool readF32Value(Parser&, void* val_ptr);
+	static bool readF64Value(Parser&, void* val_ptr);
+	static bool readColor4Value(Parser&, void* val_ptr);
+	static bool readUIColorValue(Parser&, void* val_ptr);
+	static bool readUUIDValue(Parser&, void* val_ptr);
+	static bool readSDValue(Parser&, void* val_ptr);
+
+private:
+	static void startElementHandler(void *userData, const char *name, const char **atts);
+	static void endElementHandler(void *userData, const char *name);
+	static void characterDataHandler(void *userData, const char *s, int len);
+
+	void startElement(const char *name, const char **atts);
+	void endElement(const char *name);
+	void characterData(const char *s, int len);
+	bool readAttributes(const char **atts);
+
+	LLInitParam::BaseBlock*			mBlock;
+	Parser::name_stack_t			mNameStack;
+	struct XML_ParserStruct*		mParser;
+	S32								mLastWriteGeneration;
+	LLXMLNodePtr					mLastWrittenChild;
+	S32								mCurReadDepth;
+	std::string						mCurFileName;
+	std::string						mTextContents;
+	const char*						mCurAttributeValueBegin;
+	std::vector<S32>				mTokenSizeStack;
+	std::vector<std::string>		mScope;
+};
+
 
 #endif //LLXUIPARSER_H
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 64bcf12b065544c99c2ff4340839b6002ef76b46..7d70b2a49bb0947be6feea08783fc7418cebb9b7 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -230,6 +230,7 @@ set(viewer_SOURCE_FILES
     llgroupiconctrl.cpp
     llgrouplist.cpp
     llgroupmgr.cpp
+    llhints.cpp
     llhomelocationresponder.cpp
     llhudeffect.cpp
     llhudeffectbeam.cpp
@@ -300,6 +301,7 @@ set(viewer_SOURCE_FILES
     llnotificationalerthandler.cpp
     llnotificationgrouphandler.cpp
     llnotificationhandlerutil.cpp
+    llnotificationhinthandler.cpp
     llnotificationmanager.cpp
     llnotificationofferhandler.cpp
     llnotificationscripthandler.cpp
@@ -754,6 +756,7 @@ set(viewer_HEADER_FILES
     llgroupiconctrl.h
     llgrouplist.h
     llgroupmgr.h
+    llhints.h
     llhomelocationresponder.h
     llhudeffect.h
     llhudeffectbeam.h
@@ -1300,6 +1303,7 @@ set(viewer_APPSETTINGS_FILES
     app_settings/cmd_line.xml
     app_settings/grass.xml
     app_settings/high_graphics.xml
+    app_settings/ignorable_dialogs.xml
     app_settings/keys.ini
     app_settings/keywords.ini
     app_settings/logcontrol.xml
diff --git a/indra/newview/app_settings/ignorable_dialogs.xml b/indra/newview/app_settings/ignorable_dialogs.xml
index d0e1f62a84a0abdadf453e6d358539cb6d1cac8c..0720ccee49190d109c106e4daa57b9ad92a092f0 100644
--- a/indra/newview/app_settings/ignorable_dialogs.xml
+++ b/indra/newview/app_settings/ignorable_dialogs.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0" ?>
 <llsd>
 <map>
-    <key>FirstAppearance</key>
+    <key>FirstInventoryOffer</key>
     <map>
       <key>Comment</key>
-      <string>Enables FirstAppearance warning dialog</string>
+      <string>Shows hint when a person or object offers resident an inventory item</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -12,120 +12,54 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
-    <key>FirstAttach</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstAttach warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstBalanceDecrease</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstBalanceDecrease warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstBalanceIncrease</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstBalanceIncrease warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstBuild</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstBuild warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstDebugMenus</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstDebugMenus warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstFlexible</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstFlexible warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstGoTo</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstGoTo warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstInventory</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstInventory warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstLeftClickNoHit</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstLeftClickNoHit warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstMap</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstMap warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstMedia</key>
+  <key>FirstNotUseDestinationGuide</key>
+  <map>
+    <key>Comment</key>
+    <string>Shows hint when resident doesn't activate destination guide</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>1</integer>
+  </map>
+  <key>FirstNotUseSidePanel</key>
+  <map>
+    <key>Comment</key>
+    <string>Shows hint when resident doesn't activate side panel</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>1</integer>
+  </map>
+  <key>FirstNotMoving</key>
+  <map>
+    <key>Comment</key>
+    <string>Shows hint when resident doesn't move</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>1</integer>
+  </map>
+  <key>FirstReceiveLindens</key>
+  <map>
+    <key>Comment</key>
+    <string>Shows hint when resident receives linden dollars</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>1</integer>
+  </map>
+  <key>FirstOtherChatBeforeUser</key>
     <map>
       <key>Comment</key>
-      <string>Enables FirstMedia warning dialog</string>
+      <string>Shows hint when someone else chats first</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -155,43 +89,11 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
-    <key>FirstSculptedPrim</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstSculptedPrim warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
+
     <key>FirstSit</key>
     <map>
       <key>Comment</key>
-      <string>Enables FirstSit warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstTeleport</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstTeleport warning dialog</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
-    <key>FirstVoice</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables FirstVoice warning dialog</string>
+      <string>Shows hint when someone sits for the first time</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 4c52fb015fd74f503d0215021b9601923d0eb59c..12fb8741ca69c3423c43054dd518184ce7e345d9 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -6425,6 +6425,17 @@
         <key>Value</key>
             <real>1.0</real>
         </map>
+    <key>MediaBrowserWindowLimit</key>
+    <map>
+      <key>Comment</key>
+      <string>Maximum number of media brower windows that can be open at once (0 for no limit)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>5</integer>
+    </map>
   <key>MediaRollOffRate</key>
   <map>
     <key>Comment</key>
@@ -11936,5 +11947,38 @@
       <key>Value</key>
       <integer>10</integer>
     </map>
+    <key>NotMovingHintTimeout</key>
+    <map>
+      <key>Comment</key>
+      <string>Number of seconds to wait for resident to move before displaying move hint.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>120.0</real>
+    </map>
+    <key>DestinationGuideHintTimeout</key>
+    <map>
+      <key>Comment</key>
+      <string>Number of seconds to wait before telling resident about destination guide.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>600.0</real>
+    </map>
+    <key>SidePanelHintTimeout</key>
+    <map>
+      <key>Comment</key>
+      <string>Number of seconds to wait before telling resident about side panel.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>300.0</real>
+    </map>
 </map>
 </llsd>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index e85d108bb29171b3c9d7492f9bc98aff2b6422ff..70bda3893e3d72f1eb2a70ea85bccdb528770a45 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -44,6 +44,7 @@
 #include "llcallingcard.h"
 #include "llchannelmanager.h"
 #include "llconsole.h"
+#include "llfirstuse.h"
 #include "llfloatercamera.h"
 #include "llfloaterreg.h"
 #include "llfloatertools.h"
@@ -232,8 +233,9 @@ LLAgent::LLAgent() :
 		mControlsTakenPassedOnCount[i] = 0;
 	}
 
-
 	mListener.reset(new LLAgentListener(*this));
+
+	mMoveTimer.stop();
 }
 
 // Requires gSavedSettings to be initialized.
@@ -242,6 +244,8 @@ LLAgent::LLAgent() :
 //-----------------------------------------------------------------------------
 void LLAgent::init()
 {
+	mMoveTimer.start();
+
 	gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", FALSE);
 	gSavedSettings.getControl("SlowMotionAnimation")->getSignal()->connect(boost::bind(&handleSlowMotionAnimation, _2));
 	
@@ -306,6 +310,9 @@ void LLAgent::ageChat()
 //-----------------------------------------------------------------------------
 void LLAgent::moveAt(S32 direction, bool reset)
 {
+	mMoveTimer.reset();
+	LLFirstUse::notMoving(false);
+
 	// age chat timer so it fades more quickly when you are intentionally moving
 	ageChat();
 
@@ -331,6 +338,9 @@ void LLAgent::moveAt(S32 direction, bool reset)
 //-----------------------------------------------------------------------------
 void LLAgent::moveAtNudge(S32 direction)
 {
+	mMoveTimer.reset();
+	LLFirstUse::notMoving(false);
+
 	// age chat timer so it fades more quickly when you are intentionally moving
 	ageChat();
 
@@ -353,6 +363,9 @@ void LLAgent::moveAtNudge(S32 direction)
 //-----------------------------------------------------------------------------
 void LLAgent::moveLeft(S32 direction)
 {
+	mMoveTimer.reset();
+	LLFirstUse::notMoving(false);
+
 	// age chat timer so it fades more quickly when you are intentionally moving
 	ageChat();
 
@@ -375,6 +388,9 @@ void LLAgent::moveLeft(S32 direction)
 //-----------------------------------------------------------------------------
 void LLAgent::moveLeftNudge(S32 direction)
 {
+	mMoveTimer.reset();
+	LLFirstUse::notMoving(false);
+
 	// age chat timer so it fades more quickly when you are intentionally moving
 	ageChat();
 
@@ -397,6 +413,9 @@ void LLAgent::moveLeftNudge(S32 direction)
 //-----------------------------------------------------------------------------
 void LLAgent::moveUp(S32 direction)
 {
+	mMoveTimer.reset();
+	LLFirstUse::notMoving(false);
+
 	// age chat timer so it fades more quickly when you are intentionally moving
 	ageChat();
 
@@ -1534,6 +1553,12 @@ void LLAgent::propagate(const F32 dt)
 //-----------------------------------------------------------------------------
 void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y)
 {
+	if (mMoveTimer.getStarted() && mMoveTimer.getElapsedTimeF32() > gSavedSettings.getF32("NotMovingHintTimeout"))
+	{
+		LLFirstUse::notMoving();
+		mMoveTimer.stop();
+	}
+
 	propagate(dt);
 
 	// static S32 cameraUpdateCount = 0;
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 32f9b001356f592cec6b29ca9edc117a48d7df5f..0185f874f964914e11420c038e93ba05fabc0a61 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -270,6 +270,7 @@ class LLAgent : public LLOldEvents::LLObservable
 private:
 	LLFrameTimer	mFidgetTimer;
 	LLFrameTimer	mFocusObjectFadeTimer;
+	LLFrameTimer	mMoveTimer;
 	F32				mNextFidgetTime;
 	S32				mCurrentFidget;
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d222d94ec608126e1475c9ce8aa911f685fecf7a..768be116f6d821acd72316db2631b0d210bb6ba9 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -268,6 +268,7 @@ const F64 FRAME_STALL_THRESHOLD = 1.0;
 
 LLTimer gRenderStartTime;
 LLFrameTimer gForegroundTime;
+LLFrameTimer gLoggedInTime;
 LLTimer gLogoutTimer;
 static const F32 LOGOUT_REQUEST_TIME = 6.f;  // this will be cut short by the LogoutReply msg.
 F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
@@ -597,6 +598,7 @@ LLAppViewer::LLAppViewer() :
 
 	setupErrorHandling();
 	sInstance = this;
+	gLoggedInTime.stop();
 }
 
 LLAppViewer::~LLAppViewer()
@@ -4281,6 +4283,7 @@ void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
 
 void LLAppViewer::handleLoginComplete()
 {
+	gLoggedInTime.start();
 	initMainloopTimeout("Mainloop Init");
 
 	// Store some data to DebugInfo in case of a freeze.
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 0b862a92a1acfdca774e40d44e3d46822b79eac3..e5e27dc90892a8ea730e9435570b8ecb0e3b5a25 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -313,6 +313,7 @@ extern U32 		gFrameStalls;
 
 extern LLTimer gRenderStartTime;
 extern LLFrameTimer gForegroundTime;
+extern LLFrameTimer gLoggedInTime;
 
 extern F32 gLogoutMaxTime;
 extern LLTimer gLogoutTimer;
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 0e5e8d0fe7ccd7ad592638c370a15ef6efac4c21..e0b605a724d49b6c124bfc70c96b671dafe55596 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -47,6 +47,7 @@
 #include "llagentcamera.h"
 #include "llchiclet.h"
 #include "llfloatercamera.h"
+#include "llhints.h"
 #include "llimfloater.h" // for LLIMFloater
 #include "llnearbychatbar.h"
 #include "llspeakbutton.h"
@@ -68,10 +69,6 @@ template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();
 namespace
 {
 	const std::string& PANEL_CHICLET_NAME	= "chiclet_list_panel";
-	const std::string& PANEL_CHATBAR_NAME	= "chat_bar";
-	const std::string& PANEL_MOVEMENT_NAME	= "movement_panel";
-	const std::string& PANEL_CAMERA_NAME	= "cam_panel";
-	const std::string& PANEL_GESTURE_NAME	= "gesture_panel";
 
 	S32 get_panel_min_width(LLLayoutStack* stack, LLView* panel)
 	{
@@ -474,10 +471,12 @@ BOOL LLBottomTray::postBuild()
 	mBottomTrayContextMenu =  LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_bottomtray.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	gMenuHolder->addChild(mBottomTrayContextMenu);
 
-
 	mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar");
+	LLHints::registerHintTarget("nearby_chat_bar", mNearbyChatBar->LLView::getHandle());
+
 	mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
 	mMovementButton = getChild<LLButton>("movement_btn");
+	LLHints::registerHintTarget("move_btn", mMovementButton->getHandle());
 	mCamButton = getChild<LLButton>("camera_btn");
 	setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4));
 
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 73fbe78298d49dd522711f9c74e3a75b02dba7ca..96001a07a0baf6b9128bb65d8f26647992e2e153 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -571,6 +571,10 @@ void LLChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type,
 
 void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate)
 {
+	// as soon as we say something, we no longer care about teaching the user
+	// how to chat
+	gWarningSettings.setBOOL("FirstOtherChatBeforeUser", FALSE);
+	
 	// Look for "/20 foo" channel chats.
 	S32 channel = 0;
 	LLWString out_text = stripChannelNumber(wtext, &channel);
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 8bc3b5a75f09c646152075991e4b6d1f07d90958..696ac4e6fac36a07f3c1a5e53f9e0ab1e6bdbfbb 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -123,7 +123,7 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
 	{
 		S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());
 		bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY);
-		mPrintStats = bar_idx;
+		mPrintStats = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - bar_idx;
 	}
 	return FALSE;
 }
@@ -140,6 +140,17 @@ LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y)
 	return NULL;
 }
 
+BOOL LLFastTimerView::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+	for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
+		it != end_timer_tree();
+		++it)
+	{
+		(*it)->setCollapsed(false);
+	}
+	return TRUE;
+}
+
 BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 
@@ -953,7 +964,7 @@ void LLFastTimerView::draw()
 			{
 				legend_stat += ", ";
 			}
-			first = true;
+			first = false;
 			legend_stat += idp->getName();
 
 			if (idp->getCollapsed())
@@ -980,8 +991,7 @@ void LLFastTimerView::draw()
 			U64 ticks;
 			if (mPrintStats > 0)
 			{
-				S32 hidx = (mPrintStats - 1) - mScrollIndex;
-				ticks = idp->getHistoricalCount(hidx);
+				ticks = idp->getHistoricalCount(mPrintStats);
 			}
 			else
 			{
diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h
index ac069909138121212776ce66a5c4dc85635cfd3d..6f64248f782645d15033ea51e960d7ed01608ef9 100644
--- a/indra/newview/llfasttimerview.h
+++ b/indra/newview/llfasttimerview.h
@@ -54,6 +54,7 @@ class LLFastTimerView : public LLFloater
 public:
 
 	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+	virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
 	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
 	virtual BOOL handleHover(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp
index b3fdf60b11a1cce7fc35b45c2efebb516ae0f8af..15de138c957e80ec19104b3eedf95033905939e1 100644
--- a/indra/newview/llfirstuse.cpp
+++ b/indra/newview/llfirstuse.cpp
@@ -36,7 +36,7 @@
 
 // library includes
 #include "indra_constants.h"
-#include "llnotificationsutil.h"
+#include "llnotifications.h"
 
 // viewer includes
 #include "llagent.h"	// for gAgent.inPrelude()
@@ -45,9 +45,10 @@
 #include "llappviewer.h"
 #include "lltracker.h"
 
-/*
+
 // static
 std::set<std::string> LLFirstUse::sConfigVariables;
+std::map<std::string, LLNotificationPtr> LLFirstUse::sNotifications;
 
 // static
 void LLFirstUse::addConfigVariable(const std::string& var)
@@ -76,211 +77,90 @@ void LLFirstUse::resetFirstUse()
 		gWarningSettings.setBOOL(*iter, TRUE);
 	}
 }
-*/
-/*
-
-// Called whenever the viewer detects that your balance went up
-void LLFirstUse::useBalanceIncrease(S32 delta)
-{
-	if (gWarningSettings.getBOOL("FirstBalanceIncrease"))
-	{
-		gWarningSettings.setBOOL("FirstBalanceIncrease", FALSE);
-
-		LLSD args;
-		args["AMOUNT"] = llformat("%d",delta);
-		LLNotificationsUtil::add("FirstBalanceIncrease", args);
-	}
-}
-
 
-// Called whenever the viewer detects your balance went down
-void LLFirstUse::useBalanceDecrease(S32 delta)
+// static
+void LLFirstUse::useOverrideKeys()
 {
-	if (gWarningSettings.getBOOL("FirstBalanceDecrease"))
+	// Our orientation island uses key overrides to teach vehicle driving
+	// so don't show this message until you get off OI. JC
+	if (!gAgent.inPrelude())
 	{
-		gWarningSettings.setBOOL("FirstBalanceDecrease", FALSE);
-
-		LLSD args;
-		args["AMOUNT"] = llformat("%d",-delta);
-		LLNotificationsUtil::add("FirstBalanceDecrease", args);
+		firstUseNotification("FirstOverrideKeys", true, "FirstOverrideKeys");
 	}
 }
 
-
-// static
-void LLFirstUse::useSit()
-{
-	// Our orientation island uses sitting to teach vehicle driving
-	// so just never show this message. JC
-	//if (gWarningSettings.getBOOL("FirstSit"))
-	//{
-	//	gWarningSettings.setBOOL("FirstSit", FALSE);
-        //
-	//	LLNotificationsUtil::add("FirstSit");
-	//}
-}
-
 // static
-void LLFirstUse::useMap()
+void LLFirstUse::otherAvatarChatFirst(bool enable)
 {
-	if (gWarningSettings.getBOOL("FirstMap"))
-	{
-		gWarningSettings.setBOOL("FirstMap", FALSE);
-
-		LLNotificationsUtil::add("FirstMap");
-	}
+	firstUseNotification("FirstOtherChatBeforeUser", enable, "HintChat", LLSD(), LLSD().with("target", "nearby_chat_bar").with("direction", "top"));
 }
 
 // static
-void LLFirstUse::useGoTo()
+void LLFirstUse::sit(bool enable)
 {
-	// nothing for now JC
+	firstUseNotification("FirstSit", enable, "HintSit", LLSD(), LLSD().with("target", "stand_btn").with("direction", "top"));
 }
 
 // static
-void LLFirstUse::useBuild()
+void LLFirstUse::inventoryOffer(bool enable)
 {
-	if (gWarningSettings.getBOOL("FirstBuild"))
-	{
-		gWarningSettings.setBOOL("FirstBuild", FALSE);
-
-		LLNotificationsUtil::add("FirstBuild");
-	}
+	firstUseNotification("FirstInventoryOffer", enable, "HintInventory", LLSD(), LLSD().with("target", "inventory_btn").with("direction", "left"));
 }
- 
- */
-/*
-// static
-void LLFirstUse::useLeftClickNoHit()
-{ 
-	if (gWarningSettings.getBOOL("FirstLeftClickNoHit"))
-	{
-		gWarningSettings.setBOOL("FirstLeftClickNoHit", FALSE);
 
-		LLNotificationsUtil::add("FirstLeftClickNoHit");
-	}
-}
-*/
-/*
 // static
-void LLFirstUse::useTeleport()
+void LLFirstUse::useSandbox()
 {
-	if (gWarningSettings.getBOOL("FirstTeleport"))
-	{
-		LLVector3d teleportDestination = LLTracker::getTrackedPositionGlobal();
-		if(teleportDestination != LLVector3d::zero)
-		{
-			gWarningSettings.setBOOL("FirstTeleport", FALSE);
-
-		        LLNotificationsUtil::add("FirstTeleport");
-		}
-	}
+	firstUseNotification("FirstSandbox", true, "FirstSandbox", LLSD().with("HOURS", SANDBOX_CLEAN_FREQ).with("TIME", SANDBOX_FIRST_CLEAN_HOUR));
 }
-*/
-// static
-void LLFirstUse::useOverrideKeys()
-{
-	// Our orientation island uses key overrides to teach vehicle driving
-	// so don't show this message until you get off OI. JC
-	if (!gAgent.inPrelude())
-	{
-		if (gWarningSettings.getBOOL("FirstOverrideKeys"))
-		{
-			gWarningSettings.setBOOL("FirstOverrideKeys", FALSE);
 
-			LLNotificationsUtil::add("FirstOverrideKeys");
-		}
-	}
-}
-/*
 // static
-void LLFirstUse::useAttach()
+void LLFirstUse::notUsingDestinationGuide(bool enable)
 {
-	// nothing for now
+	// not doing this yet
+	//firstUseNotification("FirstNotUseDestinationGuide", enable, "HintDestinationGuide", LLSD(), LLSD().with("target", "dest_guide_btn").with("direction", "left"));
 }
 
 // static
-void LLFirstUse::useAppearance()
+void LLFirstUse::notUsingSidePanel(bool enable)
 {
-	if (gWarningSettings.getBOOL("FirstAppearance"))
-	{
-		gWarningSettings.setBOOL("FirstAppearance", FALSE);
-
-		LLNotificationsUtil::add("FirstAppearance");
-	}
+	// not doing this yet
+	//firstUseNotification("FirstNotUseSidePanel", enable, "HintSidePanel", LLSD(), LLSD().with("target", "side_panel_btn").with("direction", "left"));
 }
 
 // static
-void LLFirstUse::useInventory()
+void LLFirstUse::notMoving(bool enable)
 {
-	if (gWarningSettings.getBOOL("FirstInventory"))
-	{
-		gWarningSettings.setBOOL("FirstInventory", FALSE);
-
-		LLNotificationsUtil::add("FirstInventory");
-	}
+	firstUseNotification("FirstNotMoving", enable, "HintMove", LLSD(), LLSD().with("target", "move_btn").with("direction", "top"));
 }
 
-*/
-
 // static
-void LLFirstUse::useSandbox()
+void LLFirstUse::receiveLindens(bool enable)
 {
-	if (gWarningSettings.getBOOL("FirstSandbox"))
-	{
-		gWarningSettings.setBOOL("FirstSandbox", FALSE);
-
-		LLSD args;
-		args["HOURS"] = llformat("%d",SANDBOX_CLEAN_FREQ);
-		args["TIME"] = llformat("%d",SANDBOX_FIRST_CLEAN_HOUR);
-		LLNotificationsUtil::add("FirstSandbox", args);
-	}
+	firstUseNotification("FirstReceiveLindens", enable, "HintLindenDollar", LLSD(), LLSD().with("target", "linden_balance").with("direction", "bottom"));
 }
-/*
-// static
-void LLFirstUse::useFlexible()
-{
-	if (gWarningSettings.getBOOL("FirstFlexible"))
-	{
-		gWarningSettings.setBOOL("FirstFlexible", FALSE);
 
-		LLNotificationsUtil::add("FirstFlexible");
-	}
-}
 
-// static
-void LLFirstUse::useDebugMenus()
+//static 
+void LLFirstUse::firstUseNotification(const std::string& control_var, bool enable, const std::string& notification_name, LLSD args, LLSD payload)
 {
-	if (gWarningSettings.getBOOL("FirstDebugMenus"))
-	{
-		gWarningSettings.setBOOL("FirstDebugMenus", FALSE);
+	LLNotificationPtr notif = sNotifications[notification_name];
 
-		LLNotificationsUtil::add("FirstDebugMenus");
-	}
-}
-
-// static
-void LLFirstUse::useSculptedPrim()
-{
-	if (gWarningSettings.getBOOL("FirstSculptedPrim"))
+	if (enable)
 	{
-		gWarningSettings.setBOOL("FirstSculptedPrim", FALSE);
-
-		LLNotificationsUtil::add("FirstSculptedPrim");
-		
+		if (!notif && gWarningSettings.getBOOL(control_var))
+		{ // create new notification
+			sNotifications[notification_name] = LLNotifications::instance().add(LLNotification::Params().name(notification_name).substitutions(args).payload(payload));
+			gWarningSettings.setBOOL(control_var, FALSE);
+		}
+	}	
+	else
+	{ // want to hide notification
+		if (notif)
+		{ // cancel existing notification
+			LLNotifications::instance().cancel(notif);
+			sNotifications.erase(notification_name);
+		}
+		gWarningSettings.setBOOL(control_var, FALSE);
 	}
-}
 
-// static 
-void LLFirstUse::useMedia()
-{
-	if (gWarningSettings.getBOOL("FirstMedia"))
-	{
-		gWarningSettings.setBOOL("FirstMedia", FALSE);
-
-		// Popup removed as a short-term fix for EXT-1643.
-		// Ultimately, the plan is to kill all First Use dialogs
-		//LLNotificationsUtil::add("FirstMedia");
-	}
 }
-*/
diff --git a/indra/newview/llfirstuse.h b/indra/newview/llfirstuse.h
index 3c7551f6cbb4e472a4a3c90dae2bed078b121213..48943cd9ab1b70a4ff742c9cf6eba640794e9b64 100644
--- a/indra/newview/llfirstuse.h
+++ b/indra/newview/llfirstuse.h
@@ -76,10 +76,13 @@ object or from inventory.
 14. First time you create/edit a sculpted prim.
 */
 
+class LLNotification;
+
+
 class LLFirstUse
 {
 public:
-/*	
+
 	// Add a config variable to be reset on resetFirstUse()
 	static void addConfigVariable(const std::string& var);
 	
@@ -87,35 +90,20 @@ class LLFirstUse
 	static void disableFirstUse();
 	static void resetFirstUse();
 
-	// These methods are called each time the appropriate action is
-	// taken.  The functions themselves handle only showing the dialog
-	// the first time, or subsequent times if the user wishes.
-	static void useBalanceIncrease(S32 delta);
-	static void useBalanceDecrease(S32 delta);
-	static void useSit();
-	static void useMap();
-	static void useGoTo();
-	static void useBuild();
-//	static void useLeftClickNoHit();
-	static void useTeleport();
-*/ 
 	static void useOverrideKeys();
-/*	
-	static void useAttach();
-	static void useAppearance();
-	static void useInventory();
- */
+	static void otherAvatarChatFirst(bool enable = true);
+	static void sit(bool enable = true);
+	static void notUsingDestinationGuide(bool enable = true);
+	static void notUsingSidePanel(bool enable = true);
+	static void notMoving(bool enable = true);
+	static void inventoryOffer(bool enable = true);
+	static void receiveLindens(bool enable = true);
 	static void useSandbox();
 	
-/*
-	static void useFlexible();
-	static void useDebugMenus();
-	static void useSculptedPrim();
-	static void useMedia();
-	
 protected:
+	static void firstUseNotification(const std::string& control_var, bool enable, const std::string& notification_name, LLSD args = LLSD(), LLSD payload = LLSD());
 	static std::set<std::string> sConfigVariables;
-*/
+	static std::map<std::string, boost::shared_ptr<LLNotification> > sNotifications;
 };
 
 #endif
diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp
index 43f158658a9d41d7ebd8c28e6ebb3c83a46a5b39..834f5177345549ec9bcb29d94d1db745fa852260 100644
--- a/indra/newview/llfloatergroups.cpp
+++ b/indra/newview/llfloatergroups.cpp
@@ -344,11 +344,10 @@ void LLPanelGroups::onGroupList(LLUICtrl* ctrl, void* userdata)
 	if(self) self->enableButtons();
 }
 
-void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 powers_mask)
+void init_group_list(LLScrollListCtrl* group_list, const LLUUID& highlight_id, U64 powers_mask)
 {
 	S32 count = gAgent.mGroups.count();
 	LLUUID id;
-	LLCtrlListInterface *group_list = ctrl->getListInterface();
 	if (!group_list) return;
 
 	group_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
@@ -372,10 +371,12 @@ void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 pow
 			element["columns"][0]["font"]["name"] = "SANSSERIF";
 			element["columns"][0]["font"]["style"] = style;
 
-			group_list->addElement(element, ADD_SORTED);
+			group_list->addElement(element);
 		}
 	}
 
+	group_list->sortOnce(0, TRUE);
+
 	// add "none" to list at top
 	{
 		std::string style = "NORMAL";
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 625b443abc4a157ba09af9d08c1dc6b51a8f8449..19e28720ae385dbaffd07f91f8288b8790c22b30 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2440,7 +2440,7 @@ void LLPanelLandAccess::refresh()
 					suffix.append(" " + parent_floater->getString("Remaining") + ")");
 				}
 				if (mListAccess)
-					mListAccess->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix);
+					mListAccess->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix);
 			}
 		}
 		
@@ -2481,7 +2481,7 @@ void LLPanelLandAccess::refresh()
 					}
 					suffix.append(" " + parent_floater->getString("Remaining") + ")");
 				}
-				mListBanned->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix);
+				mListBanned->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix);
 			}
 		}
 		
diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp
index 3c8ee6eb9e584e1f133d616f3c3965a3cce62ba6..12d27b879093d8f8e7361b2a01bc542029029145 100644
--- a/indra/newview/llfloaterlandholdings.cpp
+++ b/indra/newview/llfloaterlandholdings.cpp
@@ -75,10 +75,9 @@ BOOL LLFloaterLandHoldings::postBuild()
 	childSetAction("Show on Map", onClickMap, this);
 
 	// Grant list
-	getChild<LLScrollListCtrl>("grant list")->setDoubleClickCallback(onGrantList, this);
-
-	LLCtrlListInterface *list = childGetListInterface("grant list");
-	if (!list) return TRUE;
+	LLScrollListCtrl* grant_list = getChild<LLScrollListCtrl>("grant list");
+	grant_list->sortByColumnIndex(0, TRUE);
+	grant_list->setDoubleClickCallback(onGrantList, this);
 
 	S32 count = gAgent.mGroups.count();
 	for(S32 i = 0; i < count; ++i)
@@ -97,7 +96,7 @@ BOOL LLFloaterLandHoldings::postBuild()
 		element["columns"][1]["value"] = areastr;
 		element["columns"][1]["font"] = "SANSSERIF";
 
-		list->addElement(element, ADD_SORTED);
+		grant_list->addElement(element);
 	}
 	
 	center();
diff --git a/indra/newview/llfloatermediabrowser.cpp b/indra/newview/llfloatermediabrowser.cpp
index 5405de2f9ab9cd4d53eecfb11ddcdd3821fc022d..90147ff6505dec609a79527cd903da218ea8fed0 100644
--- a/indra/newview/llfloatermediabrowser.cpp
+++ b/indra/newview/llfloatermediabrowser.cpp
@@ -63,6 +63,54 @@ LLFloaterMediaBrowser::LLFloaterMediaBrowser(const LLSD& key)
 
 }
 
+//static 
+void LLFloaterMediaBrowser::create(const std::string &url, const std::string& target)
+{
+	std::string tag = target;
+	
+	if(target.empty() || target == "_blank")
+	{
+		// create a unique tag for this instance
+		LLUUID id;
+		id.generate();
+		tag = id.asString();
+	}
+	
+	S32 browser_window_limit = gSavedSettings.getS32("MediaBrowserWindowLimit");
+	
+	if(LLFloaterReg::findInstance("media_browser", tag) != NULL)
+	{
+		// There's already a media browser for this tag, so we won't be opening a new window.
+	}
+	else if(browser_window_limit != 0)
+	{
+		// showInstance will open a new window.  Figure out how many media browsers are already open, 
+		// and close the least recently opened one if this will put us over the limit.
+		
+		LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("media_browser");
+		lldebugs << "total instance count is " << instances.size() << llendl;
+		
+		for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
+		{
+			lldebugs << "    " << (*iter)->getKey() << llendl;
+		}
+		
+		if(instances.size() >= (size_t)browser_window_limit)
+		{
+			// Destroy the least recently opened instance
+			(*instances.begin())->closeFloater();
+		}
+	}
+
+	LLFloaterMediaBrowser *browser = dynamic_cast<LLFloaterMediaBrowser*> (LLFloaterReg::showInstance("media_browser", tag));
+	llassert(browser);
+	if(browser)
+	{
+		// tell the browser instance to load the specified URL
+		browser->openMedia(url);
+	}
+}
+
 void LLFloaterMediaBrowser::draw()
 {
 	getChildView("go")->setEnabled(!mAddressCombo->getValue().asString().empty());
@@ -105,6 +153,7 @@ BOOL LLFloaterMediaBrowser::postBuild()
 
 	mAddressCombo = getChild<LLComboBox>("address");
 	mAddressCombo->setCommitCallback(onEnterAddress, this);
+	mAddressCombo->sortByName();
 
 	childSetAction("back", onClickBack, this);
 	childSetAction("forward", onClickForward, this);
@@ -185,7 +234,7 @@ void LLFloaterMediaBrowser::setCurrentURL(const std::string& url)
 	if (mCurrentURL != "about:blank")
 	{
 		mAddressCombo->remove(mCurrentURL);
-		mAddressCombo->add(mCurrentURL, ADD_SORTED);
+		mAddressCombo->add(mCurrentURL);
 		mAddressCombo->selectByValue(mCurrentURL);
 
 		// Serialize url history
@@ -197,12 +246,6 @@ void LLFloaterMediaBrowser::setCurrentURL(const std::string& url)
 	getChildView("reload")->setEnabled(TRUE);
 }
 
-void LLFloaterMediaBrowser::onOpen(const LLSD& media_url)
-{
-	LLFloater::onOpen(media_url);
-	openMedia(media_url.asString());
-}
-
 //static 
 void LLFloaterMediaBrowser::onEnterAddress(LLUICtrl* ctrl, void* user_data)
 {
diff --git a/indra/newview/llfloatermediabrowser.h b/indra/newview/llfloatermediabrowser.h
index c315f9e7978d375d79656261656fe24f4eea587e..4255d814c014bd8018b3ae891267b49be09f3078 100644
--- a/indra/newview/llfloatermediabrowser.h
+++ b/indra/newview/llfloatermediabrowser.h
@@ -45,12 +45,14 @@ class LLFloaterMediaBrowser :
 	public LLViewerMediaObserver
 {
 public:
+    LOG_CLASS(LLFloaterMediaBrowser);
 	LLFloaterMediaBrowser(const LLSD& key);
 
+	static void create(const std::string &url, const std::string& target);
+	
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void onClose(bool app_quitting);
 	/*virtual*/ void draw();
-	/*virtual*/ void onOpen(const LLSD& key);
 
 	// inherited from LLViewerMediaObserver
 	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 7791c037d38a1a90f5ca3647aafd0fd4f39299bf..a4b45e04f20d5b517afc020a8003b30495bc0a85 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -826,13 +826,11 @@ void LLFloaterPreference::buildPopupLists()
 				row["columns"][1]["font"] = "SANSSERIF_SMALL";
 				row["columns"][1]["width"] = 360;
 			}
-			item = disabled_popups.addElement(row,
-											  ADD_SORTED);
+			item = disabled_popups.addElement(row);
 		}
 		else
 		{
-			item = enabled_popups.addElement(row,
-											 ADD_SORTED);
+			item = enabled_popups.addElement(row);
 		}
 		
 		if (item)
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index e0f646349e3898eb6b26b81da79c7605f087a6cf..a77fc4710a48b4438b274c742ebea9daa71effb6 100644
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -712,38 +712,44 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
 				}
 			}
 
-			LLSD element;
+			LLScrollListItem::Params item_params;
+			item_params.value = task_id;
 
-			element["id"] = task_id;
-			element["columns"][0]["column"] = "size";
-			element["columns"][0]["value"] = llformat("%d", size);
-			element["columns"][0]["font"] = "SANSSERIF";
-			element["columns"][1]["column"] = "urls";
-			element["columns"][1]["value"] = llformat("%d", urls);
-			element["columns"][1]["font"] = "SANSSERIF";
-			element["columns"][2]["column"] = "name";
-			element["columns"][2]["value"] = name_buf;
-			element["columns"][2]["font"] = "SANSSERIF";
-			element["columns"][3]["column"] = "owner";
-			element["columns"][3]["value"] = owner_buf;
-			element["columns"][3]["font"] = "SANSSERIF";
-			element["columns"][4]["column"] = "parcel";
-			element["columns"][4]["value"] = parcel_name;
-			element["columns"][4]["font"] = "SANSSERIF";
-			element["columns"][5]["column"] = "location";
-			if(has_locations)
-			{
-				element["columns"][5]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z);
-			}
-			else
-			{
-				element["columns"][5]["value"] = "";
-			}
-			element["columns"][5]["font"] = "SANSSERIF";
+			LLScrollListCell::Params cell_params;
+			cell_params.font = LLFontGL::getFontSansSerif();
+
+			cell_params.column = "size";
+			cell_params.value = size;
+			item_params.columns.add(cell_params);
+
+			cell_params.column = "urls";
+			cell_params.value = urls;
+			item_params.columns.add(cell_params);
+
+			cell_params.column = "name";
+			cell_params.value = name_buf;
+			item_params.columns.add(cell_params);
 
-			list->addElement(element, ADD_SORTED);
+			cell_params.column = "owner";
+			cell_params.value = owner_buf;
+			item_params.columns.add(cell_params);
+
+			cell_params.column = "parcel";
+			cell_params.value = parcel_name;
+			item_params.columns.add(cell_params);
+
+			cell_params.column = "location";
+			cell_params.value = has_locations
+				? llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z)
+				: "";
+			item_params.columns.add(cell_params);
+
+			list->addRow(item_params);
 			
+			LLSD element;
 			element["owner_id"] = owner_id;
+
+			element["id"] = task_id;
 			element["local_id"] = local_id;
 			mObjectListItems.push_back(element);
 		}
diff --git a/indra/newview/llhints.cpp b/indra/newview/llhints.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..14a9871a7d958a3e0bc9fbdd8146eda20df28fb1
--- /dev/null
+++ b/indra/newview/llhints.cpp
@@ -0,0 +1,304 @@
+/**
+ * @file llhints.cpp
+ * @brief Hint popups for displaying context sensitive help in a UI overlay
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llhints.h"
+
+#include "llbutton.h"
+#include "lltextbox.h"
+#include "llviewerwindow.h"
+#include "llsdparam.h"
+
+class LLHintPopup : public LLPanel
+{
+public:
+
+	typedef enum e_popup_direction
+	{
+		LEFT,
+		TOP,
+		RIGHT,
+		BOTTOM
+	} EPopupDirection;
+
+	struct PopupDirections : public LLInitParam::TypeValuesHelper<LLHintPopup::EPopupDirection, PopupDirections>
+	{
+		static void declareValues()
+		{
+			declare("left", LLHintPopup::LEFT);
+			declare("right", LLHintPopup::RIGHT);
+			declare("top", LLHintPopup::TOP);
+			declare("bottom", LLHintPopup::BOTTOM);
+		}
+	};
+
+	struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+	{
+		Mandatory<LLNotificationPtr>	notification;
+		Optional<std::string>			target;
+		Optional<EPopupDirection, PopupDirections>	direction;
+		Optional<S32>					distance;
+		Optional<LLUIImage*>			left_arrow,
+										up_arrow,
+										right_arrow,
+										down_arrow;	
+		Optional<S32>					left_arrow_offset,
+										up_arrow_offset,
+										right_arrow_offset,
+										down_arrow_offset;
+		Optional<F32>					fade_in_time,
+										fade_out_time;
+
+		Params()
+		:	direction("direction", TOP),
+			distance("distance", 24),
+			target("target"),
+			left_arrow("left_arrow", LLUI::getUIImage("hint_arrow_left")),
+			up_arrow("up_arrow", LLUI::getUIImage("hint_arrow_up")),
+			right_arrow("right_arrow", LLUI::getUIImage("hint_arrow_right")),
+			down_arrow("down_arrow", LLUI::getUIImage("hint_arrow_down")),
+			left_arrow_offset("left_arrow_offset", 3),
+			up_arrow_offset("up_arrow_offset", -2),
+			right_arrow_offset("right_arrow_offset", -3),
+			down_arrow_offset("down_arrow_offset", 5),
+			fade_in_time("fade_in_time", 0.2f),
+			fade_out_time("fade_out_time", 0.5f)
+		{}
+	};
+
+	LLHintPopup(const Params&);
+
+	void setHintTarget(LLHandle<LLView> target) { mTarget = target; }
+	/*virtual*/ BOOL postBuild();
+
+	void onClickClose() { hide(); }
+	void draw();
+	void hide() { if(!mHidden) {mHidden = true; mFadeTimer.reset();} }
+
+private:
+	LLNotificationPtr	mNotification;
+	LLHandle<LLView>	mTarget;
+	EPopupDirection		mDirection;
+	S32					mDistance;
+	LLUIImagePtr		mArrowLeft,
+						mArrowUp,
+						mArrowRight,
+						mArrowDown;
+	S32					mArrowLeftOffset,
+						mArrowUpOffset,
+						mArrowRightOffset,
+						mArrowDownOffset;
+	LLFrameTimer		mFadeTimer;
+	F32					mFadeInTime,
+						mFadeOutTime;
+	bool				mHidden;
+};
+
+
+
+
+LLHintPopup::LLHintPopup(const LLHintPopup::Params& p)
+:	mNotification(p.notification),
+	mDirection(p.direction),
+	mDistance(p.distance),
+	mTarget(LLHints::getHintTarget(p.target)),
+	mArrowLeft(p.left_arrow),
+	mArrowUp(p.up_arrow),
+	mArrowRight(p.right_arrow),
+	mArrowDown(p.down_arrow),
+	mArrowLeftOffset(p.left_arrow_offset),
+	mArrowUpOffset(p.up_arrow_offset),
+	mArrowRightOffset(p.right_arrow_offset),
+	mArrowDownOffset(p.down_arrow_offset),
+	mHidden(false),
+	mFadeInTime(p.fade_in_time),
+	mFadeOutTime(p.fade_out_time),
+	LLPanel(p)
+{
+	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_hint.xml");
+}
+
+BOOL LLHintPopup::postBuild()
+{
+	LLTextBox& hint_text = getChildRef<LLTextBox>("hint_text");
+	hint_text.setText(mNotification->getMessage());
+	
+	getChild<LLButton>("close")->setClickedCallback(boost::bind(&LLHintPopup::onClickClose, this));
+	getChild<LLTextBox>("hint_title")->setText(mNotification->getLabel());
+
+	LLRect text_bounds = hint_text.getTextBoundingRect();
+	S32 delta_height = text_bounds.getHeight() - hint_text.getRect().getHeight();
+	reshape(getRect().getWidth(), getRect().getHeight() + delta_height);
+	return TRUE;
+}
+
+void LLHintPopup::draw()
+{
+	F32 alpha = 1.f;
+	if (mHidden)
+	{
+		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, mFadeOutTime, 1.f, 0.f);
+		if (alpha == 0.f)
+		{
+			die();
+		}
+	}
+	else
+	{
+		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, mFadeInTime, 0.f, 1.f);
+	}
+	LLViewDrawContext context(alpha);
+
+	LLView* targetp = mTarget.get();
+	if (!targetp || !targetp->isInVisibleChain()) 
+	{
+		hide();
+	}
+	else
+	{
+		LLRect target_rect;
+		targetp->localRectToOtherView(targetp->getLocalRect(), &target_rect, getParent());
+
+		LLRect my_local_rect = getLocalRect();
+		LLRect my_rect;
+		LLRect arrow_rect;
+		LLUIImagePtr arrow_imagep;
+
+		switch(mDirection)
+		{
+		case LEFT:
+			my_rect.setCenterAndSize(	target_rect.mLeft - (my_local_rect.getWidth() / 2 + mDistance), 
+										target_rect.getCenterY(), 
+										my_local_rect.getWidth(), 
+										my_local_rect.getHeight());
+			arrow_rect.setCenterAndSize(my_local_rect.mRight + mArrowRight->getWidth() / 2 + mArrowRightOffset,
+										my_local_rect.getCenterY(),
+										mArrowRight->getWidth(), 
+										mArrowRight->getHeight());
+			arrow_imagep = mArrowRight;
+			break;
+		case TOP:
+			my_rect.setCenterAndSize(	target_rect.getCenterX(), 
+										target_rect.mTop + (my_local_rect.getHeight() / 2 + mDistance), 
+										my_local_rect.getWidth(), 
+										my_local_rect.getHeight());
+			arrow_rect.setCenterAndSize(my_local_rect.getCenterX(),
+										my_local_rect.mBottom - mArrowDown->getHeight() / 2 + mArrowDownOffset,
+										mArrowDown->getWidth(), 
+										mArrowDown->getHeight());
+			arrow_imagep = mArrowDown;
+			break;
+		case RIGHT:
+			my_rect.setCenterAndSize(	target_rect.getCenterX(), 
+										target_rect.mTop - (my_local_rect.getHeight() / 2 + mDistance), 
+										my_local_rect.getWidth(), 
+										my_local_rect.getHeight());
+			arrow_rect.setCenterAndSize(my_local_rect.mLeft - mArrowLeft->getWidth() / 2 + mArrowLeftOffset,
+										my_local_rect.getCenterY(),
+										mArrowLeft->getWidth(), 
+										mArrowLeft->getHeight());
+			arrow_imagep = mArrowLeft;
+			break;
+		case BOTTOM:
+			my_rect.setCenterAndSize(	target_rect.getCenterX(), 
+										target_rect.mBottom - (my_local_rect.getHeight() / 2 + mDistance),
+										my_local_rect.getWidth(), 
+										my_local_rect.getHeight());
+			arrow_rect.setCenterAndSize(my_local_rect.getCenterX(),
+										my_local_rect.mTop + mArrowUp->getHeight() / 2 + mArrowUpOffset,
+										mArrowUp->getWidth(), 
+										mArrowUp->getHeight());
+			arrow_imagep = mArrowUp;
+			break;
+		}
+		setShape(my_rect);
+		LLPanel::draw();
+
+		arrow_imagep->draw(arrow_rect, LLColor4(1.f, 1.f, 1.f, alpha));
+	}
+}
+
+
+LLRegistry<std::string, LLHandle<LLView> > LLHints::sTargetRegistry;
+std::map<LLNotificationPtr, class LLHintPopup*> LLHints::sHints;
+
+//static
+void LLHints::show(LLNotificationPtr hint)
+{
+	LLHintPopup::Params p;
+	LLParamSDParser::instance().readSD(hint->getPayload(), p);
+
+	p.notification = hint;
+
+	LLHintPopup* popup = new LLHintPopup(p);
+	
+	sHints[hint] = popup;
+
+	LLView* hint_holder = gViewerWindow->getHintHolder();
+	if (hint_holder)
+	{
+		hint_holder->addChild(popup);
+		popup->centerWithin(hint_holder->getLocalRect());
+	}
+}
+
+void LLHints::hide(LLNotificationPtr hint)
+{
+	hint_map_t::iterator found_it = sHints.find(hint);
+	if (found_it != sHints.end())
+	{
+		found_it->second->hide();
+		sHints.erase(found_it);
+	}
+}
+
+//static
+void LLHints::registerHintTarget(const std::string& name, LLHandle<LLView> target)
+{
+	sTargetRegistry.defaultRegistrar().add(name, target);
+}
+
+//static 
+LLHandle<LLView> LLHints::getHintTarget(const std::string& name)
+{
+	LLHandle<LLView>* handlep = sTargetRegistry.getValue(name);
+	if (handlep) 
+	{
+		return *handlep;
+	}
+	else
+	{
+		return LLHandle<LLView>();
+	}
+}
diff --git a/indra/newview/llhints.h b/indra/newview/llhints.h
new file mode 100644
index 0000000000000000000000000000000000000000..d2580df012f58b59afec2ea9d6b142edfdd278e7
--- /dev/null
+++ b/indra/newview/llhints.h
@@ -0,0 +1,54 @@
+/**
+ * @file llhints.h
+ * @brief Hint popups for displaying context sensitive help in a UI overlay
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-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_LLHINTS_H
+#define LL_LLHINTS_H
+
+#include "llpanel.h"
+#include "llnotifications.h"
+
+
+class LLHints
+{
+public:
+	static void show(LLNotificationPtr hint);
+	static void hide(LLNotificationPtr hint);
+	static void registerHintTarget(const std::string& name, LLHandle<LLView> target);
+	static LLHandle<LLView> getHintTarget(const std::string& name);
+private:
+	static LLRegistry<std::string, LLHandle<LLView> > sTargetRegistry;
+	typedef std::map<LLNotificationPtr, class LLHintPopup*> hint_map_t;
+	static hint_map_t sHints;
+};
+
+
+#endif
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index fc4113768678dbe3e973fe24c53c562879ee805d..148a5786cba252728b080cd941f0ca519eaff328 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -45,7 +45,9 @@
 #include "llvoavatarself.h" // to check gAgentAvatarp->isSitting()
 #include "llbottomtray.h"
 #include "llbutton.h"
+#include "llfirstuse.h"
 #include "llfloaterreg.h"
+#include "llhints.h"
 #include "lljoystickbutton.h"
 #include "lluictrlfactory.h"
 #include "llviewerwindow.h"
@@ -167,6 +169,7 @@ void LLFloaterMove::setVisible(BOOL visible)
 
 	if (visible)
 	{
+		LLFirstUse::notMoving(false);
 		// Attach the Stand/Stop Flying panel.
 		LLPanelStandStopFlying* ssf_panel = LLPanelStandStopFlying::getInstance();
 		ssf_panel->reparent(this);
@@ -566,6 +569,11 @@ void LLPanelStandStopFlying::setStandStopFlyingMode(EStandStopFlyingMode mode)
 {
 	LLPanelStandStopFlying* panel = getInstance();
 
+	if (mode == SSFM_STAND)
+	{
+		LLFirstUse::sit();
+		LLFirstUse::notMoving(false);
+	}
 	panel->mStandButton->setVisible(SSFM_STAND == mode);
 	panel->mStopFlyingButton->setVisible(SSFM_STOP_FLYING == mode);
 
@@ -596,6 +604,7 @@ BOOL LLPanelStandStopFlying::postBuild()
 	mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this));
 	mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance, TRUE));
 	mStandButton->setVisible(FALSE);
+	LLHints::registerHintTarget("stand_btn", mStandButton->getHandle());
 	
 	mStopFlyingButton = getChild<LLButton>("stop_fly_btn");
 	//mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE));
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 6cfd810c10875b1fb00e7b5da365c7c1e5555669..41a19a54a847ea058da6ecd59541b7fbcc926acc 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -38,6 +38,7 @@
 #include "llfloaterreg.h"
 #include "lltrans.h"
 
+#include "llfirstuse.h"
 #include "llnearbychatbar.h"
 #include "llbottomtray.h"
 #include "llagent.h"
@@ -490,6 +491,7 @@ BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::strin
 
 void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata)
 {
+	LLFirstUse::otherAvatarChatFirst(false);
 
 	LLNearbyChatBar* self = (LLNearbyChatBar *)userdata;
 
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index 1fadb126e4cb6589176610d4dbeeaf76a0798fea..4011552112e1e56c9b4de2f97961ab30956b4dde 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -37,6 +37,7 @@
 
 #include "llbottomtray.h"
 #include "llchatitemscontainerctrl.h"
+#include "llfirstuse.h"
 #include "llfloaterscriptdebug.h"
 #include "llnearbychat.h"
 #include "llrecentpeople.h"
@@ -347,7 +348,13 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
 	if(chat_msg.mMuted == TRUE)
 		return;
 	if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull())
-         LLRecentPeople::instance().add(chat_msg.mFromID);
+	{
+        LLRecentPeople::instance().add(chat_msg.mFromID);
+		if (chat_msg.mFromID != gAgentID)
+		{
+	 		LLFirstUse::otherAvatarChatFirst();
+		}
+	}
 
 	if(chat_msg.mText.empty())
 		return;//don't process empty messages
diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
index 99a1fedcf3a7784c52081eb44c258e029892629c..7b8f530178a58518b903575a6dad5c6a8eee350e 100644
--- a/indra/newview/llnotificationhandler.h
+++ b/indra/newview/llnotificationhandler.h
@@ -269,6 +269,20 @@ class LLOfferHandler : public LLSysHandler
 	void onRejectToast(LLUUID& id);
 };
 
+/**
+ * Handler for UI hints.
+ */
+class LLHintHandler : public LLSingleton<LLHintHandler>
+{
+public:
+	LLHintHandler();
+	virtual ~LLHintHandler();
+
+	// base interface functions
+	virtual bool processNotification(const LLSD& notify);
+};
+
+
 class LLHandlerUtil
 {
 public:
diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9460821b031bf9646c234b47bf411be445280b1
--- /dev/null
+++ b/indra/newview/llnotificationhinthandler.cpp
@@ -0,0 +1,64 @@
+/**
+ * @file llnotificationhinthandler.cpp
+ * @brief Notification Handler Class for UI Hints
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llnotificationhandler.h"
+#include "llhints.h"
+#include "llnotifications.h"
+
+using namespace LLNotificationsUI;
+
+LLHintHandler::LLHintHandler()
+{
+}
+
+LLHintHandler::~LLHintHandler()
+{
+}
+
+bool LLHintHandler::processNotification(const LLSD& notify)
+{
+	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+	std::string sigtype = notify["sigtype"].asString();
+	if (sigtype == "add" || sigtype == "load")
+	{
+		LLHints::show(notification);
+	}
+	else if (sigtype == "delete")
+	{
+		LLHints::hide(notification);
+	}
+	return false;
+}
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
index 4401bb953f9568e66a38fd18549bf02571fbea03..86496c9d02fa3f1a9ce632bf8a58d203212a39f5 100644
--- a/indra/newview/llnotificationmanager.cpp
+++ b/indra/newview/llnotificationmanager.cpp
@@ -66,6 +66,7 @@ void LLNotificationManager::init()
 	LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
 	LLNotificationChannel::buildChannel("IM Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytoast"));
 	LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer"));
+	LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint"));
   
 	LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
 	LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
@@ -74,6 +75,7 @@ void LLNotificationManager::init()
 	LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
 	LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
 	LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+	LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1));
 
 	mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD()));
 	mNotifyHandlers["notifytip"] =  boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD()));
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 230277280312567c2d70c2defa59d0d6badd5268..155e000bb80f5c51155c5f0c8ab7a3fec164efb8 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -746,7 +746,7 @@ void LLPanelGroupGeneral::updateMembers()
 		sSDTime += sd_timer.getElapsedTimeF32();
 
 		element_timer.reset();
-		LLScrollListItem* member_row = mListVisibleMembers->addElement(row);//, ADD_SORTED);
+		LLScrollListItem* member_row = mListVisibleMembers->addElement(row);
 		
 		if ( member->isOwner() )
 		{
diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index 1404cfcea24fa7079563a156a5dc528ec9f9d0d7..16d5f8140d6b780b014a4cec18914a3bacd161b9 100644
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -528,7 +528,7 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
 			row["columns"][4]["column"] = "hidden";
 			row["columns"][4]["value"] = hidden;
 			
-			mGroupParcelsp->addElement(row, ADD_SORTED);
+			mGroupParcelsp->addElement(row);
 		}
 	}
 }
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 7a28d10bafec0295cb9a3455c12d8fb657ba6f69..efc797cfe90c7bb5e8bdbf1029b1b125c8466387 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1631,7 +1631,7 @@ void LLPanelGroupMembersSubTab::updateMembers()
 			row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();
 			row["columns"][2]["font"] = "SANSSERIF_SMALL";
 
-			LLScrollListItem* member = mMembersList->addElement(row);//, ADD_SORTED);
+			LLScrollListItem* member = mMembersList->addElement(row);
 
 			LLUUID id = member->getUUID();
 			mHasMatch = TRUE;
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 4b23e63f12b29fda2ddd28c2a3fae3e50cb55237..58ed01896ad76fb05934459ea86cc7a71a52fba0 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -1110,9 +1110,10 @@ void LLPanelLogin::updateServerCombo()
 	{
 		if (!grid_choice->first.empty())
 		{
-			server_choice_combo->add(grid_choice->second, grid_choice->first, ADD_SORTED);
+			server_choice_combo->add(grid_choice->second, grid_choice->first);
 		}
 	}
+	server_choice_combo->sortByName();
 	
 	server_choice_combo->addSeparator(ADD_TOP);
 	
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index abf2b94b09e7dc3bb31e4ff1aa703fd5f6031897..c8a9176d929f5ed0f82c08548ce8b257bf09d55a 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -42,6 +42,7 @@
 
 #include "llcombobox.h"
 #include "llfiltereditor.h"
+#include "llfirstuse.h"
 #include "llfloaterreg.h"
 #include "llnotificationsutil.h"
 #include "lltabcontainer.h"
@@ -351,6 +352,8 @@ BOOL LLPanelPlaces::postBuild()
 
 void LLPanelPlaces::onOpen(const LLSD& key)
 {
+	LLFirstUse::notUsingDestinationGuide(false);
+
 	if (!mPlaceProfile || !mLandmarkInfo)
 		return;
 
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 9cc775d42738d798c17750e4541a68d59cf34a59..583b41aa573ae2602a450b234db26b2d2a1c0912 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -1178,7 +1178,7 @@ void LLPanelPrimMediaControls::setCurrentURL()
 //	if (media_address_combo && mCurrentURL != "about:blank")
 //	{
 //		media_address_combo->remove(mCurrentURL);
-//		media_address_combo->add(mCurrentURL, ADD_SORTED);
+//		media_address_combo->add(mCurrentURL);
 //		media_address_combo->selectByValue(mCurrentURL);
 //	}
 #else   // USE_COMBO_BOX_FOR_MEDIA_URL
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 0951586dd5077aa5208099149073bda4dd8deb68..f9189bfb2248cfadb2c14ad3709cedee91aa6e53 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -36,6 +36,7 @@
 #include "llappearancemgr.h"
 #include "llavataractions.h"
 #include "llbutton.h"
+#include "llfirstuse.h"
 #include "llinventorybridge.h"
 #include "llinventoryfunctions.h"
 #include "llinventorypanel.h"
@@ -128,6 +129,8 @@ BOOL LLSidepanelInventory::postBuild()
 
 void LLSidepanelInventory::onOpen(const LLSD& key)
 {
+	LLFirstUse::inventoryOffer(false);
+
 	if(key.size() == 0)
 		return;
 
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 7104f3934d802e902d5e57182aa7b2e97fb04dee..7cfc7748830bab51c60d7363f17b8312d769499a 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -37,6 +37,8 @@
 #include "llagentcamera.h"
 #include "llappviewer.h"
 #include "llbottomtray.h"
+#include "llfirstuse.h"
+#include "llhints.h"
 #include "llsidetray.h"
 #include "llviewerwindow.h"
 #include "llaccordionctrl.h"
@@ -422,6 +424,7 @@ void	LLSideTray::createButtons	()
 		{
 			mCollapseButton = createButton("",sidebar_tab->mImage,sidebar_tab->getTabTitle(),
 				boost::bind(&LLSideTray::onToggleCollapse, this));
+			LLHints::registerHintTarget("side_panel_btn", mCollapseButton->getHandle());
 		}
 		else
 		{
@@ -430,6 +433,8 @@ void	LLSideTray::createButtons	()
 			mTabButtons[name] = button;
 		}
 	}
+	LLHints::registerHintTarget("inventory_btn", mTabButtons["sidebar_inventory"]->getHandle());
+	LLHints::registerHintTarget("dest_guide_btn", mTabButtons["sidebar_places"]->getHandle());
 }
 
 void		LLSideTray::processTriState ()
@@ -466,6 +471,7 @@ void		LLSideTray::onTabButtonClick(string name)
 
 void		LLSideTray::onToggleCollapse()
 {
+	LLFirstUse::notUsingSidePanel(false);
 	if(mCollapsed)
 	{
 		expandSideBar();
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index a6bb4d4d5f9b4fd50ad2acfb09118d071747184a..6a081a573e6dbe8f9a2b3fa5df85f6028db28be1 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -39,6 +39,7 @@
 #include "llagentcamera.h"
 #include "llbutton.h"
 #include "llcommandhandler.h"
+#include "llfirstuse.h"
 #include "llviewercontrol.h"
 #include "llfloaterbuycurrency.h"
 #include "llbuycurrencyhtml.h"
@@ -47,6 +48,7 @@
 #include "llpanelvolumepulldown.h"
 #include "llfloaterregioninfo.h"
 #include "llfloaterscriptdebug.h"
+#include "llhints.h"
 #include "llhudicon.h"
 #include "llnavigationbar.h"
 #include "llkeyboard.h"
@@ -191,6 +193,8 @@ BOOL LLStatusBar::postBuild()
 	mMediaToggle->setClickedCallback( &LLStatusBar::onClickMediaToggle, this );
 	mMediaToggle->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterNearbyMedia, this));
 
+	LLHints::registerHintTarget("linden_balance", getChild<LLView>("balance_bg")->getHandle());
+
 	gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2));
 
 	// Adding Net Stat Graph
@@ -338,6 +342,11 @@ void LLStatusBar::creditBalance(S32 credit)
 
 void LLStatusBar::setBalance(S32 balance)
 {
+	if (balance > getBalance() && getBalance() != 0)
+	{
+		LLFirstUse::receiveLindens();
+	}
+
 	std::string money_str = LLResMgr::getInstance()->getMonetaryString( balance );
 
 	LLTextBox* balance_box = getChild<LLTextBox>("balance");
@@ -460,6 +469,7 @@ void LLStatusBar::onClickBuyCurrency()
 	// open a currency floater - actual one open depends on 
 	// value specified in settings.xml
 	LLBuyCurrencyHTML::openCurrencyFloater();
+	LLFirstUse::receiveLindens(false);
 }
 
 void LLStatusBar::onMouseEnterVolume()
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 1f3785d7332d8b05d54105017ec6c1b21ddadbd2..d89ee13b9548dbcfaa0af1ab51e279dbed326295 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -2826,25 +2826,18 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
 			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << plugin->getClickTarget() << "\", uri is " << plugin->getClickURL() << LL_ENDL;
 			// retrieve the event parameters
 			std::string url = plugin->getClickURL();
+			std::string target = plugin->getClickTarget();
 			U32 target_type = plugin->getClickTargetType();
-			
+
 			switch (target_type)
 			{
-			case LLPluginClassMedia::TARGET_EXTERNAL:
-				// force url to external browser
-				LLWeb::loadURLExternal(url);
-				break;
-			case LLPluginClassMedia::TARGET_BLANK:
-				// open in SL media browser or external browser based on user pref
-				LLWeb::loadURL(url);
-				break;
 			case LLPluginClassMedia::TARGET_NONE:
 				// ignore this click and let media plugin handle it
 				break;
-			case LLPluginClassMedia::TARGET_OTHER:
-				LL_WARNS("LinkTarget") << "Unsupported link target type" << LL_ENDL;
+			default:
+				// loadURL now handles distinguishing between _blank, _external, and other named targets.
+				LLWeb::loadURL(url, target);
 				break;
-			default: break;
 			}
 		};
 		break;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index a04c919310ff192ed36229aa074cecc822b9a0b2..9bb734a3d3d7b48149a304893f81b777d1639858 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -56,6 +56,7 @@
 #include "llagentcamera.h"
 #include "llcallingcard.h"
 #include "llbuycurrencyhtml.h"
+#include "llfirstuse.h"
 #include "llfloaterbuyland.h"
 #include "llfloaterland.h"
 #include "llfloaterregioninfo.h"
@@ -1763,6 +1764,8 @@ void inventory_offer_handler(LLOfferInfo* info)
 		return;
 	}
 
+	LLFirstUse::inventoryOffer();
+
 	// Avoid the Accept/Discard dialog if the user so desires. JC
 	if (gSavedSettings.getBOOL("AutoAcceptNewInventory")
 		&& (info->mType == LLAssetType::AT_NOTECARD
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index b36af7d95b0b79ecbdf614bd54000daef5a1eeaa..cfb8b077e58a101d6162ff654b30cfc954d4b317 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -102,6 +102,7 @@
 #include "llface.h"
 #include "llfeaturemanager.h"
 #include "llfilepicker.h"
+#include "llfirstuse.h"
 #include "llfloater.h"
 #include "llfloaterbuildoptions.h"
 #include "llfloaterbuyland.h"
@@ -1529,6 +1530,7 @@ void LLViewerWindow::initBase()
 	mNonSideTrayView = main_view->getChildView("non_side_tray_view")->getHandle();
 	mFloaterViewHolder = main_view->getChildView("floater_view_holder")->getHandle();
 	mPopupView = main_view->getChild<LLPopupView>("popup_holder");
+	mHintHolder = main_view->getChild<LLView>("hint_holder")->getHandle();
 
 	// Constrain floaters to inside the menu and status bar regions.
 	gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
@@ -2422,6 +2424,18 @@ void LLViewerWindow::updateUI()
 
 	static std::string last_handle_msg;
 
+	if (gLoggedInTime.getStarted())
+	{
+		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("DestinationGuideHintTimeout"))
+		{
+			LLFirstUse::notUsingDestinationGuide();
+		}
+		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("SidePanelHintTimeout"))
+		{
+			LLFirstUse::notUsingSidePanel();
+		}
+	}
+
 	LLConsole::updateClass();
 
 	// animate layout stacks so we have up to date rect for world view
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 1e0200a075aa17dc7d56870af0a6e3141a0ff7a3..cd1ee8a5fd7098831b4b551f99a2f56240b0f901 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -294,6 +294,7 @@ class LLViewerWindow : public LLWindowCallbacks
 	void			updateWorldViewRect(bool use_full_window=false);
 	LLView*			getNonSideTrayView() { return mNonSideTrayView.get(); }
 	LLView*			getFloaterViewHolder() { return mFloaterViewHolder.get(); }
+	LLView*			getHintHolder() { return mHintHolder.get(); }
 	BOOL			handleKey(KEY key, MASK mask);
 	void			handleScrollWheel	(S32 clicks);
 
@@ -453,6 +454,7 @@ class LLViewerWindow : public LLWindowCallbacks
 	LLHandle<LLView> mWorldViewPlaceholder;	// widget that spans the portion of screen dedicated to rendering the 3d world
 	LLHandle<LLView> mNonSideTrayView;		// parent of world view + bottom bar, etc...everything but the side tray
 	LLHandle<LLView> mFloaterViewHolder;	// container for floater_view
+	LLHandle<LLView> mHintHolder;			// container for hints
 	LLPopupView*	mPopupView;			// container for transient popups
 	
 	class LLDebugText* mDebugText; // Internal class for debug text
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index 5c9633c03688ecfb74106ed5a7ddffa649043d3b..b61109d4900c626a8ff3cbdf8ed77034518ac0aa 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -84,23 +84,23 @@ void LLWeb::initClass()
 
 
 // static
-void LLWeb::loadURL(const std::string& url)
+void LLWeb::loadURL(const std::string& url, const std::string& target)
 {
-	if (gSavedSettings.getBOOL("UseExternalBrowser"))
+	if (gSavedSettings.getBOOL("UseExternalBrowser") || (target == "_external"))
 	{
 		loadURLExternal(url);
 	}
 	else
 	{
-		loadURLInternal(url);
+		loadURLInternal(url, target);
 	}
 }
 
 
 // static
-void LLWeb::loadURLInternal(const std::string &url)
+void LLWeb::loadURLInternal(const std::string &url, const std::string& target)
 {
-	LLFloaterReg::showInstance("media_browser", url);
+	LLFloaterMediaBrowser::create(url, target);
 }
 
 
diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h
index 1119b80bb4f94ad327ff5918275eaa72d892dce0..20c7391dbfb8993958619b4b5c41ef76ee77a164 100644
--- a/indra/newview/llweb.h
+++ b/indra/newview/llweb.h
@@ -49,11 +49,14 @@ class LLWeb
 	static void initClass();
 	
 	/// Load the given url in the user's preferred web browser
-	static void loadURL(const std::string& url);
+	static void loadURL(const std::string& url, const std::string& target);
+	static void loadURL(const std::string& url) { loadURL(url, LLStringUtil::null); }
 	/// Load the given url in the user's preferred web browser	
-	static void loadURL(const char* url) { loadURL( ll_safe_string(url) ); }
+	static void loadURL(const char* url, const std::string& target) { loadURL( ll_safe_string(url), target); }
+	static void loadURL(const char* url) { loadURL( ll_safe_string(url), LLStringUtil::null ); }
 	/// Load the given url in the Second Life internal web browser
-	static void loadURLInternal(const std::string &url);
+	static void loadURLInternal(const std::string &url, const std::string& target);
+	static void loadURLInternal(const std::string &url) { loadURLInternal(url, LLStringUtil::null); }
 	/// Load the given url in the operating system's web browser, async if we want to return immediately
 	/// before browser has spawned
 	static void loadURLExternal(const std::string& url);
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 082b37d80b9dba749e39bec43620822c2d71d175..9fbbfb1d2bdae1bac707dd9c4d450478c77511b4 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -645,5 +645,11 @@ with the same filename but different name
   <texture name="buy_off" file_name="widgets/buy_off.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>
   <texture name="buy_over" file_name="widgets/buy_over.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>
   <texture name="buy_press" file_name="widgets/buy_press.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>
-  
+
+  <texture name="hint_background" file_name="windows/hint_background.png" preload="false" scale.left="8" scale.top="70" scale.right="195" scale.bottom="11"/>
+  <texture name="hint_arrow_left" file_name="windows/hint_arrow_left.png" preload="false"/>
+  <texture name="hint_arrow_right" file_name="windows/hint_arrow_right.png" preload="false"/>
+  <texture name="hint_arrow_up" file_name="windows/hint_arrow_up.png" preload="false"/>
+  <texture name="hint_arrow_down" file_name="windows/hint_arrow_down.png" preload="false"/>
+
 </textures>
diff --git a/indra/newview/skins/default/textures/windows/hint_arrow_down.png b/indra/newview/skins/default/textures/windows/hint_arrow_down.png
new file mode 100644
index 0000000000000000000000000000000000000000..11ab3c2d0ce025c91c7f5581e82947fdf373170d
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/hint_arrow_down.png differ
diff --git a/indra/newview/skins/default/textures/windows/hint_arrow_left.png b/indra/newview/skins/default/textures/windows/hint_arrow_left.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5c597a5506a50b77832927369489daa81891d75
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/hint_arrow_left.png differ
diff --git a/indra/newview/skins/default/textures/windows/hint_arrow_right.png b/indra/newview/skins/default/textures/windows/hint_arrow_right.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f89187e136f07963fc4ada15ad72d947faf5c6f
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/hint_arrow_right.png differ
diff --git a/indra/newview/skins/default/textures/windows/hint_arrow_up.png b/indra/newview/skins/default/textures/windows/hint_arrow_up.png
new file mode 100644
index 0000000000000000000000000000000000000000..1050097efb4288925e6bd0ca04bdb186516d5e9e
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/hint_arrow_up.png differ
diff --git a/indra/newview/skins/default/textures/windows/hint_background.png b/indra/newview/skins/default/textures/windows/hint_background.png
new file mode 100644
index 0000000000000000000000000000000000000000..0839a952059d55eb83c45713e18a23072f98149d
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/hint_background.png differ
diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml
index c02d6075866ab69c720d1dcae353d92c9316d122..18f3b9ab0670c06f2aba6bbdb381f0d424329383 100644
--- a/indra/newview/skins/default/xui/en/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml
@@ -9,7 +9,7 @@
  name="floater_about"
  help_topic="floater_about"
  save_rect="true"
- single_instance="true"
+ auto_tile="true"
  title="MEDIA BROWSER"
  width="820">
     <floater.string
diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml
index a1ca910cbbb96b7d84d29d5526f675b980dba296..0bf5717de88df38b1cdc5a9657d257ae38700941 100644
--- a/indra/newview/skins/default/xui/en/main_view.xml
+++ b/indra/newview/skins/default/xui/en/main_view.xml
@@ -208,6 +208,13 @@
           bottom="-1"
           height="11" />
   </panel>
+  <view top="0"
+        left="0"
+        width="1024"
+        height="768"
+        name="hint_holder"
+        mouse_opaque="false"
+        follows="all"/>
   <menu_holder top="0"
                follows="all"
                height="768"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 609a9b09be4e9af0504bf2c125b8c8408a08daba..60b0b1e8dcfd553100795c2ce8adabd2175efed2 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6397,6 +6397,57 @@ Mute everyone?
     <unique/>
   </notification>
 
+  <notification
+  name="HintChat"
+  label="Chat"
+  type="hint">
+    To join the conversation, type into the chat field below.
+  </notification>
+
+  <notification
+  name="HintSit"
+  label="Stand"
+  type="hint">
+    To stand up and exit the sitting position, click the Stand button.
+  </notification>
+  
+  <notification
+  name="HintDestinationGuide"
+  label="Explore the World"
+  type="hint">
+    The Destination Guide contains thousands of new places to discover. Select a location and choose Teleport to start exploring.
+  </notification>
+  
+  <notification
+    name="HintSidePanel"
+    label="Side Panel"
+    type="hint">
+    Get quick access to your inventory, outfits, profiles and more in the side panel.
+    <!--<unique/>-->
+  </notification>
+
+  <notification
+  name="HintMove"
+  label="Move"
+  type="hint">
+    To walk or run, open the Move Panel and use the directional arrows to navigate. You can also use the directional keys on your keyboard.
+    <!--<unique/>-->
+  </notification>
+
+  <notification
+  name="HintInventory"
+  label="Inventory"
+  type="hint">
+    Check your inventory to find items. Newest items can be easily found in the Recent tab.
+  </notification>
+
+  <notification
+  name="HintLindenDollar"
+  label="You've got Linden Dollars!"
+  type="hint">
+    Here's your current balance of L$. Click Buy L$ to purchase more Linden Dollars.
+  </notification>
+
   <global name="UnsupportedCPU">
 - Your CPU speed does not meet the minimum requirements.
   </global>
diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
index 76f7484c6803deb2d088a312d6ebf3452b7c68f2..1e1d2d18ca30fd7f7de98fa33732d31ac3134cc9 100644
--- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
@@ -60,6 +60,8 @@
      left="0"
      right="-1"
      top="0"
+     sort_column="0"
+     sort_ascending="true"
      name="group_parcel_list"
      width="313">
         <scroll_list.columns
diff --git a/indra/newview/skins/default/xui/en/panel_hint.xml b/indra/newview/skins/default/xui/en/panel_hint.xml
new file mode 100644
index 0000000000000000000000000000000000000000..54ea08e5d430190b68fb81cb643924ef7fef382e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_hint.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ name="hint"
+ width="205"
+ height="100"
+ background_opaque="true"
+ background_visible="true"
+ layout="topleft" 
+ bg_opaque_image="hint_background">
+  <text name="hint_title"
+        font="SansSerifMedium" 
+        left="8"
+        right="180"
+        top="8"
+        bottom="20"
+        follows="left|right|top"
+        text_color="White"
+        wrap="false"/>
+  <text name="hint_text"
+        left="8"
+        right="197"
+        top="26"
+        bottom="90"
+        follows="all" 
+        text_color="White"
+        wrap="true"/>
+  <button right="197" 
+          top="8"
+          width="16" 
+          height="16"
+          name="close" 
+          follows="right|top" 
+          image_unselected="Icon_Close_Foreground"
+          image_selected="Icon_Close_Press"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml
index 516457dd931d066b7fa558fca2e2b220403990e4..559df5bec946a8b0e7f16c28e1258d100ae92cd2 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml
@@ -57,6 +57,8 @@
      left="10"
      multi_select="true"
      name="enabled_popups"
+     sort_column="0"
+     sort_ascending="true" 
      width="495" />
 	 <button
 	 enabled_control="FirstSelectedDisabledPopups"
@@ -103,6 +105,8 @@
      height="140"
      layout="topleft"
      left="10"
+     sort_column="0"
+     sort_ascending="true"
      multi_select="true"
      name="disabled_popups"
      width="495" />
diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
index 9dff00fa0b93019f87595aac6953a5c879b35b78..c5e8bf5803dc57358e56a4599ef39908d5a7c8b2 100644
--- a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
+++ b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
@@ -79,6 +79,8 @@
      layout="topleft"
      left_delta="0"
      multi_select="true"
+     sort_column="0"
+     sort_ascending="true"
      name="scripts_list"
      top_delta="16"
      width="460">
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp
index 7a544debb2b94cd811804e61250d0f05db125383..166905c37cfb8e710d6d0a6bdf79ab0fd91d7127 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.cpp
+++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp
@@ -959,6 +959,23 @@ mediaPanel*  LLMediaPluginTest::findMediaPanel( LLPluginClassMedia* source )
 	return result;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+//
+mediaPanel* LLMediaPluginTest::findMediaPanel( const std::string &target_name )
+{
+	mediaPanel *result = NULL;
+
+	for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
+	{
+		if ( mMediaPanels[ panel ]->mTarget == target_name )
+		{
+			result = mMediaPanels[ panel ];
+		}
+	}
+
+	return result;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 //
 void LLMediaPluginTest::navigateToNewURI( std::string uri )
@@ -1571,7 +1588,7 @@ std::string LLMediaPluginTest::pluginNameFromMimeType( std::string& mime_type )
 
 ////////////////////////////////////////////////////////////////////////////////
 //
-void LLMediaPluginTest::addMediaPanel( std::string url )
+mediaPanel* LLMediaPluginTest::addMediaPanel( std::string url )
 {
 	// Get the plugin filename using the URL
 	std::string mime_type = mimeTypeFromUrl( url );
@@ -1603,7 +1620,7 @@ void LLMediaPluginTest::addMediaPanel( std::string url )
 	if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
 	{
 		std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
-		return;
+		return NULL;
 	}
 	std::string user_data_path = std::string( cwd ) + "/";
 #endif
@@ -1673,6 +1690,8 @@ void LLMediaPluginTest::addMediaPanel( std::string url )
 
 		std::cout << "Adding new media panel for " << url << "(" << media_width << "x" << media_height << ") with index " << panel->mId << " - total panels = " << mMediaPanels.size() << std::endl;
 	}
+	
+	return panel;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1778,15 +1797,15 @@ void LLMediaPluginTest::updateMediaPanel( mediaPanel* panel )
 
 ////////////////////////////////////////////////////////////////////////////////
 //
-void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )
+mediaPanel* LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )
 {
 	// no media panels so we can't change anything - have to add
 	if ( mMediaPanels.size() == 0 )
-		return;
+		return NULL;
 
 	// sanity check
 	if ( ! panel )
-		return;
+		return NULL;
 
 	int index;
 	for(index = 0; index < (int)mMediaPanels.size(); index++)
@@ -1798,7 +1817,7 @@ void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )
 	if(index >= (int)mMediaPanels.size())
 	{
 		// panel isn't in mMediaPanels
-		return;
+		return NULL;
 	}
 
 	std::cout << "Replacing media panel with index " << panel->mId << std::endl;
@@ -1840,7 +1859,7 @@ void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )
 	if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
 	{
 		std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
-		return;
+		return NULL;
 	}
 	std::string user_data_path = std::string( cwd ) + "/";
 #endif
@@ -1880,6 +1899,8 @@ void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )
 	// load and start the URL
 	panel->mMediaSource->loadURI( url );
 	panel->mMediaSource->start();
+	
+	return panel;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2139,7 +2160,46 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e
 		break;
 
 		case MEDIA_EVENT_CLICK_LINK_HREF:
-			std::cerr <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << std::endl;
+		{
+			std::cerr <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << ", target is " << self->getClickTarget() << std::endl;
+			// retrieve the event parameters
+			std::string url = self->getClickURL();
+			std::string target = self->getClickTarget();
+			U32 target_type = self->getClickTargetType();
+
+			switch (target_type)
+			{
+				case LLPluginClassMedia::TARGET_NONE:
+					// ignore this click
+				break;
+				
+				case LLPluginClassMedia::TARGET_EXTERNAL:
+					// this should open in an external browser, but since this is a test app we don't care.
+				break;
+				
+				case LLPluginClassMedia::TARGET_BLANK:
+					// Create a new panel with the specified URL.
+					addMediaPanel(url);
+				break;
+
+				case LLPluginClassMedia::TARGET_OTHER:
+					mediaPanel *target_panel = findMediaPanel(target);
+					if(target_panel)
+					{
+						target_panel = replaceMediaPanel(target_panel, url);
+					}
+					else
+					{
+						target_panel = addMediaPanel(url);
+					}
+
+					if(target_panel)
+					{
+						target_panel->mTarget = target;
+					}
+				break;
+			}
+		}
 		break;
 
 		case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.h b/indra/test_apps/llplugintest/llmediaplugintest.h
index 5d08e4214891dc8e6bb88cb9ad924f7ad8269b46..ecd6cbfc4ff0575d7e147f272bd6d9b9666f8e1e 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.h
+++ b/indra/test_apps/llplugintest/llmediaplugintest.h
@@ -56,6 +56,7 @@ struct mediaPanel
 		int mId;
 		std::string mStartUrl;
 		std::string mMimeType;
+		std::string mTarget;
 		LLPluginClassMedia *mMediaSource;
 		int mMediaWidth;
 		int mMediaHeight;
@@ -96,16 +97,17 @@ class LLMediaPluginTest : public LLPluginClassMediaOwner
 		void draw( int draw_type );
 		void windowPosToTexturePos( int window_x, int window_y, int& media_x, int& media_y, int& id );
 
-		void addMediaPanel( std::string url );
+		mediaPanel* addMediaPanel( std::string url );
 		void updateMediaPanel( mediaPanel* panel );
 		void remMediaPanel( mediaPanel* panel );
-		void replaceMediaPanel( mediaPanel* panel, std::string url );
+		mediaPanel* replaceMediaPanel( mediaPanel* panel, std::string url );
 		void getRandomMediaSize( int& width, int& height, std::string mime_type );
 		void navigateToNewURI( std::string uri );
         void initUrlHistory( std::string uri );
 		void selectPanelById( int id );
 		void selectPanel( mediaPanel* panel );
 		mediaPanel* findMediaPanel( LLPluginClassMedia* panel );
+		mediaPanel* findMediaPanel( const std::string &target_name );
 		void makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels );
 		void makeChrome();
 		void resetView();
diff --git a/install.xml b/install.xml
index 3795fc3757233ae9eb2b86ca4434758259c2e847..a3f5b5c7bc3269a434e1d56a5a18be3ffee8576e 100644
--- a/install.xml
+++ b/install.xml
@@ -185,7 +185,7 @@
         <key>copyright</key>
         <string>various</string>
         <key>description</key>
-        <string>A set of portable C++ libraries which provide a wide set of functionality. Used primarily for tokenization. </string>
+        <string>A set of portable C++ libraries which provide a wide set of functionality. </string>
         <key>license</key>
         <string>boost</string>
         <key>packages</key>
@@ -981,9 +981,9 @@ anguage Infrstructure (CLI) international standard</string>
           <key>darwin</key>
           <map>
             <key>md5sum</key>
-            <string>becffca6bd8dcb239de284ea2a8b485b</string>
+            <string>093c977ef0ef2396cc235b3620329a87</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6+cookies-darwin-20100617.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20100805.tar.bz2</uri>
           </map>
           <key>linux</key>
           <map>
@@ -995,9 +995,9 @@ anguage Infrstructure (CLI) international standard</string>
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>df1bdd683128e060d60e435f65d8f7e8</string>
+            <string>1591dab02d6135c204a7a31bf72d8ac1</string>
             <key>url</key>
-            <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100617.tar.bz2</uri>
+            <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100809.tar.bz2</uri>
           </map>
         </map>
       </map>