diff --git a/.hgtags b/.hgtags
index 8b1b58bc5e5600506c76cd47c7e257db182b238f..d3172eb75aa6e6b8eaaa26681f7d1ef8ad160c5f 100644
--- a/.hgtags
+++ b/.hgtags
@@ -22,4 +22,3 @@ c6969fe44e58c542bfc6f1bd6c0be2fa860929ac 2-1-beta-4
 d2382d374139850efa5bb6adfb229e3e656cfc40 howard-demo
 d40ac9dd949cba6dab1cc386da6a2027690c2519 alpha-5
 d6781e22543acd7e21b967209f3c6e7003d380e3 fork to viewer-2-0
-c6e6324f5be1401f077ad18a4a0f6b46451c2f7b last_sprint
diff --git a/etc/message.xml b/etc/message.xml
index c17ae3656d0d8850b496a8f5ce36879bc1062040..ebbb4e57a96fafd0407f74861500e67daf1916cf 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -370,6 +370,14 @@
 				</map>
 
 				<!-- Server to client -->
+				<key>DisplayNameUpdate</key>
+				<map>
+					<key>flavor</key>
+					<string>llsd</string>
+					<key>trusted-sender</key>
+					<boolean>true</boolean>
+				</map>
+                
 				<key>ParcelVoiceInfo</key>
 				<map>
 					<key>flavor</key>
@@ -426,6 +434,14 @@
           <boolean>true</boolean>
         </map>
 
+        <key>SetDisplayNameReply</key>
+        <map>
+          <key>flavor</key>
+          <string>llsd</string>
+          <key>trusted-sender</key>
+          <boolean>true</boolean>
+        </map>
+
         <key>DirLandReply</key>
         <map>
           <key>flavor</key>
diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py
index 104585c19532f0b50ce91778494a90bc73d2b8cf..ffc32525a4c5796738b136669a5c111691356e7a 100644
--- a/indra/cmake/run_build_test.py
+++ b/indra/cmake/run_build_test.py
@@ -24,7 +24,7 @@
 
 $LicenseInfo:firstyear=2009&license=viewerlgpl$
 Second Life Viewer Source Code
-Copyright (C) 2010, Linden Research, Inc.
+Copyright (C) 2009-2010, Linden Research, Inc.
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
diff --git a/indra/lib/python/indra/__init__.py b/indra/lib/python/indra/__init__.py
index e010741c1c5e09c64b0e906dd565803715fd2420..0c5053cf499ec94654cdf3054d0763e9c725bc1e 100644
--- a/indra/lib/python/indra/__init__.py
+++ b/indra/lib/python/indra/__init__.py
@@ -4,7 +4,7 @@
 
 $LicenseInfo:firstyear=2006&license=viewerlgpl$
 Second Life Viewer Source Code
-Copyright (C) 2010, Linden Research, Inc.
+Copyright (C) 2006-2010, Linden Research, Inc.
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 2a036df06e737c718e63beeb4e77c7128ecfe16b..77740fb8bf9b5dcc100d49789463a2245949f922 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -33,6 +33,7 @@ set(llcommon_SOURCE_FILES
     llapp.cpp
     llapr.cpp
     llassettype.cpp
+    llavatarname.cpp
     llbase32.cpp
     llbase64.cpp
     llcommon.cpp
@@ -115,6 +116,7 @@ set(llcommon_HEADER_FILES
     llallocator.h
     llallocator_heap_profile.h
     llagentconstants.h
+    llavatarname.h
     llapp.h
     llapr.h
     llassettype.h
diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..14dc41591b7072a2e4515c2d3308d9f280218759
--- /dev/null
+++ b/indra/llcommon/llavatarname.cpp
@@ -0,0 +1,119 @@
+/** 
+ * @file llavatarname.cpp
+ * @brief Represents name-related data for an avatar, such as the
+ * username/SLID ("bobsmith123" or "james.linden") and the display
+ * name ("James Cook")
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2010, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llavatarname.h"
+
+#include "lldate.h"
+#include "llsd.h"
+
+// Store these in pre-built std::strings to avoid memory allocations in
+// LLSD map lookups
+static const std::string USERNAME("username");
+static const std::string DISPLAY_NAME("display_name");
+static const std::string LEGACY_FIRST_NAME("legacy_first_name");
+static const std::string LEGACY_LAST_NAME("legacy_last_name");
+static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default");
+static const std::string DISPLAY_NAME_EXPIRES("display_name_expires");
+static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update");
+
+LLAvatarName::LLAvatarName()
+:	mUsername(),
+	mDisplayName(),
+	mLegacyFirstName(),
+	mLegacyLastName(),
+	mIsDisplayNameDefault(false),
+	mIsDummy(false),
+	mExpires(F64_MAX),
+	mNextUpdate(0.0)
+{ }
+
+bool LLAvatarName::operator<(const LLAvatarName& rhs) const
+{
+	if (mUsername == rhs.mUsername)
+		return mDisplayName < rhs.mDisplayName;
+	else
+		return mUsername < rhs.mUsername;
+}
+
+LLSD LLAvatarName::asLLSD() const
+{
+	LLSD sd;
+	sd[USERNAME] = mUsername;
+	sd[DISPLAY_NAME] = mDisplayName;
+	sd[LEGACY_FIRST_NAME] = mLegacyFirstName;
+	sd[LEGACY_LAST_NAME] = mLegacyLastName;
+	sd[IS_DISPLAY_NAME_DEFAULT] = mIsDisplayNameDefault;
+	sd[DISPLAY_NAME_EXPIRES] = LLDate(mExpires);
+	sd[DISPLAY_NAME_NEXT_UPDATE] = LLDate(mNextUpdate);
+	return sd;
+}
+
+void LLAvatarName::fromLLSD(const LLSD& sd)
+{
+	mUsername = sd[USERNAME].asString();
+	mDisplayName = sd[DISPLAY_NAME].asString();
+	mLegacyFirstName = sd[LEGACY_FIRST_NAME].asString();
+	mLegacyLastName = sd[LEGACY_LAST_NAME].asString();
+	mIsDisplayNameDefault = sd[IS_DISPLAY_NAME_DEFAULT].asBoolean();
+	LLDate expires = sd[DISPLAY_NAME_EXPIRES];
+	mExpires = expires.secondsSinceEpoch();
+	LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
+	mNextUpdate = next_update.secondsSinceEpoch();
+}
+
+std::string LLAvatarName::getCompleteName() const
+{
+	std::string name;
+	if (!mUsername.empty())
+	{
+		name = mDisplayName + " (" + mUsername + ")";
+	}
+	else
+	{
+		// ...display names are off, legacy name is in mDisplayName
+		name = mDisplayName;
+	}
+	return name;
+}
+
+std::string LLAvatarName::getLegacyName() const
+{
+	std::string name;
+	name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
+	name = mLegacyFirstName;
+	name += " ";
+	name += mLegacyLastName;
+	return name;
+}
diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h
new file mode 100644
index 0000000000000000000000000000000000000000..650a09a125e52fd77a9ebb270cc88b71d00b90ff
--- /dev/null
+++ b/indra/llcommon/llavatarname.h
@@ -0,0 +1,101 @@
+/** 
+ * @file llavatarname.h
+ * @brief Represents name-related data for an avatar, such as the
+ * username/SLID ("bobsmith123" or "james.linden") and the display
+ * name ("James Cook")
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2010, 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 LLAVATARNAME_H
+#define LLAVATARNAME_H
+
+#include <string>
+
+class LLSD;
+
+class LL_COMMON_API LLAvatarName
+{
+public:
+	LLAvatarName();
+	
+	bool operator<(const LLAvatarName& rhs) const;
+
+	LLSD asLLSD() const;
+
+	void fromLLSD(const LLSD& sd);
+
+	// For normal names, returns "James Linden (james.linden)"
+	// When display names are disabled returns just "James Linden"
+	std::string getCompleteName() const;
+
+	// Returns "James Linden" or "bobsmith123 Resident" for backwards
+	// compatibility with systems like voice and muting
+	// *TODO: Eliminate this in favor of username only
+	std::string getLegacyName() const;
+
+	// "bobsmith123" or "james.linden", US-ASCII only
+	std::string mUsername;
+
+	// "Jose' Sanchez" or "James Linden", UTF-8 encoded Unicode
+	// Contains data whether or not user has explicitly set
+	// a display name; may duplicate their username.
+	std::string mDisplayName;
+
+	// For "James Linden", "James"
+	// For "bobsmith123", "bobsmith123"
+	// Used to communicate with legacy systems like voice and muting which
+	// rely on old-style names.
+	// *TODO: Eliminate this in favor of username only
+	std::string mLegacyFirstName;
+
+	// For "James Linden", "Linden"
+	// For "bobsmith123", "Resident"
+	// see above for rationale
+	std::string mLegacyLastName;
+
+	// If true, both display name and SLID were generated from
+	// a legacy first and last name, like "James Linden (james.linden)"
+	bool mIsDisplayNameDefault;
+
+	// Under error conditions, we may insert "dummy" records with
+	// names like "???" into caches as placeholders.  These can be
+	// shown in UI, but are not serialized.
+	bool mIsDummy;
+
+	// Names can change, so need to keep track of when name was
+	// last checked.
+	// Unix time-from-epoch seconds for efficiency
+	F64 mExpires;
+	
+	// You can only change your name every N hours, so record
+	// when the next update is allowed
+	// Unix time-from-epoch seconds
+	F64 mNextUpdate;
+};
+
+#endif
diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h
index 52b85c7bba132691d43b7022a1e73b44cdd106ab..87c2d6775ba9c273aff0f39fb5b778d9b6d4c60f 100644
--- a/indra/llcommon/llchat.h
+++ b/indra/llcommon/llchat.h
@@ -28,7 +28,6 @@
 #ifndef LL_LLCHAT_H
 #define LL_LLCHAT_H
 
-#include "llstring.h"
 #include "lluuid.h"
 #include "v3math.h"
 
@@ -71,7 +70,7 @@ typedef enum e_chat_style
 class LLChat
 {
 public:
-	LLChat(const std::string& text = LLStringUtil::null)
+	LLChat(const std::string& text = std::string())
 	:	mText(text),
 		mFromName(),
 		mFromID(),
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 33b55d843cabf4cfc3513d660c7545afcb7d37f2..fe5d61763ba956b45144268e4083e437fb2f2c60 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -731,14 +731,17 @@ void LLStringOps::setupDatetimeInfo (bool daylight)
 
 	nowT = time (NULL);
 
-	tmpT = localtime (&nowT);
-	localT = mktime (tmpT);
-
 	tmpT = gmtime (&nowT);
 	gmtT = mktime (tmpT);
 
+	tmpT = localtime (&nowT);
+	localT = mktime (tmpT);
+	
 	sLocalTimeOffset = (long) (gmtT - localT);
-
+	if (tmpT->tm_isdst)
+	{
+		sLocalTimeOffset -= 60 * 60;	// 1 hour
+	}
 
 	sPacificDaylightTime = daylight;
 	sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;
diff --git a/indra/llinventory/lltransactionflags.cpp b/indra/llinventory/lltransactionflags.cpp
index 8f7eeb8efac64aff2c82b86a5d344fed9cb8ec1e..ee0e6ae26ca0a5c313b8376f6044497d127af9fb 100644
--- a/indra/llinventory/lltransactionflags.cpp
+++ b/indra/llinventory/lltransactionflags.cpp
@@ -108,6 +108,9 @@ std::string build_transfer_message_to_source(
 	std::ostringstream ostr;
 	if(dest_id.isNull())
 	{
+		// *NOTE: Do not change these strings!  The viewer matches
+		// them in llviewermessage.cpp to perform localization.
+		// If you need to make changes, add a new, localizable message. JC
 		ostr << "You paid L$" << amount;
 		switch(transaction_type)
 		{
@@ -154,6 +157,9 @@ std::string build_transfer_message_to_destination(
 		return description;
 	}
 	std::ostringstream ostr;
+	// *NOTE: Do not change these strings!  The viewer matches
+	// them in llviewermessage.cpp to perform localization.
+	// If you need to make changes, add a new, localizable message. JC
 	ostr << source_name << " paid you L$" << amount;
 	append_reason(ostr, transaction_type, description);
 	ostr << ".";
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 1f8ee2671663f9fdd69aaa724da1e845e6d54925..1cad0f6d22df836cef6f8ef776a73f58822fefc6 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -25,6 +25,7 @@ set(llmessage_SOURCE_FILES
     llares.cpp
     llareslistener.cpp
     llassetstorage.cpp
+    llavatarnamecache.cpp
     llblowfishcipher.cpp
     llbuffer.cpp
     llbufferstream.cpp
@@ -110,6 +111,7 @@ set(llmessage_HEADER_FILES
     llares.h
     llareslistener.h
     llassetstorage.h
+    llavatarnamecache.h
     llblowfishcipher.h
     llbuffer.h
     llbufferstream.h
@@ -248,6 +250,7 @@ if (LL_TESTS)
     "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
     )
 
+  LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0571973c23f1e8d9183af9972b86ce0f632b5b5e
--- /dev/null
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -0,0 +1,818 @@
+/** 
+ * @file llavatarnamecache.cpp
+ * @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
+ * ("James Cook") from avatar UUIDs.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2010, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llavatarnamecache.h"
+
+#include "llcachename.h"		// we wrap this system
+#include "llframetimer.h"
+#include "llhttpclient.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+
+#include <boost/tokenizer.hpp>
+
+#include <map>
+#include <set>
+
+namespace LLAvatarNameCache
+{
+	// Manual override for display names - can disable even if the region
+	// supports it.
+	bool sUseDisplayNames = true;
+
+	// Cache starts in a paused state until we can determine if the
+	// current region supports display names.
+	bool sRunning = false;
+	
+	// Base lookup URL for name service.
+	// On simulator, loaded from indra.xml
+	// On viewer, usually a simulator capability (at People API team's request)
+	// Includes the trailing slash, like "http://pdp60.lindenlab.com:8000/agents/"
+	std::string sNameLookupURL;
+
+	// accumulated agent IDs for next query against service
+	typedef std::set<LLUUID> ask_queue_t;
+	ask_queue_t sAskQueue;
+
+	// agent IDs that have been requested, but with no reply
+	// maps agent ID to frame time request was made
+	typedef std::map<LLUUID, F64> pending_queue_t;
+	pending_queue_t sPendingQueue;
+
+	// Callbacks to fire when we received a name.
+	// May have multiple callbacks for a single ID, which are
+	// represented as multiple slots bound to the signal.
+	// Avoid copying signals via pointers.
+	typedef std::map<LLUUID, callback_signal_t*> signal_map_t;
+	signal_map_t sSignalMap;
+
+	// names we know about
+	typedef std::map<LLUUID, LLAvatarName> cache_t;
+	cache_t sCache;
+
+	// Send bulk lookup requests a few times a second at most
+	// only need per-frame timing resolution
+	LLFrameTimer sRequestTimer;
+
+	// Periodically clean out expired entries from the cache
+	//LLFrameTimer sEraseExpiredTimer;
+
+	//-----------------------------------------------------------------------
+	// Internal methods
+	//-----------------------------------------------------------------------
+
+	// Handle name response off network.
+	// Optionally skip adding to cache, used when this is a fallback to the
+	// legacy name system.
+	void processName(const LLUUID& agent_id,
+					 const LLAvatarName& av_name,
+					 bool add_to_cache);
+
+	void requestNamesViaCapability();
+
+	// Legacy name system callback
+	void legacyNameCallback(const LLUUID& agent_id,
+		const std::string& full_name,
+		bool is_group);
+
+	void requestNamesViaLegacy();
+
+	// Fill in an LLAvatarName with the legacy name data
+	void buildLegacyName(const std::string& full_name,
+						 LLAvatarName* av_name);
+
+	// Do a single callback to a given slot
+	void fireSignal(const LLUUID& agent_id,
+					const callback_slot_t& slot,
+					const LLAvatarName& av_name);
+	
+	// Is a request in-flight over the network?
+	bool isRequestPending(const LLUUID& agent_id);
+
+	// Erase expired names from cache
+	void eraseExpired();
+
+	bool expirationFromCacheControl(LLSD headers, F64 *expires);
+}
+
+/* Sample response:
+<?xml version="1.0"?>
+<llsd>
+  <map>
+    <key>agents</key>
+    <array>
+      <map>
+        <key>display_name_next_update</key>
+        <date>2010-04-16T21:34:02+00:00Z</date>
+        <key>display_name_expires</key>
+        <date>2010-04-16T21:32:26.142178+00:00Z</date>
+        <key>display_name</key>
+        <string>MickBot390 LLQABot</string>
+        <key>sl_id</key>
+        <string>mickbot390.llqabot</string>
+        <key>id</key>
+        <string>0012809d-7d2d-4c24-9609-af1230a37715</string>
+        <key>is_display_name_default</key>
+        <boolean>false</boolean>
+      </map>
+      <map>
+        <key>display_name_next_update</key>
+        <date>2010-04-16T21:34:02+00:00Z</date>
+        <key>display_name_expires</key>
+        <date>2010-04-16T21:32:26.142178+00:00Z</date>
+        <key>display_name</key>
+        <string>Bjork Gudmundsdottir</string>
+        <key>sl_id</key>
+        <string>sardonyx.linden</string>
+        <key>id</key>
+        <string>3941037e-78ab-45f0-b421-bd6e77c1804d</string>
+        <key>is_display_name_default</key>
+        <boolean>true</boolean>
+      </map>
+    </array>
+  </map>
+</llsd>
+*/
+
+class LLAvatarNameResponder : public LLHTTPClient::Responder
+{
+private:
+	// need to store agent ids that are part of this request in case of
+	// an error, so we can flag them as unavailable
+	std::vector<LLUUID> mAgentIDs;
+
+	// Need the headers to look up Expires: and Retry-After:
+	LLSD mHeaders;
+	
+public:
+	LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
+	:	mAgentIDs(agent_ids),
+		mHeaders()
+	{ }
+	
+	/*virtual*/ void completedHeader(U32 status, const std::string& reason, 
+		const LLSD& headers)
+	{
+		mHeaders = headers;
+	}
+
+	/*virtual*/ void result(const LLSD& content)
+	{
+		// Pull expiration out of headers if available
+		F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(mHeaders);
+
+		LLSD agents = content["agents"];
+		LLSD::array_const_iterator it = agents.beginArray();
+		for ( ; it != agents.endArray(); ++it)
+		{
+			const LLSD& row = *it;
+			LLUUID agent_id = row["id"].asUUID();
+
+			LLAvatarName av_name;
+			av_name.fromLLSD(row);
+
+			// Use expiration time from header
+			av_name.mExpires = expires;
+
+			// Some avatars don't have explicit display names set
+			if (av_name.mDisplayName.empty())
+			{
+				av_name.mDisplayName = av_name.mUsername;
+			}
+
+			// cache it and fire signals
+			LLAvatarNameCache::processName(agent_id, av_name, true);
+		}
+
+		// Same logic as error response case
+		LLSD unresolved_agents = content["bad_ids"];
+		if (unresolved_agents.size() > 0)
+		{
+			const std::string DUMMY_NAME("\?\?\?");
+			LLAvatarName av_name;
+			av_name.mUsername = DUMMY_NAME;
+			av_name.mDisplayName = DUMMY_NAME;
+			av_name.mIsDisplayNameDefault = false;
+			av_name.mIsDummy = true;
+			av_name.mExpires = expires;
+
+			it = unresolved_agents.beginArray();
+			for ( ; it != unresolved_agents.endArray(); ++it)
+			{
+				const LLUUID& agent_id = *it;
+				// cache it and fire signals
+				LLAvatarNameCache::processName(agent_id, av_name, true);
+			}
+		}
+	}
+
+	/*virtual*/ void error(U32 status, const std::string& reason)
+	{
+		// We're going to construct a dummy record and cache it for a while,
+		// either briefly for a 503 Service Unavailable, or longer for other
+		// errors.
+		F64 retry_timestamp = errorRetryTimestamp(status);
+
+		// *NOTE: "??" starts trigraphs in C/C++, escape the question marks.
+		const std::string DUMMY_NAME("\?\?\?");
+		LLAvatarName av_name;
+		av_name.mUsername = DUMMY_NAME;
+		av_name.mDisplayName = DUMMY_NAME;
+		av_name.mIsDisplayNameDefault = false;
+		av_name.mIsDummy = true;
+		av_name.mExpires = retry_timestamp;
+
+		// Add dummy records for all agent IDs in this request
+		std::vector<LLUUID>::const_iterator it = mAgentIDs.begin();
+		for ( ; it != mAgentIDs.end(); ++it)
+		{
+			const LLUUID& agent_id = *it;
+			// cache it and fire signals
+			LLAvatarNameCache::processName(agent_id, av_name, true);
+		}
+	}
+
+	// Return time to retry a request that generated an error, based on
+	// error type and headers.  Return value is seconds-since-epoch.
+	F64 errorRetryTimestamp(S32 status)
+	{
+		F64 now = LLFrameTimer::getTotalSeconds();
+
+		// Retry-After takes priority
+		LLSD retry_after = mHeaders["retry-after"];
+		if (retry_after.isDefined())
+		{
+			// We only support the delta-seconds type
+			S32 delta_seconds = retry_after.asInteger();
+			if (delta_seconds > 0)
+			{
+				// ...valid delta-seconds
+				return now + F64(delta_seconds);
+			}
+		}
+
+		// If no Retry-After, look for Cache-Control max-age
+		F64 expires = 0.0;
+		if (LLAvatarNameCache::expirationFromCacheControl(mHeaders, &expires))
+		{
+			return expires;
+		}
+
+		// No information in header, make a guess
+		if (status == 503)
+		{
+			// ...service unavailable, retry soon
+			const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min
+			return now + SERVICE_UNAVAILABLE_DELAY;
+		}
+		else
+		{
+			// ...other unexpected error
+			const F64 DEFAULT_DELAY = 3600.0; // 1 hour
+			return now + DEFAULT_DELAY;
+		}
+	}
+};
+
+void LLAvatarNameCache::processName(const LLUUID& agent_id,
+									const LLAvatarName& av_name,
+									bool add_to_cache)
+{
+	if (add_to_cache)
+	{
+		sCache[agent_id] = av_name;
+	}
+
+	sPendingQueue.erase(agent_id);
+
+	// signal everyone waiting on this name
+	signal_map_t::iterator sig_it =	sSignalMap.find(agent_id);
+	if (sig_it != sSignalMap.end())
+	{
+		callback_signal_t* signal = sig_it->second;
+		(*signal)(agent_id, av_name);
+
+		sSignalMap.erase(agent_id);
+
+		delete signal;
+		signal = NULL;
+	}
+}
+
+void LLAvatarNameCache::requestNamesViaCapability()
+{
+	F64 now = LLFrameTimer::getTotalSeconds();
+
+	// URL format is like:
+	// http://pdp60.lindenlab.com:8000/agents/?ids=3941037e-78ab-45f0-b421-bd6e77c1804d&ids=0012809d-7d2d-4c24-9609-af1230a37715&ids=0019aaba-24af-4f0a-aa72-6457953cf7f0
+	//
+	// Apache can handle URLs of 4096 chars, but let's be conservative
+	const U32 NAME_URL_MAX = 4096;
+	const U32 NAME_URL_SEND_THRESHOLD = 3000;
+	std::string url;
+	url.reserve(NAME_URL_MAX);
+
+	std::vector<LLUUID> agent_ids;
+	agent_ids.reserve(128);
+	
+	ask_queue_t::const_iterator it = sAskQueue.begin();
+	for ( ; it != sAskQueue.end(); ++it)
+	{
+		const LLUUID& agent_id = *it;
+
+		if (url.empty())
+		{
+			// ...starting new request
+			url += sNameLookupURL;
+			url += "?ids=";
+		}
+		else
+		{
+			// ...continuing existing request
+			url += "&ids=";
+		}
+		url += agent_id.asString();
+		agent_ids.push_back(agent_id);
+
+		// mark request as pending
+		sPendingQueue[agent_id] = now;
+
+		if (url.size() > NAME_URL_SEND_THRESHOLD)
+		{
+			//llinfos << "requestNames " << url << llendl;
+			LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
+			url.clear();
+			agent_ids.clear();
+		}
+	}
+
+	if (!url.empty())
+	{
+		//llinfos << "requestNames " << url << llendl;
+		LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
+		url.clear();
+		agent_ids.clear();
+	}
+
+	// We've moved all asks to the pending request queue
+	sAskQueue.clear();
+}
+
+void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
+										   const std::string& full_name,
+										   bool is_group)
+{
+	// Construct a dummy record for this name.  By convention, SLID is blank
+	// Never expires, but not written to disk, so lasts until end of session.
+	LLAvatarName av_name;
+	buildLegacyName(full_name, &av_name);
+
+	// Don't add to cache, the data already exists in the legacy name system
+	// cache and we don't want or need duplicate storage, because keeping the
+	// two copies in sync is complex.
+	processName(agent_id, av_name, false);
+}
+
+void LLAvatarNameCache::requestNamesViaLegacy()
+{
+	F64 now = LLFrameTimer::getTotalSeconds();
+	std::string full_name;
+	ask_queue_t::const_iterator it = sAskQueue.begin();
+	for (; it != sAskQueue.end(); ++it)
+	{
+		const LLUUID& agent_id = *it;
+
+		// Mark as pending first, just in case the callback is immediately
+		// invoked below.  This should never happen in practice.
+		sPendingQueue[agent_id] = now;
+
+		gCacheName->get(agent_id, false,  // legacy compatibility
+			boost::bind(&LLAvatarNameCache::legacyNameCallback,
+				_1, _2, _3));
+	}
+
+	// We've either answered immediately or moved all asks to the
+	// pending queue
+	sAskQueue.clear();
+}
+
+void LLAvatarNameCache::initClass(bool running)
+{
+	sRunning = running;
+}
+
+void LLAvatarNameCache::cleanupClass()
+{
+}
+
+void LLAvatarNameCache::importFile(std::istream& istr)
+{
+	LLSD data;
+	S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr);
+	if (parse_count < 1) return;
+
+	// by convention LLSD storage is a map
+	// we only store one entry in the map
+	LLSD agents = data["agents"];
+
+	LLUUID agent_id;
+	LLAvatarName av_name;
+	LLSD::map_const_iterator it = agents.beginMap();
+	for ( ; it != agents.endMap(); ++it)
+	{
+		agent_id.set(it->first);
+		av_name.fromLLSD( it->second );
+		sCache[agent_id] = av_name;
+	}
+	// entries may have expired since we last ran the viewer, just
+	// clean them out now
+	eraseExpired();
+	llinfos << "loaded " << sCache.size() << llendl;
+}
+
+void LLAvatarNameCache::exportFile(std::ostream& ostr)
+{
+	LLSD agents;
+	cache_t::const_iterator it = sCache.begin();
+	for ( ; it != sCache.end(); ++it)
+	{
+		const LLUUID& agent_id = it->first;
+		const LLAvatarName& av_name = it->second;
+		if (!av_name.mIsDummy)
+		{
+			// key must be a string
+			agents[agent_id.asString()] = av_name.asLLSD();
+		}
+	}
+	LLSD data;
+	data["agents"] = agents;
+	LLSDSerialize::toPrettyXML(data, ostr);
+}
+
+void LLAvatarNameCache::setNameLookupURL(const std::string& name_lookup_url)
+{
+	sNameLookupURL = name_lookup_url;
+}
+
+bool LLAvatarNameCache::hasNameLookupURL()
+{
+	return !sNameLookupURL.empty();
+}
+
+void LLAvatarNameCache::idle()
+{
+	// By convention, start running at first idle() call
+	sRunning = true;
+
+	// *TODO: Possibly re-enabled this based on People API load measurements
+	// 100 ms is the threshold for "user speed" operations, so we can
+	// stall for about that long to batch up requests.
+	//const F32 SECS_BETWEEN_REQUESTS = 0.1f;
+	//if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS))
+	//{
+	//	return;
+	//}
+
+	// Must be large relative to above
+
+	// No longer deleting expired entries, just re-requesting in the get
+	// this way first synchronous get call on an expired entry won't return
+	// legacy name.  LF
+
+	//const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds
+	//if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT))
+	//{
+	//	eraseExpired();
+	//}
+
+	if (sAskQueue.empty())
+	{
+		return;
+	}
+
+	if (useDisplayNames())
+	{
+		requestNamesViaCapability();
+	}
+	else
+	{
+		// ...fall back to legacy name cache system
+		requestNamesViaLegacy();
+	}
+}
+
+bool LLAvatarNameCache::isRequestPending(const LLUUID& agent_id)
+{
+	const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
+	F64 now = LLFrameTimer::getTotalSeconds();
+	F64 expire_time = now - PENDING_TIMEOUT_SECS;
+
+	pending_queue_t::const_iterator it = sPendingQueue.find(agent_id);
+	if (it != sPendingQueue.end())
+	{
+		bool request_expired = (it->second < expire_time);
+		return !request_expired;
+	}
+	return false;
+}
+
+void LLAvatarNameCache::eraseExpired()
+{
+	F64 now = LLFrameTimer::getTotalSeconds();
+	cache_t::iterator it = sCache.begin();
+	while (it != sCache.end())
+	{
+		cache_t::iterator cur = it;
+		++it;
+		const LLAvatarName& av_name = cur->second;
+		if (av_name.mExpires < now)
+		{
+			sCache.erase(cur);
+		}
+	}
+}
+
+void LLAvatarNameCache::buildLegacyName(const std::string& full_name,
+										LLAvatarName* av_name)
+{
+	llassert(av_name);
+	av_name->mUsername = "";
+	av_name->mDisplayName = full_name;
+	av_name->mIsDisplayNameDefault = true;
+	av_name->mIsDummy = true;
+	av_name->mExpires = F64_MAX;
+}
+
+// fills in av_name if it has it in the cache, even if expired (can check expiry time)
+// returns bool specifying  if av_name was filled, false otherwise
+bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
+{
+	if (sRunning)
+	{
+		// ...only do immediate lookups when cache is running
+		if (useDisplayNames())
+		{
+			// ...use display names cache
+			std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
+			if (it != sCache.end())
+			{
+				*av_name = it->second;
+
+				// re-request name if entry is expired
+				if (av_name->mExpires < LLFrameTimer::getTotalSeconds())
+				{
+					if (!isRequestPending(agent_id))
+					{
+						sAskQueue.insert(agent_id);
+					}
+				}
+				
+				return true;
+			}
+		}
+		else
+		{
+			// ...use legacy names cache
+			std::string full_name;
+			if (gCacheName->getFullName(agent_id, full_name))
+			{
+				buildLegacyName(full_name, av_name);
+				return true;
+			}
+		}
+	}
+
+	if (!isRequestPending(agent_id))
+	{
+		sAskQueue.insert(agent_id);
+	}
+
+	return false;
+}
+
+void LLAvatarNameCache::fireSignal(const LLUUID& agent_id,
+								   const callback_slot_t& slot,
+								   const LLAvatarName& av_name)
+{
+	callback_signal_t signal;
+	signal.connect(slot);
+	signal(agent_id, av_name);
+}
+
+void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
+{
+	if (sRunning)
+	{
+		// ...only do immediate lookups when cache is running
+		if (useDisplayNames())
+		{
+			// ...use new cache
+			std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
+			if (it != sCache.end())
+			{
+				const LLAvatarName& av_name = it->second;
+				
+				if (av_name.mExpires > LLFrameTimer::getTotalSeconds())
+				{
+					// ...name already exists in cache, fire callback now
+					fireSignal(agent_id, slot, av_name);
+
+					return;
+				}
+			}
+		}
+		else
+		{
+			// ...use old name system
+			std::string full_name;
+			if (gCacheName->getFullName(agent_id, full_name))
+			{
+				LLAvatarName av_name;
+				buildLegacyName(full_name, &av_name);
+				fireSignal(agent_id, slot, av_name);
+				return;
+			}
+		}
+	}
+
+	// schedule a request
+	if (!isRequestPending(agent_id))
+	{
+		sAskQueue.insert(agent_id);
+	}
+
+	// always store additional callback, even if request is pending
+	signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
+	if (sig_it == sSignalMap.end())
+	{
+		// ...new callback for this id
+		callback_signal_t* signal = new callback_signal_t();
+		signal->connect(slot);
+		sSignalMap[agent_id] = signal;
+	}
+	else
+	{
+		// ...existing callback, bind additional slot
+		callback_signal_t* signal = sig_it->second;
+		signal->connect(slot);
+	}
+}
+
+
+void LLAvatarNameCache::setUseDisplayNames(bool use)
+{
+	if (use != sUseDisplayNames)
+	{
+		sUseDisplayNames = use;
+		// flush our cache
+		sCache.clear();
+	}
+}
+
+bool LLAvatarNameCache::useDisplayNames()
+{
+	// Must be both manually set on and able to look up names.
+	return sUseDisplayNames && !sNameLookupURL.empty();
+}
+
+void LLAvatarNameCache::erase(const LLUUID& agent_id)
+{
+	sCache.erase(agent_id);
+}
+
+void LLAvatarNameCache::fetch(const LLUUID& agent_id)
+{
+	// re-request, even if request is already pending
+	sAskQueue.insert(agent_id);
+}
+
+void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_name)
+{
+	// *TODO: update timestamp if zero?
+	sCache[agent_id] = av_name;
+}
+
+F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers)
+{
+	F64 expires = 0.0;
+	if (expirationFromCacheControl(headers, &expires))
+	{
+		return expires;
+	}
+	else
+	{
+		// With no expiration info, default to an hour
+		const F64 DEFAULT_EXPIRES = 60.0 * 60.0;
+		F64 now = LLFrameTimer::getTotalSeconds();
+		return now + DEFAULT_EXPIRES;
+	}
+}
+
+bool LLAvatarNameCache::expirationFromCacheControl(LLSD headers, F64 *expires)
+{
+	// Allow the header to override the default
+	LLSD cache_control_header = headers["cache-control"];
+	if (cache_control_header.isDefined())
+	{
+		S32 max_age = 0;
+		std::string cache_control = cache_control_header.asString();
+		if (max_age_from_cache_control(cache_control, &max_age))
+		{
+			F64 now = LLFrameTimer::getTotalSeconds();
+			*expires = now + (F64)max_age;
+			return true;
+		}
+	}
+	return false;
+}
+
+static const std::string MAX_AGE("max-age");
+static const boost::char_separator<char> EQUALS_SEPARATOR("=");
+static const boost::char_separator<char> COMMA_SEPARATOR(",");
+
+bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age)
+{
+	// Split the string on "," to get a list of directives
+	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+	tokenizer directives(cache_control, COMMA_SEPARATOR);
+
+	tokenizer::iterator token_it = directives.begin();
+	for ( ; token_it != directives.end(); ++token_it)
+	{
+		// Tokens may have leading or trailing whitespace
+		std::string token = *token_it;
+		LLStringUtil::trim(token);
+
+		if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
+		{
+			// ...this token starts with max-age, so let's chop it up by "="
+			tokenizer subtokens(token, EQUALS_SEPARATOR);
+			tokenizer::iterator subtoken_it = subtokens.begin();
+
+			// Must have a token
+			if (subtoken_it == subtokens.end()) return false;
+			std::string subtoken = *subtoken_it;
+
+			// Must exactly equal "max-age"
+			LLStringUtil::trim(subtoken);
+			if (subtoken != MAX_AGE) return false;
+
+			// Must have another token
+			++subtoken_it;
+			if (subtoken_it == subtokens.end()) return false;
+			subtoken = *subtoken_it;
+
+			// Must be a valid integer
+			// *NOTE: atoi() returns 0 for invalid values, so we have to
+			// check the string first.
+			// *TODO: Do servers ever send "0000" for zero?  We don't handle it
+			LLStringUtil::trim(subtoken);
+			if (subtoken == "0")
+			{
+				*max_age = 0;
+				return true;
+			}
+			S32 val = atoi( subtoken.c_str() );
+			if (val > 0 && val < S32_MAX)
+			{
+				*max_age = val;
+				return true;
+			}
+			return false;
+		}
+	}
+	return false;
+}
+
+
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a8b987b05884b0e4b3f56c9c12a7710a755c122
--- /dev/null
+++ b/indra/llmessage/llavatarnamecache.h
@@ -0,0 +1,103 @@
+/** 
+ * @file llavatarnamecache.h
+ * @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
+ * ("James Cook") from avatar UUIDs.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2010, 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 LLAVATARNAMECACHE_H
+#define LLAVATARNAMECACHE_H
+
+#include "llavatarname.h"	// for convenience
+
+#include <boost/signals2.hpp>
+
+class LLSD;
+class LLUUID;
+
+namespace LLAvatarNameCache
+{
+	// Until the cache is set running, immediate lookups will fail and
+	// async lookups will be queued.  This allows us to block requests
+	// until we know if the first region supports display names.
+	void initClass(bool running);
+	void cleanupClass();
+
+	void importFile(std::istream& istr);
+	void exportFile(std::ostream& ostr);
+
+	// On the viewer, usually a simulator capabilitity
+	// If empty, name cache will fall back to using legacy name
+	// lookup system
+	void setNameLookupURL(const std::string& name_lookup_url);
+
+	// Do we have a valid lookup URL, hence are we trying to use the
+	// new display name lookup system?
+	bool hasNameLookupURL();
+	
+	// Periodically makes a batch request for display names not already in
+	// cache.  Call once per frame.
+	void idle();
+
+	// If name is in cache, returns true and fills in provided LLAvatarName
+	// otherwise returns false
+	bool get(const LLUUID& agent_id, LLAvatarName *av_name);
+
+	// Callback types for get() below
+	typedef boost::signals2::signal<
+		void (const LLUUID& agent_id, const LLAvatarName& av_name)>
+			callback_signal_t;
+	typedef callback_signal_t::slot_type callback_slot_t;
+
+	// Fetches name information and calls callback.
+	// If name information is in cache, callback will be called immediately.
+	void get(const LLUUID& agent_id, callback_slot_t slot);
+
+	// Allow display names to be explicitly disabled for testing.
+	void setUseDisplayNames(bool use);
+	bool useDisplayNames();
+
+	void erase(const LLUUID& agent_id);
+
+	// Force a re-fetch of the most recent data, but keep the current
+	// data in cache
+	void fetch(const LLUUID& agent_id);
+
+	void insert(const LLUUID& agent_id, const LLAvatarName& av_name);
+
+	// Compute name expiration time from HTTP Cache-Control header,
+	// or return default value, in seconds from epoch.
+	F64 nameExpirationFromHeaders(LLSD headers);
+}
+
+// Parse a cache-control header to get the max-age delta-seconds.
+// Returns true if header has max-age param and it parses correctly.
+// Exported here to ease unit testing.
+bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);
+
+#endif
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 379f3906256c5483423eb9fad5ca6cd1c3512240..4a66a31c35b8faab74fee32a6774255a714c1fac 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -69,6 +69,8 @@ class LLCacheNameEntry
 public:
 	bool mIsGroup;
 	U32 mCreateTime;	// unix time_t
+	// IDEVO TODO collapse names to one field, which will eliminate
+	// many string compares on "Resident"
 	std::string mFirstName;
 	std::string mLastName;
 	std::string mGroupName;
@@ -214,7 +216,9 @@ class LLCacheName::Impl
 
 	Impl(LLMessageSystem* msg);
 	~Impl();
-	
+
+	BOOL getName(const LLUUID& id, std::string& first, std::string& last);
+
 	boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback);
 	void addPending(const LLUUID& id, const LLHost& host);
 	
@@ -300,89 +304,10 @@ boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback&
 	return impl.mSignal.connect(callback);
 }
 
-void LLCacheName::importFile(LLFILE* fp)
-{
-	S32 count = 0;
-
-	const S32 BUFFER_SIZE = 1024;
-	char buffer[BUFFER_SIZE];	/*Flawfinder: ignore*/
-
-	// *NOTE: These buffer sizes are hardcoded into sscanf() below
-	char id_string[MAX_STRING]; /*Flawfinder: ignore*/
-	char firstname[MAX_STRING]; /*Flawfinder: ignore*/
-	char lastname[MAX_STRING]; /*Flawfinder: ignore*/
-	U32 create_time;
-
-	// This is OK if the first line is actually a name.  We just don't load it.
-	char* valid = fgets(buffer, BUFFER_SIZE, fp);
-	if (!valid) return;
-
-	// *NOTE: This buffer size is hardcoded into sscanf() below
-	char version_string[BUFFER_SIZE]; /*Flawfinder: ignore*/
-	S32 version = 0;
-	S32 match = sscanf(	/* Flawfinder: ignore */
-		buffer,
-		"%1023s %d",
-		version_string, &version);
-	if (   match != 2
-		|| strcmp(version_string, "version")
-		|| version != CN_FILE_VERSION)
-	{
-		llwarns << "Ignoring old cache name file format" << llendl;
-		return;
-	}
-
-	// We'll expire entries more than a week old
-	U32 now = (U32)time(NULL);
-	const U32 SECS_PER_DAY = 60 * 60 * 24;
-	U32 delete_before_time = now - (7 * SECS_PER_DAY);
-
-	while(!feof(fp))
-	{
-		valid = fgets(buffer, BUFFER_SIZE, fp);
-		if (!valid) break;
-
-		match = sscanf(	/* Flawfinder: ignore */
-			buffer,
-			"%254s %u %254s %254s",
-			id_string, 
-			&create_time,
-			firstname, 
-			lastname);
-		if (4 != match) continue;
-
-		LLUUID id(id_string);
-		if (id.isNull()) continue;
-
-		// undo trivial XOR
-		S32 i;
-		for (i = 0; i < UUID_BYTES; i++)
-		{
-			id.mData[i] ^= 0x33;
-		}
-
-		// Don't load entries that are more than a week old
-		if (create_time < delete_before_time) continue;
-
-		LLCacheNameEntry* entry = new LLCacheNameEntry();
-		entry->mIsGroup = false;
-		entry->mCreateTime = create_time;
-		entry->mFirstName = firstname;
-		entry->mLastName = lastname;
-		impl.mCache[id] = entry;
-		std::string fullname = entry->mFirstName + " " + entry->mLastName;
-		impl.mReverseCache[fullname] = id;
-		
-		count++;
-	}
-
-	llinfos << "LLCacheName loaded " << count << " names" << llendl;
-}
-
 bool LLCacheName::importFile(std::istream& istr)
 {
 	LLSD data;
-	if(LLSDSerialize::fromXML(data, istr) < 1)
+	if(LLSDSerialize::fromXMLDocument(data, istr) < 1)
 		return false;
 
 	// We'll expire entries more than a week old
@@ -408,7 +333,7 @@ bool LLCacheName::importFile(std::istream& istr)
 		entry->mFirstName = agent[FIRST].asString();
 		entry->mLastName = agent[LAST].asString();
 		impl.mCache[id] = entry;
-		std::string fullname = entry->mFirstName + " " + entry->mLastName;
+		std::string fullname = buildFullName(entry->mFirstName, entry->mLastName);
 		impl.mReverseCache[fullname] = id;
 
 		++count;
@@ -457,6 +382,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
 		// store it
 		LLUUID id = iter->first;
 		std::string id_str = id.asString();
+		// IDEVO TODO: Should we store SLIDs with last name "Resident" or not?
 		if(!entry->mFirstName.empty() && !entry->mLastName.empty())
 		{
 			data[AGENTS][id_str][FIRST] = entry->mFirstName;
@@ -474,7 +400,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
 }
 
 
-BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& last)
+BOOL LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last)
 {
 	if(id.isNull())
 	{
@@ -483,7 +409,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
 		return TRUE;
 	}
 
-	LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
+	LLCacheNameEntry* entry = get_ptr_in_map(mCache, id );
 	if (entry)
 	{
 		first = entry->mFirstName;
@@ -494,16 +420,17 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
 	{
 		first = sCacheName["waiting"];
 		last.clear();
-		if (!impl.isRequestPending(id))
+		if (!isRequestPending(id))
 		{
-			impl.mAskNameQueue.insert(id);
+			mAskNameQueue.insert(id);
 		}	
 		return FALSE;
 	}
 
 }
+
 // static
-void LLCacheName::LocalizeCacheName(std::string key, std::string value)
+void LLCacheName::localizeCacheName(std::string key, std::string value)
 {
 	if (key!="" && value!= "" )
 		sCacheName[key]=value;
@@ -514,11 +441,13 @@ void LLCacheName::LocalizeCacheName(std::string key, std::string value)
 BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
 {
 	std::string first_name, last_name;
-	BOOL res = getName(id, first_name, last_name);
-	fullname = first_name + " " + last_name;
+	BOOL res = impl.getName(id, first_name, last_name);
+	fullname = buildFullName(first_name, last_name);
 	return res;
 }
 
+
+
 BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
 {
 	if(id.isNull())
@@ -555,13 +484,13 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
 
 BOOL LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id)
 {
-	std::string fullname = first + " " + last;
-	return getUUID(fullname, id);
+	std::string full_name = buildFullName(first, last);
+	return getUUID(full_name, id);
 }
 
-BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
+BOOL LLCacheName::getUUID(const std::string& full_name, LLUUID& id)
 {
-	ReverseCache::iterator iter = impl.mReverseCache.find(fullname);
+	ReverseCache::iterator iter = impl.mReverseCache.find(full_name);
 	if (iter != impl.mReverseCache.end())
 	{
 		id = iter->second;
@@ -573,6 +502,55 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
 	}
 }
 
+//static
+std::string LLCacheName::buildFullName(const std::string& first, const std::string& last)
+{
+	std::string fullname = first;
+	if (!last.empty()
+		&& last != "Resident")
+	{
+		fullname += ' ';
+		fullname += last;
+	}
+	return fullname;
+}
+
+//static
+std::string LLCacheName::cleanFullName(const std::string& full_name)
+{
+	return full_name.substr(0, full_name.find(" Resident"));
+}
+
+//static 
+std::string LLCacheName::buildUsername(const std::string& full_name)
+{
+	// rare, but handle hard-coded error names returned from server
+	if (full_name == "(\?\?\?) (\?\?\?)")
+	{
+		return "(\?\?\?)";
+	}
+	
+	std::string::size_type index = full_name.find(' ');
+
+	if (index != std::string::npos)
+	{
+		std::string username;
+		username = full_name.substr(0, index);
+		std::string lastname = full_name.substr(index+1);
+
+		if (lastname != "Resident")
+		{
+			username = username + "." + lastname;
+		}
+		
+		LLStringUtil::toLower(username);
+		return username;
+	}
+
+	// if the input wasn't a correctly formatted legacy name just return it unchanged
+	return full_name;
+}
+
 // This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
 //  The reason it is a slot is so that the legacy get() function below can bind an old callback
 //  and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
@@ -580,7 +558,7 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
 //  we call it immediately. -Steve
 // NOTE: Even though passing first and last name is a bit of extra overhead, it eliminates the
 //  potential need for any parsing should any code need to handle first and last name independently.
-boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
 {
 	boost::signals2::connection res;
 	
@@ -588,7 +566,7 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
 	{
 		LLCacheNameSignal signal;
 		signal.connect(callback);
-		signal(id, sCacheName["nobody"], "", is_group);
+		signal(id, sCacheName["nobody"], is_group);
 		return res;
 	}
 
@@ -600,11 +578,13 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
 		// id found in map therefore we can call the callback immediately.
 		if (entry->mIsGroup)
 		{
-			signal(id, entry->mGroupName, "", entry->mIsGroup);
+			signal(id, entry->mGroupName, entry->mIsGroup);
 		}
 		else
 		{
-			signal(id, entry->mFirstName, entry->mLastName, entry->mIsGroup);
+			std::string fullname =
+				buildFullName(entry->mFirstName, entry->mLastName);
+			signal(id, fullname, entry->mIsGroup);
 		}
 	}
 	else
@@ -626,9 +606,15 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
 	return res;
 }
 
-boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data)
+boost::signals2::connection LLCacheName::getGroup(const LLUUID& group_id,
+												  const LLCacheNameCallback& callback)
+{
+	return get(group_id, true, callback);
+}
+
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data)
 {
-	return get(id, is_group, boost::bind(callback, _1, _2, _3, _4, user_data));
+	return get(id, is_group, boost::bind(callback, _1, _2, _3, user_data));
 }
 
 void LLCacheName::processPending()
@@ -700,7 +686,7 @@ void LLCacheName::dump()
 		{
 			llinfos
 				<< iter->first << " = "
-				<< entry->mFirstName << " " << entry->mLastName
+				<< buildFullName(entry->mFirstName, entry->mLastName)
 				<< " @ " << entry->mCreateTime
 				<< llendl;
 		}
@@ -719,12 +705,24 @@ void LLCacheName::dumpStats()
 			<< llendl;
 }
 
+void LLCacheName::clear()
+{
+	for_each(impl.mCache.begin(), impl.mCache.end(), DeletePairedPointer());
+	impl.mCache.clear();
+}
+
 //static 
 std::string LLCacheName::getDefaultName()
 {
 	return sCacheName["waiting"];
 }
 
+//static 
+std::string LLCacheName::getDefaultLastName()
+{
+	return "Resident";
+}
+
 void LLCacheName::Impl::processPendingAsks()
 {
 	LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS);
@@ -746,11 +744,13 @@ void LLCacheName::Impl::processPendingReplies()
 
 		if (!entry->mIsGroup)
 		{
-			(reply->mSignal)(reply->mID, entry->mFirstName, entry->mLastName, FALSE);
+			std::string fullname =
+				LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
+			(reply->mSignal)(reply->mID, fullname, false);
 		}
 		else
 		{
-			(reply->mSignal)(reply->mID, entry->mGroupName, "", TRUE);
+			(reply->mSignal)(reply->mID, entry->mGroupName, true);
 		}
 	}
 
@@ -921,13 +921,27 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
 
 		if (!isGroup)
 		{
-			mSignal(id, entry->mFirstName, entry->mLastName, FALSE);
-			std::string fullname = entry->mFirstName + " " + entry->mLastName;
-			mReverseCache[fullname] = id;
+			// NOTE: Very occasionally the server sends down a full name
+			// in the first name field with an empty last name, for example,
+			// first = "Ladanie1 Resident", last = "".
+			// I cannot reproduce this, nor can I find a bug in the server code.
+			// Ensure "Resident" does not appear via cleanFullName, because
+			// buildFullName only checks last name. JC
+			std::string full_name;
+			if (entry->mLastName.empty())
+			{
+				full_name = cleanFullName(entry->mFirstName);
+			}
+			else
+			{
+				full_name = LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
+			}
+			mSignal(id, full_name, false);
+			mReverseCache[full_name] = id;
 		}
 		else
 		{
-			mSignal(id, entry->mGroupName, "", TRUE);
+			mSignal(id, entry->mGroupName, true);
 			mReverseCache[entry->mGroupName] = id;
 		}
 	}
@@ -956,4 +970,3 @@ void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** us
 {
 	((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
 }
-
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index ab65800cb03c05ace3441fac9d58c69260c07b81..b4698030603f292ff2174da015595ae628854c0f 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -36,13 +36,12 @@ class LLUUID;
 
 
 typedef boost::signals2::signal<void (const LLUUID& id,
-                                      const std::string& first_name,
-                                      const std::string& last_name,
-                                      BOOL is_group)> LLCacheNameSignal;
+                                      const std::string& name,
+                                      bool is_group)> LLCacheNameSignal;
 typedef LLCacheNameSignal::slot_type LLCacheNameCallback;
 
 // Old callback with user data for compatability
-typedef void (*old_callback_t)(const LLUUID&, const std::string&, const std::string&, BOOL, void*);
+typedef void (*old_callback_t)(const LLUUID&, const std::string&, bool, void*);
 
 // Here's the theory:
 // If you request a name that isn't in the cache, it returns "waiting"
@@ -65,24 +64,31 @@ class LLCacheName
 
 	boost::signals2::connection addObserver(const LLCacheNameCallback& callback);
 
-	// janky old format. Remove after a while. Phoenix. 2008-01-30
-	void importFile(LLFILE* fp);
-
 	// storing cache on disk; for viewer, in name.cache
 	bool importFile(std::istream& istr);
 	void exportFile(std::ostream& ostr);
 
-	// If available, copies the first and last name into the strings provided.
-	// first must be at least DB_FIRST_NAME_BUF_SIZE characters.
-	// last must be at least DB_LAST_NAME_BUF_SIZE characters.
+	// If available, copies name ("bobsmith123" or "James Linden") into string
 	// If not available, copies the string "waiting".
 	// Returns TRUE iff available.
-	BOOL getName(const LLUUID& id, std::string& first, std::string& last);
-	BOOL getFullName(const LLUUID& id, std::string& fullname);
-	
+	BOOL getFullName(const LLUUID& id, std::string& full_name);
+
 	// Reverse lookup of UUID from name
 	BOOL getUUID(const std::string& first, const std::string& last, LLUUID& id);
 	BOOL getUUID(const std::string& fullname, LLUUID& id);
+
+	// IDEVO Temporary code
+	// Clean up new-style "bobsmith123 Resident" names to "bobsmith123" for display
+	static std::string buildFullName(const std::string& first, const std::string& last);
+
+	// Clean up legacy "bobsmith123 Resident" to "bobsmith123"
+	// If name does not contain "Resident" returns it unchanged.
+	static std::string cleanFullName(const std::string& full_name);
+	
+	// Converts a standard legacy name to a username
+	// "bobsmith123 Resident" -> "bobsmith"
+	// "Random Linden" -> "random.linden"
+	static std::string buildUsername(const std::string& name);
 	
 	// If available, this method copies the group name into the string
 	// provided. The caller must allocate at least
@@ -94,10 +100,15 @@ class LLCacheName
 	// If the data is currently available, may call the callback immediatly
 	// otherwise, will request the data, and will call the callback when
 	// available.  There is no garuntee the callback will ever be called.
-	boost::signals2::connection get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback);
-	
+	boost::signals2::connection get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback);
+
+	// Convenience method for looking up a group name, so you can
+	// tell the difference between avatar lookup and group lookup
+	// in global searches
+	boost::signals2::connection getGroup(const LLUUID& group_id, const LLCacheNameCallback& callback);
+
 	// LEGACY
-	boost::signals2::connection get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data);
+	boost::signals2::connection get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data);
 	// This method needs to be called from time to time to send out
 	// requests.
 	void processPending();
@@ -108,9 +119,15 @@ class LLCacheName
 	// Debugging
 	void dump();		// Dumps the contents of the cache
 	void dumpStats();	// Dumps the sizes of the cache and associated queues.
+	void clear();		// Deletes all entries from the cache
 
 	static std::string getDefaultName();
-	static void LocalizeCacheName(std::string key, std::string value);
+
+	// Returns "Resident", the default last name for SLID-based accounts
+	// that have no last name.
+	static std::string getDefaultLastName();
+
+	static void localizeCacheName(std::string key, std::string value);
 	static std::map<std::string, std::string> sCacheName;
 private:
 
diff --git a/indra/llmessage/mean_collision_data.h b/indra/llmessage/mean_collision_data.h
index cf1063eb555ff6622477a3f8c2f209fce013917f..29de091603409a2328ba8d2748334a16e3e9e92b 100644
--- a/indra/llmessage/mean_collision_data.h
+++ b/indra/llmessage/mean_collision_data.h
@@ -55,7 +55,7 @@ class LLMeanCollisionData
 	
 	LLMeanCollisionData(LLMeanCollisionData *mcd)
 		: mVictim(mcd->mVictim), mPerp(mcd->mPerp), mTime(mcd->mTime), mType(mcd->mType), mMag(mcd->mMag),
-		  mFirstName(mcd->mFirstName), mLastName(mcd->mLastName)
+		  mFullName(mcd->mFullName)
 	{
 	}		
 	
@@ -89,8 +89,7 @@ class LLMeanCollisionData
 	time_t mTime;
 	EMeanCollisionType mType;
 	F32	   mMag;
-	std::string mFirstName;
-	std::string mLastName;
+	std::string mFullName;
 };
 
 
diff --git a/indra/llmessage/tests/llavatarnamecache_test.cpp b/indra/llmessage/tests/llavatarnamecache_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eeadb703d144658499afd7695d0995f38a417ea3
--- /dev/null
+++ b/indra/llmessage/tests/llavatarnamecache_test.cpp
@@ -0,0 +1,109 @@
+/**
+ * @file llhost_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief llhost test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ * 
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+ 
+#include "linden_common.h"
+
+#include "../llavatarnamecache.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+	struct avatarnamecache_data
+	{
+	};
+	typedef test_group<avatarnamecache_data> avatarnamecache_test;
+	typedef avatarnamecache_test::object avatarnamecache_object;
+	tut::avatarnamecache_test avatarnamecache_testcase("llavatarnamecache");
+
+	template<> template<>
+	void avatarnamecache_object::test<1>()
+	{
+		bool valid = false;
+		S32 max_age = 0;
+
+		valid = max_age_from_cache_control("max-age=3600", &max_age);
+		ensure("typical input valid", valid);
+		ensure_equals("typical input parsed", max_age, 3600);
+
+		valid = max_age_from_cache_control(
+			" max-age=600 , no-cache,private=\"stuff\" ", &max_age);
+		ensure("complex input valid", valid);
+		ensure_equals("complex input parsed", max_age, 600);
+
+		valid = max_age_from_cache_control(
+			"no-cache, max-age = 123 ", &max_age);
+		ensure("complex input 2 valid", valid);
+		ensure_equals("complex input 2 parsed", max_age, 123);
+	}
+
+	template<> template<>
+	void avatarnamecache_object::test<2>()
+	{
+		bool valid = false;
+		S32 max_age = -1;
+
+		valid = max_age_from_cache_control("", &max_age);
+		ensure("empty input returns invalid", !valid);
+		ensure_equals("empty input doesn't change val", max_age, -1);
+
+		valid = max_age_from_cache_control("no-cache", &max_age);
+		ensure("no max-age field returns invalid", !valid);
+
+		valid = max_age_from_cache_control("max", &max_age);
+		ensure("just 'max' returns invalid", !valid);
+
+		valid = max_age_from_cache_control("max-age", &max_age);
+		ensure("partial max-age is invalid", !valid);
+
+		valid = max_age_from_cache_control("max-age=", &max_age);
+		ensure("longer partial max-age is invalid", !valid);
+
+		valid = max_age_from_cache_control("max-age=FOO", &max_age);
+		ensure("invalid integer max-age is invalid", !valid);
+
+		valid = max_age_from_cache_control("max-age 234", &max_age);
+		ensure("space separated max-age is invalid", !valid);
+
+		valid = max_age_from_cache_control("max-age=0", &max_age);
+		ensure("zero max-age is valid", valid);
+
+		// *TODO: Handle "0000" as zero
+		//valid = max_age_from_cache_control("max-age=0000", &max_age);
+		//ensure("multi-zero max-age is valid", valid);
+
+		valid = max_age_from_cache_control("max-age=-123", &max_age);
+		ensure("less than zero max-age is invalid", !valid);
+	}
+}
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 910bab9a97f2bcd268ed3bcb4a225e212d2a610f..f91b4ad025513387e950f7280329d212b11fa1c4 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -52,8 +52,6 @@
 #include "lltooltip.h"
 
 // Globals
-S32 LLCOMBOBOX_HEIGHT = 0;
-S32 LLCOMBOBOX_WIDTH = 0;
 S32 MAX_COMBO_WIDTH = 500;
 
 static LLDefaultChildRegistry::Register<LLComboBox> register_combo_box("combo_box");
@@ -705,10 +703,10 @@ void LLComboBox::onItemSelected(const LLSD& data)
 		setLabel(getSelectedItemLabel());
 
 		if (mAllowTextEntry)
-		{
-			gFocusMgr.setKeyboardFocus(mTextEntry);
-			mTextEntry->selectAll();
-		}
+	{
+		gFocusMgr.setKeyboardFocus(mTextEntry);
+		mTextEntry->selectAll();
+	}
 	}
 	// hiding the list reasserts the old value stored in the text editor/dropdown button
 	hideList();
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index f369147dedc6ade485000a71ab31242683b75a4d..5f0e4a6843026dd8a5ff3de805f81764a0e3022a 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -43,9 +43,6 @@
 class LLFontGL;
 class LLViewBorder;
 
-extern S32 LLCOMBOBOX_HEIGHT;
-extern S32 LLCOMBOBOX_WIDTH;
-
 class LLComboBox
 :	public LLUICtrl, public LLCtrlListInterface
 {
@@ -224,8 +221,8 @@ class LLComboBox
 	commit_callback_t	mPrearrangeCallback;
 	commit_callback_t	mTextEntryCallback;
 	commit_callback_t	mSelectionCallback;
-        boost::signals2::connection mTopLostSignalConnection;
-    S32					mLastSelectedIndex;
+	boost::signals2::connection mTopLostSignalConnection;
+	S32                 mLastSelectedIndex;
 };
 
 // A combo box with icons for the list of items.
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 99d540a9de779bba7279d4ae6673bfd644c05478..4f179f112e8b40921f36fd06d29c63bb5909d268 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -28,7 +28,9 @@
 
 #include "llnotifications.h"
 
+#include "llavatarnamecache.h"
 #include "llinstantmessage.h"
+#include "llcachename.h"
 #include "llxmlnode.h"
 #include "lluictrl.h"
 #include "lluictrlfactory.h"
@@ -1481,17 +1483,50 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
 	return s;
 }
 
-void LLPostponedNotification::onCachedNameReceived(const LLUUID& id, const std::string& first,
-		const std::string& last, bool is_group)
+//static
+void LLPostponedNotification::lookupName(LLPostponedNotification* thiz,
+										 const LLUUID& id,
+										 bool is_group)
+{
+	if (is_group)
+	{
+		gCacheName->getGroup(id,
+			boost::bind(&LLPostponedNotification::onGroupNameCache,
+				thiz, _1, _2, _3));
+	}
+	else
+	{
+		LLAvatarNameCache::get(id,
+			boost::bind(&LLPostponedNotification::onAvatarNameCache,
+				thiz, _1, _2));
+	}
+}
+
+void LLPostponedNotification::onGroupNameCache(const LLUUID& id,
+											   const std::string& full_name,
+											   bool is_group)
+{
+	finalizeName(full_name);
+}
+
+void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id,
+												const LLAvatarName& av_name)
 {
-	mName = first + " " + last;
+	std::string name = av_name.getCompleteName();
 
-	LLStringUtil::trim(mName);
-	if (mName.empty())
+	// from PE merge - we should figure out if this is the right thing to do
+	if (name.empty())
 	{
-		llwarns << "Empty name received for Id: " << id << llendl;
-		mName = SYSTEM_FROM;
+		llwarns << "Empty name received for Id: " << agent_id << llendl;
+		name = SYSTEM_FROM;
 	}
+	
+	finalizeName(name);
+}
+
+void LLPostponedNotification::finalizeName(const std::string& name)
+{
+	mName = name;
 	modifyNotificationParams();
 	LLNotifications::instance().add(mParams);
 	cleanup();
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 2cc8803f10172bbac85c88e86e8ef467b77e052d..952bb7f44693f7562c3d3619270c67f3383304d7 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -98,8 +98,8 @@
 #include "llinitparam.h"
 #include "llnotificationslistener.h"
 #include "llnotificationptr.h"
-#include "llcachename.h"
 
+class LLAvatarName;
 	
 typedef enum e_notification_priority
 {
@@ -994,17 +994,20 @@ class LLPostponedNotification
 	{
 		// upcast T to the base type to restrict T derivation from LLPostponedNotification
 		LLPostponedNotification* thiz = new T();
-
 		thiz->mParams = params;
 
-		gCacheName->get(id, is_group, boost::bind(
-				&LLPostponedNotification::onCachedNameReceived, thiz, _1, _2,
-				_3, _4));
+		// Avoid header file dependency on llcachename.h
+		lookupName(thiz, id, is_group);
 	}
 
 private:
-	void onCachedNameReceived(const LLUUID& id, const std::string& first,
-			const std::string& last, bool is_group);
+	static void lookupName(LLPostponedNotification* thiz, const LLUUID& id, bool is_group);
+	// only used for groups
+	void onGroupNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
+	// only used for avatars
+	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
+	// used for both group and avatar names
+	void finalizeName(const std::string& name);
 
 	void cleanup()
 	{
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index 5e09cee78b6d3bedbd05d60b182ccd095a99ed85..28a064e6b60c4e4ea8c8653ecd028c44cdc1e3fb 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -40,7 +40,8 @@ LLStyle::Params::Params()
 	selected_color("selected_color", LLColor4::black),
 	font("font", LLFontGL::getFontMonospace()),
 	image("image"),
-	link_href("href")
+	link_href("href"),
+	is_link("is_link")
 {}
 
 
@@ -51,6 +52,7 @@ LLStyle::LLStyle(const LLStyle::Params& p)
 	mSelectedColor(p.selected_color),
 	mFont(p.font()),
 	mLink(p.link_href),
+	mIsLink(p.is_link.isProvided() ? p.is_link : !p.link_href().empty()),
 	mDropShadow(p.drop_shadow),
 	mImagep(p.image())
 {}
@@ -73,7 +75,7 @@ void LLStyle::setLinkHREF(const std::string& href)
 
 BOOL LLStyle::isLink() const
 {
-	return mLink.size();
+	return mIsLink;
 }
 
 BOOL LLStyle::isVisible() const
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index 66cd639936ab6c73b5ddcccedd2f84b4a882e4af..322edc343ce9ba1f94ac9cc73e23092e6e679ebc 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -46,6 +46,7 @@ class LLStyle : public LLRefCount
 		Optional<const LLFontGL*>		font;
 		Optional<LLUIImage*>			image;
 		Optional<std::string>			link_href;
+		Optional<bool>					is_link;
 		Params();
 	};
 	LLStyle(const Params& p = Params());
@@ -106,6 +107,7 @@ class LLStyle : public LLRefCount
 	std::string			mFontName;
 	const LLFontGL*		mFont;
 	std::string			mLink;
+	bool				mIsLink;
 	LLUIImagePtr		mImagep;
 };
 
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 574b24cf13ace5745c7b8b1452f3f9f56967d778..9adeddca99635cf4801399a782d79c67989e3951 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -5,7 +5,7 @@
  *
  * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2009-2010, Linden Research, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -475,8 +475,8 @@ void LLTextBase::drawCursor()
 			{
 				LLColor4 text_color;
 				const LLFontGL* fontp;
-					text_color = segmentp->getColor();
-					fontp = segmentp->getStyle()->getFont();
+				text_color = segmentp->getColor();
+				fontp = segmentp->getStyle()->getFont();
 				fontp->render(text, mCursorPos, cursor_rect, 
 					LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),
 					LLFontGL::LEFT, mVAlign,
@@ -1602,6 +1602,20 @@ std::string LLTextBase::getText() const
 	return getViewModel()->getValue().asString();
 }
 
+// IDEVO - icons can be UI image names or UUID sent from
+// server with avatar display name
+static LLUIImagePtr image_from_icon_name(const std::string& icon_name)
+{
+	if (LLUUID::validate(icon_name))
+	{
+		return LLUI::getUIImageByID( LLUUID(icon_name) );
+	}
+	else
+	{
+		return LLUI::getUIImage(icon_name);
+	}
+}
+
 void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
 {
 	LLStyle::Params style_params(input_params);
@@ -1614,16 +1628,13 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
 		LLUrlMatch match;
 		std::string text = new_text;
 		while ( LLUrlRegistry::instance().findUrl(text, match,
-		        boost::bind(&LLTextBase::replaceUrlLabel, this, _1, _2)) )
+		        boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) )
 		{
 			start = match.getStart();
 			end = match.getEnd()+1;
 
-			LLStyle::Params link_params = style_params;
-			link_params.color = match.getColor();
-			link_params.readonly_color =  match.getColor();
-			link_params.font.style("UNDERLINE");
-			link_params.link_href = match.getUrl();
+			LLStyle::Params link_params(style_params);
+			link_params.overwriteFrom(match.getStyle());
 
 			// output the text before the Url
 			if (start > 0)
@@ -1644,26 +1655,20 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
 			// inserts an avatar icon preceding the Url if appropriate
 			LLTextUtil::processUrlMatch(&match,this);
 
-			// output the styled Url (unless we've been asked to suppress hyperlinking)
-			if (match.isLinkDisabled())
+			// output the styled Url
+			appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.underlineOnHoverOnly());
+			
+			// set the tooltip for the Url label
+			if (! match.getTooltip().empty())
 			{
-				appendAndHighlightText(match.getLabel(), part, style_params);
+				segment_set_t::iterator it = getSegIterContaining(getLength()-1);
+				if (it != mSegments.end())
+					{
+						LLTextSegmentPtr segment = *it;
+						segment->setToolTip(match.getTooltip());
+					}
 			}
-			else
-			{
-				appendAndHighlightText(match.getLabel(), part, link_params, match.underlineOnHoverOnly());
 
-				// set the tooltip for the Url label
-				if (! match.getTooltip().empty())
-				{
-					segment_set_t::iterator it = getSegIterContaining(getLength()-1);
-					if (it != mSegments.end())
-						{
-							LLTextSegmentPtr segment = *it;
-							segment->setToolTip(match.getTooltip());
-						}
-				}
-			}
 			// move on to the rest of the text after the Url
 			if (end < (S32)text.length()) 
 			{
@@ -1848,8 +1853,9 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
 }
 
 
-void LLTextBase::replaceUrlLabel(const std::string &url,
-								   const std::string &label)
+void LLTextBase::replaceUrl(const std::string &url,
+							const std::string &label,
+							const std::string &icon)
 {
 	// get the full (wide) text for the editor so we can change it
 	LLWString text = getWText();
@@ -1870,7 +1876,7 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
 		seg->setEnd(seg_start + seg_length);
 
 		// if we find a link with our Url, then replace the label
-		if (style->isLink() && style->getLinkHREF() == url)
+		if (style->getLinkHREF() == url)
 		{
 			S32 start = seg->getStart();
 			S32 end = seg->getEnd();
@@ -1879,6 +1885,21 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
 			modified = true;
 		}
 
+		// Icon might be updated when more avatar or group info
+		// becomes available
+		if (style->isImage() && style->getLinkHREF() == url)
+		{
+			LLUIImagePtr image = image_from_icon_name( icon );
+			if (image)
+			{
+				LLStyle::Params icon_params;
+				icon_params.image = image;
+				LLStyleConstSP new_style(new LLStyle(icon_params));
+				seg->setStyle(new_style);
+				modified = true;
+			}
+		}
+
 		// work out the character offset for the next segment
 		seg_start = seg->getEnd();
 	}
@@ -1976,8 +1997,8 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
 		else if (hit_past_end_of_line && segmentp->getEnd() > line_iter->mDocIndexEnd - 1)	
 		{
 			// segment wraps to next line, so just set doc pos to the end of the line
- 			// segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
- 			pos = llmin(getLength(), line_iter->mDocIndexEnd);
+			// segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
+			pos = llmin(getLength(), line_iter->mDocIndexEnd);
 			break;
 		}
 		start_x += text_width;
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index e5dfecad5490037e45dd9a2308493a8ae8f1816e..84d6632271a50d7c5db926671cb0b990813fa4b1 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -492,7 +492,11 @@ class LLTextBase
 	// misc
 	void							updateRects();
 	void							needsScroll() { mScrollNeeded = TRUE; }
-	void							replaceUrlLabel(const std::string &url, const std::string &label);
+
+	struct URLLabelCallback;
+	// Replace a URL with a new icon and label, for example, when
+	// avatar names are looked up.
+	void replaceUrl(const std::string &url, const std::string &label, const std::string& icon);
 	
 	void							appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params());
 	void							appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 5680ab8bd4a3656f1c748a4a2760a016cd8c36f8..f58c07754feaf4efc84c78477f4a106cb7737def 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -31,18 +31,19 @@
 #include "llurlmatch.h"
 #include "llurlregistry.h"
 
+#include "llavatarnamecache.h"
 #include "llcachename.h"
 #include "lltrans.h"
 #include "lluicolortable.h"
 
 #define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
 
+// Utility functions
+std::string localize_slapp_label(const std::string& url, const std::string& full_name);
 
-LLUrlEntryBase::LLUrlEntryBase() :
-	mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")),
-	mDisabledLink(false)
-{
-}
+
+LLUrlEntryBase::LLUrlEntryBase()
+{}
 
 LLUrlEntryBase::~LLUrlEntryBase()
 {
@@ -53,6 +54,22 @@ std::string LLUrlEntryBase::getUrl(const std::string &string) const
 	return escapeUrl(string);
 }
 
+//virtual
+std::string LLUrlEntryBase::getIcon(const std::string &url)
+{
+	return mIcon;
+}
+
+LLStyle::Params LLUrlEntryBase::getStyle() const
+{
+	LLStyle::Params style_params;
+	style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+	style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+	style_params.font.style = "UNDERLINE";
+	return style_params;
+}
+
+
 std::string LLUrlEntryBase::getIDStringFromUrl(const std::string &url) const
 {
 	// return the id from a SLURL in the format /app/{cmd}/{id}/about
@@ -130,16 +147,20 @@ void LLUrlEntryBase::addObserver(const std::string &id,
 		mObservers.insert(std::pair<std::string, LLUrlEntryObserver>(id, observer));
 	}
 }
- 
-void LLUrlEntryBase::callObservers(const std::string &id, const std::string &label)
+
+// *NOTE: See also LLUrlEntryAgent::callObservers()
+void LLUrlEntryBase::callObservers(const std::string &id,
+								   const std::string &label,
+								   const std::string &icon)
 {
 	// notify all callbacks waiting on the given uuid
-	std::multimap<std::string, LLUrlEntryObserver>::iterator it;
-	for (it = mObservers.find(id); it != mObservers.end();)
+	typedef std::multimap<std::string, LLUrlEntryObserver>::iterator observer_it;
+	std::pair<observer_it, observer_it> matching_range = mObservers.equal_range(id);
+	for (observer_it it = matching_range.first; it != matching_range.second;)
 	{
 		// call the callback - give it the new label
 		LLUrlEntryObserver &observer = it->second;
-		(*observer.signal)(it->second.url, label);
+		(*observer.signal)(it->second.url, label, icon);
 		// then remove the signal - we only need to call it once
 		delete observer.signal;
 		mObservers.erase(it++);
@@ -308,16 +329,35 @@ LLUrlEntryAgent::LLUrlEntryAgent()
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_agent.xml";
 	mIcon = "Generic_Person";
-	mColor = LLUIColorTable::instance().getColor("AgentLinkColor");
 }
 
-void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
-										  const std::string& first,
-										  const std::string& last,
-										  BOOL is_group)
+// virtual
+void LLUrlEntryAgent::callObservers(const std::string &id,
+								    const std::string &label,
+								    const std::string &icon)
 {
+	// notify all callbacks waiting on the given uuid
+	typedef std::multimap<std::string, LLUrlEntryObserver>::iterator observer_it;
+	std::pair<observer_it, observer_it> matching_range = mObservers.equal_range(id);
+	for (observer_it it = matching_range.first; it != matching_range.second;)
+	{
+		// call the callback - give it the new label
+		LLUrlEntryObserver &observer = it->second;
+		std::string final_label = localize_slapp_label(observer.url, label);
+		(*observer.signal)(observer.url, final_label, icon);
+		// then remove the signal - we only need to call it once
+		delete observer.signal;
+		mObservers.erase(it++);
+	}
+}
+
+void LLUrlEntryAgent::onAvatarNameCache(const LLUUID& id,
+										const LLAvatarName& av_name)
+{
+	std::string label = av_name.getCompleteName();
+
 	// received the agent name from the server - tell our observers
-	callObservers(id.asString(), first + " " + last);
+	callObservers(id.asString(), label, mIcon);
 }
 
 LLUUID	LLUrlEntryAgent::getID(const std::string &string) const
@@ -330,6 +370,10 @@ std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
 	// return a tooltip corresponding to the URL type instead of the generic one
 	std::string url = getUrl(string);
 
+	if (LLStringUtil::endsWith(url, "/inspect"))
+	{
+		return LLTrans::getString("TooltipAgentInspect");
+	}
 	if (LLStringUtil::endsWith(url, "/mute"))
 	{
 		return LLTrans::getString("TooltipAgentMute");
@@ -379,50 +423,182 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
 	}
 
 	LLUUID agent_id(agent_id_string);
-	std::string full_name;
 	if (agent_id.isNull())
 	{
 		return LLTrans::getString("AvatarNameNobody");
 	}
-	else if (gCacheName->getFullName(agent_id, full_name))
-	{
-		// customize label string based on agent SLapp suffix
-		if (LLStringUtil::endsWith(url, "/mute"))
-		{
-			return LLTrans::getString("SLappAgentMute") + " " + full_name;
-		}
-		if (LLStringUtil::endsWith(url, "/unmute"))
-		{
-			return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
-		}
-		if (LLStringUtil::endsWith(url, "/im"))
-		{
-			return LLTrans::getString("SLappAgentIM") + " " + full_name;
-		}
-		if (LLStringUtil::endsWith(url, "/pay"))
-		{
-			return LLTrans::getString("SLappAgentPay") + " " + full_name;
-		}
-		if (LLStringUtil::endsWith(url, "/offerteleport"))
-		{
-			return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
-		}
-		if (LLStringUtil::endsWith(url, "/requestfriend"))
-		{
-			return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
-		}
-		return full_name;
+
+	LLAvatarName av_name;
+	if (LLAvatarNameCache::get(agent_id, &av_name))
+	{
+		std::string label = av_name.getCompleteName();
+
+		// handle suffixes like /mute or /offerteleport
+		label = localize_slapp_label(url, label);
+		return label;
 	}
 	else
 	{
-		gCacheName->get(agent_id, FALSE,
-			boost::bind(&LLUrlEntryAgent::onAgentNameReceived,
-				this, _1, _2, _3, _4));
+		LLAvatarNameCache::get(agent_id,
+			boost::bind(&LLUrlEntryAgent::onAvatarNameCache,
+				this, _1, _2));
 		addObserver(agent_id_string, url, cb);
 		return LLTrans::getString("LoadingData");
 	}
 }
 
+LLStyle::Params LLUrlEntryAgent::getStyle() const
+{
+	LLStyle::Params style_params = LLUrlEntryBase::getStyle();
+	style_params.color = LLUIColorTable::instance().getColor("AgentLinkColor");
+	style_params.readonly_color = LLUIColorTable::instance().getColor("AgentLinkColor");
+	return style_params;
+}
+
+std::string localize_slapp_label(const std::string& url, const std::string& full_name)
+{
+	// customize label string based on agent SLapp suffix
+	if (LLStringUtil::endsWith(url, "/mute"))
+	{
+		return LLTrans::getString("SLappAgentMute") + " " + full_name;
+	}
+	if (LLStringUtil::endsWith(url, "/unmute"))
+	{
+		return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
+	}
+	if (LLStringUtil::endsWith(url, "/im"))
+	{
+		return LLTrans::getString("SLappAgentIM") + " " + full_name;
+	}
+	if (LLStringUtil::endsWith(url, "/pay"))
+	{
+		return LLTrans::getString("SLappAgentPay") + " " + full_name;
+	}
+	if (LLStringUtil::endsWith(url, "/offerteleport"))
+	{
+		return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
+	}
+	if (LLStringUtil::endsWith(url, "/requestfriend"))
+	{
+		return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
+	}
+	return full_name;
+}
+
+
+std::string LLUrlEntryAgent::getIcon(const std::string &url)
+{
+	// *NOTE: Could look up a badge here by calling getIDStringFromUrl()
+	// and looking up the badge for the agent.
+	return mIcon;
+}
+
+//
+// LLUrlEntryAgentName describes a Second Life agent name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
+//
+LLUrlEntryAgentName::LLUrlEntryAgentName()
+{}
+
+void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id,
+										const LLAvatarName& av_name)
+{
+	std::string label = getName(av_name);
+	// received the agent name from the server - tell our observers
+	callObservers(id.asString(), label, mIcon);
+}
+
+std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+	if (!gCacheName)
+	{
+		// probably at the login screen, use short string for layout
+		return LLTrans::getString("LoadingData");
+	}
+
+	std::string agent_id_string = getIDStringFromUrl(url);
+	if (agent_id_string.empty())
+	{
+		// something went wrong, just give raw url
+		return unescapeUrl(url);
+	}
+
+	LLUUID agent_id(agent_id_string);
+	if (agent_id.isNull())
+	{
+		return LLTrans::getString("AvatarNameNobody");
+	}
+
+	LLAvatarName av_name;
+	if (LLAvatarNameCache::get(agent_id, &av_name))
+	{
+		return getName(av_name);
+	}
+	else
+	{
+		LLAvatarNameCache::get(agent_id,
+			boost::bind(&LLUrlEntryAgentCompleteName::onAvatarNameCache,
+				this, _1, _2));
+		addObserver(agent_id_string, url, cb);
+		return LLTrans::getString("LoadingData");
+	}
+}
+
+LLStyle::Params LLUrlEntryAgentName::getStyle() const
+{
+	// don't override default colors
+	return LLStyle::Params().is_link(false);
+}
+
+//
+// LLUrlEntryAgentCompleteName describes a Second Life agent complete name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
+//
+LLUrlEntryAgentCompleteName::LLUrlEntryAgentCompleteName()
+{
+	mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/completename",
+							boost::regex::perl|boost::regex::icase);
+}
+
+std::string LLUrlEntryAgentCompleteName::getName(const LLAvatarName& avatar_name)
+{
+	return avatar_name.getCompleteName();
+}
+
+//
+// LLUrlEntryAgentDisplayName describes a Second Life agent display name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
+//
+LLUrlEntryAgentDisplayName::LLUrlEntryAgentDisplayName()
+{
+	mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/displayname",
+							boost::regex::perl|boost::regex::icase);
+}
+
+std::string LLUrlEntryAgentDisplayName::getName(const LLAvatarName& avatar_name)
+{
+	return avatar_name.mDisplayName;
+}
+
+//
+// LLUrlEntryAgentUserName describes a Second Life agent user name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
+//
+LLUrlEntryAgentUserName::LLUrlEntryAgentUserName()
+{
+	mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/username",
+							boost::regex::perl|boost::regex::icase);
+}
+
+std::string LLUrlEntryAgentUserName::getName(const LLAvatarName& avatar_name)
+{
+	return avatar_name.mUsername.empty() ? avatar_name.getLegacyName() : avatar_name.mUsername;
+}
+
 //
 // LLUrlEntryGroup Describes a Second Life group Url, e.g.,
 // secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
@@ -436,18 +612,16 @@ LLUrlEntryGroup::LLUrlEntryGroup()
 	mMenuName = "menu_url_group.xml";
 	mIcon = "Generic_Group";
 	mTooltip = LLTrans::getString("TooltipGroupUrl");
-	mColor = LLUIColorTable::instance().getColor("GroupLinkColor");
 }
 
 
 
 void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id,
-										  const std::string& first,
-										  const std::string& last,
-										  BOOL is_group)
+										  const std::string& name,
+										  bool is_group)
 {
 	// received the group name from the server - tell our observers
-	callObservers(id.asString(), first);
+	callObservers(id.asString(), name, mIcon);
 }
 
 LLUUID	LLUrlEntryGroup::getID(const std::string &string) const
@@ -483,14 +657,23 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa
 	}
 	else
 	{
-		gCacheName->get(group_id, TRUE,
+		gCacheName->getGroup(group_id,
 			boost::bind(&LLUrlEntryGroup::onGroupNameReceived,
-				this, _1, _2, _3, _4));
+				this, _1, _2, _3));
 		addObserver(group_id_string, url, cb);
 		return LLTrans::getString("LoadingData");
 	}
 }
 
+LLStyle::Params LLUrlEntryGroup::getStyle() const
+{
+	LLStyle::Params style_params = LLUrlEntryBase::getStyle();
+	style_params.color = LLUIColorTable::instance().getColor("GroupLinkColor");
+	style_params.readonly_color = LLUIColorTable::instance().getColor("GroupLinkColor");
+	return style_params;
+}
+
+
 //
 // LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
 // secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
@@ -791,7 +974,6 @@ LLUrlEntryNoLink::LLUrlEntryNoLink()
 {
 	mPattern = boost::regex("<nolink>[^<]*</nolink>",
 							boost::regex::perl|boost::regex::icase);
-	mDisabledLink = true;
 }
 
 std::string LLUrlEntryNoLink::getUrl(const std::string &url) const
@@ -805,6 +987,12 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC
 	return getUrl(url);
 }
 
+LLStyle::Params LLUrlEntryNoLink::getStyle() const 
+{ 
+	return LLStyle::Params(); 
+}
+
+
 //
 // LLUrlEntryIcon describes an icon with <icon>...</icon> tags
 //
@@ -812,7 +1000,6 @@ LLUrlEntryIcon::LLUrlEntryIcon()
 {
 	mPattern = boost::regex("<icon\\s*>\\s*([^<]*)?\\s*</icon\\s*>",
 							boost::regex::perl|boost::regex::icase);
-	mDisabledLink = true;
 }
 
 std::string LLUrlEntryIcon::getUrl(const std::string &url) const
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index e25eaa75558f559cb01e6c9a6745c495e2616f68..f6424c28b860fc1eb5359061827de8faf1d75d35 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -30,13 +30,17 @@
 
 #include "lluuid.h"
 #include "lluicolor.h"
+#include "llstyle.h"
 #include <boost/signals2.hpp>
 #include <boost/regex.hpp>
 #include <string>
 #include <map>
 
+class LLAvatarName;
+
 typedef boost::signals2::signal<void (const std::string& url,
-									  const std::string& label)> LLUrlLabelSignal;
+									  const std::string& label,
+									  const std::string& icon)> LLUrlLabelSignal;
 typedef LLUrlLabelSignal::slot_type LLUrlLabelCallback;
 
 ///
@@ -71,10 +75,10 @@ class LLUrlEntryBase
 	virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
 
 	/// Return an icon that can be displayed next to Urls of this type
-	virtual std::string getIcon(const std::string &url) { return mIcon; }
+	virtual std::string getIcon(const std::string &url);
 
-	/// Return the color to render the displayed text
-	LLUIColor getColor() const { return mColor; }
+	/// Return the style to render the displayed text
+	virtual LLStyle::Params getStyle() const;
 
 	/// Given a matched Url, return a tooltip string for the hyperlink
 	virtual std::string getTooltip(const std::string &string) const { return mTooltip; }
@@ -85,9 +89,6 @@ class LLUrlEntryBase
 	/// Return the name of a SL location described by this Url, if any
 	virtual std::string getLocation(const std::string &url) const { return ""; }
 
-	/// is this a match for a URL that should not be hyperlinked?
-	bool isLinkDisabled() const { return mDisabledLink; }
-
 	/// Should this link text be underlined only when mouse is hovered over it?
 	virtual bool underlineOnHoverOnly(const std::string &string) const { return false; }
 
@@ -100,7 +101,7 @@ class LLUrlEntryBase
 	std::string getLabelFromWikiLink(const std::string &url) const;
 	std::string getUrlFromWikiLink(const std::string &string) const;
 	void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb); 
-	void callObservers(const std::string &id, const std::string &label);
+	virtual void callObservers(const std::string &id, const std::string &label, const std::string& icon);
 
 	typedef struct {
 		std::string url;
@@ -111,9 +112,7 @@ class LLUrlEntryBase
 	std::string                                    	mIcon;
 	std::string                                    	mMenuName;
 	std::string                                    	mTooltip;
-	LLUIColor										mColor;
 	std::multimap<std::string, LLUrlEntryObserver>	mObservers;
-	bool                                            mDisabledLink;
 };
 
 ///
@@ -162,18 +161,78 @@ class LLUrlEntrySLURL : public LLUrlEntryBase
 ///
 /// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
 /// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
-///
 class LLUrlEntryAgent : public LLUrlEntryBase
 {
 public:
 	LLUrlEntryAgent();
 	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+	/*virtual*/ std::string getIcon(const std::string &url);
 	/*virtual*/ std::string getTooltip(const std::string &string) const;
+	/*virtual*/ LLStyle::Params getStyle() const;
 	/*virtual*/ LLUUID	getID(const std::string &string) const;
 	/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
+protected:
+	/*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon);
+private:
+	void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
+};
+
+///
+/// LLUrlEntryAgentName Describes a Second Life agent name Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
+/// that displays various forms of user name
+/// This is a base class for the various implementations of name display
+class LLUrlEntryAgentName : public LLUrlEntryBase
+{
+public:
+	LLUrlEntryAgentName();
+	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+	/*virtual*/ LLStyle::Params getStyle() const;
+protected:
+	// override this to pull out relevant name fields
+	virtual std::string getName(const LLAvatarName& avatar_name) = 0;
+private:
+	void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
+};
+
+
+///
+/// LLUrlEntryAgentCompleteName Describes a Second Life agent name Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
+/// that displays the full display name + user name for an avatar
+/// such as "James Linden (james.linden)"
+class LLUrlEntryAgentCompleteName : public LLUrlEntryAgentName
+{
+public:
+	LLUrlEntryAgentCompleteName();
+private:
+	/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
+};
+
+///
+/// LLUrlEntryAgentDisplayName Describes a Second Life agent display name Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
+/// that displays the just the display name for an avatar
+/// such as "James Linden"
+class LLUrlEntryAgentDisplayName : public LLUrlEntryAgentName
+{
+public:
+	LLUrlEntryAgentDisplayName();
+private:
+	/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
+};
+
+///
+/// LLUrlEntryAgentUserName Describes a Second Life agent username Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
+/// that displays the just the display name for an avatar
+/// such as "james.linden"
+class LLUrlEntryAgentUserName : public LLUrlEntryAgentName
+{
+public:
+	LLUrlEntryAgentUserName();
 private:
-	void onAgentNameReceived(const LLUUID& id, const std::string& first,
-							 const std::string& last, BOOL is_group);
+	/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
 };
 
 ///
@@ -185,10 +244,10 @@ class LLUrlEntryGroup : public LLUrlEntryBase
 public:
 	LLUrlEntryGroup();
 	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+	/*virtual*/ LLStyle::Params getStyle() const;
 	/*virtual*/ LLUUID	getID(const std::string &string) const;
 private:
-	void onGroupNameReceived(const LLUUID& id, const std::string& first,
-							 const std::string& last, BOOL is_group);
+	void onGroupNameReceived(const LLUUID& id, const std::string& name, bool is_group);
 };
 
 ///
@@ -297,6 +356,7 @@ class LLUrlEntryNoLink : public LLUrlEntryBase
 	LLUrlEntryNoLink();
 	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
 	/*virtual*/ std::string getUrl(const std::string &string) const;
+	/*virtual*/ LLStyle::Params getStyle() const;
 };
 
 ///
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
index e53b0c43708a9166ad96e08a9a88bc6fb5d9d5c5..c1f1382a9fe0b3dc152b2a656500ab8e329f0b23 100644
--- a/indra/llui/llurlmatch.cpp
+++ b/indra/llui/llurlmatch.cpp
@@ -37,16 +37,15 @@ LLUrlMatch::LLUrlMatch() :
 	mIcon(""),
 	mMenuName(""),
 	mLocation(""),
-	mDisabledLink(false),
 	mUnderlineOnHoverOnly(false)
 {
 }
 
 void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
 						   const std::string &label, const std::string &tooltip,
-						   const std::string &icon, const LLUIColor& color,
+						   const std::string &icon, const LLStyle::Params& style,
 						   const std::string &menu, const std::string &location,
-						   bool disabled_link, const LLUUID& id, bool underline_on_hover_only)
+						   const LLUUID& id, bool underline_on_hover_only)
 {
 	mStart = start;
 	mEnd = end;
@@ -54,10 +53,10 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
 	mLabel = label;
 	mTooltip = tooltip;
 	mIcon = icon;
-	mColor = color;
+	mStyle = style;
+	mStyle.link_href = url;
 	mMenuName = menu;
 	mLocation = location;
-	mDisabledLink = disabled_link;
 	mID = id;
 	mUnderlineOnHoverOnly = underline_on_hover_only;
 }
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
index d1b2112ee71104482bc2eea2574209a6fa76c1c3..2818f452072ce2eb474c3a921f9bab7a2a570f10 100644
--- a/indra/llui/llurlmatch.h
+++ b/indra/llui/llurlmatch.h
@@ -28,11 +28,11 @@
 #ifndef LL_LLURLMATCH_H
 #define LL_LLURLMATCH_H
 
-#include "linden_common.h"
+//#include "linden_common.h"
 
 #include <string>
 #include <vector>
-#include "lluicolor.h"
+#include "llstyle.h"
 
 ///
 /// LLUrlMatch describes a single Url that was matched within a string by 
@@ -69,7 +69,7 @@ class LLUrlMatch
 	std::string getIcon() const { return mIcon; }
 
 	/// Return the color to render the displayed text
-	LLUIColor getColor() const { return mColor; }
+	LLStyle::Params getStyle() const { return mStyle; }
 
 	/// Return the name of a XUI file containing the context menu items
 	std::string getMenuName() const { return mMenuName; }
@@ -77,21 +77,17 @@ class LLUrlMatch
 	/// return the SL location that this Url describes, or "" if none.
 	std::string getLocation() const { return mLocation; }
 
-	/// is this a match for a URL that should not be hyperlinked?
-	bool isLinkDisabled() const { return mDisabledLink; }
-
 	/// Should this link text be underlined only when mouse is hovered over it?
 	bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
 
 	/// Change the contents of this match object (used by LLUrlRegistry)
 	void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
 	               const std::string &tooltip, const std::string &icon,
-				   const LLUIColor& color, const std::string &menu, 
-				   const std::string &location, bool disabled_link
-				   , const LLUUID& id, bool underline_on_hover_only  = false );
-
-	const LLUUID& getID() const { return mID;}
+				   const LLStyle::Params& style, const std::string &menu, 
+				   const std::string &location, const LLUUID& id,
+				   bool underline_on_hover_only = false );
 
+	const LLUUID& getID() const { return mID; }
 private:
 	U32         mStart;
 	U32         mEnd;
@@ -101,10 +97,8 @@ class LLUrlMatch
 	std::string mIcon;
 	std::string mMenuName;
 	std::string mLocation;
-
 	LLUUID		mID;
-	LLUIColor	mColor;
-	bool        mDisabledLink;
+	LLStyle::Params mStyle;
 	bool		mUnderlineOnHoverOnly;
 };
 
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 9d215cf7ef7a9a29cd0ab1fe18ce80bd9ae15b39..478b412d5ea541a2bbd908d9b4f3055bede59882 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -31,18 +31,25 @@
 #include <boost/regex.hpp>
 
 // default dummy callback that ignores any label updates from the server
-void LLUrlRegistryNullCallback(const std::string &url, const std::string &label)
+void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, const std::string& icon)
 {
 }
 
 LLUrlRegistry::LLUrlRegistry()
 {
+	mUrlEntry.reserve(20);
+
 	// Urls are matched in the order that they were registered
 	registerUrl(new LLUrlEntryNoLink());
 	registerUrl(new LLUrlEntryIcon());
 	registerUrl(new LLUrlEntrySLURL());
 	registerUrl(new LLUrlEntryHTTP());
 	registerUrl(new LLUrlEntryHTTPLabel());
+	registerUrl(new LLUrlEntryAgentCompleteName());
+	registerUrl(new LLUrlEntryAgentDisplayName());
+	registerUrl(new LLUrlEntryAgentUserName());
+	// LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since 
+	// LLUrlEntryAgent is a less specific (catchall for agent urls)
 	registerUrl(new LLUrlEntryAgent());
 	registerUrl(new LLUrlEntryGroup());
 	registerUrl(new LLUrlEntryParcel());
@@ -71,10 +78,13 @@ LLUrlRegistry::~LLUrlRegistry()
 	}
 }
 
-void LLUrlRegistry::registerUrl(LLUrlEntryBase *url)
+void LLUrlRegistry::registerUrl(LLUrlEntryBase *url, bool force_front)
 {
 	if (url)
 	{
+		if (force_front)  // IDEVO
+			mUrlEntry.insert(mUrlEntry.begin(), url);
+		else
 		mUrlEntry.push_back(url);
 	}
 }
@@ -174,10 +184,9 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
 						match_entry->getLabel(url, cb),
 						match_entry->getTooltip(url),
 						match_entry->getIcon(url),
-						match_entry->getColor(),
+						match_entry->getStyle(),
 						match_entry->getMenuName(),
 						match_entry->getLocation(url),
-						match_entry->isLinkDisabled(),
 						match_entry->getID(url),
 						match_entry->underlineOnHoverOnly(url));
 		return true;
@@ -210,10 +219,9 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
 						match.getLabel(),
 						match.getTooltip(),
 						match.getIcon(),
-						match.getColor(),
+						match.getStyle(),
 						match.getMenuName(),
 						match.getLocation(),
-						match.isLinkDisabled(),
 						match.getID(),
 						match.underlineOnHoverOnly());
 		return true;
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index 24ce516c4307c4681c385bc8b8a9cca3742e1bbe..da16171a9753f9c0c76fc2ab573481d45dcbc888 100644
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -37,7 +37,9 @@
 #include <vector>
 
 /// This default callback for findUrl() simply ignores any label updates
-void LLUrlRegistryNullCallback(const std::string &url, const std::string &label);
+void LLUrlRegistryNullCallback(const std::string &url,
+							   const std::string &label,
+							   const std::string &icon);
 
 ///
 /// LLUrlRegistry is a singleton that contains a set of Url types that
@@ -64,7 +66,9 @@ class LLUrlRegistry : public LLSingleton<LLUrlRegistry>
 	~LLUrlRegistry();
 
 	/// add a new Url handler to the registry (will be freed on destruction)
-	void registerUrl(LLUrlEntryBase *url);
+	/// optionally force it to the front of the list, making it take
+	/// priority over other regular expression matches for URLs
+	void registerUrl(LLUrlEntryBase *url, bool force_front = false);
 
 	/// get the next Url in an input string, starting at a given character offset
 	/// your callback is invoked if the matched Url's label changes in the future
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index ff53ae562470b9b31c6bcd6281334a67ce546703..c062a38077552835f7cf2a079b4a76825c92aad0 100644
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -27,11 +27,28 @@
 
 #include "llstring.h"
 #include "llfile.h"
+#include "llavatarnamecache.h"
 #include "llcachename.h"
 #include "lluuid.h"
 
 #include <string>
 
+// Stub for LLAvatarNameCache
+bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
+{
+	return false;
+}
+
+void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
+{
+	return;
+}
+
+bool LLAvatarNameCache::useDisplayNames()
+{
+	return false;
+}
+
 //
 // Stub implementation for LLCacheName
 //
@@ -47,7 +64,12 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
 	return TRUE;
 }
 
-boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
+{
+	return boost::signals2::connection();
+}
+
+boost::signals2::connection LLCacheName::getGroup(const LLUUID& id, const LLCacheNameCallback& callback)
 {
 	return boost::signals2::connection();
 }
@@ -67,3 +89,106 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::
 {
 	return std::string();
 }
+
+//
+// Stub implementation for LLStyle::Params::Params
+//
+
+LLStyle::Params::Params()
+{
+}
+
+//
+// Stub implementations for various LLInitParam classes
+//
+
+namespace LLInitParam
+{
+	BaseBlock::BaseBlock() {}
+	BaseBlock::~BaseBlock() {}
+	Param::Param(BaseBlock* enclosing_block)
+	:	mIsProvided(false)
+	{
+		const U8* my_addr = reinterpret_cast<const U8*>(this);
+		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
+		mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+	}
+	void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {}
+
+	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){}
+	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
+	
+	void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+	{
+		mBlockDescriptor = &descriptor;
+		descriptor.mCurrentBlockPtr = this;
+	}
+	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; }
+	bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; }
+	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; }
+	bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
+	bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
+
+	TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+	:	super_t(descriptor, name, value, func, min_count, max_count)
+	{}
+
+	void TypedParam<LLUIColor>::setValueFromBlock() const
+	{}
+	
+	void TypedParam<LLUIColor>::setBlockFromValue()
+	{}
+
+	void TypeValues<LLUIColor>::declareValues()
+	{}
+
+	bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
+	{
+		return false;
+	}
+
+	TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+	:	super_t(descriptor, _name, value, func, min_count, max_count)
+	{}
+
+	void TypedParam<const LLFontGL*>::setValueFromBlock() const
+	{}
+	
+	void TypedParam<const LLFontGL*>::setBlockFromValue()
+	{}
+
+	void TypeValues<LLFontGL::HAlign>::declareValues()
+	{}
+
+	void TypeValues<LLFontGL::VAlign>::declareValues()
+	{}
+
+	void TypeValues<LLFontGL::ShadowType>::declareValues()
+	{}
+
+	void TypedParam<LLUIImage*>::setValueFromBlock() const
+	{}
+	
+	void TypedParam<LLUIImage*>::setBlockFromValue()
+	{}
+
+	
+	bool ParamCompare<LLUIImage*, false>::equals(
+		LLUIImage* const &a,
+		LLUIImage* const &b)
+	{
+		return false;
+	}
+
+	bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
+	{
+		return false;
+	}
+
+}
+
+//static
+LLFontGL* LLFontGL::getFontDefault()
+{
+	return NULL; 
+}
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 95affe4460ff65b10bc153c66e5a472a6bbd3a62..5c6623da6105e583a0fdff7276c26c4fd295b350 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -30,6 +30,7 @@
 #include "llurlentry_stub.cpp"
 #include "lltut.h"
 #include "../lluicolortable.h"
+#include "../lluiimage.h"
 
 #include <boost/regex.hpp>
 
@@ -40,6 +41,26 @@ LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& defa
 
 LLUIColor::LLUIColor() : mColorPtr(NULL) {}
 
+LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
+{
+}
+
+LLUIImage::~LLUIImage()
+{
+}
+
+//virtual
+S32 LLUIImage::getWidth() const
+{
+	return 0;
+}
+
+//virtual
+S32 LLUIImage::getHeight() const
+{
+	return 0;
+}
+
 namespace tut
 {
 	struct LLUrlEntryData
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index 4e38bea1bd458040103c5874b6aa8aa56cc94294..560d83100b76664e98eb6dd40ff79b37dda23555 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -25,14 +25,136 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
+
 #include "../llurlmatch.h"
+#include "../lluiimage.h"
 #include "lltut.h"
 
-// link seam
+// link seams
+
 LLUIColor::LLUIColor()
 	: mColorPtr(NULL)
 {}
 
+LLStyle::Params::Params()
+{
+}
+
+LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
+{
+}
+
+LLUIImage::~LLUIImage()
+{
+}
+
+//virtual
+S32 LLUIImage::getWidth() const
+{
+	return 0;
+}
+
+//virtual
+S32 LLUIImage::getHeight() const
+{
+	return 0;
+}
+
+namespace LLInitParam
+{
+	BaseBlock::BaseBlock() {}
+	BaseBlock::~BaseBlock() {}
+
+	void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {}
+
+	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){}
+	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
+	
+	void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+	{
+		mBlockDescriptor = &descriptor;
+		descriptor.mCurrentBlockPtr = this;
+	}
+
+	Param::Param(BaseBlock* enclosing_block)
+	:	mIsProvided(false)
+	{
+		const U8* my_addr = reinterpret_cast<const U8*>(this);
+		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
+		mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+	}
+
+	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; }
+	bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; }
+	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; }
+	bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
+	bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
+
+	TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+	:	super_t(descriptor, name, value, func, min_count, max_count)
+	{}
+
+	void TypedParam<LLUIColor>::setValueFromBlock() const
+	{}
+	
+	void TypedParam<LLUIColor>::setBlockFromValue()
+	{}
+
+	void TypeValues<LLUIColor>::declareValues()
+	{}
+
+	bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
+	{
+		return false;
+	}
+
+	TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+	:	super_t(descriptor, _name, value, func, min_count, max_count)
+	{}
+
+	void TypedParam<const LLFontGL*>::setValueFromBlock() const
+	{}
+	
+	void TypedParam<const LLFontGL*>::setBlockFromValue()
+	{}
+
+	void TypeValues<LLFontGL::HAlign>::declareValues()
+	{}
+
+	void TypeValues<LLFontGL::VAlign>::declareValues()
+	{}
+
+	void TypeValues<LLFontGL::ShadowType>::declareValues()
+	{}
+
+	void TypedParam<LLUIImage*>::setValueFromBlock() const
+	{}
+	
+	void TypedParam<LLUIImage*>::setBlockFromValue()
+	{}
+	
+	bool ParamCompare<LLUIImage*, false>::equals(
+		LLUIImage* const &a,
+		LLUIImage* const &b)
+	{
+		return false;
+	}
+
+	bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
+	{
+		return false;
+	}
+
+}
+
+//static
+LLFontGL* LLFontGL::getFontDefault()
+{
+	return NULL; 
+}
+
+
 namespace tut
 {
 	struct LLUrlMatchData
@@ -59,7 +181,7 @@ namespace tut
 		LLUrlMatch match;
 		ensure("empty()", match.empty());
 
-		match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure("! empty()", ! match.empty());
 	}
 
@@ -72,7 +194,7 @@ namespace tut
 		LLUrlMatch match;
 		ensure_equals("getStart() == 0", match.getStart(), 0);
 
-		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getStart() == 10", match.getStart(), 10);
 	}
 
@@ -85,7 +207,7 @@ namespace tut
 		LLUrlMatch match;
 		ensure_equals("getEnd() == 0", match.getEnd(), 0);
 
-		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getEnd() == 20", match.getEnd(), 20);
 	}
 
@@ -98,10 +220,10 @@ namespace tut
 		LLUrlMatch match;
 		ensure_equals("getUrl() == ''", match.getUrl(), "");
 
-		match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "http://slurl.com/", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/");
 
-		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getUrl() == '' (2)", match.getUrl(), "");
 	}
 
@@ -114,10 +236,10 @@ namespace tut
 		LLUrlMatch match;
 		ensure_equals("getLabel() == ''", match.getLabel(), "");
 
-		match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "Label", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label");
 
-		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getLabel() == '' (2)", match.getLabel(), "");
 	}
 
@@ -130,10 +252,10 @@ namespace tut
 		LLUrlMatch match;
 		ensure_equals("getTooltip() == ''", match.getTooltip(), "");
 
-		match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "Info", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info");
 
-		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");
 	}
 
@@ -146,10 +268,10 @@ namespace tut
 		LLUrlMatch match;
 		ensure_equals("getIcon() == ''", match.getIcon(), "");
 
-		match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon");
 
-		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure_equals("getIcon() == '' (2)", match.getIcon(), "");
 	}
 
@@ -162,10 +284,10 @@ namespace tut
 		LLUrlMatch match;
 		ensure("getMenuName() empty", match.getMenuName().empty());
 
-		match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "xui_file.xml", "", LLUUID::null);
 		ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml");
 
-		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure("getMenuName() empty (2)", match.getMenuName().empty());
 	}
 
@@ -178,10 +300,10 @@ namespace tut
 		LLUrlMatch match;
 		ensure("getLocation() empty", match.getLocation().empty());
 
-		match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "xui_file.xml", "Paris", LLUUID::null);
 		ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris");
 
-		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+		match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
 		ensure("getLocation() empty (2)", match.getLocation().empty());
 	}
 }
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 630902c48f5dcafdcc0d3d9a8e93de4b1e4bdb00..6b212b92e2c0ac5f63912f6d81278c201dd032f4 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -238,6 +238,7 @@ set(viewer_SOURCE_FILES
     llhudeffecttrail.cpp
     llhudicon.cpp
     llhudmanager.cpp
+    llhudnametag.cpp
     llhudobject.cpp
     llhudrender.cpp
     llhudtext.cpp
@@ -476,6 +477,7 @@ set(viewer_SOURCE_FILES
     llviewercontrol.cpp
     llviewercontrollistener.cpp
     llviewerdisplay.cpp
+    llviewerdisplayname.cpp
     llviewerfloaterreg.cpp
     llviewerfoldertype.cpp
     llviewergenericmessage.cpp
@@ -762,6 +764,7 @@ set(viewer_HEADER_FILES
     llhudeffecttrail.h
     llhudicon.h
     llhudmanager.h
+    llhudnametag.h
     llhudobject.h
     llhudrender.h
     llhudtext.h
@@ -1000,6 +1003,7 @@ set(viewer_HEADER_FILES
     llviewercontrol.h
     llviewercontrollistener.h
     llviewerdisplay.h
+    llviewerdisplayname.h
     llviewerfloaterreg.h
     llviewerfoldertype.h
     llviewergenericmessage.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 6285df31c0e03ae0cce05279e3b8fb9681be7051..80f610bb2f889325cdac9e64fef4105bfbfae437 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7899,7 +7899,7 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>RenderShowGroupTitleAll</key>
+    <key>NameTagShowGroupTitles</key>
     <map>
       <key>Comment</key>
       <string>Show group titles in name labels</string>
@@ -7908,7 +7908,40 @@
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>NameTagShowDisplayNames</key>
+    <map>
+      <key>Comment</key>
+      <string>Show display names in name labels</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>NameTagShowFriends</key>
+    <map>
+      <key>Comment</key>
+      <string>Highlight the name tags of your friends</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>NameTagShowUsernames</key>
+    <map>
+      <key>Comment</key>
+      <string>Show usernames in avatar name tags</string>
+      <key>Persist</key>
       <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
     </map>
     <key>RenderInitError</key>
     <map>
@@ -10936,6 +10969,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+  <key>UseDisplayNames</key>
+  <map>
+    <key>Comment</key>
+    <string>Use new, changeable, unicode names</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>1</integer>
+  </map>
     <key>UseEnergy</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp
index f52f1361181f948a011312c35832d2a8f8f8dfd1..b9ec304b7eb8eb6996b68bdc1bfe630a8b5d825a 100644
--- a/indra/newview/llagentui.cpp
+++ b/indra/newview/llagentui.cpp
@@ -39,29 +39,6 @@
 #include "llvoavatarself.h"
 #include "llslurl.h"
 
-//static
-void LLAgentUI::buildName(std::string& name)
-{
-	name.clear();
-	if (isAgentAvatarValid())
-	{
-		LLNameValue *first_nv = gAgentAvatarp->getNVPair("FirstName");
-		LLNameValue *last_nv = gAgentAvatarp->getNVPair("LastName");
-		if (first_nv && last_nv)
-		{
-			name = first_nv->printData() + " " + last_nv->printData();
-		}
-		else
-		{
-			llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl;
-		}
-	}
-	else
-	{
-		name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName");
-	}
-}
-
 //static
 void LLAgentUI::buildFullname(std::string& name)
 {
diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h
index afc0ba5d9a623d86fe4df0d043a744e4109b11f5..dda5dc1fd11560afa2e9cbd56a83309d2371043d 100644
--- a/indra/newview/llagentui.h
+++ b/indra/newview/llagentui.h
@@ -41,7 +41,6 @@ class LLAgentUI
 		LOCATION_FORMAT_FULL,			// Parcel, Region (x, y, z) - Maturity
 	};
 
-	static void buildName(std::string& name);
 	static void buildFullname(std::string &name);
 
 	static void buildSLURL(LLSLURL& slurl, const bool escaped = true);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index bfe3e52657019fbb34f4f832005bf51a5706d821..97f59612330e8d071104ba76f7e65b359c118dae 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -84,6 +84,7 @@
 #include "llsecondlifeurls.h"
 
 // Linden library includes
+#include "llavatarnamecache.h"
 #include "llimagej2c.h"
 #include "llmemory.h"
 #include "llprimitive.h"
@@ -156,7 +157,6 @@
 // Included so that constants/settings might be initialized
 // in save_settings_to_globals()
 #include "llbutton.h"
-#include "llcombobox.h"
 #include "llstatusbar.h"
 #include "llsurface.h"
 #include "llvosky.h"
@@ -432,9 +432,6 @@ static void settings_to_globals()
 	MENU_BAR_HEIGHT		= gSavedSettings.getS32("MenuBarHeight");
 	MENU_BAR_WIDTH		= gSavedSettings.getS32("MenuBarWidth");
 
-	LLCOMBOBOX_HEIGHT	= BTN_HEIGHT - 2;
-	LLCOMBOBOX_WIDTH	= 128;
-
 	LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
 	
 	LLImageGL::sGlobalUseAnisotropic	= gSavedSettings.getBOOL("RenderAnisotropic");
@@ -1353,8 +1350,7 @@ bool LLAppViewer::cleanup()
 
 	LLPolyMesh::freeAllMeshes();
 
-	delete gCacheName;
-	gCacheName = NULL;
+	LLStartUp::cleanupNameCache();
 
 	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
 
@@ -3420,6 +3416,15 @@ void LLAppViewer::saveFinalSnapshot()
 
 void LLAppViewer::loadNameCache()
 {
+	// display names cache
+	std::string filename =
+		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+	llifstream name_cache_stream(filename);
+	if(name_cache_stream.is_open())
+	{
+		LLAvatarNameCache::importFile(name_cache_stream);
+	}
+
 	if (!gCacheName) return;
 
 	std::string name_cache;
@@ -3429,19 +3434,19 @@ void LLAppViewer::loadNameCache()
 	{
 		if(gCacheName->importFile(cache_file)) return;
 	}
+}
 
-	// Try to load from the legacy format. This should go away after a
-	// while. Phoenix 2008-01-30
-	LLFILE* name_cache_fp = LLFile::fopen(name_cache, "r");		// Flawfinder: ignore
-	if (name_cache_fp)
+void LLAppViewer::saveNameCache()
 	{
-		gCacheName->importFile(name_cache_fp);
-		fclose(name_cache_fp);
-	}
+	// display names cache
+	std::string filename =
+		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+	llofstream name_cache_stream(filename);
+	if(name_cache_stream.is_open())
+	{
+		LLAvatarNameCache::exportFile(name_cache_stream);
 }
 
-void LLAppViewer::saveNameCache()
-{
 	if (!gCacheName) return;
 
 	std::string name_cache;
@@ -3641,6 +3646,7 @@ void LLAppViewer::idle()
 	    // NOTE: Starting at this point, we may still have pointers to "dead" objects
 	    // floating throughout the various object lists.
 	    //
+		idleNameCache();
     
 		idleNetwork();
 	    	        
@@ -3978,6 +3984,60 @@ void LLAppViewer::sendLogoutRequest()
 	}
 }
 
+void LLAppViewer::idleNameCache()
+{
+	// Neither old nor new name cache can function before agent has a region
+	LLViewerRegion* region = gAgent.getRegion();
+	if (!region) return;
+
+	// deal with any queued name requests and replies.
+	gCacheName->processPending();
+
+	// Can't run the new cache until we have the list of capabilities
+	// for the agent region, and can therefore decide whether to use
+	// display names or fall back to the old name system.
+	if (!region->capabilitiesReceived()) return;
+
+	// Agent may have moved to a different region, so need to update cap URL
+	// for name lookups.  Can't do this in the cap grant code, as caps are
+	// granted to neighbor regions before the main agent gets there.  Can't
+	// do it in the move-into-region code because cap not guaranteed to be
+	// granted yet, for example on teleport.
+	bool had_capability = LLAvatarNameCache::hasNameLookupURL();
+	std::string name_lookup_url;
+	name_lookup_url.reserve(128); // avoid a memory allocation below
+	name_lookup_url = region->getCapability("GetDisplayNames");
+	bool have_capability = !name_lookup_url.empty();
+	if (have_capability)
+	{
+		// we have support for display names, use it
+	    U32 url_size = name_lookup_url.size();
+	    // capabilities require URLs with slashes before query params:
+	    // https://<host>:<port>/cap/<uuid>/?ids=<blah>
+	    // but the caps are granted like:
+	    // https://<host>:<port>/cap/<uuid>
+	    if (url_size > 0 && name_lookup_url[url_size-1] != '/')
+	    {
+		    name_lookup_url += '/';
+	    }
+		LLAvatarNameCache::setNameLookupURL(name_lookup_url);
+	}
+	else
+	{
+		// Display names not available on this region
+		LLAvatarNameCache::setNameLookupURL( std::string() );
+	}
+
+	// Error recovery - did we change state?
+	if (had_capability != have_capability)
+	{
+		// name tags are persistant on screen, so make sure they refresh
+		LLVOAvatar::invalidateNameTags();
+	}
+
+	LLAvatarNameCache::idle();
+}
+
 //
 // Handle messages, and all message related stuff
 //
@@ -4003,8 +4063,6 @@ void LLAppViewer::idleNetwork()
 	{
 		LLFastTimer t(FTM_IDLE_NETWORK); // decode
 		
-		// deal with any queued name requests and replies.
-		gCacheName->processPending();
 		LLTimer check_message_timer;
 		//  Read all available packets from network 
 		const S64 frame_count = gFrameCount;  // U32->S64
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 1fcf38d18ad8ffd41a43a4e378ff113ffc73acaf..9a214ce0c6aeab448636fe7d33c5861a8755e24a 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -203,6 +203,8 @@ class LLAppViewer : public LLApp
     
     void idle(); 
     void idleShutdown();
+	// update avatar SLID and display name caches
+	void idleNameCache();
     void idleNetwork();
 
     void sendLogoutRequest();
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index b9ae976e58f2c59bb42bd585283a060910524490..00c2e9fabaa1801662865a7999450f974d833f3a 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -31,11 +31,11 @@
 
 #include "boost/lambda/lambda.hpp"	// for lambda::constant
 
+#include "llavatarnamecache.h"	// IDEVO
 #include "llsd.h"
 #include "lldarray.h"
 #include "llnotifications.h"
 #include "llnotificationsutil.h"
-
 #include "roles_constants.h"    // for GP_MEMBER_INVITE
 
 #include "llagent.h"
@@ -64,6 +64,7 @@
 #include "llimfloater.h"
 #include "lltrans.h"
 #include "llcallingcard.h"
+#include "llslurl.h"			// IDEVO
 
 // static
 void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)
@@ -75,26 +76,22 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::strin
 	}
 
 	LLSD args;
-	args["NAME"] = name;
+	args["NAME"] = LLSLURL("agent", id, "completename").getSLURLString();
 	LLSD payload;
 	payload["id"] = id;
 	payload["name"] = name;
-    // Look for server versions like: Second Life Server 1.24.4.95600
-	if (gLastVersionChannel.find(" 1.24.") != std::string::npos)
-	{
-		// Old and busted server version, doesn't support friend
-		// requests with messages.
-    	LLNotificationsUtil::add("AddFriend", args, payload, &callbackAddFriend);
-	}
-	else
-	{
+    
     	LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage);
-	}
 
 	// add friend to recent people list
 	LLRecentPeople::instance().add(id);
 }
 
+void on_avatar_name_friendship(const LLUUID& id, const LLAvatarName av_name)
+{
+	LLAvatarActions::requestFriendshipDialog(id, av_name.getCompleteName());
+}
+
 // static
 void LLAvatarActions::requestFriendshipDialog(const LLUUID& id)
 {
@@ -103,9 +100,7 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id)
 		return;
 	}
 
-	std::string full_name;
-	gCacheName->getFullName(id, full_name);
-	requestFriendshipDialog(id, full_name);
+	LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_friendship, _1, _2));
 }
 
 // static
@@ -130,11 +125,10 @@ void LLAvatarActions::removeFriendsDialog(const uuid_vec_t& ids)
 	if(ids.size() == 1)
 	{
 		LLUUID agent_id = ids[0];
-		std::string first, last;
-		if(gCacheName->getName(agent_id, first, last))
+		LLAvatarName av_name;
+		if(LLAvatarNameCache::get(agent_id, &av_name))
 		{
-			args["FIRST_NAME"] = first;
-			args["LAST_NAME"] = last;	
+			args["NAME"] = av_name.mDisplayName;
 		}
 
 		msgType = "RemoveFromFriends";
@@ -162,14 +156,6 @@ void LLAvatarActions::offerTeleport(const LLUUID& invitee)
 	if (invitee.isNull())
 		return;
 
-	//waiting until Name Cache gets updated with corresponding avatar name
-	std::string just_to_request_name;
-	if (!gCacheName->getFullName(invitee, just_to_request_name))
-	{
-		gCacheName->get(invitee, FALSE, boost::bind((void (*)(const LLUUID&)) &LLAvatarActions::offerTeleport, invitee));
-		return;
-	}
-
 	LLDynamicArray<LLUUID> ids;
 	ids.push_back(invitee);
 	offerTeleport(ids);
@@ -184,20 +170,11 @@ void LLAvatarActions::offerTeleport(const uuid_vec_t& ids)
 	handle_lure(ids);
 }
 
-// static
-void LLAvatarActions::startIM(const LLUUID& id)
+static void on_avatar_name_cache_start_im(const LLUUID& agent_id,
+										  const LLAvatarName& av_name)
 {
-	if (id.isNull())
-		return;
-
-	std::string name;
-	if (!gCacheName->getFullName(id, name))
-	{
-		gCacheName->get(id, FALSE, boost::bind(&LLAvatarActions::startIM, id));
-		return;
-	}
-
-	LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
+	std::string name = av_name.getCompleteName();
+	LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id);
 	if (session_id != LLUUID::null)
 	{
 		LLIMFloater::show(session_id);
@@ -205,6 +182,16 @@ void LLAvatarActions::startIM(const LLUUID& id)
 	make_ui_sound("UISndStartIM");
 }
 
+// static
+void LLAvatarActions::startIM(const LLUUID& id)
+{
+	if (id.isNull())
+		return;
+
+	LLAvatarNameCache::get(id,
+		boost::bind(&on_avatar_name_cache_start_im, _1, _2));
+}
+
 // static
 void LLAvatarActions::endIM(const LLUUID& id)
 {
@@ -218,6 +205,18 @@ void LLAvatarActions::endIM(const LLUUID& id)
 	}
 }
 
+static void on_avatar_name_cache_start_call(const LLUUID& agent_id,
+											const LLAvatarName& av_name)
+{
+	std::string name = av_name.getCompleteName();
+	LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id, true);
+	if (session_id != LLUUID::null)
+	{
+		gIMMgr->startCall(session_id);
+	}
+	make_ui_sound("UISndStartIM");
+}
+
 // static
 void LLAvatarActions::startCall(const LLUUID& id)
 {
@@ -225,15 +224,8 @@ void LLAvatarActions::startCall(const LLUUID& id)
 	{
 		return;
 	}
-
-	std::string name;
-	gCacheName->getFullName(id, name);
-	LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id, true);
-	if (session_id != LLUUID::null)
-	{
-		gIMMgr->startCall(session_id);
-	}
-	make_ui_sound("UISndStartIM");
+	LLAvatarNameCache::get(id,
+		boost::bind(&on_avatar_name_cache_start_call, _1, _2));
 }
 
 // static
@@ -329,14 +321,14 @@ void LLAvatarActions::showProfile(const LLUUID& id)
 // static
 void LLAvatarActions::showOnMap(const LLUUID& id)
 {
-	std::string name;
-	if (!gCacheName->getFullName(id, name))
+	LLAvatarName av_name;
+	if (!LLAvatarNameCache::get(id, &av_name))
 	{
-		gCacheName->get(id, FALSE, boost::bind(&LLAvatarActions::showOnMap, id));
+		LLAvatarNameCache::get(id, boost::bind(&LLAvatarActions::showOnMap, id));
 		return;
 	}
 
-	gFloaterWorldMap->trackAvatar(id, name);
+	gFloaterWorldMap->trackAvatar(id, av_name.mDisplayName);
 	LLFloaterReg::showInstance("world_map");
 }
 
@@ -486,14 +478,15 @@ namespace action_give_inventory
 		return acceptable;
 	}
 
-	static void build_residents_string(const std::vector<std::string>& avatar_names, std::string& residents_string)
+	static void build_residents_string(const std::vector<LLAvatarName> avatar_names, std::string& residents_string)
 	{
 		llassert(avatar_names.size() > 0);
 
 		const std::string& separator = LLTrans::getString("words_separator");
-		for (std::vector<std::string>::const_iterator it = avatar_names.begin(); ; )
+		for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; )
 		{
-			residents_string.append(*it);
+			LLAvatarName av_name = *it;
+			residents_string.append(av_name.mDisplayName);
 			if	(++it == avatar_names.end())
 			{
 				break;
@@ -530,7 +523,7 @@ namespace action_give_inventory
 
 	struct LLShareInfo : public LLSingleton<LLShareInfo>
 	{
-		std::vector<std::string> mAvatarNames;
+		std::vector<LLAvatarName> mAvatarNames;
 		uuid_vec_t mAvatarUuids;
 	};
 
@@ -595,7 +588,7 @@ namespace action_give_inventory
 				}
 				else
 				{
-					LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
+				LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
 					shared = true;
 				}
 			}
@@ -627,11 +620,10 @@ namespace action_give_inventory
 	 * @param avatar_names - avatar names request to be sent.
 	 * @param avatar_uuids - avatar names request to be sent.
 	 */
-	static void give_inventory(const std::vector<std::string>& avatar_names, const uuid_vec_t& avatar_uuids)
+	static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names)
 	{
 		llassert(avatar_names.size() == avatar_uuids.size());
 
-
 		LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
 		if (!active_panel)
 		{
@@ -677,7 +669,7 @@ void LLAvatarActions::toggleBlock(const LLUUID& id)
 {
 	std::string name;
 
-	gCacheName->getFullName(id, name);
+	gCacheName->getFullName(id, name); // needed for mute
 	LLMute mute(id, name, LLMute::AGENT);
 
 	if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
@@ -865,23 +857,6 @@ bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& respo
 	}
 	return false;
 }
-// static
-bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (option == 0)
-	{
-		// Servers older than 1.25 require the text of the message to be the
-		// calling card folder ID for the offering user. JC
-		LLUUID calling_card_folder_id = 
-			gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
-		std::string message = calling_card_folder_id.asString();
-		requestFriendship(notification["payload"]["id"].asUUID(), 
-		    notification["payload"]["name"].asString(),
-		    message);
-	}
-    return false;
-}
 
 // static
 void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message)
@@ -899,7 +874,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri
 
 	LLSD payload;
 	payload["from_id"] = target_id;
-	payload["SESSION_NAME"] = target_name;
 	payload["SUPPRESS_TOAST"] = true;
 	LLNotificationsUtil::add("FriendshipOffered", args, payload);
 }
@@ -914,16 +888,16 @@ bool LLAvatarActions::isFriend(const LLUUID& id)
 bool LLAvatarActions::isBlocked(const LLUUID& id)
 {
 	std::string name;
-	gCacheName->getFullName(id, name);
+	gCacheName->getFullName(id, name); // needed for mute
 	return LLMuteList::getInstance()->isMuted(id, name);
 }
 
 // static
 bool LLAvatarActions::canBlock(const LLUUID& id)
 {
-	std::string firstname, lastname;
-	gCacheName->getName(id, firstname, lastname);
-	bool is_linden = !LLStringUtil::compareStrings(lastname, "Linden");
+	std::string full_name;
+	gCacheName->getFullName(id, full_name); // needed for mute
+	bool is_linden = (full_name.find("Linden") != std::string::npos);
 	bool is_self = id == gAgentID;
 	return !is_self && !is_linden;
 }
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 6313ae075931c75d8216223ff27521736891d9f5..9cfdc884dc4b7230e51230d7216e2bd1e55d0850 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -184,7 +184,6 @@ class LLAvatarActions
 	static bool canOfferTeleport(const uuid_vec_t& ids);
 
 private:
-	static bool callbackAddFriend(const LLSD& notification, const LLSD& response);
 	static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
 	static bool handleRemove(const LLSD& notification, const LLSD& response);
 	static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id);
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index 09fbed9e06b4d772fc8071d3c88f53a16ee2cda2..d0f4d19f561df37d2d66d974904ccfe76be399b7 100644
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -28,17 +28,19 @@
 
 #include "llavatariconctrl.h"
 
+// viewer includes
 #include "llagent.h"
 #include "llavatarconstants.h"
 #include "llcallingcard.h" // for LLAvatarTracker
 #include "llavataractions.h"
 #include "llmenugl.h"
 #include "lluictrlfactory.h"
-
-#include "llcachename.h"
 #include "llagentdata.h"
 #include "llimfloater.h"
 
+// library includes
+#include "llavatarnamecache.h"
+
 #define MENU_ITEM_VIEW_PROFILE 0
 #define MENU_ITEM_SEND_IM 1
 
@@ -227,6 +229,9 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
 			// Check if cache already contains image_id for that avatar
 			if (!updateFromCache())
 			{
+				// *TODO: Consider getting avatar icon/badge directly from 
+				// People API, rather than sending AvatarPropertyRequest
+				// messages.  People API already hits the user table.
 				LLIconCtrl::setValue(mDefaultIconName);
 				app->addObserver(mAvatarId, this);
 				app->sendAvatarPropertiesRequest(mAvatarId);
@@ -238,10 +243,9 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
 		LLIconCtrl::setValue(value);
 	}
 
-	if  (gCacheName)
-	{
-		gCacheName->get(mAvatarId, FALSE, boost::bind(&LLAvatarIconCtrl::nameUpdatedCallback, this, _1, _2, _3, _4));
-	}
+	LLAvatarNameCache::get(mAvatarId,
+		boost::bind(&LLAvatarIconCtrl::onAvatarNameCache, 
+			this, _1, _2));
 }
 
 bool LLAvatarIconCtrl::updateFromCache()
@@ -284,24 +288,21 @@ void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type)
 	}
 }
 
-void LLAvatarIconCtrl::nameUpdatedCallback(
-	const LLUUID& id,
-	const std::string& first,
-	const std::string& last,
-	BOOL is_group)
+void LLAvatarIconCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
 {
-	if (id == mAvatarId)
+	if (agent_id == mAvatarId)
 	{
-		mFirstName = first;
-		mLastName = last;
+		// Most avatar icon controls are next to a UI element that shows
+		// a display name, so only show username.
+		mFullName = av_name.mUsername;
 
 		if (mDrawTooltip)
 		{
-			setToolTip(mFirstName + " " + mLastName);
+			setToolTip(mFullName);
 		}
 		else
 		{
-			setToolTip(std::string(""));
+			setToolTip(std::string());
 		}
 	}
 }
diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
index b24d7356a84fa4bd3544aca916e20912ab931ab9..7f568fc5b89314f1e9798e44fc2794cff7942b89 100644
--- a/indra/newview/llavatariconctrl.h
+++ b/indra/newview/llavatariconctrl.h
@@ -31,6 +31,8 @@
 #include "llavatarpropertiesprocessor.h"
 #include "llviewermenu.h"
 
+class LLAvatarName;
+
 class LLAvatarIconIDCache: public LLSingleton<LLAvatarIconIDCache>
 {
 public:
@@ -84,22 +86,16 @@ class LLAvatarIconCtrl
 	// LLAvatarPropertiesProcessor observer trigger
 	virtual void processProperties(void* data, EAvatarProcessorType type);
 
-	void nameUpdatedCallback(
-		const LLUUID& id,
-		const std::string& first,
-		const std::string& last,
-		BOOL is_group);
+	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
 
 	const LLUUID&		getAvatarId() const	{ return mAvatarId; }
-	const std::string&	getFirstName() const { return mFirstName; }
-	const std::string&	getLastName() const { return mLastName; }
+	const std::string&	getFullName() const { return mFullName; }
 
 	void setDrawTooltip(bool value) { mDrawTooltip = value;}
 
 protected:
 	LLUUID				mAvatarId;
-	std::string			mFirstName;
-	std::string			mLastName;
+	std::string			mFullName;
 	bool				mDrawTooltip;
 	std::string			mDefaultIconName;
 
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 1cd705c2f9d8b555f56a83cbb388e029083a00a2..24596e5723afc39b80121193023234ef3d3f9655 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -38,6 +38,7 @@
 // newview
 #include "llagentdata.h" // for comparator
 #include "llavatariconctrl.h"
+#include "llavatarnamecache.h"
 #include "llcallingcard.h" // for LLAvatarTracker
 #include "llcachename.h"
 #include "lllistcontextmenu.h"
@@ -236,12 +237,15 @@ void LLAvatarList::refresh()
 
 	// Handle added items.
 	unsigned nadded = 0;
+	const std::string waiting_str = LLTrans::getString("AvatarNameWaiting");
+
 	for (uuid_vec_t::const_iterator it=added.begin(); it != added.end(); it++)
 	{
-		std::string name;
 		const LLUUID& buddy_id = *it;
-		have_names &= (bool)gCacheName->getFullName(buddy_id, name);
-		if (!have_filter || findInsensitive(name, mNameFilter))
+		LLAvatarName av_name;
+		have_names &= LLAvatarNameCache::get(buddy_id, &av_name);
+
+		if (!have_filter || findInsensitive(av_name.mDisplayName, mNameFilter))
 		{
 			if (nadded >= ADD_LIMIT)
 			{
@@ -250,7 +254,11 @@ void LLAvatarList::refresh()
 			}
 			else
 			{
-				addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
+				// *NOTE: If you change the UI to show a different string,
+				// be sure to change the filter code below.
+				addNewItem(buddy_id, 
+					       av_name.mDisplayName.empty() ? waiting_str : av_name.mDisplayName, 
+						   LLAvatarTracker::instance().isBuddyOnline(buddy_id));
 				modified = true;
 				nadded++;
 			}
@@ -272,10 +280,10 @@ void LLAvatarList::refresh()
 
 		for (std::vector<LLSD>::const_iterator it=cur_values.begin(); it != cur_values.end(); it++)
 		{
-			std::string name;
 			const LLUUID& buddy_id = it->asUUID();
-			have_names &= (bool)gCacheName->getFullName(buddy_id, name);
-			if (!findInsensitive(name, mNameFilter))
+			LLAvatarName av_name;
+			have_names &= LLAvatarNameCache::get(buddy_id, &av_name);
+			if (!findInsensitive(av_name.mDisplayName, mNameFilter))
 			{
 				removeItemByUUID(buddy_id);
 				modified = true;
@@ -327,14 +335,14 @@ bool LLAvatarList::filterHasMatches()
 
 	for (uuid_vec_t::const_iterator it=values.begin(); it != values.end(); it++)
 	{
-		std::string name;
 		const LLUUID& buddy_id = *it;
-		BOOL have_name = gCacheName->getFullName(buddy_id, name);
+		LLAvatarName av_name;
+		bool have_name = LLAvatarNameCache::get(buddy_id, &av_name);
 
 		// If name has not been loaded yet we consider it as a match.
 		// When the name will be loaded the filter will be applied again(in refresh()).
 
-		if (have_name && !findInsensitive(name, mNameFilter))
+		if (have_name && !findInsensitive(av_name.mDisplayName, mNameFilter))
 		{
 			continue;
 		}
@@ -368,7 +376,7 @@ S32 LLAvatarList::notifyParent(const LLSD& info)
 void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
 {
 	LLAvatarListItem* item = new LLAvatarListItem();
-	item->setName(name);
+	// This sets the name as a side effect
 	item->setAvatarId(id, mSessionID, mIgnoreOnlineStatus);
 	item->setOnline(mIgnoreOnlineStatus ? true : is_online);
 	item->showLastInteractionTime(mShowLastInteractionTime);
@@ -534,11 +542,13 @@ void LLAvalineListItem::setName(const std::string& name)
 		std::string hidden_name = LLTrans::getString("AvalineCaller", args);
 
 		LL_DEBUGS("Avaline") << "Avaline caller: " << uuid << ", name: " << hidden_name << LL_ENDL;
-		LLAvatarListItem::setName(hidden_name);
+		LLAvatarListItem::setAvatarName(hidden_name);
+		LLAvatarListItem::setAvatarToolTip(hidden_name);
 	}
 	else
 	{
 		const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
-		LLAvatarListItem::setName(formatted_phone);
+		LLAvatarListItem::setAvatarName(formatted_phone);
+		LLAvatarListItem::setAvatarToolTip(formatted_phone);
 	}
 }
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index 83faa53c281a6f309899ca8902cfb3130160f1ce..48bc76828e8321485dd25aae6dc661c83e08ac7e 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -28,7 +28,6 @@
 #define LL_LLAVATARLIST_H
 
 #include "llflatlistview.h"
-
 #include "llavatarlistitem.h"
 
 class LLTimer;
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index 341913edf7b80723677976545d18e01a94c7d011..51444569c149ae74f357e1794e3206138779ca0e 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -35,6 +35,7 @@
 #include "lltextutil.h"
 
 #include "llagent.h"
+#include "llavatarnamecache.h"
 #include "llavatariconctrl.h"
 #include "lloutputmonitorctrl.h"
 
@@ -161,11 +162,16 @@ void LLAvatarListItem::setOnline(bool online)
 	setState(online ? IS_ONLINE : IS_OFFLINE);
 }
 
-void LLAvatarListItem::setName(const std::string& name)
+void LLAvatarListItem::setAvatarName(const std::string& name)
 {
 	setNameInternal(name, mHighlihtSubstring);
 }
 
+void LLAvatarListItem::setAvatarToolTip(const std::string& tooltip)
+{
+	mAvatarName->setToolTip(tooltip);
+}
+
 void LLAvatarListItem::setHighlight(const std::string& highlight)
 {
 	setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);
@@ -224,7 +230,8 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, const LLUUID& session_id, b
 		mAvatarIcon->setValue(id);
 
 		// Set avatar name.
-		gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
+		LLAvatarNameCache::get(id,
+			boost::bind(&LLAvatarListItem::onAvatarNameCache, this, _2));
 	}
 }
 
@@ -317,23 +324,27 @@ const LLUUID& LLAvatarListItem::getAvatarId() const
 	return mAvatarId;
 }
 
-const std::string LLAvatarListItem::getAvatarName() const
+std::string LLAvatarListItem::getAvatarName() const
 {
 	return mAvatarName->getValue();
 }
 
+std::string LLAvatarListItem::getAvatarToolTip() const
+{
+	return mAvatarName->getToolTip();
+}
+
 //== PRIVATE SECITON ==========================================================
 
 void LLAvatarListItem::setNameInternal(const std::string& name, const std::string& highlight)
 {
 	LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle, name, highlight);
-	mAvatarName->setToolTip(name);
 }
 
-void LLAvatarListItem::onNameCache(const std::string& first_name, const std::string& last_name)
+void LLAvatarListItem::onAvatarNameCache(const LLAvatarName& av_name)
 {
-	std::string name = first_name + " " + last_name;
-	setName(name);
+	setAvatarName(av_name.mDisplayName);
+	setAvatarToolTip(av_name.mUsername);
 
 	//requesting the list to resort
 	notifyParent(LLSD().with("sort", LLSD()));
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index e252e69ea9b614852d87c55aed039281808e6d2d..7bba6fdbd015f61da222d63cb4478ab7db2ba67f 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -36,6 +36,7 @@
 #include "llcallingcard.h" // for LLFriendObserver
 
 class LLAvatarIconCtrl;
+class LLAvatarName;
 
 class LLAvatarListItem : public LLPanel, public LLFriendObserver
 {
@@ -85,7 +86,8 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 	virtual void changed(U32 mask); // from LLFriendObserver
 
 	void setOnline(bool online);
-	void setName(const std::string& name);
+	void setAvatarName(const std::string& name);
+	void setAvatarToolTip(const std::string& tooltip);
 	void setHighlight(const std::string& highlight);
 	void setState(EItemState item_style);
 	void setAvatarId(const LLUUID& id, const LLUUID& session_id, bool ignore_status_changes = false, bool is_resident = true);
@@ -98,7 +100,8 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 	void setAvatarIconVisible(bool visible);
 	
 	const LLUUID& getAvatarId() const;
-	const std::string getAvatarName() const;
+	std::string getAvatarName() const;
+	std::string getAvatarToolTip() const;
 
 	void onInfoBtnClick();
 	void onProfileBtnClick();
@@ -139,7 +142,7 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 	} EAvatarListItemChildIndex;
 
 	void setNameInternal(const std::string& name, const std::string& highlight);
-	void onNameCache(const std::string& first_name, const std::string& last_name);
+	void onAvatarNameCache(const LLAvatarName& av_name);
 
 	std::string formatSeconds(U32 secs);
 
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index c78f73c3b88d1e41ab9a19201a7383a17ca27667..c0babc6851e9b929c21983850a4597db2e8efdc7 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -27,13 +27,14 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "llcallfloater.h"
+
 #include "llnotificationsutil.h"
 #include "lltrans.h"
 
-#include "llcallfloater.h"
-
 #include "llagent.h"
 #include "llagentdata.h" // for gAgentID
+#include "llavatarnamecache.h"
 #include "llavatariconctrl.h"
 #include "llavatarlist.h"
 #include "llbottomtray.h"
@@ -77,7 +78,8 @@ class LLNonAvatarCaller : public LLAvatarListItem
 	void setName(const std::string& name)
 	{
 		const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
-		LLAvatarListItem::setName(formatted_phone);
+		LLAvatarListItem::setAvatarName(formatted_phone);
+		LLAvatarListItem::setAvatarToolTip(formatted_phone);
 	}
 
 	void setSpeakerId(const LLUUID& id) { mSpeakingIndicator->setSpeakerId(id); }
@@ -368,9 +370,31 @@ void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
 	call_floater->connectToChannel(channel);
 }
 
+void LLCallFloater::onAvatarNameCache(const LLUUID& agent_id,
+									  const LLAvatarName& av_name)
+{
+	LLStringUtil::format_map_t args;
+	args["[NAME]"] = av_name.getCompleteName();
+	std::string title = getString("title_peer_2_peer", args);
+	setTitle(title);
+}
+
 void LLCallFloater::updateTitle()
 {
 	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+	if (mVoiceType == VC_PEER_TO_PEER)
+	{
+		LLUUID session_id = voice_channel->getSessionID();
+		LLIMModel::LLIMSession* im_session =
+			LLIMModel::getInstance()->findIMSession(session_id);
+		if (im_session)
+		{
+			LLAvatarNameCache::get(im_session->mOtherParticipantID,
+				boost::bind(&LLCallFloater::onAvatarNameCache,
+					this, _1, _2));
+			return;
+		}
+	}
 	std::string title;
 	switch (mVoiceType)
 	{
@@ -415,9 +439,10 @@ void LLCallFloater::initAgentData()
 	{
 		mAgentPanel->getChild<LLUICtrl>("user_icon")->setValue(gAgentID);
 
-		std::string name;
-		gCacheName->getFullName(gAgentID, name);
-		mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(name);
+		// Just use display name, because it's you
+		LLAvatarName av_name;
+		LLAvatarNameCache::get( gAgentID, &av_name );
+		mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(av_name.mDisplayName);
 
 		mSpeakingIndicator = mAgentPanel->getChild<LLOutputMonitorCtrl>("speaking_indicator");
 		mSpeakingIndicator->setSpeakerId(gAgentID);
@@ -438,7 +463,10 @@ void LLCallFloater::setModeratorMutedVoice(bool moderator_muted)
 void LLCallFloater::updateAgentModeratorState()
 {
 	std::string name;
-	gCacheName->getFullName(gAgentID, name);
+	// Just use display name, because it's you
+	LLAvatarName av_name;
+	LLAvatarNameCache::get(gAgentID, &av_name);
+	name = av_name.mDisplayName;
 
 	if(gAgent.isInGroup(mSpeakerManager->getSessionID()))
 	{
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 881f777b4826152be0c4a626ea1f50b953f83bcf..cb4d175eb9be42cb69214e6d40aa1226b7a0ed3d 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -34,6 +34,7 @@
 
 class LLAvatarList;
 class LLAvatarListItem;
+class LLAvatarName;
 class LLNonAvatarCaller;
 class LLOutputMonitorCtrl;
 class LLParticipantList;
@@ -116,6 +117,10 @@ class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipan
 	 */
 	void onAvatarListRefreshed();
 
+	/**
+	 * Updates window title with an avatar name
+	 */
+	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
 	
 	void updateTitle();
 	void initAgentData();
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index a664dbe53af4257e365e90eca06c75730d6780d3..0d55c4429af2e38700f3e567f8b24bc849a6ee14 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -37,6 +37,7 @@
 //#include <iterator>
 
 #include "indra_constants.h"
+#include "llavatarnamecache.h"
 #include "llcachename.h"
 #include "llstl.h"
 #include "lltimer.h"
@@ -44,6 +45,7 @@
 #include "message.h"
 
 #include "llagent.h"
+#include "llavatarnamecache.h"
 #include "llbutton.h"
 #include "llinventoryobserver.h"
 #include "llinventorymodel.h"
@@ -90,8 +92,10 @@ const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f;
 // static
 LLAvatarTracker LLAvatarTracker::sInstance;
 
-
-
+static void on_avatar_name_cache_notify(const LLUUID& agent_id,
+										const LLAvatarName& av_name,
+										bool online,
+										LLSD payload);
 
 ///----------------------------------------------------------------------------
 /// Class LLAvatarTracker
@@ -244,7 +248,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
 	using namespace std;
 
 	U32 new_buddy_count = 0;
-	std::string first,last;
+	std::string full_name;
 	LLUUID agent_id;
 	for(buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end(); ++itr)
 	{
@@ -254,7 +258,8 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
 		{
 			++new_buddy_count;
 			mBuddyInfo[agent_id] = (*itr).second;
-			gCacheName->getName(agent_id, first, last);
+			// IDEVO: is this necessary?  name is unused?
+			gCacheName->getFullName(agent_id, full_name);
 			addChangedMask(LLFriendObserver::ADD, agent_id);
 			lldebugs << "Added buddy " << agent_id
 					<< ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline")
@@ -627,12 +632,9 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
 			{
 				if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^  new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
 				{
-					std::string name;
 					LLSD args;
-					if(gCacheName->getFullName(agent_id, name))
-					{
-						args["NAME"] = name;
-					}
+					args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString();
+					
 					LLSD payload;
 					payload["from_id"] = agent_id;
 					if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights)
@@ -674,8 +676,6 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
 		{
 			tracking_id = mTrackingData->mAvatarID;
 		}
-		BOOL notify = FALSE;
-		LLSD args;
 		LLSD payload;
 		for(S32 i = 0; i < count; ++i)
 		{
@@ -685,17 +685,6 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
 			if(info)
 			{
 				setBuddyOnline(agent_id,online);
-				if(chat_notify)
-				{
-					std::string first, last;
-					if(gCacheName->getName(agent_id, first, last))
-					{
-						notify = TRUE;
-						args["FIRST"] = first;
-						args["LAST"] = last;
-					}
-
-				}
 			}
 			else
 			{
@@ -711,29 +700,12 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
 			// *TODO: get actual inventory id
 			gInventory.addChangedMask(LLInventoryObserver::CALLING_CARD, LLUUID::null);
 		}
-		if(notify)
+		if(chat_notify)
 		{
-			// Popup a notify box with online status of this agent
-			LLNotificationPtr notification;
-
-			if (online)
-			{
-				notification =
-					LLNotificationsUtil::add("FriendOnline",
-											 args,
-											 payload.with("respond_on_mousedown", TRUE),
-											 boost::bind(&LLAvatarActions::startIM, agent_id));
-			}
-			else
-			{
-				notification =
-					LLNotificationsUtil::add("FriendOffline", args, payload);
-			}
-
-			// If there's an open IM session with this agent, send a notification there too.
-			LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
-			std::string notify_msg = notification->getMessage();
-			LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
+			// Look up the name of this agent for the notification
+			LLAvatarNameCache::get(agent_id,
+				boost::bind(&on_avatar_name_cache_notify,
+					_1, _2, online, payload));
 		}
 
 		mModifyMask |= LLFriendObserver::ONLINE;
@@ -742,6 +714,37 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
 	}
 }
 
+static void on_avatar_name_cache_notify(const LLUUID& agent_id,
+										const LLAvatarName& av_name,
+										bool online,
+										LLSD payload)
+{
+	// Popup a notify box with online status of this agent
+	// Use display name only because this user is your friend
+	LLSD args;
+	args["NAME"] = av_name.mDisplayName;
+
+	LLNotificationPtr notification;
+	if (online)
+	{
+		notification =
+			LLNotificationsUtil::add("FriendOnline",
+									 args,
+									 payload.with("respond_on_mousedown", TRUE),
+									 boost::bind(&LLAvatarActions::startIM, agent_id));
+	}
+	else
+	{
+		notification =
+			LLNotificationsUtil::add("FriendOffline", args, payload);
+	}
+
+	// If there's an open IM session with this agent, send a notification there too.
+	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
+	std::string notify_msg = notification->getMessage();
+	LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
+}
+
 void LLAvatarTracker::formFriendship(const LLUUID& id)
 {
 	if(id.notNull())
@@ -862,10 +865,9 @@ bool LLCollectProxyBuddies::operator()(const LLUUID& buddy_id, LLRelationship* b
 
 bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
 {
-	gCacheName->getName(buddy_id, mFirst, mLast);
-	std::ostringstream fullname;
-	fullname << mFirst << " " << mLast;
-	buddy_map_t::value_type value(fullname.str(), buddy_id);
+	LLAvatarName av_name;
+	LLAvatarNameCache::get( buddy_id, &av_name);
+	buddy_map_t::value_type value(av_name.mDisplayName, buddy_id);
 	if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION))
 	{
 		mMappable.insert(value);
@@ -875,10 +877,8 @@ bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship
 
 bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
 {
-	gCacheName->getName(buddy_id, mFirst, mLast);
-	std::ostringstream fullname;
-	fullname << mFirst << " " << mLast;
-	buddy_map_t::value_type value(fullname.str(), buddy_id);
+	gCacheName->getFullName(buddy_id, mFullName);
+	buddy_map_t::value_type value(mFullName, buddy_id);
 	if(buddy->isOnline())
 	{
 		mOnline.insert(value);
@@ -888,10 +888,10 @@ bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship*
 
 bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
 {
-	gCacheName->getName(buddy_id, mFirst, mLast);
-	std::ostringstream fullname;
-	fullname << mFirst << " " << mLast;
-	buddy_map_t::value_type value(fullname.str(), buddy_id);
+	LLAvatarName av_name;
+	LLAvatarNameCache::get(buddy_id, &av_name);
+	mFullName = av_name.mDisplayName;
+	buddy_map_t::value_type value(mFullName, buddy_id);
 	if(buddy->isOnline())
 	{
 		mOnline.insert(value);
@@ -902,5 +902,3 @@ bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* bud
 	}
 	return true;
 }
-
-
diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h
index 617f8fe27b74381185915d68762c789ee687fa36..c6378151c50bd575e0abb312a0388fceeecff8b0 100644
--- a/indra/newview/llcallingcard.h
+++ b/indra/newview/llcallingcard.h
@@ -235,8 +235,7 @@ class LLCollectMappableBuddies : public LLRelationshipFunctor
 	virtual bool operator()(const LLUUID& buddy_id, LLRelationship* buddy);
 	typedef std::map<std::string, LLUUID, LLDictionaryLess> buddy_map_t;
 	buddy_map_t mMappable;
-	std::string mFirst;
-	std::string mLast;
+	std::string mFullName;
 };
 
 // collect dictionary sorted map of name -> agent_id for every online buddy
@@ -248,8 +247,7 @@ class LLCollectOnlineBuddies : public LLRelationshipFunctor
 	virtual bool operator()(const LLUUID& buddy_id, LLRelationship* buddy);
 	typedef std::map<std::string, LLUUID, LLDictionaryLess> buddy_map_t;
 	buddy_map_t mOnline;
-	std::string mFirst;
-	std::string mLast;
+	std::string mFullName;
 };
 
 // collect dictionary sorted map of name -> agent_id for every buddy,
@@ -263,8 +261,7 @@ class LLCollectAllBuddies : public LLRelationshipFunctor
 	typedef std::map<std::string, LLUUID, LLDictionaryLess> buddy_map_t;
 	buddy_map_t mOnline;
 	buddy_map_t mOffline;
-	std::string mFirst;
-	std::string mLast;
+	std::string mFullName;
 };
 
 #endif // LL_LLCALLINGCARD_H
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 1f67a659bd2a101bceef36f5c60729e31a86ab0e..a89897d1f997b664f57bb30d0296194038d652c9 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -26,10 +26,12 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "llchathistory.h"
+
+#include "llavatarnamecache.h"
 #include "llinstantmessage.h"
 
 #include "llimview.h"
-#include "llchathistory.h"
 #include "llcommandhandler.h"
 #include "llpanel.h"
 #include "lluictrlfactory.h"
@@ -98,6 +100,18 @@ LLObjectIMHandler gObjectIMHandler;
 class LLChatHistoryHeader: public LLPanel
 {
 public:
+	LLChatHistoryHeader()
+	:	LLPanel(),
+		mPopupMenuHandleAvatar(),
+		mPopupMenuHandleObject(),
+		mAvatarID(),
+		mSourceType(CHAT_SOURCE_UNKNOWN),
+		mFrom(),
+		mSessionID(),
+		mMinUserNameWidth(0),
+		mUserNameFont(NULL)
+	{}
+
 	static LLChatHistoryHeader* createInstance(const std::string& file_name)
 	{
 		LLChatHistoryHeader* pInstance = new LLChatHistoryHeader;
@@ -240,7 +254,6 @@ class LLChatHistoryHeader: public LLPanel
 		mAvatarID = chat.mFromID;
 		mSessionID = chat.mSessionID;
 		mSourceType = chat.mSourceType;
-		gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4));
 
 		//*TODO overly defensive thing, source type should be maintained out there
 		if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull())
@@ -248,22 +261,40 @@ class LLChatHistoryHeader: public LLPanel
 			mSourceType = CHAT_SOURCE_SYSTEM;
 		}
 
-		LLTextBox* userName = getChild<LLTextBox>("user_name");
+		mUserNameFont = style_params.font();
+		LLTextBox* user_name = getChild<LLTextBox>("user_name");
+		user_name->setReadOnlyColor(style_params.readonly_color());
+		user_name->setColor(style_params.color());
 
-		userName->setReadOnlyColor(style_params.readonly_color());
-		userName->setColor(style_params.color());
-		
-		userName->setValue(chat.mFromName);
-		mFrom = chat.mFromName;
-		if (chat.mFromName.empty() || CHAT_SOURCE_SYSTEM == mSourceType)
+		if (chat.mFromName.empty()
+			|| mSourceType == CHAT_SOURCE_SYSTEM
+			|| mAvatarID.isNull())
 		{
 			mFrom = LLTrans::getString("SECOND_LIFE");
-			userName->setValue(mFrom);
+			user_name->setValue(mFrom);
+			updateMinUserNameWidth();
+		}
+		else if (mSourceType == CHAT_SOURCE_AGENT
+				 && chat.mChatStyle != CHAT_STYLE_HISTORY)
+		{
+			// ...from a normal user, lookup the name and fill in later.
+			// *NOTE: Do not do this for chat history logs, otherwise the viewer
+			// will flood the People API with lookup requests on startup
+
+			// Start with blank so sample data from XUI XML doesn't
+			// flash on the screen
+			user_name->setValue( LLSD() );
+			LLAvatarNameCache::get(mAvatarID,
+				boost::bind(&LLChatHistoryHeader::onAvatarNameCache, this, _1, _2));
+		}
+		else {
+			// ...from an object, just use name as given
+			mFrom = chat.mFromName;
+			user_name->setValue(mFrom);
+			updateMinUserNameWidth();
 		}
 
 
-		mMinUserNameWidth = style_params.font()->getWidth(userName->getWText().c_str()) + PADDING;
-
 		setTimeField(chat);
 		
 		LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
@@ -317,12 +348,28 @@ class LLChatHistoryHeader: public LLPanel
 		LLPanel::draw();
 	}
 
-	void nameUpdatedCallback(const LLUUID& id,const std::string& first,const std::string& last,BOOL is_group)
+	void updateMinUserNameWidth()
 	{
-		if (id != mAvatarID)
-			return;
-		mFrom = first + " " + last;
+		if (mUserNameFont)
+		{
+			LLTextBox* user_name = getChild<LLTextBox>("user_name");
+			const LLWString& text = user_name->getWText();
+			mMinUserNameWidth = mUserNameFont->getWidth(text.c_str()) + PADDING;
+		}
 	}
+
+	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
+	{
+		mFrom = av_name.mDisplayName;
+
+		LLTextBox* user_name = getChild<LLTextBox>("user_name");
+		user_name->setValue( LLSD(av_name.mDisplayName ) );
+		user_name->setToolTip( av_name.mUsername );
+		setToolTip( av_name.mUsername );
+		// name might have changed, update width
+		updateMinUserNameWidth();
+	}
+
 protected:
 	static const S32 PADDING = 20;
 
@@ -449,6 +496,7 @@ class LLChatHistoryHeader: public LLPanel
 	LLUUID				mSessionID;
 
 	S32					mMinUserNameWidth;
+	const LLFontGL*		mUserNameFont;
 };
 
 LLUICtrl* LLChatHistoryHeader::sInfoCtrl = NULL;
diff --git a/indra/newview/lldateutil.cpp b/indra/newview/lldateutil.cpp
index e575e06c5a8551f6b7ae902cfea938fdf7321fab..fcc73a07bc639c915a1c74eb3170b054ac7f0bf8 100644
--- a/indra/newview/lldateutil.cpp
+++ b/indra/newview/lldateutil.cpp
@@ -166,3 +166,23 @@ std::string LLDateUtil::ageFromDate(const std::string& date_string)
 {
 	return ageFromDate(date_string, LLDate::now());
 }
+
+//std::string LLDateUtil::ageFromDateISO(const std::string& date_string,
+//									   const LLDate& now)
+//{
+//	S32 born_month, born_day, born_year;
+//	S32 matched = sscanf(date_string.c_str(), "%d-%d-%d",
+//			&born_year, &born_month, &born_day);
+//	if (matched != 3) return "???";
+//	date.fromYMDHMS(year, month, day);
+//	F64 secs_since_epoch = date.secondsSinceEpoch();
+//	// Correct for the fact that specified date is in Pacific time, == UTC - 8
+//	secs_since_epoch += 8.0 * 60.0 * 60.0;
+//	date.secondsSinceEpoch(secs_since_epoch);
+//	return ageFromDate(born_year, born_month, born_day, now);
+//}
+//
+//std::string LLDateUtil::ageFromDateISO(const std::string& date_string)
+//{
+//	return ageFromDateISO(date_string, LLDate::now());
+//}
diff --git a/indra/newview/lldateutil.h b/indra/newview/lldateutil.h
index 5b465367dc3379c3759be5046609fe4609115e04..2843a357c9a245efabc786c4003caedc6e344da0 100644
--- a/indra/newview/lldateutil.h
+++ b/indra/newview/lldateutil.h
@@ -61,6 +61,14 @@ namespace LLDateUtil
 
 	// Calls the above with LLDate::now()
 	std::string ageFromDate(const std::string& date_string);
+
+	// As above, for YYYY-MM-DD dates
+	//std::string ageFromDateISO(const std::string& date_string, const LLDate& now);
+
+	// Calls the above with LLDate::now()
+	//std::string ageFromDateISO(const std::string& date_string);
+
+	//std::string ageFromDate(S32 born_year, S32 born_month, S32 born_day, const LLDate& now);
 }
 
 #endif
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index 9cf9b69d3e986447eb691022e82429394aebc077..2cea41df0a20b1a482f4ab9c6a546eebc77deaa1 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -47,6 +47,7 @@ class LLCamera;
 class LLDrawPool;
 class LLDrawable;
 class LLFace;
+class LLFacePool;
 class LLSpatialGroup;
 class LLSpatialBridge;
 class LLSpatialPartition;
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 9391c761b72381ce727ca67a8e650637437a231c..dbe98eda83b7524cc0dce0b3fa82c91cf3684fb0 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -35,10 +35,14 @@
 #include "llimview.h"			// for gIMMgr
 #include "lltooldraganddrop.h"	// for LLToolDragAndDrop
 #include "llviewercontrol.h"
+#include "llviewerregion.h"		// getCapability()
 #include "llworld.h"
 
 // Linden libraries
+#include "llavatarnamecache.h"	// IDEVO
 #include "llbutton.h"
+#include "llcachename.h"
+#include "llhttpclient.h"		// IDEVO
 #include "lllineeditor.h"
 #include "llscrolllistctrl.h"
 #include "llscrolllistitem.h"
@@ -47,6 +51,11 @@
 #include "lluictrlfactory.h"
 #include "message.h"
 
+//#include "llsdserialize.h"
+
+//put it back as a member once the legacy path is out?
+static std::map<LLUUID, LLAvatarName> sAvatarNameMap;
+
 LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
 												   BOOL allow_multiple,
 												   BOOL closeOnSelect)
@@ -153,7 +162,7 @@ void LLFloaterAvatarPicker::onBtnFind()
 	find();
 }
 
-static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vector<std::string>& avatar_names, uuid_vec_t& avatar_ids)
+static void getSelectedAvatarData(const LLScrollListCtrl* from, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names)
 {
 	std::vector<LLScrollListItem*> items = from->getAllSelected();
 	for (std::vector<LLScrollListItem*>::iterator iter = items.begin(); iter != items.end(); ++iter)
@@ -161,8 +170,21 @@ static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vector<std:
 		LLScrollListItem* item = *iter;
 		if (item->getUUID().notNull())
 		{
-			avatar_names.push_back(item->getColumn(0)->getValue().asString());
 			avatar_ids.push_back(item->getUUID());
+
+			std::map<LLUUID, LLAvatarName>::iterator iter = sAvatarNameMap.find(item->getUUID());
+			if (iter != sAvatarNameMap.end())
+			{
+				avatar_names.push_back(iter->second);
+			}
+			else
+			{
+				// the only case where it isn't in the name map is friends
+				// but it should be in the name cache
+				LLAvatarName av_name;
+				LLAvatarNameCache::get(item->getUUID(), &av_name);
+				avatar_names.push_back(av_name);
+			}
 		}
 	}
 }
@@ -198,10 +220,10 @@ void LLFloaterAvatarPicker::onBtnSelect()
 
 		if(list)
 		{
-			std::vector<std::string>	avatar_names;
 			uuid_vec_t			avatar_ids;
-			getSelectedAvatarData(list, avatar_names, avatar_ids);
-			mSelectionCallback(avatar_names, avatar_ids);
+			std::vector<LLAvatarName>	avatar_names;
+			getSelectedAvatarData(list, avatar_ids, avatar_names);
+			mSelectionCallback(avatar_ids, avatar_names);
 		}
 	}
 	getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
@@ -251,15 +273,22 @@ void LLFloaterAvatarPicker::populateNearMe()
 		if(av == gAgent.getID()) continue;
 		LLSD element;
 		element["id"] = av; // value
-		std::string fullname;
-		if(!gCacheName->getFullName(av, fullname))
+		LLAvatarName av_name;
+
+		if (!LLAvatarNameCache::get(av, &av_name))
 		{
+			element["columns"][0]["column"] = "name";
 			element["columns"][0]["value"] = LLCacheName::getDefaultName();
 			all_loaded = FALSE;
 		}			
 		else
 		{
-			element["columns"][0]["value"] = fullname;
+			element["columns"][0]["column"] = "name";
+			element["columns"][0]["value"] = av_name.mDisplayName;
+			element["columns"][1]["column"] = "username";
+			element["columns"][1]["value"] = av_name.mUsername;
+
+			sAvatarNameMap[av] = av_name;
 		}
 		near_me_scroller->addElement(element);
 		empty = FALSE;
@@ -294,7 +323,6 @@ void LLFloaterAvatarPicker::populateFriend()
 	LLAvatarTracker::instance().applyFunctor(collector);
 	LLCollectAllBuddies::buddy_map_t::iterator it;
 	
-	
 	for(it = collector.mOnline.begin(); it!=collector.mOnline.end(); it++)
 	{
 		friends_scroller->addStringUUIDItem(it->first, it->second);
@@ -346,23 +374,81 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
 	return FALSE;
 }
 
+class LLAvatarPickerResponder : public LLHTTPClient::Responder
+{
+public:
+	LLUUID mQueryID;
+
+	LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { }
+
+	/*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		//std::ostringstream ss;
+		//LLSDSerialize::toPrettyXML(content, ss);
+		//llinfos << ss.str() << llendl;
+
+		// in case of invalid characters, the avatar picker returns a 400
+		// just set it to process so it displays 'not found'
+		if (isGoodStatus(status) || status == 400)
+		{
+			LLFloaterAvatarPicker* floater =
+				LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker");
+			if (floater)
+			{
+				floater->processResponse(mQueryID, content);
+			}
+		}
+		else
+		{
+			llinfos << "avatar picker failed " << status
+					<< " reason " << reason << llendl;
+			
+		}
+	}
+};
+
 void LLFloaterAvatarPicker::find()
 {
+	//clear our stored LLAvatarNames
+	sAvatarNameMap.clear();
+
 	std::string text = getChild<LLUICtrl>("Edit")->getValue().asString();
 
 	mQueryID.generate();
 
-	LLMessageSystem* msg = gMessageSystem;
-
-	msg->newMessage("AvatarPickerRequest");
-	msg->nextBlock("AgentData");
-	msg->addUUID("AgentID", gAgent.getID());
-	msg->addUUID("SessionID", gAgent.getSessionID());
-	msg->addUUID("QueryID", mQueryID);	// not used right now
-	msg->nextBlock("Data");
-	msg->addString("Name", text);
+	std::string url;
+	url.reserve(128); // avoid a memory allocation or two
 
-	gAgent.sendReliableMessage();
+	LLViewerRegion* region = gAgent.getRegion();
+	url = region->getCapability("AvatarPickerSearch");
+	// Prefer use of capabilities to search on both SLID and display name
+	// but allow display name search to be manually turned off for test
+	if (!url.empty()
+		&& LLAvatarNameCache::useDisplayNames())
+	{
+		// capability urls don't end in '/', but we need one to parse
+		// query parameters correctly
+		if (url.size() > 0 && url[url.size()-1] != '/')
+		{
+			url += "/";
+		}
+		url += "?page_size=100&names=";
+		url += LLURI::escape(text);
+		llinfos << "avatar picker " << url << llendl;
+		LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID));
+	}
+	else
+	{
+		LLMessageSystem* msg = gMessageSystem;
+		msg->newMessage("AvatarPickerRequest");
+		msg->nextBlock("AgentData");
+		msg->addUUID("AgentID", gAgent.getID());
+		msg->addUUID("SessionID", gAgent.getSessionID());
+		msg->addUUID("QueryID", mQueryID);	// not used right now
+		msg->nextBlock("Data");
+		msg->addString("Name", text);
+		gAgent.sendReliableMessage();
+	}
 
 	getChild<LLScrollListCtrl>("SearchResults")->deleteAllItems();
 	getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("searching"));
@@ -503,12 +589,21 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
 		}
 		else
 		{
-			avatar_name = first_name + " " + last_name;
+			avatar_name = LLCacheName::buildFullName(first_name, last_name);
 			search_results->setEnabled(TRUE);
 			found_one = TRUE;
+
+			LLAvatarName av_name;
+			av_name.mLegacyFirstName = first_name;
+			av_name.mLegacyLastName = last_name;
+			av_name.mDisplayName = avatar_name;
+			const LLUUID& agent_id = avatar_id;
+			sAvatarNameMap[agent_id] = av_name;
+
 		}
 		LLSD element;
 		element["id"] = avatar_id; // value
+		element["columns"][0]["column"] = "name";
 		element["columns"][0]["value"] = avatar_name;
 		search_results->addElement(element);
 	}
@@ -522,10 +617,61 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
 	}
 }
 
+void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD& content)
+{
+	// Check for out-of-date query
+	if (query_id != mQueryID) return;
+
+	LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("SearchResults");
+
+	LLSD agents = content["agents"];
+	if (agents.size() == 0)
+	{
+		LLStringUtil::format_map_t map;
+		map["[TEXT]"] = childGetText("Edit");
+		LLSD item;
+		item["id"] = LLUUID::null;
+		item["columns"][0]["column"] = "name";
+		item["columns"][0]["value"] = getString("not_found", map);
+		search_results->addElement(item);
+		search_results->setEnabled(false);
+		getChildView("ok_btn")->setEnabled(false);
+		return;
+	}
+
+	// clear "Searching" label on first results
+	search_results->deleteAllItems();
+
+	LLSD item;
+	LLSD::array_const_iterator it = agents.beginArray();
+	for ( ; it != agents.endArray(); ++it)
+	{
+		const LLSD& row = *it;
+		item["id"] = row["id"];
+		LLSD& columns = item["columns"];
+		columns[0]["column"] = "name";
+		columns[0]["value"] = row["display_name"];
+		columns[1]["column"] = "username";
+		columns[1]["value"] = row["username"];
+		search_results->addElement(item);
+
+		// add the avatar name to our list
+		LLAvatarName avatar_name;
+		avatar_name.fromLLSD(row);
+		sAvatarNameMap[row["id"].asUUID()] = avatar_name;
+	}
+
+	getChildView("ok_btn")->setEnabled(true);
+	search_results->setEnabled(true);
+	search_results->selectFirstItem();
+	onList();
+	search_results->setFocus(TRUE);
+}
+
 //static
 void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data)
 {
-	getChildView("Find")->setEnabled(caller->getText().size() >= 3);
+	getChildView("Find")->setEnabled(caller->getText().size() > 0);
 }
 
 // virtual
@@ -583,8 +729,8 @@ bool LLFloaterAvatarPicker::isSelectBtnEnabled()
 		if(list)
 		{
 			uuid_vec_t avatar_ids;
-			std::vector<std::string> avatar_names;
-			getSelectedAvatarData(list, avatar_names, avatar_ids);
+			std::vector<LLAvatarName> avatar_names;
+			getSelectedAvatarData(list, avatar_ids, avatar_names);
 			return mOkButtonValidateSignal(avatar_ids);
 		}
 	}
diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h
index b476e898e9e29eebee108807a24c9b60723ea398..96c039443ab222454621025c6a99419232cd0d5c 100644
--- a/indra/newview/llfloateravatarpicker.h
+++ b/indra/newview/llfloateravatarpicker.h
@@ -31,6 +31,7 @@
 
 #include <vector>
 
+class LLAvatarName;
 class LLScrollListCtrl;
 
 class LLFloaterAvatarPicker : public LLFloater
@@ -40,7 +41,7 @@ class LLFloaterAvatarPicker : public LLFloater
 	typedef validate_signal_t::slot_type validate_callback_t;
 
 	// The callback function will be called with an avatar name and UUID.
-	typedef boost::function<void (const std::vector<std::string>&, const uuid_vec_t&)> select_callback_t;
+	typedef boost::function<void (const uuid_vec_t&, const std::vector<LLAvatarName>&)> select_callback_t;
 	// Call this to select an avatar.	
 	static LLFloaterAvatarPicker* show(select_callback_t callback, 
 									   BOOL allow_multiple = FALSE,
@@ -54,6 +55,7 @@ class LLFloaterAvatarPicker : public LLFloater
 	void setOkBtnEnableCb(validate_callback_t cb);
 
 	static void processAvatarPickerReply(class LLMessageSystem* msg, void**);
+	void processResponse(const LLUUID& query_id, const LLSD& content);
 
 	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
 						   BOOL drop, EDragAndDropType cargo_type,
diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp
index a6613968fb3192a5ab971e37b4e22c97cae418be..121c8cbe0f9d9852d2523e3b59205f46a35bcbd9 100644
--- a/indra/newview/llfloateravatartextures.cpp
+++ b/indra/newview/llfloateravatartextures.cpp
@@ -27,6 +27,9 @@
 #include "llviewerprecompiledheaders.h"
 #include "llfloateravatartextures.h"
 
+// library headers
+#include "llavatarnamecache.h"
+
 #include "llagent.h"
 #include "llagentwearables.h"
 #include "lltexturectrl.h"
@@ -132,10 +135,10 @@ void LLFloaterAvatarTextures::refresh()
 		LLVOAvatar *avatarp = find_avatar(mID);
 		if (avatarp)
 		{
-			std::string fullname;
-			if (gCacheName->getFullName(avatarp->getID(), fullname))
+			LLAvatarName av_name;
+			if (LLAvatarNameCache::get(avatarp->getID(), &av_name))
 			{
-				setTitle(mTitle + ": " + fullname);
+				setTitle(mTitle + ": " + av_name.getCompleteName());
 			}
 			for (U32 i=0; i < TEX_NUM_INDICES; i++)
 			{
diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp
index af98453c3cdeffd922e9cabf5374b4d8f13c91e3..cb79bd890a845f5a609fe1af4c79ca796c8ca52d 100644
--- a/indra/newview/llfloaterbump.cpp
+++ b/indra/newview/llfloaterbump.cpp
@@ -83,7 +83,7 @@ void LLFloaterBump::onOpen(const LLSD& key)
 
 void LLFloaterBump::add(LLScrollListCtrl* list, LLMeanCollisionData* mcd)
 {
-	if (mcd->mFirstName.empty() || list->getItemCount() >= 20)
+	if (mcd->mFullName.empty() || list->getItemCount() >= 20)
 	{
 		return;
 	}
@@ -121,8 +121,7 @@ void LLFloaterBump::add(LLScrollListCtrl* list, LLMeanCollisionData* mcd)
 	// All above action strings are in XML file
 	LLUIString text = getString(action);
 	text.setArg("[TIME]", timeStr);
-	text.setArg("[FIRST]", mcd->mFirstName);
-	text.setArg("[LAST]", mcd->mLastName);
+	text.setArg("[NAME]", mcd->mFullName);
 
 	LLSD row;
 	row["id"] = mcd->mPerp;
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index a5c62495fe3aa1e412ff580a049cd7b66d45bc1e..1a5dd3f86df36da6a0f8264b25642098528846df 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -180,9 +180,8 @@ class LLFloaterBuyLandUI
 	void updateNames();
 	// Name cache callback
 	void updateGroupName(const LLUUID& id,
-						 const std::string& first_name,
-						 const std::string& last_name,
-						 BOOL is_group);
+						 const std::string& name,
+						 bool is_group);
 	
 	void refreshUI();
 	
@@ -820,28 +819,26 @@ void LLFloaterBuyLandUI::updateNames()
 	}
 	else if (parcelp->getIsGroupOwned())
 	{
-		gCacheName->get(parcelp->getGroupID(), TRUE,
+		gCacheName->getGroup(parcelp->getGroupID(),
 			boost::bind(&LLFloaterBuyLandUI::updateGroupName, this,
-				_1, _2, _3, _4));
+				_1, _2, _3));
 	}
 	else
 	{
-		mParcelSellerName =
-			LLSLURL("agent", parcelp->getOwnerID(), "inspect").getSLURLString();
+		mParcelSellerName = LLSLURL("agent", parcelp->getOwnerID(), "completename").getSLURLString();
 	}
 }
 
 void LLFloaterBuyLandUI::updateGroupName(const LLUUID& id,
-						 const std::string& first_name,
-						 const std::string& last_name,
-						 BOOL is_group)
+						 const std::string& name,
+						 bool is_group)
 {
 	LLParcel* parcelp = mParcel->getParcel();
 	if (parcelp
 		&& parcelp->getGroupID() == id)
 	{
 		// request is current
-		mParcelSellerName = first_name;
+		mParcelSellerName = name;
 	}
 }
 
diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp
index f95112a8ab15f00eb383bd638fff44f6076b5a17..279b410927f35b54177a7254415f85be558c3c9e 100644
--- a/indra/newview/llfloatergodtools.cpp
+++ b/indra/newview/llfloatergodtools.cpp
@@ -28,6 +28,7 @@
 
 #include "llfloatergodtools.h"
 
+#include "llavatarnamecache.h"
 #include "llcoord.h"
 #include "llfontgl.h"
 #include "llframetimer.h"
@@ -1145,11 +1146,11 @@ void LLPanelObjectTools::onClickSetBySelection(void* data)
 	panelp->getChild<LLUICtrl>("target_avatar_name")->setValue(name);
 }
 
-void LLPanelObjectTools::callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelObjectTools::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
 {
 	if (ids.empty() || names.empty()) return;
 	mTargetAvatar = ids[0];
-	getChild<LLUICtrl>("target_avatar_name")->setValue(names[0]);
+	getChild<LLUICtrl>("target_avatar_name")->setValue(names[0].getCompleteName());
 	refresh();
 }
 
diff --git a/indra/newview/llfloatergodtools.h b/indra/newview/llfloatergodtools.h
index 60fc95580fd99c9812dbf1f03ab79f3c118c59bb..1aa8b838fb70516acdcc5420e8f1424caa6a1663 100644
--- a/indra/newview/llfloatergodtools.h
+++ b/indra/newview/llfloatergodtools.h
@@ -35,6 +35,7 @@
 #include "llpanel.h"
 #include <vector>
 
+class LLAvatarName;
 class LLButton;
 class LLCheckBoxCtrl;
 class LLComboBox;
@@ -225,7 +226,7 @@ class LLPanelObjectTools
 	void onChangeAnything();
 	void onApplyChanges();
 	void onClickSet();
-	void callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids);
+	void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
 	void onClickDeletePublicOwnedBy();
 	void onClickDeleteAllScriptedOwnedBy();
 	void onClickDeleteAllOwnedBy();
diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp
index 8e7f7e083ce8249c62c7c8d12491792ed0e04e2f..3a95f4922d1e28dc846f9e7a0bee0e9f8fe69426 100644
--- a/indra/newview/llfloaterinspect.cpp
+++ b/indra/newview/llfloaterinspect.cpp
@@ -31,7 +31,7 @@
 #include "llfloaterreg.h"
 #include "llfloatertools.h"
 #include "llavataractions.h"
-#include "llcachename.h"
+#include "llavatarnamecache.h"
 #include "llscrolllistctrl.h"
 #include "llscrolllistitem.h"
 #include "llselectmgr.h"
@@ -206,8 +206,12 @@ void LLFloaterInspect::refresh()
 		substitution["datetime"] = (S32) timestamp;
 		LLStringUtil::format (timeStr, substitution);
 
-		gCacheName->getFullName(obj->mPermissions->getOwner(), owner_name);
-		gCacheName->getFullName(obj->mPermissions->getCreator(), creator_name);
+		LLAvatarName av_name;
+		LLAvatarNameCache::get(obj->mPermissions->getOwner(), &av_name);
+		owner_name = av_name.getCompleteName();
+		LLAvatarNameCache::get(obj->mPermissions->getCreator(), &av_name);
+		creator_name = av_name.getCompleteName();
+		
 		row["id"] = obj->getObject()->getID();
 		row["columns"][0]["column"] = "object_name";
 		row["columns"][0]["type"] = "text";
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 2f080ab334a9f039282e91f57a06ed7169231874..d32140ab2a2c8119c2faa5b6735a0c45489b8da8 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -31,7 +31,7 @@
 
 #include "llfloaterland.h"
 
-#include "llcachename.h"
+#include "llavatarnamecache.h"
 #include "llfocusmgr.h"
 #include "llnotificationsutil.h"
 #include "llparcel.h"
@@ -1377,10 +1377,7 @@ bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, co
 			}
 			else
 			{
-				std::string first, last;
-				gCacheName->getName(owner_id, first, last);
-				args["FIRST"] = first;
-				args["LAST"] = last;
+				args["NAME"] = LLSLURL("agent", owner_id, "completename").getSLURLString();
 				LLNotificationsUtil::add("OtherObjectsReturned", args);
 			}
 			send_return_objects_message(parcel->getLocalID(), RT_OWNER);
@@ -1598,9 +1595,9 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo
 		}
 
 		// Placeholder for name.
-		std::string name;
-		gCacheName->getFullName(owner_id, name);		
-		item_params.columns.add().value(name).font(FONT).column("name");
+		LLAvatarName av_name;
+		LLAvatarNameCache::get(owner_id, &av_name);
+		item_params.columns.add().value(av_name.getCompleteName()).font(FONT).column("name");
 
 		object_count_str = llformat("%d", object_count);
 		item_params.columns.add().value(object_count_str).font(FONT).column("count");
@@ -1709,9 +1706,7 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata)
 	}
 	else
 	{
-		std::string name;
-		gCacheName->getFullName(owner_id, name);
-		args["NAME"] = name;
+		args["NAME"] = LLSLURL("agent", owner_id, "completename").getSLURLString();
 		LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2));
 	}
 }
@@ -1770,10 +1765,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
 		}
 		else
 		{
-			std::string name;
-			gCacheName->getFullName(owner_id, name);
-			args["NAME"] = name;
-
+			args["NAME"] = LLSLURL("agent", owner_id, "completename").getSLURLString();
 			LLNotificationsUtil::add("ReturnObjectsNotOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
 		}
 	}
@@ -2764,12 +2756,12 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata)
 
 void LLPanelLandAccess::onClickAddAccess()
 {
-	gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1,_2)) );
+	gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1)) );
 }
 
-void LLPanelLandAccess::callbackAvatarCBAccess(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelLandAccess::callbackAvatarCBAccess(const uuid_vec_t& ids)
 {
-	if (!names.empty() && !ids.empty())
+	if (!ids.empty())
 	{
 		LLUUID id = ids[0];
 		LLParcel* parcel = mParcel->getParcel();
@@ -2808,13 +2800,13 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data)
 // static
 void LLPanelLandAccess::onClickAddBanned()
 {
-	gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1,_2)));
+	gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1)));
 }
 
 // static
-void LLPanelLandAccess::callbackAvatarCBBanned(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelLandAccess::callbackAvatarCBBanned(const uuid_vec_t& ids)
 {
-	if (!names.empty() && !ids.empty())
+	if (!ids.empty())
 	{
 		LLUUID id = ids[0];
 		LLParcel* parcel = mParcel->getParcel();
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 309e0ee4e15fe65e9b84d0e23536d672609b14e8..a096fb64cdb2b39ebc890f16bc9bfcb98f58edb8 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -372,8 +372,8 @@ class LLPanelLandAccess
 	
 	void onClickAddAccess();
 	void onClickAddBanned();
-	void callbackAvatarCBBanned(const std::vector<std::string>& names, const uuid_vec_t& ids);
-	void callbackAvatarCBAccess(const std::vector<std::string>& names, const uuid_vec_t& ids);
+	void callbackAvatarCBBanned(const uuid_vec_t& ids);
+	void callbackAvatarCBAccess(const uuid_vec_t& ids);
 
 protected:
 	LLNameListCtrl*		mListAccess;
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
index 151a76285b2eb4a6eac512f044d4f6fc114d5bc2..b0009fd94f34b249569c6c4809c2bf8542ef189e 100644
--- a/indra/newview/llfloaterpay.cpp
+++ b/indra/newview/llfloaterpay.cpp
@@ -41,6 +41,7 @@
 #include "lllineeditor.h"
 #include "llmutelist.h"
 #include "llfloaterreporter.h"
+#include "llslurl.h"
 #include "llviewerobject.h"
 #include "llviewerobjectlist.h"
 #include "llviewerregion.h"
@@ -96,10 +97,6 @@ class LLFloaterPay : public LLFloater
 	static void onGive(void* data);
 	void give(S32 amount);
 	static void processPayPriceReply(LLMessageSystem* msg, void **userdata);
-	void onCacheOwnerName(const LLUUID& owner_id,
-						  const std::string& firstname,
-						  const std::string& lastname,
-						  BOOL is_group);
 	void finishPayUI(const LLUUID& target_id, BOOL is_group);
 
 protected:
@@ -152,7 +149,7 @@ BOOL LLFloaterPay::postBuild()
 	mCallbackData.push_back(info);
 
 	childSetAction("fastpay 1",&LLFloaterPay::onGive,info);
-	getChildView("fastpay 1")->setVisible( FALSE);
+	getChildView("fastpay 1")->setVisible(FALSE);
 
 	mQuickPayButton[i] = getChild<LLButton>("fastpay 1");
 	mQuickPayInfo[i] = info;
@@ -162,7 +159,7 @@ BOOL LLFloaterPay::postBuild()
 	mCallbackData.push_back(info);
 
 	childSetAction("fastpay 5",&LLFloaterPay::onGive,info);
-	getChildView("fastpay 5")->setVisible( FALSE);
+	getChildView("fastpay 5")->setVisible(FALSE);
 
 	mQuickPayButton[i] = getChild<LLButton>("fastpay 5");
 	mQuickPayInfo[i] = info;
@@ -172,7 +169,7 @@ BOOL LLFloaterPay::postBuild()
 	mCallbackData.push_back(info);
 
 	childSetAction("fastpay 10",&LLFloaterPay::onGive,info);
-	getChildView("fastpay 10")->setVisible( FALSE);
+	getChildView("fastpay 10")->setVisible(FALSE);
 
 	mQuickPayButton[i] = getChild<LLButton>("fastpay 10");
 	mQuickPayInfo[i] = info;
@@ -182,14 +179,14 @@ BOOL LLFloaterPay::postBuild()
 	mCallbackData.push_back(info);
 
 	childSetAction("fastpay 20",&LLFloaterPay::onGive,info);
-	getChildView("fastpay 20")->setVisible( FALSE);
+	getChildView("fastpay 20")->setVisible(FALSE);
 
 	mQuickPayButton[i] = getChild<LLButton>("fastpay 20");
 	mQuickPayInfo[i] = info;
 	++i;
 
 
-	getChildView("amount text")->setVisible( FALSE);	
+	getChildView("amount text")->setVisible(FALSE);	
 
 	std::string last_amount;
 	if(sLastAmount > 0)
@@ -197,7 +194,7 @@ BOOL LLFloaterPay::postBuild()
 		last_amount = llformat("%d", sLastAmount);
 	}
 
-	getChildView("amount")->setVisible( FALSE);
+	getChildView("amount")->setVisible(FALSE);
 
 	getChild<LLLineEditor>("amount")->setKeystrokeCallback(&LLFloaterPay::onKeystroke, this);
 	getChild<LLUICtrl>("amount")->setValue(last_amount);
@@ -208,7 +205,7 @@ BOOL LLFloaterPay::postBuild()
 
 	childSetAction("pay btn",&LLFloaterPay::onGive,info);
 	setDefaultBtn("pay btn");
-	getChildView("pay btn")->setVisible( FALSE);
+	getChildView("pay btn")->setVisible(FALSE);
 	getChildView("pay btn")->setEnabled((sLastAmount > 0));
 
 	childSetAction("cancel btn",&LLFloaterPay::onCancel,this);
@@ -243,25 +240,25 @@ void LLFloaterPay::processPayPriceReply(LLMessageSystem* msg, void **userdata)
 		
 		if (PAY_PRICE_HIDE == price)
 		{
-			self->getChildView("amount")->setVisible( FALSE);
-			self->getChildView("pay btn")->setVisible( FALSE);
-			self->getChildView("amount text")->setVisible( FALSE);
+			self->getChildView("amount")->setVisible(FALSE);
+			self->getChildView("pay btn")->setVisible(FALSE);
+			self->getChildView("amount text")->setVisible(FALSE);
 		}
 		else if (PAY_PRICE_DEFAULT == price)
 		{			
-			self->getChildView("amount")->setVisible( TRUE);
-			self->getChildView("pay btn")->setVisible( TRUE);
-			self->getChildView("amount text")->setVisible( TRUE);
+			self->getChildView("amount")->setVisible(TRUE);
+			self->getChildView("pay btn")->setVisible(TRUE);
+			self->getChildView("amount text")->setVisible(TRUE);
 		}
 		else
 		{
 			// PAY_PRICE_HIDE and PAY_PRICE_DEFAULT are negative values
 			// So we take the absolute value here after we have checked for those cases
 			
-			self->getChildView("amount")->setVisible( TRUE);
-			self->getChildView("pay btn")->setVisible( TRUE);
+			self->getChildView("amount")->setVisible(TRUE);
+			self->getChildView("pay btn")->setVisible(TRUE);
 			self->getChildView("pay btn")->setEnabled(TRUE);
-			self->getChildView("amount text")->setVisible( TRUE);
+			self->getChildView("amount text")->setVisible(TRUE);
 
 			self->getChild<LLUICtrl>("amount")->setValue(llformat("%d", llabs(price)));
 		}
@@ -409,9 +406,9 @@ void LLFloaterPay::payDirectly(money_callback callback,
 	floater->setCallback(callback);
 	floater->mObjectSelection = NULL;
 	
-	floater->getChildView("amount")->setVisible( TRUE);
-	floater->getChildView("pay btn")->setVisible( TRUE);
-	floater->getChildView("amount text")->setVisible( TRUE);
+	floater->getChildView("amount")->setVisible(TRUE);
+	floater->getChildView("pay btn")->setVisible(TRUE);
+	floater->getChildView("amount text")->setVisible(TRUE);
 
 	floater->getChildView("fastpay text")->setVisible(TRUE);
 	for(S32 i=0;i<MAX_PAY_BUTTONS;++i)
@@ -424,33 +421,26 @@ void LLFloaterPay::payDirectly(money_callback callback,
 	
 void LLFloaterPay::finishPayUI(const LLUUID& target_id, BOOL is_group)
 {
-	gCacheName->get(target_id, is_group, boost::bind(&LLFloaterPay::onCacheOwnerName, this, _1, _2, _3, _4));
-
-	// Make sure the amount field has focus
-
-	getChild<LLUICtrl>("amount")->setFocus( TRUE);
-	
-	LLLineEditor* amount = getChild<LLLineEditor>("amount");
-	amount->selectAll();
-	mTargetIsGroup = is_group;
-}
-
-void LLFloaterPay::onCacheOwnerName(const LLUUID& owner_id,
-									const std::string& firstname,
-									const std::string& lastname,
-									BOOL is_group)
-{
+	std::string slurl;
 	if (is_group)
 	{
 		setTitle(getString("payee_group"));
+		slurl = LLSLURL("group", target_id, "inspect").getSLURLString();
 	}
 	else
 	{
 		setTitle(getString("payee_resident"));
+		slurl = LLSLURL("agent", target_id, "inspect").getSLURLString();
 	}
+	getChild<LLTextBox>("payee_name")->setText(slurl);
 	
-	getChild<LLUICtrl>("payee_name")->setTextArg("[FIRST]", firstname);
-	getChild<LLUICtrl>("payee_name")->setTextArg("[LAST]", lastname);
+	// Make sure the amount field has focus
+
+	LLLineEditor* amount = getChild<LLLineEditor>("amount");
+	amount->setFocus(TRUE);
+	amount->selectAll();
+
+	mTargetIsGroup = is_group;
 }
 
 // static
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 3804a1b85840db0d9959b06eb1f4786ca830e5d3..460cab9ef3339661fe175dba34851d751eed9d4f 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -76,6 +76,7 @@
 #include "llvosky.h"
 
 // linden library includes
+#include "llavatarnamecache.h"
 #include "llerror.h"
 #include "llfontgl.h"
 #include "llrect.h"
@@ -179,6 +180,8 @@ void LLVoiceSetKeyDialog::onCancel(void* user_data)
 // if creating/destroying these is too slow, we'll need to create
 // a static member and update all our static callbacks
 
+void handleNameTagOptionChanged(const LLSD& newvalue);	
+void handleDisplayNamesOptionChanged(const LLSD& newvalue);	
 bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response);
 
 //bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater);
@@ -214,6 +217,18 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response
 	return false;
 }
 
+void handleNameTagOptionChanged(const LLSD& newvalue)
+{
+	LLVOAvatar::invalidateNameTags();
+}
+
+void handleDisplayNamesOptionChanged(const LLSD& newvalue)
+{
+	LLAvatarNameCache::setUseDisplayNames(newvalue.asBoolean());
+	LLVOAvatar::invalidateNameTags();
+}
+
+
 /*bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater)
 {
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -307,6 +322,10 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.BlockList",				boost::bind(&LLFloaterPreference::onClickBlockList, this));
 
 	sSkin = gSavedSettings.getString("SkinCurrent");
+	
+	gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged,  _2));	
+	gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged,  _2));	
+	gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged,  _2));
 }
 
 BOOL LLFloaterPreference::postBuild()
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 29ad0f3b9ca615ce685558fa141a337574311780..61ad2660f14cffbd7107cbfadc9dbd29652dd5fc 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -43,6 +43,7 @@
 
 #include "llagent.h"
 #include "llappviewer.h"
+#include "llavatarname.h"
 #include "llfloateravatarpicker.h"
 #include "llbutton.h" 
 #include "llcheckboxctrl.h"
@@ -600,13 +601,13 @@ void LLPanelRegionGeneralInfo::onClickKick()
 	// this depends on the grandparent view being a floater
 	// in order to set up floater dependency
 	LLFloater* parent_floater = gFloaterView->getParentFloater(this);
-	LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1,_2), FALSE, TRUE);
+	LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE);
 	parent_floater->addDependentFloater(child_floater);
 }
 
-void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelRegionGeneralInfo::onKickCommit(const uuid_vec_t& ids)
 {
-	if (names.empty() || ids.empty()) return;
+	if (ids.empty()) return;
 	if(ids[0].notNull())
 	{
 		strings_t strings;
@@ -842,11 +843,11 @@ void LLPanelRegionDebugInfo::onClickChooseAvatar()
 }
 
 
-void LLPanelRegionDebugInfo::callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelRegionDebugInfo::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
 {
 	if (ids.empty() || names.empty()) return;
 	mTargetAvatar = ids[0];
-	getChild<LLUICtrl>("target_avatar_name")->setValue(LLSD(names[0]));
+	getChild<LLUICtrl>("target_avatar_name")->setValue(LLSD(names[0].getCompleteName()));
 	refreshFromRegion( gAgent.getRegion() );
 }
 
@@ -1513,24 +1514,17 @@ void LLPanelEstateInfo::onClickKickUser()
 	// this depends on the grandparent view being a floater
 	// in order to set up floater dependency
 	LLFloater* parent_floater = gFloaterView->getParentFloater(this);
-	LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1, _2), FALSE, TRUE);
+	LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE);
 	parent_floater->addDependentFloater(child_floater);
 }
 
-void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelEstateInfo::onKickUserCommit(const uuid_vec_t& ids)
 {
-	if (names.empty() || ids.empty()) return;
+	if (ids.empty()) return;
 	
-	//check to make sure there is one valid user and id
-	if( (ids[0].isNull()) ||
-		(names[0].length() == 0) )
-	{
-		return;
-	}
-
 	//Bring up a confirmation dialog
 	LLSD args;
-	args["EVIL_USER"] = names[0];
+	args["EVIL_USER"] = LLSLURL("agent", ids[0], "completename").getSLURLString();
 	LLSD payload;
 	payload["agent_id"] = ids[0];
 	LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, this, _1, _2));
@@ -1696,12 +1690,12 @@ bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& res
 
 	LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]);
 	// avatar picker yes multi-select, yes close-on-select
-	LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, _2, (void*)change_info), TRUE, TRUE);
+	LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, (void*)change_info), TRUE, TRUE);
 	return false;
 }
 
 // static
-void LLPanelEstateInfo::accessAddCore3(const std::vector<std::string>& names, const uuid_vec_t& ids, void* data)
+void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, void* data)
 {
 	LLEstateAccessChangeInfo* change_info = (LLEstateAccessChangeInfo*)data;
 	if (!change_info) return;
@@ -1957,8 +1951,15 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region)
 	getChildView("remove_allowed_avatar_btn")->setEnabled(god || owner || manager);
 	getChildView("add_allowed_group_btn")->setEnabled(god || owner || manager);
 	getChildView("remove_allowed_group_btn")->setEnabled(god || owner || manager);
-	getChildView("add_banned_avatar_btn")->setEnabled(god || owner || manager);
-	getChildView("remove_banned_avatar_btn")->setEnabled(god || owner || manager);
+
+	// Can't ban people from mainland, orientation islands, etc. because this
+	// creates much network traffic and server load.
+	// Disable their accounts in CSR tool instead.
+	bool linden_estate = (getEstateID() <= ESTATE_LAST_LINDEN);
+	bool enable_ban = (god || owner || manager) && !linden_estate;
+	getChildView("add_banned_avatar_btn")->setEnabled(enable_ban);
+	getChildView("remove_banned_avatar_btn")->setEnabled(enable_ban);
+
 	getChildView("message_estate_btn")->setEnabled(god || owner || manager);
 	getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager);
 
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 2393c74c4509243c6c0886a774397e1e90aacd63..c0758fa92d31efb39f990872eb54f6283eee4a4a 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -34,6 +34,7 @@
 #include "llhost.h"
 #include "llpanel.h"
 
+class LLAvatarName;
 class LLDispatcher;
 class LLLineEditor;
 class LLMessageSystem;
@@ -162,7 +163,7 @@ class LLPanelRegionGeneralInfo : public LLPanelRegionInfo
 protected:
 	virtual BOOL sendUpdate();
 	void onClickKick();
-	void onKickCommit(const std::vector<std::string>& names, const uuid_vec_t& ids);
+	void onKickCommit(const uuid_vec_t& ids);
 	static void onClickKickAll(void* userdata);
 	bool onKickAllCommit(const LLSD& notification, const LLSD& response);
 	static void onClickMessage(void* userdata);
@@ -187,7 +188,7 @@ class LLPanelRegionDebugInfo : public LLPanelRegionInfo
 	virtual BOOL sendUpdate();
 
 	void onClickChooseAvatar();
-	void callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids);
+	void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
 	static void onClickReturn(void *);
 	bool callbackReturn(const LLSD& notification, const LLSD& response);
 	static void onClickTopColliders(void*);
@@ -278,7 +279,7 @@ class LLPanelEstateInfo : public LLPanelRegionInfo
 	// Core methods for all above add/remove button clicks
 	static void accessAddCore(U32 operation_flag, const std::string& dialog_name);
 	static bool accessAddCore2(const LLSD& notification, const LLSD& response);
-	static void accessAddCore3(const std::vector<std::string>& names, const uuid_vec_t& ids, void* data);
+	static void accessAddCore3(const uuid_vec_t& ids, void* data);
 
 	static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name);
 	static bool accessRemoveCore2(const LLSD& notification, const LLSD& response);
@@ -290,7 +291,7 @@ class LLPanelEstateInfo : public LLPanelRegionInfo
 	// Send the actual EstateOwnerRequest "estateaccessdelta" message
 	static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id);
 
-	void onKickUserCommit(const std::vector<std::string>& names, const uuid_vec_t& ids);
+	void onKickUserCommit(const uuid_vec_t& ids);
 	static void onClickMessageEstate(void* data);
 	bool onMessageCommit(const LLSD& notification, const LLSD& response);
 	
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 97f192a70830089b93d2bb25d20e8e642af51696..469c8bdecfc1daa1e0adda03d557832ff182f44c 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -33,6 +33,8 @@
 
 // linden library includes
 #include "llassetstorage.h"
+#include "llavatarnamecache.h"
+#include "llcachename.h"
 #include "llfontgl.h"
 #include "llimagej2c.h"
 #include "llinventory.h"
@@ -176,9 +178,8 @@ BOOL LLFloaterReporter::postBuild()
 	childSetAction("cancel_btn", onClickCancel, this);
 	
 	// grab the user's name
-	std::string fullname;
-	LLAgentUI::buildFullname(fullname);
-	getChild<LLUICtrl>("reporter_field")->setValue(fullname);
+	std::string reporter = LLSLURL("agent", gAgent.getID(), "inspect").getSLURLString();
+	getChild<LLUICtrl>("reporter_field")->setValue(reporter);
 	
 	center();
 
@@ -261,22 +262,7 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
 	
 			if (objectp->isAvatar())
 			{
-				// we have the information we need
-				std::string object_owner;
-
-				LLNameValue* firstname = objectp->getNVPair("FirstName");
-				LLNameValue* lastname =  objectp->getNVPair("LastName");
-				if (firstname && lastname)
-				{
-					object_owner.append(firstname->getString());
-					object_owner.append(1, ' ');
-					object_owner.append(lastname->getString());
-				}
-				else
-				{
-					object_owner.append("Unknown");
-				}
-				setFromAvatar(mObjectID, object_owner);
+				setFromAvatarID(mObjectID);
 			}
 			else
 			{
@@ -303,11 +289,11 @@ void LLFloaterReporter::onClickSelectAbuser()
 	gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE ));
 }
 
-void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLFloaterReporter::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
 {
 	if (ids.empty() || names.empty()) return;
 
-	getChild<LLUICtrl>("abuser_name_edit")->setValue(names[0] );
+	getChild<LLUICtrl>("abuser_name_edit")->setValue(names[0].getCompleteName());
 
 	mAbuserID = ids[0];
 
@@ -315,18 +301,27 @@ void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names,
 
 }
 
-void LLFloaterReporter::setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name)
+void LLFloaterReporter::setFromAvatarID(const LLUUID& avatar_id)
 {
 	mAbuserID = mObjectID = avatar_id;
-	mOwnerName = avatar_name;
-
-	std::string avatar_link =
-	  LLSLURL("agent", mObjectID, "inspect").getSLURLString();
+	std::string avatar_link = LLSLURL("agent", mObjectID, "inspect").getSLURLString();
 	getChild<LLUICtrl>("owner_name")->setValue(avatar_link);
-	getChild<LLUICtrl>("object_name")->setValue(avatar_name);
-	getChild<LLUICtrl>("abuser_name_edit")->setValue(avatar_name);
+
+	LLAvatarNameCache::get(avatar_id, boost::bind(&LLFloaterReporter::onAvatarNameCache, this, _1, _2));
 }
 
+void LLFloaterReporter::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
+{
+	if (mObjectID == avatar_id)
+	{
+		mOwnerName = av_name.getCompleteName();
+		getChild<LLUICtrl>("object_name")->setValue(av_name.getCompleteName());
+		getChild<LLUICtrl>("object_name")->setToolTip(av_name.getCompleteName());
+		getChild<LLUICtrl>("abuser_name_edit")->setValue(av_name.getCompleteName());
+	}
+}
+
+
 // static
 void LLFloaterReporter::onClickSend(void *userdata)
 {
@@ -466,16 +461,15 @@ void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_
 {
 	LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
 
-	// grab the user's name
-	std::string fullname;
-	LLAgentUI::buildFullname(fullname);
-	f->getChild<LLUICtrl>("reporter_field")->setValue(fullname);
-
 	if (avatar_name.empty())
+	{
 		// Request info for this object
 		f->getObjectInfo(object_id);
+	}
 	else
-		f->setFromAvatar(object_id, avatar_name);
+	{
+		f->setFromAvatarID(object_id);
+	}
 
 	// Need to deselect on close
 	f->mDeselectOnClose = TRUE;
diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h
index 92e842d3180a5e74ffec85367ce18c4df931a802..cd98f7be57312b4b2b1de51e5e46424a10e64098 100644
--- a/indra/newview/llfloaterreporter.h
+++ b/indra/newview/llfloaterreporter.h
@@ -32,6 +32,7 @@
 #include "lluuid.h"
 #include "v3math.h"
 
+class LLAvatarName;
 class LLMessageSystem;
 class LLViewerTexture;
 class LLInventoryItem;
@@ -117,8 +118,9 @@ class LLFloaterReporter
 	void setPosBox(const LLVector3d &pos);
 	void enableControls(BOOL own_avatar);
 	void getObjectInfo(const LLUUID& object_id);
-	void callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids);
-	void setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name = LLStringUtil::null);
+	void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
+	void setFromAvatarID(const LLUUID& avatar_id);
+	void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name);
 
 private:
 	EReportType		mReportType;
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 571f26e09ff68b4389c6cce6db6c2aa5cb65fa47..ac88d0ad8350584459dc37b34d4566c73c4450e6 100644
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -28,6 +28,8 @@
 #include "llviewerprecompiledheaders.h"
 #include "llfloaterscriptlimits.h"
 
+// library includes
+#include "llavatarnamecache.h"
 #include "llsdutil.h"
 #include "llsdutil_math.h"
 #include "message.h"
@@ -289,7 +291,7 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
 		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
 		if(tab)
 		{
-			LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+		LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
 			if(panel_memory)
 			{
 				panel_memory->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
@@ -300,9 +302,9 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
 					btn->setEnabled(true);
 				}
 				
-				panel_memory->setRegionSummary(content);
-			}
-		}
+		panel_memory->setRegionSummary(content);
+	}
+}
 	}
 }
 
@@ -592,17 +594,24 @@ void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::stri
 // callback from the name cache with an owner name to add to the list
 void LLPanelScriptLimitsRegionMemory::onNameCache(
 						 const LLUUID& id,
-						 const std::string& first_name,
-						 const std::string& last_name)
+						 const std::string& full_name)
 {
-	std::string name = first_name + " " + last_name;
-
 	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");	
 	if(!list)
 	{
 		return;
 	}
 	
+	std::string name;
+	if (LLAvatarNameCache::useDisplayNames())
+	{
+		name = LLCacheName::buildUsername(full_name);
+	}
+	else
+	{
+		name = full_name;
+	}
+
 	std::vector<LLSD>::iterator id_itor;
 	for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
 	{
@@ -668,6 +677,9 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
 			std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
 			LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
 			LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID();
+			// This field may not be sent by all server versions, but it's OK if
+			// it uses the LLSD default of false
+			bool is_group_owned = content["parcels"][i]["objects"][j]["is_group_owned"].asBoolean();
 
 			F32 location_x = 0.0f;
 			F32 location_y = 0.0f;
@@ -693,15 +705,27 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
 			// ...and if not use the slightly more painful method of disovery:
 			else
 			{
-				BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf);
+				BOOL name_is_cached;
+				if (is_group_owned)
+				{
+					name_is_cached = gCacheName->getGroupName(owner_id, owner_buf);
+				}
+				else
+				{
+					name_is_cached = gCacheName->getFullName(owner_id, owner_buf);  // username
+					if (LLAvatarNameCache::useDisplayNames())
+					{
+						owner_buf = LLCacheName::buildUsername(owner_buf);
+					}
+				}
 				if(!name_is_cached)
 				{
 					if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end())
 					{
 						names_requested.push_back(owner_id);
-						gCacheName->get(owner_id, TRUE,
-						boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache,
-							this, _1, _2, _3));
+						gCacheName->get(owner_id, is_group_owned,  // username
+							boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache,
+							    this, _1, _2));
 					}
 				}
 			}
@@ -1303,7 +1327,7 @@ void LLPanelScriptLimitsAttachment::setAttachmentSummary(LLSD content)
 
 // static
 void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
-{	
+{
 	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
 	if(instance)
 	{
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
index 46e2e6f0e204702c29d13f561438119899665aa0..9bcfa5fe1426ad3aad34d9986306be6c9d3526c4 100644
--- a/indra/newview/llfloaterscriptlimits.h
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -164,10 +164,8 @@ class LLPanelScriptLimitsRegionMemory : public LLPanelScriptLimitsInfo, LLRemote
 	void returnObjects();
 
 private:
-
 	void onNameCache(const LLUUID& id,
-			 const std::string& first_name,
-			 const std::string& last_name);
+						 const std::string& name);
 
 	LLSD mContent;
 	LLUUID mParcelId;
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index 3d87904dbebbbd6b54b84de3c0b80caac8a0c815..8558a1277ce514d691fecc317c4e135eec595e9d 100644
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -27,6 +27,7 @@
 
 #include "llfloatersellland.h"
 
+#include "llavatarnamecache.h"
 #include "llfloateravatarpicker.h"
 #include "llfloaterreg.h"
 #include "llfloaterland.h"
@@ -41,6 +42,8 @@
 #include "lluictrlfactory.h"
 #include "llviewerwindow.h"
 
+class LLAvatarName;
+
 // defined in llfloaterland.cpp
 void send_parcel_select_objects(S32 parcel_local_id, U32 return_type,
 								uuid_list_t* return_ids = NULL);
@@ -89,7 +92,9 @@ class LLFloaterSellLandUI
 	bool onConfirmSale(const LLSD& notification, const LLSD& response);
 	static void doShowObjects(void *userdata);
 
-	void callbackAvatarPick(const std::vector<std::string>& names, const uuid_vec_t& ids);
+	void callbackAvatarPick(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
+
+	void onBuyerNameCache(const LLAvatarName& av_name);
 
 public:
 	virtual BOOL postBuild();
@@ -224,12 +229,17 @@ void LLFloaterSellLandUI::updateParcelInfo()
 
 	if(mSellToBuyer)
 	{
-		std::string name;
-		gCacheName->getFullName(mAuthorizedBuyer, name);
-		getChild<LLUICtrl>("sell_to_agent")->setValue(name);
+		LLAvatarNameCache::get(mAuthorizedBuyer, 
+			boost::bind(&LLFloaterSellLandUI::onBuyerNameCache, this, _2));
 	}
 }
 
+void LLFloaterSellLandUI::onBuyerNameCache(const LLAvatarName& av_name)
+{
+	getChild<LLUICtrl>("sell_to_agent")->setValue(av_name.getCompleteName());
+	getChild<LLUICtrl>("sell_to_agent")->setToolTip(av_name.mUsername);
+}
+
 void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
 {
 	static std::string badgeOK("badge_ok.j2c");
@@ -385,7 +395,7 @@ void LLFloaterSellLandUI::doSelectAgent()
 	addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE));
 }
 
-void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLFloaterSellLandUI::callbackAvatarPick(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
 {	
 	LLParcel* parcel = mParcelSelection->getParcel();
 
@@ -396,7 +406,7 @@ void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& nam
 
 	mAuthorizedBuyer = ids[0];
 
-	getChild<LLUICtrl>("sell_to_agent")->setValue(names[0]);
+	getChild<LLUICtrl>("sell_to_agent")->setValue(names[0].getCompleteName());
 
 	refreshUI();
 }
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index a984dd1d51783bffb75df19ae6a8f1e0a1a40739..862a44ca95a2f48d34a2d69bf52e7c4d00e538ea 100644
--- a/indra/newview/llfloatertopobjects.cpp
+++ b/indra/newview/llfloatertopobjects.cpp
@@ -28,7 +28,9 @@
 
 #include "llfloatertopobjects.h"
 
+// library includes
 #include "message.h"
+#include "llavatarnamecache.h"
 #include "llfontgl.h"
 
 #include "llagent.h"
@@ -190,37 +192,53 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
 		LLSD element;
 
 		element["id"] = task_id;
-		element["object_name"] = name_buf;
-		element["owner_name"] = owner_buf;
-		element["columns"][0]["column"] = "score";
-		element["columns"][0]["value"] = llformat("%0.3f", score);
-		element["columns"][0]["font"] = "SANSSERIF";
+
+		LLSD columns;
+		columns[0]["column"] = "score";
+		columns[0]["value"] = llformat("%0.3f", score);
+		columns[0]["font"] = "SANSSERIF";
+		
+		columns[1]["column"] = "name";
+		columns[1]["value"] = name_buf;
+		columns[1]["font"] = "SANSSERIF";
+		
+		// Owner names can have trailing spaces sent from server
+		LLStringUtil::trim(owner_buf);
 		
-		element["columns"][1]["column"] = "name";
-		element["columns"][1]["value"] = name_buf;
-		element["columns"][1]["font"] = "SANSSERIF";
-		element["columns"][2]["column"] = "owner";
-		element["columns"][2]["value"] = owner_buf;
-		element["columns"][2]["font"] = "SANSSERIF";
-		element["columns"][3]["column"] = "location";
-		element["columns"][3]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z);
-		element["columns"][3]["font"] = "SANSSERIF";
-		element["columns"][4]["column"] = "time";
-		element["columns"][4]["value"] = formatted_time((time_t)time_stamp);
-		element["columns"][4]["font"] = "SANSSERIF";
+		if (LLAvatarNameCache::useDisplayNames())
+		{
+			// ...convert hard-coded name from server to a username
+			// *TODO: Send owner_id from server and look up display name
+			owner_buf = LLCacheName::buildUsername(owner_buf);
+		}
+		else
+		{
+			// ...just strip out legacy "Resident" name
+			owner_buf = LLCacheName::cleanFullName(owner_buf);
+		}
+		columns[2]["column"] = "owner";
+		columns[2]["value"] = owner_buf;
+		columns[2]["font"] = "SANSSERIF";
+
+		columns[3]["column"] = "location";
+		columns[3]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z);
+		columns[3]["font"] = "SANSSERIF";
+		columns[4]["column"] = "time";
+		columns[4]["value"] = formatted_time((time_t)time_stamp);
+		columns[4]["font"] = "SANSSERIF";
 
 		if (mCurrentMode == STAT_REPORT_TOP_SCRIPTS
 			&& have_extended_data)
 		{
-			element["columns"][5]["column"] = "mono_time";
-			element["columns"][5]["value"] = llformat("%0.3f", mono_score);
-			element["columns"][5]["font"] = "SANSSERIF";
+			columns[5]["column"] = "mono_time";
+			columns[5]["value"] = llformat("%0.3f", mono_score);
+			columns[5]["font"] = "SANSSERIF";
 
-			element["columns"][6]["column"] = "URLs";
-			element["columns"][6]["value"] = llformat("%d", public_urls);
-			element["columns"][6]["font"] = "SANSSERIF";
+			columns[6]["column"] = "URLs";
+			columns[6]["value"] = llformat("%d", public_urls);
+			columns[6]["font"] = "SANSSERIF";
 		}
-		
+		element["columns"] = columns;
 		list->addElement(element);
 		
 		mObjectListData.append(element);
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 980f9a34a6bb6e6ebf47795e25c040d4d651cffa..1dedc97316ac29ee2b743f346e0bfbc1c9c69bef 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -115,7 +115,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	const std::string getFilterSubString(BOOL trim = FALSE);
 	U32 getFilterObjectTypes() const;
 	PermissionMask getFilterPermissions() const;
-	// JAMESDEBUG use getFilter()->getShowFolderState();
+	// *NOTE: use getFilter()->getShowFolderState();
 	//LLInventoryFilter::EFolderShow getShowFolderState();
 	U32 getSortOrder() const;
 	BOOL isFilterModified();
diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h
index ade30d92661e60b926ccd72cb8e94e304a7ae183..3bfbf3611033942a69331389ca6673b9c431042e 100644
--- a/indra/newview/llfoldervieweventlistener.h
+++ b/indra/newview/llfoldervieweventlistener.h
@@ -25,7 +25,7 @@
 #ifndef LLFOLDERVIEWEVENTLISTENER_H
 #define LLFOLDERVIEWEVENTLISTENER_H
 
-#include "lldarray.h"	// JAMESDEBUG convert to std::vector
+#include "lldarray.h"	// *TODO: convert to std::vector
 #include "llfoldertype.h"
 #include "llfontgl.h"	// just for StyleFlags enum
 #include "llinventorytype.h"
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 11b644e3aa01116d48ddd3b373c76262af2b6b50..d599b7f53a22c872e05e6a6a875ba1729ca0feb1 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -51,7 +51,7 @@ enum EInventorySortGroup
 	SG_ITEM 
 };
 
-// JAMESDEBUG *TODO: do we really need one sort object per folder?
+// *TODO: do we really need one sort object per folder?
 // can we just have one of these per LLFolderView ?
 class LLInventorySort
 {
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 2f856abe8fbbea272506d11e501c48140f385b68..e9f1e3bc22d364f00bec70fabd5c0be72358c8e0 100644
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -26,13 +26,14 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "llfriendcard.h"
+
+#include "llavatarnamecache.h"
 #include "llinventory.h"
 #include "llinventoryfunctions.h"
 #include "llinventoryobserver.h"
 #include "lltrans.h"
 
-#include "llfriendcard.h"
-
 #include "llcallingcard.h" // for LLAvatarTracker
 #include "llviewerinventory.h"
 #include "llinventorymodel.h"
@@ -541,8 +542,9 @@ void LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)
 {
 
 	bool shouldBeAdded = true;
-	std::string name;
-	gCacheName->getFullName(avatarID, name);
+	LLAvatarName av_name;
+	LLAvatarNameCache::get(avatarID, &av_name);
+	const std::string& name = av_name.mUsername;
 
 	lldebugs << "Processing buddy name: " << name 
 		<< ", id: " << avatarID
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 83846f5b619d294de6b340150cf88d58d17e40a6..d43b3a5d6ec9e31aca62899383d5c03e4c03260d 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -48,6 +48,7 @@
 #include "lltoolmgr.h"
 #include "llselectmgr.h"
 #include "llhudmanager.h"
+#include "llhudtext.h"
 #include "llrendersphere.h"
 #include "llviewerobjectlist.h"
 #include "lltoolselectrect.h"
@@ -888,7 +889,7 @@ void LLViewerObjectList::renderObjectBeacons()
 			color = debug_beacon.mTextColor;
 			color.mV[3] *= 1.f;
 
-			hud_textp->setString(utf8str_to_wstring(debug_beacon.mString));
+			hud_textp->setString(debug_beacon.mString);
 			hud_textp->setColor(color);
 			hud_textp->setPositionAgent(debug_beacon.mPositionAgent);
 			debug_beacon.mHUDObject = hud_textp;
diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h
index 7712ebac1a8a3af3f03a9b3323d5e706d47d0f1c..8d7b8d4288b2b0091ef51690341cf17498a2973f 100644
--- a/indra/newview/llhudicon.h
+++ b/indra/newview/llhudicon.h
@@ -44,6 +44,7 @@
 // Renders a 2D icon billboard floating at the location specified.
 class LLDrawable;
 class LLViewerObject;
+class LLViewerTexture;
 
 class LLHUDIcon : public LLHUDObject
 {
diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..303f048dfc7692845b2f8a0548d8d14080f3399e
--- /dev/null
+++ b/indra/newview/llhudnametag.cpp
@@ -0,0 +1,1072 @@
+/** 
+ * @file llhudnametag.cpp
+ * @brief Name tags for avatars
+ * @author James Cook
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llhudnametag.h"
+
+#include "llrender.h"
+
+#include "llagent.h"
+#include "llviewercontrol.h"
+#include "llcriticaldamp.h"
+#include "lldrawable.h"
+#include "llfontgl.h"
+#include "llglheaders.h"
+#include "llhudrender.h"
+#include "llui.h"
+#include "llviewercamera.h"
+#include "llviewertexturelist.h"
+#include "llviewerobject.h"
+#include "llvovolume.h"
+#include "llviewerwindow.h"
+#include "llstatusbar.h"
+#include "llmenugl.h"
+#include "pipeline.h"
+#include <boost/tokenizer.hpp>
+
+
+const F32 SPRING_STRENGTH = 0.7f;
+const F32 RESTORATION_SPRING_TIME_CONSTANT = 0.1f;
+const F32 HORIZONTAL_PADDING = 16.f;
+const F32 VERTICAL_PADDING = 12.f;
+const F32 LINE_PADDING = 3.f;			// aka "leading"
+const F32 BUFFER_SIZE = 2.f;
+const F32 MIN_EDGE_OVERLAP = 3.f;
+const F32 HUD_TEXT_MAX_WIDTH = 190.f;
+const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f;
+const F32 RESIZE_TIME = 0.f;
+const S32 NUM_OVERLAP_ITERATIONS = 10;
+const F32 NEIGHBOR_FORCE_FRACTION = 1.f;
+const F32 POSITION_DAMPING_TC = 0.2f;
+const F32 MAX_STABLE_CAMERA_VELOCITY = 0.1f;
+const F32 LOD_0_SCREEN_COVERAGE = 0.15f;
+const F32 LOD_1_SCREEN_COVERAGE = 0.30f;
+const F32 LOD_2_SCREEN_COVERAGE = 0.40f;
+
+std::set<LLPointer<LLHUDNameTag> > LLHUDNameTag::sTextObjects;
+std::vector<LLPointer<LLHUDNameTag> > LLHUDNameTag::sVisibleTextObjects;
+BOOL LLHUDNameTag::sDisplayText = TRUE ;
+
+bool llhudnametag_further_away::operator()(const LLPointer<LLHUDNameTag>& lhs, const LLPointer<LLHUDNameTag>& rhs) const
+{
+	return lhs->getDistance() > rhs->getDistance();
+}
+
+
+LLHUDNameTag::LLHUDNameTag(const U8 type)
+:	LLHUDObject(type),
+	mDoFade(TRUE),
+	mFadeDistance(8.f),
+	mFadeRange(4.f),
+	mLastDistance(0.f),
+	mZCompare(TRUE),
+	mVisibleOffScreen(FALSE),
+	mOffscreen(FALSE),
+	mColor(1.f, 1.f, 1.f, 1.f),
+//	mScale(),
+	mWidth(0.f),
+	mHeight(0.f),
+	mFontp(LLFontGL::getFontSansSerifSmall()),
+	mBoldFontp(LLFontGL::getFontSansSerifBold()),
+	mSoftScreenRect(),
+	mPositionAgent(),
+	mPositionOffset(),
+	mMass(10.f),
+	mMaxLines(10),
+	mOffsetY(0),
+	mRadius(0.1f),
+	mTextSegments(),
+	mLabelSegments(),
+	mTextAlignment(ALIGN_TEXT_CENTER),
+	mVertAlignment(ALIGN_VERT_CENTER),
+	mLOD(0),
+	mHidden(FALSE)
+{
+	LLPointer<LLHUDNameTag> ptr(this);
+	sTextObjects.insert(ptr);
+}
+
+LLHUDNameTag::~LLHUDNameTag()
+{
+}
+
+
+BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render)
+{
+	if (!mVisible || mHidden)
+	{
+		return FALSE;
+	}
+
+	// don't pick text that isn't bound to a viewerobject
+	if (!mSourceObject || mSourceObject->mDrawable.isNull())
+	{
+		return FALSE;
+	}
+	
+	F32 alpha_factor = 1.f;
+	LLColor4 text_color = mColor;
+	if (mDoFade)
+	{
+		if (mLastDistance > mFadeDistance)
+		{
+			alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
+			text_color.mV[3] = text_color.mV[3]*alpha_factor;
+		}
+	}
+	if (text_color.mV[3] < 0.01f)
+	{
+		return FALSE;
+	}
+
+	mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
+
+	// scale screen size of borders down
+	//RN: for now, text on hud objects is never occluded
+
+	LLVector3 x_pixel_vec;
+	LLVector3 y_pixel_vec;
+	
+	LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+
+	LLVector3 width_vec = mWidth * x_pixel_vec;
+	LLVector3 height_vec = mHeight * y_pixel_vec;
+	
+	LLCoordGL screen_pos;
+	LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
+
+	LLVector2 screen_offset;
+	screen_offset = updateScreenPos(mPositionOffset);
+	
+	LLVector3 render_position = mPositionAgent  
+			+ (x_pixel_vec * screen_offset.mV[VX])
+			+ (y_pixel_vec * screen_offset.mV[VY]);
+
+
+	//if (mUseBubble)
+	{
+		LLVector3 bg_pos = render_position
+			+ (F32)mOffsetY * y_pixel_vec
+			- (width_vec / 2.f)
+			- (height_vec);
+		//LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
+
+		LLVector3 v[] = 
+		{
+			bg_pos,
+			bg_pos + width_vec,
+			bg_pos + width_vec + height_vec,
+			bg_pos + height_vec,
+		};
+
+		if (debug_render)
+		{
+			gGL.begin(LLRender::LINE_STRIP);
+			gGL.vertex3fv(v[0].mV);
+			gGL.vertex3fv(v[1].mV);
+			gGL.vertex3fv(v[2].mV);
+			gGL.vertex3fv(v[3].mV);
+			gGL.vertex3fv(v[0].mV);
+			gGL.vertex3fv(v[2].mV);
+			gGL.end();
+		}
+
+		LLVector3 dir = end-start;
+		F32 t = 0.f;
+
+		if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, NULL, NULL, &t, FALSE) ||
+			LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, NULL, NULL, &t, FALSE) )
+		{
+			if (t <= 1.f)
+			{
+				intersection = start + dir*t;
+				return TRUE;
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+void LLHUDNameTag::render()
+{
+	if (sDisplayText)
+	{
+		LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+		renderText(FALSE);
+	}
+}
+
+void LLHUDNameTag::renderForSelect()
+{
+	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+	renderText(TRUE);
+}
+
+void LLHUDNameTag::renderText(BOOL for_select)
+{
+	if (!mVisible || mHidden)
+	{
+		return;
+	}
+
+	// don't pick text that isn't bound to a viewerobject
+	if (for_select && 
+		(!mSourceObject || mSourceObject->mDrawable.isNull()))
+	{
+		return;
+	}
+	
+	if (for_select)
+	{
+		gGL.getTexUnit(0)->disable();
+	}
+	else
+	{
+		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+	}
+
+	LLGLState gls_blend(GL_BLEND, for_select ? FALSE : TRUE);
+	LLGLState gls_alpha(GL_ALPHA_TEST, for_select ? FALSE : TRUE);
+	
+	LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f);
+	F32 alpha_factor = 1.f;
+	LLColor4 text_color = mColor;
+	if (mDoFade)
+	{
+		if (mLastDistance > mFadeDistance)
+		{
+			alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
+			text_color.mV[3] = text_color.mV[3]*alpha_factor;
+		}
+	}
+	if (text_color.mV[3] < 0.01f)
+	{
+		return;
+	}
+	shadow_color.mV[3] = text_color.mV[3];
+
+	mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
+
+	// *TODO: cache this image
+	LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Rect");
+
+	// *TODO: make this a per-text setting
+	LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground");
+	bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
+
+	// maybe a no-op?
+	//const S32 border_height = 16;
+	//const S32 border_width = 16;
+	const S32 border_height = 8;
+	const S32 border_width = 8;
+
+	// *TODO move this into helper function
+	F32 border_scale = 1.f;
+
+	if (border_height * 2 > mHeight)
+	{
+		border_scale = (F32)mHeight / ((F32)border_height * 2.f);
+	}
+	if (border_width * 2 > mWidth)
+	{
+		border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f));
+	}
+
+	// scale screen size of borders down
+	//RN: for now, text on hud objects is never occluded
+
+	LLVector3 x_pixel_vec;
+	LLVector3 y_pixel_vec;
+	
+	LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+
+	LLVector2 border_scale_vec((F32)border_width / (F32)imagep->getTextureWidth(), (F32)border_height / (F32)imagep->getTextureHeight());
+	LLVector3 width_vec = mWidth * x_pixel_vec;
+	LLVector3 height_vec = mHeight * y_pixel_vec;
+	LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec;
+	LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec;
+
+	mRadius = (width_vec + height_vec).magVec() * 0.5f;
+
+	LLCoordGL screen_pos;
+	LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
+
+	LLVector2 screen_offset;
+//	if (!mUseBubble)
+//	{
+//		screen_offset = mPositionOffset;
+//	}
+//	else
+//	{
+		screen_offset = updateScreenPos(mPositionOffset);
+//	}
+
+	LLVector3 render_position = mPositionAgent  
+			+ (x_pixel_vec * screen_offset.mV[VX])
+			+ (y_pixel_vec * screen_offset.mV[VY]);
+
+//	if (mUseBubble)
+	{
+		LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+		LLUI::pushMatrix();
+		{
+			LLVector3 bg_pos = render_position
+				+ (F32)mOffsetY * y_pixel_vec
+				- (width_vec / 2.f)
+				- (height_vec);
+			LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
+
+			if (for_select)
+			{
+				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+				S32 name = mSourceObject->mGLName;
+				LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name);
+				gGL.color4ubv(coloru.mV);
+				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
+				LLUI::popMatrix();
+				return;
+			}
+			else
+			{
+				gGL.getTexUnit(0)->bind(imagep->getImage());
+				
+				gGL.color4fv(bg_color.mV);
+				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
+		
+				if ( mLabelSegments.size())
+				{
+					LLUI::pushMatrix();
+					{
+						gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
+						LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec;
+						LLVector3 label_offset = height_vec - label_height;
+						LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]);
+						gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height);
+					}
+					LLUI::popMatrix();
+				}
+			}
+
+			BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f;
+			BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f);
+
+			// draw line segments pointing to parent object
+			if (!mOffscreen && (outside_width || outside_height))
+			{
+				LLUI::pushMatrix();
+				{
+					gGL.color4fv(bg_color.mV);
+					LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec);
+					target_pos += (width_vec / 2.f);
+					target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero;
+					target_pos -= 3.f * x_pixel_vec;
+					target_pos -= 6.f * y_pixel_vec;
+					LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]);
+					gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec);	
+				}
+				LLUI::popMatrix();
+
+				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+				LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE);
+				
+				LLVector3 box_center_offset;
+				box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f);
+				LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]);
+				gGL.color4fv(bg_color.mV);
+				LLUI::setLineWidth(2.0);
+				gGL.begin(LLRender::LINES);
+				{
+					if (outside_width)
+					{
+						LLVector3 vert;
+						// draw line in x then y
+						if (mPositionOffset.mV[VX] < 0.f)
+						{
+							// start at right edge
+							vert = width_vec * 0.5f;
+							gGL.vertex3fv(vert.mV);
+						}
+						else
+						{
+							// start at left edge
+							vert = width_vec * -0.5f;
+							gGL.vertex3fv(vert.mV);
+						}
+						vert = -mPositionOffset.mV[VX] * x_pixel_vec;
+						gGL.vertex3fv(vert.mV);
+						gGL.vertex3fv(vert.mV);
+						vert -= mPositionOffset.mV[VY] * y_pixel_vec;
+						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
+						gGL.vertex3fv(vert.mV);
+					}
+					else
+					{
+						LLVector3 vert;
+						// draw line in y then x
+						if (mPositionOffset.mV[VY] < 0.f)
+						{
+							// start at top edge
+							vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
+							gGL.vertex3fv(vert.mV);
+						}
+						else
+						{
+							// start at bottom edge
+							vert = (height_vec * -0.5f)  - (mPositionOffset.mV[VX] * x_pixel_vec);
+							gGL.vertex3fv(vert.mV);
+						}
+						vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec;
+						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
+						gGL.vertex3fv(vert.mV);
+					}
+				}
+				gGL.end();
+				LLUI::setLineWidth(1.0);
+
+			}
+		}
+		LLUI::popMatrix();
+	}
+
+	F32 y_offset = (F32)mOffsetY;
+		
+	// Render label
+	{
+		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+		for(std::vector<LLHUDTextSegment>::iterator segment_iter = mLabelSegments.begin();
+			segment_iter != mLabelSegments.end(); ++segment_iter )
+		{
+			// Label segments use default font
+			const LLFontGL* fontp = (segment_iter->mStyle == LLFontGL::BOLD) ? mBoldFontp : mFontp;
+			y_offset -= fontp->getLineHeight();
+
+			F32 x_offset;
+			if (mTextAlignment == ALIGN_TEXT_CENTER)
+			{
+				x_offset = -0.5f*segment_iter->getWidth(fontp);
+			}
+			else // ALIGN_LEFT
+			{
+				x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f);
+			}
+
+			LLColor4 label_color(0.f, 0.f, 0.f, 1.f);
+			label_color.mV[VALPHA] = alpha_factor;
+			hud_render_text(segment_iter->getText(), render_position, *fontp, segment_iter->mStyle, LLFontGL::NO_SHADOW, x_offset, y_offset, label_color, FALSE);
+		}
+	}
+
+	// Render text
+	{
+		// -1 mMaxLines means unlimited lines.
+		S32 start_segment;
+		S32 max_lines = getMaxLines();
+
+		if (max_lines < 0) 
+		{
+			start_segment = 0;
+		}
+		else 
+		{
+			start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines);
+		}
+
+		for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment;
+			 segment_iter != mTextSegments.end(); ++segment_iter )
+		{
+			const LLFontGL* fontp = segment_iter->mFont;
+			y_offset -= fontp->getLineHeight();
+			y_offset -= LINE_PADDING;
+
+			U8 style = segment_iter->mStyle;
+			LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW;
+	
+			F32 x_offset;
+			if (mTextAlignment== ALIGN_TEXT_CENTER)
+			{
+				x_offset = -0.5f*segment_iter->getWidth(fontp);
+			}
+			else // ALIGN_LEFT
+			{
+				x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f);
+
+				// *HACK
+				x_offset += 1;
+			}
+
+			text_color = segment_iter->mColor;
+			text_color.mV[VALPHA] *= alpha_factor;
+
+			hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, FALSE);
+		}
+	}
+	/// Reset the default color to white.  The renderer expects this to be the default. 
+	gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
+	if (for_select)
+	{
+		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+	}
+}
+
+void LLHUDNameTag::setString(const std::string &text_utf8)
+{
+	mTextSegments.clear();
+	addLine(text_utf8, mColor);
+}
+
+void LLHUDNameTag::clearString()
+{
+	mTextSegments.clear();
+}
+
+
+void LLHUDNameTag::addLine(const std::string &text_utf8,
+						const LLColor4& color,
+						const LLFontGL::StyleFlags style,
+						const LLFontGL* font)
+{
+	LLWString wline = utf8str_to_wstring(text_utf8);
+	if (!wline.empty())
+	{
+		// use default font for segment if custom font not specified
+		if (!font)
+		{
+			font = mFontp;
+		}
+		typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
+		LLWString seps(utf8str_to_wstring("\r\n"));
+		boost::char_separator<llwchar> sep(seps.c_str());
+
+		tokenizer tokens(wline, sep);
+		tokenizer::iterator iter = tokens.begin();
+
+		while (iter != tokens.end())
+		{
+			U32 line_length = 0;
+			do	
+			{
+				F32 max_pixels = HUD_TEXT_MAX_WIDTH;
+				S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+				LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
+				mTextSegments.push_back(segment);
+				line_length += segment_length;
+			}
+			while (line_length != iter->size());
+			++iter;
+		}
+	}
+}
+
+void LLHUDNameTag::setLabel(const std::string &label_utf8)
+{
+	mLabelSegments.clear();
+	addLabel(label_utf8);
+}
+
+void LLHUDNameTag::addLabel(const std::string& label_utf8)
+{
+	LLWString wstr = utf8string_to_wstring(label_utf8);
+	if (!wstr.empty())
+	{
+		LLWString seps(utf8str_to_wstring("\r\n"));
+		LLWString empty;
+
+		typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
+		boost::char_separator<llwchar> sep(seps.c_str(), empty.c_str(), boost::keep_empty_tokens);
+
+		tokenizer tokens(wstr, sep);
+		tokenizer::iterator iter = tokens.begin();
+
+		while (iter != tokens.end())
+		{
+			U32 line_length = 0;
+			do	
+			{
+				S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), 
+					HUD_TEXT_MAX_WIDTH, wstr.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+				LLHUDTextSegment segment(iter->substr(line_length, segment_length), LLFontGL::NORMAL, mColor, mFontp);
+				mLabelSegments.push_back(segment);
+				line_length += segment_length;
+			}
+			while (line_length != iter->size());
+			++iter;
+		}
+	}
+}
+
+void LLHUDNameTag::setZCompare(const BOOL zcompare)
+{
+	mZCompare = zcompare;
+}
+
+void LLHUDNameTag::setFont(const LLFontGL* font)
+{
+	mFontp = font;
+}
+
+
+void LLHUDNameTag::setColor(const LLColor4 &color)
+{
+	mColor = color;
+	for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
+		 segment_iter != mTextSegments.end(); ++segment_iter )
+	{
+		segment_iter->mColor = color;
+	}
+}
+
+void LLHUDNameTag::setAlpha(F32 alpha)
+{
+	mColor.mV[VALPHA] = alpha;
+	for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
+		 segment_iter != mTextSegments.end(); ++segment_iter )
+	{
+		segment_iter->mColor.mV[VALPHA] = alpha;
+	}
+}
+
+
+void LLHUDNameTag::setDoFade(const BOOL do_fade)
+{
+	mDoFade = do_fade;
+}
+
+void LLHUDNameTag::updateVisibility()
+{
+	if (mSourceObject)
+	{
+		mSourceObject->updateText();
+	}
+	
+	mPositionAgent = gAgent.getPosAgentFromGlobal(mPositionGlobal);
+
+	if (!mSourceObject)
+	{
+		//llwarns << "LLHUDNameTag::updateScreenPos -- mSourceObject is NULL!" << llendl;
+		mVisible = TRUE;
+		sVisibleTextObjects.push_back(LLPointer<LLHUDNameTag> (this));
+		return;
+	}
+
+	// Not visible if parent object is dead
+	if (mSourceObject->isDead())
+	{
+		mVisible = FALSE;
+		return;
+	}
+
+	// push text towards camera by radius of object, but not past camera
+	LLVector3 vec_from_camera = mPositionAgent - LLViewerCamera::getInstance()->getOrigin();
+	LLVector3 dir_from_camera = vec_from_camera;
+	dir_from_camera.normVec();
+
+	if (dir_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= 0.f)
+	{ //text is behind camera, don't render
+		mVisible = FALSE;
+		return;
+	}
+		
+	if (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= LLViewerCamera::getInstance()->getNear() + 0.1f + mSourceObject->getVObjRadius())
+	{
+		mPositionAgent = LLViewerCamera::getInstance()->getOrigin() + vec_from_camera * ((LLViewerCamera::getInstance()->getNear() + 0.1f) / (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis()));
+	}
+	else
+	{
+		mPositionAgent -= dir_from_camera * mSourceObject->getVObjRadius();
+	}
+
+	mLastDistance = (mPositionAgent - LLViewerCamera::getInstance()->getOrigin()).magVec();
+
+	if (mLOD >= 3 || !mTextSegments.size() || (mDoFade && (mLastDistance > mFadeDistance + mFadeRange)))
+	{
+		mVisible = FALSE;
+		return;
+	}
+
+	LLVector3 x_pixel_vec;
+	LLVector3 y_pixel_vec;
+
+	LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+
+	LLVector3 render_position = mPositionAgent + 			
+			(x_pixel_vec * mPositionOffset.mV[VX]) +
+			(y_pixel_vec * mPositionOffset.mV[VY]);
+
+	mOffscreen = FALSE;
+	if (!LLViewerCamera::getInstance()->sphereInFrustum(render_position, mRadius))
+	{
+		if (!mVisibleOffScreen)
+		{
+			mVisible = FALSE;
+			return;
+		}
+		else
+		{
+			mOffscreen = TRUE;
+		}
+	}
+
+	mVisible = TRUE;
+	sVisibleTextObjects.push_back(LLPointer<LLHUDNameTag> (this));
+}
+
+LLVector2 LLHUDNameTag::updateScreenPos(LLVector2 &offset)
+{
+	LLCoordGL screen_pos;
+	LLVector2 screen_pos_vec;
+	LLVector3 x_pixel_vec;
+	LLVector3 y_pixel_vec;
+	LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+	LLVector3 world_pos = mPositionAgent + (offset.mV[VX] * x_pixel_vec) + (offset.mV[VY] * y_pixel_vec);
+	if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen)
+	{
+		// bubble off-screen, so find a spot for it along screen edge
+		LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(world_pos, screen_pos);
+	}
+
+	screen_pos_vec.setVec((F32)screen_pos.mX, (F32)screen_pos.mY);
+
+	LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+	S32 bottom = world_rect.mBottom + STATUS_BAR_HEIGHT;
+
+	LLVector2 screen_center;
+	screen_center.mV[VX] = llclamp((F32)screen_pos_vec.mV[VX], (F32)world_rect.mLeft + mWidth * 0.5f, (F32)world_rect.mRight - mWidth * 0.5f);
+
+	if(mVertAlignment == ALIGN_VERT_TOP)
+	{
+		screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY], 
+			(F32)bottom, 
+			(F32)world_rect.mTop - mHeight - (F32)MENU_BAR_HEIGHT);
+		mSoftScreenRect.setLeftTopAndSize(screen_center.mV[VX] - (mWidth + BUFFER_SIZE) * 0.5f, 
+			screen_center.mV[VY] + (mHeight + BUFFER_SIZE), mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
+	}
+	else
+	{
+		screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY], 
+			(F32)bottom + mHeight * 0.5f, 
+			(F32)world_rect.mTop - mHeight * 0.5f - (F32)MENU_BAR_HEIGHT);
+		mSoftScreenRect.setCenterAndSize(screen_center.mV[VX], screen_center.mV[VY], mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
+	}
+
+	return offset + (screen_center - LLVector2((F32)screen_pos.mX, (F32)screen_pos.mY));
+}
+
+void LLHUDNameTag::updateSize()
+{
+	F32 height = 0.f;
+	F32 width = 0.f;
+
+	S32 max_lines = getMaxLines();
+	//S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines);
+	//F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());
+
+	S32 start_segment;
+	if (max_lines < 0) start_segment = 0;
+	else start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines);
+
+	std::vector<LLHUDTextSegment>::iterator iter = mTextSegments.begin() + start_segment;
+	while (iter != mTextSegments.end())
+	{
+		const LLFontGL* fontp = iter->mFont;
+		height += fontp->getLineHeight();
+		height += LINE_PADDING;
+		width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH));
+		++iter;
+	}
+
+	// Don't want line spacing under the last line
+	if (height > 0.f)
+	{
+		height -= LINE_PADDING;
+	}
+
+	iter = mLabelSegments.begin();
+	while (iter != mLabelSegments.end())
+	{
+		height += mFontp->getLineHeight();
+		width = llmax(width, llmin(iter->getWidth(mFontp), HUD_TEXT_MAX_WIDTH));
+		++iter;
+	}
+	
+	if (width == 0.f)
+	{
+		return;
+	}
+
+	width += HORIZONTAL_PADDING;
+	height += VERTICAL_PADDING;
+
+	// *TODO: Could do a timer-based resize here
+	//mWidth = llmax(width, lerp(mWidth, (F32)width, u));
+	//mHeight = llmax(height, lerp(mHeight, (F32)height, u));
+	mWidth = width;
+	mHeight = height;
+}
+
+void LLHUDNameTag::updateAll()
+{
+	// iterate over all text objects, calculate their restoration forces,
+	// and add them to the visible set if they are on screen and close enough
+	sVisibleTextObjects.clear();
+	
+	TextObjectIterator text_it;
+	for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
+	{
+		LLHUDNameTag* textp = (*text_it);
+		textp->mTargetPositionOffset.clearVec();
+		textp->updateSize();
+		textp->updateVisibility();
+	}
+	
+	// sort back to front for rendering purposes
+	std::sort(sVisibleTextObjects.begin(), sVisibleTextObjects.end(), llhudnametag_further_away());
+
+	// iterate from front to back, and set LOD based on current screen coverage
+	F32 screen_area = (F32)(gViewerWindow->getWindowWidthScaled() * gViewerWindow->getWindowHeightScaled());
+	F32 current_screen_area = 0.f;
+	std::vector<LLPointer<LLHUDNameTag> >::reverse_iterator r_it;
+	for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)
+	{
+		LLHUDNameTag* textp = (*r_it);
+//		if (textp->mUseBubble)
+//		{
+			if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE)
+			{
+				textp->setLOD(3);
+			}
+			else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE)
+			{
+				textp->setLOD(2);
+			}
+			else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE)
+			{
+				textp->setLOD(1);
+			}
+			else
+			{
+				textp->setLOD(0);
+			}
+			textp->updateSize();
+			// find on-screen position and initialize collision rectangle
+			textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero);
+			current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight());
+//		}
+	}
+
+	LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat();
+	F32 camera_vel = camera_vel_stat->getCurrent();
+	if (camera_vel > MAX_STABLE_CAMERA_VELOCITY)
+	{
+		return;
+	}
+
+	VisibleTextObjectIterator src_it;
+
+	for (S32 i = 0; i < NUM_OVERLAP_ITERATIONS; i++)
+	{
+		for (src_it = sVisibleTextObjects.begin(); src_it != sVisibleTextObjects.end(); ++src_it)
+		{
+			LLHUDNameTag* src_textp = (*src_it);
+
+//			if (!src_textp->mUseBubble)
+//			{
+//				continue;
+//			}
+			VisibleTextObjectIterator dst_it = src_it;
+			++dst_it;
+			for (; dst_it != sVisibleTextObjects.end(); ++dst_it)
+			{
+				LLHUDNameTag* dst_textp = (*dst_it);
+
+//				if (!dst_textp->mUseBubble)
+//				{
+//					continue;
+//				}
+				if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))
+				{
+					LLRectf intersect_rect = src_textp->mSoftScreenRect;
+					intersect_rect.intersectWith(dst_textp->mSoftScreenRect);
+					intersect_rect.stretch(-BUFFER_SIZE * 0.5f);
+					
+					F32 src_center_x = src_textp->mSoftScreenRect.getCenterX();
+					F32 src_center_y = src_textp->mSoftScreenRect.getCenterY();
+					F32 dst_center_x = dst_textp->mSoftScreenRect.getCenterX();
+					F32 dst_center_y = dst_textp->mSoftScreenRect.getCenterY();
+					F32 intersect_center_x = intersect_rect.getCenterX();
+					F32 intersect_center_y = intersect_rect.getCenterY();
+					LLVector2 force = lerp(LLVector2(dst_center_x - intersect_center_x, dst_center_y - intersect_center_y), 
+										LLVector2(intersect_center_x - src_center_x, intersect_center_y - src_center_y),
+										0.5f);
+					force.setVec(dst_center_x - src_center_x, dst_center_y - src_center_y);
+					force.normVec();
+
+					LLVector2 src_force = -1.f * force;
+					LLVector2 dst_force = force;
+
+					LLVector2 force_strength;
+					F32 src_mult = dst_textp->mMass / (dst_textp->mMass + src_textp->mMass); 
+					F32 dst_mult = 1.f - src_mult;
+					F32 src_aspect_ratio = src_textp->mSoftScreenRect.getWidth() / src_textp->mSoftScreenRect.getHeight();
+					F32 dst_aspect_ratio = dst_textp->mSoftScreenRect.getWidth() / dst_textp->mSoftScreenRect.getHeight();
+					src_force.mV[VY] *= src_aspect_ratio;
+					src_force.normVec();
+					dst_force.mV[VY] *= dst_aspect_ratio;
+					dst_force.normVec();
+
+					src_force.mV[VX] *= llmin(intersect_rect.getWidth() * src_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
+					src_force.mV[VY] *= llmin(intersect_rect.getHeight() * src_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
+					dst_force.mV[VX] *=  llmin(intersect_rect.getWidth() * dst_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
+					dst_force.mV[VY] *=  llmin(intersect_rect.getHeight() * dst_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
+					
+					src_textp->mTargetPositionOffset += src_force;
+					dst_textp->mTargetPositionOffset += dst_force;
+					src_textp->mTargetPositionOffset = src_textp->updateScreenPos(src_textp->mTargetPositionOffset);
+					dst_textp->mTargetPositionOffset = dst_textp->updateScreenPos(dst_textp->mTargetPositionOffset);
+				}
+			}
+		}
+	}
+
+	VisibleTextObjectIterator this_object_it;
+	for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it)
+	{
+//		if (!(*this_object_it)->mUseBubble)
+//		{
+//			continue;
+//		}
+		(*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC));
+	}
+}
+
+void LLHUDNameTag::setLOD(S32 lod)
+{
+	mLOD = lod;
+	//RN: uncomment this to visualize LOD levels
+	//std::string label = llformat("%d", lod);
+	//setLabel(label);
+}
+
+S32 LLHUDNameTag::getMaxLines()
+{
+	switch(mLOD)
+	{
+	case 0:
+		return mMaxLines;
+	case 1:
+		return mMaxLines > 0 ? mMaxLines / 2 : 5;
+	case 2:
+		return mMaxLines > 0 ? mMaxLines / 3 : 2;
+	default:
+		// label only
+		return 0;
+	}
+}
+
+void LLHUDNameTag::markDead()
+{
+	sTextObjects.erase(LLPointer<LLHUDNameTag>(this));
+	LLHUDObject::markDead();
+}
+
+void LLHUDNameTag::shiftAll(const LLVector3& offset)
+{
+	TextObjectIterator text_it;
+	for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
+	{
+		LLHUDNameTag *textp = text_it->get();
+		textp->shift(offset);
+	}
+}
+
+void LLHUDNameTag::shift(const LLVector3& offset)
+{
+	mPositionAgent += offset;
+}
+
+//static 
+void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list)
+{
+	//this might put an object on the pick list a second time, overriding it's mGLName, which is ok
+	// *FIX: we should probably cull against pick frustum
+	VisibleTextObjectIterator text_it;
+	for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it)
+	{
+//		if (!(*text_it)->mUseBubble)
+//		{
+//			continue;
+//		}
+		pick_list.insert((*text_it)->mSourceObject);
+	}
+}
+
+//static
+// called when UI scale changes, to flush font width caches
+void LLHUDNameTag::reshape()
+{
+	TextObjectIterator text_it;
+	for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
+	{
+		LLHUDNameTag* textp = (*text_it);
+		std::vector<LLHUDTextSegment>::iterator segment_iter; 
+		for (segment_iter = textp->mTextSegments.begin();
+			 segment_iter != textp->mTextSegments.end(); ++segment_iter )
+		{
+			segment_iter->clearFontWidthMap();
+		}
+		for(segment_iter = textp->mLabelSegments.begin();
+			segment_iter != textp->mLabelSegments.end(); ++segment_iter )
+		{
+			segment_iter->clearFontWidthMap();
+		}		
+	}
+}
+
+//============================================================================
+
+F32 LLHUDNameTag::LLHUDTextSegment::getWidth(const LLFontGL* font)
+{
+	std::map<const LLFontGL*, F32>::iterator iter = mFontWidthMap.find(font);
+	if (iter != mFontWidthMap.end())
+	{
+		return iter->second;
+	}
+	else
+	{
+		F32 width = font->getWidthF32(mText.c_str());
+		mFontWidthMap[font] = width;
+		return width;
+	}
+}
diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a92307009df71484c15ce8e3751f79f30fd62d3
--- /dev/null
+++ b/indra/newview/llhudnametag.h
@@ -0,0 +1,191 @@
+/** 
+ * @file llhudnametag.h
+ * @brief Name tags for avatars
+ * @author James Cook
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2002-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 LLHUDNAMETAG_H
+#define LLHUDNAMETAG_H
+
+#include "llpointer.h"
+
+#include "llhudobject.h"
+#include "v4color.h"
+//#include "v4coloru.h"
+#include "v2math.h"
+#include "llrect.h"
+//#include "llframetimer.h"
+#include "llfontgl.h"
+#include <set>
+#include <vector>
+
+class LLDrawable;
+class LLHUDNameTag;
+
+struct llhudnametag_further_away
+{
+	bool operator()(const LLPointer<LLHUDNameTag>& lhs, const LLPointer<LLHUDNameTag>& rhs) const;
+};
+
+class LLHUDNameTag : public LLHUDObject
+{
+protected:
+	class LLHUDTextSegment
+	{
+	public:
+		LLHUDTextSegment(const LLWString& text, const LLFontGL::StyleFlags style, const LLColor4& color, const LLFontGL* font)
+		:	mColor(color),
+			mStyle(style),
+			mText(text),
+			mFont(font)
+		{}
+		F32 getWidth(const LLFontGL* font);
+		const LLWString& getText() const { return mText; }
+		void clearFontWidthMap() { mFontWidthMap.clear(); }
+		
+		LLColor4				mColor;
+		LLFontGL::StyleFlags	mStyle;
+		const LLFontGL*			mFont;
+	private:
+		LLWString				mText;
+		std::map<const LLFontGL*, F32> mFontWidthMap;
+	};
+
+public:
+	typedef enum e_text_alignment
+	{
+		ALIGN_TEXT_LEFT,
+		ALIGN_TEXT_CENTER
+	} ETextAlignment;
+
+	typedef enum e_vert_alignment
+	{
+		ALIGN_VERT_TOP,
+		ALIGN_VERT_CENTER
+	} EVertAlignment;
+
+public:
+	// Set entire string, eliminating existing lines
+	void setString(const std::string& text_utf8);
+
+	void clearString();
+
+	// Add text a line at a time, allowing custom formatting
+	void addLine(const std::string &text_utf8, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL, const LLFontGL* font = NULL);
+
+	// For bubble chat, set the part above the chat text
+	void setLabel(const std::string& label_utf8);
+	void addLabel(const std::string& label_utf8);
+
+	// Sets the default font for lines with no font specified
+	void setFont(const LLFontGL* font);
+	void setColor(const LLColor4 &color);
+	void setAlpha(F32 alpha);
+	void setZCompare(const BOOL zcompare);
+	void setDoFade(const BOOL do_fade);
+	void setVisibleOffScreen(BOOL visible) { mVisibleOffScreen = visible; }
+	
+	// mMaxLines of -1 means unlimited lines.
+	void setMaxLines(S32 max_lines) { mMaxLines = max_lines; }
+	void setFadeDistance(F32 fade_distance, F32 fade_range) { mFadeDistance = fade_distance; mFadeRange = fade_range; }
+	void updateVisibility();
+	LLVector2 updateScreenPos(LLVector2 &offset_target);
+	void updateSize();
+//	void setMass(F32 mass) { mMass = llmax(0.1f, mass); }
+	void setTextAlignment(ETextAlignment alignment) { mTextAlignment = alignment; }
+	void setVertAlignment(EVertAlignment alignment) { mVertAlignment = alignment; }
+	/*virtual*/ void markDead();
+	friend class LLHUDObject;
+	/*virtual*/ F32 getDistance() const { return mLastDistance; }
+	//void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; }
+	S32  getLOD() { return mLOD; }
+	BOOL getVisible() { return mVisible; }
+	BOOL getHidden() const { return mHidden; }
+	void setHidden( BOOL hide ) { mHidden = hide; }
+	void shift(const LLVector3& offset);
+
+	BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render = FALSE);
+
+	static void shiftAll(const LLVector3& offset);
+	static void addPickable(std::set<LLViewerObject*> &pick_list);
+	static void reshape();
+	static void setDisplayText(BOOL flag) { sDisplayText = flag ; }
+
+protected:
+	LLHUDNameTag(const U8 type);
+
+	/*virtual*/ void render();
+	/*virtual*/ void renderForSelect();
+	void renderText(BOOL for_select);
+	static void updateAll();
+	void setLOD(S32 lod);
+	S32 getMaxLines();
+
+private:
+	~LLHUDNameTag();
+	BOOL			mDoFade;
+	F32				mFadeRange;
+	F32				mFadeDistance;
+	F32				mLastDistance;
+	BOOL			mZCompare;
+	BOOL			mVisibleOffScreen;
+	BOOL			mOffscreen;
+	LLColor4		mColor;
+//	LLVector3		mScale;
+	F32				mWidth;
+	F32				mHeight;
+//	LLColor4U		mPickColor;
+	const LLFontGL*	mFontp;
+	const LLFontGL*	mBoldFontp;
+	LLRectf			mSoftScreenRect;
+	LLVector3		mPositionAgent;
+	LLVector2		mPositionOffset;
+	LLVector2		mTargetPositionOffset;
+	F32				mMass;
+	S32				mMaxLines;
+	S32				mOffsetY;
+	F32				mRadius;
+	std::vector<LLHUDTextSegment> mTextSegments;
+	std::vector<LLHUDTextSegment> mLabelSegments;
+//	LLFrameTimer	mResizeTimer;
+	ETextAlignment	mTextAlignment;
+	EVertAlignment	mVertAlignment;
+	S32				mLOD;
+	BOOL			mHidden;
+
+	static BOOL    sDisplayText ;
+	static std::set<LLPointer<LLHUDNameTag> > sTextObjects;
+	static std::vector<LLPointer<LLHUDNameTag> > sVisibleTextObjects;
+//	static std::vector<LLPointer<LLHUDNameTag> > sVisibleHUDTextObjects;
+	typedef std::set<LLPointer<LLHUDNameTag> >::iterator TextObjectIterator;
+	typedef std::vector<LLPointer<LLHUDNameTag> >::iterator VisibleTextObjectIterator;
+};
+
+#endif
diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp
index 3e814a0773efbd06c5459cbc3ac96850c1b93db7..09200ee5be66102701d24a21e816332f7f02a65c 100644
--- a/indra/newview/llhudobject.cpp
+++ b/indra/newview/llhudobject.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2002-2010, Linden Research, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -24,9 +24,6 @@
  * $/LicenseInfo$
  */
 
-// llhudobject.cpp
-// Copyright 2002, Linden Research, Inc.
-
 #include "llviewerprecompiledheaders.h"
 
 #include "llhudobject.h"
@@ -38,7 +35,7 @@
 #include "llhudeffecttrail.h"
 #include "llhudeffectlookat.h"
 #include "llhudeffectpointat.h"
-
+#include "llhudnametag.h"
 #include "llvoicevisualizer.h"
 
 #include "llagent.h"
@@ -66,7 +63,6 @@ LLHUDObject::LLHUDObject(const U8 type) :
 	mVisible = TRUE;
 	mType = type;
 	mDead = FALSE;
-	mOnHUDAttachment = FALSE;
 }
 
 LLHUDObject::~LLHUDObject()
@@ -145,6 +141,9 @@ LLHUDObject *LLHUDObject::addHUDObject(const U8 type)
 	case LL_HUD_ICON:
 		hud_objectp = new LLHUDIcon(type);
 		break;
+	case LL_HUD_NAME_TAG:
+		hud_objectp = new LLHUDNameTag(type);
+		break;
 	default:
 		llwarns << "Unknown type of hud object:" << (U32) type << llendl;
 	}
@@ -257,6 +256,7 @@ void LLHUDObject::updateAll()
 	LLFastTimer ftm(FTM_HUD_UPDATE);
 	LLHUDText::updateAll();
 	LLHUDIcon::updateAll();
+	LLHUDNameTag::updateAll();
 	sortObjects();
 }
 
@@ -325,6 +325,14 @@ void LLHUDObject::renderAllForTimer()
 	}
 }
 
+// static
+void LLHUDObject::reshapeAll()
+{
+	// only hud objects that use fonts care about window size/scale changes
+	LLHUDText::reshape();
+	LLHUDNameTag::reshape();
+}
+
 // static
 void LLHUDObject::sortObjects()
 {
diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h
index 97145b9a84d40d60f66cfc0e72ea1e2d749876b9..4282ade34dc97c3245a5161b1c2398dc3139de28 100644
--- a/indra/newview/llhudobject.h
+++ b/indra/newview/llhudobject.h
@@ -36,7 +36,7 @@
 #include "v4color.h"
 #include "v3math.h"
 #include "v3dmath.h"
-#include "lldrawpool.h"
+#include "lldrawpool.h"		// TODO: eliminate, unused below
 #include <list>
 
 class LLViewerCamera;
@@ -71,6 +71,9 @@ class LLHUDObject : public LLRefCount
 	static void renderAllForSelect();
 	static void renderAllForTimer();
 
+	// Some objects may need to update when window shape changes
+	static void reshapeAll();
+
 	static void cleanupHUDObjects();
 
 	enum
@@ -91,7 +94,8 @@ class LLHUDObject : public LLRefCount
 		LL_HUD_EFFECT_EDIT,
 		LL_HUD_EFFECT_LOOKAT,
 		LL_HUD_EFFECT_POINTAT,
-		LL_HUD_EFFECT_VOICE_VISUALIZER	// Ventrella
+		LL_HUD_EFFECT_VOICE_VISUALIZER,	// Ventrella
+		LL_HUD_NAME_TAG
 	};
 protected:
 	static void sortObjects();
@@ -108,7 +112,6 @@ class LLHUDObject : public LLRefCount
 	BOOL			mDead;
 	BOOL			mVisible;
 	LLVector3d		mPositionGlobal;
-	BOOL			mOnHUDAttachment;
 	LLPointer<LLViewerObject> mSourceObject;
 	LLPointer<LLViewerObject> mTargetObject;
 
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 96638018c4b0921bf667c6cbbf45d1d015e937e4..6a423e529a5e533936fed91994bbf3db440dab50 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -1,7 +1,6 @@
-
 /** 
  * @file llhudtext.cpp
- * @brief LLHUDText class implementation
+ * @brief Floating text above objects, set via script with llSetText()
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -56,16 +55,16 @@ const F32 HORIZONTAL_PADDING = 15.f;
 const F32 VERTICAL_PADDING = 12.f;
 const F32 BUFFER_SIZE = 2.f;
 const F32 MIN_EDGE_OVERLAP = 3.f;
-F32 HUD_TEXT_MAX_WIDTH = 190.f;
+const F32 HUD_TEXT_MAX_WIDTH = 190.f;
 const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f;
 const F32 RESIZE_TIME = 0.f;
 const S32 NUM_OVERLAP_ITERATIONS = 10;
 const F32 NEIGHBOR_FORCE_FRACTION = 1.f;
 const F32 POSITION_DAMPING_TC = 0.2f;
 const F32 MAX_STABLE_CAMERA_VELOCITY = 0.1f;
-const F32 LOD_0_SCREEN_COVERAGE = 0.15f;
-const F32 LOD_1_SCREEN_COVERAGE = 0.30f;
-const F32 LOD_2_SCREEN_COVERAGE = 0.40f;
+//const F32 LOD_0_SCREEN_COVERAGE = 0.15f;
+//const F32 LOD_1_SCREEN_COVERAGE = 0.30f;
+//const F32 LOD_2_SCREEN_COVERAGE = 0.40f;
 
 std::set<LLPointer<LLHUDText> > LLHUDText::sTextObjects;
 std::vector<LLPointer<LLHUDText> > LLHUDText::sVisibleTextObjects;
@@ -74,15 +73,14 @@ BOOL LLHUDText::sDisplayText = TRUE ;
 
 bool lltextobject_further_away::operator()(const LLPointer<LLHUDText>& lhs, const LLPointer<LLHUDText>& rhs) const
 {
-	return (lhs->getDistance() > rhs->getDistance()) ? true : false;
+	return lhs->getDistance() > rhs->getDistance();
 }
 
 
 LLHUDText::LLHUDText(const U8 type) :
 			LLHUDObject(type),
-			mUseBubble(FALSE),
-			mUsePixelSize(TRUE),
-			mVisibleOffScreen(FALSE),
+			mOnHUDAttachment(FALSE),
+//			mVisibleOffScreen(FALSE),
 			mWidth(0.f),
 			mHeight(0.f),
 			mFontp(LLFontGL::getFontSansSerifSmall()),
@@ -92,7 +90,7 @@ LLHUDText::LLHUDText(const U8 type) :
 			mOffsetY(0),
 			mTextAlignment(ALIGN_TEXT_CENTER),
 			mVertAlignment(ALIGN_VERT_CENTER),
-			mLOD(0),
+//			mLOD(0),
 			mHidden(FALSE)
 {
 	mColor = LLColor4(1.f, 1.f, 1.f, 1.f);
@@ -100,7 +98,6 @@ LLHUDText::LLHUDText(const U8 type) :
 	mFadeDistance = 8.f;
 	mFadeRange = 4.f;
 	mZCompare = TRUE;
-	mDropShadow = TRUE;
 	mOffscreen = FALSE;
 	mRadius = 0.1f;
 	LLPointer<LLHUDText> ptr(this);
@@ -111,112 +108,6 @@ LLHUDText::~LLHUDText()
 {
 }
 
-
-BOOL LLHUDText::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render)
-{
-	if (!mVisible || mHidden)
-	{
-		return FALSE;
-	}
-
-	// don't pick text that isn't bound to a viewerobject or isn't in a bubble
-	if (!mSourceObject || mSourceObject->mDrawable.isNull() || !mUseBubble)
-	{
-		return FALSE;
-	}
-	
-	F32 alpha_factor = 1.f;
-	LLColor4 text_color = mColor;
-	if (mDoFade)
-	{
-		if (mLastDistance > mFadeDistance)
-		{
-			alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
-			text_color.mV[3] = text_color.mV[3]*alpha_factor;
-		}
-	}
-	if (text_color.mV[3] < 0.01f)
-	{
-		return FALSE;
-	}
-
-	mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
-
-	// scale screen size of borders down
-	//RN: for now, text on hud objects is never occluded
-
-	LLVector3 x_pixel_vec;
-	LLVector3 y_pixel_vec;
-	
-	if (mOnHUDAttachment)
-	{
-		x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWindowWidthScaled();
-		y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWindowHeightScaled();
-	}
-	else
-	{
-		LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
-	}
-
-	LLVector3 width_vec = mWidth * x_pixel_vec;
-	LLVector3 height_vec = mHeight * y_pixel_vec;
-	
-	LLCoordGL screen_pos;
-	LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
-
-	LLVector2 screen_offset;
-	screen_offset = updateScreenPos(mPositionOffset);
-	
-	LLVector3 render_position = mPositionAgent  
-			+ (x_pixel_vec * screen_offset.mV[VX])
-			+ (y_pixel_vec * screen_offset.mV[VY]);
-
-
-	if (mUseBubble)
-	{
-		LLVector3 bg_pos = render_position
-			+ (F32)mOffsetY * y_pixel_vec
-			- (width_vec / 2.f)
-			- (height_vec);
-		//LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
-
-		LLVector3 v[] = 
-		{
-			bg_pos,
-			bg_pos + width_vec,
-			bg_pos + width_vec + height_vec,
-			bg_pos + height_vec,
-		};
-
-		if (debug_render)
-		{
-			gGL.begin(LLRender::LINE_STRIP);
-			gGL.vertex3fv(v[0].mV);
-			gGL.vertex3fv(v[1].mV);
-			gGL.vertex3fv(v[2].mV);
-			gGL.vertex3fv(v[3].mV);
-			gGL.vertex3fv(v[0].mV);
-			gGL.vertex3fv(v[2].mV);
-			gGL.end();
-		}
-
-		LLVector3 dir = end-start;
-		F32 t = 0.f;
-
-		if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, NULL, NULL, &t, FALSE) ||
-			LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, NULL, NULL, &t, FALSE) )
-		{
-			if (t <= 1.f)
-			{
-				intersection = start + dir*t;
-				return TRUE;
-			}
-		}
-	}
-
-	return FALSE;
-}
-
 void LLHUDText::render()
 {
 	if (!mOnHUDAttachment && sDisplayText)
@@ -242,21 +133,13 @@ void LLHUDText::renderText(BOOL for_select)
 		return;
 	}
 
-	// don't pick text that isn't bound to a viewerobject or isn't in a bubble
-	if (for_select && 
-		(!mSourceObject || mSourceObject->mDrawable.isNull() || !mUseBubble))
+	// don't pick text
+	if (for_select)
 	{
 		return;
 	}
 	
-	if (for_select)
-	{
-		gGL.getTexUnit(0)->disable();
-	}
-	else
-	{
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-	}
+	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
 
 	LLGLState gls_blend(GL_BLEND, for_select ? FALSE : TRUE);
 	LLGLState gls_alpha(GL_ALPHA_TEST, for_select ? FALSE : TRUE);
@@ -284,7 +167,7 @@ void LLHUDText::renderText(BOOL for_select)
 	LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
 
 	// *TODO: make this a per-text setting
-	LLColor4 bg_color = LLUIColorTable::instance().getColor("BackgroundChatColor");
+	LLColor4 bg_color = LLUIColorTable::instance().getColor("ObjectBubbleColor");
 	bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
 
 	const S32 border_height = 16;
@@ -330,178 +213,17 @@ void LLHUDText::renderText(BOOL for_select)
 	LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
 
 	LLVector2 screen_offset;
-	if (!mUseBubble)
-	{
-		screen_offset = mPositionOffset;
-	}
-	else
-	{
-		screen_offset = updateScreenPos(mPositionOffset);
-	}
+	screen_offset = mPositionOffset;
 
 	LLVector3 render_position = mPositionAgent  
 			+ (x_pixel_vec * screen_offset.mV[VX])
 			+ (y_pixel_vec * screen_offset.mV[VY]);
 
-	//if (mOnHUD)
-	//{
-	//	render_position.mV[VY] -= fmodf(render_position.mV[VY], 1.f / (F32)gViewerWindow->getWindowWidthScaled());
-	//	render_position.mV[VZ] -= fmodf(render_position.mV[VZ], 1.f / (F32)gViewerWindow->getWindowHeightScaled());
-	//}
-	//else
-	//{
-	//	render_position = LLViewerCamera::getInstance()->roundToPixel(render_position);
-	//}
-
-	if (mUseBubble)
-	{
-		LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-		LLUI::pushMatrix();
-		{
-			LLVector3 bg_pos = render_position
-				+ (F32)mOffsetY * y_pixel_vec
-				- (width_vec / 2.f)
-				- (height_vec);
-			LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
-
-			if (for_select)
-			{
-				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-				S32 name = mSourceObject->mGLName;
-				LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name);
-				gGL.color4ubv(coloru.mV);
-				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
-				LLUI::popMatrix();
-				return;
-			}
-			else
-			{
-				gGL.getTexUnit(0)->bind(imagep->getImage());
-				
-				gGL.color4fv(bg_color.mV);
-				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
-		
-				if ( mLabelSegments.size())
-				{
-					LLUI::pushMatrix();
-					{
-						gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
-						LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec;
-						LLVector3 label_offset = height_vec - label_height;
-						LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]);
-						gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height);
-					}
-					LLUI::popMatrix();
-				}
-			}
-
-			BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f;
-			BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f);
-
-			// draw line segments pointing to parent object
-			if (!mOffscreen && (outside_width || outside_height))
-			{
-				LLUI::pushMatrix();
-				{
-					gGL.color4fv(bg_color.mV);
-					LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec);
-					target_pos += (width_vec / 2.f);
-					target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero;
-					target_pos -= 3.f * x_pixel_vec;
-					target_pos -= 6.f * y_pixel_vec;
-					LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]);
-					gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec);	
-				}
-				LLUI::popMatrix();
-
-				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-				LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE);
-				
-				LLVector3 box_center_offset;
-				box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f);
-				LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]);
-				gGL.color4fv(bg_color.mV);
-				LLUI::setLineWidth(2.0);
-				gGL.begin(LLRender::LINES);
-				{
-					if (outside_width)
-					{
-						LLVector3 vert;
-						// draw line in x then y
-						if (mPositionOffset.mV[VX] < 0.f)
-						{
-							// start at right edge
-							vert = width_vec * 0.5f;
-							gGL.vertex3fv(vert.mV);
-						}
-						else
-						{
-							// start at left edge
-							vert = width_vec * -0.5f;
-							gGL.vertex3fv(vert.mV);
-						}
-						vert = -mPositionOffset.mV[VX] * x_pixel_vec;
-						gGL.vertex3fv(vert.mV);
-						gGL.vertex3fv(vert.mV);
-						vert -= mPositionOffset.mV[VY] * y_pixel_vec;
-						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
-						gGL.vertex3fv(vert.mV);
-					}
-					else
-					{
-						LLVector3 vert;
-						// draw line in y then x
-						if (mPositionOffset.mV[VY] < 0.f)
-						{
-							// start at top edge
-							vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
-							gGL.vertex3fv(vert.mV);
-						}
-						else
-						{
-							// start at bottom edge
-							vert = (height_vec * -0.5f)  - (mPositionOffset.mV[VX] * x_pixel_vec);
-							gGL.vertex3fv(vert.mV);
-						}
-						vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec;
-						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
-						gGL.vertex3fv(vert.mV);
-					}
-				}
-				gGL.end();
-				LLUI::setLineWidth(1.0);
-
-			}
-		}
-		LLUI::popMatrix();
-	}
-
 	F32 y_offset = (F32)mOffsetY;
 		
 	// Render label
 	{
 		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-
-		for(std::vector<LLHUDTextSegment>::iterator segment_iter = mLabelSegments.begin();
-			segment_iter != mLabelSegments.end(); ++segment_iter )
-		{
-			const LLFontGL* fontp = (segment_iter->mStyle == LLFontGL::BOLD) ? mBoldFontp : mFontp;
-			y_offset -= fontp->getLineHeight();
-
-			F32 x_offset;
-			if (mTextAlignment == ALIGN_TEXT_CENTER)
-			{
-				x_offset = -0.5f*segment_iter->getWidth(fontp);
-			}
-			else // ALIGN_LEFT
-			{
-				x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f);
-			}
-
-			LLColor4 label_color(0.f, 0.f, 0.f, 1.f);
-			label_color.mV[VALPHA] = alpha_factor;
-			hud_render_text(segment_iter->getText(), render_position, *fontp, segment_iter->mStyle, LLFontGL::NO_SHADOW, x_offset, y_offset, label_color, mOnHUDAttachment);
-		}
 	}
 
 	// Render text
@@ -522,15 +244,11 @@ void LLHUDText::renderText(BOOL for_select)
 		for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment;
 			 segment_iter != mTextSegments.end(); ++segment_iter )
 		{
-			const LLFontGL* fontp = (segment_iter->mStyle == LLFontGL::BOLD) ? mBoldFontp : mFontp;
+			const LLFontGL* fontp = segment_iter->mFont;
 			y_offset -= fontp->getLineHeight();
 
 			U8 style = segment_iter->mStyle;
-			LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW;
-			if (mDropShadow)
-			{
-				shadow = LLFontGL::DROP_SHADOW;
-			}
+			LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW;
 	
 			F32 x_offset;
 			if (mTextAlignment== ALIGN_TEXT_CENTER)
@@ -550,21 +268,12 @@ void LLHUDText::renderText(BOOL for_select)
 	}
 	/// Reset the default color to white.  The renderer expects this to be the default. 
 	gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
-	if (for_select)
-	{
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-	}
-}
-
-void LLHUDText::setStringUTF8(const std::string &wtext)
-{
-	setString(utf8str_to_wstring(wtext));
 }
 
-void LLHUDText::setString(const LLWString &wtext)
+void LLHUDText::setString(const std::string &text_utf8)
 {
 	mTextSegments.clear();
-	addLine(wtext, mColor);
+	addLine(text_utf8, mColor);
 }
 
 void LLHUDText::clearString()
@@ -573,21 +282,19 @@ void LLHUDText::clearString()
 }
 
 
-void LLHUDText::addLine(const std::string &str, const LLColor4& color, const LLFontGL::StyleFlags style)
+void LLHUDText::addLine(const std::string &text_utf8,
+						const LLColor4& color,
+						const LLFontGL::StyleFlags style,
+						const LLFontGL* font)
 {
-	addLine(utf8str_to_wstring(str), color, style);
-}
-
-
-void LLHUDText::addLine(const LLWString &wstr, const LLColor4& color, const LLFontGL::StyleFlags style)
-{
-	if (gNoRender)
-	{
-		return;
-	}
-	if (!wstr.empty())
+	LLWString wline = utf8str_to_wstring(text_utf8);
+	if (!wline.empty())
 	{
-		LLWString wline(wstr);
+		// use default font for segment if custom font not specified
+		if (!font)
+		{
+			font = mFontp;
+		}
 		typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
 		LLWString seps(utf8str_to_wstring("\r\n"));
 		boost::char_separator<llwchar> sep(seps.c_str());
@@ -600,8 +307,10 @@ void LLHUDText::addLine(const LLWString &wstr, const LLColor4& color, const LLFo
 			U32 line_length = 0;
 			do	
 			{
-				S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
-				mTextSegments.push_back(LLHUDTextSegment(iter->substr(line_length, segment_length), style, color));
+				F32 max_pixels = HUD_TEXT_MAX_WIDTH_NO_BUBBLE;
+				S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+				LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
+				mTextSegments.push_back(segment);
 				line_length += segment_length;
 			}
 			while (line_length != iter->size());
@@ -610,47 +319,6 @@ void LLHUDText::addLine(const LLWString &wstr, const LLColor4& color, const LLFo
 	}
 }
 
-void LLHUDText::setLabel(const std::string &label)
-{
-	setLabel(utf8str_to_wstring(label));
-}
-
-void LLHUDText::setLabel(const LLWString &wlabel)
-{
-	mLabelSegments.clear();
-
-	if (!wlabel.empty())
-	{
-		LLWString wstr(wlabel);
-		LLWString seps(utf8str_to_wstring("\r\n"));
-		LLWString empty;
-
-		typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
-		boost::char_separator<llwchar> sep(seps.c_str(), empty.c_str(), boost::keep_empty_tokens);
-
-		tokenizer tokens(wstr, sep);
-		tokenizer::iterator iter = tokens.begin();
-
-		while (iter != tokens.end())
-		{
-			U32 line_length = 0;
-			do	
-			{
-				S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wstr.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
-				mLabelSegments.push_back(LLHUDTextSegment(iter->substr(line_length, segment_length), LLFontGL::NORMAL, mColor));
-				line_length += segment_length;
-			}
-			while (line_length != iter->size());
-			++iter;
-		}
-	}
-}
-
-void LLHUDText::setDropShadow(const BOOL do_shadow)
-{
-	mDropShadow = do_shadow;
-}
-
 void LLHUDText::setZCompare(const BOOL zcompare)
 {
 	mZCompare = zcompare;
@@ -672,12 +340,17 @@ void LLHUDText::setColor(const LLColor4 &color)
 	}
 }
 
-
-void LLHUDText::setUsePixelSize(const BOOL use_pixel_size)
+void LLHUDText::setAlpha(F32 alpha)
 {
-	mUsePixelSize = use_pixel_size;
+	mColor.mV[VALPHA] = alpha;
+	for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
+		 segment_iter != mTextSegments.end(); ++segment_iter )
+	{
+		segment_iter->mColor.mV[VALPHA] = alpha;
+	}
 }
 
+
 void LLHUDText::setDoFade(const BOOL do_fade)
 {
 	mDoFade = do_fade;
@@ -745,7 +418,7 @@ void LLHUDText::updateVisibility()
 
 	mLastDistance = (mPositionAgent - LLViewerCamera::getInstance()->getOrigin()).magVec();
 
-	if (mLOD >= 3 || !mTextSegments.size() || (mDoFade && (mLastDistance > mFadeDistance + mFadeRange)))
+	if (!mTextSegments.size() || (mDoFade && (mLastDistance > mFadeDistance + mFadeRange)))
 	{
 		mVisible = FALSE;
 		return;
@@ -763,15 +436,15 @@ void LLHUDText::updateVisibility()
 	mOffscreen = FALSE;
 	if (!LLViewerCamera::getInstance()->sphereInFrustum(render_position, mRadius))
 	{
-		if (!mVisibleOffScreen)
-		{
+//		if (!mVisibleOffScreen)
+//		{
 			mVisible = FALSE;
 			return;
-		}
-		else
-		{
-			mOffscreen = TRUE;
-		}
+//		}
+//		else
+//		{
+//			mOffscreen = TRUE;
+//		}
 	}
 
 	mVisible = TRUE;
@@ -786,11 +459,11 @@ LLVector2 LLHUDText::updateScreenPos(LLVector2 &offset)
 	LLVector3 y_pixel_vec;
 	LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
 	LLVector3 world_pos = mPositionAgent + (offset.mV[VX] * x_pixel_vec) + (offset.mV[VY] * y_pixel_vec);
-	if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen)
-	{
-		// bubble off-screen, so find a spot for it along screen edge
-		LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(world_pos, screen_pos);
-	}
+//	if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen)
+//	{
+//		// bubble off-screen, so find a spot for it along screen edge
+//		LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(world_pos, screen_pos);
+//	}
 
 	screen_pos_vec.setVec((F32)screen_pos.mX, (F32)screen_pos.mY);
 
@@ -821,12 +494,12 @@ LLVector2 LLHUDText::updateScreenPos(LLVector2 &offset)
 
 void LLHUDText::updateSize()
 {
+	F32 height = 0.f;
 	F32 width = 0.f;
 
 	S32 max_lines = getMaxLines();
-	S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines);
-
-	F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());
+	//S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines);
+	//F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());
 
 	S32 start_segment;
 	if (max_lines < 0) start_segment = 0;
@@ -835,17 +508,12 @@ void LLHUDText::updateSize()
 	std::vector<LLHUDTextSegment>::iterator iter = mTextSegments.begin() + start_segment;
 	while (iter != mTextSegments.end())
 	{
-		width = llmax(width, llmin(iter->getWidth(mFontp), HUD_TEXT_MAX_WIDTH));
+		const LLFontGL* fontp = iter->mFont;
+		height += fontp->getLineHeight();
+		width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH));
 		++iter;
 	}
 
-	iter = mLabelSegments.begin();
-	while (iter != mLabelSegments.end())
-	{
-		width = llmax(width, llmin(iter->getWidth(mFontp), HUD_TEXT_MAX_WIDTH));
-		++iter;
-	}
-	
 	if (width == 0.f)
 	{
 		return;
@@ -854,18 +522,8 @@ void LLHUDText::updateSize()
 	width += HORIZONTAL_PADDING;
 	height += VERTICAL_PADDING;
 
-	if (!mResizeTimer.getStarted() && (width != mWidth || height != mHeight))
-	{
-		mResizeTimer.start();
-	}
-
-	// *NOTE: removed logic which did a divide by zero.
-	F32 u = 1.f;//llclamp(mResizeTimer.getElapsedTimeF32() / RESIZE_TIME, 0.f, 1.f);
-	if (u == 1.f)
-	{
-		mResizeTimer.stop();
-	}
-
+	// *TODO: Could do some sort of timer-based resize logic here
+	F32 u = 1.f;
 	mWidth = llmax(width, lerp(mWidth, (F32)width, u));
 	mHeight = llmax(height, lerp(mHeight, (F32)height, u));
 }
@@ -889,146 +547,31 @@ void LLHUDText::updateAll()
 	// sort back to front for rendering purposes
 	std::sort(sVisibleTextObjects.begin(), sVisibleTextObjects.end(), lltextobject_further_away());
 	std::sort(sVisibleHUDTextObjects.begin(), sVisibleHUDTextObjects.end(), lltextobject_further_away());
-
-	// iterate from front to back, and set LOD based on current screen coverage
-	F32 screen_area = (F32)(gViewerWindow->getWindowWidthScaled() * gViewerWindow->getWindowHeightScaled());
-	F32 current_screen_area = 0.f;
-	std::vector<LLPointer<LLHUDText> >::reverse_iterator r_it;
-	for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)
-	{
-		LLHUDText* textp = (*r_it);
-		if (textp->mUseBubble)
-		{
-			if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE)
-			{
-				textp->setLOD(3);
-			}
-			else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE)
-			{
-				textp->setLOD(2);
-			}
-			else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE)
-			{
-				textp->setLOD(1);
-			}
-			else
-			{
-				textp->setLOD(0);
-			}
-			textp->updateSize();
-			// find on-screen position and initialize collision rectangle
-			textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero);
-			current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight());
-		}
-	}
-
-	LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat();
-	F32 camera_vel = camera_vel_stat->getCurrent();
-	if (camera_vel > MAX_STABLE_CAMERA_VELOCITY)
-	{
-		return;
-	}
-
-	VisibleTextObjectIterator src_it;
-
-	for (S32 i = 0; i < NUM_OVERLAP_ITERATIONS; i++)
-	{
-		for (src_it = sVisibleTextObjects.begin(); src_it != sVisibleTextObjects.end(); ++src_it)
-		{
-			LLHUDText* src_textp = (*src_it);
-
-			if (!src_textp->mUseBubble)
-			{
-				continue;
-			}
-			VisibleTextObjectIterator dst_it = src_it;
-			++dst_it;
-			for (; dst_it != sVisibleTextObjects.end(); ++dst_it)
-			{
-				LLHUDText* dst_textp = (*dst_it);
-
-				if (!dst_textp->mUseBubble)
-				{
-					continue;
-				}
-				if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))
-				{
-					LLRectf intersect_rect = src_textp->mSoftScreenRect;
-					intersect_rect.intersectWith(dst_textp->mSoftScreenRect);
-					intersect_rect.stretch(-BUFFER_SIZE * 0.5f);
-					
-					F32 src_center_x = src_textp->mSoftScreenRect.getCenterX();
-					F32 src_center_y = src_textp->mSoftScreenRect.getCenterY();
-					F32 dst_center_x = dst_textp->mSoftScreenRect.getCenterX();
-					F32 dst_center_y = dst_textp->mSoftScreenRect.getCenterY();
-					F32 intersect_center_x = intersect_rect.getCenterX();
-					F32 intersect_center_y = intersect_rect.getCenterY();
-					LLVector2 force = lerp(LLVector2(dst_center_x - intersect_center_x, dst_center_y - intersect_center_y), 
-										LLVector2(intersect_center_x - src_center_x, intersect_center_y - src_center_y),
-										0.5f);
-					force.setVec(dst_center_x - src_center_x, dst_center_y - src_center_y);
-					force.normVec();
-
-					LLVector2 src_force = -1.f * force;
-					LLVector2 dst_force = force;
-
-					LLVector2 force_strength;
-					F32 src_mult = dst_textp->mMass / (dst_textp->mMass + src_textp->mMass); 
-					F32 dst_mult = 1.f - src_mult;
-					F32 src_aspect_ratio = src_textp->mSoftScreenRect.getWidth() / src_textp->mSoftScreenRect.getHeight();
-					F32 dst_aspect_ratio = dst_textp->mSoftScreenRect.getWidth() / dst_textp->mSoftScreenRect.getHeight();
-					src_force.mV[VY] *= src_aspect_ratio;
-					src_force.normVec();
-					dst_force.mV[VY] *= dst_aspect_ratio;
-					dst_force.normVec();
-
-					src_force.mV[VX] *= llmin(intersect_rect.getWidth() * src_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
-					src_force.mV[VY] *= llmin(intersect_rect.getHeight() * src_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
-					dst_force.mV[VX] *=  llmin(intersect_rect.getWidth() * dst_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
-					dst_force.mV[VY] *=  llmin(intersect_rect.getHeight() * dst_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
-					
-					src_textp->mTargetPositionOffset += src_force;
-					dst_textp->mTargetPositionOffset += dst_force;
-					src_textp->mTargetPositionOffset = src_textp->updateScreenPos(src_textp->mTargetPositionOffset);
-					dst_textp->mTargetPositionOffset = dst_textp->updateScreenPos(dst_textp->mTargetPositionOffset);
-				}
-			}
-		}
-	}
-
-	VisibleTextObjectIterator this_object_it;
-	for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it)
-	{
-		if (!(*this_object_it)->mUseBubble)
-		{
-			continue;
-		}
-		(*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC));
-	}
 }
 
-void LLHUDText::setLOD(S32 lod)
-{
-	mLOD = lod;
-	//RN: uncomment this to visualize LOD levels
-	//std::string label = llformat("%d", lod);
-	//setLabel(label);
-}
+//void LLHUDText::setLOD(S32 lod)
+//{
+//	mLOD = lod;
+//	//RN: uncomment this to visualize LOD levels
+//	//std::string label = llformat("%d", lod);
+//	//setLabel(label);
+//}
 
 S32 LLHUDText::getMaxLines()
 {
-	switch(mLOD)
-	{
-	case 0:
-		return mMaxLines;
-	case 1:
-		return mMaxLines > 0 ? mMaxLines / 2 : 5;
-	case 2:
-		return mMaxLines > 0 ? mMaxLines / 3 : 2;
-	default:
-		// label only
-		return 0;
-	}
+	return mMaxLines;
+	//switch(mLOD)
+	//{
+	//case 0:
+	//	return mMaxLines;
+	//case 1:
+	//	return mMaxLines > 0 ? mMaxLines / 2 : 5;
+	//case 2:
+	//	return mMaxLines > 0 ? mMaxLines / 3 : 2;
+	//default:
+	//	// label only
+	//	return 0;
+	//}
 }
 
 void LLHUDText::markDead()
@@ -1079,22 +622,6 @@ void LLHUDText::shift(const LLVector3& offset)
 	mPositionAgent += offset;
 }
 
-//static 
-void LLHUDText::addPickable(std::set<LLViewerObject*> &pick_list)
-{
-	//this might put an object on the pick list a second time, overriding it's mGLName, which is ok
-	// *FIX: we should probably cull against pick frustum
-	VisibleTextObjectIterator text_it;
-	for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it)
-	{
-		if (!(*text_it)->mUseBubble)
-		{
-			continue;
-		}
-		pick_list.insert((*text_it)->mSourceObject);
-	}
-}
-
 //static
 // called when UI scale changes, to flush font width caches
 void LLHUDText::reshape()
@@ -1109,11 +636,6 @@ void LLHUDText::reshape()
 		{
 			segment_iter->clearFontWidthMap();
 		}
-		for(segment_iter = textp->mLabelSegments.begin();
-			segment_iter != textp->mLabelSegments.end(); ++segment_iter )
-		{
-			segment_iter->clearFontWidthMap();
-		}		
 	}
 }
 
diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h
index 4f4ee55a614a8cb503d711122ce415b5bb135cef..f05ee4d594858ac446c33d704f495999944fcf4d 100644
--- a/indra/newview/llhudtext.h
+++ b/indra/newview/llhudtext.h
@@ -28,18 +28,15 @@
 #define LL_LLHUDTEXT_H
 
 #include "llpointer.h"
-#include "lldarrayptr.h"
 
 #include "llhudobject.h"
 #include "v4color.h"
 #include "v4coloru.h"
 #include "v2math.h"
 #include "llrect.h"
-#include "llframetimer.h"
 #include "llfontgl.h"
 #include <set>
 #include <vector>
-#include "lldarray.h"
 
 // Renders a 2D text billboard floating at the location specified.
 class LLDrawable;
@@ -56,14 +53,19 @@ class LLHUDText : public LLHUDObject
 	class LLHUDTextSegment
 	{
 	public:
-		LLHUDTextSegment(const LLWString& text, const LLFontGL::StyleFlags style, const LLColor4& color)
-			: mColor(color), mStyle(style), mText(text) {}
+		LLHUDTextSegment(const LLWString& text, const LLFontGL::StyleFlags style, const LLColor4& color, const LLFontGL* font)
+		:	mColor(color),
+			mStyle(style),
+			mText(text),
+			mFont(font)
+		{}
 		F32 getWidth(const LLFontGL* font);
-		const LLWString& getText() const { return mText; };
+		const LLWString& getText() const { return mText; }
 		void clearFontWidthMap() { mFontWidthMap.clear(); }
 		
 		LLColor4				mColor;
 		LLFontGL::StyleFlags	mStyle;
+		const LLFontGL*			mFont;
 	private:
 		LLWString				mText;
 		std::map<const LLFontGL*, F32> mFontWidthMap;
@@ -83,20 +85,21 @@ class LLHUDText : public LLHUDObject
 	} EVertAlignment;
 
 public:
-	void setStringUTF8(const std::string &utf8string);
-	void setString(const LLWString &wstring);
+	// Set entire string, eliminating existing lines
+	void setString(const std::string& text_utf8);
+
 	void clearString();
-	void addLine(const std::string &text, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL);
-	void addLine(const LLWString &wtext, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL);
-	void setLabel(const std::string &label);
-	void setLabel(const LLWString &label);
-	void setDropShadow(const BOOL do_shadow);
+
+	// Add text a line at a time, allowing custom formatting
+	void addLine(const std::string &text_utf8, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL, const LLFontGL* font = NULL);
+
+	// Sets the default font for lines with no font specified
 	void setFont(const LLFontGL* font);
 	void setColor(const LLColor4 &color);
-	void setUsePixelSize(const BOOL use_pixel_size);
+	void setAlpha(F32 alpha);
 	void setZCompare(const BOOL zcompare);
 	void setDoFade(const BOOL do_fade);
-	void setVisibleOffScreen(BOOL visible) { mVisibleOffScreen = visible; }
+//	void setVisibleOffScreen(BOOL visible) { mVisibleOffScreen = visible; }
 	
 	// mMaxLines of -1 means unlimited lines.
 	void setMaxLines(S32 max_lines) { mMaxLines = max_lines; }
@@ -110,21 +113,17 @@ class LLHUDText : public LLHUDObject
 	/*virtual*/ void markDead();
 	friend class LLHUDObject;
 	/*virtual*/ F32 getDistance() const { return mLastDistance; }
-	void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; }
-	S32  getLOD() { return mLOD; }
 	BOOL getVisible() { return mVisible; }
 	BOOL getHidden() const { return mHidden; }
 	void setHidden( BOOL hide ) { mHidden = hide; }
 	void setOnHUDAttachment(BOOL on_hud) { mOnHUDAttachment = on_hud; }
 	void shift(const LLVector3& offset);
 
-	BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render = FALSE);
-
 	static void shiftAll(const LLVector3& offset);
 	static void renderAllHUD();
-	static void addPickable(std::set<LLViewerObject*> &pick_list);
 	static void reshape();
 	static void setDisplayText(BOOL flag) { sDisplayText = flag ; }
+
 protected:
 	LLHUDText(const U8 type);
 
@@ -132,21 +131,17 @@ class LLHUDText : public LLHUDObject
 	/*virtual*/ void renderForSelect();
 	void renderText(BOOL for_select);
 	static void updateAll();
-	void setLOD(S32 lod);
 	S32 getMaxLines();
 
 private:
 	~LLHUDText();
-	BOOL			mOnHUD;
-	BOOL			mUseBubble;
-	BOOL			mDropShadow;
+	BOOL			mOnHUDAttachment;
 	BOOL			mDoFade;
 	F32				mFadeRange;
 	F32				mFadeDistance;
 	F32				mLastDistance;
-	BOOL			mUsePixelSize;
 	BOOL			mZCompare;
-	BOOL			mVisibleOffScreen;
+//	BOOL			mVisibleOffScreen;
 	BOOL			mOffscreen;
 	LLColor4		mColor;
 	LLVector3		mScale;
@@ -164,11 +159,8 @@ class LLHUDText : public LLHUDObject
 	S32				mOffsetY;
 	F32				mRadius;
 	std::vector<LLHUDTextSegment> mTextSegments;
-	std::vector<LLHUDTextSegment> mLabelSegments;
-	LLFrameTimer	mResizeTimer;
 	ETextAlignment	mTextAlignment;
 	EVertAlignment	mVertAlignment;
-	S32				mLOD;
 	BOOL			mHidden;
 
 	static BOOL    sDisplayText ;
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 658e9403d874a85666980fe8c7d204e83f992910..66cd76e57b20bb4a81ee738e301d2c82ce376519 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -32,6 +32,7 @@
 
 #include "llagent.h"
 #include "llappviewer.h"
+#include "llavatarnamecache.h"
 #include "llbutton.h"
 #include "llbottomtray.h"
 #include "llchannelmanager.h"
@@ -275,12 +276,6 @@ BOOL LLIMFloater::postBuild()
 	mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
 	mInputEditor->setPassDelete( TRUE );
 
-	std::string session_name(LLIMModel::instance().getName(mSessionID));
-
-	mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + session_name);
-
-	setTitle(session_name);
-
 	childSetCommitCallback("chat_editor", onSendMsg, this);
 	
 	mChatHistory = getChild<LLChatHistory>("chat_history");
@@ -298,6 +293,19 @@ BOOL LLIMFloater::postBuild()
 		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
 	}
 
+	if ( im_session && im_session->isP2PSessionType())
+	{
+		// look up display name for window title
+		LLAvatarNameCache::get(im_session->mOtherParticipantID,
+							   boost::bind(&LLIMFloater::onAvatarNameCache,
+										   this, _1, _2));
+	}
+	else
+	{
+		std::string session_name(LLIMModel::instance().getName(mSessionID));
+		updateSessionName(session_name, session_name);
+	}
+	
 	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
 	//see LLFloaterIMPanel for how it is done (IB)
 
@@ -311,6 +319,23 @@ BOOL LLIMFloater::postBuild()
 	}
 }
 
+void LLIMFloater::updateSessionName(const std::string& ui_title,
+									const std::string& ui_label)
+{
+	mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label);
+	setTitle(ui_title);	
+}
+
+void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,
+									const LLAvatarName& av_name)
+{
+	// Use display name only for labels, as the extended name will be in the
+	// floater title
+	std::string ui_title = av_name.getCompleteName();
+	updateSessionName(ui_title, av_name.mDisplayName);
+	mTypingStart.setArg("[NAME]", ui_title);
+}
+
 // virtual
 void LLIMFloater::draw()
 {
@@ -1071,13 +1096,9 @@ void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)
 	{
 		mOtherTyping = true;
 
-		// Create typing is started title string
-		LLUIString typing_start(mTypingStart);
-		typing_start.setArg("[NAME]", im_info->mName);
-
 		// Save and set new title
 		mSavedTitle = getTitle();
-		setTitle (typing_start);
+		setTitle (mTypingStart);
 
 		// Update speaker
 		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index e604623b1bbf9156161ecfedd3c01928e73a1025..e80e45e64ae8c48fd3f56ad5cce0dfe5eb6c9aea 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -32,6 +32,7 @@
 #include "lltooldraganddrop.h"
 #include "lltransientdockablefloater.h"
 
+class LLAvatarName;
 class LLLineEditor;
 class LLPanelChatControlPanel;
 class LLChatHistory;
@@ -124,6 +125,12 @@ class LLIMFloater : public LLTransientDockableFloater
 	/* virtual */ void onFocusLost();
 	/* virtual */ void onFocusReceived();
 
+	// Update the window title, input field help text, etc.
+	void updateSessionName(const std::string& ui_title, const std::string& ui_label);
+	
+	// For display name lookups for IM window titles
+	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
+	
 	BOOL dropCallingCard(LLInventoryItem* item, BOOL drop);
 	BOOL dropCategory(LLInventoryCategory* category, BOOL drop);
 
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 129c9aec142de34d4d4392368a8aa9068b4d0a3b..070e384fa422e68a21f649a7405bea05e478f2ec 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -28,6 +28,7 @@
 
 #include "llimview.h"
 
+#include "llavatarnamecache.h"	// IDEVO
 #include "llfloaterreg.h"
 #include "llfontgl.h"
 #include "llgl.h"
@@ -64,11 +65,6 @@
 #include "llviewerparcelmgr.h"
 
 
-const static std::string IM_TIME("time");
-const static std::string IM_TEXT("message");
-const static std::string IM_FROM("from");
-const static std::string IM_FROM_ID("from_id");
-
 const static std::string NO_SESSION("(IM Session Doesn't Exist)");
 const static std::string ADHOC_NAME_SUFFIX(" Conference");
 
@@ -102,6 +98,20 @@ BOOL LLSessionTimeoutTimer::tick()
 	return TRUE;
 }
 
+static void on_avatar_name_cache_toast(const LLUUID& agent_id,
+									   const LLAvatarName& av_name,
+									   LLSD msg)
+{
+	LLSD args;
+	args["MESSAGE"] = msg["message"];
+	args["TIME"] = msg["time"];
+	// *TODO: Can this ever be an object name or group name?
+	args["FROM"] = av_name.getCompleteName();
+	args["FROM_ID"] = msg["from_id"];
+	args["SESSION_ID"] = msg["session_id"];
+	LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
+}
+
 void toast_callback(const LLSD& msg){
 	// do not show toast in busy mode or it goes from agent
 	if (gAgent.getBusy() || gAgent.getID() == msg["from_id"])
@@ -129,14 +139,9 @@ void toast_callback(const LLSD& msg){
 		return;
 	}
 
-	LLSD args;
-	args["MESSAGE"] = msg["message"];
-	args["TIME"] = msg["time"];
-	args["FROM"] = msg["from"];
-	args["FROM_ID"] = msg["from_id"];
-	args["SESSION_ID"] = msg["session_id"];
-
-	LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
+	LLAvatarNameCache::get(msg["from_id"].asUUID(),
+		boost::bind(&on_avatar_name_cache_toast,
+			_1, _2, msg));
 }
 
 void LLIMModel::setActiveSessionID(const LLUUID& session_id)
@@ -282,7 +287,7 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES
 		// no text notifications
 		break;
 	case P2P_SESSION:
-		gCacheName->getFullName(mOtherParticipantID, other_avatar_name);
+		gCacheName->getFullName(mOtherParticipantID, other_avatar_name); // voice
 
 		if(direction == LLVoiceChannel::INCOMING_CALL)
 		{
@@ -417,13 +422,17 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list<LLSD>& histo
 		const LLSD& msg = *it;
 
 		std::string from = msg[IM_FROM];
-		LLUUID from_id = LLUUID::null;
-		if (msg[IM_FROM_ID].isUndefined())
+		LLUUID from_id;
+		if (msg[IM_FROM_ID].isDefined())
+		{
+			from_id = msg[IM_FROM_ID].asUUID();
+		}
+		else
 		{
+			// Legacy chat logs only wrote the legacy name, not the agent_id
 			gCacheName->getUUID(from, from_id);
 		}
 
-
 		std::string timestamp = msg[IM_TIME];
 		std::string text = msg[IM_TEXT];
 
@@ -1754,11 +1763,23 @@ void LLOutgoingCallDialog::show(const LLSD& key)
 		callee_name = LLTextUtil::formatPhoneNumber(callee_name);
 	}
 	
-	setTitle(callee_name);
-
 	LLSD callee_id = mPayload["other_user_id"];
-	getChild<LLUICtrl>("calling")->setTextArg("[CALLEE_NAME]", callee_name);
-	getChild<LLUICtrl>("connecting")->setTextArg("[CALLEE_NAME]", callee_name);
+	// Beautification:  Since you know who you called, just show display name
+	std::string title = callee_name;
+	std::string final_callee_name = callee_name;
+	if (mPayload["session_type"].asInteger() == LLIMModel::LLIMSession::P2P_SESSION)
+	{
+		LLAvatarName av_name;
+		if (LLAvatarNameCache::get(callee_id, &av_name))
+		{
+			final_callee_name = av_name.mDisplayName;
+			title = av_name.getCompleteName();
+		}
+	}
+	getChild<LLUICtrl>("calling")->setTextArg("[CALLEE_NAME]", final_callee_name);
+	getChild<LLUICtrl>("connecting")->setTextArg("[CALLEE_NAME]", final_callee_name);
+
+	setTitle(title);
 
 	// for outgoing group calls callee_id == group id == session id
 	setIcon(callee_id, callee_id);
@@ -1913,16 +1934,21 @@ BOOL LLIncomingCallDialog::postBuild()
 	if (caller_name == "anonymous")
 	{
 		caller_name = getString("anonymous");
+		setCallerName(caller_name, caller_name, call_type);
 	}
 	else if (!is_avatar)
 	{
 		caller_name = LLTextUtil::formatPhoneNumber(caller_name);
+		setCallerName(caller_name, caller_name, call_type);
+	}
+	else
+	{
+		// Get the full name information
+		LLAvatarNameCache::get(caller_id,
+			boost::bind(&LLIncomingCallDialog::onAvatarNameCache,
+				this, _1, _2, call_type));
 	}
 
-	setTitle(caller_name + " " + call_type);
-
-	LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
-	caller_name_widget->setValue(caller_name + " " + call_type);
 	setIcon(session_id, caller_id);
 
 	childSetAction("Accept", onAccept, this);
@@ -1950,6 +1976,24 @@ BOOL LLIncomingCallDialog::postBuild()
 	return TRUE;
 }
 
+void LLIncomingCallDialog::setCallerName(const std::string& ui_title,
+										 const std::string& ui_label,
+										 const std::string& call_type)
+{
+	setTitle(ui_title);
+
+	// call_type may be a string like " is calling."
+	LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
+	caller_name_widget->setValue(ui_label + " " + call_type);
+}
+
+void LLIncomingCallDialog::onAvatarNameCache(const LLUUID& agent_id,
+											 const LLAvatarName& av_name,
+											 const std::string& call_type)
+{
+	std::string title = av_name.getCompleteName();
+	setCallerName(title, av_name.mDisplayName, call_type);
+}
 
 void LLIncomingCallDialog::onOpen(const LLSD& key)
 {
@@ -2057,8 +2101,11 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
 					}
 					else
 					{
-						if (gCacheName->getFullName(caller_id, correct_session_name))
+						// *NOTE: really should be using callbacks here
+						LLAvatarName av_name;
+						if (LLAvatarNameCache::get(caller_id, &av_name))
 						{
+							correct_session_name = av_name.mDisplayName + " (" + av_name.mUsername + ")";
 							correct_session_name.append(ADHOC_NAME_SUFFIX); 
 						}
 					}
@@ -2579,7 +2626,8 @@ void LLIMMgr::inviteToSession(
 	{
 		if (caller_name.empty())
 		{
-			gCacheName->get(caller_id, FALSE, boost::bind(&LLIMMgr::onInviteNameLookup, payload, _1, _2, _3, _4));
+			gCacheName->get(caller_id, false,  // voice
+				boost::bind(&LLIMMgr::onInviteNameLookup, payload, _1, _2, _3));
 		}
 		else
 		{
@@ -2589,9 +2637,9 @@ void LLIMMgr::inviteToSession(
 	}
 }
 
-void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group)
 {
-	payload["caller_name"] = first + " " + last;
+	payload["caller_name"] = name;
 	payload["session_name"] = payload["caller_name"].asString();
 
 	std::string notify_box_type = payload["notify_box_type"].asString();
@@ -2812,13 +2860,14 @@ void LLIMMgr::noteOfflineUsers(
 		for(S32 i = 0; i < count; ++i)
 		{
 			info = at.getBuddyInfo(ids.get(i));
-			std::string first, last;
-			if(info && !info->isOnline()
-			   && gCacheName->getName(ids.get(i), first, last))
+			LLAvatarName av_name;
+			if (info
+				&& !info->isOnline()
+				&& LLAvatarNameCache::get(ids.get(i), &av_name))
 			{
 				LLUIString offline = LLTrans::getString("offline_message");
-				offline.setArg("[FIRST]", first);
-				offline.setArg("[LAST]", last);
+				// Use display name only because this user is your friend
+				offline.setArg("[NAME]", av_name.mDisplayName);
 				im_model.proccessOnlineOfflineNotification(session_id, offline);
 			}
 		}
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 4ce94773bf296b4d2158c9db1ec6cdcf000ff6d8..c95f98f5524cf3d90c502a66e4cc77b9c8fbd701 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -35,7 +35,7 @@
 #include "llvoicechannel.h"
 
 
-
+class LLAvatarName;
 class LLFriendObserver;
 class LLCallDialogManager;	
 class LLIMSpeakerMgr;
@@ -453,7 +453,7 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 
 	void processIMTypingCore(const LLIMInfo* im_info, BOOL typing);
 
-	static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+	static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group);
 
 	void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
 	void notifyObserverSessionRemoved(const LLUUID& session_id);
@@ -535,6 +535,13 @@ class LLIncomingCallDialog : public LLCallDialog
 	static void onStartIM(void* user_data);
 
 private:
+	void setCallerName(const std::string& ui_title,
+		const std::string& ui_label,
+		const std::string& call_type);
+	void onAvatarNameCache(const LLUUID& agent_id,
+		const LLAvatarName& av_name,
+		const std::string& call_type);
+
 	/*virtual*/ void onLifetimeExpired();
 	void processCallResponse(S32 response);
 };
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index b367d68b02ade89eebcaa59aaa23fb86225bf1fa..29dcb2c4d3a89beb0573aea6decb7c7902c8af67 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -31,6 +31,7 @@
 #include "llagent.h"
 #include "llagentdata.h"
 #include "llavataractions.h"
+#include "llavatarnamecache.h"
 #include "llavatarpropertiesprocessor.h"
 #include "llcallingcard.h"
 #include "lldateutil.h"
@@ -51,6 +52,7 @@
 #include "llfloater.h"
 #include "llfloaterreg.h"
 #include "llmenubutton.h"
+#include "lltextbox.h"
 #include "lltooltip.h"	// positionViewNearMouse()
 #include "lltrans.h"
 #include "lluictrl.h"
@@ -137,17 +139,13 @@ class LLInspectAvatar : public LLInspect, LLTransientFloater
 	// Is used to determine if "Add friend" option should be enabled in gear menu
 	bool isNotFriend();
 	
-	// Callback for gCacheName to look up avatar name
-	void nameUpdatedCallback(
-							 const LLUUID& id,
-							 const std::string& first,
-							 const std::string& last,
-							 BOOL is_group);
+	void onAvatarNameCache(const LLUUID& agent_id,
+						   const LLAvatarName& av_name);
 	
 private:
 	LLUUID				mAvatarID;
 	// Need avatar name information to spawn friend add request
-	std::string			mAvatarName;
+	LLAvatarName		mAvatarName;
 	// an in-flight request for avatar properties from LLAvatarPropertiesProcessor
 	// is represented by this object
 	LLFetchAvatarData*	mPropertiesRequest;
@@ -330,6 +328,8 @@ void LLInspectAvatar::requestUpdate()
 
 	// Clear out old data so it doesn't flash between old and new
 	getChild<LLUICtrl>("user_name")->setValue("");
+	getChild<LLUICtrl>("user_name_small")->setValue("");
+	getChild<LLUICtrl>("user_slid")->setValue("");
 	getChild<LLUICtrl>("user_subtitle")->setValue("");
 	getChild<LLUICtrl>("user_details")->setValue("");
 	
@@ -367,9 +367,9 @@ void LLInspectAvatar::requestUpdate()
 
 	getChild<LLUICtrl>("avatar_icon")->setValue(LLSD(mAvatarID) );
 
-	gCacheName->get(mAvatarID, FALSE,
-		boost::bind(&LLInspectAvatar::nameUpdatedCallback,
-			this, _1, _2, _3, _4));
+	LLAvatarNameCache::get(mAvatarID,
+			boost::bind(&LLInspectAvatar::onAvatarNameCache,
+				this, _1, _2));
 }
 
 void LLInspectAvatar::processAvatarData(LLAvatarData* data)
@@ -556,7 +556,7 @@ void LLInspectAvatar::updateVolumeSlider()
 
 		LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn");
 
-		bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden");
+		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden");
 
 		mute_btn->setEnabled( !is_linden);
 		mute_btn->setValue( is_muted );
@@ -587,7 +587,7 @@ void LLInspectAvatar::onClickMuteVolume()
 	LLMuteList* mute_list = LLMuteList::getInstance();
 	bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat);
 
-	LLMute mute(mAvatarID, mAvatarName, LLMute::AGENT);
+	LLMute mute(mAvatarID, mAvatarName.getLegacyName(), LLMute::AGENT);
 	if (!is_muted)
 	{
 		mute_list->add(mute, LLMute::flagVoiceChat);
@@ -606,22 +606,36 @@ void LLInspectAvatar::onVolumeChange(const LLSD& data)
 	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume);
 }
 
-void LLInspectAvatar::nameUpdatedCallback(
-	const LLUUID& id,
-	const std::string& first,
-	const std::string& last,
-	BOOL is_group)
+void LLInspectAvatar::onAvatarNameCache(
+		const LLUUID& agent_id,
+		const LLAvatarName& av_name)
 {
-	if (id == mAvatarID)
+	if (agent_id == mAvatarID)
 	{
-		mAvatarName = first + " " + last;
-		getChild<LLUICtrl>("user_name")->setValue(LLSD(mAvatarName) );
+		getChild<LLUICtrl>("user_name")->setValue(av_name.mDisplayName);
+		getChild<LLUICtrl>("user_name_small")->setValue(av_name.mDisplayName);
+		getChild<LLUICtrl>("user_slid")->setValue(av_name.mUsername);
+		mAvatarName = av_name;
+		
+		// show smaller display name if too long to display in regular size
+		if (getChild<LLTextBox>("user_name")->getTextPixelWidth() > getChild<LLTextBox>("user_name")->getRect().getWidth())
+		{
+			getChild<LLUICtrl>("user_name_small")->setVisible( true );
+			getChild<LLUICtrl>("user_name")->setVisible( false );
+		}
+		else
+		{
+			getChild<LLUICtrl>("user_name_small")->setVisible( false );
+			getChild<LLUICtrl>("user_name")->setVisible( true );
+
+		}
+
 	}
 }
 
 void LLInspectAvatar::onClickAddFriend()
 {
-	LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName);
+	LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName.getLegacyName());
 	closeFloater();
 }
 
@@ -689,7 +703,7 @@ void LLInspectAvatar::onClickShare()
 
 void LLInspectAvatar::onToggleMute()
 {
-	LLMute mute(mAvatarID, mAvatarName, LLMute::AGENT);
+	LLMute mute(mAvatarID, mAvatarName.getLegacyName(), LLMute::AGENT);
 
 	if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
 	{
@@ -706,7 +720,7 @@ void LLInspectAvatar::onToggleMute()
 
 void LLInspectAvatar::onClickReport()
 {
-	LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName);
+	LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName.getCompleteName());
 	closeFloater();
 }
 
@@ -730,17 +744,17 @@ void LLInspectAvatar::onClickZoomIn()
 
 void LLInspectAvatar::onClickFindOnMap()
 {
-	gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName);
+	gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName.mDisplayName);
 	LLFloaterReg::showInstance("world_map");
 }
 
 
 bool LLInspectAvatar::enableMute()
 {
-		bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden");
+		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden");
 		bool is_self = mAvatarID == gAgent.getID();
 
-		if (!is_linden && !is_self && !LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName))
+		if (!is_linden && !is_self && !LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName()))
 		{
 			return true;
 		}
@@ -752,10 +766,10 @@ bool LLInspectAvatar::enableMute()
 
 bool LLInspectAvatar::enableUnmute()
 {
-		bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden");
+		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden");
 		bool is_self = mAvatarID == gAgent.getID();
 
-		if (!is_linden && !is_self && LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName))
+		if (!is_linden && !is_self && LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName()))
 		{
 			return true;
 		}
diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp
index 214b135bc1f02e01a7d8cd1d9a3a35a0b724d17e..76617b55bf28b4e32e527799b5fe46feb377057c 100644
--- a/indra/newview/llinspectgroup.cpp
+++ b/indra/newview/llinspectgroup.cpp
@@ -78,9 +78,8 @@ class LLInspectGroup : public LLInspect
 	// Callback for gCacheName to look up group name
 	// Faster than waiting for group properties to return
 	void nameUpdatedCallback(const LLUUID& id,
-							 const std::string& first,
-							 const std::string& last,
-							 BOOL is_group);
+							 const std::string& name,
+							 bool is_group);
 
 	// Button/menu callbacks
 	void onClickViewProfile();
@@ -219,21 +218,19 @@ void LLInspectGroup::requestUpdate()
 	mPropertiesRequest = new LLFetchGroupData(mGroupID, this);
 
 	// Name lookup will be faster out of cache, use that
-	gCacheName->get(mGroupID, TRUE,
+	gCacheName->getGroup(mGroupID,
 		boost::bind(&LLInspectGroup::nameUpdatedCallback,
-			this, _1, _2, _3, _4));
+			this, _1, _2, _3));
 }
 
 void LLInspectGroup::nameUpdatedCallback(
 	const LLUUID& id,
-	const std::string& first,
-	const std::string& last,
-	BOOL is_group)
+	const std::string& name,
+	bool is_group)
 {
 	if (id == mGroupID)
 	{
-		// group names are returned as a first name
-		getChild<LLUICtrl>("group_name")->setValue(LLSD(first) );
+		getChild<LLUICtrl>("group_name")->setValue( LLSD(name) );
 	}
 	
 	// Otherwise possibly a request for an older inspector, ignore it
diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp
index e956b3b8dec81bf600bef7a8358e23588f457c70..bf6cf5229803ce02c32823e64e02e731dde3512a 100644
--- a/indra/newview/llinspectremoteobject.cpp
+++ b/indra/newview/llinspectremoteobject.cpp
@@ -60,12 +60,12 @@ class LLInspectRemoteObject : public LLInspect
 	
 private:
 	void update();
-	static void nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data);
+	void onNameCache(const LLUUID& id, const std::string& name, bool is_group);
 	
 private:
 	LLUUID		 mObjectID;
 	LLUUID		 mOwnerID;
-	std::string  mOwner;
+	std::string  mOwnerLegacyName;
 	std::string  mSLurl;
 	std::string  mName;
 	bool         mGroupOwned;
@@ -75,7 +75,7 @@ LLInspectRemoteObject::LLInspectRemoteObject(const LLSD& sd) :
 	LLInspect(LLSD()),
 	mObjectID(NULL),
 	mOwnerID(NULL),
-	mOwner(""),
+	mOwnerLegacyName(),
 	mSLurl(""),
 	mName(""),
 	mGroupOwned(false)
@@ -112,10 +112,11 @@ void LLInspectRemoteObject::onOpen(const LLSD& data)
 	mSLurl      = data["slurl"].asString();
 
 	// work out the owner's name
-	mOwner = "";
+	mOwnerLegacyName = "";
 	if (gCacheName)
 	{
-		gCacheName->get(mOwnerID, mGroupOwned, nameCallback, this);
+		gCacheName->get(mOwnerID, mGroupOwned,  // muting
+			boost::bind(&LLInspectRemoteObject::onNameCache, this, _1, _2, _3));
 	}
 
 	// update the inspector with the current object state
@@ -144,7 +145,7 @@ void LLInspectRemoteObject::onClickMap()
 void LLInspectRemoteObject::onClickBlock()
 {
 	LLMute::EType mute_type = mGroupOwned ? LLMute::GROUP : LLMute::AGENT;
-	LLMute mute(mOwnerID, mOwner, mute_type);
+	LLMute mute(mOwnerID, mOwnerLegacyName, mute_type);
 	LLMuteList::getInstance()->add(mute);
 	LLPanelBlockedList::showPanelAndSelect(mute.mID);
 	closeFloater();
@@ -155,16 +156,10 @@ void LLInspectRemoteObject::onClickClose()
 	closeFloater();
 }
 
-//static 
-void LLInspectRemoteObject::nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data)
+void LLInspectRemoteObject::onNameCache(const LLUUID& id, const std::string& name, bool is_group)
 {
-	LLInspectRemoteObject *self = (LLInspectRemoteObject*)data;
-	self->mOwner = first;
-	if (!last.empty())
-	{
-		self->mOwner += " " + last;
-	}
-	self->update();
+	mOwnerLegacyName = name;
+	update();
 }
 
 void LLInspectRemoteObject::update()
@@ -174,7 +169,7 @@ void LLInspectRemoteObject::update()
 	getChild<LLUICtrl>("object_name")->setValue("<nolink>" + mName + "</nolink>");
 
 	// show the object's owner - click it to show profile
-	std::string owner = mOwner;
+	std::string owner;
 	if (! mOwnerID.isNull())
 	{
 		if (mGroupOwned)
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index aff0bc409976dc0b8f3dc47dac7e48a6b300d7a1..af823852d5a674bb2d1aebeb398530682078e8ab 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -29,6 +29,7 @@
 
 // external projects
 #include "lltransfersourceasset.h"
+#include "llavatarnamecache.h"	// IDEVO
 
 #include "llagent.h"
 #include "llagentcamera.h"
@@ -3450,6 +3451,13 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act
 		{
 			std::string callingcard_name;
 			gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
+			// IDEVO
+			LLAvatarName av_name;
+			if (LLAvatarNameCache::useDisplayNames()
+				&& LLAvatarNameCache::get(item->getCreatorUUID(), &av_name))
+			{
+				callingcard_name = av_name.mDisplayName + " (" + av_name.mUsername + ")";
+			}
 			LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
 			if (session_id != LLUUID::null)
 			{
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index f5f4feeab3e21970b5da003aa199082e75fb9573..c8fd1e1d9aa0a9fd2c88202fc0c1a224fec9cdda 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -26,13 +26,18 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "lllogchat.h"
+
+// viewer includes
 #include "llagent.h"
 #include "llagentui.h"
-#include "lllogchat.h"
 #include "lltrans.h"
 #include "llviewercontrol.h"
 
+// library includes
+#include "llchat.h"
 #include "llinstantmessage.h"
+#include "llsdserialize.h"
 #include "llsingleton.h" // for LLSingleton
 
 #include <boost/algorithm/string/trim.hpp>
@@ -56,12 +61,13 @@
 
 const S32 LOG_RECALL_SIZE = 2048;
 
-const static std::string IM_TIME("time");
-const static std::string IM_TEXT("message");
-const static std::string IM_FROM("from");
-const static std::string IM_FROM_ID("from_id");
-const static std::string IM_SEPARATOR(": ");
+const std::string IM_TIME("time");
+const std::string IM_TEXT("message");
+const std::string IM_FROM("from");
+const std::string IM_FROM_ID("from_id");
+const std::string IM_SOURCE_TYPE("source_type");
 
+const static std::string IM_SEPARATOR(": ");
 const static std::string NEW_LINE("\n");
 const static std::string NEW_LINE_SPACE_PREFIX("\n ");
 const static std::string TWO_SPACES("  ");
@@ -184,7 +190,8 @@ std::string LLLogChat::makeLogFileName(std::string filename)
 {
 	filename = cleanFileName(filename);
 	filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename);
-	filename += ".txt";
+	// new files are llsd notation format
+	filename += ".llsd";
 	return filename;
 }
 
@@ -233,6 +240,18 @@ void LLLogChat::saveHistory(const std::string& filename,
 			    const std::string& from,
 			    const LLUUID& from_id,
 			    const std::string& line)
+{
+	LLChat chat;
+	chat.mText = line;
+	chat.mFromName = from;
+	chat.mFromID = from_id;
+	// default to being from an agent
+	chat.mSourceType = CHAT_SOURCE_AGENT;
+	saveHistory(filename, chat);
+}
+
+//static
+void LLLogChat::saveHistory(const std::string& filename, const LLChat& chat)
 {
 	std::string tmp_filename = filename;
 	LLStringUtil::trim(tmp_filename);
@@ -254,89 +273,27 @@ void LLLogChat::saveHistory(const std::string& filename,
 	LLSD item;
 
 	if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
-		 item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
+		 item[IM_TIME] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
 
-	item["from_id"]	= from_id;
-	item["message"]	= line;
+	item[IM_FROM_ID] = chat.mFromID;
+	item[IM_TEXT] = chat.mText;
+	item[IM_SOURCE_TYPE] = chat.mSourceType;
 
 	//adding "Second Life:" for all system messages to make chat log history parsing more reliable
-	if (from.empty() && from_id.isNull())
+	if (chat.mFromName.empty() && chat.mFromID.isNull())
 	{
-		item["from"] = SYSTEM_FROM; 
+		item[IM_FROM] = SYSTEM_FROM; 
 	}
 	else
 	{
-		item["from"] = from;
+		item[IM_FROM] = chat.mFromName;
 	}
 
-	file << LLChatLogFormatter(item) << std::endl;
+	file << LLSDOStreamer<LLSDNotationFormatter>(item) << std::endl;
 
 	file.close();
 }
 
-void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata)
-{
-	if(!filename.size())
-	{
-		llwarns << "Filename is Empty!" << llendl;
-		return ;
-	}
-        
-	LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r");		/*Flawfinder: ignore*/
-	if (!fptr)
-	{
-		callback(LOG_EMPTY, LLSD(), userdata);
-		return;			//No previous conversation with this name.
-	}
-	else
-	{
-		char buffer[LOG_RECALL_SIZE];		/*Flawfinder: ignore*/
-		char *bptr;
-		S32 len;
-		bool firstline=TRUE;
-
-		if ( fseek(fptr, (LOG_RECALL_SIZE - 1) * -1  , SEEK_END) )		
-		{	//File is smaller than recall size.  Get it all.
-			firstline = FALSE;
-			if ( fseek(fptr, 0, SEEK_SET) )
-			{
-				fclose(fptr);
-				return;
-			}
-		}
-
-		while ( fgets(buffer, LOG_RECALL_SIZE, fptr)  && !feof(fptr) ) 
-		{
-			len = strlen(buffer) - 1;		/*Flawfinder: ignore*/
-			for ( bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--)	*bptr='\0';
-			
-			if (!firstline)
-			{
-				LLSD item;
-				std::string line(buffer);
-				std::istringstream iss(line);
-				
-				if (!LLChatLogParser::parse(line, item))
-				{
-					item["message"]	= line;
-					callback(LOG_LINE, item, userdata);
-				}
-				else
-				{
-					callback(LOG_LLSD, item, userdata);
-				}
-			}
-			else
-			{
-				firstline = FALSE;
-			}
-		}
-		callback(LOG_END, LLSD(), userdata);
-		
-		fclose(fptr);
-	}
-}
-
 void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
 {
 	if (!messages.size()) return;
@@ -346,6 +303,7 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
 	messages.back()[IM_TEXT] = im_text;
 }
 
+// static
 void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& messages)
 {
 	if (file_name.empty())
@@ -409,53 +367,25 @@ void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& me
 	fclose(fptr);
 }
 
-//*TODO mark object's names in a special way so that they will be distinguishable form avatar name 
-//which are more strict by its nature (only firstname and secondname)
-//Example, an object's name can be writen like "Object <actual_object's_name>"
-void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
-{
-	if (!im.isMap())
-	{
-		llwarning("invalid LLSD type of an instant message", 0);
-		return;
-	}
-
-	if (im[IM_TIME].isDefined())
-	{
-		std::string timestamp = im[IM_TIME].asString();
-		boost::trim(timestamp);
-		ostr << '[' << timestamp << ']' << TWO_SPACES;
-	}
-
-	//*TODO mark object's names in a special way so that they will be distinguishable form avatar name 
-	//which are more strict by its nature (only firstname and secondname)
-	//Example, an object's name can be writen like "Object <actual_object's_name>"
-	if (im[IM_FROM].isDefined())
-	{
-		std::string from = im[IM_FROM].asString();
-		boost::trim(from);
-		if (from.size())
-		{
-			ostr << from << IM_SEPARATOR;
-		}
-	}
-	
-	if (im[IM_TEXT].isDefined())
-	{
-		std::string im_text = im[IM_TEXT].asString();
-
-		//multilined text will be saved with prepended spaces
-		boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX);
-		ostr << im_text;
-	}
-}
-
-bool LLChatLogParser::parse(std::string& raw, LLSD& im)
+// static
+bool LLChatLogParser::parse(const std::string& raw, LLSD& im)
 {
 	if (!raw.length()) return false;
 	
 	im = LLSD::emptyMap();
 
+	// In Viewer 2.1 we added UUID to chat/IM logging so we can look up
+	// display names
+	if (raw[0] == '{')
+	{
+		// ...this is a viewer 2.1, new-style LLSD notation format log
+		std::istringstream raw_stream(raw);
+		LLPointer<LLSDParser> parser = new LLSDNotationParser();
+		S32 count = parser->parse(raw_stream, im, raw.length());
+		// expect several map items per parsed line
+		return (count != LLSDParser::PARSE_FAILURE);
+	}
+
 	//matching a timestamp
 	boost::match_results<std::string::const_iterator> matches;
 	if (!boost::regex_match(raw, matches, TIMESTAMP_AND_STUFF)) return false;
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index e544bb2d45da02ea0da15c1c13de3b8328d61ebd..8b1cc3484fdbcc4bff5a970f7a302e1bc82e140b 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -24,10 +24,11 @@
  * $/LicenseInfo$
  */
 
-
 #ifndef LL_LLLOGCHAT_H
 #define LL_LLLOGCHAT_H
 
+class LLChat;
+
 class LLLogChat
 {
 public:
@@ -40,48 +41,21 @@ class LLLogChat
 	};
 	static std::string timestamp(bool withdate = false);
 	static std::string makeLogFileName(std::string(filename));
+
+	// Log a single line item to the appropriate chat file
+	static void saveHistory(const std::string& filename, const LLChat& chat);
+
+	// Prefer the above version - it saves more metadata about the item
 	static void saveHistory(const std::string& filename,
 				const std::string& from,
 				const LLUUID& from_id,
 				const std::string& line);
 
-	/** @deprecated @see loadAllHistory() */
-	static void loadHistory(const std::string& filename, 
-		                    void (*callback)(ELogLineType, const LLSD&, void*), 
-							void* userdata);
-
 	static void loadAllHistory(const std::string& file_name, std::list<LLSD>& messages);
 private:
 	static std::string cleanFileName(std::string filename);
 };
 
-/**
- * Formatter for the plain text chat log files
- */
-class LLChatLogFormatter
-{
-public:
-	LLChatLogFormatter(const LLSD& im) : mIM(im) {}
-	virtual ~LLChatLogFormatter() {};
-
-	friend std::ostream& operator<<(std::ostream& str, const LLChatLogFormatter& formatter)
-	{
-		formatter.format(formatter.mIM, str);
-		return str;
-	}
-
-protected:
-
-	/**
-	 * Format an instant message to a stream
-	 * Timestamps and sender names are required
-	 * New lines of multilined messages are prepended with a space
-	 */
-	void format(const LLSD& im, std::ostream& ostr) const;
-
-	LLSD mIM;
-};
-
 /**
  * Parser for the plain text chat log files
  */
@@ -100,11 +74,18 @@ class LLChatLogParser
 	 *
 	 * @return false if failed to parse mandatory data - message text
 	 */
-	static bool parse(std::string& raw, LLSD& im);
+	static bool parse(const std::string& raw, LLSD& im);
 
 protected:
 	LLChatLogParser();
 	virtual ~LLChatLogParser() {};
 };
 
+// LLSD map lookup constants
+extern const std::string IM_TIME; //("time");
+extern const std::string IM_TEXT; //("message");
+extern const std::string IM_FROM; //("from");
+extern const std::string IM_FROM_ID; //("from_id");
+extern const std::string IM_SOURCE_TYPE; //("source_type");
+
 #endif
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 7b2f5984a778899df811cdc064c61efb71b47ecd..b87ee6f9f02a2121439ecba50266f9dfe0c7467c 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -137,6 +137,7 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
 
 	requested_options.append("initial-outfit");
 	requested_options.append("gestures");
+	requested_options.append("display_names");
 	requested_options.append("event_categories");
 	requested_options.append("event_notifications");
 	requested_options.append("classified_categories");
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index eb00663d3f1a1c4c950ea97a73bf32447abf853e..af8fdb17cfc06f95f6f3f8ebcd5e2ef40c06a53e 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -112,9 +112,8 @@ LLMute::LLMute(const LLUUID& id, const std::string& name, EType type, U32 flags)
 		LLNameValue* lastname = mute_object->getNVPair("LastName");
 		if (firstname && lastname)
 		{
-			mName.assign( firstname->getString() );
-			mName.append(" ");
-			mName.append( lastname->getString() );
+			mName = LLCacheName::buildFullName(
+				firstname->getString(), lastname->getString());
 		}
 		mType = mute_object->isAvatar() ? AGENT : OBJECT;
 	}
@@ -410,7 +409,7 @@ void LLMuteList::updateRemove(const LLMute& mute)
 	gAgent.sendReliableMessage();
 }
 
-void notify_automute_callback(const LLUUID& agent_id, const std::string& first_name, const std::string& last_name, BOOL is_group, LLMuteList::EAutoReason reason)
+void notify_automute_callback(const LLUUID& agent_id, const std::string& full_name, bool is_group, LLMuteList::EAutoReason reason)
 {
 	std::string notif_name;
 	switch (reason)
@@ -428,8 +427,7 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& first_n
 	}
 
 	LLSD args;
-	args["FIRST"] = first_name;
-	args["LAST"] = last_name;
+	args["NAME"] = full_name;
     
 	LLNotificationPtr notif_ptr = LLNotifications::instance().add(notif_name, args, LLSD());
 	if (notif_ptr)
@@ -444,7 +442,7 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& first_n
 }
 
 
-BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason, const std::string& first_name, const std::string& last_name)
+BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason)
 {
 	BOOL removed = FALSE;
 
@@ -454,24 +452,17 @@ BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason, co
 		removed = TRUE;
 		remove(automute);
 
-		if (first_name.empty() && last_name.empty())
-		{
-			std::string cache_first, cache_last;
-			if (gCacheName->getName(agent_id, cache_first, cache_last))
+		std::string full_name;
+		if (gCacheName->getFullName(agent_id, full_name))
 			{
 				// name in cache, call callback directly
-				notify_automute_callback(agent_id, cache_first, cache_last, FALSE, reason);
+			notify_automute_callback(agent_id, full_name, false, reason);
 			}
 			else
 			{
 				// not in cache, lookup name from cache
-				gCacheName->get(agent_id, FALSE, boost::bind(&notify_automute_callback, _1, _2, _3, _4, reason));
-			}
-		}
-		else
-		{
-			// call callback directly
-			notify_automute_callback(agent_id, first_name, last_name, FALSE, reason);
+			gCacheName->get(agent_id, false,
+				boost::bind(&notify_automute_callback, _1, _2, _3, reason));
 		}
 	}
 
diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h
index 62c72dd9c68a3b68a689eecd717aa18ad55376b7..04e157008111bf7c43e51933aad8876dc8884caf 100644
--- a/indra/newview/llmutelist.h
+++ b/indra/newview/llmutelist.h
@@ -63,7 +63,7 @@ class LLMute
 	
 public:
 	LLUUID		mID;	// agent or object id
-	std::string	mName;	// agent or object name
+	std::string	mName;	// agent or object name, does not store last name "Resident"
 	EType		mType;	// needed for UI display of existing mutes
 	U32			mFlags;	// flags pertaining to this mute entry
 };
@@ -96,7 +96,7 @@ class LLMuteList : public LLSingleton<LLMuteList>
 
 	// Remove both normal and legacy mutes, for any or all properties.
 	BOOL remove(const LLMute& mute, U32 flags = 0);
-	BOOL autoRemove(const LLUUID& agent_id, const EAutoReason reason, const std::string& first_name = LLStringUtil::null, const std::string& last_name = LLStringUtil::null);
+	BOOL autoRemove(const LLUUID& agent_id, const EAutoReason reason);
 	
 	// Name is required to test against legacy text-only mutes.
 	BOOL isMuted(const LLUUID& id, const std::string& name = LLStringUtil::null, U32 flags = 0) const;
diff --git a/indra/newview/llnamebox.cpp b/indra/newview/llnamebox.cpp
index 74d4217899dd5255e3dde8c8959d7906716d60cd..85cde5f94cfa0eff6ff22e55ff6f312bf3b061ba 100644
--- a/indra/newview/llnamebox.cpp
+++ b/indra/newview/llnamebox.cpp
@@ -81,26 +81,15 @@ void LLNameBox::setNameID(const LLUUID& name_id, BOOL is_group)
 		setText(mInitialValue);
 }
 
-void LLNameBox::refresh(const LLUUID& id, const std::string& firstname,
-						const std::string& lastname, BOOL is_group)
+void LLNameBox::refresh(const LLUUID& id, const std::string& full_name, bool is_group)
 {
 	if (id == mNameID)
 	{
-		std::string name;
-		if (!is_group)
-		{
-			name = firstname + " " + lastname;
-		}
-		else
-		{
-			name = firstname;
-		}
-		setName(name, is_group);
+		setName(full_name, is_group);
 	}
 }
 
-void LLNameBox::refreshAll(const LLUUID& id, const std::string& firstname,
-						   const std::string& lastname, BOOL is_group)
+void LLNameBox::refreshAll(const LLUUID& id, const std::string& full_name, bool is_group)
 {
 	std::set<LLNameBox*>::iterator it;
 	for (it = LLNameBox::sInstances.begin();
@@ -108,7 +97,7 @@ void LLNameBox::refreshAll(const LLUUID& id, const std::string& firstname,
 		 ++it)
 	{
 		LLNameBox* box = *it;
-		box->refresh(id, firstname, lastname, is_group);
+		box->refresh(id, full_name, is_group);
 	}
 }
 
diff --git a/indra/newview/llnamebox.h b/indra/newview/llnamebox.h
index dbabcc0e52cc3239548f4af45a9ccdcaec49ff0a..76e85512683eb161c35b2929411d262cce9ef496 100644
--- a/indra/newview/llnamebox.h
+++ b/indra/newview/llnamebox.h
@@ -53,10 +53,9 @@ class LLNameBox
 
 	void setNameID(const LLUUID& name_id, BOOL is_group);
 
-	void refresh(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+	void refresh(const LLUUID& id, const std::string& full_name, bool is_group);
 
-	static void refreshAll(const LLUUID& id, const std::string& firstname,
-						   const std::string& lastname, BOOL is_group);
+	static void refreshAll(const LLUUID& id, const std::string& full_name, bool is_group);
 
 protected:
 	LLNameBox (const Params&);
diff --git a/indra/newview/llnameeditor.cpp b/indra/newview/llnameeditor.cpp
index f53252b6149b895eb393c754bc95999ae06925c6..b3b1ff7c06f2385ba992597f3ef49e36051aaa82 100644
--- a/indra/newview/llnameeditor.cpp
+++ b/indra/newview/llnameeditor.cpp
@@ -75,26 +75,15 @@ void LLNameEditor::setNameID(const LLUUID& name_id, BOOL is_group)
 	setText(name);
 }
 
-void LLNameEditor::refresh(const LLUUID& id, const std::string& firstname,
-						   const std::string& lastname, BOOL is_group)
+void LLNameEditor::refresh(const LLUUID& id, const std::string& full_name, bool is_group)
 {
 	if (id == mNameID)
 	{
-		std::string name;
-		if (!is_group)
-		{
-			name = firstname + " " + lastname;
-		}
-		else
-		{
-			name = firstname;
-		}
-		setText(name);
+		setText(full_name);
 	}
 }
 
-void LLNameEditor::refreshAll(const LLUUID& id, const std::string& firstname,
-							  const std::string& lastname, BOOL is_group)
+void LLNameEditor::refreshAll(const LLUUID& id, const std::string& full_name, bool is_group)
 {
 	std::set<LLNameEditor*>::iterator it;
 	for (it = LLNameEditor::sInstances.begin();
@@ -102,7 +91,7 @@ void LLNameEditor::refreshAll(const LLUUID& id, const std::string& firstname,
 		 ++it)
 	{
 		LLNameEditor* box = *it;
-		box->refresh(id, firstname, lastname, is_group);
+		box->refresh(id, full_name, is_group);
 	}
 }
 
diff --git a/indra/newview/llnameeditor.h b/indra/newview/llnameeditor.h
index d8360f9f4bd1a5145fe0e5a1553368fc02c51268..b8c4a6042e13e2732b66ad14857de10b6673036b 100644
--- a/indra/newview/llnameeditor.h
+++ b/indra/newview/llnameeditor.h
@@ -59,10 +59,9 @@ class LLNameEditor
 
 	void setNameID(const LLUUID& name_id, BOOL is_group);
 
-	void refresh(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+	void refresh(const LLUUID& id, const std::string& full_name, bool is_group);
 
-	static void refreshAll(const LLUUID& id, const std::string& firstname,
-						   const std::string& lastname, BOOL is_group);
+	static void refreshAll(const LLUUID& id, const std::string& full_name, bool is_group);
 
 
 	// Take/return agent UUIDs
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index e7e60f544cdf0b5e9296ac02609824e7293cbdf1..dfab5c7634ac11948f3eda643fcae399e94b62ee 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -30,6 +30,7 @@
 
 #include <boost/tokenizer.hpp>
 
+#include "llavatarnamecache.h"
 #include "llcachename.h"
 #include "llfloaterreg.h"
 #include "llinventory.h"
@@ -38,6 +39,7 @@
 #include "llscrolllistcolumn.h"
 #include "llsdparam.h"
 #include "lltooltip.h"
+#include "lltrans.h"
 
 static LLDefaultChildRegistry::Register<LLNameListCtrl> r("name_list");
 
@@ -52,7 +54,8 @@ void LLNameListCtrl::NameTypeNames::declareValues()
 
 LLNameListCtrl::Params::Params()
 :	name_column(""),
-	allow_calling_card_drop("allow_calling_card_drop", false)
+	allow_calling_card_drop("allow_calling_card_drop", false),
+	short_names("short_names", false)
 {
 	name = "name_list";
 }
@@ -61,7 +64,8 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
 :	LLScrollListCtrl(p),
 	mNameColumnIndex(p.name_column.column_index),
 	mNameColumn(p.name_column.column_name),
-	mAllowCallingCardDrop(p.allow_calling_card_drop)
+	mAllowCallingCardDrop(p.allow_calling_card_drop),
+	mShortNames(p.short_names)
 {}
 
 // public
@@ -291,10 +295,24 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
 		break;
 	case INDIVIDUAL:
 		{
-			std::string name;
-			if (gCacheName->getFullName(id, name))
+			LLAvatarName av_name;
+			if (id.isNull())
 			{
-				fullname = name;
+				fullname = LLTrans::getString("AvatarNameNobody");
+			}
+			else if (LLAvatarNameCache::get(id, &av_name))
+			{
+				if (mShortNames)
+					fullname = av_name.mDisplayName;
+				else
+					fullname = av_name.getCompleteName();
+			}
+			else
+			{
+				// ...schedule a callback
+				LLAvatarNameCache::get(id,
+					boost::bind(&LLNameListCtrl::onAvatarNameCache,
+						this, _1, _2));
 			}
 			break;
 		}
@@ -349,34 +367,25 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)
 	}
 }
 
-// public
-void LLNameListCtrl::refresh(const LLUUID& id, const std::string& first, 
-							 const std::string& last, BOOL is_group)
+void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,
+									   const LLAvatarName& av_name)
 {
-	//llinfos << "LLNameListCtrl::refresh " << id << " '" << first << " "
-	//	<< last << "'" << llendl;
-
-	std::string fullname;
-	if (!is_group)
-	{
-		fullname = first + " " + last;
-	}
+	std::string name;
+	if (mShortNames)
+		name = av_name.mDisplayName;
 	else
-	{
-		fullname = first;
-	}
+		name = av_name.getCompleteName();
 
-	// TODO: scan items for that ID, fix if necessary
 	item_list::iterator iter;
 	for (iter = getItemList().begin(); iter != getItemList().end(); iter++)
 	{
 		LLScrollListItem* item = *iter;
-		if (item->getUUID() == id)
+		if (item->getUUID() == agent_id)
 		{
 			LLScrollListCell* cell = item->getColumn(mNameColumnIndex);
 			if (cell)
 			{
-				cell->setValue(fullname);
+				cell->setValue(name);
 			}
 		}
 	}
@@ -385,19 +394,6 @@ void LLNameListCtrl::refresh(const LLUUID& id, const std::string& first,
 }
 
 
-// static
-void LLNameListCtrl::refreshAll(const LLUUID& id, const std::string& first,
-								const std::string& last, BOOL is_group)
-{
-	LLInstanceTrackerScopedGuard guard;
-	LLInstanceTracker<LLNameListCtrl>::instance_iter it;
-	for (it = guard.beginInstances(); it != guard.endInstances(); ++it)
-	{
-		LLNameListCtrl& ctrl = *it;
-		ctrl.refresh(id, first, last, is_group);
-	}
-}
-
 void LLNameListCtrl::updateColumns()
 {
 	LLScrollListCtrl::updateColumns();
diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h
index 981e3df16b25f3c4a9e3fb103eb4d6af0f6169ef..6805630ef19cb832b0950c6f0e021ae591fcc449 100644
--- a/indra/newview/llnamelistctrl.h
+++ b/indra/newview/llnamelistctrl.h
@@ -31,6 +31,7 @@
 
 #include "llscrolllistctrl.h"
 
+class LLAvatarName;
 
 class LLNameListCtrl
 :	public LLScrollListCtrl, public LLInstanceTracker<LLNameListCtrl>
@@ -74,6 +75,7 @@ class LLNameListCtrl
 	{
 		Optional<NameColumn>	name_column;
 		Optional<bool>	allow_calling_card_drop;
+		Optional<bool>			short_names;
 		Params();
 	};
 
@@ -99,11 +101,6 @@ class LLNameListCtrl
 
 	void removeNameItem(const LLUUID& agent_id);
 
-	void refresh(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
-
-	static void refreshAll(const LLUUID& id, const std::string& firstname,
-						   const std::string& lastname, BOOL is_group);
-
 	// LLView interface
 	/*virtual*/ BOOL	handleDragAndDrop(S32 x, S32 y, MASK mask,
 									  BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
@@ -118,11 +115,13 @@ class LLNameListCtrl
 	/*virtual*/ void	mouseOverHighlightNthItem( S32 index );
 private:
 	void showInspector(const LLUUID& avatar_id, bool is_group);
+	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
 
 private:
 	S32    			mNameColumnIndex;
 	std::string		mNameColumn;
 	BOOL			mAllowCallingCardDrop;
+	bool			mShortNames;  // display name only, no SLID
 };
 
 /**
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 5f71d7100b8f21d2e756730f73c15b8b1fff02b7..02fbb7b6993c615ac7a83924b9513499b7e49723 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -55,12 +55,6 @@
 
 static const S32 RESIZE_BAR_THICKNESS = 3;
 
-const static std::string IM_TIME("time");
-const static std::string IM_TEXT("message");
-const static std::string IM_FROM("from");
-const static std::string IM_FROM_ID("from_id");
-
-
 LLNearbyChat::LLNearbyChat(const LLSD& key) 
 	: LLDockableFloater(NULL, false, false, key)
 	,mChatHistory(NULL)
@@ -185,7 +179,7 @@ void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
 
 	if (gSavedPerAccountSettings.getBOOL("LogNearbyChat"))
 	{
-		LLLogChat::saveHistory("chat", chat.mFromName, chat.mFromID, chat.mText);
+		LLLogChat::saveHistory("chat", chat);
 	}
 }
 
@@ -275,8 +269,12 @@ void LLNearbyChat::loadHistory()
 		const LLSD& msg = *it;
 
 		std::string from = msg[IM_FROM];
-		LLUUID from_id = LLUUID::null;
-		if (msg[IM_FROM_ID].isUndefined())
+		LLUUID from_id;
+		if (msg[IM_FROM_ID].isDefined())
+		{
+			from_id = msg[IM_FROM_ID].asUUID();
+		}
+		else
 		{
 			gCacheName->getUUID(from, from_id);
 		}
@@ -288,11 +286,14 @@ void LLNearbyChat::loadHistory()
 		chat.mTimeStr = msg[IM_TIME].asString();
 		chat.mChatStyle = CHAT_STYLE_HISTORY;
 
-		chat.mSourceType = CHAT_SOURCE_AGENT;
-		if (from_id.isNull() && SYSTEM_FROM == from)
+		if (msg.has(IM_SOURCE_TYPE))
+		{
+			S32 source_type = msg[IM_SOURCE_TYPE].asInteger();
+			chat.mSourceType = (EChatSourceType)source_type;
+		}
+		else if (from_id.isNull() && SYSTEM_FROM == from)
 		{	
 			chat.mSourceType = CHAT_SOURCE_SYSTEM;
-			
 		}
 		else if (from_id.isNull())
 		{
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 6db8001d57a1d8130d3c414ebbebc8aabeace7e9..b0b2a3f6f9f3031ddae822b0f31ac4a470d07b73 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -5,7 +5,7 @@
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2001-2010, Linden Research, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -31,6 +31,7 @@
 
 // Library includes (should move below)
 #include "indra_constants.h"
+#include "llavatarnamecache.h"
 #include "llmath.h"
 #include "llfloaterreg.h"
 #include "llfocusmgr.h"
@@ -567,34 +568,25 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask )
 	{
 		return FALSE;
 	}
-
-	std::string avatar_name;
-	if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, avatar_name))
+	
+	// mToolTipMsg = "[AGENT][REGION](Double-click to open Map)"
+	
+	bool have_agent = false;
+	LLStringUtil::format_map_t args;
+	LLAvatarName av_name;
+	if(mClosestAgentToCursor.notNull()
+	   && LLAvatarNameCache::get(mClosestAgentToCursor, &av_name))
 	{
-		// only show tooltip if same inspector not already open
-		LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_avatar");
-		if (!existing_inspector 
-			|| !existing_inspector->getVisible()
-			|| existing_inspector->getKey()["avatar_id"].asUUID() != mClosestAgentToCursor)
-		{
-			LLInspector::Params p;
-			p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
-			p.message(avatar_name);
-			p.image.name("Inspector_I");
-			p.click_callback(boost::bind(showAvatarInspector, mClosestAgentToCursor));
-			p.visible_time_near(6.f);
-			p.visible_time_far(3.f);
-			p.delay_time(0.35f);
-			p.wrap(false);
-
-			LLToolTipMgr::instance().show(p);
-		}
-		return TRUE;
+		args["[AGENT]"] = av_name.getCompleteName() + "\n";
+		have_agent = true;
 	}
-
-	LLStringUtil::format_map_t args;
+	else
+	{
+		args["[AGENT]"] = "";
+	}
+	
 	LLViewerRegion*	region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y ) );
-	if( region )
+	if( region && !have_agent)
 	{
 		args["[REGION]"] = region->getName() + "\n";
 	}
@@ -625,21 +617,6 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask )
 	return TRUE;
 }
 
-// static
-void LLNetMap::showAvatarInspector(const LLUUID& avatar_id)
-{
-	LLSD params;
-	params["avatar_id"] = avatar_id;
-
-	if (LLToolTipMgr::instance().toolTipVisible())
-	{
-		LLRect rect = LLToolTipMgr::instance().getToolTipRect();
-		params["pos"]["x"] = rect.mLeft;
-		params["pos"]["y"] = rect.mTop;
-	}
-
-	LLFloaterReg::showInstance("inspect_avatar", params);
-}
 
 void LLNetMap::renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius_meters )
 {
diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp
index b5683296ebf6c73e047357a20dcc60229ee6c38c..40b4ae7b2e92729d70604b5c6493d8b9a2fe63f0 100644
--- a/indra/newview/llnotificationhandlerutil.cpp
+++ b/indra/newview/llnotificationhandlerutil.cpp
@@ -107,8 +107,11 @@ void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif)
 }
 
 const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),
-		REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), OBJECT_GIVE_ITEM(
-				"ObjectGiveItem"), PAYMENT_RECIVED("PaymentRecived"),
+		REVOKED_MODIFY_RIGHTS("RevokedModifyRights"),
+		OBJECT_GIVE_ITEM("ObjectGiveItem"),
+		OBJECT_GIVE_ITEM_UNKNOWN_USER("ObjectGiveItemUnknownUser"),
+						PAYMENT_RECEIVED("PaymentReceived"),
+						PAYMENT_SENT("PaymentSent"),
 						ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"),
 						USER_GIVE_ITEM("UserGiveItem"),
 						INVENTORY_ACCEPTED("InventoryAccepted"),
@@ -130,7 +133,8 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)
 {
 	return GRANTED_MODIFY_RIGHTS == notification->getName()
 			|| REVOKED_MODIFY_RIGHTS == notification->getName()
-			|| PAYMENT_RECIVED == notification->getName()
+			|| PAYMENT_RECEIVED == notification->getName()
+			|| PAYMENT_SENT == notification->getName()
 			|| OFFER_FRIENDSHIP == notification->getName()
 			|| FRIENDSHIP_OFFERED == notification->getName()
 			|| FRIENDSHIP_ACCEPTED == notification->getName()
@@ -311,34 +315,35 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification)
 	logToIMP2P(notification, false);
 }
 
+void log_name_callback(const std::string& full_name, const std::string& from_name, 
+					   const std::string& message, const LLUUID& from_id)
+
+{
+	LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, full_name, from_name, message,
+					from_id, LLUUID());
+}
+
 // static
 void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only)
 {
-	const std::string name = LLHandlerUtil::getSubstitutionName(notification);
-
-	const std::string& session_name = notification->getPayload().has(
-			"SESSION_NAME") ? notification->getPayload()["SESSION_NAME"].asString() : name;
-
 	// don't create IM p2p session with objects, it's necessary condition to log
 	if (notification->getName() != OBJECT_GIVE_ITEM)
 	{
 		LLUUID from_id = notification->getPayload()["from_id"];
 
-		//there still appears a log history file with weird name " .txt"
-		if (" " == session_name || "{waiting}" == session_name || "{nobody}" == session_name)
+		if (from_id.isNull())
 		{
-			llwarning("Weird session name (" + session_name + ") for notification " + notification->getName(), 666)
+			llwarns << " from_id for notification " << notification->getName() << " is null " << llendl;
+			return;
 		}
 
 		if(to_file_only)
 		{
-			logToIM(IM_NOTHING_SPECIAL, session_name, "", notification->getMessage(),
-					LLUUID(), LLUUID());
+			gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, "", notification->getMessage(), LLUUID()));
 		}
 		else
 		{
-			logToIM(IM_NOTHING_SPECIAL, session_name, INTERACTIVE_SYSTEM_FROM, notification->getMessage(),
-					from_id, LLUUID());
+			gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id));
 		}
 	}
 }
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 68ca65420a8f757e390c18a241354b6b80ea9f1d..57180f63b5189cb4f3eb90e1321ffedb4177af7c 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -44,7 +44,7 @@
 #include "llfloaterreg.h"
 #include "llnotificationsutil.h"
 #include "llvoiceclient.h"
-#include "llnamebox.h"
+#include "lltextbox.h"
 #include "lltrans.h"
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -218,13 +218,8 @@ void LLPanelAvatarNotes::rightsConfirmationCallback(const LLSD& notification,
 
 void LLPanelAvatarNotes::confirmModifyRights(bool grant, S32 rights)
 {
-	std::string first, last;
 	LLSD args;
-	if (gCacheName->getName(getAvatarId(), first, last))
-	{
-		args["FIRST_NAME"] = first;
-		args["LAST_NAME"] = last;
-	}
+	args["NAME"] = LLSLURL("agent", getAvatarId(), "displayname").getSLURLString();
 
 	if (grant)
 	{
@@ -562,8 +557,7 @@ void LLPanelAvatarProfile::resetData()
 	getChild<LLUICtrl>("homepage_edit")->setValue(LLStringUtil::null);
 	getChild<LLUICtrl>("register_date")->setValue(LLStringUtil::null);
 	getChild<LLUICtrl>("acc_status_text")->setValue(LLStringUtil::null);
-	getChild<LLUICtrl>("partner_text")->setTextArg("[FIRST]", LLStringUtil::null);
-	getChild<LLUICtrl>("partner_text")->setTextArg("[LAST]", LLStringUtil::null);
+	getChild<LLUICtrl>("partner_text")->setValue(LLStringUtil::null);
 }
 
 void LLPanelAvatarProfile::processProperties(void* data, EAvatarProcessorType type)
@@ -654,15 +648,14 @@ void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)
 
 void LLPanelAvatarProfile::fillPartnerData(const LLAvatarData* avatar_data)
 {
-	LLNameBox* name_box = getChild<LLNameBox>("partner_text");
+	LLTextBox* partner_text = getChild<LLTextBox>("partner_text");
 	if (avatar_data->partner_id.notNull())
 	{
-		name_box->setNameID(avatar_data->partner_id, FALSE);
+		partner_text->setText(LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString());
 	}
 	else
 	{
-		name_box->setNameID(LLUUID::null, FALSE);
-		name_box->setText(getString("no_partner_text"));
+		partner_text->setText(getString("no_partner_text"));
 	}
 }
 
diff --git a/indra/newview/llpanelavatartag.cpp b/indra/newview/llpanelavatartag.cpp
index d174b8da96108d2ca92a767e7df38c9d0b71ec6e..fc9283add576d8e75e2bc633526c4bc8afcfb167 100644
--- a/indra/newview/llpanelavatartag.cpp
+++ b/indra/newview/llpanelavatartag.cpp
@@ -80,7 +80,7 @@ void LLPanelAvatarTag::setAvatarId(const LLUUID& avatar_id)
 	{
 		mIcon->setValue(avatar_id);
 	}
-	setName(std::string(mIcon->getFirstName()+ " "+ mIcon->getLastName()));
+	setName(std::string(mIcon->getFullName()));
 }
 
 boost::signals2::connection LLPanelAvatarTag::setLeftButtonClickCallback(
diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp
index fd2e961cb7a4d11d5969d164c18d8544ae32dbe5..81e199d85b53eb2ebe8f118676452f1a6ea8058a 100644
--- a/indra/newview/llpanelblockedlist.cpp
+++ b/indra/newview/llpanelblockedlist.cpp
@@ -29,6 +29,7 @@
 #include "llpanelblockedlist.h"
 
 // library include
+#include "llavatarname.h"
 #include "llfloater.h"
 #include "llfloaterreg.h"
 #include "llnotificationsutil.h"
@@ -180,10 +181,10 @@ void LLPanelBlockedList::onBlockByNameClick()
 	LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName);
 }
 
-void LLPanelBlockedList::callbackBlockPicked(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
 {
 	if (names.empty() || ids.empty()) return;
-	LLMute mute(ids[0], names[0], LLMute::AGENT);
+	LLMute mute(ids[0], names[0].getLegacyName(), LLMute::AGENT);
 	LLMuteList::getInstance()->add(mute);
 	showPanelAndSelect(mute.mID);
 }
diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h
index eb9f082d87a6f285a80cb082bddfa03d760572d8..74ad82e32d697b9bb278e700d9b95e91cdf106af 100644
--- a/indra/newview/llpanelblockedlist.h
+++ b/indra/newview/llpanelblockedlist.h
@@ -36,7 +36,8 @@
 // class LLLineEditor;
 // class LLMessageSystem;
 // class LLUUID;
- class LLScrollListCtrl;
+class LLAvatarName;
+class LLScrollListCtrl;
 
 class LLPanelBlockedList
 	:	public LLPanel, public LLMuteListObserver
@@ -72,7 +73,7 @@ class LLPanelBlockedList
 	void onPickBtnClick();
 	void onBlockByNameClick();
 
-	void callbackBlockPicked(const std::vector<std::string>& names, const uuid_vec_t& ids);
+	void callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
 	static void callbackBlockByName(const std::string& text);
 
 private:
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 840b98213d66bb841a2a2cd29bfc46708dfe31b4..f3bac9f6e7c216aaae0cb2112c6f31347d3f5658 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -40,7 +40,6 @@
 #include "llavataractions.h"
 #include "llgroupactions.h"
 #include "lllineeditor.h"
-#include "llnamebox.h"
 #include "llnamelistctrl.h"
 #include "llnotificationsutil.h"
 #include "llscrolllistitem.h"
@@ -206,7 +205,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group)
 	{
 		mInsignia->setCommitCallback(onCommitAny, this);
 	}
-	mFounderName = getChild<LLNameBox>("founder_name");
+	mFounderName = getChild<LLTextBox>("founder_name");
 
 
 	mGroupNameEditor = panel_group->getChild<LLLineEditor>("group_name_editor");
@@ -638,7 +637,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc)
 	if (mEditCharter) mEditCharter->setEnabled(mAllowEdit && can_change_ident);
 	
 	if (mGroupNameEditor) mGroupNameEditor->setVisible(FALSE);
-	if (mFounderName) mFounderName->setNameID(gdatap->mFounderID,FALSE);
+	if (mFounderName) mFounderName->setText(LLSLURL("agent", gdatap->mFounderID, "inspect").getSLURLString());
 	if (mInsignia)
 	{
 		if (gdatap->mInsigniaID.notNull())
diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h
index cbf173f845cd889551edf9b1486b9b472ca3b1f9..88c092c461bc9c88dc47a6f67aae19acd9abbe30 100644
--- a/indra/newview/llpanelgroupgeneral.h
+++ b/indra/newview/llpanelgroupgeneral.h
@@ -37,7 +37,6 @@ class LLButton;
 class LLNameListCtrl;
 class LLCheckBoxCtrl;
 class LLComboBox;
-class LLNameBox;
 class LLSpinCtrl;
 
 class LLPanelGroupGeneral : public LLPanelGroupTab
@@ -91,7 +90,7 @@ class LLPanelGroupGeneral : public LLPanelGroupTab
 
 	// Group information (include any updates in updateChanged)
 	LLLineEditor		*mGroupNameEditor;
-	LLNameBox			*mFounderName;
+	LLTextBox			*mFounderName;
 	LLTextureCtrl		*mInsignia;
 	LLTextEditor		*mEditCharter;
 
diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp
index 535b2a9e2dea703af2e06e2a9cf7d15483a56649..abc4f643d40a3ae0560f2a113ab37f1c0ffd6eef 100644
--- a/indra/newview/llpanelgroupinvite.cpp
+++ b/indra/newview/llpanelgroupinvite.cpp
@@ -28,6 +28,7 @@
 #include "llpanelgroupinvite.h"
 
 #include "llagent.h"
+#include "llavatarnamecache.h"
 #include "llfloateravatarpicker.h"
 #include "llbutton.h"
 #include "llcallingcard.h"
@@ -62,9 +63,13 @@ class LLPanelGroupInvite::impl
 	static void callbackClickAdd(void* userdata);
 	static void callbackClickRemove(void* userdata);
 	static void callbackSelect(LLUICtrl* ctrl, void* userdata);
-	static void callbackAddUsers(const std::vector<std::string>& names,
-								 const uuid_vec_t& agent_ids,
+	static void callbackAddUsers(const uuid_vec_t& agent_ids,
 								 void* user_data);
+	
+	static void onAvatarNameCache(const LLUUID& agent_id,
+											 const LLAvatarName& av_name,
+											 void* user_data);
+
 	bool inviteOwnerCallback(const LLSD& notification, const LLSD& response);
 
 public:
@@ -287,7 +292,7 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata)
 		LLFloater* parentp;
 
 		parentp = gFloaterView->getParentFloater(panelp);
-		parentp->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(impl::callbackAddUsers, _1, _2,
+		parentp->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(impl::callbackAddUsers, _1,
 																panelp->mImplementation),
 																 TRUE));
 	}
@@ -353,16 +358,38 @@ void LLPanelGroupInvite::impl::callbackClickOK(void* userdata)
 	if ( selfp ) selfp->submitInvitations();
 }
 
+
+
 //static
-void LLPanelGroupInvite::impl::callbackAddUsers(const std::vector<std::string>& names,
-												const uuid_vec_t& ids,
-												void* user_data)
+void LLPanelGroupInvite::impl::callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data)
+{	
+	std::vector<std::string> names;
+	for (S32 i = 0; i < (S32)agent_ids.size(); i++)
+	{
+		LLAvatarNameCache::get(agent_ids[i],
+			boost::bind(&LLPanelGroupInvite::impl::onAvatarNameCache, _1, _2, user_data));
+	}	
+	
+}
+
+void LLPanelGroupInvite::impl::onAvatarNameCache(const LLUUID& agent_id,
+											 const LLAvatarName& av_name,
+											 void* user_data)
 {
 	impl* selfp = (impl*) user_data;
 
-	if ( selfp) selfp->addUsers(names, ids);
+	if (selfp)
+	{
+		std::vector<std::string> names;
+		uuid_vec_t agent_ids;
+		agent_ids.push_back(agent_id);
+		names.push_back(av_name.getCompleteName());
+		
+		selfp->addUsers(names, agent_ids);
+	}
 }
 
+
 LLPanelGroupInvite::LLPanelGroupInvite(const LLUUID& group_id)
 	: LLPanel(),
 	  mImplementation(new impl(group_id)),
@@ -398,16 +425,18 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
 	std::vector<std::string> names;
 	for (S32 i = 0; i < (S32)agent_ids.size(); i++)
 	{
+		std::string fullname;
 		LLUUID agent_id = agent_ids[i];
 		LLViewerObject* dest = gObjectList.findObject(agent_id);
-		std::string fullname;
 		if(dest && dest->isAvatar())
 		{
 			LLNameValue* nvfirst = dest->getNVPair("FirstName");
 			LLNameValue* nvlast = dest->getNVPair("LastName");
 			if(nvfirst && nvlast)
 			{
-				fullname = std::string(nvfirst->getString()) + " " + std::string(nvlast->getString());
+				fullname = LLCacheName::buildFullName(
+					nvfirst->getString(), nvlast->getString());
+
 			}
 			if (!fullname.empty())
 			{
@@ -430,8 +459,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
 				{
 					// actually it should happen, just in case
 					gCacheName->get(LLUUID(agent_id), false, boost::bind(
-							&LLPanelGroupInvite::addUserCallback, this, _1, _2,
-							_3));
+							&LLPanelGroupInvite::addUserCallback, this, _1, _2));
 					// for this special case!
 					//when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence
 					// removed id will be added in callback
@@ -447,16 +475,16 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
 	mImplementation->addUsers(names, agent_ids);
 }
 
-void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const std::string& first_name, const std::string& last_name)
+void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const std::string& full_name)
 {
 	std::vector<std::string> names;
 	uuid_vec_t agent_ids;
-	std::string full_name = first_name + " " + last_name;
 	agent_ids.push_back(id);
-	names.push_back(first_name + " " + last_name);
+	names.push_back(full_name);
 
 	mImplementation->addUsers(names, agent_ids);
 }
+
 void LLPanelGroupInvite::draw()
 {
 	LLPanel::draw();
diff --git a/indra/newview/llpanelgroupinvite.h b/indra/newview/llpanelgroupinvite.h
index 01e73154867281296d96ecfd190ae31f19f3629b..a7bfd2226e8ebe2b93a8caf3add33b9767151dff 100644
--- a/indra/newview/llpanelgroupinvite.h
+++ b/indra/newview/llpanelgroupinvite.h
@@ -40,7 +40,7 @@ class LLPanelGroupInvite
 	/**
 	 * this callback is being used to add a user whose fullname isn't been loaded before invoking of addUsers().
 	 */  
-	void addUserCallback(const LLUUID& id, const std::string& first_name, const std::string& last_name);
+	void addUserCallback(const LLUUID& id, const std::string& full_name);
 	void clear();
 	void update();
 
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index a24dbf6681504c9ddd4f59e82f56745742555e11..cdf6e51bf811945e2aebb00cff22a913d5b340cb 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -30,6 +30,7 @@
 
 #include "llview.h"
 
+#include "llavatarnamecache.h"
 #include "llinventory.h"
 #include "llviewerinventory.h"
 #include "llinventorydefines.h"
@@ -540,6 +541,12 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)
 		msg->getU8("Data","AssetType",asset_type,i);
 		msg->getU32("Data","Timestamp",timestamp,i);
 
+		// we only have the legacy name here, convert it to a username
+		if (LLAvatarNameCache::useDisplayNames())
+		{
+			name = LLCacheName::buildUsername(name);
+		}
+
 		LLSD row;
 		row["id"] = id;
 		
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 579a271ce818ebee8ed51c220d14d1f35a753cd8..0c0fcac385a0a5b21a5c4780157d2fe89be31bd4 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1110,11 +1110,7 @@ void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, c
 		for (uuid_vec_t::const_iterator i = selected_members.begin(); i != selected_members.end(); ++i)
 		{
 			LLSD args;
-			std::string name;
-			
-			gCacheName->getFullName(*i, name);
-
-			args["AVATAR_NAME"] = name;
+			args["AVATAR_NAME"] = LLSLURL("agent", *i, "displayname").getSLURLString();
 			args["GROUP_NAME"] = group_data->mName;
 			
 			LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 7489c02d8dd0bc1b38a27b8c9eceb08a30309d5c..0cc5dcda82040724a864f6210757f718bb5d932a 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -180,7 +180,7 @@ void LLPanelIMControlPanel::onViewProfileButtonClicked()
 void LLPanelIMControlPanel::onAddFriendButtonClicked()
 {
 	LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon");
-	std::string full_name = avatar_icon->getFirstName() + " " + avatar_icon->getLastName();
+	std::string full_name = avatar_icon->getFullName();
 	LLAvatarActions::requestFriendshipDialog(mAvatarID, full_name);
 }
 
@@ -231,6 +231,15 @@ void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
 		getChildView("share_btn")->setEnabled(FALSE);
 		getChildView("teleport_btn")->setEnabled(FALSE);
 		getChildView("pay_btn")->setEnabled(FALSE);
+
+        getChild<LLTextBox>("avatar_name")->setValue(im_session->mName);
+        getChild<LLTextBox>("avatar_name")->setToolTip(im_session->mName);
+	}
+	else
+	{
+		// If the participant is an avatar, fetch the currect name
+		gCacheName->get(mAvatarID, false,
+			boost::bind(&LLPanelIMControlPanel::onNameCache, this, _1, _2, _3));
 	}
 }
 
@@ -246,6 +255,16 @@ void LLPanelIMControlPanel::changed(U32 mask)
 	}
 }
 
+void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group)
+{
+	if ( id == mAvatarID )
+	{
+		std::string avatar_name = full_name;
+		getChild<LLTextBox>("avatar_name")->setValue(avatar_name);
+		getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name);
+	}
+}
+
 LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id):
 mParticipantList(NULL)
 {
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index 45ada3ae1dd89415e1cd609abc132e1e3232b510..3bbe24ecb9e0d8f375196f8fa2141efe0b69a26c 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -83,6 +83,9 @@ class LLPanelIMControlPanel : public LLPanelChatControlPanel, LLFriendObserver
 	// LLFriendObserver trigger
 	virtual void changed(U32 mask);
 
+protected:
+	void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
+
 private:
 	void onViewProfileButtonClicked();
 	void onAddFriendButtonClicked();
diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
index b69cee95864c1048fa40c36c375cc5f2f6fb6ada..87acd83b23bdd0d1bc88682bf47f0c4165817752 100644
--- a/indra/newview/llpanellandmarkinfo.cpp
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -39,6 +39,7 @@
 #include "llagent.h"
 #include "llagentui.h"
 #include "lllandmarkactions.h"
+#include "llslurl.h"
 #include "llviewerinventory.h"
 #include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
@@ -246,13 +247,10 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem)
 	//////////////////
 	if (pItem->getCreatorUUID().notNull())
 	{
-		std::string name;
+		// IDEVO
 		LLUUID creator_id = pItem->getCreatorUUID();
-		if (!gCacheName->getFullName(creator_id, name))
-		{
-			gCacheName->get(creator_id, FALSE,
-							boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mCreator, _2, _3));
-		}
+		std::string name =
+			LLSLURL("agent", creator_id, "inspect").getSLURLString();
 		mCreator->setText(name);
 	}
 	else
@@ -269,20 +267,12 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem)
 		if (perm.isGroupOwned())
 		{
 			LLUUID group_id = perm.getGroup();
-			if (!gCacheName->getGroupName(group_id, name))
-			{
-				gCacheName->get(group_id, TRUE,
-								boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mOwner, _2, _3));
-			}
+			name = LLSLURL("group", group_id, "inspect").getSLURLString();
 		}
 		else
 		{
 			LLUUID owner_id = perm.getOwner();
-			if (!gCacheName->getFullName(owner_id, name))
-			{
-				gCacheName->get(owner_id, FALSE,
-								boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mOwner, _2, _3));
-			}
+			name = LLSLURL("agent", owner_id, "inspect").getSLURLString();
 		}
 		mOwner->setText(name);
 	}
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index be1afbd8d70aa473f0a80fe5bbc148e0ed08a3ad..a55adbc444eba0a3b0de4407b94432cc488233ef 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -205,7 +205,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 	}
 
 #if !USE_VIEWER_AUTH
-	getChild<LLLineEditor>("username_edit")->setPrevalidate(LLTextValidate::validateASCIIPrintableNoPipe);
 	getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
 
 	// change z sort of clickable text to be behind buttons
@@ -508,8 +507,16 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
 	LLSD identifier = credential->getIdentifier();
 	if((std::string)identifier["type"] == "agent") 
 	{
-		sInstance->getChild<LLUICtrl>("username_edit")->setValue((std::string)identifier["first_name"] + " " + 
-								(std::string)identifier["last_name"]);	
+		std::string firstname = identifier["first_name"].asString();
+		std::string lastname = identifier["last_name"].asString();
+	    std::string login_id = firstname;
+	    if (!lastname.empty() && lastname != "Resident")
+	    {
+		    // support traditional First Last name SLURLs
+		    login_id += " ";
+		    login_id += lastname;
+	    }
+		sInstance->getChild<LLUICtrl>("username_edit")->setValue(login_id);	
 	}
 	else if((std::string)identifier["type"] == "account")
 	{
@@ -573,7 +580,8 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
 	LL_INFOS2("Credentials", "Authentication") << "retrieving username:" << username << LL_ENDL;
 	// determine if the username is a first/last form or not.
 	size_t separator_index = username.find_first_of(' ');
-	if (separator_index == username.npos)
+	if (separator_index == username.npos
+		&& !LLGridManager::getInstance()->isSystemGrid())
 	{
 		LL_INFOS2("Credentials", "Authentication") << "account: " << username << LL_ENDL;
 		// single username, so this is a 'clear' identifier
@@ -590,9 +598,23 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
 	}
 	else
 	{
+		// Be lenient in terms of what separators we allow for two-word names
+		// and allow legacy users to login with firstname.lastname
+		separator_index = username.find_first_of(" ._");
 		std::string first = username.substr(0, separator_index);
-		std::string last = username.substr(separator_index, username.npos);
+		std::string last;
+		if (separator_index != username.npos)
+		{
+			last = username.substr(separator_index+1, username.npos);
 		LLStringUtil::trim(last);
+		}
+		else
+		{
+			// ...on Linden grids, single username users as considered to have
+			// last name "Resident"
+			// *TODO: Make login.cgi support "account_name" like above
+			last = "Resident";
+		}
 		
 		if (last.find_first_of(' ') == last.npos)
 		{
diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp
index 5cd4cea96d7bfbeb111ba20697c5d2494b7e0a12..b76a6bba2e4f96c8f5aaa14f55eed1cc36ca6d2f 100644
--- a/indra/newview/llpanelme.cpp
+++ b/indra/newview/llpanelme.cpp
@@ -26,17 +26,25 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "llpanelme.h"
+
+// Viewer includes
 #include "llpanelprofile.h"
 #include "llavatarconstants.h"
-#include "llpanelme.h"
 #include "llagent.h"
 #include "llagentcamera.h"
 #include "llagentwearables.h"
-#include "lliconctrl.h"
 #include "llsidetray.h"
+#include "llviewercontrol.h"
+#include "llviewerdisplayname.h"
+
+// Linden libraries
+#include "llavatarnamecache.h"		// IDEVO
+#include "lliconctrl.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"	// IDEVO
 #include "lltabcontainer.h"
 #include "lltexturectrl.h"
-#include "llviewercontrol.h"
 
 #define PICKER_SECOND_LIFE "2nd_life_pic"
 #define PICKER_FIRST_LIFE "real_world_pic"
@@ -174,6 +182,15 @@ void LLPanelMyProfileEdit::onOpen(const LLSD& key)
 	// Disable editing until data is loaded, or edited fields will be overwritten when data
 	// is loaded.
 	enableEditing(false);
+
+	// Only allow changing name if this region/grid supports it
+	bool use_display_names = LLAvatarNameCache::useDisplayNames();
+	LLUICtrl* set_name = getChild<LLUICtrl>("set_name");
+	set_name->setVisible(use_display_names);
+	set_name->setEnabled(use_display_names);
+	// force new avatar name fetch so we have latest update time
+	LLAvatarNameCache::fetch(gAgent.getID()); 
+
 	LLPanelMyProfile::onOpen(getAvatarId());
 }
 
@@ -207,13 +224,14 @@ void LLPanelMyProfileEdit::processProfileProperties(const LLAvatarData* avatar_d
 
 	getChild<LLUICtrl>("show_in_search_checkbox")->setValue((BOOL)(avatar_data->flags & AVATAR_ALLOW_PUBLISH));
 
-	std::string first, last;
-	BOOL found = gCacheName->getName(avatar_data->avatar_id, first, last);
-	if (found)
-	{
-		getChild<LLUICtrl>("name_text")->setTextArg("[FIRST]", first);
-		getChild<LLUICtrl>("name_text")->setTextArg("[LAST]", last);
-	}
+	LLAvatarNameCache::get(avatar_data->avatar_id,
+		boost::bind(&LLPanelMyProfileEdit::onNameCache, this, _1, _2));
+}
+
+void LLPanelMyProfileEdit::onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
+{
+	getChild<LLUICtrl>("user_name")->setValue( av_name.mDisplayName );
+	getChild<LLUICtrl>("user_slid")->setValue( av_name.mUsername );
 }
 
 BOOL LLPanelMyProfileEdit::postBuild()
@@ -223,6 +241,9 @@ BOOL LLPanelMyProfileEdit::postBuild()
 	getChild<LLUICtrl>("partner_edit_link")->setTextArg("[URL]", getString("partner_edit_link_url"));
 	getChild<LLUICtrl>("my_account_link")->setTextArg("[URL]", getString("my_account_link_url"));
 
+	getChild<LLUICtrl>("set_name")->setCommitCallback(
+		boost::bind(&LLPanelMyProfileEdit::onClickSetName, this));
+
 	return LLPanelAvatarProfile::postBuild();
 }
 /**
@@ -250,8 +271,10 @@ void LLPanelMyProfileEdit::resetData()
 {
 	LLPanelMyProfile::resetData();
 
-	getChild<LLUICtrl>("name_text")->setTextArg("[FIRST]", LLStringUtil::null);
-	getChild<LLUICtrl>("name_text")->setTextArg("[LAST]", LLStringUtil::null);
+	//childSetTextArg("name_text", "[FIRST]", LLStringUtil::null);
+	//childSetTextArg("name_text", "[LAST]", LLStringUtil::null);
+	getChild<LLUICtrl>("user_name")->setValue( LLSD() );
+	getChild<LLUICtrl>("user_slid")->setValue( LLSD() );
 }
 
 void LLPanelMyProfileEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
@@ -263,6 +286,140 @@ void LLPanelMyProfileEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
 	mTextureEditIconMap[ctrl->getName()]->setVisible(FALSE);
 }
 
+void LLPanelMyProfileEdit::onCacheSetName(bool success,
+										  const std::string& reason,
+										  const LLSD& content)
+{
+	if (success)
+	{
+		// Inform the user that the change took place, but will take a while
+		// to percolate.
+		LLSD args;
+		args["DISPLAY_NAME"] = content["display_name"];
+		LLNotificationsUtil::add("SetDisplayNameSuccess", args);
+
+		// Re-fetch my name, as it may have been sanitized by the service
+		LLAvatarNameCache::get(getAvatarId(),
+			boost::bind(&LLPanelMyProfileEdit::onNameCache, this, _1, _2));
+		return;
+	}
+
+	// Request failed, notify the user
+	std::string error_tag = content["error_tag"].asString();
+	llinfos << "set name failure error_tag " << error_tag << llendl;
+
+	// We might have a localized string for this message
+	// error_args will usually be empty from the server.
+	if (!error_tag.empty()
+		&& LLNotifications::getInstance()->templateExists(error_tag))
+	{
+		LLNotificationsUtil::add(error_tag);
+		return;
+	}
+
+	// The server error might have a localized message for us
+	std::string lang_code = LLUI::getLanguage();
+	LLSD error_desc = content["error_description"];
+	if (error_desc.has( lang_code ))
+	{
+		LLSD args;
+		args["MESSAGE"] = error_desc[lang_code].asString();
+		LLNotificationsUtil::add("GenericAlert", args);
+		return;
+	}
+
+	// No specific error, throw a generic one
+	LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
+}
+
+void LLPanelMyProfileEdit::onDialogSetName(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (option == 0 || option == 1)
+	{
+		LLUUID agent_id = notification["payload"]["agent_id"];
+		if (agent_id.isNull()) return;
+
+		std::string display_name_utf8;
+		if (option == 0)
+		{
+			// user gave us a name
+			display_name_utf8 = response["display_name"].asString();
+		}
+		else
+		{
+			// reset back to People API default
+			display_name_utf8 = "";
+		}
+
+		const U32 DISPLAY_NAME_MAX_LENGTH = 31; // characters, not bytes
+		LLWString display_name_wstr = utf8string_to_wstring(display_name_utf8);
+		if (display_name_wstr.size() > DISPLAY_NAME_MAX_LENGTH)
+		{
+			LLSD args;
+			args["LENGTH"] = llformat("%d", DISPLAY_NAME_MAX_LENGTH);
+			LLNotificationsUtil::add("SetDisplayNameFailedLength", args);
+			return;
+		}
+
+		LLViewerDisplayName::set(display_name_utf8,
+			boost::bind(&LLPanelMyProfileEdit::onCacheSetName, this,
+				_1, _2, _3));
+	}
+}
+
+void LLPanelMyProfileEdit::onClickSetName()
+{	
+	LLAvatarNameCache::get(getAvatarId(), 
+			boost::bind(&LLPanelMyProfileEdit::onAvatarNameCache,
+				this, _1, _2));
+}
+
+void LLPanelMyProfileEdit::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
+{
+	if (av_name.mDisplayName.empty())
+	{
+		// something is wrong, tell user to try again later
+		LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
+		return;		
+	}
+
+	llinfos << "name-change now " << LLDate::now() << " next_update "
+		<< LLDate(av_name.mNextUpdate) << llendl;
+	F64 now_secs = LLDate::now().secondsSinceEpoch();
+
+	if (now_secs < av_name.mNextUpdate)
+	{
+		// if the update time is more than a year in the future, it means updates have been blocked
+		// show a more general message
+        const int YEAR = 60*60*24*365; 
+		if (now_secs + YEAR < av_name.mNextUpdate)
+		{
+			LLNotificationsUtil::add("SetDisplayNameBlocked");
+			return;
+		}
+	
+		// ...can't update until some time in the future
+		F64 next_update_local_secs =
+			av_name.mNextUpdate - LLStringOps::getLocalTimeOffset();
+		LLDate next_update_local(next_update_local_secs);
+		// display as "July 18 12:17 PM"
+		std::string next_update_string =
+		next_update_local.toHTTPDateString("%B %d %I:%M %p");
+		LLSD args;
+		args["TIME"] = next_update_string;
+		LLNotificationsUtil::add("SetDisplayNameFailedLockout", args);
+		return;
+	}
+	
+	LLSD args;
+	args["DISPLAY_NAME"] = av_name.mDisplayName;
+	LLSD payload;
+	payload["agent_id"] = agent_id;
+	LLNotificationsUtil::add("SetDisplayName", args, payload, 
+		boost::bind(&LLPanelMyProfileEdit::onDialogSetName, this, _1, _2));
+}
+
 void LLPanelMyProfileEdit::enableEditing(bool enable)
 {
 	getChildView("2nd_life_pic")->setEnabled(enable);
diff --git a/indra/newview/llpanelme.h b/indra/newview/llpanelme.h
index 984ba1e9a2a6ede82b35f1489a835a51ee877cbd..93264922f61e40f5c6f05c0b64ef77a6039cc5aa 100644
--- a/indra/newview/llpanelme.h
+++ b/indra/newview/llpanelme.h
@@ -28,8 +28,9 @@
 #define LL_LLPANELMEPROFILE_H
 
 #include "llpanel.h"
-#include "llpanelavatar.h"
+#include "llpanelprofile.h"
 
+class LLAvatarName;
 class LLPanelMyProfileEdit;
 class LLPanelProfile;
 class LLIconCtrl;
@@ -83,11 +84,16 @@ class LLPanelMyProfileEdit : public LLPanelMyProfile
 	/*virtual*/void resetData();
 
 	void processProfileProperties(const LLAvatarData* avatar_data);
+	void onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
 
 private:
 	void initTexturePickerMouseEvents();
 	void onTexturePickerMouseEnter(LLUICtrl* ctrl);
 	void onTexturePickerMouseLeave(LLUICtrl* ctrl);
+	void onClickSetName();
+	void onDialogSetName(const LLSD& notification, const LLSD& response);
+	void onCacheSetName(bool success, const std::string& reason, const LLSD& content);
+	void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
 
 	/**
 	 * Enabled/disables controls to prevent overwriting edited data upon receiving
@@ -95,6 +101,8 @@ class LLPanelMyProfileEdit : public LLPanelMyProfile
 	 */
 	void enableEditing(bool enable);
 
+
+
 private:
 	// map TexturePicker name => Edit Icon pointer should be visible while hovering Texture Picker
 	typedef std::map<std::string, LLIconCtrl*> texture_edit_icon_map_t;
diff --git a/indra/newview/llpanelmediasettingspermissions.cpp b/indra/newview/llpanelmediasettingspermissions.cpp
index 339376cbf6a5c7b947a7b209b4bb8c11a8a56696..1e6b953d4e7e10dbdaf55f270b66c21de4f3f36c 100644
--- a/indra/newview/llpanelmediasettingspermissions.cpp
+++ b/indra/newview/llpanelmediasettingspermissions.cpp
@@ -101,16 +101,16 @@ void LLPanelMediaSettingsPermissions::draw()
 		if(mPermsGroupName)
 		{
 			mPermsGroupName->setNameID(group_id, true);
-		};
+		}
 	}
 	else
 	{
 		if(mPermsGroupName)
 		{
 			mPermsGroupName->setNameID(LLUUID::null, TRUE);
-			mPermsGroupName->refresh(LLUUID::null, LLStringUtil::null, LLStringUtil::null, true);
-		};
-	};
+			mPermsGroupName->refresh(LLUUID::null, std::string(), true);
+		}
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -192,7 +192,7 @@ void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& me
             data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
         };
     };
-	
+
 	// *NOTE: If any of a particular flavor is tentative, we have to disable 
 	// them all because of an architectural issue: namely that we represent 
 	// these as a bit field, and we can't selectively apply only one bit to all selected
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 06ba08b51c9ca4b90a8cca81a50aa767552e2ba7..6a59b58d3467940d3ddff7347c534229cb2f8d48 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -27,6 +27,7 @@
 #include "llviewerprecompiledheaders.h"
 
 // libs
+#include "llavatarname.h"
 #include "llfloaterreg.h"
 #include "llmenugl.h"
 #include "llnotificationsutil.h"
@@ -1148,12 +1149,10 @@ void LLPanelPeople::onActivateButtonClicked()
 }
 
 // static
-void LLPanelPeople::onAvatarPicked(
-		const std::vector<std::string>& names,
-		const uuid_vec_t& ids)
+void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
 {
 	if (!names.empty() && !ids.empty())
-		LLAvatarActions::requestFriendshipDialog(ids[0], names[0]);
+		LLAvatarActions::requestFriendshipDialog(ids[0], names[0].getCompleteName());
 }
 
 void LLPanelPeople::onGroupPlusButtonClicked()
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index d0913ee756c7740bfc0b5a8a39951534791462d5..f5ff09b0380529a4781174eef67f094504078934 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -32,10 +32,11 @@
 #include "llcallingcard.h" // for avatar tracker
 #include "llvoiceclient.h"
 
-class LLFilterEditor;
-class LLTabContainer;
 class LLAvatarList;
+class LLAvatarName;
+class LLFilterEditor;
 class LLGroupList;
+class LLTabContainer;
 
 class LLPanelPeople 
 	: public LLPanel
@@ -122,9 +123,7 @@ class LLPanelPeople
 	bool					onNearbyViewSortMenuItemCheck(const LLSD& userdata);
 
 	// misc callbacks
-	static void				onAvatarPicked(
-								const std::vector<std::string>& names,
-								const uuid_vec_t& ids);
+	static void				onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
 
 	void					onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list);
 
diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp
index e35574be6cadf6dbe9ef8537822fe53d2e1d8519..59130236f262162a1a485b0afd9349176bab66d3 100644
--- a/indra/newview/llpanelpermissions.cpp
+++ b/indra/newview/llpanelpermissions.cpp
@@ -379,7 +379,7 @@ void LLPanelPermissions::refresh()
 		if (mLabelGroupName)
 		{
 			mLabelGroupName->setNameID(LLUUID::null, TRUE);
-			mLabelGroupName->refresh(LLUUID::null,LLStringUtil::null, LLStringUtil::null, TRUE);
+			mLabelGroupName->refresh(LLUUID::null, std::string(), true);
 			mLabelGroupName->setEnabled(FALSE);
 		}
 	}
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index a5c3c9faefc00dc61fc81d08f05f3038b7952c42..6062c1797ada03b5195796ed7d157ae87b5164d5 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -229,9 +229,9 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
 		LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data);
 		if(avatar_picks && getAvatarId() == avatar_picks->target_id)
 		{
-			std::string name, second_name;
-			gCacheName->getName(getAvatarId(),name,second_name);
-			getChild<LLUICtrl>("pick_title")->setTextArg("[NAME]", name);
+			std::string full_name;
+			gCacheName->getFullName(getAvatarId(), full_name);
+			getChild<LLUICtrl>("pick_title")->setTextArg("[NAME]", full_name);
 			
 			// Save selection, to be able to edit same item after saving changes. See EXT-3023.
 			LLUUID selected_id = mPicksList->getSelectedValue()[PICK_ID];
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index bbaffda2f224b094344aebba254ccb4cdd851dfc..9cbb512e7022a31d40cb17ed08a893a323165a0c 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -28,6 +28,7 @@
 
 #include "llpanelplaceinfo.h"
 
+#include "llavatarname.h"
 #include "llsdutil.h"
 
 #include "llsdutil_math.h"
@@ -304,9 +305,15 @@ void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit*
 }
 
 // static
-void LLPanelPlaceInfo::nameUpdatedCallback(LLTextBox* text,
-										   const std::string& first,
-										   const std::string& last)
+void LLPanelPlaceInfo::onNameCache(LLTextBox* text, const std::string& full_name)
 {
-	text->setText(first + " " + last);
+	text->setText(full_name);
+}
+
+// static
+void LLPanelPlaceInfo::onAvatarNameCache(const LLUUID& agent_id,
+										 const LLAvatarName& av_name,
+										 LLTextBox* text)
+{
+	text->setText( av_name.getCompleteName() );
 }
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 1e0975a898c732ac5a757c5edab9087edc2621ce..64f0b6b5503898e84746a10d35b5cfc406af52a2 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -34,6 +34,7 @@
 
 #include "llremoteparcelrequest.h"
 
+class LLAvatarName;
 class LLExpandableTextBox;
 class LLIconCtrl;
 class LLInventoryItem;
@@ -96,9 +97,10 @@ class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
 	void createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel);
 
 protected:
-	static void nameUpdatedCallback(LLTextBox* text,
-									const std::string& first,
-									const std::string& last);
+	static void onNameCache(LLTextBox* text, const std::string& full_name);
+	static void onAvatarNameCache(const LLUUID& agent_id,
+								  const LLAvatarName& av_name,
+								  LLTextBox* text);
 
 	/**
 	 * mParcelID is valid only for remote places, in other cases it's null. See resetLocation() 
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
index ee30c928c29045537639de9b5431c9e6f64a60e3..e57a5aeb28cff3d396a359e2960fb7b4e78877a6 100644
--- a/indra/newview/llpanelplaceprofile.cpp
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -28,6 +28,7 @@
 
 #include "llpanelplaceprofile.h"
 
+#include "llavatarnamecache.h"
 #include "llparcel.h"
 #include "message.h"
 
@@ -45,6 +46,7 @@
 #include "llappviewer.h"
 #include "llcallbacklist.h"
 #include "llbuycurrencyhtml.h"
+#include "llslurl.h"
 #include "llstatusbar.h"
 #include "llviewercontrol.h"
 #include "llviewerparcelmgr.h"
@@ -430,11 +432,11 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
 			if(!parcel->getGroupID().isNull())
 			{
 				// FIXME: Using parcel group as region group.
-				gCacheName->get(parcel->getGroupID(), TRUE,
-								boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mRegionGroupText, _2, _3));
+				gCacheName->getGroup(parcel->getGroupID(),
+								boost::bind(&LLPanelPlaceInfo::onNameCache, mRegionGroupText, _2));
 
-				gCacheName->get(parcel->getGroupID(), TRUE,
-								boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mParcelOwner, _2, _3));
+				gCacheName->getGroup(parcel->getGroupID(),
+								boost::bind(&LLPanelPlaceInfo::onNameCache, mParcelOwner, _2));
 			}
 			else
 			{
@@ -446,10 +448,12 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
 		else
 		{
 			// Figure out the owner's name
-			gCacheName->get(parcel->getOwnerID(), FALSE,
-							boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mParcelOwner, _2, _3));
-			gCacheName->get(region->getOwner(), FALSE,
-							boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mRegionOwnerText, _2, _3));
+			std::string parcel_owner =
+				LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString();
+			mParcelOwner->setText(parcel_owner);
+			LLAvatarNameCache::get(region->getOwner(),
+								   boost::bind(&LLPanelPlaceInfo::onAvatarNameCache,
+											   _1, _2, mRegionOwnerText));
 		}
 
 		if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus())
@@ -471,9 +475,10 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
 		const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID();
 		if(auth_buyer_id.notNull())
 		{
-			gCacheName->get(auth_buyer_id, TRUE,
-							boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mSaleToText, _2, _3));
-
+			LLAvatarNameCache::get(auth_buyer_id,
+								   boost::bind(&LLPanelPlaceInfo::onAvatarNameCache,
+											   _1, _2, mSaleToText));
+			
 			// Show sales info to a specific person or a group he belongs to.
 			if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id))
 			{
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
index 0546c1858337300983bf31ad65aa86e3a7530ccf..d2bcee80760344a64b5bd5c0bb1c4a6fd7ad8fba 100644
--- a/indra/newview/llpanelprofile.h
+++ b/indra/newview/llpanelprofile.h
@@ -27,7 +27,6 @@
 #ifndef LL_LLPANELPROFILE_H
 #define LL_LLPANELPROFILE_H
 
-#include "llviewerprecompiledheaders.h"
 #include "llpanel.h"
 #include "llpanelavatar.h"
 
diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp
index c0f504fef66bf0be674c7eb5ec7205d73b25e7e1..dfbd3552478aa83b02bbff05125699d9dc7d821d 100644
--- a/indra/newview/llpanelprofileview.cpp
+++ b/indra/newview/llpanelprofileview.cpp
@@ -26,11 +26,12 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "llpanelprofileview.h"
+
 #include "llavatarconstants.h"
+#include "llavatarnamecache.h"	// IDEVO
 #include "lluserrelations.h"
 
-#include "llpanelprofileview.h"
-
 #include "llavatarpropertiesprocessor.h"
 #include "llcallingcard.h"
 #include "llpanelavatar.h"
@@ -98,11 +99,15 @@ void LLPanelProfileView::onOpen(const LLSD& key)
 	if(id.notNull() && getAvatarId() != id)
 	{
 		setAvatarId(id);
+
+		// clear name fields, which might have old data
+		getChild<LLUICtrl>("user_name")->setValue( LLSD() );
+		getChild<LLUICtrl>("user_slid")->setValue( LLSD() );
 	}
 
 	// Update the avatar name.
-	gCacheName->get(getAvatarId(), FALSE,
-		boost::bind(&LLPanelProfileView::onAvatarNameCached, this, _1, _2, _3, _4));
+	LLAvatarNameCache::get(getAvatarId(),
+		boost::bind(&LLPanelProfileView::onAvatarNameCache, this, _1, _2));
 
 	updateOnlineStatus();
 
@@ -192,10 +197,26 @@ void LLPanelProfileView::processOnlineStatus(bool online)
 	mStatusText->setValue(status);
 }
 
-void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& first_name, const std::string& last_name, BOOL is_group)
+void LLPanelProfileView::onAvatarNameCache(const LLUUID& agent_id,
+										   const LLAvatarName& av_name)
 {
-	llassert(getAvatarId() == id);
-	getChild<LLUICtrl>("user_name", FALSE)->setValue(first_name + " " + last_name);
+	getChild<LLUICtrl>("user_name")->setValue( av_name.mDisplayName );
+	getChild<LLUICtrl>("user_name_small")->setValue( av_name.mDisplayName );
+	getChild<LLUICtrl>("user_slid")->setValue( av_name.mUsername );
+
+	// show smaller display name if too long to display in regular size
+	if (getChild<LLTextBox>("user_name")->getTextPixelWidth() > getChild<LLTextBox>("user_name")->getRect().getWidth())
+	{
+		getChild<LLUICtrl>("user_name_small")->setVisible( true );
+		getChild<LLUICtrl>("user_name")->setVisible( false );
+	}
+	else
+	{
+		getChild<LLUICtrl>("user_name_small")->setVisible( false );
+		getChild<LLUICtrl>("user_name")->setVisible( true );
+
+	}
+
 }
 
 // EOF
diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h
index 9972b085d8ad12b06b1d64d6e78e501105369d12..153496bfd03ad2a3a16ff67d55c07ed16bd5eabd 100644
--- a/indra/newview/llpanelprofileview.h
+++ b/indra/newview/llpanelprofileview.h
@@ -33,6 +33,7 @@
 #include "llagent.h"
 #include "lltooldraganddrop.h"
 
+class LLAvatarName;
 class LLPanelProfile;
 class LLPanelProfileTab;
 class LLTextBox;
@@ -93,11 +94,11 @@ class LLPanelProfileView : public LLPanelProfile
 private:
 	// LLCacheName will call this function when avatar name is loaded from server.
 	// This is required to display names that have not been cached yet.
-	void onAvatarNameCached(
-		const LLUUID& id, 
-		const std::string& first_name,
-		const std::string& last_name,
-		BOOL is_group);
+//	void onNameCache(
+//		const LLUUID& id, 
+//		const std::string& full_name,
+//		bool is_group);
+	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
 
 	LLTextBox* mStatusText;
 	AvatarStatusObserver* mAvatarStatusObserver;
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index c8aa9ac91e6c34570384ee8fde3308886f92e4bb..01b3b5572e3477eb8800321edd550e9f512a56e9 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -331,11 +331,18 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
 			if ( item )
 			{
 				std::string name = item->getAvatarName();
+				std::string tooltip = item->getAvatarToolTip();
 				size_t found = name.find(moderator_indicator);
 				if (found != std::string::npos)
 				{
 					name.erase(found, moderator_indicator_len);
-					item->setName(name);
+					item->setAvatarName(name);
+				}
+				found = tooltip.find(moderator_indicator);
+				if (found != tooltip.npos)
+				{
+					tooltip.erase(found, moderator_indicator_len);
+					item->setAvatarToolTip(tooltip);
 				}
 			}
 		}
@@ -351,12 +358,20 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
 			if ( item )
 			{
 				std::string name = item->getAvatarName();
+				std::string tooltip = item->getAvatarToolTip();
 				size_t found = name.find(moderator_indicator);
 				if (found == std::string::npos)
 				{
 					name += " ";
 					name += moderator_indicator;
-					item->setName(name);
+					item->setAvatarName(name);
+				}
+				found = tooltip.find(moderator_indicator);
+				if (found == std::string::npos)
+				{
+					tooltip += " ";
+					tooltip += moderator_indicator;
+					item->setAvatarToolTip(tooltip);
 				}
 			}
 		}
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index 731079fb5d6fc6a45c2e503e706903111f273ce9..ac9d2702762365ddbaf4fb21611b6edecb310ea2 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -275,11 +275,12 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
 
 	if (item->getCreatorUUID().notNull())
 	{
-		std::string name;
-		gCacheName->getFullName(item->getCreatorUUID(), name);
+		LLUUID creator_id = item->getCreatorUUID();
+		std::string name =
+			LLSLURL("agent", creator_id, "completename").getSLURLString();
 		getChildView("BtnCreator")->setEnabled(TRUE);
 		getChildView("LabelCreatorTitle")->setEnabled(TRUE);
-		getChildView("LabelCreatorName")->setEnabled(TRUE);
+		getChildView("LabelCreatorName")->setEnabled(FALSE);
 		getChild<LLUICtrl>("LabelCreatorName")->setValue(name);
 	}
 	else
@@ -302,11 +303,12 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
 		}
 		else
 		{
-			gCacheName->getFullName(perm.getOwner(), name);
+			LLUUID owner_id = perm.getOwner();
+			name = LLSLURL("agent", owner_id, "completename").getSLURLString();
 		}
 		getChildView("BtnOwner")->setEnabled(TRUE);
 		getChildView("LabelOwnerTitle")->setEnabled(TRUE);
-		getChildView("LabelOwnerName")->setEnabled(TRUE);
+		getChildView("LabelOwnerName")->setEnabled(FALSE);
 		getChild<LLUICtrl>("LabelOwnerName")->setValue(name);
 	}
 	else
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
index 4552088cadfee9a602d180898175bb7c8f0f705a..47d904dfcc7d15567dd8ead74b57974999f871c1 100644
--- a/indra/newview/llsidepaneltaskinfo.cpp
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -345,7 +345,7 @@ void LLSidepanelTaskInfo::refresh()
 		if (mLabelGroupName)
 		{
 			mLabelGroupName->setNameID(LLUUID::null, TRUE);
-			mLabelGroupName->refresh(LLUUID::null,LLStringUtil::null, LLStringUtil::null, TRUE);
+			mLabelGroupName->refresh(LLUUID::null, std::string(), true);
 			mLabelGroupName->setEnabled(FALSE);
 		}
 	}
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 196ed5e0bbdd6022b862accaf46acb709c4c0653..40aea058397345450d5216f98b24eec130a67942 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -70,13 +70,13 @@ void LLSpeaker::lookupName()
 {
 	if (mDisplayName.empty())
 	{
-		gCacheName->get(mID, FALSE, boost::bind(&LLSpeaker::onAvatarNameLookup, this, _1, _2, _3, _4));
+		gCacheName->get(mID, false, boost::bind(&LLSpeaker::onNameCache, this, _1, _2, _3));
 	}
 }
 
-void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+void LLSpeaker::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group)
 {
-	mDisplayName = first + " " + last;
+	mDisplayName = full_name;
 }
 
 bool LLSpeaker::isInVoiceChannel()
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index 08fb4052659b7c45d2b1bf462902a200ce941ed7..35f2ee7056235d9d12e1b77a0ff36b5fcbd70825 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -60,7 +60,7 @@ class LLSpeaker : public LLRefCount, public LLOldEvents::LLObservable, public LL
 	~LLSpeaker() {};
 	void lookupName();
 
-	void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+	void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
 
 	bool isInVoiceChannel();
 
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 975d1f9f32cf77eebfca8057baf5fde16890fdff..b70b3662a7a2c68959a28461fe5092be4b8e2f4d 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -46,6 +46,7 @@
 #endif
 
 #include "llares.h"
+#include "llavatarnamecache.h"
 #include "lllandmark.h"
 #include "llcachename.h"
 #include "lldir.h"
@@ -261,11 +262,10 @@ void apply_udp_blacklist(const std::string& csv);
 bool process_login_success_response();
 void transition_back_to_login_panel(const std::string& emsg);
 
-void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group)
+void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is_group)
 {
-	LLNameListCtrl::refreshAll(id, firstname, lastname, is_group);
-	LLNameBox::refreshAll(id, firstname, lastname, is_group);
-	LLNameEditor::refreshAll(id, firstname, lastname, is_group);
+	LLNameBox::refreshAll(id, full_name, is_group);
+	LLNameEditor::refreshAll(id, full_name, is_group);
 	
 	// TODO: Actually be intelligent about the refresh.
 	// For now, just brute force refresh the dialogs.
@@ -1279,16 +1279,7 @@ bool idle_startup()
 
 		gXferManager->registerCallbacks(gMessageSystem);
 
-		if ( gCacheName == NULL )
-		{
-			gCacheName = new LLCacheName(gMessageSystem);
-			gCacheName->addObserver(&callback_cache_name);
-			gCacheName->LocalizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting"));
-			gCacheName->LocalizeCacheName("nobody", LLTrans::getString("AvatarNameNobody"));
-			gCacheName->LocalizeCacheName("none", LLTrans::getString("GroupNameNone"));
-			// Load stored cache if possible
-            LLAppViewer::instance()->loadNameCache();
-		}
+		LLStartUp::initNameCache();
 
 		// update the voice settings *after* gCacheName initialization
 		// so that we can construct voice UI that relies on the name cache
@@ -1630,7 +1621,6 @@ bool idle_startup()
 			LLClassifiedInfo::loadCategories(classified_categories);
 		}
 
-
 		// This method MUST be called before gInventory.findCategoryUUIDForType because of 
 		// gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.
 		gInventory.buildParentChildMap();
@@ -2675,6 +2665,33 @@ void LLStartUp::fontInit()
 	LLFontGL::loadDefaultFonts();
 }
 
+void LLStartUp::initNameCache()
+{
+	// Can be called multiple times
+	if ( gCacheName ) return;
+
+	gCacheName = new LLCacheName(gMessageSystem);
+	gCacheName->addObserver(&callback_cache_name);
+	gCacheName->localizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting"));
+	gCacheName->localizeCacheName("nobody", LLTrans::getString("AvatarNameNobody"));
+	gCacheName->localizeCacheName("none", LLTrans::getString("GroupNameNone"));
+	// Load stored cache if possible
+	LLAppViewer::instance()->loadNameCache();
+
+	// Start cache in not-running state until we figure out if we have
+	// capabilities for display name lookup
+	LLAvatarNameCache::initClass(false);
+	LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames"));
+}
+
+void LLStartUp::cleanupNameCache()
+{
+	LLAvatarNameCache::cleanupClass();
+
+	delete gCacheName;
+	gCacheName = NULL;
+}
+
 bool LLStartUp::dispatchURL()
 {
 	// ok, if we've gotten this far and have a startup URL
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index e79aa0dbee296a4715db4a9c6865496cfeec3dc0..be1043cf910a05c8f1f22f7b97d1e3d9b2d7e385 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -87,8 +87,12 @@ class LLStartUp
 	// Load default fonts not already loaded at start screen
 	static void fontInit();
 
+	static void initNameCache();
+	
 	static void copyLibraryGestures(const std::string& same_gender_gestures);
 
+	static void cleanupNameCache();
+
 	// outfit_folder_name can be a folder anywhere in your inventory, 
 	// but the name must be a case-sensitive exact match.
 	// gender_name is either "male" or "female"
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 750fbe54a725573949dcb62fb01e56f4e399a5ab..092b31516bbeb482243c79b943f0a4eaed63a4de 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -26,14 +26,15 @@
 
 #include "llviewerprecompiledheaders.h" // must be first include
 
+#include "llsyswellwindow.h"
+
 #include "llagent.h"
+#include "llavatarnamecache.h"
 
 #include "llflatlistview.h"
 #include "llfloaterreg.h"
 #include "llnotifications.h"
 
-#include "llsyswellwindow.h"
-
 #include "llbottomtray.h"
 #include "llscriptfloater.h"
 #include "llviewercontrol.h"
@@ -278,13 +279,30 @@ LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID&
 	mChiclet->setOtherParticipantId(otherParticipantId);
 	mChiclet->setVisible(true);
 
-	LLTextBox* contactName = getChild<LLTextBox>("contact_name");
-	contactName->setValue(name);
+	if (im_chiclet_type == LLIMChiclet::TYPE_IM)
+	{
+		LLAvatarNameCache::get(otherParticipantId,
+			boost::bind(&LLIMWellWindow::RowPanel::onAvatarNameCache,
+				this, _1, _2));
+	}
+	else
+	{
+		LLTextBox* contactName = getChild<LLTextBox>("contact_name");
+		contactName->setValue(name);
+	}
 
 	mCloseBtn = getChild<LLButton>("hide_btn");
 	mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::RowPanel::onClosePanel, this));
 }
 
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::RowPanel::onAvatarNameCache(const LLUUID& agent_id,
+												 const LLAvatarName& av_name)
+{
+	LLTextBox* contactName = getChild<LLTextBox>("contact_name");
+	contactName->setValue( av_name.getCompleteName() );
+}
+
 //---------------------------------------------------------------------------------
 void LLIMWellWindow::RowPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
 {
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 5854deb840af3d58749c1383e9b6edaa980d3096..9f8ab0181088186d780f615782e01bfda607ba24 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -37,6 +37,7 @@
 
 #include "boost/shared_ptr.hpp"
 
+class LLAvatarName;
 class LLFlatListView;
 class LLChiclet;
 class LLIMChiclet;
@@ -202,6 +203,7 @@ class LLIMWellWindow : public LLSysWellWindow, LLIMSessionObserver, LLInitClass<
 
 	private:
 		static const S32 CHICLET_HPAD = 10;
+		void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
 		void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param);
 		void onClosePanel();
 	public:
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
index 4c75b07ae8e0de920ac3ca4fb56d573af2e7557f..da81c9634d5ac1c0941c50180ed3ebd8805313a4 100644
--- a/indra/newview/lltoastgroupnotifypanel.cpp
+++ b/indra/newview/lltoastgroupnotifypanel.cpp
@@ -36,6 +36,7 @@
 #include "llnotifications.h"
 #include "llviewertexteditor.h"
 
+#include "llavatarnamecache.h"
 #include "lluiconstants.h"
 #include "llui.h"
 #include "llviewercontrol.h"
@@ -67,7 +68,11 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
 	pGroupIcon->setValue(groupData.mInsigniaID);
 
 	//header title
-	const std::string& from_name = payload["sender_name"].asString();
+	std::string from_name = payload["sender_name"].asString();
+	if (LLAvatarNameCache::useDisplayNames())
+	{
+		from_name = LLCacheName::buildUsername(from_name);
+	}
 	std::stringstream from;
 	from << from_name << "/" << groupData.mName;
 	LLTextBox* pTitleText = getChild<LLTextBox>("title");
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index 82ccca433026f930da8565589b08976be3e8d71e..a97c8360a466f5c129450ca343d2ab9a20adee00 100644
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -141,7 +141,8 @@ void LLToastIMPanel::spawnNameToolTip()
 {
 	// Spawn at right side of the name textbox.
 	LLRect sticky_rect = mAvatarName->calcScreenRect();
-	S32 icon_x = llmin(sticky_rect.mLeft + mAvatarName->getTextPixelWidth() + 3, sticky_rect.mRight - 16);
+	S32 icon_x =
+		llmin(sticky_rect.mLeft + mAvatarName->getTextPixelWidth() + 3, sticky_rect.mRight);
 	LLCoordGL pos(icon_x, sticky_rect.mTop);
 
 	LLToolTip::Params params;
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index d8be70e54698b36ca8b3e7a438609811742aa33d..6c45b7cc60f0b26ed856c44f2311040244140309 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -34,6 +34,7 @@
 
 #include "llagent.h"
 #include "llagentcamera.h"
+#include "llavatarnamecache.h"
 #include "llviewercontrol.h"
 #include "llfocusmgr.h"
 //#include "llfirstuse.h"
@@ -855,23 +856,40 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l
 			|| !existing_inspector->getVisible()
 			|| existing_inspector->getKey()["avatar_id"].asUUID() != hover_object->getID())
 		{
-			std::string avatar_name;
+			// IDEVO: try to get display name + username
+			std::string final_name;
+			std::string full_name;
+			if (!gCacheName->getFullName(hover_object->getID(), full_name))
+			{
 			LLNameValue* firstname = hover_object->getNVPair("FirstName");
 			LLNameValue* lastname =  hover_object->getNVPair("LastName");
 			if (firstname && lastname)
 			{
-				avatar_name = llformat("%s %s", firstname->getString(), lastname->getString());
+					full_name = LLCacheName::buildFullName(
+						firstname->getString(), lastname->getString());
+				}
+				else
+				{
+					full_name = LLTrans::getString("TooltipPerson");
+				}
+			}
+
+			LLAvatarName av_name;
+			if (LLAvatarNameCache::useDisplayNames() && 
+				LLAvatarNameCache::get(hover_object->getID(), &av_name))
+			{
+				final_name = av_name.mDisplayName + " (" + av_name.mUsername + ")";
 			}
 			else
 			{
-				avatar_name = LLTrans::getString("TooltipPerson");
+				final_name = full_name;
 			}
-			
+
 			// *HACK: We may select this object, so pretend it was clicked
 			mPick = mHoverPick;
 			LLInspector::Params p;
 			p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
-			p.message(avatar_name);
+			p.message(final_name);
 			p.image.name("Inspector_I");
 			p.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));
 			p.visible_time_near(6.f);
diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp
index 8391c0f832a5bff6d41bcf0ac3d21da6165d9423..c3dd17def90f98d9391db9c7f1ea867db50c18b3 100644
--- a/indra/newview/lltracker.cpp
+++ b/indra/newview/lltracker.cpp
@@ -564,16 +564,16 @@ void LLTracker::renderBeacon(LLVector3d pos_global,
 	std::string text;
 	text = llformat( "%.0f m", to_vec.magVec());
 
-	LLWString wstr;
-	wstr += utf8str_to_wstring(label);
-	wstr += '\n';
-	wstr += utf8str_to_wstring(text);
+	std::string str;
+	str += label;
+	str += '\n';
+	str += text;
 
 	hud_textp->setFont(LLFontGL::getFontSansSerif());
 	hud_textp->setZCompare(FALSE);
 	hud_textp->setColor(LLColor4(1.f, 1.f, 1.f, llmax(0.2f, llmin(1.f,(dist-FADE_DIST)/FADE_DIST))));
 
-	hud_textp->setString(wstr);
+	hud_textp->setString(str);
 	hud_textp->setVertAlignment(LLHUDText::ALIGN_VERT_CENTER);
 	hud_textp->setPositionAgent(pos_agent);
 }
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index d0ad918c58b05dd954e791a5c21b54e36c0f74a1..46407ac44d911867748652afdf5c08a7616d58df 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -317,7 +317,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 	LLImageGL::updateStats(gFrameTimeSeconds);
 	
 	LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
-	LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("RenderShowGroupTitleAll") && gSavedSettings.getS32("AvatarNameTagMode"));
+	LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode"));
 	
 	gPipeline.mBackfaceCull = TRUE;
 	gFrameCount++;
diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bda0fe9737db08b7682b5a3ea47f95255c011fea
--- /dev/null
+++ b/indra/newview/llviewerdisplayname.cpp
@@ -0,0 +1,205 @@
+/** 
+ * @file llviewerdisplayname.cpp
+ * @brief Wrapper for display name functionality
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2010, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerdisplayname.h"
+
+// viewer includes
+#include "llagent.h"
+#include "llviewerregion.h"
+#include "llvoavatar.h"
+
+// library includes
+#include "llavatarnamecache.h"
+#include "llhttpclient.h"
+#include "llhttpnode.h"
+#include "llnotificationsutil.h"
+#include "llui.h"					// getLanguage()
+
+namespace LLViewerDisplayName
+{
+	// Fired when viewer receives server response to display name change
+	set_name_signal_t sSetDisplayNameSignal;
+}
+
+class LLSetDisplayNameResponder : public LLHTTPClient::Responder
+{
+public:
+	// only care about errors
+	/*virtual*/ void error(U32 status, const std::string& reason)
+	{
+		LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD());
+		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
+	}
+};
+
+void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot)
+{
+	// TODO: simple validation here
+
+	LLViewerRegion* region = gAgent.getRegion();
+	llassert(region);
+	std::string cap_url = region->getCapability("SetDisplayName");
+	if (cap_url.empty())
+	{
+		// this server does not support display names, report error
+		slot(false, "unsupported", LLSD());
+		return;
+	}
+
+	// People API can return localized error messages.  Indicate our
+	// language preference via header.
+	LLSD headers;
+	headers["Accept-Language"] = LLUI::getLanguage();
+
+	// People API requires both the old and new value to change a variable.
+	// Our display name will be in cache before the viewer's UI is available
+	// to request a change, so we can use direct lookup without callback.
+	LLAvatarName av_name;
+	if (!LLAvatarNameCache::get( gAgent.getID(), &av_name))
+	{
+		slot(false, "name unavailable", LLSD());
+		return;
+	}
+
+	// People API expects array of [ "old value", "new value" ]
+	LLSD change_array = LLSD::emptyArray();
+	change_array.append(av_name.mDisplayName);
+	change_array.append(display_name);
+	
+	llinfos << "Set name POST to " << cap_url << llendl;
+
+	// Record our caller for when the server sends back a reply
+	sSetDisplayNameSignal.connect(slot);
+	
+	// POST the requested change.  The sim will not send a response back to
+	// this request directly, rather it will send a separate message after it
+	// communicates with the back-end.
+	LLSD body;
+	body["display_name"] = change_array;
+	LLHTTPClient::post(cap_url, body, new LLSetDisplayNameResponder, headers);
+}
+
+class LLSetDisplayNameReply : public LLHTTPNode
+{
+	LOG_CLASS(LLSetDisplayNameReply);
+public:
+	/*virtual*/ void post(
+		LLHTTPNode::ResponsePtr response,
+		const LLSD& context,
+		const LLSD& input) const
+	{
+		LLSD body = input["body"];
+
+		S32 status = body["status"].asInteger();
+		bool success = (status == 200);
+		std::string reason = body["reason"].asString();
+		LLSD content = body["content"];
+
+		llinfos << "status " << status << " reason " << reason << llendl;
+
+		// If viewer's concept of display name is out-of-date, the set request
+		// will fail with 409 Conflict.  If that happens, fetch up-to-date
+		// name information.
+		if (status == 409)
+		{
+			LLUUID agent_id = gAgent.getID();
+			// Flush stale data
+			LLAvatarNameCache::erase( agent_id );
+			// Queue request for new data
+			LLAvatarName ignored;
+			LLAvatarNameCache::get( agent_id, &ignored );
+			// Kill name tag, as it is wrong
+			LLVOAvatar::invalidateNameTag( agent_id );
+		}
+
+		// inform caller of result
+		LLViewerDisplayName::sSetDisplayNameSignal(success, reason, content);
+		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
+	}
+};
+
+
+class LLDisplayNameUpdate : public LLHTTPNode
+{
+	/*virtual*/ void post(
+		LLHTTPNode::ResponsePtr response,
+		const LLSD& context,
+		const LLSD& input) const
+	{
+		LLSD body = input["body"];
+		LLUUID agent_id = body["agent_id"];
+		std::string old_display_name = body["old_display_name"];
+		// By convention this record is called "agent" in the People API
+		LLSD name_data = body["agent"];
+
+		// Inject the new name data into cache
+		LLAvatarName av_name;
+		av_name.fromLLSD( name_data );
+
+		llinfos << "name-update now " << LLDate::now()
+			<< " next_update " << LLDate(av_name.mNextUpdate)
+			<< llendl;
+
+		// Name expiration time may be provided in headers, or we may use a
+		// default value
+		// *TODO: get actual headers out of ResponsePtr
+		//LLSD headers = response->mHeaders;
+		LLSD headers;
+		av_name.mExpires = 
+			LLAvatarNameCache::nameExpirationFromHeaders(headers);
+
+		LLAvatarNameCache::insert(agent_id, av_name);
+
+		// force name tag to update
+		LLVOAvatar::invalidateNameTag(agent_id);
+
+		// Don't show a notification for my name, because we'll show a nicer
+		// dialog
+		if (agent_id != gAgent.getID())
+		{
+			LLSD args;
+			args["OLD_NAME"] = old_display_name;
+			args["SLID"] = av_name.mUsername;
+			args["NEW_NAME"] = av_name.mDisplayName;
+			LLNotificationsUtil::add("DisplayNameUpdate", args);
+		}
+	}
+};
+
+LLHTTPRegistration<LLSetDisplayNameReply>
+    gHTTPRegistrationMessageSetDisplayNameReply(
+		"/message/SetDisplayNameReply");
+
+LLHTTPRegistration<LLDisplayNameUpdate>
+    gHTTPRegistrationMessageDisplayNameUpdate(
+		"/message/DisplayNameUpdate");
diff --git a/indra/newview/llviewerdisplayname.h b/indra/newview/llviewerdisplayname.h
new file mode 100644
index 0000000000000000000000000000000000000000..c77388531bc977d77a8cc801e634733991c7399f
--- /dev/null
+++ b/indra/newview/llviewerdisplayname.h
@@ -0,0 +1,53 @@
+/** 
+ * @file llviewerdisplayname.h
+ * @brief Wrapper for display name functionality
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2010, 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 LLVIEWERDISPLAYNAME_H
+#define LLVIEWERDISPLAYNAME_H
+
+#include <boost/signals2.hpp>
+
+class LLSD;
+class LLUUID;
+
+namespace LLViewerDisplayName
+{
+	typedef boost::signals2::signal<
+		void (bool success, const std::string& reason, const LLSD& content)>
+			set_name_signal_t;
+	typedef set_name_signal_t::slot_type set_name_slot_t;
+
+	// Sends an update to the server to change a display name
+	// and call back when done.  May not succeed due to service
+	// unavailable or name not available.
+	void set(const std::string& display_name, const set_name_slot_t& slot);
+}
+
+#endif // LLVIEWERDISPLAYNAME_H
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 75a5b14154fcc2b3660782808ffb9b2ae750325c..7dbaa4cf9286875f25caa0baaad5479e667c7aac 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1776,9 +1776,9 @@ PermissionMask LLViewerInventoryItem::getPermissionMask() const
 
 //----------
 
-void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name)
+void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& name, bool is_group)
 {
-	rename(first_name + " " + last_name);
+	rename(name);
 	gInventory.addChangedMask(LLInventoryObserver::LABEL, getUUID());
 	gInventory.notifyObservers();
 }
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 7f5a92eeab2d638cd5013c2acb567fad072ef386..1af06a1be82d254441c0a336a578a306e649e7fe 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -157,7 +157,7 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr
 	PermissionMask getPermissionMask() const;
 
 	// callback
-	void onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name);
+	void onCallingCardNameLookup(const LLUUID& id, const std::string& name, bool is_group);
 
 	// If this is a broken link, try to fix it and any other identical link.
 	BOOL regenerateLink();
diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp
index ecb7e2064dad760251de17d13b8ca1c39ca9d291..4e14824e69a3f726c575037a80eae56c93ad486c 100644
--- a/indra/newview/llviewerjointattachment.cpp
+++ b/indra/newview/llviewerjointattachment.cpp
@@ -32,6 +32,7 @@
 #include "llviewercontrol.h"
 #include "lldrawable.h"
 #include "llgl.h"
+#include "llhudtext.h"
 #include "llrender.h"
 #include "llvoavatarself.h"
 #include "llvolume.h"
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index daeace0ec5c9f2bf1e856dc13615bcac4e6d891e..d1d352aa210bbcfa66591329505b30924f6336c3 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -28,6 +28,7 @@
 #include "llviewermenu.h" 
 
 // linden library includes
+#include "llavatarnamecache.h"	// IDEVO
 #include "llfloaterreg.h"
 #include "llcombobox.h"
 #include "llinventorypanel.h"
@@ -2800,9 +2801,8 @@ class LLObjectMute : public view_listener_t
 			LLNameValue *lastname = avatar->getNVPair("LastName");
 			if (firstname && lastname)
 			{
-				name = firstname->getString();
-				name += " ";
-				name += lastname->getString();
+				name = LLCacheName::buildFullName(
+					firstname->getString(), lastname->getString());
 			}
 			
 			type = LLMute::AGENT;
@@ -3148,58 +3148,6 @@ bool enable_freeze_eject(const LLSD& avatar_id)
 	return new_value;
 }
 
-class LLAvatarGiveCard : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		llinfos << "handle_give_card()" << llendl;
-		LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-		if(dest && dest->isAvatar())
-		{
-			bool found_name = false;
-			LLSD args;
-			LLSD old_args;
-			LLNameValue* nvfirst = dest->getNVPair("FirstName");
-			LLNameValue* nvlast = dest->getNVPair("LastName");
-			if(nvfirst && nvlast)
-			{
-				args["FIRST"] = nvfirst->getString();
-				args["LAST"] = nvlast->getString();
-				old_args["FIRST"] = nvfirst->getString();
-				old_args["LAST"] = nvlast->getString();
-				found_name = true;
-			}
-			LLViewerRegion* region = dest->getRegion();
-			LLHost dest_host;
-			if(region)
-			{
-				dest_host = region->getHost();
-			}
-			if(found_name && dest_host.isOk())
-			{
-				LLMessageSystem* msg = gMessageSystem;
-				msg->newMessage("OfferCallingCard");
-				msg->nextBlockFast(_PREHASH_AgentData);
-				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-				msg->nextBlockFast(_PREHASH_AgentBlock);
-				msg->addUUIDFast(_PREHASH_DestID, dest->getID());
-				LLUUID transaction_id;
-				transaction_id.generate();
-				msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
-				msg->sendReliable(dest_host);
-				LLNotificationsUtil::add("OfferedCard", args);
-			}
-			else
-			{
-				LLNotificationsUtil::add("CantOfferCallingCard", old_args);
-			}
-		}
-		return true;
-	}
-};
-
-
 
 void login_done(S32 which, void *user)
 {
@@ -3622,21 +3570,17 @@ void request_friendship(const LLUUID& dest_id)
 	LLViewerObject* dest = gObjectList.findObject(dest_id);
 	if(dest && dest->isAvatar())
 	{
-		std::string fullname;
-		LLSD args;
+		std::string full_name;
 		LLNameValue* nvfirst = dest->getNVPair("FirstName");
 		LLNameValue* nvlast = dest->getNVPair("LastName");
 		if(nvfirst && nvlast)
 		{
-			args["FIRST"] = nvfirst->getString();
-			args["LAST"] = nvlast->getString();
-			fullname = nvfirst->getString();
-			fullname += " ";
-			fullname += nvlast->getString();
+			full_name = LLCacheName::buildFullName(
+				nvfirst->getString(), nvlast->getString());
 		}
-		if (!fullname.empty())
+		if (!full_name.empty())
 		{
-			LLAvatarActions::requestFriendshipDialog(dest_id, fullname);
+			LLAvatarActions::requestFriendshipDialog(dest_id, full_name);
 		}
 		else
 		{
@@ -7719,6 +7663,16 @@ class LLWorldToggleCameraControls : public view_listener_t
 	}
 };
 
+void handle_flush_name_caches()
+{
+	// Toggle display names on and off to flush
+	bool use_display_names = LLAvatarNameCache::useDisplayNames();
+	LLAvatarNameCache::setUseDisplayNames(!use_display_names);
+	LLAvatarNameCache::setUseDisplayNames(use_display_names);
+
+	if (gCacheName) gCacheName->clear();
+}
+
 class LLUploadCostCalculator : public view_listener_t
 {
 	std::string mCostStr;
@@ -7950,6 +7904,7 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole");
 	view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole");
 	view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole");
+	
 	// Advanced > HUD Info
 	view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo");
 	view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo");
@@ -8033,6 +7988,7 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames");
 	view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames");
 	view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs");
+	commit.add("Advanced.FlushNameCaches", boost::bind(&handle_flush_name_caches));
 
 	// Advanced > Character > Grab Baked Texture
 	view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture");
@@ -8133,7 +8089,6 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug");
 	view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
 	view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
-	view_listener_t::addMenu(new LLAvatarGiveCard(), "Avatar.GiveCard");
 	commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
 	view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
 	view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call");
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 781e324e25dc27c616538fe600d7376800545c73..ce4c0aaf5cffcfa414d95eadebb75efacb46a1bc 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -28,9 +28,11 @@
 #include "llviewermessage.h"
 #include "boost/lexical_cast.hpp"
 
+// Linden libraries
 #include "llanimationstates.h"
 #include "llaudioengine.h" 
 #include "llavataractions.h"
+#include "llavatarnamecache.h"		// IDEVO HACK
 #include "lscript_byteformat.h"
 #include "lleconomy.h"
 #include "lleventtimer.h"
@@ -78,6 +80,7 @@
 #include "llspeakers.h"
 #include "lltrans.h"
 #include "llviewerfoldertype.h"
+#include "llvoavatar.h"				// IDEVO HACK
 #include "lluri.h"
 #include "llviewergenericmessage.h"
 #include "llviewermenu.h"
@@ -126,6 +129,7 @@ extern BOOL gDebugClicks;
 
 // function prototypes
 bool check_offer_throttle(const std::string& from_name, bool check_only);
+static void process_money_balance_reply_extended(LLMessageSystem* msg);
 
 //inventory offer throttle globals
 LLFrameTimer gThrottleTimer;
@@ -1223,28 +1227,26 @@ bool highlight_offered_object(const LLUUID& obj_id)
 }
 
 void inventory_offer_mute_callback(const LLUUID& blocked_id,
-								   const std::string& first_name,
-								   const std::string& last_name,
-								   BOOL is_group, boost::shared_ptr<LLNotificationResponderInterface> offer_ptr)
+								   const std::string& full_name,
+								   bool is_group,
+								   boost::shared_ptr<LLNotificationResponderInterface> offer_ptr)
 {
 	LLOfferInfo* offer =  dynamic_cast<LLOfferInfo*>(offer_ptr.get());
-	std::string from_name;
+	
+	std::string from_name = full_name;
 	LLMute::EType type;
 	if (is_group)
 	{
 		type = LLMute::GROUP;
-		from_name = first_name;
 	}
 	else if(offer && offer->mFromObject)
 	{
 		//we have to block object by name because blocked_id is an id of owner
 		type = LLMute::BY_NAME;
-		from_name = offer->mFromName;
 	}
 	else
 	{
 		type = LLMute::AGENT;
-		from_name = first_name + " " + last_name;
 	}
 
 	// id should be null for BY_NAME mute, see  LLMuteList::add for details  
@@ -1422,7 +1424,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 		llassert(notification_ptr != NULL);
 		if (notification_ptr != NULL)
 		{
-			gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4, notification_ptr->getResponderPtr()));
+			gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,notification_ptr->getResponderPtr()));
 		}
 	}
 
@@ -1562,7 +1564,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
 		llassert(notification_ptr != NULL);
 		if (notification_ptr != NULL)
 		{
-			gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4, notification_ptr->getResponderPtr()));
+			gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,notification_ptr->getResponderPtr()));
 		}
 	}
 	
@@ -1611,12 +1613,12 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
 		}
 		else
 		{
-			std::string first_name, last_name;
-			if (gCacheName->getName(mFromID, first_name, last_name))
+			std::string full_name;
+			if (gCacheName->getFullName(mFromID, full_name))
 			{
 				from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+ LLTrans::getString("'") + mFromName 
-				+ LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + first_name + " " + last_name;
-				chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + first_name + " " + last_name;
+					+ LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + full_name;
+				chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + full_name;
 			}
 			else
 			{
@@ -1820,7 +1822,14 @@ void inventory_offer_handler(LLOfferInfo* info)
 	payload["give_inventory_notification"] = FALSE;
 	args["OBJECTFROMNAME"] = info->mFromName;
 	args["NAME"] = info->mFromName;
-	args["NAME_SLURL"] = LLSLURL("agent", info->mFromID, "about").getSLURLString();
+	if (info->mFromGroup)
+	{
+		args["NAME_SLURL"] = LLSLURL("group", info->mFromID, "about").getSLURLString();
+	}
+	else
+	{
+		args["NAME_SLURL"] = LLSLURL("agent", info->mFromID, "about").getSLURLString();
+	}
 	std::string verb = "select?name=" + LLURI::escape(msg);
 	args["ITEM_SLURL"] = LLSLURL("inventory", info->mObjectID, verb.c_str()).getSLURLString();
 
@@ -1940,7 +1949,6 @@ class LLPostponedServerObjectNotification: public LLPostponedNotification
 	void modifyNotificationParams()
 	{
 		LLSD payload = mParams.payload;
-		payload["SESSION_NAME"] = mName;
 		mParams.payload = payload;
 	}
 };
@@ -2003,6 +2011,99 @@ static bool parse_lure_bucket(const std::string& bucket,
 	return true;
 }
 
+// Strip out "Resident" for display, but only if the message came from a user
+// (rather than a script)
+static std::string clean_name_from_im(const std::string& name, EInstantMessage type)
+{
+	switch(type)
+	{
+	case IM_NOTHING_SPECIAL:
+	case IM_MESSAGEBOX:
+	case IM_GROUP_INVITATION:
+	case IM_INVENTORY_OFFERED:
+	case IM_INVENTORY_ACCEPTED:
+	case IM_INVENTORY_DECLINED:
+	case IM_GROUP_VOTE:
+	case IM_GROUP_MESSAGE_DEPRECATED:
+	//IM_TASK_INVENTORY_OFFERED
+	//IM_TASK_INVENTORY_ACCEPTED
+	//IM_TASK_INVENTORY_DECLINED
+	case IM_NEW_USER_DEFAULT:
+	case IM_SESSION_INVITE:
+	case IM_SESSION_P2P_INVITE:
+	case IM_SESSION_GROUP_START:
+	case IM_SESSION_CONFERENCE_START:
+	case IM_SESSION_SEND:
+	case IM_SESSION_LEAVE:
+	//IM_FROM_TASK
+	case IM_BUSY_AUTO_RESPONSE:
+	case IM_CONSOLE_AND_CHAT_HISTORY:
+	case IM_LURE_USER:
+	case IM_LURE_ACCEPTED:
+	case IM_LURE_DECLINED:
+	case IM_GODLIKE_LURE_USER:
+	case IM_YET_TO_BE_USED:
+	case IM_GROUP_ELECTION_DEPRECATED:
+	//IM_GOTO_URL
+	//IM_FROM_TASK_AS_ALERT
+	case IM_GROUP_NOTICE:
+	case IM_GROUP_NOTICE_INVENTORY_ACCEPTED:
+	case IM_GROUP_NOTICE_INVENTORY_DECLINED:
+	case IM_GROUP_INVITATION_ACCEPT:
+	case IM_GROUP_INVITATION_DECLINE:
+	case IM_GROUP_NOTICE_REQUESTED:
+	case IM_FRIENDSHIP_OFFERED:
+	case IM_FRIENDSHIP_ACCEPTED:
+	case IM_FRIENDSHIP_DECLINED_DEPRECATED:
+	//IM_TYPING_START
+	//IM_TYPING_STOP
+		return LLCacheName::cleanFullName(name);
+	default:
+		return name;
+	}
+}
+
+static std::string clean_name_from_task_im(const std::string& msg,
+										   BOOL from_group)
+{
+	boost::smatch match;
+	static const boost::regex returned_exp(
+		"(.*been returned to your inventory lost and found folder by )(.+)( (from|near).*)");
+	if (boost::regex_match(msg, match, returned_exp))
+	{
+		// match objects are 1-based for groups
+		std::string final = match[1].str();
+		std::string name = match[2].str();
+		// Don't try to clean up group names
+		if (!from_group)
+		{
+			if (LLAvatarNameCache::useDisplayNames())
+			{
+				// ...just convert to username
+				final += LLCacheName::buildUsername(name);
+			}
+			else
+			{
+				// ...strip out legacy "Resident" name
+				final += LLCacheName::cleanFullName(name);
+			}
+		}
+		final += match[3].str();
+		return final;
+	}
+	return msg;
+}
+
+void notification_display_name_callback(const LLUUID& id,
+					  const LLAvatarName& av_name,
+					  const std::string& name, 
+					  LLSD& substitutions, 
+					  const LLSD& payload)
+{
+	substitutions["NAME"] = av_name.mDisplayName;
+	LLNotificationsUtil::add(name, substitutions, payload);
+}
+
 class LLPostponedIMSystemTipNotification: public LLPostponedNotification
 {
 protected:
@@ -2013,8 +2114,28 @@ class LLPostponedIMSystemTipNotification: public LLPostponedNotification
 		payload["SESSION_NAME"] = mName;
 		mParams.payload = payload;
 	}
+
 };
 
+// Callback for name resolution of a god/estate message
+void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string message)
+{	
+	LLSD args;
+	args["NAME"] = av_name.getCompleteName();
+	args["MESSAGE"] = message;
+	LLNotificationsUtil::add("GodMessage", args);
+
+	// Treat like a system message and put in chat history.
+	chat.mText = av_name.getCompleteName() + ": " + message;
+
+	LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+	if(nearby_chat)
+	{
+		nearby_chat->addMessage(chat);
+	}
+
+}
+
 void process_improved_im(LLMessageSystem *msg, void **user_data)
 {
 	if (gNoRender)
@@ -2062,6 +2183,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 	{
         name = LLTrans::getString("Unnamed");
 	}
+	// IDEVO convert new-style "Resident" names for display
+	name = clean_name_from_im(name, dialog);
 
 	BOOL is_busy = gAgent.getBusy();
 	BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat);
@@ -2091,7 +2214,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 	{
 	case IM_CONSOLE_AND_CHAT_HISTORY:
 		args["MESSAGE"] = message;
-		args["NAME"] = name;
 		payload["from_id"] = from_id;
 
 		params.name = "IMSystemMessageTip";
@@ -2161,21 +2283,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 		}
 		else if (to_id.isNull())
 		{
-			// Message to everyone from GOD
-			args["NAME"] = name;
-			args["MESSAGE"] = message;
-			LLNotificationsUtil::add("GodMessage", args);
-
-			// Treat like a system message and put in chat history.
-			// Claim to be from a local agent so it doesn't go into
-			// console.
-			chat.mText = name + separator_string + message;
-
-			LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
-			if(nearby_chat)
-			{
-				nearby_chat->addMessage(chat);
-			}
+			// Message to everyone from GOD, look up the fullname since
+			// server always slams name to legacy names
+			LLAvatarNameCache::get(from_id, boost::bind(god_message_name_cb, _2, chat, message));
 		}
 		else
 		{
@@ -2375,6 +2485,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 				invite_bucket = (struct invite_bucket_t*) &binary_bucket[0];
 				S32 membership_fee = ntohl(invite_bucket->membership_fee);
 
+				// IDEVO Clean up legacy name "Resident" in message constructed in
+				// lldatagroups.cpp
+				U32 pos = message.find(" has invited you to join a group.\n");
+				if (pos != std::string::npos)
+				{
+					// use cleaned-up name from above
+					message = name + message.substr(pos);
+				}
+
 				LLSD payload;
 				payload["transaction_id"] = session_id;
 				payload["group_id"] = from_id;
@@ -2462,7 +2581,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 
 	case IM_INVENTORY_ACCEPTED:
 	{
-		args["NAME"] = name;
+		args["NAME"] = LLSLURL("agent", from_id, "completename").getSLURLString();;
 		LLSD payload;
 		payload["from_id"] = from_id;
 		LLNotificationsUtil::add("InventoryAccepted", args, payload);
@@ -2470,7 +2589,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 	}
 	case IM_INVENTORY_DECLINED:
 	{
-		args["NAME"] = name;
+		args["NAME"] = LLSLURL("agent", from_id, "completename").getSLURLString();;
 		LLSD payload;
 		payload["from_id"] = from_id;
 		LLNotificationsUtil::add("InventoryDeclined", args, payload);
@@ -2562,6 +2681,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 				chat.mSourceType = CHAT_SOURCE_SYSTEM;
 			}
 
+			// IDEVO Some messages have embedded resident names
+			message = clean_name_from_task_im(message, from_group);
+
 			LLSD query_string;
 			query_string["owner"] = from_id;
 			query_string["slurl"] = location;
@@ -2770,7 +2892,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 			args["NAME"] = name;
 			LLSD payload;
 			payload["from_id"] = from_id;
-			LLNotificationsUtil::add("FriendshipAccepted", args, payload);
+			LLAvatarNameCache::get(from_id, boost::bind(&notification_display_name_callback,
+														 _1,
+														 _2,
+														 "FriendshipAccepted",
+														 args,
+														 payload));
 		}
 		break;
 
@@ -2874,9 +3001,8 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
 		LLNameValue* nvlast  = source->getNVPair("LastName");
 		if (nvfirst && nvlast)
 		{
-			args["FIRST"] = nvfirst->getString();
-			args["LAST"] = nvlast->getString();
-			source_name = std::string(nvfirst->getString()) + " " + nvlast->getString();
+			source_name = LLCacheName::buildFullName(
+				nvfirst->getString(), nvlast->getString());
 		}
 	}
 
@@ -2909,7 +3035,6 @@ void process_decline_callingcard(LLMessageSystem* msg, void**)
 	LLNotificationsUtil::add("CallingCardDeclined");
 }
 
-
 void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 {
 	LLChat	chat;
@@ -2925,7 +3050,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 	LLViewerObject*	chatter;
 
 	msg->getString("ChatData", "FromName", from_name);
-	chat.mFromName = from_name;
 	
 	msg->getUUID("ChatData", "SourceID", from_id);
 	chat.mFromID = from_id;
@@ -2944,6 +3068,27 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 	
 	chat.mTime = LLFrameTimer::getElapsedSeconds();
 	
+	// IDEVO Correct for new-style "Resident" names
+	if (chat.mSourceType == CHAT_SOURCE_AGENT)
+	{
+		// I don't know if it's OK to change this here, if 
+		// anything downstream does lookups by name, for instance
+		
+		LLAvatarName av_name;
+		if (LLAvatarNameCache::get(from_id, &av_name))
+		{
+			chat.mFromName = av_name.mDisplayName;
+		}
+		else
+		{
+			chat.mFromName = LLCacheName::cleanFullName(from_name);
+		}
+	}
+	else
+	{
+		chat.mFromName = from_name;
+	}
+
 	BOOL is_busy = gAgent.getBusy();
 
 	BOOL is_muted = FALSE;
@@ -4803,168 +4948,287 @@ void process_time_dilation(LLMessageSystem *msg, void **user_data)
 */
 
 
-
 void process_money_balance_reply( LLMessageSystem* msg, void** )
 {
 	S32 balance = 0;
 	S32 credit = 0;
 	S32 committed = 0;
 	std::string desc;
+	LLUUID tid;
 
+	msg->getUUID("MoneyData", "TransactionID", tid);
 	msg->getS32("MoneyData", "MoneyBalance", balance);
 	msg->getS32("MoneyData", "SquareMetersCredit", credit);
 	msg->getS32("MoneyData", "SquareMetersCommitted", committed);
 	msg->getStringFast(_PREHASH_MoneyData, _PREHASH_Description, desc);
 	LL_INFOS("Messaging") << "L$, credit, committed: " << balance << " " << credit << " "
 			<< committed << LL_ENDL;
-
+    
 	if (gStatusBar)
 	{
-	//	S32 old_balance = gStatusBar->getBalance();
-
-		// This is an update, not the first transmission of balance
-	/*	if (old_balance != 0)
-		{
-			// this is actually an update
-			if (balance > old_balance)
-			{
-				LLFirstUse::useBalanceIncrease(balance - old_balance);
-			}
-			else if (balance < old_balance)
-			{
-				LLFirstUse::useBalanceDecrease(balance - old_balance);
-			}
-		}
-	 */
 		gStatusBar->setBalance(balance);
 		gStatusBar->setLandCredit(credit);
 		gStatusBar->setLandCommitted(committed);
 	}
 
-	LLUUID tid;
-	msg->getUUID("MoneyData", "TransactionID", tid);
+	if (desc.empty()
+		|| !gSavedSettings.getBOOL("NotifyMoneyChange"))
+	{
+		// ...nothing to display
+		return;
+	}
+
+	// Suppress duplicate messages about the same transaction
 	static std::deque<LLUUID> recent;
-	if(!desc.empty() && gSavedSettings.getBOOL("NotifyMoneyChange")
-	   && (std::find(recent.rbegin(), recent.rend(), tid) == recent.rend()))
+	if (std::find(recent.rbegin(), recent.rend(), tid) != recent.rend())
 	{
-		// Make the user confirm the transaction, since they might
-		// have missed something during an event.
-		// *TODO: Translate
-		LLSD args;
-		
+		return;
+	}
 
-		// this is a marker to retrieve avatar name from server message:
-		// "<avatar name> paid you L$"
-		const std::string marker = "paid you L$";
+	// Once the 'recent' container gets large enough, chop some
+	// off the beginning.
+	const U32 MAX_LOOKBACK = 30;
+	const S32 POP_FRONT_SIZE = 12;
+	if(recent.size() > MAX_LOOKBACK)
+	{
+		LL_DEBUGS("Messaging") << "Removing oldest transaction records" << LL_ENDL;
+		recent.erase(recent.begin(), recent.begin() + POP_FRONT_SIZE);
+	}
+	//LL_DEBUGS("Messaging") << "Pushing back transaction " << tid << LL_ENDL;
+	recent.push_back(tid);
 
+	if (msg->has("TransactionInfo"))
+	{
+		// ...message has extended info for localization
+		process_money_balance_reply_extended(msg);
+	}
+	else
+	{
+		// Only old dev grids will not supply the TransactionInfo block,
+		// so we can just use the hard-coded English string.
+		LLSD args;
 		args["MESSAGE"] = desc;
+		LLNotificationsUtil::add("SystemMessage", args);
+	}
+}
+
+static std::string reason_from_transaction_type(S32 transaction_type,
+												const std::string& item_desc)
+{
+	// *NOTE: The keys for the reason strings are unusual because
+	// an earlier version of the code used English language strings
+	// extracted from hard-coded server English descriptions.
+	// Keeping them so we don't have to re-localize them.
+	switch (transaction_type)
+	{
+		case TRANS_OBJECT_SALE:
+		{
+			LLStringUtil::format_map_t arg;
+			arg["ITEM"] = item_desc;
+			return LLTrans::getString("for item", arg);
+		}
+		case TRANS_LAND_SALE:
+			return LLTrans::getString("for a parcel of land");
+			
+		case TRANS_LAND_PASS_SALE:
+			return LLTrans::getString("for a land access pass");
+			
+		case TRANS_GROUP_LAND_DEED:
+			return LLTrans::getString("for deeding land");
+			
+		case TRANS_GROUP_CREATE:
+			return LLTrans::getString("to create a group");
+			
+		case TRANS_GROUP_JOIN:
+			return LLTrans::getString("to join a group");
+			
+		case TRANS_UPLOAD_CHARGE:
+			return LLTrans::getString("to upload");
 
-		// extract avatar name from system message
-		S32 marker_pos = desc.find(marker, 0);
+		case TRANS_CLASSIFIED_CHARGE:
+			return LLTrans::getString("to publish a classified ad");
+			
+		// These have no reason to display, but are expected and should not
+		// generate warnings
+		case TRANS_GIFT:
+		case TRANS_PAY_OBJECT:
+		case TRANS_OBJECT_PAYS:
+			return std::string();
 
-		std::string base_name = desc.substr(0, marker_pos);
-		
-		std::string name = base_name;
-		LLStringUtil::trim(name);
+		default:
+			llwarns << "Unknown transaction type " 
+				<< transaction_type << llendl;
+			return std::string();
+	}
+}
 
-		// if name extracted and name cache contains avatar id send loggable notification
-		LLUUID from_id;
-		if(name.size() > 0 && gCacheName->getUUID(name, from_id))
-		{
-			//description always comes not localized. lets fix this
+static void money_balance_group_notify(const LLUUID& group_id,
+									   const std::string& name,
+									   bool is_group,
+									   std::string notification,
+									   LLSD args,
+									   LLSD payload)
+{
+	// Message uses name SLURLs, don't actually have to substitute in
+	// the name.  We're just making sure it's available.
+	// Notification is either PaymentReceived or PaymentSent
+	LLNotificationsUtil::add(notification, args, payload);
+}
 
-			//ammount paid
-			std::string ammount = desc.substr(marker_pos + marker.length(),desc.length() - marker.length() - marker_pos);
-	
-			//reform description
-			LLStringUtil::format_map_t str_args;
-			str_args["NAME"] = base_name;
-			str_args["AMOUNT"] = ammount;
-			std::string new_description = LLTrans::getString("paid_you_ldollars", str_args);
+static void money_balance_avatar_notify(const LLUUID& agent_id,
+										const LLAvatarName& av_name,
+									   	std::string notification,
+									   	LLSD args,
+									   	LLSD payload)
+{
+	// Message uses name SLURLs, don't actually have to substitute in
+	// the name.  We're just making sure it's available.
+	// Notification is either PaymentReceived or PaymentSent
+	LLNotificationsUtil::add(notification, args, payload);
+}
 
+static void process_money_balance_reply_extended(LLMessageSystem* msg)
+{
+    // Added in server 1.40 and viewer 2.1, support for localization
+    // and agent ids for name lookup.
+    S32 transaction_type = 0;
+    LLUUID source_id;
+	BOOL is_source_group = FALSE;
+    LLUUID dest_id;
+	BOOL is_dest_group = FALSE;
+    S32 amount = 0;
+    std::string item_description;
+
+    msg->getS32("TransactionInfo", "TransactionType", transaction_type);
+    msg->getUUID("TransactionInfo", "SourceID", source_id);
+	msg->getBOOL("TransactionInfo", "IsSourceGroup", is_source_group);
+    msg->getUUID("TransactionInfo", "DestID", dest_id);
+	msg->getBOOL("TransactionInfo", "IsDestGroup", is_dest_group);
+    msg->getS32("TransactionInfo", "Amount", amount);
+    msg->getString("TransactionInfo", "ItemDescription", item_description);
+    LL_INFOS("Money") << "MoneyBalanceReply source " << source_id 
+		<< " dest " << dest_id
+		<< " type " << transaction_type
+		<< " item " << item_description << LL_ENDL;
+
+	if (source_id.isNull() && dest_id.isNull())
+	{
+		// this is a pure balance update, no notification required
+		return;
+	}
 
-			args["MESSAGE"] = new_description;
-			args["NAME"] = name;
-			LLSD payload;
-			payload["from_id"] = from_id;
-			LLNotificationsUtil::add("PaymentRecived", args, payload);
+	std::string source_slurl;
+	if (is_source_group)
+	{
+		source_slurl =
+			LLSLURL( "group", source_id, "inspect").getSLURLString();
+	}
+	else
+	{
+		source_slurl =
+			LLSLURL( "agent", source_id, "completename").getSLURLString();
+	}
+
+	std::string dest_slurl;
+	if (is_dest_group)
+	{
+		dest_slurl =
+			LLSLURL( "group", dest_id, "inspect").getSLURLString();
+	}
+	else
+	{
+		dest_slurl =
+			LLSLURL( "agent", dest_id, "completename").getSLURLString();
+	}
+
+	std::string reason =
+		reason_from_transaction_type(transaction_type, item_description);
+	
+	LLStringUtil::format_map_t args;
+	args["REASON"] = reason; // could be empty
+	args["AMOUNT"] = llformat("%d", amount);
+	
+	// Need to delay until name looked up, so need to know whether or not
+	// is group
+	bool is_name_group = false;
+	LLUUID name_id;
+	std::string message;
+	std::string notification;
+	LLSD final_args;
+	LLSD payload;
+	
+	bool you_paid_someone = (source_id == gAgentID);
+	if (you_paid_someone)
+	{
+		args["NAME"] = dest_slurl;
+		is_name_group = is_dest_group;
+		name_id = dest_id;
+		if (!reason.empty())
+		{
+			if (dest_id.notNull())
+			{
+				message = LLTrans::getString("you_paid_ldollars", args);
+			}
+			else
+			{
+				// transaction fee to the system, eg, to create a group
+				message = LLTrans::getString("you_paid_ldollars_no_name", args);
+			}
 		}
-		//AD *HACK: Parsing incoming string to localize messages that come from server! EXT-5986
-		// It's only a temporarily and ineffective measure. It doesn't affect performance much
-		// because we get here only for specific type of messages, but anyway it is not right to do it!
-		// *TODO: Server-side changes should be made and this code removed.
 		else
 		{
-			if(desc.find("You paid")==0)
+			if (dest_id.notNull())
 			{
-				// Regular expression for message parsing- change it in case of server-side changes.
-				// Each set of parenthesis will later be used to find arguments of message we generate
-				// in the end of this if- (.*) gives us name of money receiver, (\\d+)-amount of money we pay
-				// and ([^$]*)- reason of payment
-				boost::regex expr("You paid (?:.{0}|(.*) )L\\$(\\d+)\\s?([^$]*)\\.");
-				boost::match_results <std::string::const_iterator> matches;
-				if(boost::regex_match(desc, matches, expr))
-				{
-					// Name of full localizable notification string
-					// there are four types of this string- with name of receiver and reason of payment,
-					// without name and without reason (both may also be absent simultaneously).
-					// example of string without name - You paid L$100 to create a group.
-					// example of string without reason - You paid Smdby Linden L$100.
-					// example of string with reason and name - You paid Smbdy Linden L$100 for a land access pass.
-					// example of string with no info - You paid L$50.
-					std::string line = "you_paid_ldollars_no_name";
-
-					// arguments of string which will be in notification
-					LLStringUtil::format_map_t str_args;
-
-					// extracting amount of money paid (without L$ symbols). It is always present.
-					str_args["[AMOUNT]"] = std::string(matches[2]);
-
-					// extracting name of person/group you are paying (it may be absent)
-					std::string name = std::string(matches[1]);
-					if(!name.empty())
-					{
-						str_args["[NAME]"] = name;
-						line = "you_paid_ldollars";
-					}
-
-					// extracting reason of payment (it may be absent)
-					std::string reason = std::string(matches[3]);
-					if (reason.empty())
-					{
-						line = name.empty() ? "you_paid_ldollars_no_info" : "you_paid_ldollars_no_reason";
-					}
-					else
-					{
-						std::string localized_reason;
-						// if we haven't found localized string for reason of payment leave it as it was
-						str_args["[REASON]"] =  LLTrans::findString(localized_reason, reason) ? localized_reason : reason;
-					}
-
-					// forming final message string by retrieving localized version from xml
-					// and applying previously found arguments
-					line = LLTrans::getString(line, str_args);
-					args["MESSAGE"] = line;
-				}
+				message = LLTrans::getString("you_paid_ldollars_no_reason", args);
+			}
+			else
+			{
+				// no target, no reason, you just paid money
+				message = LLTrans::getString("you_paid_ldollars_no_info", args);
 			}
-
-			LLNotificationsUtil::add("SystemMessage", args);
 		}
-
-		// Once the 'recent' container gets large enough, chop some
-		// off the beginning.
-		const U32 MAX_LOOKBACK = 30;
-		const S32 POP_FRONT_SIZE = 12;
-		if(recent.size() > MAX_LOOKBACK)
+		final_args["MESSAGE"] = message;
+		notification = "PaymentSent";
+	}
+	else {
+		// ...someone paid you
+		args["NAME"] = source_slurl;
+		is_name_group = is_source_group;
+		name_id = source_id;
+		if (!reason.empty())
 		{
-			LL_DEBUGS("Messaging") << "Removing oldest transaction records" << LL_ENDL;
-			recent.erase(recent.begin(), recent.begin() + POP_FRONT_SIZE);
+			message = LLTrans::getString("paid_you_ldollars", args);
 		}
-		//LL_DEBUGS("Messaging") << "Pushing back transaction " << tid << LL_ENDL;
-		recent.push_back(tid);
+		else {
+			message = LLTrans::getString("paid_you_ldollars_no_reason", args);
+		}
+		final_args["MESSAGE"] = message;
+
+		// make notification loggable
+		payload["from_id"] = source_id;
+		notification = "PaymentReceived";
+	}
+
+	// Despite using SLURLs, wait until the name is available before
+	// showing the notification, otherwise the UI layout is strange and
+	// the user sees a "Loading..." message
+	if (is_name_group)
+	{
+		gCacheName->getGroup(name_id,
+						boost::bind(&money_balance_group_notify,
+									_1, _2, _3,
+									notification, final_args, payload));
+	}
+	else {
+		LLAvatarNameCache::get(name_id,
+							   boost::bind(&money_balance_avatar_notify,
+										   _1, _2,
+										   notification, final_args, payload));										   
 	}
 }
 
+
+
 bool handle_special_notification_callback(const LLSD& notification, const LLSD& response)
 {
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -5206,7 +5470,7 @@ void handle_show_mean_events(void *)
 	//LLFloaterBump::showInstance();
 }
 
-void mean_name_callback(const LLUUID &id, const std::string& first, const std::string& last, BOOL always_false)
+void mean_name_callback(const LLUUID &id, const std::string& full_name, bool is_group)
 {
 	if (gNoRender)
 	{
@@ -5228,8 +5492,7 @@ void mean_name_callback(const LLUUID &id, const std::string& first, const std::s
 		LLMeanCollisionData *mcd = *iter;
 		if (mcd->mPerp == id)
 		{
-			mcd->mFirstName = first;
-			mcd->mLastName = last;
+			mcd->mFullName = full_name;
 		}
 	}
 }
@@ -5283,8 +5546,7 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use
 		{
 			LLMeanCollisionData *mcd = new LLMeanCollisionData(gAgentID, perp, time, type, mag);
 			gMeanCollisionList.push_front(mcd);
-			const BOOL is_group = FALSE;
-			gCacheName->get(perp, is_group, &mean_name_callback);
+			gCacheName->get(perp, false, boost::bind(&mean_name_callback, _1, _2, _3));
 		}
 	}
 }
@@ -5506,7 +5768,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
 	// so we'll reuse the same namespace for both throttle types.
 	std::string throttle_name = owner_name;
 	std::string self_name;
-	LLAgentUI::buildName( self_name );
+	LLAgentUI::buildFullname( self_name );
 	if( owner_name == self_name )
 	{
 		throttle_name = taskid.getString();
@@ -5542,7 +5804,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
 		S32 count = 0;
 		LLSD args;
 		args["OBJECTNAME"] = object_name;
-		args["NAME"] = owner_name;
+		args["NAME"] = LLCacheName::cleanFullName(owner_name);
 
 		// check the received permission flags against each permission
 		for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
@@ -5935,15 +6197,14 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)
 			// Record the offer.
 			{
 				std::string target_name;
-				gCacheName->getFullName(target_id, target_name);
+				gCacheName->getFullName(target_id, target_name);  // for im log filenames
 				LLSD args;
-				args["TO_NAME"] = target_name;
+				args["TO_NAME"] = LLSLURL("agent", target_id, "displayname").getSLURLString();;
 	
 				LLSD payload;
 				
 				//*TODO please rewrite all keys to the same case, lower or upper
 				payload["from_id"] = target_id;
-				payload["SESSION_NAME"] = target_name;
 				payload["SUPPRESS_TOAST"] = true;
 				LLNotificationsUtil::add("TeleportOfferSent", args, payload);
 			}
@@ -6157,8 +6418,7 @@ void process_script_dialog(LLMessageSystem* msg, void**)
 	LLNotificationPtr notification;
 	if (!first_name.empty())
 	{
-		args["FIRST"] = first_name;
-		args["LAST"] = last_name;
+		args["NAME"] = LLCacheName::buildFullName(first_name, last_name);
 		notification = LLNotifications::instance().add(
 			LLNotification::Params("ScriptDialog").substitutions(args).payload(payload).form_elements(form.asLLSD()));
 	}
@@ -6191,7 +6451,7 @@ static LLNotificationFunctorRegistration callback_load_url_reg("LoadWebPage", ca
 
 // We've got the name of the person who owns the object hurling the url.
 // Display confirmation dialog.
-void callback_load_url_name(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+void callback_load_url_name(const LLUUID& id, const std::string& full_name, bool is_group)
 {
 	std::vector<LLSD>::iterator it;
 	for (it = gLoadUrlList.begin(); it != gLoadUrlList.end(); )
@@ -6204,11 +6464,11 @@ void callback_load_url_name(const LLUUID& id, const std::string& first, const st
 			std::string owner_name;
 			if (is_group)
 			{
-				owner_name = first + LLTrans::getString("Group");
+				owner_name = full_name + LLTrans::getString("Group");
 			}
 			else
 			{
-				owner_name = first + " " + last;
+				owner_name = full_name;
 			}
 
 			// For legacy name-only mutes.
@@ -6268,7 +6528,8 @@ void process_load_url(LLMessageSystem* msg, void**)
 	// Add to list of pending name lookups
 	gLoadUrlList.push_back(payload);
 
-	gCacheName->get(owner_id, owner_is_group, &callback_load_url_name);
+	gCacheName->get(owner_id, owner_is_group,
+		boost::bind(&callback_load_url_name, _1, _2, _3));
 }
 
 
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 25cc24da95c36f85c0dc0d15cd4d03d2b01e1971..996181afaf529369829867181cb2f35e5741c247 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -63,6 +63,7 @@
 #include "llface.h"
 #include "llfloaterproperties.h"
 #include "llfollowcam.h"
+#include "llhudtext.h"
 #include "llselectmgr.h"
 #include "llrendersphere.h"
 #include "lltooldraganddrop.h"
@@ -1092,7 +1093,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					// alpha was flipped so that it zero encoded better
 					coloru.mV[3] = 255 - coloru.mV[3];
 					mText->setColor(LLColor4(coloru));
-					mText->setStringUTF8(temp_string);
+					mText->setString(temp_string);
 					
 					if (mDrawable.notNull())
 					{
@@ -1484,7 +1485,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					dp->unpackBinaryDataFixed(coloru.mV, 4, "Color");
 					coloru.mV[3] = 255 - coloru.mV[3];
 					mText->setColor(LLColor4(coloru));
-					mText->setStringUTF8(temp_string);
+					mText->setString(temp_string);
 
 					setChanged(TEXTURE);
 				}
@@ -4150,7 +4151,7 @@ void LLViewerObject::setDebugText(const std::string &utf8text)
 		mText->setOnHUDAttachment(isHUDAttachment());
 	}
 	mText->setColor(LLColor4::white);
-	mText->setStringUTF8(utf8text);
+	mText->setString(utf8text);
 	mText->setZCompare(FALSE);
 	mText->setDoFade(FALSE);
 	updateText();
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index bcc2cb164f2804cf0ce7a83f798f39c4c7a64b25..7d697a4a5fd74aff5229b991bea78d13dba3930c 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -31,7 +31,6 @@
 
 #include "llassetstorage.h"
 #include "lldarrayptr.h"
-#include "llhudtext.h"
 #include "llhudicon.h"
 #include "llinventory.h"
 #include "llrefcount.h"
@@ -54,6 +53,7 @@ class LLColor4;
 class LLFrameTimer;
 class LLDrawable;
 class LLHost;
+class LLHUDText;
 class LLWorld;
 class LLNameValue;
 class LLNetMap;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 05695193a572a62c25537fa311d59b79d25a6754..b597e6148ece96f0c23841932f50e1d366fa4e18 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -47,7 +47,7 @@
 #include "lltooltip.h"
 #include "llworld.h"
 #include "llstring.h"
-#include "llhudtext.h"
+#include "llhudnametag.h"
 #include "lldrawable.h"
 #include "xform.h"
 #include "llsky.h"
@@ -1195,7 +1195,7 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)
 			}
 		}
 
-		LLHUDText::addPickable(mSelectPickList);
+		LLHUDNameTag::addPickable(mSelectPickList);
 
 		for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
 			iter != LLCharacter::sInstances.end(); ++iter)
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 660bb9356252c6dd0268123d2c420c6af239de24..11de3774101344f00bef5dca9b652c98f3c13c1f 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -2069,10 +2069,7 @@ void LLViewerParcelMgr::deedLandToGroup()
 	args["GROUP_NAME"] = group_name;
 	if(mCurrentParcel->getContributeWithDeed())
 	{
-		std::string first_name, last_name;
-		gCacheName->getName(mCurrentParcel->getOwnerID(), first_name, last_name);
-		args["FIRST_NAME"] = first_name;
-		args["LAST_NAME"] = last_name;
+		args["NAME"] = LLSLURL("agent", mCurrentParcel->getOwnerID(), "completename").getSLURLString();
 		LLNotificationsUtil::add("DeedLandToGroupWithContribution",args, LLSD(), deedAlertCB);
 	}
 	else
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index a86efa215b1c9a6ae29c4840d253190af2f6d344..aa367fc1b8c54c8c61f4e83bf45fde94ba8cd636 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -28,7 +28,9 @@
 
 #include "llviewerregion.h"
 
+// linden libraries
 #include "indra_constants.h"
+#include "llavatarnamecache.h"		// name lookup cap url
 #include "llfloaterreg.h"
 #include "llmath.h"
 #include "llhttpclient.h"
@@ -170,7 +172,9 @@ class BaseCapabilitiesComplete : public LLHTTPClient::Responder
 				mRegion->showReleaseNotes();
 			}
 		}
-		
+
+		mRegion->setCapabilitiesReceived(true);
+
 		if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
 		{
 			LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
@@ -228,7 +232,8 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
     // LLCapabilityListener binds all the globals it expects to need at
     // construction time.
     mCapabilityListener(host.getString(), gMessageSystem, *this,
-                        gAgent.getID(), gAgent.getSessionID())
+                        gAgent.getID(), gAgent.getSessionID()),
+	mCapabilitiesReceived(false)
 {
 	mWidth = region_width_meters;
 	mOriginGlobal = from_region_handle(handle); 
@@ -1492,6 +1497,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	LLSD capabilityNames = LLSD::emptyArray();
 	
 	capabilityNames.append("AttachmentResources");
+	capabilityNames.append("AvatarPickerSearch");
 	capabilityNames.append("ChatSessionRequest");
 	capabilityNames.append("CopyInventoryFromNotecard");
 	capabilityNames.append("DispatchRegionInfo");
@@ -1502,6 +1508,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	capabilityNames.append("ObjectMediaNavigate");
 	capabilityNames.append("FetchLib");
 	capabilityNames.append("FetchLibDescendents");
+	capabilityNames.append("GetDisplayNames");
 	capabilityNames.append("GetTexture");
 	capabilityNames.append("GroupProposalBallot");
 	capabilityNames.append("HomeLocation");
@@ -1523,6 +1530,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	capabilityNames.append("SendUserReport");
 	capabilityNames.append("SendUserReportWithScreenshot");
 	capabilityNames.append("ServerReleaseNotes");
+	capabilityNames.append("SetDisplayName");
 	capabilityNames.append("StartGroupProposal");
 	capabilityNames.append("TextureStats");
 	capabilityNames.append("UntrustedSimulatorMessage");
@@ -1584,6 +1592,16 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
 	return iter->second;
 }
 
+bool LLViewerRegion::capabilitiesReceived() const
+{
+	return mCapabilitiesReceived;
+}
+
+void LLViewerRegion::setCapabilitiesReceived(bool received)
+{
+	mCapabilitiesReceived = received;
+}
+
 void LLViewerRegion::logActiveCapabilities() const
 {
 	int count = 0;
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 361ae87e1b9b087d96ba2f9ddcd4764fe53470d1..4afd57d96aa0382040ecfdcc1de945d42fde3f82 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -228,6 +228,11 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	void setCapability(const std::string& name, const std::string& url);
 	// implements LLCapabilityProvider
     virtual std::string getCapability(const std::string& name) const;
+
+	// has region received its final (not seed) capability list?
+	bool capabilitiesReceived() const;
+	void setCapabilitiesReceived(bool received);
+
 	static bool isSpecialCapabilityName(const std::string &name);
 	void logActiveCapabilities() const;
 
@@ -413,6 +418,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 
 private:
 	bool	mAlive;					// can become false if circuit disconnects
+	bool	mCapabilitiesReceived;
 
 	//spatial partitions for objects in this region
 	std::vector<LLSpatialPartition*> mObjectPartition;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index e55808597cd782e5957bd532350e79b3b26dd6e7..42266ad233145f37c7e9660389d9f37cf0f3013c 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -847,6 +847,9 @@ void send_stats()
 
 	llinfos << "Misc Stats: int_1: " << misc["int_1"] << " int_2: " << misc["int_2"] << llendl;
 	llinfos << "Misc Stats: string_1: " << misc["string_1"] << " string_2: " << misc["string_2"] << llendl;
+
+	body["DisplayNamesEnabled"] = gSavedSettings.getBOOL("UseDisplayNames");
+	body["DisplayNamesShowUsername"] = gSavedSettings.getBOOL("NameTagShowUsernames");
 	
 	LLViewerStats::getInstance()->addToMessage(body);
 	LLHTTPClient::post(url, body, new ViewerStatsResponder());
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 13db913f605255feff69c80d6d26e85d73311389..aa1e626e48f4ed330320419df2f5dd619640e648 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -114,6 +114,7 @@
 #include "llglheaders.h"
 #include "lltooltip.h"
 #include "llhudmanager.h"
+#include "llhudobject.h"
 #include "llhudview.h"
 #include "llimagebmp.h"
 #include "llimagej2c.h"
@@ -1172,12 +1173,8 @@ BOOL LLViewerWindow::handlePaint(LLWindow *window,  S32 x,  S32 y, S32 width,  S
 		//SetBKColor(hdc, RGB(255, 255, 255));
 		FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255)));
 
-		std::string name_str;
-		LLAgentUI::buildName(name_str);
-
 		std::string temp_str;
-		temp_str = llformat( "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f",		/* Flawfinder: ignore */
-				name_str.c_str(),
+		temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f",		/* Flawfinder: ignore */
 				LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(),
 				LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0),
 				LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0));
@@ -1871,7 +1868,7 @@ void LLViewerWindow::reshape(S32 width, S32 height)
 		// clear font width caches
 		if (display_scale_changed)
 		{
-			LLHUDText::reshape();
+			LLHUDObject::reshapeAll();
 		}
 
 		sendShapeToSim();
@@ -3913,7 +3910,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 		send_agent_pause();
 		//rescale fonts
 		initFonts(scale_factor);
-		LLHUDText::reshape();
+		LLHUDObject::reshapeAll();
 	}
 
 	S32 output_buffer_offset_y = 0;
@@ -4042,7 +4039,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 	if (high_res)
 	{
 		initFonts(1.f);
-		LLHUDText::reshape();
+		LLHUDObject::reshapeAll();
 	}
 
 	// Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 9af1198df1d9e5ec1362da718bf81bb2ed077c25..f0a99e75efb4a68575e5e5f9c483b0bb800b92c5 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -38,6 +38,7 @@
 #include <ctype.h>
 
 #include "llaudioengine.h"
+#include "llcachename.h"
 #include "noise.h"
 #include "sound_ids.h"
 
@@ -45,8 +46,10 @@
 #include "llagentcamera.h"
 #include "llagentwearables.h"
 #include "llanimationstates.h"
+#include "llavatarnamecache.h"
 #include "llavatarpropertiesprocessor.h"
 #include "llviewercontrol.h"
+#include "llcallingcard.h"		// IDEVO for LLAvatarTracker
 #include "lldrawpoolavatar.h"
 #include "lldriverparam.h"
 #include "lleditingmotion.h"
@@ -55,6 +58,8 @@
 #include "llheadrotmotion.h"
 #include "llhudeffecttrail.h"
 #include "llhudmanager.h"
+#include "llhudnametag.h"
+#include "llhudtext.h"				// for mText/mDebugText
 #include "llkeyframefallmotion.h"
 #include "llkeyframestandmotion.h"
 #include "llkeyframewalkmotion.h"
@@ -653,12 +658,14 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mAppearanceAnimating(FALSE),
 	mNameString(),
 	mTitle(),
-	mNameAway(FALSE),
-	mNameBusy(FALSE),
-	mNameMute(FALSE),
+	mNameAway(false),
+	mNameBusy(false),
+	mNameMute(false),
+	mNameAppearance(false),
+	mNameFriend(false),
+	mNameAlpha(0.f),
 	mRenderGroupTitles(sRenderGroupTitles),
-	mNameAppearance(FALSE),
-	mNameCloud(FALSE),
+	mNameCloud(false),
 	mFirstTEMessageReceived( FALSE ),
 	mFirstAppearanceMessageReceived( FALSE ),
 	mCulled( FALSE ),
@@ -2773,8 +2780,18 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
 								 && gSavedSettings.getS32("AvatarNameTagMode") ));
 	}
 
-	if ( render_name )
+	if ( !render_name )
 	{
+		if (mNameText)
+		{
+			// ...clean up old name tag
+			mNameText->markDead();
+			mNameText = NULL;
+			sNumVisibleChatBubbles--;
+		}
+		return;
+	}
+
 		BOOL new_name = FALSE;
 		if (visible_chat != mVisibleChat)
 		{
@@ -2790,7 +2807,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
 
 		// First Calculate Alpha
 		// If alpha > 0, create mNameText if necessary, otherwise delete it
-		{
 			F32 alpha = 0.f;
 			if (mAppAngle > 5.f)
 			{
@@ -2811,66 +2827,62 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
 				alpha = (mAppAngle-2.f)/3.f;
 			}
 
-			if (alpha > 0.f)
+	if (alpha <= 0.f)
 			{
+		if (mNameText)
+		{
+			mNameText->markDead();
+			mNameText = NULL;
+			sNumVisibleChatBubbles--;
+		}
+		return;
+	}
+
 				if (!mNameText)
 				{
-					mNameText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
-					mNameText->setMass(10.f);
+		mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject(
+			LLHUDObject::LL_HUD_NAME_TAG) );
+		//mNameText->setMass(10.f);
 					mNameText->setSourceObject(this);
-					mNameText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
+		mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP);
 					mNameText->setVisibleOffScreen(TRUE);
 					mNameText->setMaxLines(11);
 					mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
-					mNameText->setUseBubble(TRUE);
 					sNumVisibleChatBubbles++;
 					new_name = TRUE;
 				}
 				
-				LLColor4 avatar_name_color = LLUIColorTable::instance().getColor( "AvatarNameColor" );
-				avatar_name_color.setAlpha(alpha);
-				mNameText->setColor(avatar_name_color);
+	LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last);
+	mNameText->setPositionAgent(name_position);
 				
-				LLQuaternion root_rot = mRoot.getWorldRotation();
-				mNameText->setUsePixelSize(TRUE);
-				LLVector3 pixel_right_vec;
-				LLVector3 pixel_up_vec;
-				LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec);
-				LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin();
-				camera_to_av.normalize();
-				LLVector3 local_camera_at = camera_to_av * ~root_rot;
-				LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis();
-				local_camera_up.normalize();
-				local_camera_up = local_camera_up * ~root_rot;
+	idleUpdateNameTagText(new_name);
 			
-				local_camera_up.scaleVec(mBodySize * 0.5f);
-				local_camera_at.scaleVec(mBodySize * 0.5f);
+	idleUpdateNameTagAlpha(new_name, alpha);
+}
 
-				LLVector3 name_position = mRoot.getWorldPosition() + 
-					(local_camera_up * root_rot) -
-					(projected_vec(local_camera_at * root_rot, camera_to_av));
-				name_position += pixel_up_vec * 15.f;
-				mNameText->setPositionAgent(name_position);
-			}
-			else if (mNameText)
+void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
 			{
-				mNameText->markDead();
-				mNameText = NULL;
-				sNumVisibleChatBubbles--;
-			}
-		}
-		
 		LLNameValue *title = getNVPair("Title");
 		LLNameValue* firstname = getNVPair("FirstName");
 		LLNameValue* lastname = getNVPair("LastName");
 
-		if (mNameText.notNull() && firstname && lastname)
+	// Avatars must have a first and last name
+	if (!firstname || !lastname) return;
+
+	bool is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY)  != mSignaledAnimations.end();
+	bool is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end();
+	bool is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end();
+	bool is_muted;
+	if (isSelf())
+	{
+		is_muted = false;
+	}
+	else
 		{
-			const BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY)  != mSignaledAnimations.end();
-			const BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end();
-			const BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end();
-			const BOOL is_muted = isSelf() ? FALSE : LLMuteList::getInstance()->isMuted(getID());
-			const BOOL is_cloud = getIsCloud();
+		is_muted = LLMuteList::getInstance()->isMuted(getID());
+	}
+	bool is_friend = LLAvatarTracker::instance().isBuddy(getID());
+	bool is_cloud = getIsCloud();
 
 			if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
 			{
@@ -2895,105 +2907,129 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
 				}
 			}
 
-			if (mNameString.empty() ||
-				new_name ||
-				(!title && !mTitle.empty()) ||
-				(title && mTitle != title->getString()) ||
-				(is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute)
+	// Rebuild name tag if state change detected
+	if (mNameString.empty()
+		|| new_name
+		|| (!title && !mTitle.empty())
+		|| (title && mTitle != title->getString())
+		|| is_away != mNameAway 
+		|| is_busy != mNameBusy 
+		|| is_muted != mNameMute
 				|| is_appearance != mNameAppearance 
-				|| is_cloud != mNameCloud
-				)
-			{
-				std::string line;
-				if (!sRenderGroupTitles)
-				{
-					// If all group titles are turned off, stack first name
-					// on a line above last name
-					line += firstname->getString();
-					line += "\n";
-				}
-				else if (title && title->getString() && title->getString()[0] != '\0')
+		|| is_friend != mNameFriend
+		|| is_cloud != mNameCloud)
 				{
-					line += title->getString();
-					LLStringFn::replace_ascii_controlchars(line,LL_UNKNOWN_CHAR);
-					line += "\n";
-					line += firstname->getString();
-				}
-				else
-				{
-					line += firstname->getString();
-				}
+		LLColor4 name_tag_color = getNameTagColor(is_friend);
 
-				line += " ";
-				line += lastname->getString();
-				BOOL need_comma = FALSE;
+		clearNameTag();
 
-				if (is_away || is_muted || is_busy)
+		if (is_away || is_muted || is_busy || is_appearance)
 				{
-					line += " (";
+			std::string line;
 					if (is_away)
 					{
 						line += LLTrans::getString("AvatarAway");
-						need_comma = TRUE;
+				line += ", ";
 					}
 					if (is_busy)
 					{
-						if (need_comma)
+				line += LLTrans::getString("AvatarBusy");
+				line += ", ";
+			}
+			if (is_muted)
 						{
+				line += LLTrans::getString("AvatarMuted");
 							line += ", ";
 						}
-						line += LLTrans::getString("AvatarBusy");
-						need_comma = TRUE;
+			if (is_appearance)
+			{
+				line += LLTrans::getString("AvatarEditingAppearance");
+				line += ", ";
 					}
-					if (is_muted)
+			if (is_cloud)
 					{
-						if (need_comma)
+				line += LLTrans::getString("LoadingData");
+				line += ", ";
+			}
+			// trim last ", "
+			line.resize( line.length() - 2 );
+			LLColor4 status_color =
+				LLUIColorTable::getInstance()->getColor("NameTagStatus");
+			addNameTagLine(line, status_color, LLFontGL::NORMAL,
+				LLFontGL::getFontSansSerifSmall());
+		}
+
+		if (sRenderGroupTitles
+			&& title && title->getString() && title->getString()[0] != '\0')
 						{
-							line += ", ";
+			LLColor4 group_color =
+				LLUIColorTable::getInstance()->getColor("NameTagGroup");
+			std::string title_str = title->getString();
+			LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR);
+			addNameTagLine(title_str, group_color, LLFontGL::NORMAL,
+				LLFontGL::getFontSansSerifSmall());
 						}
-						line += LLTrans::getString("AvatarMuted");
-						need_comma = TRUE;
+
+		static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames");
+		static LLUICachedControl<bool> show_usernames("NameTagShowUsernames");
+
+		if (LLAvatarNameCache::useDisplayNames())
+		{
+			LLAvatarName av_name;
+			if (!LLAvatarNameCache::get(getID(), &av_name))
+			{
+				// ...call this function back when the name arrives
+				// and force a rebuild
+				LLAvatarNameCache::get(getID(),
+					boost::bind(&LLVOAvatar::clearNameTag, this));
 					}
-					line += ")";
+
+			// Might be blank if name not available yet, that's OK
+			if (show_display_names)
+			{
+				addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL,
+					LLFontGL::getFontSansSerif());
 				}
-				if (is_cloud)
+			// Suppress SLID display if display name matches exactly (ugh)
+			if (show_usernames && !av_name.mIsDisplayNameDefault)
 				{
-					line += "\n";
-					line += "(" + LLTrans::getString("LoadingData") + ")";
+				// *HACK: Desaturate the color
+				LLColor4 username_color = name_tag_color * 0.83f;
+				addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL,
+					LLFontGL::getFontSansSerifSmall());
+			}
 				}
-				else if (is_appearance)
+		else
 				{
-					line += "\n";
-					line += LLTrans::getString("AvatarEditingAppearance");
+			const LLFontGL* font = LLFontGL::getFontSansSerif();
+			std::string full_name =
+				LLCacheName::buildFullName( firstname->getString(), lastname->getString() );
+			addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font);
 				}
+
 				mNameAway = is_away;
 				mNameBusy = is_busy;
 				mNameMute = is_muted;
 				mNameAppearance = is_appearance;
+		mNameFriend = is_friend;
 				mNameCloud = is_cloud;
 				mTitle = title ? title->getString() : "";
 				LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR);
-				mNameString = utf8str_to_wstring(line);
 				new_name = TRUE;
 			}
 
-			if (visible_chat)
+	if (mVisibleChat)
 			{
-				mNameText->setDropShadow(TRUE);
 				mNameText->setFont(LLFontGL::getFontSansSerif());
-				mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_LEFT);
+		mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT);
 				mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f);
-				if (new_name)
-				{
-					mNameText->setLabel(mNameString);
-				}
 			
 				char line[MAX_STRING];		/* Flawfinder: ignore */
 				line[0] = '\0';
 				std::deque<LLChat>::iterator chat_iter = mChats.begin();
 				mNameText->clearString();
 
-				LLColor4 new_chat = LLUIColorTable::instance().getColor( "AvatarNameColor" );
+		LLColor4 new_chat = LLUIColorTable::instance().getColor( "NameTagChat" );
 				LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f);
 				LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f);
 				if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) 
@@ -3020,17 +3056,17 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
 					if (chat_fade_amt < 1.f)
 					{
 						F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f);
-						mNameText->addLine(utf8str_to_wstring(chat_iter->mText), lerp(new_chat, normal_chat, u), style);
+						mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style);
 					}
 					else if (chat_fade_amt < 2.f)
 					{
 						F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f);
-						mNameText->addLine(utf8str_to_wstring(chat_iter->mText), lerp(normal_chat, old_chat, u), style);
+						mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style);
 					}
 					else if (chat_fade_amt < 3.f)
 					{
 						// *NOTE: only remove lines down to minimum number
-						mNameText->addLine(utf8str_to_wstring(chat_iter->mText), old_chat, style);
+						mNameText->addLine(chat_iter->mText, old_chat, style);
 					}
 				}
 				mNameText->setVisibleOffScreen(TRUE);
@@ -3055,24 +3091,129 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
 			}
 			else
 			{
-				mNameText->setFont(LLFontGL::getFontSansSerif());
-				mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_CENTER);
+		// ...not using chat bubbles, just names
+		mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER);
 				mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
 				mNameText->setVisibleOffScreen(FALSE);
-				if (new_name)
+	}
+}
+
+void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font)
+{
+	llassert(mNameText);
+	if (mVisibleChat)
+	{
+		mNameText->addLabel(line);
+	}
+	else
+	{
+		mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font);
+	}
+	mNameString += line;
+	mNameString += '\n';
+}
+
+void LLVOAvatar::clearNameTag()
+{
+	mNameString.clear();
+	if (mNameText)
 				{
 					mNameText->setLabel("");
-					mNameText->setString(mNameString);
+		mNameText->setString( "" );
+	}
+}
+
+//static
+void LLVOAvatar::invalidateNameTag(const LLUUID& agent_id)
+{
+	LLViewerObject* obj = gObjectList.findObject(agent_id);
+	if (!obj) return;
+
+	LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(obj);
+	if (!avatar) return;
+
+	avatar->clearNameTag();
+}
+
+//static
+void LLVOAvatar::invalidateNameTags()
+{
+	std::vector<LLCharacter*>::iterator it = LLCharacter::sInstances.begin();
+	for ( ; it != LLCharacter::sInstances.end(); ++it)
+	{
+		LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*it);
+		if (!avatar) continue;
+		if (avatar->isDead()) continue;
+
+		avatar->clearNameTag();
 				}
 			}
+
+// Compute name tag position during idle update
+LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)
+{
+	LLQuaternion root_rot = mRoot.getWorldRotation();
+	LLVector3 pixel_right_vec;
+	LLVector3 pixel_up_vec;
+	LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec);
+	LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin();
+	camera_to_av.normalize();
+	LLVector3 local_camera_at = camera_to_av * ~root_rot;
+	LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis();
+	local_camera_up.normalize();
+	local_camera_up = local_camera_up * ~root_rot;
+
+	local_camera_up.scaleVec(mBodySize * 0.5f);
+	local_camera_at.scaleVec(mBodySize * 0.5f);
+
+	LLVector3 name_position = mRoot.getWorldPosition() + 
+		(local_camera_up * root_rot) -
+		(projected_vec(local_camera_at * root_rot, camera_to_av));
+	name_position += pixel_up_vec * 15.f;
+	return name_position;
+		}
+
+void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha)
+{
+	llassert(mNameText);
+
+	if (new_name
+		|| alpha != mNameAlpha)
+	{
+		mNameText->setAlpha(alpha);
+		mNameAlpha = alpha;
+	}
+}
+
+LLColor4 LLVOAvatar::getNameTagColor(bool is_friend)
+{
+	static LLUICachedControl<bool> show_friends("NameTagShowFriends");
+	const char* color_name;
+	if (show_friends && is_friend)
+	{
+		color_name = "NameTagFriend";
+	}
+	else if (LLAvatarNameCache::useDisplayNames())
+	{
+		// ...color based on whether username "matches" a computed display
+		// name
+		LLAvatarName av_name;
+		if (LLAvatarNameCache::get(getID(), &av_name)
+			&& av_name.mIsDisplayNameDefault)
+		{
+			color_name = "NameTagMatch";
 		}
+		else
+		{
+			color_name = "NameTagMismatch";
 	}
-	else if (mNameText)
+	}
+	else
 	{
-		mNameText->markDead();
-		mNameText = NULL;
-		sNumVisibleChatBubbles--;
+		// ...not using display names
+		color_name = "NameTagLegacy";
 	}
+	return LLUIColorTable::getInstance()->getColor( color_name );
 }
 
 //--------------------------------------------------------------------
@@ -6757,7 +6898,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 	{
 		releaseComponentTextures();
 	}
-		
+	
 	// parse visual params
 	S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
 	bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing
@@ -6850,9 +6991,9 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			// re-request appearance, hoping that it comes back with a shape next time
 			llinfos << "Re-requesting AvatarAppearance for object: "  << getID() << llendl;
 			LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID());
-		}
-		else
-		{
+	}
+	else
+	{
 			llinfos << "That's okay, we already have a non-default shape for object: "  << getID() << llendl;
 			// we don't really care.
 		}
@@ -7744,9 +7885,7 @@ std::string LLVOAvatar::getFullname() const
 	LLNameValue* last  = getNVPair("LastName"); 
 	if (first && last)
 	{
-		name += first->getString();
-		name += " ";
-		name += last->getString();
+		name = LLCacheName::buildFullName( first->getString(), last->getString() );
 	}
 
 	return name;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 6d9424c8beb4cf179cee13acf31f58ad08bcb517..62ffdcd27de665e747adad1bed0a8e667a94e441 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -59,7 +59,7 @@ extern const LLUUID ANIM_AGENT_WALK_ADJUST;
 
 class LLTexLayerSet;
 class LLVoiceVisualizer;
-class LLHUDText;
+class LLHUDNameTag;
 class LLHUDEffectSpiral;
 class LLTexGlobalColor;
 class LLVOAvatarBoneInfo;
@@ -207,6 +207,15 @@ class LLVOAvatar :
 	void 			idleUpdateLoadingEffect();
 	void 			idleUpdateWindEffect();
 	void 			idleUpdateNameTag(const LLVector3& root_pos_last);
+	void			idleUpdateNameTagText(BOOL new_name);
+	LLVector3		idleUpdateNameTagPosition(const LLVector3& root_pos_last);
+	void			idleUpdateNameTagAlpha(BOOL new_name, F32 alpha);
+	LLColor4		getNameTagColor(bool is_friend);
+	void			clearNameTag();
+	static void		invalidateNameTag(const LLUUID& agent_id);
+	// force all name tags to rebuild, useful when display names turned on/off
+	static void		invalidateNameTags();
+	void			addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);
 	void 			idleUpdateRenderCost();
 	void 			idleUpdateTractorBeam();
 	void 			idleUpdateBelowWater();
@@ -828,13 +837,15 @@ class LLVOAvatar :
 	static void		getAnimLabels(LLDynamicArray<std::string>* labels);
 	static void		getAnimNames(LLDynamicArray<std::string>* names);	
 private:
-	LLWString 		mNameString;
+	std::string		mNameString;		// UTF-8 title + name + status
 	std::string  	mTitle;
-	BOOL	  		mNameAway;
-	BOOL	  		mNameBusy;
-	BOOL	  		mNameMute;
-	BOOL      		mNameAppearance;
-	BOOL      		mNameCloud;
+	bool	  		mNameAway;
+	bool	  		mNameBusy;
+	bool	  		mNameMute;
+	bool      		mNameAppearance;
+	bool			mNameFriend;
+	bool			mNameCloud;
+	F32				mNameAlpha;
 	BOOL      		mRenderGroupTitles;
 
 	//--------------------------------------------------------------------
@@ -842,7 +853,7 @@ class LLVOAvatar :
 	//--------------------------------------------------------------------
 public:
 	LLFrameTimer	mChatTimer;
-	LLPointer<LLHUDText> mNameText;
+	LLPointer<LLHUDNameTag> mNameText;
 private:
 	LLFrameTimer	mTimeVisible;
 	std::deque<LLChat> mChats;
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index c8d338b0a38000d453d8acd1338f4ba8d4034b16..7cef3c13d1d7d011ccb7f484812b59c733a720fc 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -76,6 +76,9 @@ class LLVoiceChannel : public LLVoiceClientStatusObserver
 	virtual void getChannelInfo();
 	virtual BOOL isActive();
 	virtual BOOL callStarted();
+
+	// Session name is a UI label used for feedback about which person,
+	// group, or phone number you are talking to
 	const std::string& getSessionName() const { return mSessionName; }
 
 	boost::signals2::connection setStateChangedCallback(const state_changed_signal_t::slot_type& callback)
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 2e003dd2b82992d26b60c851d02a107275b5cd39..6b07b0f2286c80830db2921e7b6d398e15433080 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -31,6 +31,8 @@
 
 #include "llsdutil.h"
 
+// Linden library includes
+#include "llavatarnamecache.h"
 #include "llvoavatarself.h"
 #include "llbufferstream.h"
 #include "llfile.h"
@@ -46,6 +48,8 @@
 #include "llviewercontrol.h"
 #include "llkeyboard.h"
 #include "llappviewer.h"	// for gDisconnected, gDisableVoice
+
+// Viewer includes
 #include "llmutelist.h"  // to check for muted avatars
 #include "llagent.h"
 #include "llcachename.h"
@@ -2800,12 +2804,16 @@ void LLVivoxVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
 
 void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
 {
-	std::string name;
 	buddyListEntry *buddy = findBuddy(id);
 
 	// Make sure we don't add a name before it's been looked up.
-	if(gCacheName->getFullName(id, name))
+	LLAvatarName av_name;
+	if(LLAvatarNameCache::get(id, &av_name))
 	{
+		// *NOTE: For now, we feed legacy names to Vivox because I don't know
+		// if their service can support a mix of new and old clients with
+		// different sorts of names.
+		std::string name = av_name.getLegacyName();
 
 		const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
 		bool canSeeMeOnline = false;
@@ -6357,16 +6365,18 @@ void LLVivoxVoiceClient::notifyFriendObservers()
 
 void LLVivoxVoiceClient::lookupName(const LLUUID &id)
 {
-	BOOL is_group = FALSE;
-	gCacheName->get(id, is_group, &LLVivoxVoiceClient::onAvatarNameLookup);
+	LLAvatarNameCache::get(id,
+		boost::bind(&LLVivoxVoiceClient::onAvatarNameCache,
+			this, _1, _2));
 }
 
-//static
-void LLVivoxVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id,
+										   const LLAvatarName& av_name)
 {
-		std::string name = llformat("%s %s", first.c_str(), last.c_str());
-		LLVivoxVoiceClient::getInstance()->avatarNameResolved(id, name);
-	
+	// For Vivox, we use the legacy name because I'm uncertain whether or
+	// not their service can tolerate switching to Username or Display Name
+	std::string legacy_name = av_name.getLegacyName();
+	avatarNameResolved(agent_id, legacy_name);	
 }
 
 void LLVivoxVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name)
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index d10a56261611c99c2b83934a000f6965e0f888a2..b20609de7b3ec9bc8b945ab9275de600ee3cc1bd 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -45,7 +45,7 @@ class LLVivoxProtocolParser;
 #endif
 #include "llvoiceclient.h"
 
-
+class LLAvatarName;
 class LLVivoxVoiceAccountProvisionResponder;
 class LLVivoxVoiceClientMuteListObserver;
 class LLVivoxVoiceClientFriendsObserver;	
@@ -649,7 +649,7 @@ class LLVivoxVoiceClient :	public LLSingleton<LLVivoxVoiceClient>,
 	void leaveAudioSession();
 	
 	void lookupName(const LLUUID &id);
-	static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+	void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
 	void avatarNameResolved(const LLUUID &id, const std::string &name);
 
 	/////////////////////////////
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 1ee3b84b5e7666ae4aeeac587710b4b410bc4252..6a3e1aebfa6c9c2404ee55ebbcec1a41ba315543 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -64,6 +64,8 @@
 #include "llfloaterreg.h"
 #include "llgldbg.h"
 #include "llhudmanager.h"
+#include "llhudnametag.h"
+#include "llhudtext.h"
 #include "lllightconstants.h"
 #include "llresmgr.h"
 #include "llselectmgr.h"
@@ -2108,6 +2110,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset)
 	}
 
 	LLHUDText::shiftAll(offset);
+	LLHUDNameTag::shiftAll(offset);
 	display_update_camera();
 }
 
@@ -5327,7 +5330,8 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start,
 		++iter)
 	{
 		LLVOAvatar* av = (LLVOAvatar*) *iter;
-		if (av->mNameText.notNull() && av->mNameText->lineSegmentIntersect(start, local_end, position))
+		if (av->mNameText.notNull()
+			&& av->mNameText->lineSegmentIntersect(start, local_end, position))
 		{
 			drawable = av->mDrawable;
 			local_end = position;
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 5ba1fc9b21a20cc43bc212383da732ab0ce9d74b..3c1dca926544574f596b697fea96ca492d39f974 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -117,9 +117,6 @@
     <color
      name="AlertTextColor"
      value="0.58 0.66 0.84 1" />
-    <color
-     name="AvatarNameColor"
-     reference="White" />
     <color
      name="AvatarListItemIconDefaultColor"
      reference="White" />
@@ -531,6 +528,38 @@
     <color
      name="MultiSliderTriangleColor"
      reference="Unused?" />
+  <!--
+    <color
+      name="NameTagBackground"
+      value="0.85 0.85 0.85 0.80" />
+      -->
+    <color
+      name="NameTagBackground"
+      value="0 0 0 1" />
+    <color
+     name="NameTagChat"
+     reference="White" />
+    <color
+     name="NameTagFriend"
+     value="0.447 0.784 0.663 1" />
+    <color
+     name="NameTagGroup"
+     value="1 1 1 1" />
+    <color
+     name="NameTagLegacy"
+     reference="White" />
+    <color
+     name="NameTagMatch"
+     reference="White" />
+    <color
+     name="NameTagMismatch"
+     reference="White" />
+    <color
+     name="NameTagSLID"
+     value="1 1 1 1" />
+    <color
+     name="NameTagStatus"
+     value="1 1 1 1" />
     <color
      name="NetMapBackgroundColor"
      value="0 0 0 1" />
@@ -564,6 +593,9 @@
     <color
      name="NotifyTextColor"
      reference="White" />
+    <color
+     name="ObjectBubbleColor"
+     reference="DkGray_66" />
     <color
      name="ObjectChatColor"
      reference="EmphasisColor" />
diff --git a/indra/newview/skins/default/textures/Rounded_Rect.png b/indra/newview/skins/default/textures/Rounded_Rect.png
new file mode 100644
index 0000000000000000000000000000000000000000..c270c280390cbd3be570b10af98388cdad43ec0c
Binary files /dev/null and b/indra/newview/skins/default/textures/Rounded_Rect.png differ
diff --git a/indra/newview/skins/default/textures/icons/Person_Check.png b/indra/newview/skins/default/textures/icons/Person_Check.png
new file mode 100644
index 0000000000000000000000000000000000000000..f8638540d4eb8ecf17d3f19c3c943db35924b50e
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Person_Check.png differ
diff --git a/indra/newview/skins/default/textures/icons/Person_Star.png b/indra/newview/skins/default/textures/icons/Person_Star.png
new file mode 100644
index 0000000000000000000000000000000000000000..ad10580ac45e7b6f4a9b92841feb21956b28a0e8
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Person_Star.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 082b37d80b9dba749e39bec43620822c2d71d175..f293bbd1af8adc97b942a57bec17c1741c3ed6f1 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -358,6 +358,8 @@ with the same filename but different name
   <texture name="Pause_Off" file_name="icons/Pause_Off.png" preload="false" />
   <texture name="Pause_Over" file_name="icons/Pause_Over.png" preload="false" />
   <texture name="Pause_Press" file_name="icons/Pause_Press.png" preload="false" />
+  <texture name="Person_Check" file_name="icons/Person_Check.png" preload="false" />
+  <texture name="Person_Star" file_name="icons/Person_Star.png" preload="false" />
   <texture name="Play_Off" file_name="icons/Play_Off.png" preload="false" />
   <texture name="Play_Over" file_name="icons/Play_Over.png" preload="false" />
   <texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" />
@@ -387,6 +389,7 @@ with the same filename but different name
 
   <texture name="Resize_Corner" file_name="windows/Resize_Corner.png" preload="true" />
 
+  <texture name="Rounded_Rect"	file_name="Rounded_Rect.png" preload="true" scale.left="6" scale.top="24" scale.right="58" scale.bottom="6" />
   <texture name="Rounded_Square"	file_name="rounded_square.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" />
   <texture name="Row_Selection" file_name="navbar/Row_Selection.png" preload="false" />
 
diff --git a/indra/newview/skins/default/xui/da/floater_windlight_options.xml b/indra/newview/skins/default/xui/da/floater_windlight_options.xml
index 65f3f67a70272729bd981d598ef4b7a03e88b1af..56f94b24e9a9625df222e776b2856426f658f9aa 100644
--- a/indra/newview/skins/default/xui/da/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/da/floater_windlight_options.xml
@@ -1,18 +1,18 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater name="WindLight floater" title="AVANCERET OPSÆTNING FOR HIMMEL">
 	<text name="KeyFramePresetsText">
 		Faste indstillinger:
 	</text>
-	<button label="Ny" label_selected="Ny" name="WLNewPreset"/>
-	<button label="Gem" label_selected="Gem" name="WLSavePreset"/>
-	<button label="Slet" label_selected="Slet" name="WLDeletePreset"/>
-	<button label="Dags cyklus" label_selected="Dags cyklus" name="WLDayCycleMenuButton"/>
+	<button label="Ny" label_selected="Ny" name="WLNewPreset" />
+	<button label="Gem" label_selected="Gem" name="WLSavePreset" />
+	<button label="Slet" label_selected="Slet" name="WLDeletePreset" />
+	<button label="Dags cyklus" label_selected="Dags cyklus" name="WLDayCycleMenuButton" />
 	<tab_container name="WindLight Tabs">
 		<panel label="ATMOSFÆRE" name="Atmosphere">
 			<text name="BHText">
 				Blå - horisont
 			</text>
-			<button label="?" name="WLBlueHorizonHelp"/>
+			<button label="?" name="WLBlueHorizonHelp" />
 			<text name="BHText2">
 				R
 			</text>
@@ -25,19 +25,19 @@
 			<text name="BHText5">
 				I
 			</text>
-			<slider label="" name="WLBlueHorizonR"/>
-			<slider label="" name="WLBlueHorizonG"/>
-			<slider label="" name="WLBlueHorizonB"/>
-			<slider label="" name="WLBlueHorizonI"/>
+			<slider label="" name="WLBlueHorizonR" />
+			<slider label="" name="WLBlueHorizonG" />
+			<slider label="" name="WLBlueHorizonB" />
+			<slider label="" name="WLBlueHorizonI" />
 			<text name="BDensText">
 				Dis - horisont
 			</text>
-			<button label="?" name="WLHazeHorizonHelp"/>
-			<slider label="" name="WLHazeHorizon"/>
+			<button label="?" name="WLHazeHorizonHelp" />
+			<slider label="" name="WLHazeHorizon" />
 			<text name="BDensText2">
 				Blå - tæthed
 			</text>
-			<button label="?" name="WLBlueDensityHelp"/>
+			<button label="?" name="WLBlueDensityHelp" />
 			<text name="BHText6">
 				R
 			</text>
@@ -50,36 +50,36 @@
 			<text name="BHText9">
 				I
 			</text>
-			<slider label="" name="WLBlueDensityR"/>
-			<slider label="" name="WLBlueDensityG"/>
-			<slider label="" name="WLBlueDensityB"/>
-			<slider label="" name="WLBlueDensityI"/>
+			<slider label="" name="WLBlueDensityR" />
+			<slider label="" name="WLBlueDensityG" />
+			<slider label="" name="WLBlueDensityB" />
+			<slider label="" name="WLBlueDensityI" />
 			<text name="HDText">
 				Dis - intensitet
 			</text>
-			<button label="?" name="WLHazeDensityHelp"/>
-			<slider label="" name="WLHazeDensity"/>
+			<button label="?" name="WLHazeDensityHelp" />
+			<slider label="" name="WLHazeDensity" />
 			<text name="DensMultText">
 				Densitet faktor
 			</text>
-			<button label="?" name="WLDensityMultHelp"/>
-			<slider label="" name="WLDensityMult"/>
+			<button label="?" name="WLDensityMultHelp" />
+			<slider label="" name="WLDensityMult" />
 			<text name="WLDistanceMultText">
 				Distance faktor
 			</text>
-			<button label="?" name="WLDistanceMultHelp"/>
-			<slider label="" name="WLDistanceMult"/>
+			<button label="?" name="WLDistanceMultHelp" />
+			<slider label="" name="WLDistanceMult" />
 			<text name="MaxAltText">
 				Maximum højde
 			</text>
-			<button label="?" name="WLMaxAltitudeHelp"/>
-			<slider label="" name="WLMaxAltitude"/>
+			<button label="?" name="WLMaxAltitudeHelp" />
+			<slider label="" name="WLMaxAltitude" />
 		</panel>
 		<panel label="LYS" name="Lighting">
 			<text name="SLCText">
 				Sol/MÃ¥ne farve
 			</text>
-			<button label="?" name="WLSunlightColorHelp"/>
+			<button label="?" name="WLSunlightColorHelp" />
 			<text name="BHText">
 				R
 			</text>
@@ -92,19 +92,19 @@
 			<text name="BHText4">
 				I
 			</text>
-			<slider label="" name="WLSunlightR"/>
-			<slider label="" name="WLSunlightG"/>
-			<slider label="" name="WLSunlightB"/>
-			<slider label="" name="WLSunlightI"/>
+			<slider label="" name="WLSunlightR" />
+			<slider label="" name="WLSunlightG" />
+			<slider label="" name="WLSunlightB" />
+			<slider label="" name="WLSunlightI" />
 			<text name="TODText">
 				Sol/MÃ¥ne position
 			</text>
-			<button label="?" name="WLTimeOfDayHelp"/>
-			<slider label="" name="WLSunAngle"/>
+			<button label="?" name="WLTimeOfDayHelp" />
+			<slider label="" name="WLSunAngle" />
 			<text name="WLAmbientText">
 				Omgivende
 			</text>
-			<button label="?" name="WLAmbientHelp"/>
+			<button label="?" name="WLAmbientHelp" />
 			<text name="BHText5">
 				R
 			</text>
@@ -117,37 +117,37 @@
 			<text name="BHText8">
 				I
 			</text>
-			<slider label="" name="WLAmbientR"/>
-			<slider label="" name="WLAmbientG"/>
-			<slider label="" name="WLAmbientB"/>
-			<slider label="" name="WLAmbientI"/>
+			<slider label="" name="WLAmbientR" />
+			<slider label="" name="WLAmbientG" />
+			<slider label="" name="WLAmbientB" />
+			<slider label="" name="WLAmbientI" />
 			<text name="WLEastAngleText">
 				Øst vinkel
 			</text>
-			<button label="?" name="WLEastAngleHelp"/>
-			<slider label="" name="WLEastAngle"/>
+			<button label="?" name="WLEastAngleHelp" />
+			<slider label="" name="WLEastAngle" />
 			<text name="SunGlowText">
 				Sol glød
 			</text>
-			<button label="?" name="WLSunGlowHelp"/>
-			<slider label="Fokus " name="WLGlowB"/>
-			<slider label="Størr. " name="WLGlowR"/>
+			<button label="?" name="WLSunGlowHelp" />
+			<slider label="Fokus " name="WLGlowB" />
+			<slider label="Størr. " name="WLGlowR" />
 			<text name="SceneGammaText">
 				Lysintensitet (gamma)
 			</text>
-			<button label="?" name="WLSceneGammaHelp"/>
-			<slider label="" name="WLGamma"/>
+			<button label="?" name="WLSceneGammaHelp" />
+			<slider label="" name="WLGamma" />
 			<text name="WLStarText">
 				Stjerne intensitet
 			</text>
-			<button label="?" name="WLStarBrightnessHelp"/>
-			<slider label="" name="WLStarAlpha"/>
+			<button label="?" name="WLStarBrightnessHelp" />
+			<slider label="" name="WLStarAlpha" />
 		</panel>
 		<panel label="SKYER" name="Clouds">
 			<text name="WLCloudColorText">
 				Farve på skyer
 			</text>
-			<button label="?" name="WLCloudColorHelp"/>
+			<button label="?" name="WLCloudColorHelp" />
 			<text name="BHText">
 				R
 			</text>
@@ -160,14 +160,14 @@
 			<text name="BHText4">
 				I
 			</text>
-			<slider label="" name="WLCloudColorR"/>
-			<slider label="" name="WLCloudColorG"/>
-			<slider label="" name="WLCloudColorB"/>
-			<slider label="" name="WLCloudColorI"/>
+			<slider label="" name="WLCloudColorR" />
+			<slider label="" name="WLCloudColorG" />
+			<slider label="" name="WLCloudColorB" />
+			<slider label="" name="WLCloudColorI" />
 			<text name="WLCloudColorText2">
 				Skyer XY/Tæthed
 			</text>
-			<button label="?" name="WLCloudDensityHelp"/>
+			<button label="?" name="WLCloudDensityHelp" />
 			<text name="BHText5">
 				X
 			</text>
@@ -177,23 +177,23 @@
 			<text name="BHText7">
 				T
 			</text>
-			<slider label="" name="WLCloudX"/>
-			<slider label="" name="WLCloudY"/>
-			<slider label="" name="WLCloudDensity"/>
+			<slider label="" name="WLCloudX" />
+			<slider label="" name="WLCloudY" />
+			<slider label="" name="WLCloudDensity" />
 			<text name="WLCloudCoverageText">
 				Skydække
 			</text>
-			<button label="?" name="WLCloudCoverageHelp"/>
-			<slider label="" name="WLCloudCoverage"/>
+			<button label="?" name="WLCloudCoverageHelp" />
+			<slider label="" name="WLCloudCoverage" />
 			<text name="WLCloudScaleText">
 				Skystørrelse
 			</text>
-			<button label="?" name="WLCloudScaleHelp"/>
-			<slider label="" name="WLCloudScale"/>
+			<button label="?" name="WLCloudScaleHelp" />
+			<slider label="" name="WLCloudScale" />
 			<text name="WLCloudDetailText">
 				Sky detaljer(XY/tæthed)
 			</text>
-			<button label="?" name="WLCloudDetailHelp"/>
+			<button label="?" name="WLCloudDetailHelp" />
 			<text name="BHText8">
 				X
 			</text>
@@ -203,23 +203,23 @@
 			<text name="BHText10">
 				T
 			</text>
-			<slider label="" name="WLCloudDetailX"/>
-			<slider label="" name="WLCloudDetailY"/>
-			<slider label="" name="WLCloudDetailDensity"/>
+			<slider label="" name="WLCloudDetailX" />
+			<slider label="" name="WLCloudDetailY" />
+			<slider label="" name="WLCloudDetailDensity" />
 			<text name="WLCloudScrollXText">
 				Sky drift X
 			</text>
-			<button label="?" name="WLCloudScrollXHelp"/>
-			<check_box label="LÃ¥s" name="WLCloudLockX"/>
-			<slider label="" name="WLCloudScrollX"/>
+			<button label="?" name="WLCloudScrollXHelp" />
+			<check_box label="LÃ¥s" name="WLCloudLockX" />
+			<slider label="" name="WLCloudScrollX" />
 			<text name="WLCloudScrollYText">
 				Sky drift Y
 			</text>
-			<button label="?" name="WLCloudScrollYHelp"/>
-			<check_box label="LÃ¥s" name="WLCloudLockY"/>
-			<slider label="" name="WLCloudScrollY"/>
-			<check_box label="Benyt simple skyer" name="DrawClassicClouds"/>
-			<button label="?" name="WLClassicCloudsHelp"/>
+			<button label="?" name="WLCloudScrollYHelp" />
+			<check_box label="LÃ¥s" name="WLCloudLockY" />
+			<slider label="" name="WLCloudScrollY" />
+			<check_box label="Benyt simple skyer" name="DrawClassicClouds" />
+			<button label="?" name="WLClassicCloudsHelp" />
 		</panel>
 	</tab_container>
 	<string name="WLDefaultSkyNames">
diff --git a/indra/newview/skins/default/xui/da/panel_classified_info.xml b/indra/newview/skins/default/xui/da/panel_classified_info.xml
index 28f89364573cb576f0c29503fd211f1fd1c3df60..0bb52b8fa6bed7f1e56755a1677dbe08c88588f8 100644
--- a/indra/newview/skins/default/xui/da/panel_classified_info.xml
+++ b/indra/newview/skins/default/xui/da/panel_classified_info.xml
@@ -40,7 +40,7 @@
 				</layout_panel>
 				<layout_panel name="descr_layout_panel">
 					<text name="classified_desc_label" value="Beskrivelse:"/>
-					<text_editor name="classified_desc" value="[description]"/>
+			<text_editor name="classified_desc" value="[description]"/>
 				</layout_panel>
 			</layout_stack>
 		</panel>
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 99bf3e6bc124ea74add262b27b5fdd809d101f52..671d8391e65a82a64af7f0a143806affe3bca5cc 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -220,7 +220,8 @@
              layout="topleft"
              left_pad="2"
              name="OwnerText"
-             width="240">
+             use_ellipses="true" 
+             width="360">
                 Leyla Linden
             </text>
              <button
@@ -374,7 +375,8 @@ Leyla Linden               </text>
              left_delta="-199"
              name="For sale to"
              top_delta="20"
-             width="186">
+             use_ellipses="true" 
+             width="340">
                 For sale to: [BUYER]
             </text>
             <text
@@ -410,7 +412,7 @@ Leyla Linden               </text>
              right="-10"
              name="Cancel Land Sale"
              left_pad="5"
-             top_pad="-25"
+             top_pad="-15"
              width="180" />
             <text
              type="string"
@@ -541,7 +543,7 @@ Leyla Linden               </text>
              layout="topleft"
              left_delta="0"
              name="Reclaim Land..."
-             top_delta="-61"
+             top_delta="-50"
              width="180" />
             <button
              enabled="false"
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
index f59badfcb4513c7d299d954e6417fc01d0956914..a11946d3520491e713aca29828066f1f40370730 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
@@ -5,11 +5,11 @@
  height="350"
  layout="topleft"
  min_height="200"
- min_width="265"
+ min_width="400"
  name="avatarpicker"
  help_topic="avatarpicker"
  title="CHOOSE RESIDENT"
- width="265">
+ width="500">
     <floater.string
      name="not_found">
         &apos;[TEXT]&apos; not found
@@ -40,7 +40,7 @@
      name="ResidentChooserTabs"
      tab_position="top"
      top="20"
-     width="265">
+     width="500">
         <panel
          border="none"
          height="150"
@@ -83,14 +83,24 @@
              left_pad="5"
              name="Find"
              width="45" />
-            <scroll_list
-             follows="all"
-             height="98"
-             layout="topleft"
-             left="0"
-             name="SearchResults"
-             top="52"
-             width="132" />
+          <scroll_list
+            draw_heading="true" 
+           follows="all"
+           height="98"
+           layout="topleft"
+           left="0"
+           name="SearchResults"
+           top="52"
+           width="132">
+            <columns
+              label="Name"
+              name="name"
+              width="150" />
+            <columns
+              label="Username"
+              name="username"
+              width="150" />
+          </scroll_list>
         </panel>
         <panel
          border="none"
@@ -128,7 +138,7 @@
             </button>
             <scroll_list
              follows="all"
-             height="100"
+             height="120"
              border="false"
              layout="topleft"
              left="0"
@@ -194,7 +204,8 @@
              width="28"
              name="Refresh"
              image_overlay="Refresh_Off" />
-            <scroll_list
+          <scroll_list
+             draw_heading="true"
              follows="all"
              height="100"
              border="false"
@@ -202,21 +213,30 @@
              left="0"
              name="NearMe"
              sort_column="0"
-             top="50"
-             width="132" />
+             top="52"
+             width="132">
+            <columns
+              label="Name"
+              name="name"
+              width="150" />
+            <columns
+              label="Username"
+              name="username"
+              width="150" />
+          </scroll_list>
         </panel>
     </tab_container>
     <button
-     follows="right|bottom"
+     follows="left|bottom"
      height="23"
      label="OK"
      label_selected="OK"
      name="ok_btn"
      top_pad="3"
-     left="46"
+     left="10"
      width="100" />
     <button
-     follows="right|bottom"
+     follows="left|bottom"
      height="23"
      label="Cancel"
      label_selected="Cancel"
diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml
index 303c28d7c88a5bcd8df7a3d7c63444524ff7d4ee..1f2fe62b3cf85edb2dd0daa44f8173c75356ebb6 100644
--- a/indra/newview/skins/default/xui/en/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/en/floater_bumps.xml
@@ -14,23 +14,23 @@
     </floater.string>
     <floater.string
      name="bump">
-        [TIME]  [FIRST] [LAST] bumped you
+        [TIME]  [NAME] bumped you
     </floater.string>
     <floater.string
      name="llpushobject">
-        [TIME]  [FIRST] [LAST] pushed you with a script
+        [TIME]  [NAME] pushed you with a script
     </floater.string>
     <floater.string
      name="selected_object_collide">
-        [TIME]  [FIRST] [LAST] hit you with an object
+        [TIME]  [NAME] hit you with an object
     </floater.string>
     <floater.string
      name="scripted_object_collide">
-        [TIME]  [FIRST] [LAST] hit you with a scripted object
+        [TIME]  [NAME] hit you with a scripted object
     </floater.string>
     <floater.string
      name="physical_object_collide">
-        [TIME]  [FIRST] [LAST] hit you with a physical object
+        [TIME]  [NAME] hit you with a physical object
     </floater.string>
     <floater.string
      name="timeStr">
diff --git a/indra/newview/skins/default/xui/en/floater_buy_land.xml b/indra/newview/skins/default/xui/en/floater_buy_land.xml
index c88de878f49ad2330ad2afd62f87781ae5f8692e..d5d4565ca1bb02a7f6aa45539dcef793ee69f273 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml
@@ -569,7 +569,7 @@ sold with objects
          name="US$6.00/month,billedannually" />
     </combo_box>
     <locate
-     height="10"
+     height="5"
      layout="topleft" />
     <icon
      follows="top|left"
@@ -590,7 +590,7 @@ sold with objects
      left="72"
      name="land_use_action"
      right="438"
-     top="284"
+     top="279"
      width="218"
      wrap="true">
         Increase your monthly land use fees to US$ 40/month.
@@ -610,7 +610,7 @@ sold with objects
 This parcel is 512 m² of land.
     </text>
     <locate
-     height="10"
+     height="5"
      layout="topleft" />
     <icon
      follows="top|left"
@@ -654,7 +654,7 @@ This parcel is 512 m² of land.
      left_delta="0"
      name="currency_action"
      top_pad="9"
-     width="90">
+     width="95">
         Buy additional L$
     </text>
     <locate
diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml
index 3d8f5d678b0cd083888e857712f24ac9ea042744..db595458c0362c36fcbed7d3d2f3b542a850bcae 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml
@@ -2,7 +2,7 @@
 <floater
  legacy_header_height="18"
  can_resize="true"
- height="290"
+ height="310"
  layout="topleft"
  min_height="150"
  min_width="225"
@@ -84,15 +84,18 @@
      length="1"
      follows="left|right|bottom"
      font="SansSerif"
-     height="16"
+     height="35"
      layout="topleft"
      left_delta="0"
+	 line_spacing.pixels="7"
      name="buy_text"
      text_color="white"
      top_pad="5"
      use_ellipses="true"
-     width="260">
-        Buy for L$[AMOUNT] from [NAME]?
+     width="260"
+	 word_wrap="true">
+Buy for L$[AMOUNT] from:
+[NAME]?
     </text>
     <button
      follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
index 24fff6d4aeb1ebf427d9c00b3380750d0e09f015..81194f61cf50e94cae5af2560ba56d2a1685985e 100644
--- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
@@ -8,7 +8,7 @@
  layout="topleft"
  name="incoming call"
  help_topic="incoming_call"
- title="UNKNOWN PERSON IS CALLING"
+ title="Incoming call"
  width="410">
     <floater.string
      name="lifetime">
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
index 366098013b5b13a758d47c305b1637fef077ea78..2ef52bf5391daa614eabd01cb7c38e8e84098680 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
@@ -106,6 +106,7 @@
      left_delta="78"
      name="LabelCreatorName"
      top_delta="0"
+     use_ellipses="true" 
      width="170">
         Nicole Linden
     </text>
@@ -139,8 +140,9 @@
      left_delta="78"
      name="LabelOwnerName"
      top_delta="0"
+     use_ellipses="true"
      width="170">
-        Thrax Linden
+      Thrax Linden
     </text>
     <button
      follows="top|right"
diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml
index 509cffe490b7460add9b0d298a17bef22d0b64e6..7ab565313ea6cd55a00d4f0ffebd5e02ade23225 100644
--- a/indra/newview/skins/default/xui/en/floater_pay.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay.xml
@@ -7,7 +7,7 @@
  name="Give Money"
  help_topic="give_money"
  save_rect="true"
- width="225">
+ width="250">
    <string
     name="payee_group">
         Pay Group
@@ -16,28 +16,7 @@
     name="payee_resident">
         Pay Resident
    </string>
-   <text
-     type="string"
-     length="1"
-     follows="left|top"
-     height="18"
-     layout="topleft"
-     left="12"
-     name="payee_label"
-     top="22"
-     width="75">
-        Pay:
-    </text>
-   <icon
-     height="16"
-     width="16"
-     image_name="Generic_Person"
-     mouse_opaque="true"
-     name="icon_person"
-     tool_tip="Person"
-     top_pad="0"
-     left="10"
-     />
+
     <text
      type="string"
      length="1"
@@ -45,17 +24,19 @@
      font="SansSerifSmall"
      height="16"
      layout="topleft"
-     left_pad="7"
+     left="10"
      name="payee_name"
-     width="210">
-        [FIRST] [LAST]
+     top="25" 
+     use_ellipses="true"
+     width="230">
+        Test Name That Is Extremely Long To Check Clipping
     </text>
     <button
      height="23"
      label="L$1"
      label_selected="L$1"
      layout="topleft"
-     left="25"
+     left="35"
      name="fastpay 1"
      top_pad="8"
      width="80" />
@@ -72,7 +53,7 @@
      label="L$10"
      label_selected="L$10"
      layout="topleft"
-     left="25"
+     left="35"
      name="fastpay 10"
      top_pad="8"
      width="80" />
@@ -90,7 +71,7 @@
      follows="left|top"
      height="18"
      layout="topleft"
-     left="25"
+     left="35"
      name="amount text"
      top_pad="8"
      width="180">
@@ -102,7 +83,7 @@
      height="19"
      top_pad="0"
      layout="topleft"
-     left="120"
+     left="130"
      max_length="9"
      name="amount"
      width="80" />
@@ -112,16 +93,16 @@
      label="Pay"
      label_selected="Pay"
      layout="topleft"
-     left="10"
+     left="20"
      name="pay btn"
-     top_pad="5"
+     top_pad="15"
      width="100" />
     <button
      height="23"
      label="Cancel"
      label_selected="Cancel"
      layout="topleft"
-     left_pad="5"
+     left_pad="10"
      name="cancel btn"
      width="100" />
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_pay_object.xml b/indra/newview/skins/default/xui/en/floater_pay_object.xml
index d09a0a0535054610da208a6228c788c1ca225c49..d8cfed7b09ad11f9bbd85ddd60721579408c93bd 100644
--- a/indra/newview/skins/default/xui/en/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay_object.xml
@@ -2,12 +2,12 @@
 <floater
  legacy_header_height="18"
  can_minimize="false"
- height="220"
+ height="225"
  layout="topleft"
  name="Give Money"
  help_topic="give_money"
  save_rect="true"
- width="225">
+ width="250">
     <string
      name="payee_group">
         Pay Group
@@ -16,27 +16,16 @@
      name="payee_resident">
         Pay Resident
     </string>
-   <icon
-     height="16"
-     width="16"
-     image_name="Generic_Person"
-     mouse_opaque="true"
-     name="icon_person"
-     tool_tip="Person"
-     top_pad="24"
-     left="10"
-     />
     <text
-     type="string"
-     length="1"
      follows="left|top"
      height="16"
      layout="topleft"
-     left_pad="7"
-     top_delta="3"
+     left="10"
+     top_pad="24"
      name="payee_name"
-     width="184">
-      [FIRST] [LAST]
+     use_ellipses="true" 
+     width="225">
+      Ericacita Moostopolison
     </text>
     <text
      type="string"
@@ -45,9 +34,9 @@
      halign="left"
      height="14"
      layout="topleft"
-     left="34"
+     left="10"
      name="object_name_label"
-     top_pad="0"
+     top_pad="5"
      width="180">
         Via object:
     </text>
@@ -58,7 +47,7 @@
      mouse_opaque="true"
      name="icon_object"
      tool_tip="Objects"
-     top_pad="0"
+     top_pad="5"
      left="10"
      />
     <text
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index 21c0bfef48b6114d71830f45ee8d8a61c54ca5d0..47383c80101db97dbcbb0517ee18523b2dfc76c6 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -373,7 +373,6 @@
      height="23"
      layout="topleft"
      left_delta="0"
-     max_length="32"
      name="abuser_name_edit"
      top_pad="0"
      width="195" />
diff --git a/indra/newview/skins/default/xui/en/floater_sell_land.xml b/indra/newview/skins/default/xui/en/floater_sell_land.xml
index 4cae42bcfe7528ca2be28f274029b99515152b8d..619669d28a6af44382498c9b9abb0ca414f65c0e 100644
--- a/indra/newview/skins/default/xui/en/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_sell_land.xml
@@ -164,7 +164,7 @@
      left_delta="0"
      name="sell_to_agent"
      top_pad="4"
-     width="130" />
+     width="170" />
     <button
      height="20"
      label="Select"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 1d58e7a540f4d2702d80f2c716c1de3943e6334d..ad9b54a0721c9021ab0012c9f37214d9efed4ebe 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -253,7 +253,7 @@
      height="28"
 	 control_name="EditLinkedParts"
      label="Edit linked"
-     layout="topleft"     
+     layout="topleft"
      name="checkbox edit linked parts"
      top_pad="0">
 		  <check_box.commit_callback
@@ -770,7 +770,7 @@
 	 name="General"
 	 top="16"
 	 width="295">
-<panel.string
+	 <panel.string
 	  name="text deed continued">
 		Deed
 	 </panel.string>
@@ -862,19 +862,23 @@
              height="19"
              layout="topleft"
              name="Creator:"
+             top_pad="7"
              width="90">
                 Creator:
             </text>
+            <!-- *NOTE: Intentionally wide for long names -->
             <text
              type="string"
              length="1"
              follows="left|top"
              left_pad="0"
-             height="19"
+             height="30"
              layout="topleft"
              name="Creator Name"
-             width="175">
-                Esbee Linden
+             top_delta="0"
+             width="190"
+             word_wrap="true">
+                Mrs. Esbee Linden (esbee.linden)
             </text>
             <text
              type="string"
@@ -884,19 +888,23 @@
              height="19"
              layout="topleft"
              name="Owner:"
+             top_pad="3"
              width="90">
                 Owner:
             </text>
+            <!-- *NOTE: Intentionally wide for long names -->
             <text
              type="string"
              length="1"
              follows="left|top"
-             height="19"
+             height="30"
              layout="topleft"
              name="Owner Name"
              left_pad="0"
-             width="175">
-                Erica Linden
+             top_delta="0"
+             width="190"
+             word_wrap="true">
+                Mrs. Erica "Moose" Linden (erica.linden)
             </text>
            <text
              type="string"
@@ -906,7 +914,7 @@
              left="10"
              height="18"
              name="Group:"
-             top_pad="4"
+             top_pad="7"
              width="75">
                 Group:
             </text>
@@ -1060,8 +1068,8 @@ even though the user gets a free copy.
          bg_alpha_color="DkGray"
          name="perms_build"
          left="0"
-         top="241"
-         height="130"
+         top_pad="4"
+         height="105"
          width="290">
             <text
              type="string"
@@ -1132,14 +1140,16 @@ even though the user gets a free copy.
              top_delta="0"
              tool_tip="Next owner can give away or resell this object"
              width="100" />
+<!-- *NOTE: These "B/O/G/E/N/F fields may overlap "perm_modify" above, 
+     but that's OK, this is used only for debugging. -->
             <text
              type="string"
              text_color="EmphasisColor"
              length="1"
-             top_pad="5"
+             top="9"
              follows="left|top"
              layout="topleft"
-             left="10"
+             left="230"
              name="B:"
              height="10"
              width="80">
@@ -1151,7 +1161,8 @@ even though the user gets a free copy.
              length="1"
              follows="left|top"
              layout="topleft"
-             left_pad="0"
+             left_delta="0"
+             top_pad="2"
              name="O:"
              height="10"
              width="80">
@@ -1163,7 +1174,8 @@ even though the user gets a free copy.
              length="1"
              follows="left|top"
              layout="topleft"
-             left_pad="0"
+             left_delta="0"
+             top_pad="2"
              name="G:"
              height="10"
              width="80">
@@ -1174,7 +1186,7 @@ even though the user gets a free copy.
              text_color="White"
              length="1"
              follows="left|top"
-             left="10"
+             left_delta="0"
              top_pad="2"
              layout="topleft"
              name="E:"
@@ -1188,7 +1200,8 @@ even though the user gets a free copy.
              length="1"
              follows="left|top"
              layout="topleft"
-             left_pad="0"
+             left_delta="0"
+             top_pad="2"
              name="N:"
              height="10"
              width="80">
@@ -1200,7 +1213,8 @@ even though the user gets a free copy.
              length="1"
              follows="left|top"
              layout="topleft"
-             left_pad="0"
+             left_delta="0"
+             top_pad="2"
              name="F:"
              height="10"
              width="80">
@@ -1208,6 +1222,7 @@ even though the user gets a free copy.
             </text>
         </panel>
       </panel>
+      <!-- Object tab -->
       <panel
          border="false"
          follows="all"
@@ -2974,4 +2989,5 @@ even though the user gets a free copy.
          top_pad="4"
          width="125" />
  </panel>
+<!-- end of tabs -->
 </floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml
index 194ae151d23a6f541e58731adad064199e19e357..b2efd134413f0786954528e9dcd974ac2e26e045 100644
--- a/indra/newview/skins/default/xui/en/inspect_avatar.xml
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml
@@ -9,13 +9,13 @@
  bg_opaque_image="Inspector_Background"
  can_close="false"
  can_minimize="false"
- height="148"
+ height="164"
  layout="topleft"
  name="inspect_avatar"
  single_instance="true"
  sound_flags="0"
  visible="true"
- width="228">
+ width="245">
   <!-- Allowed fields include:
 	[BORN_ON] ("12/3/2008")
 	[SL_PROFILE] (Second Life profile),
@@ -34,15 +34,38 @@
     </string>
   <text
      follows="top|left"
-     font="SansSerifLarge"
-     height="16"
+     font="SansSerif"
+     height="20"
      left="8"
-     name="user_name"
-     top="10"
+     name="user_name_small"
+     top="7"
      text_color="White"
      use_ellipses="true"
-     value="Grumpity ProductEngine"
-     width="175" />
+     word_wrap="true"
+     value="Grumpity ProductEngine with a long name"
+     width="185" />
+   <text
+    follows="top|left"
+    font="SansSerifBigLarge"
+    height="21"
+    left="8"
+    name="user_name"
+    top="10"
+    text_color="White"
+    use_ellipses="true"
+    visible="false" 
+    value="Grumpity ProductEngine"
+    width="190" />
+   <text
+     follows="top|left"
+     height="16"
+     left="8"
+     name="user_slid"
+     font="SansSerifSmall"
+     text_color="White"
+     value="James.pinden"
+     width="175"
+     use_ellipses="true" />
     <text
      follows="top|left"
      height="16"
@@ -50,6 +73,7 @@
      name="user_subtitle"
      font="SansSerifSmall"
      text_color="White"
+     top_pad="0" 
      value="11 Months, 3 days old"
      width="175"
      use_ellipses="true" />
@@ -60,9 +84,9 @@
      name="user_details"
      right="-10"
      word_wrap="true"
-     top_pad="6"
+     top_pad="4"
      use_ellipses="true"
-     width="220">This is my second life description and I really think it is great.
+     width="220">This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot
     </text>
     <slider
      follows="top|left"
@@ -76,7 +100,7 @@
      tool_tip="Voice volume"
      top_pad="0"
      value="0.5"
-     width="195" />
+     width="200" />
     <button
      follows="top|left"
      height="16"
@@ -108,7 +132,7 @@
      height="20"
      label="Add Friend"
      left="8"
-     top="119"
+     top="135"
      name="add_friend_btn"
      width="90" />
     <button
@@ -152,7 +176,7 @@
      width="35" />
   <panel 
     follows="top|left" 
-    top="148" 
+    top="164" 
     left="0" 
     height="60" 
     width="228" 
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index c79a484ef63d5b46f00b71bfe17a8dd3433f152d..d2fbb801f451efe304f768dfbe713fa163f57cc3 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2752,6 +2752,12 @@
             <menu_item_call.on_click
              function="Advanced.SendTestIMs" />
           </menu_item_call>
+          <menu_item_call
+           label="Flush Names Caches"
+           name="Flush Names Caches">
+            <menu_item_call.on_click
+             function="Advanced.FlushNameCaches" />
+          </menu_item_call>
         </menu>
         <menu
          create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 609a9b09be4e9af0504bf2c125b8c8408a08daba..b9977c60ea8f528019cb738f54c856cd06cc4df6 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -257,7 +257,7 @@ Save all changes to clothing/body parts?
    name="GrantModifyRights"
    type="alertmodal">
 Granting modify rights to another Resident allows them to change, delete or take ANY objects you may have in-world. Be VERY careful when handing out this permission.
-Do you want to grant modify rights for [FIRST_NAME] [LAST_NAME]?
+Do you want to grant modify rights for [NAME]?
     <usetemplate
      name="okcancelbuttons"
      notext="No"
@@ -280,7 +280,7 @@ Do you want to grant modify rights for the selected Residents?
    icon="alertmodal.tga"
    name="RevokeModifyRights"
    type="alertmodal">
-Do you want to revoke modify rights for [FIRST_NAME] [LAST_NAME]?
+Do you want to revoke modify rights for [NAME]?
     <usetemplate
      name="okcancelbuttons"
      notext="No"
@@ -717,7 +717,7 @@ You can not wear that item because it has not yet loaded. Please try again in a
    name="MustHaveAccountToLogIn"
    type="alertmodal">
 Oops! Something was left blank.
-You need to enter both the First and Last name of your avatar.
+You need to enter the Username name of your avatar.
 
 You need an account to enter [SECOND_LIFE]. Would you like to create one now?
     <url
@@ -737,7 +737,7 @@ You need an account to enter [SECOND_LIFE]. Would you like to create one now?
    icon="alertmodal.tga"
    name="InvalidCredentialFormat"
    type="alertmodal">
-You need to enter both the First and Last name of your avatar into the Username field, then login again.
+You need to enter either the Username or both the First and Last name of your avatar into the Username field, then login again.
   </notification>
   
 
@@ -2018,20 +2018,6 @@ Unable to buy land for the group:
 You do not have permission to buy land for your active group.
   </notification>
 
-  <notification
-   icon="alertmodal.tga"
-   label="Add Friend"
-   name="AddFriend"
-   type="alertmodal">
-Friends can give permissions to track each other on the map and receive online status updates.
-
-Offer friendship to [NAME]?
-    <usetemplate
-     name="okcancelbuttons"
-     notext="Cancel"
-     yestext="OK"/>
-  </notification>
-
   <notification
    icon="alertmodal.tga"
    label="Add Friend"
@@ -2128,7 +2114,7 @@ Would you be my friend?
    icon="alertmodal.tga"
    name="RemoveFromFriends"
    type="alertmodal">
-Do you want to remove [FIRST_NAME] [LAST_NAME] from your Friends List?
+Do you want to remove [NAME] from your Friends List?
     <usetemplate
      name="okcancelbuttons"
      notext="Cancel"
@@ -2381,7 +2367,7 @@ Deed this [AREA] m² of land to the group &apos;[GROUP_NAME]&apos;?
    name="DeedLandToGroupWithContribution"
    type="alertmodal">
 By deeding this parcel, the group will be required to have and maintain sufficient land use credits.
-The deed will include a simultaneous land contribution to the group from &apos;[FIRST_NAME] [LAST_NAME]&apos;.
+The deed will include a simultaneous land contribution to the group from &apos;[NAME]&apos;.
 The purchase price of the land is not refunded to the owner. If a deeded parcel is sold, the sale price will be divided evenly among group members.
 
 Deed this [AREA] m² of land to the group &apos;[GROUP_NAME]&apos;?
@@ -3199,6 +3185,103 @@ You are no longer frozen.
     </form>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="SetDisplayName"
+   type="alert">
+The name above your avatar's head is called a [http://wiki.secondlife.com/wiki/Setting_your_display_name display name]. You can change it periodically.
+
+Press reset to make it the same as your username.
+
+Change your display name?
+    <form name="form">
+      <input name="display_name" type="text">
+[DISPLAY_NAME]
+      </input>
+      <button
+       default="true"
+       index="0"
+       name="Change"
+       text="Change"/>
+      <button
+       index="1"
+       name="Reset"
+       text="Reset"/>
+      <button
+       index="2"
+       name="Cancel"
+       text="Cancel"/>
+    </form>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SetDisplayNameSuccess"
+   type="alert">
+Hi [DISPLAY_NAME]!
+
+Just like in real life, it takes a while for everyone to learn about a new name.  Please allow several days for [http://wiki.secondlife.com/wiki/Setting_your_display_name your name to update] in objects, scripts, search, etc.
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SetDisplayNameFailedLockout"
+   type="alert">
+Sorry, you cannot [http://wiki.secondlife.com/wiki/Setting_your_display_name change your display name] until:
+[TIME]
+  </notification>
+
+  <notification
+ icon="alertmodal.tga"
+ name="SetDisplayNameBlocked"
+ type="alert">
+Sorry, you cannot change your display name. If you feel this is in error, please contact support.
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SetDisplayNameFailedLength"
+   type="alertmodal">
+Sorry, that name is too long.  Display names can have a maximum of [LENGTH] characters.
+
+Please try a shorter name.
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SetDisplayNameFailedGeneric"
+   type="alertmodal">
+    Sorry, we could not set your display name.  Please try again later.
+  </notification>
+
+<!-- *NOTE: This should never happen, users should see SetDisplayNameFailedLockout above -->
+  <notification
+   icon="alertmodal.tga"
+   name="AgentDisplayNameUpdateThresholdExceeded"
+   type="alertmodal">
+Sorry, you have to wait longer before you can change your display name.
+
+See http://wiki.secondlife.com/wiki/Setting_your_display_name
+
+Please try again later.
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="AgentDisplayNameSetBlocked"
+   type="alertmodal">
+ Sorry, we could not set your requested name because it contains a banned word.
+ 
+ Please try a different name.
+  </notification>
+
+  <notification
+   icon="notifytip.tga"
+   name="DisplayNameUpdate"
+   type="notifytip">
+    [OLD_NAME] ([SLID]) is now known as [NEW_NAME].
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="OfferTeleport"
@@ -4516,14 +4599,14 @@ Topic: [SUBJECT], Message: [MESSAGE]
    icon="notifytip.tga"
    name="FriendOnline"
    type="notifytip">
-[FIRST] [LAST] is Online
+[NAME] is Online
   </notification>
 
   <notification
    icon="notifytip.tga"
    name="FriendOffline"
    type="notifytip">
-[FIRST] [LAST] is Offline
+[NAME] is Offline
   </notification>
 
   <notification
@@ -4677,13 +4760,6 @@ You cannot modify protected categories.
 You cannot remove protected categories.
   </notification>
 
-  <notification
-   icon="notifytip.tga"
-   name="OfferedCard"
-   type="notifytip">
-You have offered a calling card to [FIRST] [LAST]
-  </notification>
-
   <notification
    icon="notifytip.tga"
    name="UnableToBuyWhileDownloading"
@@ -4839,7 +4915,15 @@ Please select at least one type of content to search (General, Moderate, or Adul
 
   <notification
    icon="notify.tga"
-   name="PaymentRecived"
+   name="PaymentReceived"
+   persist="true"
+   type="notify">
+[MESSAGE]
+  </notification>
+
+  <notification
+   icon="notify.tga"
+   name="PaymentSent"
    persist="true"
    type="notify">
 [MESSAGE]
@@ -4941,7 +5025,7 @@ The objects you own on the selected parcel of land have been returned back to yo
    name="OtherObjectsReturned"
    persist="true"
    type="notify">
-The objects on the selected parcel of land that is owned by [FIRST] [LAST] have been returned to his or her inventory.
+The objects on the selected parcel of land that is owned by [NAME] have been returned to his or her inventory.
   </notification>
 
   <notification
@@ -5606,7 +5690,7 @@ Grant this request?
    icon="notify.tga"
    name="ScriptDialog"
    type="notify">
-[FIRST] [LAST]&apos;s &apos;[TITLE]&apos;
+[NAME]&apos;s &apos;[TITLE]&apos;
 [MESSAGE]
     <form name="form">
       <button
@@ -5836,7 +5920,7 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
    name="AutoUnmuteByIM"
    persist="true"
    type="notify">
-[FIRST] [LAST] was sent an instant message and has been automatically unblocked.
+[NAME] was sent an instant message and has been automatically unblocked.
   </notification>
 
   <notification
@@ -5844,7 +5928,7 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
    name="AutoUnmuteByMoney"
    persist="true"
    type="notify">
-[FIRST] [LAST] was given money and has been automatically unblocked.
+[NAME] was given money and has been automatically unblocked.
   </notification>
 
   <notification
@@ -5852,7 +5936,7 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
    name="AutoUnmuteByInventory"
    persist="true"
    type="notify">
-[FIRST] [LAST] was offered inventory and has been automatically unblocked.
+[NAME] was offered inventory and has been automatically unblocked.
   </notification>
 
   <notification
diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
index 3416b2369d5f6da2a56f503b1ce78bca45a3b77a..72f41c62f4355a5653201655a558fdc59bbab979 100644
--- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
@@ -71,7 +71,7 @@
 		top="10"
 		left_pad="10"
 		height="14"
-		width="255"
+		width="250"
 		length="1"
 		follows="right|left"
 		use_ellipses="true"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
index 5072ec3a669df12e6d21d151cff22e8c95c1c1ed..399e91432feb9dbac3ea46c46d4d16f00bb23ea1 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
@@ -3,7 +3,7 @@
  background_visible="true"
  class="edit_profile_panel"
   follows="all"
- height="535"
+ height="548"
  label="Profile Edit"
  layout="topleft"
  left="0"
@@ -60,7 +60,7 @@
  <scroll_container
      color="DkGray2"
      follows="all"
-     height="494"
+     height="507"
      min_height="300"
      layout="topleft"
      left="8"
@@ -74,7 +74,7 @@
          follows="left|top|right"
          layout="topleft"
          top="0"
-     height="494"
+     height="507"
      min_height="300"
          left="0"
          width="292">
@@ -83,16 +83,45 @@
      follows="left|top|right"
          layout="topleft"
          top="0"
-     height="494"
+     height="507"
      min_height="300"
          left="0"
          width="292">
+      <text
+       follows="top|left"
+       font="SansSerifBigBold"
+       height="20"
+       layout="topleft"
+       left="10"
+       name="user_name"
+       text_color="white"
+       top="4"
+       value="Hamilton Hitchings"
+       width="280" />
+      <text
+       follows="top|left"
+       height="13"
+       layout="topleft"
+       left="10"
+       name="user_slid"
+       text_color="LtGray"
+       top_pad="5"
+       value="(hamilton.linden)"
+       width="150" />
+      <button
+       follows="top|left"
+       height="20"
+       label="Set Display Name..."
+       left="165"
+       name="set_name"
+       top_delta="-4"
+       width="120" />
      <panel
        name="lifes_images_panel"
          follows="left|top|right"
          height="244"
          layout="topleft"
-         top="0"
+         top="37"
          left="0"
          width="292">
 	 <panel
@@ -146,8 +175,8 @@
        height="102"
        layout="topleft"
        left="123"
-       top="25"
-       max_length="511"
+       top="62"
+       max_length="512"
        name="sl_description_edit"
        width="157"
        word_wrap="true">
@@ -202,8 +231,8 @@
        height="102"
        layout="topleft"
        left="123"
-       max_length="254"
-       top="157"
+       max_length="512"
+       top="195"
        name="fl_description_edit"
        width="157"
        word_wrap="true">
@@ -301,17 +330,17 @@
          left="10"
          name="partner_data_panel"
          width="200">
-            <name_box
-             follows="left|top|right"
-             height="30"
-             initial_value="(retrieving)"
-             layout="topleft"
-             left="0"
-             link="true"
-             name="partner_text"
-             top="0"
-             width="200"
-             word_wrap="true" />
+          <text
+           follows="left|top|right"
+           height="12"
+           initial_value="(retrieving)"
+           layout="topleft"
+           left="0"
+           link="true"
+           name="partner_text"
+           top="0"
+           use_ellipses="true"
+           width="280"/>
          </panel>
         <text
          follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml
index 2af1a84400fb82da7d45253e09fe0f34dbc1c01e..70b96ca5ebe588dece50065cec7af3a15d45fb32 100644
--- a/indra/newview/skins/default/xui/en/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_general.xml
@@ -33,7 +33,7 @@ Hover your mouse over the options for more help.
      height="110"
      label=""
      layout="topleft"
-     left="10"
+     left="5"
      name="insignia"
      no_commit_on_selection="true"
      tool_tip="Click to choose a picture"
@@ -49,22 +49,20 @@ Hover your mouse over the options for more help.
      type="string"
      height="16"
      length="1"
-     left_pad="10"
+     left_pad="8"
      name="prepend_founded_by"
      top_delta="0">
       Founder:
     </text>
-    <name_box
-     follows="left|top"
+     <text
+      follows="left|top"
      height="16"
-     initial_value="(retrieving)"
      layout="topleft"
-     left_delta="0"
-     link="true"
+     left_delta="-2"
      name="founder_name"
      top_pad="2"
      use_ellipses="true"
-     width="190" />
+     width="168" />
     <text
     font="SansSerifMedium"
     text_color="EmphasisColor"
@@ -92,13 +90,13 @@ Hover your mouse over the options for more help.
     <text_editor
      type="string"
      follows="left|top|right"
-     left="5"
+     left="3"
      height="80"
      layout="topleft"
      max_length="511"
      name="charter"
      top="105"
-     right="-1"
+     right="-4"
     bg_readonly_color="DkGray2"
     text_readonly_color="White"
      word_wrap="true">
@@ -113,6 +111,7 @@ Hover your mouse over the options for more help.
      layout="topleft"
      left="0"
      name="visible_members"
+     short_names="false" 
      top_pad="2">
         <name_list.columns
          label="Member"
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 4af4774304cbb6baf3e6215599967fd52f92ca97..074e9bf5e5813d041c9f2720a133d6ea3e1d1fd6 100644
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -85,6 +85,7 @@ clicking on their names.
              right="-1"
              multi_select="true"
              name="member_list"
+             short_names="false" 
              top_pad="5">
                 <name_list.columns
                  label="Member"
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
index 33a5e01e4c48f6c6f7f84c1e4bc80064abeb734b..a36f078f4fc519cf1647e51f835ce75729cde52e 100644
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -23,26 +23,16 @@
      orientation="vertical"
      top_pad="5"
      width="114">
-        <layout_panel
-         mouse_opaque="false"
-         auto_resize="true"
-         follows="top|left"
-         height="0"
-         layout="topleft"
-         left="2"
-         min_height="0"
-         width="109"
-         top="0"
-         name="spacer"
-         user_resize="false" />
         <layout_panel
          auto_resize="false"
          follows="top|left|right"
          height="20"
          layout="topleft"
+         left="2" 
          min_height="20"
          width="109"
          name="view_profile_btn_panel"
+         top="0" 
          user_resize="false">
             <button
              follows="left|top|right"
@@ -171,5 +161,15 @@
              name="voice_ctrls_btn"
              width="109" />
         </layout_panel>
+      <layout_panel
+       mouse_opaque="false"
+       auto_resize="true"
+       follows="top|left"
+       height="0"
+       layout="topleft"
+       min_height="0"
+       width="109"
+       name="spacer"
+       user_resize="false" />
     </layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml
index 34fd3352a345bbcda7a3c5b683930ddd44e81413..021cf00d0305a0b9a5f735bff831b04e82518f55 100644
--- a/indra/newview/skins/default/xui/en/panel_instant_message.xml
+++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml
@@ -67,7 +67,7 @@
          top="8"
          use_ellipses="true"
          value="Erica Vader"
-         width="212" />
+         width="205" />
 	 <!-- TIME STAMP -->
         <text
         font="SansSerifSmall"
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index a7e87f2a1ef9aef877bfb875dc0e5e09eda5ec23..8d43cc816c4c6ecbd36f78c7eb4765b724731568 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -3,7 +3,7 @@
    name="Landmarks"
    top="0"
    height="400"
-   layout="topleft"
+   layout="topleft" 
    left="0"
    width="313"
    help_topic="panel_landmarks"
@@ -88,7 +88,7 @@
         </accordion_tab>
     </accordion>
     <panel
-     background_visible="true"
+       background_visible="true"
      bevel_style="none"
      bottom="0"
      follows="left|right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 6b136495d2960b53149ff41b56a39d77fd7d47b9..020ce6333d15c9ca6cd47184f95baa9b9affe183 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -65,12 +65,13 @@ Username:
 <line_editor
 follows="left|bottom"
 height="22"
-label="Username"
+label="bobsmith12 or Steller Sunshine"
 left_delta="0"
-max_length="31"
+max_length="63"
 name="username_edit"
+prevalidate_callback="ascii" 
 select_on_focus="true"
-tool_tip="[SECOND_LIFE] Username"
+tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
 top_pad="0"
 width="150" />
 <text
@@ -159,8 +160,8 @@ width="135"
 tab_stop="false"
 follows="right|bottom"
 name="links"
-width="200"
-min_width="200"
+width="205"
+min_width="205"
 user_resize="false"
 height="80">
    <text
@@ -172,7 +173,7 @@ height="16"
 top="12"
 right="-10"
 name="create_new_account_text"
-  width="180">
+  width="200">
        Sign up
  </text>
 <text
@@ -184,8 +185,8 @@ height="16"
 name="forgot_password_text"
 top_pad="12"
 right="-10"
-  width="180">
-       Forgot your name or password?
+  width="200">
+       Forgot your username or password?
 </text>
 <text
 follows="right|bottom"
@@ -196,7 +197,7 @@ height="16"
 name="login_help"
 top_pad="2"
 right="-10"
-    width="180">
+    width="200">
        Need help logging in?   </text>
 <!--  <text
     follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml
index 4629bb9cfeb23333a5cde3f7fac20a806a359c6c..160d70e660e809f328f5528e8105e546c47bda4a 100644
--- a/indra/newview/skins/default/xui/en/panel_my_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml
@@ -284,7 +284,7 @@
              name="partner_data_panel"
              top_pad="0"
              width="300">
-              <name_box
+              <text
                follows="left|top"
                height="10"
                initial_value="(retrieving)"
@@ -293,8 +293,8 @@
                link="true"
                name="partner_text"
                top="0"
-           width="300"
-               word_wrap="true" />
+               use_ellipses="true" 
+           width="300" />
             </panel>
             <text
              follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index e6714af943a394ae853fa529574c5064096e5d8b..e05c1e4315c6b65092583767842a0b19089441c5 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -57,6 +57,7 @@
     <string
      name="replace_body_part"
      value="Click to replace your existing shape"/>
+  
 
     <button
      follows="top|left"
@@ -197,19 +198,19 @@ It is calculated as border_size + 2*UIResizeBarOverlap
                  user_resize="false"
                  visible="true">
 
-                    <!-- List containing items from the COF and Base outfit -->
-                    <panel
-                     background_visible="false"
-                     class="cof_wearables"
-                     filename="panel_cof_wearables.xml"
+            <!-- List containing items from the COF and Base outfit -->
+            <panel
+             background_visible="false"
+             class="cof_wearables"
+             filename="panel_cof_wearables.xml"
                      follows="all" 
                      height="129"
-                     layout="topleft"
-                     left="1"
-                     name="cof_wearables_list"
-                     top="0"
-                     width="311" />
-                    
+             layout="topleft"
+             left="1"
+             name="cof_wearables_list"
+             top="0"
+             width="311" />
+
                     <button
                      follows="left|bottom" 
                      height="22"
@@ -228,7 +229,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap
                     <combo_box
                      follows="left|right|bottom"
                      height="22"
-                     layout="topleft"
+             layout="topleft"
                      left_pad="5"
                      name="list_view_filter_combobox"
                      top_delta="0"
@@ -244,20 +245,20 @@ It is calculated as border_size + 2*UIResizeBarOverlap
                      visible="false"
                      width="152"/>
                     
-                    <button
+            <button
                      follows="bottom|right"
                      height="22"
-                     image_overlay="Search_Icon"
+             image_overlay="Search_Icon"
                      image_pressed="PushButton_Press"
                      image_pressed_selected="PushButton_Selected_Press"
                      image_selected="PushButton_Selected_Press"
-                     is_toggle="true"
-                     layout="topleft"
-                     name="filter_button"
+             is_toggle="true"
+             layout="topleft"
+             name="filter_button"
                      right="-5"
-                     top_delta="0"
+             top_delta="0"
                      visible="false"
-                     width="20" />
+             width="20" />
                 </layout_panel>
 
                 <layout_panel
@@ -286,13 +287,13 @@ It is calculated as border_size + 2*UIResizeBarOverlap
                     
                 </layout_panel>
             </layout_stack>
-        </layout_panel>
+                </layout_panel>
 
 
-        <layout_panel
+                <layout_panel
          background_visible="false"
          bg_alpha_color="DkGray2"
-         auto_resize="true"
+                 auto_resize="true"
          default_tab_group="3"
          height="450"
          min_height="73"
@@ -312,44 +313,44 @@ It is calculated as border_size + 2*UIResizeBarOverlap
              top_pad="-9"
              width="313" />
 
-            <inventory_panel
-             allow_multi_select="true"
-             background_visible="false"
-             border="false"
-             follows="left|top|right|bottom"
+                    <inventory_panel
+		             allow_multi_select="true"
+		             background_visible="false"
+		             border="false"
+		             follows="left|top|right|bottom"
              height="418"
-             layout="topleft"
-             left="0"
-             mouse_opaque="false"
+		             layout="topleft"
+		             left="0"
+		             mouse_opaque="false"
              name="folder_view"
              top_pad="0"
              width="313"
-             visible="false"/>
-            <panel
-             name="filtered_wearables_panel"
-             background_opaque="true"
-             background_visible="false"
-             layout="topleft"
-             follows="left|top|right|bottom"
-             border="false"
+		             visible="false"/>
+		            <panel
+		             name="filtered_wearables_panel"
+		             background_opaque="true"
+		             background_visible="false"
+		             layout="topleft"
+		             follows="left|top|right|bottom"
+		             border="false"
              height="418"
-             left="0"
-             mouse_opaque="false"
+		             left="0"
+		             mouse_opaque="false"
              width="310"
-             top_delta="0"
-             visible="true">
-                <wearable_items_list
-                 color="0.107 0.107 0.107 1"
+		             top_delta="0"
+		             visible="true">
+		             <wearable_items_list
+		              color="0.107 0.107 0.107 1"
                  name="list_view"
-                 allow_select="true"
-                 layout="topleft"
-                 follows="all"
-                 multi_select="true"
+		              allow_select="true"
+		              layout="topleft"
+		              follows="all"
+		              multi_select="true"
                  width="313"
                  height="418"
-                 left="0"
-                 top="0"/>
-            </panel>
+		              left="0"
+		              top="0"/>
+		            </panel>
             <button
 	         follows="bottom|left"
 	         height="22"
@@ -360,7 +361,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap
 	         top_pad="5"
 	         width="130" />
 
-        </layout_panel>
+       </layout_panel>
     </layout_stack>
 
 
@@ -461,15 +462,15 @@ It is calculated as border_size + 2*UIResizeBarOverlap
          name="list_view_btn"
          top="1"
          width="31" />
-        <icon
-         follows="bottom|left|right"
-         height="25"
+       <icon
+        follows="bottom|left|right"
+        height="25"
          image_name="Toolbar_Middle_Off"
-         layout="topleft"
-         left_pad="1"
+        layout="topleft"
+        left_pad="1"
          name="dummy_right_icon"
          width="186" >
-        </icon>
+       </icon>
         <button
          follows="bottom|right"
          height="25"
@@ -484,7 +485,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap
          tool_tip="Visit the SL Marketplace. You can also select something you are wearing, then click here to see more things like it"
          width="31" />
     </panel>
-    
+
     <!-- SAVE AND REVERT BUTTONS -->
     <panel
      follows="left|right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 7cd0d5b5f04a5c50ec08f43cadffb8ea50df86db..1353d401c37e7566040d578635e7229f5e277e5a 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -81,7 +81,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
      width="317">
      	<panel
          background_opaque="true"
-         background_visible="true"
+       background_visible="true"
          bg_alpha_color="DkGray"
          bg_opaque_color="DkGray"
          follows="all"
@@ -155,7 +155,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
         </panel>
         <panel
          background_opaque="true"
-         background_visible="true"
+       background_visible="true"
          bg_alpha_color="DkGray"
          bg_opaque_color="DkGray"
          follows="all"
@@ -280,7 +280,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
         </panel>
         <panel
          background_opaque="true"
-         background_visible="true"
+       background_visible="true"
          bg_alpha_color="DkGray"
          bg_opaque_color="DkGray"
          follows="all"
@@ -365,7 +365,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
         </panel>
         <panel
          background_opaque="true"
-         background_visible="true"
+       background_visible="true"
          bg_alpha_color="DkGray"
          bg_opaque_color="DkGray"
          follows="all"
diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml
index c6e93af50a35c1ecd063e98d73a61538375d4e87..cd63d63737e670846baa59a28d816ea002634c80 100644
--- a/indra/newview/skins/default/xui/en/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -315,7 +315,8 @@
              name="owner_value"
              top_delta="0"
              value="Alex Superduperlongenamenton"
-             width="205" />
+             use_ellipses="true" 
+             width="200" />
             <icon
              follows="top|left"
              height="16"
@@ -649,7 +650,8 @@
                          left_pad="0"
                          name="region_owner"
                          top_delta="0"
-                         value="moose Van Moose"
+                         value="moose Van Moose extra long name moose"
+                         use_ellipses="true" 
                          width="187" />
                         <text
                          follows="left|top"
@@ -710,7 +712,7 @@
                          name="estate_name_label"
                          top_pad="5"
                          value="Estate:"
-                         width="90" />
+                         width="80" />
                         <text
                          follows="left|top|right"
                          height="15"
@@ -727,7 +729,7 @@
                          name="estate_rating_label"
                          top_pad="5"
                          value="Rating:"
-                         width="90" />
+                         width="80" />
                         <text
                          follows="left|top|right"
                          height="15"
@@ -744,15 +746,17 @@
                          name="estate_owner_label"
                          top_pad="5"
                          value="Owner:"
-                         width="90" />
+                         width="80" />
                         <text
                          follows="left|top|right"
                          height="15"
                          layout="topleft"
                          left_pad="0"
                          name="estate_owner"
+                         value="Testing owner name length with long name" 
                          top_delta="0"
-                         width="187" />
+                         use_ellipses="true" 
+                         width="190" />
                         <text
                          follows="left|top"
                          height="15"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 31d8ea27d98c65ec993177413172f4cad0e4e253..7d9bd1bf2aafc336bd157341b77a2035c2778299 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -125,6 +125,7 @@ Automatic position for:
      left_pad="30"
      name="first_person_avatar_visible"
      width="256" />
+   
     <check_box
      control_name="ArrowKeysAlwaysMove"
      follows="left|top"
@@ -206,7 +207,7 @@ Automatic position for:
    left="80"
    name="UI Size:"
    top_pad="25"
-   width="160">
+   width="300">
     UI size
   </text>
   <slider
@@ -302,6 +303,7 @@ Automatic position for:
      halign="center"
      height="23"
      image_overlay="Refresh_Off"
+   layout="topleft" 
      tool_tip="Reset to Middle Mouse Button"
      mouse_opaque="true"
      name="set_voice_middlemouse_button"
@@ -315,7 +317,7 @@ Automatic position for:
  label="Other Devices"
  left="30"
  name="joystick_setup_button"
- top="27"
+ top_pad="27"
  width="155">
     <button.commit_callback
      function="Floater.Show"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index a69e8d29b0a8807a7c19190d9827558c70cfa861..2cf4118e198c417394d664f0188d8abac6cadd82 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -222,28 +222,27 @@
    </text>
    <radio_group
      control_name="AvatarNameTagMode"
-     height="20"
+     height="45"
      layout="topleft"
      left="50"
      name="Name_Tag_Preference">
         <radio_item
          label="Off"
-         layout="topleft"
          name="radio"
          value="0"
          width="75" />
         <radio_item
          label="On"
-         layout="topleft"
-         left_pad="12"
+         left_delta="0"
          name="radio2"
+		 top_pad="5"
          value="1"
          width="75" />
         <radio_item
          label="Show briefly"
-         layout="topleft"
-         left_pad="12"
+         left_delta="0"
          name="radio3"
+		 top_pad="5"
          value="2"
          width="160" />
     </radio_group>
@@ -253,18 +252,58 @@
      height="16"
      label="Show my name"
      layout="topleft"
-     left="50"
+     left="70"
      name="show_my_name_checkbox1"
+	 top_pad="4"
      width="300" />
    <check_box
+    control_name="NameTagShowFriends"
 	 enabled_control="AvatarNameTagMode"
-     control_name="RenderShowGroupTitleAll"
      height="16"
-     label="Show group titles"
+    label="Highlight friends"
+    left_delta="0"
+    name="show_friends"
+    tool_tip="Highlight the name tags of your friends"
+    top_pad="2" />
+  <text
+    follows="left|top"
+    height="15"
      layout="topleft"
-     left_delta="175"
+    left="250"
+    name="name_tags_textbox"
+    top="175"
+    width="200">
+       Tags show:
+   </text>
+    <check_box
+     control_name="NameTagShowGroupTitles"
+	 enabled_control="AvatarNameTagMode"
+     height="16"
+     label="Group titles"
+     left="265"
      name="show_all_title_checkbox1"
-     width="200" />
+	 tool_tip="Show group titles, like Officer or Member"
+     top_pad="5" />
+  <!--
+   <check_box
+     control_name="NameTagShowDisplayNames"
+	 enabled_control="AvatarNameTagMode"
+     height="16"
+     label="Display names"
+     left_delta="0"
+     name="show_display_names"
+	 tool_tip="Show display names, like José Sanchez"
+     top_pad="5" />
+     -->
+   <check_box
+     control_name="NameTagShowUsernames"
+	 enabled_control="AvatarNameTagMode"
+     height="16"
+     label="Usernames"
+     left_delta="0"
+     name="show_slids"
+     tool_tip="Show username, like bobsmith123"
+     top_pad="2" />
     <text
      type="string"
      length="1"
@@ -273,7 +312,7 @@
      layout="topleft"
      left="30"
      name="effects_color_textbox"
-     top_pad="15"
+     top="290"
      width="200">
         My effects:
     </text>
@@ -285,6 +324,7 @@
       layout="topleft"
       left_pad="5"
       name="title_afk_text"
+      top_delta="0" 
       width="190">
     Away timeout:
     </text>
@@ -353,8 +393,8 @@
       bg_writeable_color="LtGray"
       use_ellipses="false"
      commit_on_focus_lost = "true"
-     follows="left|top|right"
-     height="60"
+     follows="left|top"
+     height="42"
      layout="topleft"
      left="50"
      name="busy_response"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index 2c6ceeef2e3df40ce5fa80c5c2602f2b5d876e83..8814bcab77eb9c335564260013b714410d953fbb 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -115,7 +115,7 @@
    layout="topleft"
    left="77"
    name="connection_port_enabled"
-   top_pad="20"
+   top_pad="15"
    width="256">
     <check_box.commit_callback
      function="Notification.Show"
@@ -147,7 +147,7 @@
    left="80"
    mouse_opaque="false"
    name="cache_size_label_l"
-   top_pad="20"
+   top_pad="10"
    width="200">
     Cache size
   </text>
@@ -375,4 +375,27 @@
    name="web_proxy_port"
    top_delta="0"
    width="145" />
+  <text
+       type="string"
+       length="1"
+       follows="left|top"
+       height="10"
+       layout="topleft"
+       left="30"
+       name="Communications:"
+       top_pad="5"
+       width="300">
+    Communications:
+  </text>
+  <check_box
+control_name="UseDisplayNames"
+follows="top|left"
+height="15"
+label="View Display Names"
+layout="topleft"
+left_delta="50"
+name="display_names_check"
+width="237"
+tool_tip="Check to use display names in chat, IM, name tags, etc."
+top_pad="10"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
index e41b80baf274cdbbc2e99a94dde901eb0c590f5d..5a2bb2e965db832fc8f591f718745f8525cb467d 100644
--- a/indra/newview/skins/default/xui/en/panel_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -263,7 +263,7 @@
              name="partner_data_panel"
              top_pad="0"
              width="300">
-              <name_box
+              <text
                follows="left|top"
                height="10"
                initial_value="(retrieving)"
@@ -272,8 +272,8 @@
                link="true"
                name="partner_text"
                top="0"
-           width="300"
-               word_wrap="true" />
+               use_ellipses="true"
+           width="300" />
             </panel>
             <text
              follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml
index d9030fc0d61196878087efaa8f2e99ede47cb077..5778d3cb6f875b4bb6d1d1dac15b4fb97105ea75 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml
@@ -28,17 +28,30 @@
      tab_stop="false"
      top="2"
      width="30" />
-    <text_editor
+     <text
     	h_pad="0"
     	v_pad="0"
-      allow_scroll="false"
-      bg_visible="false"
-      read_only = "true"
       follows="top|left|right"
-      font="SansSerifHugeBold"
-      height="26"
+      font="SansSerifBigBold"
+      height="29"
       layout="topleft"
       left_pad="5"
+      name="user_name_small"
+      text_color="LtGray"
+      top="0"
+      value="(Loading...)"
+      use_ellipses="true"
+      word_wrap="true" 
+      visible="false" 
+      width="275" />
+     <text
+      h_pad="0"
+      v_pad="0"
+      follows="top|left|right"
+      font="SansSerifHugeBold"
+      height="27"
+      layout="topleft"
+      left_delta="0"
       name="user_name"
       text_color="LtGray"
       top="2"
@@ -50,13 +63,23 @@
      height="13"
      layout="topleft"
      left="45"
+     name="user_slid"
+     text_color="LtGray"
+     width="150" />
+    <text
+     follows="top|left"
+     halign="right" 
+     height="13"
+     layout="topleft"
+     left="150"
      name="status"
      text_color="LtGray_50"
+     top_delta="0" 
      value="Online"
      width="150" />
     <tab_container
      follows="all"
-     height="538"
+     height="537"
      halign="center"
      layout="topleft"
      left="5"
@@ -66,7 +89,7 @@
      tab_height="30"
      tab_position="top"
      top_pad="5"
-     width="317">
+     width="317"> 
         <panel
          class="panel_profile"
          filename="panel_profile.xml"
diff --git a/indra/newview/skins/default/xui/en/panel_region_debug.xml b/indra/newview/skins/default/xui/en/panel_region_debug.xml
index a6b4ddd01e8c5471b67e0c255da8d0778c4a04ce..15df095efa49b87bc19e8ab7a2876cee8f20b496 100644
--- a/indra/newview/skins/default/xui/en/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_debug.xml
@@ -103,7 +103,7 @@
      mouse_opaque="false"
      name="target_avatar_name"
      top_delta="-2"
-     width="180">
+     width="270">
         (none)
     </line_editor>
     <button
diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml
index 08e36d5e57a3eb8be1464272b1a125f74ec99b59..1307d807e20a9762a96e8bf5a1d50eaa514eef43 100644
--- a/indra/newview/skins/default/xui/en/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml
@@ -72,7 +72,8 @@
      left_delta="0"
      name="estate_owner"
      top_delta="16"
-     width="150">
+     use_ellipses="true"
+     width="290">
         (unknown)
     </text>
     <view_border
diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
index 49b252174cfb7711331a963392112b2a438fb57e..8121fbdc4844ce46c2b69802927789b7b311dc69 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
@@ -164,8 +164,9 @@
      layout="topleft"
      left_pad="5"
 		     name="LabelCreatorName"
-		     top_delta="6"
-		     width="140">
+       top_delta="6"
+       use_ellipses="true"
+       width="180">
       </text>
       <button
       follows="top|right"
@@ -207,7 +208,8 @@
         left_pad="5"
       name="LabelOwnerName"
       top_delta="6"
-      width="140">
+       use_ellipses="true"
+			 width="180">
       </text>
 	     <button
 			 follows="top|right"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
index 843015cb8bc546314e050657344a74313c8433f5..5da449de3defe1ccde2293ed34db81b3523b999d 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
@@ -167,7 +167,7 @@
      left_pad="0"
              name="Creator Name"
 		     top_delta="0"
-		     width="140">
+		     width="225">
 	        Erica Linden
 	     </text>
 	    <text
@@ -191,7 +191,7 @@
 			    left_pad="0"
 			    name="Owner Name"
 			    top_delta="0"
-			    width="140">
+			    width="225">
 			    Erica Linden
 	     </text>
 	    	    <text
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index cf040b10c7a5add2a8bfc9759c51e6a53d5a6da1..c96b99103418cc2e426fc8d07a62108f0aa836fd 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -89,6 +89,7 @@
 	<string name="TooltipHttpUrl">Click to view this web page</string>
 	<string name="TooltipSLURL">Click to view this location's information</string>
 	<string name="TooltipAgentUrl">Click to view this Resident's profile</string>
+  <string name="TooltipAgentInspect">Learn more about this Resident</string>
 	<string name="TooltipAgentMute">Click to mute this Resident</string>
 	<string name="TooltipAgentUnmute">Click to unmute this Resident</string>
 	<string name="TooltipAgentIM">Click to IM this Resident</string>
@@ -3043,7 +3044,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
     You are the only user in this session.
   </string>
   <string name="offline_message">
-    [FIRST] [LAST] is offline.
+    [NAME] is offline.
   </string>
   <string name="invite_message">
     Click the [BUTTON NAME] button to accept/connect to this voice chat.
@@ -3129,17 +3130,20 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <string name="voice_morphing_url">http://secondlife.com/landing/voicemorphing</string>
 
   <!-- Financial operations strings -->
-  <string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT]</string>
+  <string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT] [REASON].</string>
+  <string name="paid_you_ldollars_no_reason">[NAME] paid you L$[AMOUNT].</string>
   <string name="you_paid_ldollars">You paid [NAME] L$[AMOUNT] [REASON].</string>
   <string name="you_paid_ldollars_no_info">You paid L$[AMOUNT].</string>
   <string name="you_paid_ldollars_no_reason">You paid [NAME] L$[AMOUNT].</string>
   <string name="you_paid_ldollars_no_name">You paid L$[AMOUNT] [REASON].</string>
+  <string name="for item">for [ITEM]</string>
   <string name="for a parcel of land">for a parcel of land</string>
   <string name="for a land access pass">for a land access pass</string>
   <string name="for deeding land">for deeding land</string>
   <string name="to create a group">to create a group</string>
   <string name="to join a group">to join a group</string>
   <string name="to upload">to upload</string>
+  <string name="to publish a classified ad">to publish a classified ad</string>
   
   <string name="giving">Giving L$ [AMOUNT]</string>
   <string name="uploading_costs">Uploading costs L$ [AMOUNT]</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/inspector.xml b/indra/newview/skins/default/xui/en/widgets/inspector.xml
index 428b2ce03b0427c1245722f973db79c64cb26bf0..8c171c387f7badb381fcd8baa8aa49693fd9818f 100644
--- a/indra/newview/skins/default/xui/en/widgets/inspector.xml
+++ b/indra/newview/skins/default/xui/en/widgets/inspector.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <inspector name="inspector"
+           max_width="300"
            bg_opaque_color="DkGray_66"
            background_visible="true"
            bg_opaque_image="Inspector_Hover"
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index e9eda790dd9dda9e1c8c645b6b9fd92f8359a917..3a4ff8a81fb305994d4f5dab463036e902365b44 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -1419,7 +1419,7 @@ Esta actualización no es obligatoria, pero te sugerimos instalarla para mejorar
 	</notification>
 	<notification name="BusyModeSet">
 		Pasar al modo ocupado.
-Se ocultará el chat y los mensajes instantáneos (éstos recibirán tu Respuesta en el modo ocupado). Se rehusarán todos los ofrecimientos de teleporte. Todas las ofertas de inventario irán a tu Papelera.
+Se ocultará el chat y los mensajes instantáneos   (éstos recibirán tu Respuesta en el modo ocupado). Se rehusarán todos los ofrecimientos de teleporte. Todas las ofertas de inventario irán a tu Papelera.
 		<usetemplate ignoretext="Cambio mi estado al modo ocupado" name="okignore" yestext="OK"/>
 	</notification>
 	<notification name="JoinedTooManyGroupsMember">
@@ -1886,7 +1886,7 @@ Linden Lab
 		</form>
 	</notification>
 	<notification name="ConfirmDeleteProtectedCategory">
-		La carpeta &apos;[FOLDERNAME]&apos; pertenece al sistema, y borrar carpetas del sistema puede provocar inestabilidad.  ¿Estás seguro de que quieres borrarla?
+		La carpeta &apos;[FOLDERNAME]&apos; pertenece al sistema,   y borrar carpetas del sistema puede provocar inestabilidad.  ¿Estás seguro de que quieres borrarla?
 		<usetemplate ignoretext="Confirmar antes de borrar una carpeta del sistema" name="okcancelignore" notext="Cancelar" yestext="OK"/>
 	</notification>
 	<notification name="ConfirmEmptyTrash">
@@ -2445,7 +2445,7 @@ Esto añadirá un marcador en tu inventario para que puedas enviarle rápidament
 Si permaneces en esta región serás desconectado.
 	</notification>
 	<notification name="RegionRestartSeconds">
-		Esta región se reiniciará en [SECONDS] segundos.
+		Esta región se reiniciará en  [SECONDS] segundos.
 Si permaneces en esta región serás desconectado.
 	</notification>
 	<notification name="LoadWebPage">
@@ -2509,7 +2509,7 @@ Si no confias en este objeto y en su creador, deberías rehusar esta petición.
 	<notification name="BuyLindenDollarSuccess">
 		¡Gracias por tu pago!
 
-Tu saldo de L$ se actualizará cuando se complete el proceso. Si el proceso tarda más de 20 minutos, se cancelará tu transacción, y la cantidad se cargará en tu saldo de US$.
+Tu saldo de L$ se actualizará cuando se complete el proceso. Si el proceso tarda más de 20 minutos, se cancelará tu transacción,    y la cantidad se cargará en tu saldo de US$.
 
 Puedes revisar el estado de tu pago en el Historial de transacciones de tu [http://secondlife.com/account/ Panel de Control]
 	</notification>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index 259ac4cee638b39767afc9b8a900c8a43e98ac63..73a94e2b1a437795c71fb313d2b214371278d503 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -178,7 +178,7 @@ Voulez-vous continuer ?
 	<notification name="JoinGroupNoCost">
 		Vous vous apprêtez à rejoindre le groupe [NAME].
 Voulez-vous continuer ?
-		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="Rejoindre"/>
+		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="Fusionner"/>
 	</notification>
 	<notification name="JoinGroupCannotAfford">
 		Rejoindre ce groupe coûte [COST] L$.
diff --git a/indra/newview/skins/default/xui/ja/panel_group_land_money.xml b/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
index 4b3a7f880b70620cdeba726ab4af166074eedc3a..016dc97ab6eed5fee3c39659db4eff1f9cc52374 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
@@ -48,7 +48,7 @@
 			あなたの貢献:
 		</text>
 		<text name="your_contribution_units">
-			m²
+			平方メートル
 		</text>
 		<text name="your_contribution_max_value">
 			(最大 [AMOUNT])
diff --git a/indra/newview/skins/default/xui/ja/panel_group_roles.xml b/indra/newview/skins/default/xui/ja/panel_group_roles.xml
index be203b07615d1fff49db6b9bfdcbc276e5826bd4..d40dedf5669101f4f4a7aa7ec776c209fcbd13a8 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_roles.xml
@@ -20,7 +20,7 @@ Ctrl キーを押しながらメンバー名をクリックすると
 			<name_list name="member_list">
 				<name_list.columns label="メンバー" name="name"/>
 				<name_list.columns label="寄付" name="donated"/>
-				<name_list.columns label="ログイン" name="online"/>
+				<name_list.columns label="ステータス" name="online"/>
 			</name_list>
 			<button label="招待" name="member_invite"/>
 			<button label="追放" name="member_eject"/>
@@ -47,7 +47,7 @@ Ctrl キーを押しながらメンバー名をクリックすると
 			<filter_editor label="役割を選別" name="filter_input"/>
 			<scroll_list name="role_list">
 				<scroll_list.columns label="役割" name="name"/>
-				<scroll_list.columns label="タイトル" name="title"/>
+				<scroll_list.columns label="肩書き" name="title"/>
 				<scroll_list.columns label="#" name="members"/>
 			</scroll_list>
 			<button label="新しい役割" name="role_create"/>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 4bf2bda248f2c39bbcc2b99630a18f31bfac22b8..8752e6f43d91f0a9de55b5bb098402d508db564a 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -1385,10 +1385,10 @@
 		Script não encontrado no servidor.
 	</string>
 	<string name="CompileQueueProblemDownloading">
-		Problema no download
+		Problema no  download
 	</string>
 	<string name="CompileQueueInsufficientPermDownload">
-		Permissões insuficientes para fazer o download do script.
+		Permissões insuficientes para  fazer o download do script.
 	</string>
 	<string name="CompileQueueInsufficientPermFor">
 		Permissões insuficientes para
@@ -1702,7 +1702,7 @@
 		(vai atualizar depois de publicado)
 	</string>
 	<string name="NoPicksClassifiedsText">
-		Você não criou nenhum Destaque ou Anúncio. Clique no botão &quot;+&quot; para criar um Destaque ou Anúncio.
+		Você não criou nenhum Destaque ou Anúncio.  Clique no botão &quot;+&quot; para criar um Destaque ou Anúncio.
 	</string>
 	<string name="NoAvatarPicksClassifiedsText">
 		O usuário não tem nenhum destaque ou anúncio
diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp
index 99b346cff88d0d480fc2d8c532ebd5ec36eec1e3..47353962e1de9549015dee0d498e39b14b9e5b54 100644
--- a/indra/newview/tests/lldateutil_test.cpp
+++ b/indra/newview/tests/lldateutil_test.cpp
@@ -183,4 +183,14 @@ namespace tut
 			LLDateUtil::ageFromDate("12/13/2009", now),
 			"3 weeks old" );
 	}
+
+	//template<> template<>
+	//void dateutil_object_t::test<6>()
+	//{
+	//	set_test_name("ISO dates");
+	//	LLDate now(std::string("2010-01-04T12:00:00Z"));
+	//	ensure_equals("days",
+	//		LLDateUtil::ageFromDateISO("2009-12-13", now),
+	//		"3 weeks old" );
+	//}
 }
diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp
index 95d0421273acdddaf612613e19ec5cb8aff3c035..58bf371a042de9b3cf0a7e1a42c67f73db516466 100644
--- a/indra/viewer_components/login/tests/lllogin_test.cpp
+++ b/indra/viewer_components/login/tests/lllogin_test.cpp
@@ -6,7 +6,7 @@
  * 
  * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2009-2010, Linden Research, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index d4f791c202b655e53139c80a6c3689dd1e914d43..77dc940335cd13bad1a72b4ef61500cfebacf8ae 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -6812,6 +6812,19 @@ version 2.0
 		{	SquareMetersCommitted	S32	}
 		{	Description			Variable 1	}	// string
 	}
+	// For replies that are part of a transaction (buying something) provide
+	// metadata for localization.  If TransactionType is 0, the message is
+	// purely a balance update.  Added for server 1.40 and viewer 2.1.  JC
+	{
+		TransactionInfo		Single
+		{	TransactionType			S32			}	// lltransactiontype.h
+		{	SourceID				LLUUID		}
+		{	IsSourceGroup			BOOL		}
+		{	DestID					LLUUID		}
+		{	IsDestGroup				BOOL		}
+		{	Amount					S32			}
+		{	ItemDescription			Variable 1	}	// string
+	}
 }
 
 
@@ -6838,6 +6851,17 @@ version 2.0
 		{	SquareMetersCommitted	S32	}
 		{	Description			Variable 1	}	// string
 	}
+	// See MoneyBalanceReply above.
+	{
+		TransactionInfo		Single
+		{	TransactionType			S32			}	// lltransactiontype.h
+		{	SourceID				LLUUID		}
+		{	IsSourceGroup			BOOL		}
+		{	DestID					LLUUID		}
+		{	IsDestGroup				BOOL		}
+		{	Amount					S32			}
+		{	ItemDescription			Variable 1	}	// string
+	}
 }
 
 
@@ -8972,5 +8996,7 @@ version 2.0
 		{	InvType			S8	}
 		{	Name			Variable	1	}
 		{	Description		Variable	1	}
+
 	}
 }
+