diff -r b532610841b5 .hgtags
--- a/.hgtags	Thu Sep 02 11:27:52 2010 +0100
+++ b/.hgtags	Sun Sep 05 10:36:55 2010 +0100
@@ -22,4 +22,3 @@
 d2382d374139850efa5bb6adfb229e3e656cfc40 howard-demo
 d40ac9dd949cba6dab1cc386da6a2027690c2519 alpha-5
 d6781e22543acd7e21b967209f3c6e7003d380e3 fork to viewer-2-0
-c6e6324f5be1401f077ad18a4a0f6b46451c2f7b last_sprint
diff -r b532610841b5 build.sh
--- a/build.sh	Thu Sep 02 11:27:52 2010 +0100
+++ b/build.sh	Sun Sep 05 10:36:55 2010 +0100
@@ -59,6 +59,7 @@
     -t $variant \
     -G "$cmake_generator" \
    configure \
+	-DGRID:STRING="$viewer_grid" \
     -DVIEWER_CHANNEL:STRING="$viewer_channel" \
     -DVIEWER_LOGIN_CHANNEL:STRING="$login_channel" \
     -DINSTALL_PROPRIETARY:BOOL=ON \
diff -r b532610841b5 etc/message.xml
--- a/etc/message.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/etc/message.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/cmake/run_build_test.py
--- a/indra/cmake/run_build_test.py	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/cmake/run_build_test.py	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/lib/python/indra/__init__.py
--- a/indra/lib/python/indra/__init__.py	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/lib/python/indra/__init__.py	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/llcommon/CMakeLists.txt
--- a/indra/llcommon/CMakeLists.txt	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llcommon/CMakeLists.txt	Sun Sep 05 10:36:55 2010 +0100
@@ -33,6 +33,7 @@
     llapp.cpp
     llapr.cpp
     llassettype.cpp
+    llavatarname.cpp
     llbase32.cpp
     llbase64.cpp
     llcommon.cpp
@@ -115,6 +116,7 @@
     llallocator.h
     llallocator_heap_profile.h
     llagentconstants.h
+    llavatarname.h
     llapp.h
     llapr.h
     llassettype.h
diff -r b532610841b5 indra/llcommon/llavatarname.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/indra/llcommon/llavatarname.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -0,0 +1,113 @@
+/** 
+ * @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=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/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 -r b532610841b5 indra/llcommon/llavatarname.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/indra/llcommon/llavatarname.h	Sun Sep 05 10:36:55 2010 +0100
@@ -0,0 +1,95 @@
+/** 
+ * @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=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/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 -r b532610841b5 indra/llcommon/llchat.h
--- a/indra/llcommon/llchat.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llcommon/llchat.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 class LLChat
 {
 public:
-	LLChat(const std::string& text = LLStringUtil::null)
+	LLChat(const std::string& text = std::string())
 	:	mText(text),
 		mFromName(),
 		mFromID(),
diff -r b532610841b5 indra/llcommon/llstring.cpp
--- a/indra/llcommon/llstring.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llcommon/llstring.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -731,14 +731,17 @@
 
 	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 -r b532610841b5 indra/llinventory/lltransactionflags.cpp
--- a/indra/llinventory/lltransactionflags.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llinventory/lltransactionflags.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -108,6 +108,9 @@
 	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 @@
 		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 -r b532610841b5 indra/llmessage/CMakeLists.txt
--- a/indra/llmessage/CMakeLists.txt	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llmessage/CMakeLists.txt	Sun Sep 05 10:36:55 2010 +0100
@@ -25,6 +25,7 @@
     llares.cpp
     llareslistener.cpp
     llassetstorage.cpp
+    llavatarnamecache.cpp
     llblowfishcipher.cpp
     llbuffer.cpp
     llbufferstream.cpp
@@ -110,6 +111,7 @@
     llares.h
     llareslistener.h
     llassetstorage.h
+    llavatarnamecache.h
     llblowfishcipher.h
     llbuffer.h
     llbufferstream.h
@@ -248,6 +250,7 @@
     "${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 -r b532610841b5 indra/llmessage/llavatarnamecache.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/indra/llmessage/llavatarnamecache.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -0,0 +1,812 @@
+/** 
+ * @file llavatarnamecache.cpp
+ * @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
+ * ("James Cook") from avatar UUIDs.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/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 -r b532610841b5 indra/llmessage/llavatarnamecache.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/indra/llmessage/llavatarnamecache.h	Sun Sep 05 10:36:55 2010 +0100
@@ -0,0 +1,98 @@
+/** 
+ * @file llavatarnamecache.h
+ * @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
+ * ("James Cook") from avatar UUIDs.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/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 -r b532610841b5 indra/llmessage/llcachename.cpp
--- a/indra/llmessage/llcachename.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llmessage/llcachename.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -69,6 +69,8 @@
 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 @@
 
 	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 @@
 	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 @@
 		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 @@
 		// 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 @@
 }
 
 
-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 @@
 		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 @@
 	{
 		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 @@
 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::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 @@
 	}
 }
 
+//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 @@
 //  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 @@
 	{
 		LLCacheNameSignal signal;
 		signal.connect(callback);
-		signal(id, sCacheName["nobody"], "", is_group);
+		signal(id, sCacheName["nobody"], is_group);
 		return res;
 	}
 
@@ -600,11 +578,13 @@
 		// 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 @@
 	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(id, is_group, boost::bind(callback, _1, _2, _3, _4, user_data));
+	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, user_data));
 }
 
 void LLCacheName::processPending()
@@ -700,7 +686,7 @@
 		{
 			llinfos
 				<< iter->first << " = "
-				<< entry->mFirstName << " " << entry->mLastName
+				<< buildFullName(entry->mFirstName, entry->mLastName)
 				<< " @ " << entry->mCreateTime
 				<< llendl;
 		}
@@ -719,12 +705,24 @@
 			<< 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 @@
 
 		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 @@
 
 		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 @@
 {
 	((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
 }
-
diff -r b532610841b5 indra/llmessage/llcachename.h
--- a/indra/llmessage/llcachename.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llmessage/llcachename.h	Sun Sep 05 10:36:55 2010 +0100
@@ -36,13 +36,12 @@
 
 
 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 @@
 
 	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 @@
 	// 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 @@
 	// 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 -r b532610841b5 indra/llmessage/mean_collision_data.h
--- a/indra/llmessage/mean_collision_data.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llmessage/mean_collision_data.h	Sun Sep 05 10:36:55 2010 +0100
@@ -55,7 +55,7 @@
 	
 	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 @@
 	time_t mTime;
 	EMeanCollisionType mType;
 	F32	   mMag;
-	std::string mFirstName;
-	std::string mLastName;
+	std::string mFullName;
 };
 
 
diff -r b532610841b5 indra/llmessage/tests/llavatarnamecache_test.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/indra/llmessage/tests/llavatarnamecache_test.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -0,0 +1,102 @@
+/**
+ * @file llavatarnamecache_test.cpp
+ * @author James Cook
+ * @brief LLAvatarNameCache test cases.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/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 -r b532610841b5 indra/llui/llcombobox.cpp
--- a/indra/llui/llcombobox.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llcombobox.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 		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 -r b532610841b5 indra/llui/llcombobox.h
--- a/indra/llui/llcombobox.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llcombobox.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 -r b532610841b5 indra/llui/llnotifications.cpp
--- a/indra/llui/llnotifications.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llnotifications.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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)
 {
-	mName = first + " " + last;
+	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));
+	}
+}
 
-	LLStringUtil::trim(mName);
-	if (mName.empty())
+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)
+{
+	std::string name = av_name.getCompleteName();
+
+	// 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 -r b532610841b5 indra/llui/llnotifications.h
--- a/indra/llui/llnotifications.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llnotifications.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	{
 		// 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 -r b532610841b5 indra/llui/llstyle.cpp
--- a/indra/llui/llstyle.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llstyle.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -40,7 +40,8 @@
 	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 @@
 	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 @@
 
 BOOL LLStyle::isLink() const
 {
-	return mLink.size();
+	return mIsLink;
 }
 
 BOOL LLStyle::isVisible() const
diff -r b532610841b5 indra/llui/llstyle.h
--- a/indra/llui/llstyle.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llstyle.h	Sun Sep 05 10:36:55 2010 +0100
@@ -46,6 +46,7 @@
 		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 @@
 	std::string			mFontName;
 	const LLFontGL*		mFont;
 	std::string			mLink;
+	bool				mIsLink;
 	LLUIImagePtr		mImagep;
 };
 
diff -r b532610841b5 indra/llui/lltextbase.cpp
--- a/indra/llui/lltextbase.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/lltextbase.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 			{
 				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 @@
 	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 @@
 		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 @@
 			// 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::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 @@
 		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 @@
 			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 @@
 		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 -r b532610841b5 indra/llui/lltextbase.h
--- a/indra/llui/lltextbase.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/lltextbase.h	Sun Sep 05 10:36:55 2010 +0100
@@ -492,7 +492,11 @@
 	// 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 -r b532610841b5 indra/llui/llurlentry.cpp
--- a/indra/llui/llurlentry.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llurlentry.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 		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 @@
 							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 @@
 	// 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 @@
 	}
 
 	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))
+
+	LLAvatarName av_name;
+	if (LLAvatarNameCache::get(agent_id, &av_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 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 @@
 	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 @@
 	}
 	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 @@
 {
 	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 @@
 	return getUrl(url);
 }
 
+LLStyle::Params LLUrlEntryNoLink::getStyle() const 
+{ 
+	return LLStyle::Params(); 
+}
+
+
 //
 // LLUrlEntryIcon describes an icon with <icon>...</icon> tags
 //
@@ -812,7 +1000,6 @@
 {
 	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 -r b532610841b5 indra/llui/llurlentry.h
--- a/indra/llui/llurlentry.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llurlentry.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 	/// 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 @@
 	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 @@
 	std::string                                    	mIcon;
 	std::string                                    	mMenuName;
 	std::string                                    	mTooltip;
-	LLUIColor										mColor;
 	std::multimap<std::string, LLUrlEntryObserver>	mObservers;
-	bool                                            mDisabledLink;
 };
 
 ///
@@ -162,18 +161,78 @@
 ///
 /// 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 onAgentNameReceived(const LLUUID& id, const std::string& first,
-							 const std::string& last, BOOL is_group);
+	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:
+	/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
 };
 
 ///
@@ -185,10 +244,10 @@
 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 @@
 	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 -r b532610841b5 indra/llui/llurlmatch.cpp
--- a/indra/llui/llurlmatch.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llurlmatch.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -37,16 +37,15 @@
 	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 @@
 	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 -r b532610841b5 indra/llui/llurlmatch.h
--- a/indra/llui/llurlmatch.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llurlmatch.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 	/// 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 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;}
-
+	const LLUUID& getID() const { return mID; }
 private:
 	U32         mStart;
 	U32         mEnd;
@@ -101,10 +97,8 @@
 	std::string mIcon;
 	std::string mMenuName;
 	std::string mLocation;
-
 	LLUUID		mID;
-	LLUIColor	mColor;
-	bool        mDisabledLink;
+	LLStyle::Params mStyle;
 	bool		mUnderlineOnHoverOnly;
 };
 
diff -r b532610841b5 indra/llui/llurlregistry.cpp
--- a/indra/llui/llurlregistry.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llurlregistry.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	}
 }
 
-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 @@
 						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 @@
 						match.getLabel(),
 						match.getTooltip(),
 						match.getIcon(),
-						match.getColor(),
+						match.getStyle(),
 						match.getMenuName(),
 						match.getLocation(),
-						match.isLinkDisabled(),
 						match.getID(),
 						match.underlineOnHoverOnly());
 		return true;
diff -r b532610841b5 indra/llui/llurlregistry.h
--- a/indra/llui/llurlregistry.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/llurlregistry.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	~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 -r b532610841b5 indra/llui/tests/llurlentry_stub.cpp
--- a/indra/llui/tests/llurlentry_stub.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/tests/llurlentry_stub.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 {
 	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 -r b532610841b5 indra/llui/tests/llurlentry_test.cpp
--- a/indra/llui/tests/llurlentry_test.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/tests/llurlentry_test.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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::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 -r b532610841b5 indra/llui/tests/llurlmatch_test.cpp
--- a/indra/llui/tests/llurlmatch_test.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/llui/tests/llurlmatch_test.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 -r b532610841b5 indra/newview/CMakeLists.txt
--- a/indra/newview/CMakeLists.txt	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/CMakeLists.txt	Sun Sep 05 10:36:55 2010 +0100
@@ -238,6 +238,7 @@
     llhudeffecttrail.cpp
     llhudicon.cpp
     llhudmanager.cpp
+    llhudnametag.cpp
     llhudobject.cpp
     llhudrender.cpp
     llhudtext.cpp
@@ -476,6 +477,7 @@
     llviewercontrol.cpp
     llviewercontrollistener.cpp
     llviewerdisplay.cpp
+    llviewerdisplayname.cpp
     llviewerfloaterreg.cpp
     llviewerfoldertype.cpp
     llviewergenericmessage.cpp
@@ -762,6 +764,7 @@
     llhudeffecttrail.h
     llhudicon.h
     llhudmanager.h
+    llhudnametag.h
     llhudobject.h
     llhudrender.h
     llhudtext.h
@@ -1000,6 +1003,7 @@
     llviewercontrol.h
     llviewercontrollistener.h
     llviewerdisplay.h
+    llviewerdisplayname.h
     llviewerfloaterreg.h
     llviewerfoldertype.h
     llviewergenericmessage.h
diff -r b532610841b5 indra/newview/app_settings/settings.xml
--- a/indra/newview/app_settings/settings.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/app_settings/settings.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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>1</integer>
+      <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 -r b532610841b5 indra/newview/llagentui.cpp
--- a/indra/newview/llagentui.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llagentui.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -40,29 +40,6 @@
 #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)
 {
 	if (isAgentAvatarValid())
diff -r b532610841b5 indra/newview/llagentui.h
--- a/indra/newview/llagentui.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llagentui.h	Sun Sep 05 10:36:55 2010 +0100
@@ -41,7 +41,6 @@
 		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 -r b532610841b5 indra/newview/llappviewer.cpp
--- a/indra/newview/llappviewer.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llappviewer.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 
 	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::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 @@
 	{
 		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 @@
 	    // 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::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 @@
 	{
 		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 -r b532610841b5 indra/newview/llappviewer.h
--- a/indra/newview/llappviewer.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llappviewer.h	Sun Sep 05 10:36:55 2010 +0100
@@ -203,6 +203,8 @@
     
     void idle(); 
     void idleShutdown();
+	// update avatar SLID and display name caches
+	void idleNameCache();
     void idleNetwork();
 
     void sendLogoutRequest();
diff -r b532610841b5 indra/newview/llavataractions.cpp
--- a/indra/newview/llavataractions.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llavataractions.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	}
 
 	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 @@
 		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 @@
 	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 @@
 	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,25 +170,26 @@
 	handle_lure(ids);
 }
 
+static void on_avatar_name_cache_start_im(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);
+	if (session_id != LLUUID::null)
+	{
+		LLIMFloater::show(session_id);
+	}
+	make_ui_sound("UISndStartIM");
+}
+
 // static
 void LLAvatarActions::startIM(const LLUUID& id)
 {
 	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);
-	if (session_id != LLUUID::null)
-	{
-		LLIMFloater::show(session_id);
-	}
-	make_ui_sound("UISndStartIM");
+	LLAvatarNameCache::get(id,
+		boost::bind(&on_avatar_name_cache_start_im, _1, _2));
 }
 
 // static
@@ -218,6 +205,18 @@
 	}
 }
 
+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 @@
 	{
 		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 @@
 // 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 @@
 		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 @@
 
 	struct LLShareInfo : public LLSingleton<LLShareInfo>
 	{
-		std::vector<std::string> mAvatarNames;
+		std::vector<LLAvatarName> mAvatarNames;
 		uuid_vec_t mAvatarUuids;
 	};
 
@@ -595,7 +588,7 @@
 				}
 				else
 				{
-					LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
+				LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
 					shared = true;
 				}
 			}
@@ -627,11 +620,10 @@
 	 * @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 @@
 {
 	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 @@
 	}
 	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 @@
 
 	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::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 -r b532610841b5 indra/newview/llavataractions.h
--- a/indra/newview/llavataractions.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llavataractions.h	Sun Sep 05 10:36:55 2010 +0100
@@ -184,7 +184,6 @@
 	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 -r b532610841b5 indra/newview/llavatariconctrl.cpp
--- a/indra/newview/llavatariconctrl.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llavatariconctrl.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 			// 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 @@
 		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::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 -r b532610841b5 indra/newview/llavatariconctrl.h
--- a/indra/newview/llavatariconctrl.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llavatariconctrl.h	Sun Sep 05 10:36:55 2010 +0100
@@ -31,6 +31,8 @@
 #include "llavatarpropertiesprocessor.h"
 #include "llviewermenu.h"
 
+class LLAvatarName;
+
 class LLAvatarIconIDCache: public LLSingleton<LLAvatarIconIDCache>
 {
 public:
@@ -84,22 +86,16 @@
 	// 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 -r b532610841b5 indra/newview/llavatarlist.cpp
--- a/indra/newview/llavatarlist.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llavatarlist.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 
 	// 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 @@
 			}
 			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 @@
 
 		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 @@
 
 	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 @@
 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 @@
 		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 -r b532610841b5 indra/newview/llavatarlist.h
--- a/indra/newview/llavatarlist.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llavatarlist.h	Sun Sep 05 10:36:55 2010 +0100
@@ -28,7 +28,6 @@
 #define LL_LLAVATARLIST_H
 
 #include "llflatlistview.h"
-
 #include "llavatarlistitem.h"
 
 class LLTimer;
diff -r b532610841b5 indra/newview/llavatarlistitem.cpp
--- a/indra/newview/llavatarlistitem.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llavatarlistitem.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -35,6 +35,7 @@
 #include "lltextutil.h"
 
 #include "llagent.h"
+#include "llavatarnamecache.h"
 #include "llavatariconctrl.h"
 #include "lloutputmonitorctrl.h"
 
@@ -161,11 +162,16 @@
 	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 @@
 		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 @@
 	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 -r b532610841b5 indra/newview/llavatarlistitem.h
--- a/indra/newview/llavatarlistitem.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llavatarlistitem.h	Sun Sep 05 10:36:55 2010 +0100
@@ -36,6 +36,7 @@
 #include "llcallingcard.h" // for LLFriendObserver
 
 class LLAvatarIconCtrl;
+class LLAvatarName;
 
 class LLAvatarListItem : public LLPanel, public LLFriendObserver
 {
@@ -85,7 +86,8 @@
 	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 @@
 	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 @@
 	} 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 -r b532610841b5 indra/newview/llcallfloater.cpp
--- a/indra/newview/llcallfloater.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llcallfloater.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 	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 @@
 	{
 		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::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 -r b532610841b5 indra/newview/llcallfloater.h
--- a/indra/newview/llcallfloater.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llcallfloater.h	Sun Sep 05 10:36:55 2010 +0100
@@ -34,6 +34,7 @@
 
 class LLAvatarList;
 class LLAvatarListItem;
+class LLAvatarName;
 class LLNonAvatarCaller;
 class LLOutputMonitorCtrl;
 class LLParticipantList;
@@ -116,6 +117,10 @@
 	 */
 	void onAvatarListRefreshed();
 
+	/**
+	 * Updates window title with an avatar name
+	 */
+	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
 	
 	void updateTitle();
 	void initAgentData();
diff -r b532610841b5 indra/newview/llcallingcard.cpp
--- a/indra/newview/llcallingcard.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llcallingcard.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 // 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 @@
 	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 @@
 		{
 			++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 @@
 			{
 				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 @@
 		{
 			tracking_id = mTrackingData->mAvatarID;
 		}
-		BOOL notify = FALSE;
-		LLSD args;
 		LLSD payload;
 		for(S32 i = 0; i < count; ++i)
 		{
@@ -685,17 +685,6 @@
 			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 @@
 			// *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 @@
 	}
 }
 
+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 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 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 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 @@
 	}
 	return true;
 }
-
-
diff -r b532610841b5 indra/newview/llcallingcard.h
--- a/indra/newview/llcallingcard.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llcallingcard.h	Sun Sep 05 10:36:55 2010 +0100
@@ -235,8 +235,7 @@
 	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 @@
 	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 @@
 	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 -r b532610841b5 indra/newview/llchathistory.cpp
--- a/indra/newview/llchathistory.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llchathistory.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 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 @@
 		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 @@
 			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 @@
 		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 @@
 	LLUUID				mSessionID;
 
 	S32					mMinUserNameWidth;
+	const LLFontGL*		mUserNameFont;
 };
 
 LLUICtrl* LLChatHistoryHeader::sInfoCtrl = NULL;
diff -r b532610841b5 indra/newview/lldateutil.cpp
--- a/indra/newview/lldateutil.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lldateutil.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -166,3 +166,23 @@
 {
 	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 -r b532610841b5 indra/newview/lldateutil.h
--- a/indra/newview/lldateutil.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lldateutil.h	Sun Sep 05 10:36:55 2010 +0100
@@ -61,6 +61,14 @@
 
 	// 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 -r b532610841b5 indra/newview/lldrawable.h
--- a/indra/newview/lldrawable.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lldrawable.h	Sun Sep 05 10:36:55 2010 +0100
@@ -47,6 +47,7 @@
 class LLDrawPool;
 class LLDrawable;
 class LLFace;
+class LLFacePool;
 class LLSpatialGroup;
 class LLSpatialBridge;
 class LLSpatialPartition;
diff -r b532610841b5 indra/newview/llfloateravatarpicker.cpp
--- a/indra/newview/llfloateravatarpicker.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloateravatarpicker.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 		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 @@
 
 		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 @@
 		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 @@
 	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 @@
 	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;
+	std::string url;
+	url.reserve(128); // avoid a memory allocation or two
 
-	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();
+	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 @@
 		}
 		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::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 @@
 		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 -r b532610841b5 indra/newview/llfloateravatarpicker.h
--- a/indra/newview/llfloateravatarpicker.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloateravatarpicker.h	Sun Sep 05 10:36:55 2010 +0100
@@ -31,6 +31,7 @@
 
 #include <vector>
 
+class LLAvatarName;
 class LLScrollListCtrl;
 
 class LLFloaterAvatarPicker : public LLFloater
@@ -40,7 +41,7 @@
 	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 @@
 	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 -r b532610841b5 indra/newview/llfloateravatartextures.cpp
--- a/indra/newview/llfloateravatartextures.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloateravatartextures.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 		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 -r b532610841b5 indra/newview/llfloaterbump.cpp
--- a/indra/newview/llfloaterbump.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterbump.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -83,7 +83,7 @@
 
 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 @@
 	// 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 -r b532610841b5 indra/newview/llfloaterbuyland.cpp
--- a/indra/newview/llfloaterbuyland.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterbuyland.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -180,9 +180,8 @@
 	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 @@
 	}
 	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 -r b532610841b5 indra/newview/llfloatergodtools.cpp
--- a/indra/newview/llfloatergodtools.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloatergodtools.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -28,6 +28,7 @@
 
 #include "llfloatergodtools.h"
 
+#include "llavatarnamecache.h"
 #include "llcoord.h"
 #include "llfontgl.h"
 #include "llframetimer.h"
@@ -1145,11 +1146,11 @@
 	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 -r b532610841b5 indra/newview/llfloatergodtools.h
--- a/indra/newview/llfloatergodtools.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloatergodtools.h	Sun Sep 05 10:36:55 2010 +0100
@@ -35,6 +35,7 @@
 #include "llpanel.h"
 #include <vector>
 
+class LLAvatarName;
 class LLButton;
 class LLCheckBoxCtrl;
 class LLComboBox;
@@ -225,7 +226,7 @@
 	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 -r b532610841b5 indra/newview/llfloaterinspect.cpp
--- a/indra/newview/llfloaterinspect.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterinspect.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 		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 -r b532610841b5 indra/newview/llfloaterland.cpp
--- a/indra/newview/llfloaterland.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterland.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 			}
 			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 @@
 		}
 
 		// 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 @@
 	}
 	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 @@
 		}
 		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::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 @@
 // 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 -r b532610841b5 indra/newview/llfloaterland.h
--- a/indra/newview/llfloaterland.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterland.h	Sun Sep 05 10:36:55 2010 +0100
@@ -372,8 +372,8 @@
 	
 	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 -r b532610841b5 indra/newview/llfloaterpay.cpp
--- a/indra/newview/llfloaterpay.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterpay.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 
 	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 @@
 		
 		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 @@
 	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::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 -r b532610841b5 indra/newview/llfloaterpreference.cpp
--- a/indra/newview/llfloaterpreference.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterpreference.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 // 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 @@
 	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 @@
 	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 -r b532610841b5 indra/newview/llfloaterregioninfo.cpp
--- a/indra/newview/llfloaterregioninfo.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterregioninfo.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	// 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::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 @@
 	// 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 @@
 
 	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 @@
 	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 -r b532610841b5 indra/newview/llfloaterregioninfo.h
--- a/indra/newview/llfloaterregioninfo.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterregioninfo.h	Sun Sep 05 10:36:55 2010 +0100
@@ -34,6 +34,7 @@
 #include "llhost.h"
 #include "llpanel.h"
 
+class LLAvatarName;
 class LLDispatcher;
 class LLLineEditor;
 class LLMessageSystem;
@@ -162,7 +163,7 @@
 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 @@
 	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 @@
 	// 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 @@
 	// 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 -r b532610841b5 indra/newview/llfloaterreporter.cpp
--- a/indra/newview/llfloaterreporter.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterreporter.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 	
 			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 @@
 	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::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();
+	getChild<LLUICtrl>("owner_name")->setValue(avatar_link);
 
-	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 @@
 {
 	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 -r b532610841b5 indra/newview/llfloaterreporter.h
--- a/indra/newview/llfloaterreporter.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterreporter.h	Sun Sep 05 10:36:55 2010 +0100
@@ -32,6 +32,7 @@
 #include "lluuid.h"
 #include "v3math.h"
 
+class LLAvatarName;
 class LLMessageSystem;
 class LLViewerTexture;
 class LLInventoryItem;
@@ -117,8 +118,9 @@
 	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 -r b532610841b5 indra/newview/llfloaterscriptlimits.cpp
--- a/indra/newview/llfloaterscriptlimits.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterscriptlimits.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 		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 @@
 					btn->setEnabled(true);
 				}
 				
-				panel_memory->setRegionSummary(content);
-			}
-		}
+		panel_memory->setRegionSummary(content);
+	}
+}
 	}
 }
 
@@ -592,17 +594,24 @@
 // 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 @@
 			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 @@
 			// ...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 @@
 
 // static
 void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
-{	
+{
 	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
 	if(instance)
 	{
diff -r b532610841b5 indra/newview/llfloaterscriptlimits.h
--- a/indra/newview/llfloaterscriptlimits.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloaterscriptlimits.h	Sun Sep 05 10:36:55 2010 +0100
@@ -164,10 +164,8 @@
 	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 -r b532610841b5 indra/newview/llfloatersellland.cpp
--- a/indra/newview/llfloatersellland.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloatersellland.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 
 	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 @@
 	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 @@
 
 	mAuthorizedBuyer = ids[0];
 
-	getChild<LLUICtrl>("sell_to_agent")->setValue(names[0]);
+	getChild<LLUICtrl>("sell_to_agent")->setValue(names[0].getCompleteName());
 
 	refreshUI();
 }
diff -r b532610841b5 indra/newview/llfloatertopobjects.cpp
--- a/indra/newview/llfloatertopobjects.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfloatertopobjects.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 		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";
 		
-		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";
+		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);
+		
+		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 -r b532610841b5 indra/newview/llfolderview.h
--- a/indra/newview/llfolderview.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfolderview.h	Sun Sep 05 10:36:55 2010 +0100
@@ -115,7 +115,7 @@
 	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 -r b532610841b5 indra/newview/llfoldervieweventlistener.h
--- a/indra/newview/llfoldervieweventlistener.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfoldervieweventlistener.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/llfolderviewitem.h
--- a/indra/newview/llfolderviewitem.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfolderviewitem.h	Sun Sep 05 10:36:55 2010 +0100
@@ -51,7 +51,7 @@
 	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 -r b532610841b5 indra/newview/llfriendcard.cpp
--- a/indra/newview/llfriendcard.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llfriendcard.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 {
 
 	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 -r b532610841b5 indra/newview/llglsandbox.cpp
--- a/indra/newview/llglsandbox.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llglsandbox.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 			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 -r b532610841b5 indra/newview/llhudicon.h
--- a/indra/newview/llhudicon.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llhudicon.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/llhudnametag.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/indra/newview/llhudnametag.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -0,0 +1,1066 @@
+/** 
+ * @file llhudnametag.cpp
+ * @brief Name tags for avatars
+ * @author James Cook
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/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 -r b532610841b5 indra/newview/llhudnametag.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/indra/newview/llhudnametag.h	Sun Sep 05 10:36:55 2010 +0100
@@ -0,0 +1,185 @@
+/** 
+ * @file llhudnametag.h
+ * @brief Name tags for avatars
+ * @author James Cook
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/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 -r b532610841b5 indra/newview/llhudobject.cpp
--- a/indra/newview/llhudobject.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llhudobject.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	mVisible = TRUE;
 	mType = type;
 	mDead = FALSE;
-	mOnHUDAttachment = FALSE;
 }
 
 LLHUDObject::~LLHUDObject()
@@ -145,6 +141,9 @@
 	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 @@
 	LLFastTimer ftm(FTM_HUD_UPDATE);
 	LLHUDText::updateAll();
 	LLHUDIcon::updateAll();
+	LLHUDNameTag::updateAll();
 	sortObjects();
 }
 
@@ -326,6 +326,14 @@
 }
 
 // static
+void LLHUDObject::reshapeAll()
+{
+	// only hud objects that use fonts care about window size/scale changes
+	LLHUDText::reshape();
+	LLHUDNameTag::reshape();
+}
+
+// static
 void LLHUDObject::sortObjects()
 {
 	sHUDObjects.sort(hud_object_further_away());	
diff -r b532610841b5 indra/newview/llhudobject.h
--- a/indra/newview/llhudobject.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llhudobject.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 		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 @@
 	BOOL			mDead;
 	BOOL			mVisible;
 	LLVector3d		mPositionGlobal;
-	BOOL			mOnHUDAttachment;
 	LLPointer<LLViewerObject> mSourceObject;
 	LLPointer<LLViewerObject> mTargetObject;
 
diff -r b532610841b5 indra/newview/llhudtext.cpp
--- a/indra/newview/llhudtext.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llhudtext.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 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 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 @@
 			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 @@
 	mFadeDistance = 8.f;
 	mFadeRange = 4.f;
 	mZCompare = TRUE;
-	mDropShadow = TRUE;
 	mOffscreen = FALSE;
 	mRadius = 0.1f;
 	LLPointer<LLHUDText> ptr(this);
@@ -111,112 +108,6 @@
 {
 }
 
-
-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 @@
 		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 @@
 	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 @@
 	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 @@
 		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 @@
 	}
 	/// 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::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)
+	LLWString wline = utf8str_to_wstring(text_utf8);
+	if (!wline.empty())
 	{
-		return;
-	}
-	if (!wstr.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 @@
 			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::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,11 +340,16 @@
 	}
 }
 
+void LLHUDText::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 LLHUDText::setUsePixelSize(const BOOL use_pixel_size)
-{
-	mUsePixelSize = use_pixel_size;
-}
 
 void LLHUDText::setDoFade(const BOOL do_fade)
 {
@@ -745,7 +418,7 @@
 
 	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 @@
 	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 @@
 	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 @@
 
 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 @@
 	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 @@
 	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 @@
 	// 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 @@
 	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 @@
 		{
 			segment_iter->clearFontWidthMap();
 		}
-		for(segment_iter = textp->mLabelSegments.begin();
-			segment_iter != textp->mLabelSegments.end(); ++segment_iter )
-		{
-			segment_iter->clearFontWidthMap();
-		}		
 	}
 }
 
diff -r b532610841b5 indra/newview/llhudtext.h
--- a/indra/newview/llhudtext.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llhudtext.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 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 @@
 	} 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 @@
 	/*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 @@
 	/*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 @@
 	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 -r b532610841b5 indra/newview/llimfloater.cpp
--- a/indra/newview/llimfloater.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llimfloater.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 		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 @@
 	}
 }
 
+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 @@
 	{
 		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 -r b532610841b5 indra/newview/llimfloater.h
--- a/indra/newview/llimfloater.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llimfloater.h	Sun Sep 05 10:36:55 2010 +0100
@@ -32,6 +32,7 @@
 #include "lltooldraganddrop.h"
 #include "lltransientdockablefloater.h"
 
+class LLAvatarName;
 class LLLineEditor;
 class LLPanelChatControlPanel;
 class LLChatHistory;
@@ -124,6 +125,12 @@
 	/* 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 -r b532610841b5 indra/newview/llimview.cpp
--- a/indra/newview/llimview.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llimview.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 		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 @@
 		// 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 @@
 		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 @@
 		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 @@
 	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);
 	}
-
-	setTitle(caller_name + " " + call_type);
-
-	LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
-	caller_name_widget->setValue(caller_name + " " + call_type);
+	else
+	{
+		// Get the full name information
+		LLAvatarNameCache::get(caller_id,
+			boost::bind(&LLIncomingCallDialog::onAvatarNameCache,
+				this, _1, _2, call_type));
+	}
+
 	setIcon(session_id, caller_id);
 
 	childSetAction("Accept", onAccept, this);
@@ -1950,6 +1976,24 @@
 	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 @@
 					}
 					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 @@
 	{
 		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::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 @@
 		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 -r b532610841b5 indra/newview/llimview.h
--- a/indra/newview/llimview.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llimview.h	Sun Sep 05 10:36:55 2010 +0100
@@ -35,7 +35,7 @@
 #include "llvoicechannel.h"
 
 
-
+class LLAvatarName;
 class LLFriendObserver;
 class LLCallDialogManager;	
 class LLIMSpeakerMgr;
@@ -453,7 +453,7 @@
 
 	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 @@
 	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 -r b532610841b5 indra/newview/llinspectavatar.cpp
--- a/indra/newview/llinspectavatar.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llinspectavatar.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	// 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 @@
 
 	// 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 @@
 
 	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 @@
 
 		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 @@
 	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 @@
 	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::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::onClickReport()
 {
-	LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName);
+	LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName.getCompleteName());
 	closeFloater();
 }
 
@@ -730,17 +744,17 @@
 
 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::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 -r b532610841b5 indra/newview/llinspectgroup.cpp
--- a/indra/newview/llinspectgroup.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llinspectgroup.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -78,9 +78,8 @@
 	// 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 @@
 	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 -r b532610841b5 indra/newview/llinspectremoteobject.cpp
--- a/indra/newview/llinspectremoteobject.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llinspectremoteobject.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -60,12 +60,12 @@
 	
 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 @@
 	LLInspect(LLSD()),
 	mObjectID(NULL),
 	mOwnerID(NULL),
-	mOwner(""),
+	mOwnerLegacyName(),
 	mSLurl(""),
 	mName(""),
 	mGroupOwned(false)
@@ -112,10 +112,11 @@
 	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::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 @@
 	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 @@
 	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 -r b532610841b5 indra/newview/llinventorybridge.cpp
--- a/indra/newview/llinventorybridge.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llinventorybridge.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -29,6 +29,7 @@
 
 // external projects
 #include "lltransfersourceasset.h"
+#include "llavatarnamecache.h"	// IDEVO
 
 #include "llagent.h"
 #include "llagentcamera.h"
@@ -3450,6 +3451,13 @@
 		{
 			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 -r b532610841b5 indra/newview/lllogchat.cpp
--- a/indra/newview/lllogchat.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lllogchat.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 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 @@
 {
 	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;
 }
 
@@ -234,6 +241,18 @@
 			    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);
 	if (tmp_filename.empty())
@@ -254,89 +273,27 @@
 	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 @@
 	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 @@
 	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 -r b532610841b5 indra/newview/lllogchat.h
--- a/indra/newview/lllogchat.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lllogchat.h	Sun Sep 05 10:36:55 2010 +0100
@@ -24,10 +24,11 @@
  * $/LicenseInfo$
  */
 
-
 #ifndef LL_LLLOGCHAT_H
 #define LL_LLLOGCHAT_H
 
+class LLChat;
+
 class LLLogChat
 {
 public:
@@ -40,49 +41,22 @@
 	};
 	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
  */
 class LLChatLogParser
@@ -100,11 +74,18 @@
 	 *
 	 * @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 -r b532610841b5 indra/newview/lllogininstance.cpp
--- a/indra/newview/lllogininstance.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lllogininstance.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -137,6 +137,7 @@
 
 	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 -r b532610841b5 indra/newview/llmutelist.cpp
--- a/indra/newview/llmutelist.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llmutelist.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -112,9 +112,8 @@
 		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 @@
 	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 @@
 	}
 
 	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 @@
 }
 
 
-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 @@
 		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 -r b532610841b5 indra/newview/llmutelist.h
--- a/indra/newview/llmutelist.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llmutelist.h	Sun Sep 05 10:36:55 2010 +0100
@@ -63,7 +63,7 @@
 	
 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 @@
 
 	// 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 -r b532610841b5 indra/newview/llnamebox.cpp
--- a/indra/newview/llnamebox.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llnamebox.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -81,26 +81,15 @@
 		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 @@
 		 ++it)
 	{
 		LLNameBox* box = *it;
-		box->refresh(id, firstname, lastname, is_group);
+		box->refresh(id, full_name, is_group);
 	}
 }
 
diff -r b532610841b5 indra/newview/llnamebox.h
--- a/indra/newview/llnamebox.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llnamebox.h	Sun Sep 05 10:36:55 2010 +0100
@@ -53,10 +53,9 @@
 
 	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 -r b532610841b5 indra/newview/llnameeditor.cpp
--- a/indra/newview/llnameeditor.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llnameeditor.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -75,26 +75,15 @@
 	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 @@
 		 ++it)
 	{
 		LLNameEditor* box = *it;
-		box->refresh(id, firstname, lastname, is_group);
+		box->refresh(id, full_name, is_group);
 	}
 }
 
diff -r b532610841b5 indra/newview/llnameeditor.h
--- a/indra/newview/llnameeditor.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llnameeditor.h	Sun Sep 05 10:36:55 2010 +0100
@@ -59,10 +59,9 @@
 
 	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 -r b532610841b5 indra/newview/llnamelistctrl.cpp
--- a/indra/newview/llnamelistctrl.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llnamelistctrl.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 
 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 @@
 :	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 @@
 		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 @@
 	}
 }
 
-// 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 name;
+	if (mShortNames)
+		name = av_name.mDisplayName;
+	else
+		name = av_name.getCompleteName();
 
-	std::string fullname;
-	if (!is_group)
-	{
-		fullname = first + " " + last;
-	}
-	else
-	{
-		fullname = first;
-	}
-
-	// 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 @@
 }
 
 
-// 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 -r b532610841b5 indra/newview/llnamelistctrl.h
--- a/indra/newview/llnamelistctrl.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llnamelistctrl.h	Sun Sep 05 10:36:55 2010 +0100
@@ -31,6 +31,7 @@
 
 #include "llscrolllistctrl.h"
 
+class LLAvatarName;
 
 class LLNameListCtrl
 :	public LLScrollListCtrl, public LLInstanceTracker<LLNameListCtrl>
@@ -74,6 +75,7 @@
 	{
 		Optional<NameColumn>	name_column;
 		Optional<bool>	allow_calling_card_drop;
+		Optional<bool>			short_names;
 		Params();
 	};
 
@@ -99,11 +101,6 @@
 
 	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 @@
 	/*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 -r b532610841b5 indra/newview/llnearbychat.cpp
--- a/indra/newview/llnearbychat.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llnearbychat.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 
 	if (gSavedPerAccountSettings.getBOOL("LogNearbyChat"))
 	{
-		LLLogChat::saveHistory("chat", chat.mFromName, chat.mFromID, chat.mText);
+		LLLogChat::saveHistory("chat", chat);
 	}
 }
 
@@ -275,8 +269,12 @@
 		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 @@
 		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 -r b532610841b5 indra/newview/llnetmap.cpp
--- a/indra/newview/llnetmap.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llnetmap.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	{
 		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 @@
 	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 -r b532610841b5 indra/newview/llnotificationhandlerutil.cpp
--- a/indra/newview/llnotificationhandlerutil.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llnotificationhandlerutil.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -107,8 +107,11 @@
 }
 
 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 @@
 {
 	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 @@
 	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 -r b532610841b5 indra/newview/llpanelavatar.cpp
--- a/indra/newview/llpanelavatar.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelavatar.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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::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 @@
 	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::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 -r b532610841b5 indra/newview/llpanelavatartag.cpp
--- a/indra/newview/llpanelavatartag.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelavatartag.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -80,7 +80,7 @@
 	{
 		mIcon->setValue(avatar_id);
 	}
-	setName(std::string(mIcon->getFirstName()+ " "+ mIcon->getLastName()));
+	setName(std::string(mIcon->getFullName()));
 }
 
 boost::signals2::connection LLPanelAvatarTag::setLeftButtonClickCallback(
diff -r b532610841b5 indra/newview/llpanelblockedlist.cpp
--- a/indra/newview/llpanelblockedlist.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelblockedlist.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 -r b532610841b5 indra/newview/llpanelblockedlist.h
--- a/indra/newview/llpanelblockedlist.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelblockedlist.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 -r b532610841b5 indra/newview/llpanelgroupgeneral.cpp
--- a/indra/newview/llpanelgroupgeneral.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelgroupgeneral.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	{
 		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 @@
 	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 -r b532610841b5 indra/newview/llpanelgroupgeneral.h
--- a/indra/newview/llpanelgroupgeneral.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelgroupgeneral.h	Sun Sep 05 10:36:55 2010 +0100
@@ -37,7 +37,6 @@
 class LLNameListCtrl;
 class LLCheckBoxCtrl;
 class LLComboBox;
-class LLNameBox;
 class LLSpinCtrl;
 
 class LLPanelGroupGeneral : public LLPanelGroupTab
@@ -91,7 +90,7 @@
 
 	// Group information (include any updates in updateChanged)
 	LLLineEditor		*mGroupNameEditor;
-	LLNameBox			*mFounderName;
+	LLTextBox			*mFounderName;
 	LLTextureCtrl		*mInsignia;
 	LLTextEditor		*mEditCharter;
 
diff -r b532610841b5 indra/newview/llpanelgroupinvite.cpp
--- a/indra/newview/llpanelgroupinvite.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelgroupinvite.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 				{
 					// 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 @@
 	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 -r b532610841b5 indra/newview/llpanelgroupinvite.h
--- a/indra/newview/llpanelgroupinvite.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelgroupinvite.h	Sun Sep 05 10:36:55 2010 +0100
@@ -40,7 +40,7 @@
 	/**
 	 * 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 -r b532610841b5 indra/newview/llpanelgroupnotices.cpp
--- a/indra/newview/llpanelgroupnotices.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelgroupnotices.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -30,6 +30,7 @@
 
 #include "llview.h"
 
+#include "llavatarnamecache.h"
 #include "llinventory.h"
 #include "llviewerinventory.h"
 #include "llinventorydefines.h"
@@ -540,6 +541,12 @@
 		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 -r b532610841b5 indra/newview/llpanelgrouproles.cpp
--- a/indra/newview/llpanelgrouproles.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelgrouproles.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -1110,11 +1110,7 @@
 		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 -r b532610841b5 indra/newview/llpanelimcontrolpanel.cpp
--- a/indra/newview/llpanelimcontrolpanel.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelimcontrolpanel.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -180,7 +180,7 @@
 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 @@
 		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::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 -r b532610841b5 indra/newview/llpanelimcontrolpanel.h
--- a/indra/newview/llpanelimcontrolpanel.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelimcontrolpanel.h	Sun Sep 05 10:36:55 2010 +0100
@@ -83,6 +83,9 @@
 	// 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 -r b532610841b5 indra/newview/llpanellandmarkinfo.cpp
--- a/indra/newview/llpanellandmarkinfo.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanellandmarkinfo.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	//////////////////
 	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 @@
 		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 -r b532610841b5 indra/newview/llpanellogin.cpp
--- a/indra/newview/llpanellogin.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanellogin.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -205,7 +205,6 @@
 	}
 
 #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 @@
 	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 @@
 	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 @@
 	}
 	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)
 		{
@@ -812,7 +834,7 @@
 	curl_free(curl_version);
 
 	// Grid
-	char* curl_grid = curl_escape(LLGridManager::getInstance()->getGridLoginID().c_str(), 0);
+	char* curl_grid = curl_escape(LLGridManager::getInstance()->getGridLabel().c_str(), 0);
 	oStr << "&grid=" << curl_grid;
 	curl_free(curl_grid);
 	gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());
diff -r b532610841b5 indra/newview/llpanelme.cpp
--- a/indra/newview/llpanelme.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelme.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 "llsidetray.h"
+#include "llviewercontrol.h"
+#include "llviewerdisplayname.h"
+
+// Linden libraries
+#include "llavatarnamecache.h"		// IDEVO
 #include "lliconctrl.h"
-#include "llsidetray.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 @@
 	// 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 @@
 
 	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 @@
 	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 @@
 {
 	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 @@
 	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 -r b532610841b5 indra/newview/llpanelme.h
--- a/indra/newview/llpanelme.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelme.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	/*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 @@
 	 */
 	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 -r b532610841b5 indra/newview/llpanelmediasettingspermissions.cpp
--- a/indra/newview/llpanelmediasettingspermissions.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelmediasettingspermissions.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -101,16 +101,16 @@
 		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 @@
             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 -r b532610841b5 indra/newview/llpanelpeople.cpp
--- a/indra/newview/llpanelpeople.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelpeople.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -27,6 +27,7 @@
 #include "llviewerprecompiledheaders.h"
 
 // libs
+#include "llavatarname.h"
 #include "llfloaterreg.h"
 #include "llmenugl.h"
 #include "llnotificationsutil.h"
@@ -1148,12 +1149,10 @@
 }
 
 // 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 -r b532610841b5 indra/newview/llpanelpeople.h
--- a/indra/newview/llpanelpeople.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelpeople.h	Sun Sep 05 10:36:55 2010 +0100
@@ -32,10 +32,11 @@
 #include "llcallingcard.h" // for avatar tracker
 #include "llvoiceclient.h"
 
+class LLAvatarList;
+class LLAvatarName;
 class LLFilterEditor;
+class LLGroupList;
 class LLTabContainer;
-class LLAvatarList;
-class LLGroupList;
 
 class LLPanelPeople 
 	: public LLPanel
@@ -122,9 +123,7 @@
 	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 -r b532610841b5 indra/newview/llpanelpermissions.cpp
--- a/indra/newview/llpanelpermissions.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelpermissions.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -379,7 +379,7 @@
 		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 -r b532610841b5 indra/newview/llpanelpicks.cpp
--- a/indra/newview/llpanelpicks.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelpicks.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -229,9 +229,9 @@
 		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 -r b532610841b5 indra/newview/llpanelplaceinfo.cpp
--- a/indra/newview/llpanelplaceinfo.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelplaceinfo.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -28,6 +28,7 @@
 
 #include "llpanelplaceinfo.h"
 
+#include "llavatarname.h"
 #include "llsdutil.h"
 
 #include "llsdutil_math.h"
@@ -304,9 +305,15 @@
 }
 
 // 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 -r b532610841b5 indra/newview/llpanelplaceinfo.h
--- a/indra/newview/llpanelplaceinfo.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelplaceinfo.h	Sun Sep 05 10:36:55 2010 +0100
@@ -34,6 +34,7 @@
 
 #include "llremoteparcelrequest.h"
 
+class LLAvatarName;
 class LLExpandableTextBox;
 class LLIconCtrl;
 class LLInventoryItem;
@@ -96,9 +97,10 @@
 	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 -r b532610841b5 indra/newview/llpanelplaceprofile.cpp
--- a/indra/newview/llpanelplaceprofile.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelplaceprofile.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 			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 @@
 		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 @@
 		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 -r b532610841b5 indra/newview/llpanelprofile.h
--- a/indra/newview/llpanelprofile.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelprofile.h	Sun Sep 05 10:36:55 2010 +0100
@@ -27,7 +27,6 @@
 #ifndef LL_LLPANELPROFILE_H
 #define LL_LLPANELPROFILE_H
 
-#include "llviewerprecompiledheaders.h"
 #include "llpanel.h"
 #include "llpanelavatar.h"
 
diff -r b532610841b5 indra/newview/llpanelprofileview.cpp
--- a/indra/newview/llpanelprofileview.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelprofileview.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 	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 -r b532610841b5 indra/newview/llpanelprofileview.h
--- a/indra/newview/llpanelprofileview.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llpanelprofileview.h	Sun Sep 05 10:36:55 2010 +0100
@@ -33,6 +33,7 @@
 #include "llagent.h"
 #include "lltooldraganddrop.h"
 
+class LLAvatarName;
 class LLPanelProfile;
 class LLPanelProfileTab;
 class LLTextBox;
@@ -93,11 +94,11 @@
 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 -r b532610841b5 indra/newview/llparticipantlist.cpp
--- a/indra/newview/llparticipantlist.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llparticipantlist.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -331,11 +331,18 @@
 			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 @@
 			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 -r b532610841b5 indra/newview/llsidepaneliteminfo.cpp
--- a/indra/newview/llsidepaneliteminfo.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llsidepaneliteminfo.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -275,11 +275,12 @@
 
 	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 @@
 		}
 		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 -r b532610841b5 indra/newview/llsidepaneltaskinfo.cpp
--- a/indra/newview/llsidepaneltaskinfo.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llsidepaneltaskinfo.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -345,7 +345,7 @@
 		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 -r b532610841b5 indra/newview/llspeakers.cpp
--- a/indra/newview/llspeakers.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llspeakers.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -70,13 +70,13 @@
 {
 	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 -r b532610841b5 indra/newview/llspeakers.h
--- a/indra/newview/llspeakers.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llspeakers.h	Sun Sep 05 10:36:55 2010 +0100
@@ -60,7 +60,7 @@
 	~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 -r b532610841b5 indra/newview/llstartup.cpp
--- a/indra/newview/llstartup.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llstartup.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -46,6 +46,7 @@
 #endif
 
 #include "llares.h"
+#include "llavatarnamecache.h"
 #include "lllandmark.h"
 #include "llcachename.h"
 #include "lldir.h"
@@ -261,11 +262,10 @@
 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 @@
 
 		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 @@
 			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 @@
 	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 -r b532610841b5 indra/newview/llstartup.h
--- a/indra/newview/llstartup.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llstartup.h	Sun Sep 05 10:36:55 2010 +0100
@@ -87,8 +87,12 @@
 	// 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 -r b532610841b5 indra/newview/llsyswellwindow.cpp
--- a/indra/newview/llsyswellwindow.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llsyswellwindow.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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,14 +279,31 @@
 	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)
 {
 	LLTextBox* text = getChild<LLTextBox>("contact_name");
diff -r b532610841b5 indra/newview/llsyswellwindow.h
--- a/indra/newview/llsyswellwindow.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llsyswellwindow.h	Sun Sep 05 10:36:55 2010 +0100
@@ -37,6 +37,7 @@
 
 #include "boost/shared_ptr.hpp"
 
+class LLAvatarName;
 class LLFlatListView;
 class LLChiclet;
 class LLIMChiclet;
@@ -202,6 +203,7 @@
 
 	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 -r b532610841b5 indra/newview/lltoastgroupnotifypanel.cpp
--- a/indra/newview/lltoastgroupnotifypanel.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lltoastgroupnotifypanel.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 -r b532610841b5 indra/newview/lltoastimpanel.cpp
--- a/indra/newview/lltoastimpanel.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lltoastimpanel.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -141,7 +141,8 @@
 {
 	// 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 -r b532610841b5 indra/newview/lltoolpie.cpp
--- a/indra/newview/lltoolpie.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lltoolpie.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 			|| !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 -r b532610841b5 indra/newview/lltracker.cpp
--- a/indra/newview/lltracker.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/lltracker.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -564,16 +564,16 @@
 	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 -r b532610841b5 indra/newview/llviewerdisplay.cpp
--- a/indra/newview/llviewerdisplay.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerdisplay.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -317,7 +317,7 @@
 	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 -r b532610841b5 indra/newview/llviewerdisplayname.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/indra/newview/llviewerdisplayname.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -0,0 +1,200 @@
+/** 
+ * @file llviewerdisplayname.cpp
+ * @brief Wrapper for display name functionality
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/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 -r b532610841b5 indra/newview/llviewerdisplayname.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/indra/newview/llviewerdisplayname.h	Sun Sep 05 10:36:55 2010 +0100
@@ -0,0 +1,48 @@
+/** 
+ * @file llviewerdisplayname.h
+ * @brief Wrapper for display name functionality
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/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 -r b532610841b5 indra/newview/llviewerinventory.cpp
--- a/indra/newview/llviewerinventory.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerinventory.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -1776,9 +1776,9 @@
 
 //----------
 
-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 -r b532610841b5 indra/newview/llviewerinventory.h
--- a/indra/newview/llviewerinventory.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerinventory.h	Sun Sep 05 10:36:55 2010 +0100
@@ -157,7 +157,7 @@
 	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 -r b532610841b5 indra/newview/llviewerjointattachment.cpp
--- a/indra/newview/llviewerjointattachment.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerjointattachment.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/llviewermenu.cpp
--- a/indra/newview/llviewermenu.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewermenu.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 			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 @@
 	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 @@
 	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();
-		}
-		if (!fullname.empty())
-		{
-			LLAvatarActions::requestFriendshipDialog(dest_id, fullname);
+			full_name = LLCacheName::buildFullName(
+				nvfirst->getString(), nvlast->getString());
+		}
+		if (!full_name.empty())
+		{
+			LLAvatarActions::requestFriendshipDialog(dest_id, full_name);
 		}
 		else
 		{
@@ -7719,6 +7663,16 @@
 	}
 };
 
+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 @@
 	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 @@
 	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 @@
 	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 -r b532610841b5 indra/newview/llviewermessage.cpp
--- a/indra/newview/llviewermessage.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewermessage.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 
 // 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 @@
 }
 
 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 @@
 		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 @@
 		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 @@
 		}
 		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 @@
 	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 @@
 	void modifyNotificationParams()
 	{
 		LLSD payload = mParams.payload;
-		payload["SESSION_NAME"] = mName;
 		mParams.payload = payload;
 	}
 };
@@ -2003,6 +2011,99 @@
 	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 @@
 		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 @@
 	{
         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 @@
 	{
 	case IM_CONSOLE_AND_CHAT_HISTORY:
 		args["MESSAGE"] = message;
-		args["NAME"] = name;
 		payload["from_id"] = from_id;
 
 		params.name = "IMSystemMessageTip";
@@ -2161,21 +2283,9 @@
 		}
 		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 @@
 				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 @@
 
 	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 @@
 	}
 	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 @@
 				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 @@
 			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 @@
 		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 @@
 	LLNotificationsUtil::add("CallingCardDeclined");
 }
 
-
 void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 {
 	LLChat	chat;
@@ -2925,7 +3050,6 @@
 	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 @@
 	
 	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_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()))
-	{
-		// Make the user confirm the transaction, since they might
-		// have missed something during an event.
-		// *TODO: Translate
+	if (std::find(recent.rbegin(), recent.rend(), tid) != recent.rend())
+	{
+		return;
+	}
+
+	// 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;
-		
-
-		// this is a marker to retrieve avatar name from server message:
-		// "<avatar name> paid you L$"
-		const std::string marker = "paid you L$";
-
 		args["MESSAGE"] = desc;
-
-		// extract avatar name from system message
-		S32 marker_pos = desc.find(marker, 0);
-
-		std::string base_name = desc.substr(0, marker_pos);
-		
-		std::string name = base_name;
-		LLStringUtil::trim(name);
-
-		// 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
-
-			//ammount paid
-			std::string ammount = desc.substr(marker_pos + marker.length(),desc.length() - marker.length() - marker_pos);
+		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");
+
+		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();
+
+		default:
+			llwarns << "Unknown transaction type " 
+				<< transaction_type << llendl;
+			return std::string();
+	}
+}
+
+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);
+}
+
+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;
+	}
+
+	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);
 	
-			//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);
-
-
-			args["MESSAGE"] = new_description;
-			args["NAME"] = name;
-			LLSD payload;
-			payload["from_id"] = from_id;
-			LLNotificationsUtil::add("PaymentRecived", args, payload);
-		}
-		//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.
+	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);
+			}
+		}
 		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);
 			}
-
-			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)
-		{
-			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);
+			else
+			{
+				// no target, no reason, you just paid money
+				message = LLTrans::getString("you_paid_ldollars_no_info", args);
+			}
+		}
+		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())
+		{
+			message = LLTrans::getString("paid_you_ldollars", args);
+		}
+		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 @@
 	//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 @@
 		LLMeanCollisionData *mcd = *iter;
 		if (mcd->mPerp == id)
 		{
-			mcd->mFirstName = first;
-			mcd->mLastName = last;
+			mcd->mFullName = full_name;
 		}
 	}
 }
@@ -5283,8 +5546,7 @@
 		{
 			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 @@
 	// 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 @@
 		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 @@
 			// 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 @@
 	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 @@
 
 // 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 @@
 			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 @@
 	// 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 -r b532610841b5 indra/newview/llviewerobject.cpp
--- a/indra/newview/llviewerobject.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerobject.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 					// 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 @@
 					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 @@
 		mText->setOnHUDAttachment(isHUDAttachment());
 	}
 	mText->setColor(LLColor4::white);
-	mText->setStringUTF8(utf8text);
+	mText->setString(utf8text);
 	mText->setZCompare(FALSE);
 	mText->setDoFade(FALSE);
 	updateText();
diff -r b532610841b5 indra/newview/llviewerobject.h
--- a/indra/newview/llviewerobject.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerobject.h	Sun Sep 05 10:36:55 2010 +0100
@@ -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 LLFrameTimer;
 class LLDrawable;
 class LLHost;
+class LLHUDText;
 class LLWorld;
 class LLNameValue;
 class LLNetMap;
diff -r b532610841b5 indra/newview/llviewerobjectlist.cpp
--- a/indra/newview/llviewerobjectlist.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerobjectlist.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 			}
 		}
 
-		LLHUDText::addPickable(mSelectPickList);
+		LLHUDNameTag::addPickable(mSelectPickList);
 
 		for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
 			iter != LLCharacter::sInstances.end(); ++iter)
diff -r b532610841b5 indra/newview/llviewerparcelmgr.cpp
--- a/indra/newview/llviewerparcelmgr.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerparcelmgr.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -2069,10 +2069,7 @@
 	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 -r b532610841b5 indra/newview/llviewerregion.cpp
--- a/indra/newview/llviewerregion.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerregion.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 				mRegion->showReleaseNotes();
 			}
 		}
-		
+
+		mRegion->setCapabilitiesReceived(true);
+
 		if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
 		{
 			LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
@@ -228,7 +232,8 @@
     // 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 @@
 	LLSD capabilityNames = LLSD::emptyArray();
 	
 	capabilityNames.append("AttachmentResources");
+	capabilityNames.append("AvatarPickerSearch");
 	capabilityNames.append("ChatSessionRequest");
 	capabilityNames.append("CopyInventoryFromNotecard");
 	capabilityNames.append("DispatchRegionInfo");
@@ -1502,6 +1508,7 @@
 	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 @@
 	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 @@
 	return iter->second;
 }
 
+bool LLViewerRegion::capabilitiesReceived() const
+{
+	return mCapabilitiesReceived;
+}
+
+void LLViewerRegion::setCapabilitiesReceived(bool received)
+{
+	mCapabilitiesReceived = received;
+}
+
 void LLViewerRegion::logActiveCapabilities() const
 {
 	int count = 0;
diff -r b532610841b5 indra/newview/llviewerregion.h
--- a/indra/newview/llviewerregion.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerregion.h	Sun Sep 05 10:36:55 2010 +0100
@@ -228,6 +228,11 @@
 	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 @@
 
 private:
 	bool	mAlive;					// can become false if circuit disconnects
+	bool	mCapabilitiesReceived;
 
 	//spatial partitions for objects in this region
 	std::vector<LLSpatialPartition*> mObjectPartition;
diff -r b532610841b5 indra/newview/llviewerstats.cpp
--- a/indra/newview/llviewerstats.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerstats.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -847,6 +847,9 @@
 
 	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 -r b532610841b5 indra/newview/llviewerwindow.cpp
--- a/indra/newview/llviewerwindow.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llviewerwindow.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 		//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 @@
 		// clear font width caches
 		if (display_scale_changed)
 		{
-			LLHUDText::reshape();
+			LLHUDObject::reshapeAll();
 		}
 
 		sendShapeToSim();
@@ -3913,7 +3910,7 @@
 		send_agent_pause();
 		//rescale fonts
 		initFonts(scale_factor);
-		LLHUDText::reshape();
+		LLHUDObject::reshapeAll();
 	}
 
 	S32 output_buffer_offset_y = 0;
@@ -4042,7 +4039,7 @@
 	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 -r b532610841b5 indra/newview/llvoavatar.cpp
--- a/indra/newview/llvoavatar.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llvoavatar.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	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 @@
 								 && 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 @@
 
 		// 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 @@
 				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);
-
-				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)
-			{
-				mNameText->markDead();
-				mNameText = NULL;
-				sNumVisibleChatBubbles--;
-			}
-		}
-		
+	idleUpdateNameTagAlpha(new_name, alpha);
+}
+
+void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
+			{
 		LLNameValue *title = getNVPair("Title");
 		LLNameValue* firstname = getNVPair("FirstName");
 		LLNameValue* lastname = getNVPair("LastName");
 
-		if (mNameText.notNull() && firstname && lastname)
-		{
-			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();
+	// 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
+		{
+		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 @@
 				}
 			}
 
-			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)
+		|| is_friend != mNameFriend
+		|| is_cloud != mNameCloud)
 				{
-					// 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')
+		LLColor4 name_tag_color = getNameTagColor(is_friend);
+
+		clearNameTag();
+
+		if (is_away || is_muted || is_busy || is_appearance)
 				{
-					line += title->getString();
-					LLStringFn::replace_ascii_controlchars(line,LL_UNKNOWN_CHAR);
-					line += "\n";
-					line += firstname->getString();
-				}
-				else
-				{
-					line += firstname->getString();
-				}
-
-				line += " ";
-				line += lastname->getString();
-				BOOL need_comma = FALSE;
-
-				if (is_away || is_muted || is_busy)
-				{
-					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)
-			{
-				mNameText->setDropShadow(TRUE);
+	if (mVisibleChat)
+			{
 				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 @@
 					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 @@
 			}
 			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();
 				}
 			}
-		}
-	}
-	else if (mNameText)
-	{
-		mNameText->markDead();
-		mNameText = NULL;
-		sNumVisibleChatBubbles--;
-	}
+
+// 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
+	{
+		// ...not using display names
+		color_name = "NameTagLegacy";
+	}
+	return LLUIColorTable::getInstance()->getColor( color_name );
 }
 
 //--------------------------------------------------------------------
@@ -6757,7 +6898,7 @@
 	{
 		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 @@
 			// 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 @@
 	LLNameValue* last  = getNVPair("LastName"); 
 	if (first && last)
 	{
-		name += first->getString();
-		name += " ";
-		name += last->getString();
+		name = LLCacheName::buildFullName( first->getString(), last->getString() );
 	}
 
 	return name;
diff -r b532610841b5 indra/newview/llvoavatar.h
--- a/indra/newview/llvoavatar.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llvoavatar.h	Sun Sep 05 10:36:55 2010 +0100
@@ -59,7 +59,7 @@
 
 class LLTexLayerSet;
 class LLVoiceVisualizer;
-class LLHUDText;
+class LLHUDNameTag;
 class LLHUDEffectSpiral;
 class LLTexGlobalColor;
 class LLVOAvatarBoneInfo;
@@ -207,6 +207,15 @@
 	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 @@
 	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 @@
 	//--------------------------------------------------------------------
 public:
 	LLFrameTimer	mChatTimer;
-	LLPointer<LLHUDText> mNameText;
+	LLPointer<LLHUDNameTag> mNameText;
 private:
 	LLFrameTimer	mTimeVisible;
 	std::deque<LLChat> mChats;
diff -r b532610841b5 indra/newview/llvoicechannel.h
--- a/indra/newview/llvoicechannel.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llvoicechannel.h	Sun Sep 05 10:36:55 2010 +0100
@@ -76,6 +76,9 @@
 	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 -r b532610841b5 indra/newview/llvoicevivox.cpp
--- a/indra/newview/llvoicevivox.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llvoicevivox.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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::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::lookupName(const LLUUID &id)
 {
-	BOOL is_group = FALSE;
-	gCacheName->get(id, is_group, &LLVivoxVoiceClient::onAvatarNameLookup);
-}
-
-//static
-void LLVivoxVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
-{
-		std::string name = llformat("%s %s", first.c_str(), last.c_str());
-		LLVivoxVoiceClient::getInstance()->avatarNameResolved(id, name);
-	
+	LLAvatarNameCache::get(id,
+		boost::bind(&LLVivoxVoiceClient::onAvatarNameCache,
+			this, _1, _2));
+}
+
+void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id,
+										   const LLAvatarName& av_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 -r b532610841b5 indra/newview/llvoicevivox.h
--- a/indra/newview/llvoicevivox.h	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/llvoicevivox.h	Sun Sep 05 10:36:55 2010 +0100
@@ -45,7 +45,7 @@
 #endif
 #include "llvoiceclient.h"
 
-
+class LLAvatarName;
 class LLVivoxVoiceAccountProvisionResponder;
 class LLVivoxVoiceClientMuteListObserver;
 class LLVivoxVoiceClientFriendsObserver;	
@@ -649,7 +649,7 @@
 	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 -r b532610841b5 indra/newview/pipeline.cpp
--- a/indra/newview/pipeline.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/pipeline.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
 	}
 
 	LLHUDText::shiftAll(offset);
+	LLHUDNameTag::shiftAll(offset);
 	display_update_camera();
 }
 
@@ -5327,7 +5330,8 @@
 		++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 -r b532610841b5 indra/newview/skins/default/colors.xml
--- a/indra/newview/skins/default/colors.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/colors.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -118,9 +118,6 @@
      name="AlertTextColor"
      value="0.58 0.66 0.84 1" />
     <color
-     name="AvatarNameColor"
-     reference="White" />
-    <color
      name="AvatarListItemIconDefaultColor"
      reference="White" />
     <color
@@ -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" />
@@ -565,6 +594,9 @@
      name="NotifyTextColor"
      reference="White" />
     <color
+     name="ObjectBubbleColor"
+     reference="DkGray_66" />
+    <color
      name="ObjectChatColor"
      reference="EmphasisColor" />
     <color
diff -r b532610841b5 indra/newview/skins/default/textures/Rounded_Rect.png
Binary file indra/newview/skins/default/textures/Rounded_Rect.png has changed
diff -r b532610841b5 indra/newview/skins/default/textures/icons/Person_Check.png
Binary file indra/newview/skins/default/textures/icons/Person_Check.png has changed
diff -r b532610841b5 indra/newview/skins/default/textures/icons/Person_Star.png
Binary file indra/newview/skins/default/textures/icons/Person_Star.png has changed
diff -r b532610841b5 indra/newview/skins/default/textures/textures.xml
--- a/indra/newview/skins/default/textures/textures.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/textures/textures.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -358,6 +358,8 @@
   <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 @@
 
   <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 -r b532610841b5 indra/newview/skins/default/xui/da/floater_windlight_options.xml
--- a/indra/newview/skins/default/xui/da/floater_windlight_options.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/da/floater_windlight_options.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/da/panel_classified_info.xml
--- a/indra/newview/skins/default/xui/da/panel_classified_info.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/da/panel_classified_info.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/floater_about_land.xml
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
              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 @@
              right="-10"
              name="Cancel Land Sale"
              left_pad="5"
-             top_pad="-25"
+             top_pad="-15"
              width="180" />
             <text
              type="string"
@@ -541,7 +543,7 @@
              layout="topleft"
              left_delta="0"
              name="Reclaim Land..."
-             top_delta="-61"
+             top_delta="-50"
              width="180" />
             <button
              enabled="false"
diff -r b532610841b5 indra/newview/skins/default/xui/en/floater_avatar_picker.xml
--- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/floater_bumps.xml
--- a/indra/newview/skins/default/xui/en/floater_bumps.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_bumps.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/floater_buy_land.xml
--- a/indra/newview/skins/default/xui/en/floater_buy_land.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -569,7 +569,7 @@
          name="US$6.00/month,billedannually" />
     </combo_box>
     <locate
-     height="10"
+     height="5"
      layout="topleft" />
     <icon
      follows="top|left"
@@ -590,7 +590,7 @@
      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 @@
 This parcel is 512 m² of land.
     </text>
     <locate
-     height="10"
+     height="5"
      layout="topleft" />
     <icon
      follows="top|left"
@@ -654,7 +654,7 @@
      left_delta="0"
      name="currency_action"
      top_pad="9"
-     width="90">
+     width="95">
         Buy additional L$
     </text>
     <locate
diff -r b532610841b5 indra/newview/skins/default/xui/en/floater_buy_object.xml
--- a/indra/newview/skins/default/xui/en/floater_buy_object.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/floater_incoming_call.xml
--- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
--- a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/floater_pay.xml
--- a/indra/newview/skins/default/xui/en/floater_pay.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_pay.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/floater_pay_object.xml
--- a/indra/newview/skins/default/xui/en/floater_pay_object.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_pay_object.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/floater_report_abuse.xml
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -373,7 +373,6 @@
      height="23"
      layout="topleft"
      left_delta="0"
-     max_length="32"
      name="abuser_name_edit"
      top_pad="0"
      width="195" />
diff -r b532610841b5 indra/newview/skins/default/xui/en/floater_sell_land.xml
--- a/indra/newview/skins/default/xui/en/floater_sell_land.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_sell_land.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -164,7 +164,7 @@
      left_delta="0"
      name="sell_to_agent"
      top_pad="4"
-     width="130" />
+     width="170" />
     <button
      height="20"
      label="Select"
diff -r b532610841b5 indra/newview/skins/default/xui/en/floater_tools.xml
--- a/indra/newview/skins/default/xui/en/floater_tools.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
          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 @@
              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 @@
              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 @@
              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 @@
              text_color="White"
              length="1"
              follows="left|top"
-             left="10"
+             left_delta="0"
              top_pad="2"
              layout="topleft"
              name="E:"
@@ -1188,7 +1200,8 @@
              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 @@
              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 @@
             </text>
         </panel>
       </panel>
+      <!-- Object tab -->
       <panel
          border="false"
          follows="all"
@@ -2974,4 +2989,5 @@
          top_pad="4"
          width="125" />
  </panel>
+<!-- end of tabs -->
 </floater>
diff -r b532610841b5 indra/newview/skins/default/xui/en/inspect_avatar.xml
--- a/indra/newview/skins/default/xui/en/inspect_avatar.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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"
+     font="SansSerif"
+     height="20"
+     left="8"
+     name="user_name_small"
+     top="7"
+     text_color="White"
+     use_ellipses="true"
+     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_name"
-     top="10"
+     name="user_slid"
+     font="SansSerifSmall"
      text_color="White"
-     use_ellipses="true"
-     value="Grumpity ProductEngine"
-     width="175" />
+     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 -r b532610841b5 indra/newview/skins/default/xui/en/menu_viewer.xml
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/notifications.xml
--- a/indra/newview/skins/default/xui/en/notifications.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/notifications.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -257,7 +257,7 @@
    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 @@
    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 @@
    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 @@
    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>
   
 
@@ -2021,20 +2021,6 @@
   <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"
    name="AddFriendWithMessage"
    type="alertmodal">
 Friends can give permissions to track each other on the map and receive online status updates.
@@ -2128,7 +2114,7 @@
    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 @@
    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;?
@@ -3201,6 +3187,112 @@
 
   <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.
+
+During the evaluation period of this Project Viewer release, you are able to update your Display Name as frequently as you wish. When this feature goes officially live, you will able to update your Display Name only once a week.
+
+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="alertmodal.tga"
+ name="AgentDisplayNameSetInvalidUnicode"
+ type="alertmodal">
+    The display name you wish to set contains invalid characters.
+  </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"
    type="alertmodal">
 Offer a teleport to your location with the following message?
@@ -4516,14 +4608,14 @@
    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
@@ -4679,13 +4771,6 @@
 
   <notification
    icon="notifytip.tga"
-   name="OfferedCard"
-   type="notifytip">
-You have offered a calling card to [FIRST] [LAST]
-  </notification>
-
-  <notification
-   icon="notifytip.tga"
    name="UnableToBuyWhileDownloading"
    type="notifytip">
 Unable to buy while downloading object data.
@@ -4839,7 +4924,15 @@
 
   <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 +5034,7 @@
    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 +5699,7 @@
    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 +5929,7 @@
    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 +5937,7 @@
    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 +5945,7 @@
    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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_activeim_row.xml
--- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -71,7 +71,7 @@
 		top="10"
 		left_pad="10"
 		height="14"
-		width="255"
+		width="250"
 		length="1"
 		follows="right|left"
 		use_ellipses="true"
diff -r b532610841b5 indra/newview/skins/default/xui/en/panel_edit_profile.xml
--- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_group_general.xml
--- a/indra/newview/skins/default/xui/en/panel_group_general.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_group_general.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -33,7 +33,7 @@
      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 @@
      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 @@
     <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 @@
      layout="topleft"
      left="0"
      name="visible_members"
+     short_names="false" 
      top_pad="2">
         <name_list.columns
          label="Member"
diff -r b532610841b5 indra/newview/skins/default/xui/en/panel_group_roles.xml
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -85,6 +85,7 @@
              right="-1"
              multi_select="true"
              name="member_list"
+             short_names="false" 
              top_pad="5">
                 <name_list.columns
                  label="Member"
diff -r b532610841b5 indra/newview/skins/default/xui/en/panel_im_control_panel.xml
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -24,25 +24,15 @@
      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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_instant_message.xml
--- a/indra/newview/skins/default/xui/en/panel_instant_message.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -67,7 +67,7 @@
          top="8"
          use_ellipses="true"
          value="Erica Vader"
-         width="212" />
+         width="205" />
 	 <!-- TIME STAMP -->
         <text
         font="SansSerifSmall"
diff -r b532610841b5 indra/newview/skins/default/xui/en/panel_landmarks.xml
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_login.xml
--- a/indra/newview/skins/default/xui/en/panel_login.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_login.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -65,12 +65,13 @@
 <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 @@
 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 @@
 top="12"
 right="-10"
 name="create_new_account_text"
-  width="180">
+  width="200">
        Sign up
  </text>
 <text
@@ -184,8 +185,8 @@
 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 @@
 name="login_help"
 top_pad="2"
 right="-10"
-    width="180">
+    width="200">
        Need help logging in?   </text>
 <!--  <text
     follows="right|bottom"
diff -r b532610841b5 indra/newview/skins/default/xui/en/panel_my_profile.xml
--- a/indra/newview/skins/default/xui/en/panel_my_profile.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_outfit_edit.xml
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -57,6 +57,7 @@
     <string
      name="replace_body_part"
      value="Click to replace your existing shape"/>
+  
 
     <button
      follows="top|left"
@@ -197,19 +198,19 @@
                  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 @@
                     <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 @@
                      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 @@
                     
                 </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 @@
              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 @@
 	         top_pad="5"
 	         width="130" />
 
-        </layout_panel>
+       </layout_panel>
     </layout_stack>
 
 
@@ -461,15 +462,15 @@
          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 @@
          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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_people.xml
--- a/indra/newview/skins/default/xui/en/panel_people.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_people.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -81,7 +81,7 @@
      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 @@
         </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 @@
         </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 @@
         </panel>
         <panel
          background_opaque="true"
-         background_visible="true"
+       background_visible="true"
          bg_alpha_color="DkGray"
          bg_opaque_color="DkGray"
          follows="all"
diff -r b532610841b5 indra/newview/skins/default/xui/en/panel_place_profile.xml
--- a/indra/newview/skins/default/xui/en/panel_place_profile.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -125,6 +125,7 @@
      left_pad="30"
      name="first_person_avatar_visible"
      width="256" />
+   
     <check_box
      control_name="ArrowKeysAlwaysMove"
      follows="left|top"
@@ -206,7 +207,7 @@
    left="80"
    name="UI Size:"
    top_pad="25"
-   width="160">
+   width="300">
     UI size
   </text>
   <slider
@@ -302,6 +303,7 @@
      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 @@
  label="Other Devices"
  left="30"
  name="joystick_setup_button"
- top="27"
+ top_pad="27"
  width="155">
     <button.commit_callback
      function="Floater.Show"
diff -r b532610841b5 indra/newview/skins/default/xui/en/panel_preferences_general.xml
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_preferences_setup.xml
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_profile.xml
--- a/indra/newview/skins/default/xui/en/panel_profile.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_profile_view.xml
--- a/indra/newview/skins/default/xui/en/panel_profile_view.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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="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="26"
+      height="27"
       layout="topleft"
-      left_pad="5"
+      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 -r b532610841b5 indra/newview/skins/default/xui/en/panel_region_debug.xml
--- a/indra/newview/skins/default/xui/en/panel_region_debug.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_region_debug.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -103,7 +103,7 @@
      mouse_opaque="false"
      name="target_avatar_name"
      top_delta="-2"
-     width="180">
+     width="270">
         (none)
     </line_editor>
     <button
diff -r b532610841b5 indra/newview/skins/default/xui/en/panel_region_estate.xml
--- a/indra/newview/skins/default/xui/en/panel_region_estate.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/sidepanel_item_info.xml
--- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/sidepanel_task_info.xml
--- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/en/strings.xml
--- a/indra/newview/skins/default/xui/en/strings.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/strings.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 @@
     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 @@
   <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 -r b532610841b5 indra/newview/skins/default/xui/en/widgets/inspector.xml
--- a/indra/newview/skins/default/xui/en/widgets/inspector.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/en/widgets/inspector.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/skins/default/xui/es/notifications.xml
--- a/indra/newview/skins/default/xui/es/notifications.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/es/notifications.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -1419,7 +1419,7 @@
 	</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 @@
 		</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 @@
 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 @@
 	<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 -r b532610841b5 indra/newview/skins/default/xui/fr/notifications.xml
--- a/indra/newview/skins/default/xui/fr/notifications.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/fr/notifications.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -178,7 +178,7 @@
 	<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 -r b532610841b5 indra/newview/skins/default/xui/ja/panel_group_land_money.xml
--- a/indra/newview/skins/default/xui/ja/panel_group_land_money.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/ja/panel_group_land_money.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -48,7 +48,7 @@
 			あなたの貢献：
 		</text>
 		<text name="your_contribution_units">
-			m²
+			平方メートル
 		</text>
 		<text name="your_contribution_max_value">
 			（最大 [AMOUNT]）
diff -r b532610841b5 indra/newview/skins/default/xui/ja/panel_group_roles.xml
--- a/indra/newview/skins/default/xui/ja/panel_group_roles.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/ja/panel_group_roles.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -20,7 +20,7 @@
 			<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 @@
 			<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 -r b532610841b5 indra/newview/skins/default/xui/pt/strings.xml
--- a/indra/newview/skins/default/xui/pt/strings.xml	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/skins/default/xui/pt/strings.xml	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 indra/newview/tests/lldateutil_test.cpp
--- a/indra/newview/tests/lldateutil_test.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/newview/tests/lldateutil_test.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -183,4 +183,14 @@
 			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 -r b532610841b5 indra/viewer_components/login/tests/lllogin_test.cpp
--- a/indra/viewer_components/login/tests/lllogin_test.cpp	Thu Sep 02 11:27:52 2010 +0100
+++ b/indra/viewer_components/login/tests/lllogin_test.cpp	Sun Sep 05 10:36:55 2010 +0100
@@ -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 -r b532610841b5 scripts/messages/message_template.msg
--- a/scripts/messages/message_template.msg	Thu Sep 02 11:27:52 2010 +0100
+++ b/scripts/messages/message_template.msg	Sun Sep 05 10:36:55 2010 +0100
@@ -6812,6 +6812,19 @@
 		{	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 @@
 		{	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 @@
 		{	InvType			S8	}
 		{	Name			Variable	1	}
 		{	Description		Variable	1	}
-	}
-}
+
+	}
+}
+
diff -r b532610841b5 viewer-hg-convert.shamap
--- a/viewer-hg-convert.shamap	Thu Sep 02 11:27:52 2010 +0100
+++ b/viewer-hg-convert.shamap	Sun Sep 05 10:36:55 2010 +0100
@@ -14430,3 +14430,374 @@
 f84f5fca57946f838e79a59be20dffe407e9d3a7 edb3d5536c38643633925215404f2f02350f37d4
 426780dc180359b13f72bb6a259f9c4effe88cf9 fe1a7607de6ce5c3dedf96907e114ca0a208076a
 edef0997a11b5e3bc1c82cce0509e0d57bdde64b 6b93a09d0cdf42d7cee85979de6d7b18e34f6dd1
+e975026f2ec23d0cf56ff51adb60293e8fb4f4b6 a6250fa92374d84353e5d80d38bafc0a315a9d71
+66dccffd8fd117621f0d6ea65bc2f9e59c56b9f4 cfd06c62a3cb1ccc1b247a0c59d1cd3cc2f0f9d7
+7a3b14bb7f45704aa801bd8ac519b7177efb518e 2e9065e5172f87a30c55d04b5813de58e7355571
+4b0baed97e2042678959144f00ad6e2e34cc5e53 13a94d2bf6a186f6a075a9d3359c89d460ab1255
+3c0d907964e7e2308adaab87e07e7cf9e7d2b609 ded2549235de0fc47db47e0d0c9c840f26aedd67
+59bcd34c7fbdee27937b7f2b937b8e87f3384b2b f3b3013a7a6b3d89ce42019e70927171e702529a
+02fd12ba8904365e8c93b560f32d061dc2cca0a3 7d676a2c485e603a86df6aae03f8483cb42cd85e
+27461002613dc72f8380e506309b865eaef01da1 3622307cf11a8d0e1188ee14fef6904ad647c2b1
+a2697da70169a25e52d96f79602c9b3a68974420 a8a4230a0068c9ecae1426f1b573403e8b1285a2
+3eaeefeb0b3d3b22a8c1870312559d82fc8a55b2 f45674eac589150df9db2c371d79b2df76c07856
+8d558da227dd0511e148ed397ce548eba470188f 87241918ddecf6effa0bab99464c59b317ff160f
+100f8460b1edcb70fc101a569d6c97e2b1230420 ddf41f003dccb71b00e2e99befff7a47d3ec203b
+e7e185f4219faaa6120ea2df2566399a2e46c0bb b086a9f77fccb351b88802a2681d834e55aaa189
+ee7bf1dbca0b7f4803898fef34df4e880f30ae06 b4cd436bcdfd66615159ee9ab08356e3c5296e17
+8f9e3abdd00ae17883c3c342a729f80261d4ae7f 671ca1e312dee8ab6d01b1539f2e4060cb2f520c
+0940154965bec17a5a7c57b62dbc87eb2bd6b026 b2297afe9a31febda39d184343989080f6bd3bb4
+976e5fb71922b289e7fcccf5217333f6186e2c2d 63e8f72369808d61f2755d20c6967c140b3700e9
+af871859aa18ea6c51d29d3d25193255804bb988 ea21f74a74fd7ecc39dc62688abc0345e8e0e2d9
+f574a2376f0e892908af993de28a3c0e1f03b0a5 9cc6d1986c5b9e5e444e246648b2f6e18e8140c7
+33be702e47c359ccaeb47f251e10753fd173cc09 fbae0ece4ca3106bcf7888b8165da4d4c4afe988
+d3914405e1efae0e97012bf2705dd19a366e098d b0ed0ee20e569e6d0f942af98bb3b899f807bae8
+175847f4f9d64d23d48eabcf823e20039aa61f2c b0ed0ee20e569e6d0f942af98bb3b899f807bae8
+b8ac324851c4d87bc5c30778ec4c2668655382e7 004eb75cf1df1d92779ec521ab61dbd2987de3f6
+2c2bdef102b368fd946d08cffd37598ba1393845 d367560e16868475d6ccd57f30f0c9ecc853f789
+b263e390c8681904f2d9f3b7b73dce0c210bb681 dbdbd8c0790fa9231e9905ca30d64875180a1474
+5fbb87e35fe177a82b189f2b8e3afea3cb81db7b 4ae7ed1c18df89bf7a979f4c53c29fc465abf1dd
+13d79fcd2e8364c1b752d2d9939af6ff2220d126 3be181a6e267c3389585aef15cf8a18733cabe80
+e55a8f5973d51b81d27a6aba595d25daf50d4081 41c7a2587c9a407a9d2ad74e19990c4f5f651878
+e579e2d109671233536fdf5c408a7fc323167612 ee5f3a175dee6314ba5d5c7d6cbd8f29c45b4b25
+6d28ea5d8dc64e7dfb88454b6ddf1857381518e1 bdbc81608b436a22aa2bc7aba98c7f8302ea932a
+8f549fb9a79004ea31aa6bd3b519c7e514f8af5c aba8153c6777eee6dc2fbccd9d8846462464ec76
+7b1a8e8ac069860c1524c893bcc7f5ef91331759 5965388c8d4e3f9b106df45a142e93dfa358f088
+27e2b287789a0bfb273e275ef1ef98eaab50e59a 2ae1b808ca4ac0f2f13da5d2a23dac9aba0e3f19
+71ce9e017172d81f30a32fd57b143bfcd2164498 dc7b36d659fc3a613814ca9dd36343644ef9c03f
+6b294e7a90a05f2346cbc3863ee42f5b06dad83e 596c9e8705dead535207af7556e2c804bef28c8e
+e7751db4c5d8dfe7ab6bcb9075e7cf56076b8429 d312abb22dc4f60000181791c07a6ec5e64c809b
+9d03e83e5236479deb363518bbdae61e11aff336 79b19b9fcddf71f38a140c84fd37017d2b6f23fe
+6894440ad84422dee7b1c88ea204e691733aa528 bdba694a85657106ae06ed56f61f49cc758446ff
+39abe1ae422bf334c473ba27866308d1e9eb0261 9d99011ce01792445e904810f241ecc03cdea190
+303b79b2a44e5f3f16208491ea1d81927d413b4e 60417031bc518dfa8f59174ecc16b22e03e71e9d
+e90e4d247fc3128751ca9e58f57205037b458240 9bfc5c1f0d3d9ec67483f4acacd51948ae49f7b1
+51aa09a7ac5522cc8526034cb01fab99c64a2651 01f29c1066d268a60f9f44d47e5d23350068322b
+f699bd97323753889324eb404710b3ec83011b68 350101cbf33d593f20fc91ceea3e5a33e187843f
+1c097c30a5d71062293d491587d28bef66708bac 334ed3e360b382d204c4fec9580e62b52dce3cae
+8ca7e5e109134556f700d1cf83df93bc113df38a 2828f6dcb82eda30e86350d55db5f5837e41205a
+92dc2153c6197a4500a6bc711c555ff57dfd560e 5ccd26b9fe10941cafd1556a8957aa0e2efa3585
+27b9e03596868e47c1f8d32ac0b8d1a88a810063 8ac8f11bcb1832babe928e79e1466dde7e0015ea
+8c75569284e12e011ffb9a183e51c8410ab6c7fa 65ceb1bf482e7598884f82fd31ccc64940d9dd49
+f999f1dc139cf21ffacb3153dce695bbafafdb42 c9e5e8f9ad7c11d5f66ae8d2c2356eecf358b4cb
+1e7e5b57bbfb317133f9b4523ea98da4a810ecfb 133c44ca83927ed704678d68a11336cd08371ac8
+f682a56e2d71e5437b5026b338ada5df55e1ec06 174afef38387b2439185c058658288a1f8917ff0
+c35b2b4805c534c4b21520e2e5ad98fdc4db875b 7b7ce9a83a7f8afd844c39926f2df1edd9f4ebcc
+0c342e52eecdb6a14919d3f83702a68c66ee88db 88998d08363226f829922e525ead0886dda79841
+30a7a8317615782a28b01f83284220256a416b81 79b8c9d5577ded2090853cfb1dcb050099b2cecf
+10f43d553c815e66398275b7adf13304191b8192 7298dea19e254d0632202615e90a9525db660f4a
+4a2a83aaa2a8e1a0bcf0a545a44f98e6565676a0 571446322682f5e60431828ef502ec18e39e05a3
+ed475e19fb6aed995a3095da07ec505f58ebeedf 83e1d4051c116b6e10364824e3d3706aef212936
+5791ebd046db07b57517bd00e448788b231eac62 6dd859ba9f0691a5e620b313ded7c586d96129a1
+06466bfaaddd404787242572d22677f0e305f1c9 22b85add1e01bc199b44a305cb4cff19203480a6
+e1a652e2b865a9d9897f97465f04577934540648 55d57bcdb4402cf5f4e40a4cb39ce33e13d4db52
+b135459bb151a98ec0b22777c10876a074e4dcaa 8b09aa48746cee71ca3212a3070f1309bc7adc90
+bc2a41c01058795f9aafd0cbf6e288cda5c96cfe 11632b762887cb5ede8eb24a84ba7a0f54e5d6b1
+aefe65e3b803411a55efc98fa0dc8fa108b5f062 cccb6fe04ace38c618ea86f4f3ff44c49da41c7a
+cf03a1f97ac22bfc1e7b63e49578428da5901c1c 9358c4daecc13b6560ac4943ef430727b9d6f7cf
+21384752c01021bdf71e9103187768c8537de5cf 477394988faf20927fe8dba227d9dd504b28c4de
+571d8ae2235e379a1f6dd54dbb9f99f85423c411 fe7c0ecc51ba3fef44e12fed1ef29d49a0b5137f
+241a62229266dba4701b4d50559fbe88d1818e59 ed2ceeee90cf89c9eac501fef796b223c13045da
+ca7ddef54b902db730b5743df7042c1dd0168986 79e8acde75292e5b0d1b36d4a30c475e591c1de3
+608b4f97a001d63ed6cfbdb5b2fef86ee2b5bf69 83c330f19792850dd0ca7cc4bf4e6deb4ef5f76d
+7ea46aa0a37dd968feeb14e76034dc79a43f7fad 7f3fc11e11949e80bad1a1ec0bd565e34bdad708
+8a6dc6e4bc7b1be7ab2b5e00822897a20f422897 c82c1dcea564b3337d5bbb137547454278d95787
+66aa8fd67b5646fd097c87fbefcf8908e78ad408 84a18c758e973de1bae3f549a2d48b7607d6c198
+a847a05228794823327e04feaf7ba00699c41029 9490af626f73c520090f5892c049abc9dccf988f
+7dcd1736ae1d3f7da634176aa4030c76210f9944 4d8a8b9b5458a7785d859ea9f0360302134231fc
+9eac2ae8adf7c0bae1b4b6d6c1617e03abe7e302 084e52f5e5bef4f2bc02f758ffae4cce61680b83
+db0ffc9eb46ec0de9650a93ee628ce5cebbce88b 776a136cf7db10d72191159095b1e0da4c4ecc41
+c84be27e4be0bdbf42cf7217519d7241a82f1acf 944c1a7de790c980a619846b0d15de6c883fe350
+2a90cd1c685c1dc22bf347abad61f2c15c3aabdc 78a4287012381f64da6dfd16e559ea7c028c126a
+d84bb34a33be3834e754dc86062c634703021112 42372dc7c04f8e4efbaa81bf10c74ff1d09712cb
+d49c62d1be3cbbb31ce81d36bb386bf9e6a4e54a 42372dc7c04f8e4efbaa81bf10c74ff1d09712cb
+1e84c9ab07a8c5d65adcbd44cc5819a367fd75d4 34319c77948c045761fbebde098e421481d9e51f
+8bbde74429dfa41de70ea42e4d2efb9a177b8a36 d676f2a7b6a9e4ef7712fd328f966462b6c01a97
+a51fdbdbd6ffc32775d57701c72ed84e4c7f3acc c2c0e54380e8be22b80b5d277fdd1f2cd8076417
+edd8ab9104ae7402485f2a25bb101e68b6cd2505 5010572227cfac68fa618e227111824de3fe1415
+2f1c5e335fa1e21b6004e47c8669eb51bf40646f 52b8c32cde6c0093128dc2367140caa951a6f833
+ff1f4b6cef8365877b3610b8054b863a4a2e6ee3 463b8e28ec2229fcdf1645f7861bcb2e78504e42
+dcaa4ef93e13552ed40432bacdd79b715eb8aa46 4a191af5f67cd270900d0048ac5486176ab690c2
+416da45586d16eb6664138206a7484a97e6b2ddd 21e65b57a7489de898ef684b103bc40718ad1027
+324483b59f2ebeed453cb376573dc17422c967e5 24761bc2d4ee782545f36fc5f451f1bfa5eda7a5
+63c903bbbb9f8994359f5e3579b193997de14a34 478a308b8f139c1c236c9b356da6b18ac6160897
+2daee567b4b900eb27c38dc35497dd3b0a888d84 28c72a3d48cbd8b3ba16ae761996ce3b0f9e71e6
+fe58db66d5873bd77d3bb4172dc615b6aff02478 10751d5fc6cf3701477d5b47865a4afcab442b9d
+3f836d645cef4274f6204fb9edbd16475c40b1c9 545835237f13c937d29fb9e686e359d7df34dccd
+243cc58fe9a8e7d1ed97f3661736bae725ef3b44 6333a8e23dfd73ff03d422049ff731a59ec595f9
+d0332a8a2c496b108aeab6812277e81ec46980be f0598bcebf8d0794672567e6b7962175fff2f72f
+65035d057a050524cf0d96e69466e15e76f13b28 70e409e189b5edd3f93668f7e83235126a2d0a4f
+7c70cd6fed354b88b63daa07719ed977f30c83c5 1bac76a0e805e8d9339055227ee4ab467b7fe92f
+bb45eba2bca518667658858ddd25769088326347 ae42d6659a707d3573d0b99ccb18a1a42248296e
+83048f68f6d235f57ce95cbe35ac9376bc5a28b7 79ef06e2086c08c943f76ea99c4e4da0c4554f2c
+9195f506a6b2521d4737d36712d958242d47ff4c f701d0987407aeacd759ca0acc708f89e97205e5
+e79d74bb6184ca2a892ea657dbf755164d7fab1d 8c390ca9fa522f9d203af405193a057b6d2fbca4
+6f051897d5bdefdfed8b4501813af38d72454fb5 36cbde31518921654643e789ad78f8600b8d25ff
+9f8d0227ab38ff772ff712d4cda7b4a009f0cd59 30505fa0f4e3b7dd221774f03347768f45aff37b
+89b047185845fe5e6059ebc33a2dc62a4aac4b3b 51112c653a6c2eeec620e079f07d24e8cbdf0c90
+fead8f2e1ce1bd01585f65e187e05d4813dafcc2 bb94e4d608052e5e35b8623a684a4f7fdcb1b3cb
+18811ebc0e95ba3ffc9faa20bd9dc96aa1a14ee3 03d700c66cb257b36475ddce6743edeeeb9e59da
+64a1581a24aaa1f79d36a59e590febcba6a0282f 6f7e9e889bb2bfcdc4443ae55e7679d0fcc241e6
+4ec24ab623c0645cde31b76f80adb3a54b388081 c42c64d95a6ed18b8b45bfad477a04337ead43da
+972fa9f777271dbc663b94d76ff8294cc6e544cb 7847b6bc86ace4244aafc82535b90bb19db16260
+10b5411cbab28a31aa5d05132e317cabd2814155 04dfcdfc5342879eba9193c1a1c280871e44cd8d
+727da85430045ab9be950a66aec91e82153fca4b 9ad96d06e05f880c05bea282ab16df3cda269ae7
+181536a8410e24c26d56c56e4e02202830f65d6b 7847ec3dc260169adbc5948d93fc2c9cce6f10e3
+d355215859a86830e1bcad5907429fb3bf5b5377 7e8965721eaec9dbfdc5321fdfbfaf4f14b03f68
+1d16e58572c9f845fb17488a3836d8443967ca11 1868a0d7ce3f18cd2392b88992f106a628a4f973
+c7293fa82ab689e7d977a42f5842572f20a86b94 c8b8c02dce2d4690a212853635f71ceec9d4889f
+52bc038b3f71c2eb07f6e90222517f9837eadb55 c8b8c02dce2d4690a212853635f71ceec9d4889f
+f6c5ec32338599dd974c05eff729b1e0e21f3537 16cd734700bafa489c0079995733949b4f82422e
+fc5e955a11cd6760643cae269a84b9ec9a05c7bc db128831cc9045b5faa791eec9818275939a84c4
+48f050d962b16dcbad7c4133ac2106163c993280 c7e03e72aaa1cec06c77138d4a6a6e8eac16cacb
+0057fb0730ec8e1ea7e6e1b694be16f5f59e94cc 81ff96f535ba8b9002e3afffdeb0321e0079da95
+d061f0c76bc997d97315a5d5e2b4bc171325d5a6 d9a5cf2f9bbdc82ea89f11e1b5c7a970754f8191
+db4e63b381d98839f5b7eef8ed45cc3aec2803bd 205f3060d6654d044a0f8451d60168224125853b
+2ba920c6b890fec0aaec4592484c7c58f0afe05d a0ddcc16136a5f7989f3835b2f0744ab94f974ce
+84a447cf4554b5daf19bef1a34da6926804ac8a6 7e4269176596eb13ef5706e433b35033e3313730
+21f6555c2645ee967a0cf1d373ba73967e4da4ff 47ec383bfb1dfe713a05646a1d14dfe6a695aa99
+2b465b964a501e905bb76c2698d3216d5b8a7e85 c62e77fb255cd22f9bf346e5a0ce69f038c1802a
+242563cbb3e405594bc8d8e6b4cdd3695a3eb116 6855665fbc2736fd6d19423663daf6b612ed873b
+ba2cc5b3feacb1bd427c10df10cd4606a45ce46d 69f98f451fe4e49a8cc95636e936e324b3ba39a5
+57e8deed1754c797d1f4bc3257fc4ecec4f72381 0aae9a9b7d5e56c86d412a1b0bbfabbb394c1e55
+1661b05e868ec2302dd0eeabd374dcf300f55d6c a9ed7fac89f5bd419fd715cf7a3d8af28beaef2e
+e19f7ce8b667a334c95bc87f59ac9029b6b26990 dda04d9470473a690e09d4c24c1a6b4a007e6cf2
+f6127974f8c3ac3ec3c9667c8f4e442df7c26b78 e7628f6e722fcbd655a6e92d3dfc90092aa026ba
+172013ec9966ac57ffe789451d748f1ce268c420 6421b317cef15d54b0bff83c12bfde0e1aebbd90
+29a9f00a4e48d379e3a59ae2bd9ba43eede05337 f3702734ddd035721e5ad4bd7b1ae83d1885bc48
+224b8f9e727f42112dd5952005e730856cffe838 c543349aac02e3b1dbb5af8b3c4680bb7516350d
+36b9804f6b66dc742c11fbefd9e24a57c2cca8d1 8265ffe74fd92d73e85403b6ba583bd335a7642a
+a71012c45228968db36a871d92403bb564462b97 e2d40ed2f82753cef927cba254ebdcaf81b49f8b
+dab4605b1bf0d1a686109f4ed6e78f5fbbf1e9d5 f7a84f3af9a4fe9c06c587235858ca86d49d241a
+f3e52086c5133f7935464191ae022b49d1cd93ea 527133079cd656d6fd90f77daec8a93678962afc
+971d4b0c9f1a0690d076275a716bc02f272ee62f dd60cc12c3039920eb0eff0d2259eff0af25b304
+42e14ac94026769259af54a183850e6eb975dc64 4c2f81f0bd4c5e94d3fc69bc8fec0c193dd3bbe7
+8cad2e5be6325926e0c824069041b2e870bf52bf 1248724a14280b7c48dff9f854cea469a0696bea
+560c3b8785188a77d816e0eb9ed0b87a27ade565 ff353e408c619e6bced6bd74bceea5eaf9070ce4
+a86cb0e7c5cfbce2a1864bef535373884ba0d65c 8ad454ce2d865f80dad857b92506365fd2a3e032
+22cb5cef36f6009b5dac6784d1b1d48af6fbbe25 fb2f44be8d6fd0c0b2a6c3065a99859afdb4d246
+ed2c132bb5b7025dae00e4c76a7650f6f99963ea bd7c5c5f4a1bf02993c6511b07b625406fcd987c
+17a15fe7b21c10d3371b18a8b0f3c1be500f6f60 686808099ed95cbe8cbf6f5cc1afe90d57212fb2
+0a69f7d189bf1576d6c762b784fefc2b3f327876 f4f8ac9826e27469c3811b54fa4d996c573e95f5
+dd583a2279dd27ff6eb3c514787cbf2aeb56f4e8 98f5a275f591735c5d4e8756aadb20fb57bd562f
+c351424acf21410d081ce8de62989f73f85a8c10 9cfb405637fe411aed751293d7797deb5a59d0d1
+c6c87576e743909b387ab09fe802e48ba5e3f0b4 e6f8f82feee38144e80977d395b0966e2a34a6da
+be03e0ebbb964637715f9008d3051ecc743cc3fe 9e35342b486cd7cf3eb6b147a9b3a88d10861a66
+76cb02070c6cb35ad2f1032155b1e883d1531c81 d7a4b984e121aaf61c86f8203189cdd0457f875e
+b5325710ac2a0c6a5f0718d5ba88998c70db4885 8a6676b74d57dbe5da11cb35089aa754549b1d9f
+0a5887ac3c2d719c036a271ba54b1a25a7a91f56 bfc158cd6bccc9c43e19f45c33aac583bac14cd5
+53abe24c9d53677965de02b8de701693ad446f13 bfc158cd6bccc9c43e19f45c33aac583bac14cd5
+baf2b13c06de58e5c5fc6dacaf8d95d4b88f7655 02410f4bb682eabb5d055ae9ff921650b3bd8066
+228546f536f8542bcd3fc03651a941d41fbdbd52 304371397edc16a4e0ed3e68af37a280fc87bdaf
+c001f33dff6b167e220a4afbe471091a5dee6d94 304371397edc16a4e0ed3e68af37a280fc87bdaf
+8d2ad62e42979c64b0a2aaae2b115ed788cd6f5a 3ec1f0a1c22aed15145d5751e0df8ee47e53d2b4
+5c99782b24433479b1780757eac57351c798fb41 7f3287bff4b1c7ac53e13affa29ab9a45818d300
+6544920f2f4429d32b8a87e61ef45009e2b84cac f255405b550f26176bce3a95645d49c5727b1ef2
+701082a8d2be28cc7daa9979c14bc893480c3de9 cb3935e607767584d72cbc893aacd47a285c3838
+9e78eb0e6eb97f32da222e20a0a4411496586412 c3fc5c0e25af262ec1e12d1ca4e8e86c71ad82ee
+e9b7efa29de0f9a1065627eae24dd91b349efa91 730f5bbeb25087b27b7c4ba343709b4f95bbc8c1
+1281ecc85abffca0c02a139dd8fe0b009a2624c2 4f3660701e9a199a7c4238061bd0783ec9097518
+d1922682dd4750be91f40001b13c994e15f81192 5f3e13484f1e7321261f6cbc9c7a9a0379f1f679
+259cafb0f743a870ee33695c0abe3c97c17e79fb 786393962bcec24e434e9df123e06e641c165ed4
+3cfeda894ef67211fb556fd540695865800fc79b dc250e4489c647d552d075319d38d746db065f0e
+74d0b8904ca9264571fbf86e12671fba827a7f3f 36f91bcad175c109bbdbfbcc7a2ff508f1937f66
+8b1c59cd65391782744ec8375f77354723345d78 2eb4f1ac885cb50194ef0867fa97580b85af93a0
+fafede892b43f2474cc57145d7d4e1112c225d30 21ed31a077ffb7e66d78ac2b63f00cab05905b96
+2ef79141b7c548055fa2602f8c759f98a6ffdf92 deccc38fda47fb3fd5fe93eeb86d6971f6f944e8
+f60486fb33a46f1129926acb87bd8db2fb092ac3 0dbda301dd0ec4e7713d3da3d32d4eb33b811b6f
+6b520fd4520fad57a6afe027908c2d025d2036c4 a98a934ef3adffd0c921a684ffa6564166d715b0
+0abe1bc81a96c95b07e18e40c1dcdb2198db669a a98a934ef3adffd0c921a684ffa6564166d715b0
+a5b2e3bf5aaf613fcdf6472c42b24893040e0653 a98a934ef3adffd0c921a684ffa6564166d715b0
+9270d7600d44686cc937680cfc06363232ffdb23 b5b3111011549114f1c914cc399b65fceb73740a
+bb51c2d339673a3cb4070559c7260865f1f5f0ea 9a8a8848cb30c33a134fcd9f67a915ef67896367
+a64bc47252b634a3e164d79b8536f9af298bbd37 a698d3c4f6fb233b07454a2819bc5c735d0e53de
+7518242ba2ef9b9ef67ff990f865e1c978278703 976d6aec4956fb9a0fa03b7c5a4dfd28ba9cac00
+2625103cb2e688dbcc2a2fc2ca73a00dc6d42336 9c2257478178a6e1eb30d0633f2c2b7d73f79471
+7030896c7d94e648372cd2748fdca92f08b4646a da63c2cc6f59a05c71f926b5f82adfe5f5e17428
+616752407247c0511e1f5d9ba325d8570b542ac3 f2e64d606dad48fdd494322d6040f6714723bfdb
+b5f5609af16a5bb18254e2e6cd2048d654a0492a ed1ea8be0ad51f6cc1c15a6c58449ffaeb57959f
+37e77bb4a9d58eb1ca444e79d83f5361ec4735cd 8b732c44c517e5c2c87c1e612b46769e7bfd3193
+327f071afc26ea9b89607d2264a74ec5832dd4f4 07e1e48457d4ef73bea8ab5befcbbe469f9b3749
+031bfa823714aeafa2dc479caa95984c0e9e9f9a 3fd3f47b750c8bfc06df9b35db21bd5f61862c8d
+ae9b8dad12e34919f8523a311a46acb93ee729eb 54f1a1738d5b2c86b10364ecaea7526871d1db0c
+e80e32b160e2ef65391bf9458c567cdf04eee0b2 69718305767139bf0989cda6e95186c3da99e4ec
+1e58888b0641c37ccaa5bdd8fb239d7fca3f2904 09a51a69232c85a1e6d28450642304eea1bfc10f
+ad9f74c0ec3cb79a332f0f380b66c961c476c8d2 9b61860449952c40c5aa26406c502706ba602a60
+32b5f244d110d5f33c7609db74451cb2954db4f2 5701d5fe36e5e6ffcd75322f8b6437b3c816afd0
+e965cbc8f4283e7e0b0e71ac8d8e1c6d66ce11e0 1b5c26a1b7a8ce0c9920dc27b9f858de710acacd
+ef5c156e6d834b994d03c491b345b4998f73f222 cbbdf0cb7959d9b19d2f0e569c3b8a89c13b5a3c
+3c6858f04b8587cb9ad2c3e4458384a67aff84b7 91a3f9dd8fdaf5dcabdafc31d769a8d179a09db2
+cf53ad9b489b705aa7469c867d645f00bb0db572 48a2ea489aa39f4693ffc7d4f8f2ed1c2b19f547
+3d49a941920272516cf986fdf8442f9bb1ca1ce4 06541e114a3014c8dae724f19ed0176a4e665b78
+6e8f28a229147ff3b4942310621f3846cf1e9849 9f4e73c21d9b97a56effae1e23cb1b12121bf719
+52aa65fdd414ab47390e2e0b38b296b190cb9e15 77367f92422d60468c58fbf9fef07a7b08baa035
+629e40b26146c0fa9d65a247c5cf820cea70d6f4 fe44dd618834af6971b8bc832aecd0603a4be5d0
+d6d0e691e72062cf1bacb21f0a116146d520495d 81cd45e1291c22801b7623dd6e8ccbf1b1713f05
+04108417b64f46c00eeff9b4ca91da3d479e12f1 d2be38fdba130a1a40e9e2bd5ebbe164c931b86c
+ffcdc7b40b0e2c033c2dfe7b6152dbe9e45d9642 ee3952cbaf190b696e871f0afde8f94a2ac86338
+0904b87ceb0c1f1baa7a8202fc7d26214abd160d e139292ee5efd985f6d0d4ca8f81b4e7de70ff01
+866ed854411b23420915a80579587f4cffb4df0e d4489559a88cbba824e80ebd579fd8c6c800f5d4
+929ade1d0619e798aab5461195ed49d0401e5243 a699382fdafd6a6b0ea887408bb77a5ab143e341
+e9e2186f808e5908a1e93ef7955c50aad9190f56 7e43225b378de143f729552032505a82084efd54
+ca3e6e2efe4b6feb575d487fa951f3219a33e246 9a4741ebafcab25360084c9bf9ef5ec6f7cefa2c
+d814e6735dacf5f261afc770497fbdd09c346444 996434fdeda7f22fcac86eafc067c90ffa24c5c2
+e51510803ee3651aad11bf57489f377b7a794dd8 d484945c2d2e9680064ed5fdd1c8297c3446eb94
+6db32c1a6ccecefbe9607ea77ed2f52bf0e459b8 91480ea9e0526fed7db57393c1bf6624113e1ac6
+44b20c17758c302619954f8fc276c0f154f546bb d453b6faccd7da86be8bc3b0a044373af20f7a9e
+81a71a96647fcd450d729dd35fcc3bbe36a35271 2effbde08719985e336f316ea8a9781003d962a9
+3e0cf194c4fbcfa15ed4b8507c1f55f198246e79 3ec2608589cfecb0c1cec8e26141d0c2625c2ceb
+510dd7642a0d36a2446ac78d9934ea67da8aaa0d bbb272c8379fc8812b37bacedf9b643ff88d2718
+8a3e7705787537eddbf8bab929c9e6314f188380 e291b919ad6f748e320a99ba90d6dbb93a103672
+93d662b4fe6b36122e15aeb3afa7dc775c1e7133 996480dd0fe7fc7d9307559b20cbbf965224b4e3
+c978c8f17d41ce4657aef6b38392afd8a874cc4e 714c0c0e325bd48471c5211750b26e8f7fe46eb4
+943fb6a1c19e9f0bdc00caa0dc3a15ca4017368e d48e2b8c4b41122d0702d00dd09e0f20293d298c
+d151831aa0ba06fa0881a7c708908b08ce83d333 aa21e1b0d6ef672c84018d522b42f9a1c13a4f3a
+8f1e31afedfe5012b549583bd44cb1ec72477745 1f0f7bdc489dbadfb76e7476ead4bcd74cf65249
+1432a234e29cba17dac71d2bb85542e6059b5d08 5577554418a91890133c83c42f2707b57085b217
+246f21f4f48f0cb0bbada7266cbc219c34162a51 2769faacf41872735de41fbefbd13e252a08bc2e
+8ff7edb70fb6090bca458540d681a7032a48fb82 1b3190cc3363b9a24a44ccd04867c361fd54a39c
+0c23687b000260423026e694250d0b39abafe762 34bb555b900b22e8ad4e30f21fe340854c69669c
+7683b50d300fb35f042a80b46ceba0b32dc4241c 75ef0db627f8afde1e80c62a49a1a77938f1a3fb
+0430242156ced9f76b4ce47cfc8e5db2a0215a70 ca5ccde213d6744fa4a029ce8ed15fab3d9d27b9
+7fe732dd446923cc24d5bee656defb9b94adeb4d f94894f92e354fed31f215b9bcef13bed2f26a47
+cba6f7ec58e4bdd599a2df39eac15f729c879eeb e2a66892d1a6dcbdda8f9d6da6e2299972618e27
+b7c66289dcd0f9c1085eec4aa9b7331acc8ac75f bd140577b0fe56179ea38e1f378f7a2b59849f27
+fe15771f8d179c15c7992cc6647c15707aae6bc9 2a6e219adbd64270285f2c65bbfe697b59cd5901
+55f978cf7da82f1e4ec7fe4619b8829f91154e5d 049b41eb6951536ddf6416d40c307c0fd3a0a7a4
+dfef76b0de4b9146017cc97fa1795d18461b6469 f920a151780198f611eb417f350c0f27b67a8934
+22d473ed191d613a1cefe9c107630b058aebf9f2 d8b9d74aae5e4ac41953cf7e10639a54a6d01081
+1284c4b409000e23c4616b23247deabe95328f04 382eb9d13d8e793cdac35c9c560b3570e719ad24
+92bf7410a6ebd7f226e1787d28b5cc7d38360566 9c3d03ccc0814827e974b435ba3fff8f69652792
+8192473845912f21a48127f5f121bce6c43a5031 4ccb03c83c23aea10a924492a9ac04cebf7860b2
+8d05c834e3776caefea1f41ee96fc7266d5477b1 de3342d3a31d3286fed6bb49bd34b8f40f925c61
+efe26699180d0ec25fa3247999e18afe3b6ca223 5f07335f2ba560a1346c664ef63ac8af12f13d61
+bf6940aeed99a6dabf5ff126b42eefac8f1c030b 5d60fd16315e89b3f223b10fe23b21cc8a461e63
+39c5579bc870db6708a28934bc32ea6448d54ee0 9dad37bbc5f254e3a20e6b04bc212ea41cc9ffcc
+2c84cf07ae8d8da36cea54a22089a52bf39d0a85 ab4af8a7c257130bfe842d99836053847b941c3f
+f00c996e4ea680a3094bf5b9ac41fee6584c73c7 8566d4a80f5bdbaf7bfaeb985dd792302b57b6c2
+24e43a0644f76cc8d32845213a7cbebbc23e425d 828b4c34e19fa4947345798653ae11f07a5b5351
+c394f4e78595401f114c871f61de997c7cb2c6b3 c11fc04406f6763f190684e350a210394ac6e30e
+537d09b50f7a8e5c73216f9e68927128acdcf54b fbb6ead7cabc056201129a7ba9391046668adb15
+f76dd253ca4ca1c164c8228bfdeffa238b53a429 37e3c80d82977f9de019a46af06f31ff10b0b432
+1fab965fd81accd9801ad44455b0bf969486a9b0 0e3d77359b543b19532b6518c6a0805a32419dbb
+a44f290722ce4b88cb9de7337ab0256cf0b41d68 59e81b029c15032bb2bf4c31a6cf11dc6a264f0e
+3610fabe2a2b969adc8e8b3cb95f1f609b3b7533 80bf8b15d97e12a737c315de9e4de54d31e689fc
+27f664400117387a6af70e274b20c06f6ef8df79 40b888d1800edd11db7362ac3844d79f6ab3d7c7
+af8b804cdb9238beb2ac2fe9e27aea1e7f1734f2 0300446b133e9a5c51470641062bed806789de1f
+4eae07797fa7ddf59b091e664a76e77b6dd0ef86 1444fee60b3136abc0d7b1d6a3625d09e7615c5d
+dc1aca5bf7c62d2bd1200722fc216f95dcdf152c e3ff4cc9bd0038b9c139a5e0385096957b339638
+f588d547cfc955fec521dd8d78ecc93c0e196cf3 6e2c0cccad2670f9fa469802190318c8de506415
+384317b9a4232a0df7c2950bfd718821615cf0c2 615666b34e3208724dbda301d33c461880843d70
+2f307dc5af8f8f9f93f8618c5216b12f9a73b81a c9752733b14d75046c32034d59eff43272a18b13
+7b50a80f413588fa7b39c777e507d7cc87ef284e 94f9472fd0c4b9a89d072f37cdd81c5ae5370a2e
+65ffd5a5db3a39d7449ad04b5e811c719944ea78 d57597c3a10f7d2bdd285ff46a57c13032455fc9
+a1ac1a90dda50ad4522d58a692b7d38182b81248 8f840381ada3481335008fe82c6f95930a7caf76
+23aa79bd72afe47b304a58ab1059b8d882d74767 cf7444a23d179cb06813f0fac1d5c1731ccde305
+903688af107c5f9c4cf6263fb80ec733c4444c3d 8853ae84bdf7c565209a510bdeb495781e48fbc8
+09905c5d4a471783e05bd69741f58cda2f0bbd7f 67af7c8a570db6a2d2c9248aad6c69f134adb497
+28a470ad71d1a31e6c3c46e84207e471a3ea6020 2ac43e29c08ab54a7a2923c126164a997e331af8
+ff8a3a11ca26ba30ccee6c50d8c2bcf6fab724f0 c40c37b5d46c759b2f11992bbb414ee905e3d245
+fa565fbd994edbaad72d947f2517907c77e0ea89 e621f4c28dbb352b9f567c32565857f0f86bd07e
+65e7feeef7fe73ff06e387d845a985471c930c1a a0a4ff52dcccb831729061c5e7153f24c7e76418
+6f9c26f707d72cb6d74277669b6ea4a15c192d68 fee586e78f33304675053841639ba85de054645e
+0d7b0166e40c5f95c31972e9311c129615c7b1ee daae08036a5e84e31e775a0d3c4a87d9759cf8b0
+4fcb500a2aa588a47937500f32ecd3c9fb87ef59 3bd22a45d28138b026ed35e34a851e898a09bf07
+a8e57e05d9ed058d918a3ccceaba1814c5e56f81 9a1ec4eb469f4a91227eff08dc3e775f3411f3a0
+60e120f0e278713dfe1f7e7ad4724545c9d6990c 5acad4093229acf26af312e26a73cd1e4c65f788
+5ecd01fe91da59cce4c645a1365c9fd692fe9f9d c0ae3c411f4a2bb75166df6e6c284c117501f7ab
+8af4dc094c80909917da5d2881a7a27e859ed9e0 06fb8916d2d7be6c52f1a3585540e340b447689c
+8eab64c08f34c86372e7b514bcb86da534ae1beb 8c9d711a3e2d374bd1a65b6a41e9b0a852db9fed
+6573a5a8a192b7f1bca527e6251ba6a33b99e9bd 8cf47d25d93bbc11bf86d70129aba84e015436d4
+020f85e2747dfb604b7a3a68b3b55bb2db53045b 39a3cdc698ddef8643eb489e088ca7b5361dd74f
+849511cf6f1eaac930b841392598a6b0cb424844 dfb4659b960352065bf79bf1d1b958b36c8725e5
+553604c238ef656871da2e826f99a2b2387dbfd4 994d1a11f7e387cd079a3ae88a805c7f186a7728
+7d9e7588da4b2713ae9fe92a66d6cf4eb23a93bb 8d0115ef58ffbe94f9dd61b4459b64490254c90c
+10e2a288304a10821d5179e413427b99e37c11e4 1cd0f032f262e27a4a5c82e1830b7d1e5934c4b5
+466948a7a6757783171fadadb5abedb160e3e649 835e6cbae7115acb825fc4f1edc7cc458ed96525
+dad8eed55bd0b981ed0a339139a0c73cd09b4ee4 39c249630afe0d5641da4f073ec87e6b506712ac
+880096665e91644e46e578fcab87e7106a0774ae a93dc1c879efe08c5825a7fbd6ec5504d2285479
+7e16444d4f5efaef5837e92a16a28d6759716b7e 68c8448cb6602e37d77eb0a0aa8fe13996d64700
+ea8b903b110b16b1b5ca5e0a2ced7bf493d92a64 76a6f0bf5aef1a4272292cd5c623c4d3dcb8630c
+4fec39876ab5fd680993215389bcd89e0474823d 51bd2fa52d837a905120b95316f424d95b6de85d
+ca06291fd20689e803a19166c3b9c5dd6afb77ae 7a9df79c496686f5ea99aa8242e2a4b5f1ae7ca0
+1cb42a748ff4c67b70be557fb9ab6e48e1bb4c51 39ef85cb5945bd35b9148479d8337a154644d3e2
+7eeb068bc71a5d75043e1359290ddfd2b6ec6428 c09a5450bebba3c8841c6da3f575fc8a33993ee9
+c24608f25b3e2b1dabb659511117c475e7040d75 90f5b0301d613bc234faa4340746f8226e57e349
+cf0657b3d632793cb0725766ba7f7ba4a9d56d73 23031b5065fd603f31f175dad5d1f68ebe66465c
+fdcada2a654a852e162c7cd05f4957b33cbc8ee2 dc73cdd6eb49c9584e5f1420a6a31036b2f93966
+4503d100f8de74ab5d82e69d99eb88a276c18b66 cb223ea24f72f9dbbe30a8e0f9a9238202ea24bf
+cfe9cd208c53e35b54e5dcb3bbab70480e053f0a 5edf0b2d6e081da9cf0691ebd5ceed14308075ec
+a174edc8c89bcf84fdefa91a74d55d874855c13d d6cbf8c6abf016ab652054460d2ec54ab2eee6f7
+5b7bc0c2f3238a2ba18db03500d5c6c2f35b0e9f 1a08649c45b58a66b6862e5a6349a22ac3baad92
+2a7ab1414551ef9b35fa94495a522bd031e1313f ccbcfe82c451165a37b2991c5c8db200a6c14f7b
+aa159d98c8d7d89894bbed12b893bb8286df980c 416454f288976dae527bd278262996cff99f65d6
+90296aeccab8a4acc6428e34138ad6856034748a 1fc21a434ac4bd787ddc9c38d9f298564a106d4f
+b953bf8192ce452f4d7fb73348307c89958457b2 f5679f1293197d5673a5d005a25303dea9dcba69
+46b1b76724579b86b4b3b098b12c135f875a3123 cd8f6a9c573aff38898049614bfb157510fd5c67
+2c12ed68531423f8f5160dd8370ece15b12ef6e1 b259df1ff62208b50042fdc614dd71ea3d4a3e1b
+ef81822d8452633f5c0df4fe69a9a37b81b12306 42f02d7eb73a2b902ec6b440610a1309768ba8f2
+e9f0c71c026a1bee9a590eeec164cf22f6001712 8822fb96fda54e33a75f2e9f6ca799ef78790dee
+4bb60687c0826bb52c53cceba3f0989fc0430218 6fb928d035faa3b6fbd87c4b181be5d9045597f1
+c885afa42b50c8aae7a77aa2855f11ce0dad816c 26852eb945c51ce9435e6fa03d8ba931a5c5b389
+858419c0784b8d7196c2be79672969726213b97e 41cd56a1ff85212573719b08828bd9e21e381d3a
+02f63e300c52c70794da39e1cd4892d79a7e2277 aa8d23ec2c63d453bca02a9f096a64fbf4c99b9b
+2d062ddad0209d881f2e02dd46770d039ef36a6c 590988fed11d328889202434762ec2558fb2e8a0
+a4e50af6dc20621bd9e4b1d922e8e3dba19b10af 4100ccf099c7eb967f23bbac547f6fb424d5593c
+dcb7a730e8911953a29b70a611a1a55976036c87 b13d1d8dc224be84eedd234c00683d451fbd992e
+3473a7b27a7e4691f57a10a36de783803ce89c10 b54de647be7828787b1e0d6527339fe7620b9efe
+039fba4db247c021e18b080cf39d5448023240f7 69effa42fb5101007364c3aa92be9976864fe399
+864b803a21e8d05bcf8769fa4515e2be625e08fc da63507e9eadceda53a19f134f83e198bfc788b4
+75d6f66ba26c1883d20ffd8d2a5fcf7c30b56987 32f69511735924378e079e8cbce95853d55218ca
+323b74e803cfad1b0d4dcb752cb871cb359c783c 8f6fabd3519a99876358fec217a3981167ff2c48
+09b8c9f75f5a0e12d732ac2263c78be3ce8d1a67 675a14d18f75d3f7a75871ffd4ac7709db12ccc1
+06a3255dd5634406ddff42bc8e4dfcf88aa99147 70f6d5bd211c7818626c0b1b7469c5253fc61229
+9d248f7841180144b6c59483d165f2e220d85266 8aa27a2f5a943f876a17c69d9b9abfe07ffd23d5
+806f968dd79658f10b62629fe10dce5fd063c4df 6b7e58b232ea33ce3eba0cb359495f6552c09ef7
+6dfa525cc4df8d1bf209bf766ec4b592edb71aab add69d9d4892fffda7d908dfab4b7b6be756a51b
+4797a1ddab66b83c4a06e43d2ab646743590572e e20e4cfb58054352cd9f5ca27cff39a7865f827d
+9e539c23fdef67d6106c17f06cb89c66383a1552 97eb5f91ff238fcdf0630683ff87c39412789275
+6c519ce9907281cadd261ebcd9d9824acb76c26c 6529d7953b09cc9b27a312d7af79c2c85a04e354
+e6fe3e4822450f4bacc95696ca999afd5ffc7c2d 7474a1f7dadbcfdf87eedbf12c109141776191b4
+661e085a077a2cd9545c70d6321189c4e1935395 c189de52738974a12f0408333d7d3775f8bb49e7
+d8fb90bcaee5bebd9b894cfe97aa8f32f1277fb8 7dc5c9299f8bb9972000b8d10b73e3c40502e788
+7f5e4d3ea40b1fe2cd65c3d08341b76464591b51 2de1d5b61694c2a065632fcc48b6d4ca9c02a4d0
+77d5a678e9a4138a93cbbcbafa95a2638d3f0970 c6c03f447890ec203ff59420c4fe029bb1d22f18
+290dee064c1878668b25bb465ba90b36122eeef8 4076fa8d9101f0276bb2ff92253229baf7c370f3
+cc79d68db784d2953301c75ff40e649b67caf326 5ea3600258e631ea5cf492510495f5f08c5b163f
+96466504c293eab0753c9759ebc32410f54e38d6 6047d55343eea2927520f12293f7974bf8942a40
+0f866e8f6c90498eff4adc64cba52b33589e5459 d0cf303414d1ad9e3d6194ebb3d241fe32302c2c
+7f5967793458bb7cc3fe2759bfb8cc83bcd40e68 2153613214e476a6747d170fec90ef6c06a35cfc
+91e67e85420bd86b5e4cca72879755203c0614d0 8b2f7563400f8b8bbac0dfac18f6fd796d6157ce
+107fe46e77b1cbceee0550d5de89e9ef9e2f7789 9a554c894296e42a0dd6ffa86f4ada032d54353a
+ffbf120ea16d2754f5a0bcd997e4ad6c35d192ac 3cab9256a1f1c1ff2a768bfb99a8e0ca763d384b
+6de333be7616cc46e61491270e75cef4da52c70b d6b7d08f715f205cb38f767905f483a5609c6225
+cb89b8a70c46c53b70fef93dc699640f5368d0eb c95a8641fbc8e87f9fec17703b5101841909797b
+7df432f17574663ce7229ff3698d89de54f60bc0 e00653516de339059991c3248c4402f236f096fe
+2e2891df6476e64c705be28778a2ddb86c178518 b99723b3d0819d525c2b656bdb48754e21671a19
+f5894a9c0eb0112d7ecf765b7243052df8f73f5c 6dd0381a578564c5fb7d5a5c214737cf932cf243
+e8c58b6655a52762a07adc950ca3b9976650f864 bb94cf81b3edc23a49616b1b7110be3353051ee4
+2e645246e4708ddf6039c4e469b3f3cf40c4ae7e a377dd0842d72dfe90f43109e192a31bb6318fb0
+5e9baf57e6a36891a43a1d647f209fdb14d16587 8bbf44d6314f37560922c7c6d2b67b59d5d1b496
+53666a605f9b8f1f266a9bf3bd38664542f8e63a 6cd2f6bdac93b3205ceb2e0443ba354b4fc1f63f
+5ff52235796997bcf1d79ee04d3973e3e3a9a355 e376d6b35ac92cbcf30c742fca298e55899ab137
+e7fd284735a7a5eda25467017d9083e4edfe7edf be1ab370e57e7c544b7b9fdc567cd51ae74bfbbf
+da3545be15a096c18f6eb3f5b5ab43c69cbc0690 7c5e45780b196a042c1ac56c6c39ba37fdd140e3
+a986554af6a67340bd25fa3fca0848d07745ed2f c5a8e611aaaa8ea792192a58085aad098fe65448
+fe4076c7c05ac31d239a3304a8e7afd8c09b3289 10dc6474871cf59eec6128e2f1cc6d2d6fc45ce1
+b887a4a41dabcb0d5cd46c33bfa992519a3c52bc bc657a3304da0afab91fd9723be78f9fc14f2b01
+4fd00b3d25604d6b5746f9dae0db78ceecc8a4a9 f3d29f365ae4fbbe6082aaf636aa463bdefd769d
+ad14aa1d94a92e570d4e2d28b5a174488ee6ac83 2a17e7293c6819adfbd65d7a918321c90f6630cf
+5c6de8c98f366336b612ea1fae299cf8ac6a3458 957c8d5dce7238673db0ac6f7693e4372a7d199b
+6fd7200401f02e63f110c08c7ee8c47f1e624650 43165cedd36f0df30bd0ce34cdc8938dfc791562
+e4e1ffa7c08d80a53f977d66be18b49aa796700f 0276c9cd2202c63cfc9cd78449c98729b22c5cab
+3f6da1c3b36eec3504cf646b44d63ab69b4552a3 441ae273be41239b63198e5b7de98c5bdd498d15
+572fc7ad1b854e0743e39b5487a378733acd6275 b9279f8d94cfceaecb1137de098c0816299d17f7
+685e4d07438a09b2d494378a7660e3d0fbe7c51c 28ecbea20bad3dcf671c368cde6fe0090d2c0f9b
+0b0e3c1d3c6f6b4d941d6ddb2683a1bcf01ceaf8 69463ad570a0a69879d8bf613ea8c4a36b610c15
+d1ec40d311c7c0d21ce0199959a5c4a7016fb389 bb93876525916e7116b54e7af23334c1e1b62e29
+1afbd58ce07c1e59100c20dec3238878a07c8128 f10444f1a5fb3b19d4e6b353ce7e2251d5387a56
+2fe42b058aa75a6a5157500b906859146e689c4d b8e5b1ba6ac6182a5efd283eb62e3d3846e3cfa1
+0f6fc32adcf2154532970e7277f45267891ed321 1825eb47fbfd270c1b25f62c90c58ed8e485cfc5
+cb5b63acba38dbf3f38b8826aca7aded0b3d2d4d 64ea46825b6e1ae4d28b191e5e4c13260c2f1586
+5bb9f8487e2e804352c21484839b65a57c2dff7a ba4bdedaa46844de1d30a6674f22538048fa329a
+cd66ed79630f512fe005e8ada37bfcc1e00d53a1 7dae50aeadebd52c51222f7c6d15ea85e46ef119
+cd66ed79630f512fe005e8ada37bfcc1e00d53a1 10206014e497abfeec9cd22327d715f16ec0c5f4
