From ef0057909fcf7eaee6bdff4a58492fd17ffdd9a4 Mon Sep 17 00:00:00 2001
From: "Nyx (Neal Orman)" <nyx@lindenlab.com>
Date: Wed, 11 May 2011 12:19:36 -0400
Subject: SH-1522 FIX removed old debugging code that generated
 avatar_lad_log.txt

Old debugging code, should be very low risk to remove.
---
 indra/newview/llvoavatar.cpp | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 4767ba2bed..68637a7ed9 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5414,18 +5414,6 @@ BOOL LLVOAvatar::loadAvatar()
 		}
 	}
 
-	// Uncomment to enable avatar_lad.xml debugging. 
-	std::ofstream file;
-	file.open("avatar_lad.log");
-	for( LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam(); 
-	param;
-	param = (LLViewerVisualParam*) getNextVisualParam() )
-	{
-		param->getInfo()->toStream(file);
-		file << std::endl;
-	}
-
-	file.close();
 	
 	return TRUE;
 }
-- 
cgit v1.2.3


From 10d92237adca8bffc82c887dbd37b988602b2d59 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 15 Sep 2011 16:39:46 -0700
Subject: * Re-enabling outbox

---
 indra/newview/llinventorybridge.cpp    | 2 +-
 indra/newview/llsidepanelinventory.cpp | 2 +-
 indra/newview/llviewermedia.cpp        | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index a36aa3dedf..5482b07ce5 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -71,7 +71,7 @@
 #include "llwearablelist.h"
 
 // Marketplace outbox current disabled
-#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	0	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_PANEL
+#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_PANEL
 
 typedef std::pair<LLUUID, LLUUID> two_uuids_t;
 typedef std::list<two_uuids_t> two_uuids_list_t;
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index bd62b5c101..ec1de4af21 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -68,7 +68,7 @@ static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_
 #define AUTO_EXPAND_INBOX	0
 
 // Temporarily disabling the outbox until we straighten out the API
-#define ENABLE_MERCHANT_OUTBOX_PANEL		0	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+#define ENABLE_MERCHANT_OUTBOX_PANEL		1	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
 
 static const char * const INBOX_BUTTON_NAME = "inbox_btn";
 static const char * const OUTBOX_BUTTON_NAME = "outbox_btn";
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 13dbc5e386..e7f05dcaa3 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1368,7 +1368,7 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom
 
 // This is defined in two files but I don't want to create a dependence between this and llsidepanelinventory
 // just to be able to temporarily disable the outbox.
-#define ENABLE_INVENTORY_DISPLAY_OUTBOX		0	// keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+#define ENABLE_INVENTORY_DISPLAY_OUTBOX		1	// keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
 
 class LLInventoryUserStatusResponder : public LLHTTPClient::Responder
 {
-- 
cgit v1.2.3


From 5af39ea28be1a76ec0c3042a0bf34e7d64835c18 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 16 Sep 2011 11:46:37 -0700
Subject: EXP-1169 FIX -- No synch error icon given on Outbox on Agni where API
 does not exist

* Moved marketplace URL related functions into a new file llmarketplacefunctions.cpp/h.
  This will the future home of more marketplace-related functions.
* Disabled sync button when the marketplace API is unavailable.
---
 indra/newview/CMakeLists.txt               |  2 +
 indra/newview/llmarketplacefunctions.cpp   | 80 +++++++++++++++++++++++++++++
 indra/newview/llmarketplacefunctions.h     | 42 ++++++++++++++++
 indra/newview/llpanelmarketplaceoutbox.cpp | 22 ++------
 indra/newview/llviewermedia.cpp            | 81 +++++++++++++-----------------
 5 files changed, 165 insertions(+), 62 deletions(-)
 create mode 100644 indra/newview/llmarketplacefunctions.cpp
 create mode 100644 indra/newview/llmarketplacefunctions.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 11b19ca4fe..8c1f98979b 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -310,6 +310,7 @@ set(viewer_SOURCE_FILES
     llmaniprotate.cpp
     llmanipscale.cpp
     llmaniptranslate.cpp
+    llmarketplacefunctions.cpp
     llmediactrl.cpp
     llmediadataclient.cpp
     llmemoryview.cpp
@@ -873,6 +874,7 @@ set(viewer_HEADER_FILES
     llmaniprotate.h
     llmanipscale.h
     llmaniptranslate.h
+    llmarketplacefunctions.h
     llmediactrl.h
     llmediadataclient.h
     llmemoryview.h
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
new file mode 100644
index 0000000000..599731a641
--- /dev/null
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -0,0 +1,80 @@
+/** 
+ * @file llmarketplacefunctions.cpp
+ * @brief Implementation of assorted functions related to the marketplace
+ *
+ * $LicenseInfo:firstyear=2001&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 "llmarketplacefunctions.h"
+
+#include "llagent.h"
+#include "llviewernetwork.h"
+
+
+std::string getMarketplaceBaseURL()
+{
+	std::string url = "https://marketplace.secondlife.com/";
+
+	if (!LLGridManager::getInstance()->isInProductionGrid())
+	{
+		std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
+		url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str());
+	}
+
+	url += "api/1/users/";
+	url += gAgent.getID().getString();
+
+	return url;
+}
+
+std::string getMarketplaceURL_InventoryImport()
+{
+	std::string url = getMarketplaceBaseURL();
+
+	url += "/inventory_import";
+
+	return url;
+}
+
+std::string getMarketplaceURL_UserStatus()
+{
+	std::string url = getMarketplaceBaseURL();
+
+	url += "/user_status";
+
+	return url;
+}
+
+
+static bool gMarketplaceSyncEnabled = false;
+
+bool getMarketplaceSyncEnabled()
+{
+	return gMarketplaceSyncEnabled;
+}
+
+void setMarketplaceSyncEnabled(bool syncEnabled)
+{
+	gMarketplaceSyncEnabled = syncEnabled;
+}
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
new file mode 100644
index 0000000000..e80e6a471c
--- /dev/null
+++ b/indra/newview/llmarketplacefunctions.h
@@ -0,0 +1,42 @@
+/** 
+ * @file llmarketplacefunctions.h
+ * @brief Miscellaneous marketplace-related functions and classes
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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 LL_LLMARKETPLACEFUNCTIONS_H
+#define LL_LLMARKETPLACEFUNCTIONS_H
+
+
+std::string getMarketplaceURL_InventoryImport();
+std::string getMarketplaceURL_UserStatus();
+
+bool getMarketplaceSyncEnabled();
+void setMarketplaceSyncEnabled(bool syncEnabled);
+
+
+#endif // LL_LLMARKETPLACEFUNCTIONS_H
+
+
+
diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
index 73fb92ff72..2764527c44 100644
--- a/indra/newview/llpanelmarketplaceoutbox.cpp
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -35,6 +35,7 @@
 #include "lleventcoro.h"
 #include "llinventorypanel.h"
 #include "llloadingindicator.h"
+#include "llmarketplacefunctions.h"
 #include "llnotificationsutil.h"
 #include "llpanelmarketplaceinbox.h"
 #include "llsdutil.h"
@@ -82,7 +83,7 @@ void LLPanelMarketplaceOutbox::handleLoginComplete()
 {
 	mSyncButton = getChild<LLButton>("outbox_sync_btn");
 	mSyncButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onSyncButtonClicked, this));
-	mSyncButton->setEnabled(!isOutboxEmpty());
+	mSyncButton->setEnabled(getMarketplaceSyncEnabled() && !isOutboxEmpty());
 	
 	mSyncIndicator = getChild<LLLoadingIndicator>("outbox_sync_indicator");
 }
@@ -223,20 +224,7 @@ void LLPanelMarketplaceOutbox::onSyncButtonClicked()
 	updateSyncButtonStatus();
 
 	// Make the url for the inventory import request
-	std::string url = "https://marketplace.secondlife.com/";
-
-	if (!LLGridManager::getInstance()->isInProductionGrid())
-	{
-		std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
-		url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str());
-
-		// TEMP for Jim's pdp
-		//url = "http://pdp24.lindenlab.com:3000/";
-	}
-	
-	url += "api/1/users/";
-	url += gAgent.getID().getString();
-	url += "/inventory_import";
+	std::string url = getMarketplaceURL_InventoryImport();
 
 	llinfos << "http get:  " << url << llendl;
 	LLHTTPClient::get(url, new LLInventorySyncResponder(this), LLViewerMedia::getHeaders());
@@ -311,7 +299,7 @@ void LLPanelMarketplaceOutbox::updateSyncButtonStatus()
 		mSyncIndicator->setVisible(false);
 
 		mSyncButton->setVisible(true);
-		mSyncButton->setEnabled(!isOutboxEmpty());
+		mSyncButton->setEnabled(getMarketplaceSyncEnabled() && !isOutboxEmpty());
 	}
 }
 
@@ -352,7 +340,7 @@ void LLPanelMarketplaceOutbox::draw()
 	
 	if (!isSyncInProgress())
 	{
-		mSyncButton->setEnabled(not_empty);
+		mSyncButton->setEnabled(getMarketplaceSyncEnabled() && not_empty);
 	}
 	
 	LLPanel::draw();
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index e7f05dcaa3..b60881b5f1 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -26,51 +26,49 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "llviewermedia.h"
+
 #include "llagent.h"
 #include "llagentcamera.h"
-#include "llviewermedia.h"
-#include "llviewermediafocus.h"
-#include "llmimetypes.h"
+#include "llappviewer.h"
+#include "llaudioengine.h"  // for gAudiop
+#include "llcallbacklist.h"
+#include "lldir.h"
+#include "lldiriterator.h"
+#include "llevent.h"		// LLSimpleListener
+#include "llfilepicker.h"
+#include "llfloatermediabrowser.h"	// for handling window close requests and geometry change requests in media browser windows.
+#include "llfloaterwebcontent.h"	// for handling window close requests and geometry change requests in media browser windows.
+#include "llfocusmgr.h"
+#include "llkeyboard.h"
+#include "lllogininstance.h" 
+#include "llmarketplacefunctions.h"
 #include "llmediaentry.h"
+#include "llmimetypes.h"
+#include "llmutelist.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llpanelprofile.h"
+#include "llparcel.h"
+#include "llpluginclassmedia.h"
+#include "llplugincookiestore.h"
+#include "llurldispatcher.h"
+#include "lluuid.h"
 #include "llversioninfo.h"
 #include "llviewercontrol.h"
-#include "llviewertexture.h"
+#include "llviewermediafocus.h"
 #include "llviewerparcelmedia.h"
 #include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewertexture.h"
 #include "llviewertexturelist.h"
-#include "llvovolume.h"
-#include "llpluginclassmedia.h"
-#include "llplugincookiestore.h"
 #include "llviewerwindow.h"
-#include "llfocusmgr.h"
-#include "llcallbacklist.h"
-#include "llparcel.h"
-#include "llaudioengine.h"  // for gAudiop
-#include "llurldispatcher.h"
 #include "llvoavatar.h"
 #include "llvoavatarself.h"
-#include "llviewerregion.h"
+#include "llvovolume.h"
 #include "llwebsharing.h"	// For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!
-#include "llfilepicker.h"
-#include "llnotifications.h"
-#include "lldir.h"
-#include "lldiriterator.h"
-#include "llevent.h"		// LLSimpleListener
-#include "llnotificationsutil.h"
-#include "lluuid.h"
-#include "llkeyboard.h"
-#include "llmutelist.h"
-#include "llpanelprofile.h"
-#include "llappviewer.h"
-#include "lllogininstance.h" 
-//#include "llfirstuse.h"
-#include "llviewernetwork.h"
 #include "llwindow.h"
 
-
-#include "llfloatermediabrowser.h"	// for handling window close requests and geometry change requests in media browser windows.
-#include "llfloaterwebcontent.h"	// for handling window close requests and geometry change requests in media browser windows.
-
 #include <boost/bind.hpp>	// for SkinFolder listener
 #include <boost/signals2.hpp>
 
@@ -1394,14 +1392,20 @@ public:
 #if ENABLE_INVENTORY_DISPLAY_OUTBOX
 			gSavedSettings.setBOOL("InventoryDisplayOutbox", true);
 #endif
+
+			setMarketplaceSyncEnabled(true);
 		}
 		else if (status == 401)
 		{
 			// API is available for use but OpenID authorization failed
 			gSavedSettings.setBOOL("InventoryDisplayInbox", true);
+
+			setMarketplaceSyncEnabled(false);
 		}
 		else
 		{
+			setMarketplaceSyncEnabled(false);
+
 			// API in unavailable
 			llinfos << "Marketplace API is unavailable -- Inbox may be disabled, status = " << status << ", reason = " << reason << llendl;
 		}
@@ -1411,20 +1415,7 @@ public:
 
 void doOnetimeEarlyHTTPRequests()
 {
-	std::string url = "https://marketplace.secondlife.com/";
-
-	if (!LLGridManager::getInstance()->isInProductionGrid())
-	{
-		std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
-		url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str());
-
-		// TEMP for Jim's pdp
-		//url = "http://pdp24.lindenlab.com:3000/";
-	}
-	
-	url += "api/1/users/";
-	url += gAgent.getID().getString();
-	url += "/user_status";
+	std::string url = getMarketplaceURL_UserStatus();
 
 	llinfos << "http get: " << url << llendl;
 	LLHTTPClient::get(url, new LLInventoryUserStatusResponder(), LLViewerMedia::getHeaders());
-- 
cgit v1.2.3


From b403a9da23a2df73a657bfa835a3706a261af2fb Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 31 Oct 2011 15:45:13 -0700
Subject: Enabling outbox

---
 indra/newview/llinventorybridge.cpp    | 2 +-
 indra/newview/llsidepanelinventory.cpp | 2 +-
 indra/newview/llviewermedia.cpp        | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 0e27bd81be..0e1e6265aa 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -71,7 +71,7 @@
 #include "llwearablelist.h"
 
 // Marketplace outbox current disabled
-#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	0	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_PANEL
+#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_PANEL
 
 typedef std::pair<LLUUID, LLUUID> two_uuids_t;
 typedef std::list<two_uuids_t> two_uuids_list_t;
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 91f8035556..03d9f9817d 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -69,7 +69,7 @@ static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_
 #define AUTO_EXPAND_INBOX	0
 
 // Temporarily disabling the outbox until we straighten out the API
-#define ENABLE_MERCHANT_OUTBOX_PANEL		0	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+#define ENABLE_MERCHANT_OUTBOX_PANEL		1	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
 
 static const char * const INBOX_BUTTON_NAME = "inbox_btn";
 static const char * const OUTBOX_BUTTON_NAME = "outbox_btn";
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 41b4dc01e8..d81bed0f12 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1368,7 +1368,7 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom
 
 // This is defined in two files but I don't want to create a dependence between this and llsidepanelinventory
 // just to be able to temporarily disable the outbox.
-#define ENABLE_INVENTORY_DISPLAY_OUTBOX		0	// keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+#define ENABLE_INVENTORY_DISPLAY_OUTBOX		1	// keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
 
 class LLInventoryUserStatusResponder : public LLHTTPClient::Responder
 {
-- 
cgit v1.2.3


From 9740887b90791b3fad37e58ab9e2ac772e8d2e95 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 14 Nov 2011 14:40:58 -0800
Subject: Build fix from bad merge

---
 indra/newview/llviewermedia.cpp | 29 ++++-------------------------
 1 file changed, 4 insertions(+), 25 deletions(-)

diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 47aa2d8656..6fc4dd25af 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -33,37 +33,14 @@
 #include "llappviewer.h"
 #include "llaudioengine.h"  // for gAudiop
 #include "llcallbacklist.h"
-#include "llparcel.h"
-#include "llaudioengine.h"  // for gAudiop
-#include "llurldispatcher.h"
-#include "llvoavatar.h"
-#include "llvoavatarself.h"
-#include "llviewerregion.h"
-#include "llwebprofile.h"
-#include "llwebsharing.h"	// For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!
-#include "llfilepicker.h"
-#include "llnotifications.h"
 #include "lldir.h"
 #include "lldiriterator.h"
 #include "llevent.h"		// LLSimpleListener
 #include "llfilepicker.h"
-#include "llfloatermediabrowser.h"	// for handling window close requests and geometry change requests in media browser windows.
-#include "llnotificationsutil.h"
-#include "lluuid.h"
-#include "llkeyboard.h"
-#include "llmutelist.h"
-#include "llpanelprofile.h"
-#include "llappviewer.h"
-#include "lllogininstance.h" 
-//#include "llfirstuse.h"
-#include "llviewernetwork.h"
-#include "llwindow.h"
-
-
 #include "llfloaterwebcontent.h"	// for handling window close requests and geometry change requests in media browser windows.
 #include "llfocusmgr.h"
 #include "llkeyboard.h"
-#include "lllogininstance.h" 
+#include "lllogininstance.h"
 #include "llmarketplacefunctions.h"
 #include "llmediaentry.h"
 #include "llmimetypes.h"
@@ -77,8 +54,9 @@
 #include "llurldispatcher.h"
 #include "lluuid.h"
 #include "llversioninfo.h"
-#include "llviewercontrol.h"
 #include "llviewermediafocus.h"
+#include "llviewercontrol.h"
+#include "llviewernetwork.h"
 #include "llviewerparcelmedia.h"
 #include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
@@ -88,6 +66,7 @@
 #include "llvoavatar.h"
 #include "llvoavatarself.h"
 #include "llvovolume.h"
+#include "llwebprofile.h"
 #include "llwebsharing.h"	// For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!
 #include "llwindow.h"
 
-- 
cgit v1.2.3


From c24645f7b51ea27e1686bbe72470a9f3c09fc676 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 14 Nov 2011 14:41:26 -0800
Subject: Updated url for damballah to use secondlife-staging

---
 indra/newview/llmarketplacefunctions.cpp | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 599731a641..99b0389413 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -38,8 +38,16 @@ std::string getMarketplaceBaseURL()
 
 	if (!LLGridManager::getInstance()->isInProductionGrid())
 	{
-		std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
-		url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str());
+		std::string gridLabel = utf8str_tolower(LLGridManager::getInstance()->getGridLabel());
+		
+		if (gridLabel == "damballah")
+		{
+			url = "https://marketplace.secondlife-staging.com/";
+		}
+		else
+		{
+			url = llformat("https://marketplace.%s.lindenlab.com/", gridLabel.c_str());
+		}
 	}
 
 	url += "api/1/users/";
@@ -67,7 +75,7 @@ std::string getMarketplaceURL_UserStatus()
 }
 
 
-static bool gMarketplaceSyncEnabled = false;
+static bool gMarketplaceSyncEnabled = true;
 
 bool getMarketplaceSyncEnabled()
 {
-- 
cgit v1.2.3


From b28492fbffd7bea9e7174260d66d5f52c76d24b2 Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Thu, 17 Nov 2011 23:17:26 +0000
Subject: STORM-1708 Adding ability to save/load scripts from file.

---
 doc/contributions.txt                              |  1 +
 indra/newview/llfilepicker.cpp                     | 15 +++++
 indra/newview/llfilepicker.h                       |  2 +
 indra/newview/llfloaternamedesc.cpp                | 21 ++++++
 indra/newview/llfloaternamedesc.h                  | 10 ++-
 indra/newview/llpreviewscript.cpp                  | 78 +++++++++++++++++++---
 indra/newview/llpreviewscript.h                    |  2 +
 indra/newview/llviewerfloaterreg.cpp               |  3 +-
 indra/newview/llviewermenufile.cpp                 | 22 ++++++
 indra/newview/skins/default/xui/en/menu_viewer.xml | 15 ++++-
 .../skins/default/xui/en/panel_script_ed.xml       | 22 ++++--
 11 files changed, 174 insertions(+), 17 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 2b39e15e2a..9daef4035a 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -482,6 +482,7 @@ Ima Mechanique
 	OPEN-76
 	STORM-959
 	STORM-1175
+	STORM-1708
 Imnotgoing Sideways
 Inma Rau
 Innula Zenovka
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 4897cf1885..0801871409 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -58,6 +58,7 @@ LLFilePicker LLFilePicker::sInstance;
 #define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
 #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
 #define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"
+#define SCRIPT_FILTER L"Script files (*.lsl; *.txt)\0*.lsl;*.txt\0"
 #endif
 
 //
@@ -213,6 +214,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
 		mOFN.lpstrFilter = MODEL_FILTER \
 			L"\0";
 		break;
+	case FFLOAD_SCRIPT:
+		mOFN.lpstrFilter = SCRIPT_FILTER \
+			L"\0";
+		break;
 	default:
 		res = FALSE;
 		break;
@@ -497,6 +502,16 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
 			L"Compressed Images (*.j2c)\0*.j2c\0" \
 			L"\0";
 		break;
+	case FFSAVE_SCRIPT:
+		if (filename.empty())
+		{
+			wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE);
+		}
+		mOFN.lpstrDefExt = L"txt";
+		mOFN.lpstrFilter = 
+			L"LSL Files (*.lsl; *.txt)\0*.lsl;*.txt\0"
+			L"\0";
+		break;
 	default:
 		return FALSE;
 	}
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index cd843a8f33..a4d5d68ff5 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -84,6 +84,7 @@ public:
 		FFLOAD_RAW = 8,
 		FFLOAD_MODEL = 9,
 		FFLOAD_COLLADA = 10,
+		FFLOAD_SCRIPT = 11,
 	};
 
 	enum ESaveFilter
@@ -103,6 +104,7 @@ public:
 		FFSAVE_J2C = 12,
 		FFSAVE_PNG = 13,
 		FFSAVE_JPEG = 14,
+		FFSAVE_SCRIPT = 15,
 	};
 
 	// open the dialog. This is a modal operation
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index ae95d4392a..4d4f9f57bf 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -204,3 +204,24 @@ BOOL LLFloaterSoundPreview::postBuild()
 	getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this));
 	return TRUE;
 }
+
+
+//-----------------------------------------------------------------------------
+// LLFloaterScriptPreview()
+//-----------------------------------------------------------------------------
+
+LLFloaterScriptPreview::LLFloaterScriptPreview(const LLSD& filename )
+	: LLFloaterNameDesc(filename)
+{
+	mIsAudio = TRUE;
+}
+
+BOOL LLFloaterScriptPreview::postBuild()
+{
+	if (!LLFloaterNameDesc::postBuild())
+	{
+		return FALSE;
+	}
+	getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this));
+	return TRUE;
+}
diff --git a/indra/newview/llfloaternamedesc.h b/indra/newview/llfloaternamedesc.h
index 7381a6334a..69bbccaf80 100644
--- a/indra/newview/llfloaternamedesc.h
+++ b/indra/newview/llfloaternamedesc.h
@@ -51,6 +51,7 @@ protected:
 
 protected:
 	BOOL        mIsAudio;
+	bool		mIsText;
 
 	std::string		mFilenameAndPath;
 	std::string		mFilename;
@@ -62,5 +63,12 @@ public:
 	LLFloaterSoundPreview(const LLSD& filename );
 	virtual BOOL postBuild();
 };
-	
+
+class LLFloaterScriptPreview : public LLFloaterNameDesc
+{
+public:
+	LLFloaterScriptPreview(const LLSD& filename );
+	virtual BOOL postBuild();
+};
+
 #endif  // LL_LLFLOATERNAMEDESC_H
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index b19bf5d234..072df39514 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -35,6 +35,7 @@
 #include "llcombobox.h"
 #include "lldir.h"
 #include "llexternaleditor.h"
+#include "llfilepicker.h"
 #include "llfloaterreg.h"
 #include "llinventorydefines.h"
 #include "llinventorymodel.h"
@@ -89,15 +90,15 @@
 const std::string HELLO_LSL =
 	"default\n"
 	"{\n"
-	"    state_entry()\n"
-    "    {\n"
-    "        llSay(0, \"Hello, Avatar!\");\n"
-    "    }\n"
+	"\tstate_entry()\n"
+    "\t{\n"
+    "\t\tllOwnerSay(\"Hello, Avatar!\");\n"
+    "\t}\n"
 	"\n"
-	"    touch_start(integer total_number)\n"
-	"    {\n"
-	"        llSay(0, \"Touched.\");\n"
-	"    }\n"
+	"\ttouch_start(integer total_number)\n"
+	"\t{\n"
+	"\t\tllSay(llDetectedKey(0), \"Touched.\");\n"
+	"\t}\n"
 	"}\n";
 const std::string HELP_LSL_PORTAL_TOPIC = "LSL_Portal";
 
@@ -503,6 +504,14 @@ void LLScriptEdCore::initMenu()
 
 	menuItem = getChild<LLMenuItemCallGL>("Keyword Help...");
 	menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnDynamicHelp, this));
+
+	menuItem = getChild<LLMenuItemCallGL>("LoadFromFile");
+	menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnLoadFromFile, this));
+//	menuItem->setEnabledCallback(NULL);
+
+	menuItem = getChild<LLMenuItemCallGL>("SaveToFile");
+	menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnSaveToFile, this));
+	menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::hasChanged, this));
 }
 
 void LLScriptEdCore::setScriptText(const std::string& text, BOOL is_valid)
@@ -1096,6 +1105,59 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask)
 	return FALSE;
 }
 
+void LLScriptEdCore::onBtnLoadFromFile( void* data )
+{
+
+	LLScriptEdCore* self = (LLScriptEdCore*) data;
+	
+	LLFilePicker& file_picker = LLFilePicker::instance();
+	if( !file_picker.getOpenFile( LLFilePicker::FFLOAD_SCRIPT ) )
+	{
+		return;
+	}
+
+	std::string filename = file_picker.getFirstFile();
+
+	std::ifstream fin(filename.c_str());
+
+	std::string line;
+	std::string linetotal;
+	self->mEditor->clear();
+	while (!fin.eof())
+	{ 
+		getline(fin,line);
+		line=line+"\n";
+		self->mEditor->insertText(line);
+
+	}
+	fin.close();
+}
+
+void LLScriptEdCore::onBtnSaveToFile( void* userdata )
+{
+
+	LLViewerStats::getInstance()->incStat( LLViewerStats::ST_LSL_SAVE_COUNT );
+
+	LLScriptEdCore* self = (LLScriptEdCore*) userdata;
+
+	if( self->mSaveCallback )
+	{
+		LLFilePicker& file_picker = LLFilePicker::instance();
+		if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_SCRIPT ) )
+		{
+			return;
+		}
+
+		std::string filename = file_picker.getFirstFile();
+		std::string scriptText=self->mEditor->getText();
+		std::ofstream fout(filename.c_str());
+		fout<<(scriptText);
+		fout.close();
+		self->mSaveCallback( self->mUserdata, FALSE );
+	}
+}
+
+
 /// ---------------------------------------------------------------------------
 /// LLScriptEdContainer
 /// ---------------------------------------------------------------------------
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index f86be615c4..f50e9322b0 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -98,6 +98,8 @@ public:
 	static void		onClickForward(void* userdata);
 	static void		onBtnInsertSample(void*);
 	static void		onBtnInsertFunction(LLUICtrl*, void*);
+	static void		onBtnLoadFromFile(void*);
+	static void		onBtnSaveToFile(void*);
 
 	virtual bool	hasAccelerators() const { return true; }
 
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 273bf822bc..56c79f5b9f 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -292,9 +292,10 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterUIPreviewUtil::registerFloater();
 	LLFloaterReg::add("upload_anim", "floater_animation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");
 	LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload");
-	LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload");
 	LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload");
 	LLFloaterReg::add("upload_model_wizard", "floater_model_wizard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelWizard>);
+	LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload");
+	LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload");
 
 	LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>);
 	LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>);
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 7e830e14bf..f23d0f6b72 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -87,6 +87,14 @@ class LLFileEnableUpload : public view_listener_t
 	}
 };
 
+class LLFileEnableUploadScript : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		return true;
+	}
+};
+
 class LLFileEnableUploadModel : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -391,6 +399,20 @@ class LLFileUploadAnim : public view_listener_t
 	}
 };
 
+class LLFileUploadScript : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_SCRIPT);
+		if (!filename.empty())
+		{
+			LLFloaterReg::showInstance("upload_script", LLSD(filename));
+		}
+
+		return true;
+	}
+};
+
 class LLFileUploadBulk : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 263d961be1..b9605e1ede 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1101,7 +1101,20 @@
             <menu_item_call.on_visible
             function="File.VisibleUploadModel"/>
             </menu_item_call>
-	   <menu_item_call
+          <menu_item_call
+           label="Script (L$ 0)..."
+           layout="topleft"
+           name="Upload Script">
+            <menu_item_call.on_click
+             function="File.UploadScript"
+             parameter="" />
+            <menu_item_call.on_enable
+             function="File.EnableUploadScript" />
+            <!--menu_item_call.on_visible
+             function="Upload.CalculateCosts"
+             parameter="Upload Script" /-->
+          </menu_item_call>
+          <menu_item_call
              label="Bulk (L$[COST] per file)..."
              layout="topleft"
              name="Bulk Upload">
diff --git a/indra/newview/skins/default/xui/en/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml
index 8d42024386..f6a8af0973 100644
--- a/indra/newview/skins/default/xui/en/panel_script_ed.xml
+++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml
@@ -54,12 +54,22 @@
              label="Save"
              layout="topleft"
              name="Save" />
-            <menu_item_separator
-             layout="topleft" />
-            <menu_item_call
-             label="Revert All Changes"
-             layout="topleft"
-             name="Revert All Changes" />
+          <menu_item_separator
+           layout="topleft" />
+          <menu_item_call
+           label="Revert All Changes"
+           layout="topleft"
+           name="Revert All Changes" />
+          <menu_item_separator
+           layout="topleft" />
+          <menu_item_call
+           label="Load from file..."
+           layout="topleft"
+           name="LoadFromFile" />
+          <menu_item_call
+           label="Save to file..."
+           layout="topleft"
+           name="SaveToFile" />
         </menu>
         <menu
          top="0"
-- 
cgit v1.2.3


From 476cfabf6302e83fec77a8e0ac729f1de07bf679 Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Fri, 18 Nov 2011 21:18:13 +0000
Subject: Reverting changes to Build => Upload menu. This change was mistakenly
 included from a follow on project that is incomplete.

---
 indra/newview/skins/default/xui/en/menu_viewer.xml | 15 +--------------
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index b9605e1ede..263d961be1 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1101,20 +1101,7 @@
             <menu_item_call.on_visible
             function="File.VisibleUploadModel"/>
             </menu_item_call>
-          <menu_item_call
-           label="Script (L$ 0)..."
-           layout="topleft"
-           name="Upload Script">
-            <menu_item_call.on_click
-             function="File.UploadScript"
-             parameter="" />
-            <menu_item_call.on_enable
-             function="File.EnableUploadScript" />
-            <!--menu_item_call.on_visible
-             function="Upload.CalculateCosts"
-             parameter="Upload Script" /-->
-          </menu_item_call>
-          <menu_item_call
+	   <menu_item_call
              label="Bulk (L$[COST] per file)..."
              layout="topleft"
              name="Bulk Upload">
-- 
cgit v1.2.3


From c1745ca4aa4b7d8eb113978eb850ca791dcf2255 Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Fri, 18 Nov 2011 21:55:40 +0000
Subject: Fixes .lsl not being appended if no extension is provided.

---
 indra/newview/llfloaternamedesc.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index 4d4f9f57bf..66f0fc3cd7 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -213,7 +213,7 @@ BOOL LLFloaterSoundPreview::postBuild()
 LLFloaterScriptPreview::LLFloaterScriptPreview(const LLSD& filename )
 	: LLFloaterNameDesc(filename)
 {
-	mIsAudio = TRUE;
+	mIsText = TRUE;
 }
 
 BOOL LLFloaterScriptPreview::postBuild()
-- 
cgit v1.2.3


From e875e0548b69d1cf141e3970a81aa3f0a5ff7ed3 Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Fri, 18 Nov 2011 22:56:31 +0000
Subject: Removing code associated with Build => Upload => Script previously
 reverted.

---
 indra/newview/llviewermenufile.cpp | 22 ----------------------
 1 file changed, 22 deletions(-)

diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index f23d0f6b72..7e830e14bf 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -87,14 +87,6 @@ class LLFileEnableUpload : public view_listener_t
 	}
 };
 
-class LLFileEnableUploadScript : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		return true;
-	}
-};
-
 class LLFileEnableUploadModel : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -399,20 +391,6 @@ class LLFileUploadAnim : public view_listener_t
 	}
 };
 
-class LLFileUploadScript : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_SCRIPT);
-		if (!filename.empty())
-		{
-			LLFloaterReg::showInstance("upload_script", LLSD(filename));
-		}
-
-		return true;
-	}
-};
-
 class LLFileUploadBulk : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
-- 
cgit v1.2.3


From eeefec394c932b79a22c5ea2b8aa03690bb6061e Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Wed, 23 Nov 2011 01:30:15 +0000
Subject: Changes to filter out tabs from file load and to test if
 loading/saving should be allowed.

---
 indra/llui/lltexteditor.cpp       | 26 ++++++++++++++++++
 indra/llui/lltexteditor.h         |  5 ++++
 indra/newview/llfilepicker.cpp    | 12 +--------
 indra/newview/llpreviewscript.cpp | 56 +++++++++++++++++++++++++++++++++------
 indra/newview/llpreviewscript.h   |  4 +++
 5 files changed, 84 insertions(+), 19 deletions(-)

diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 9bd445988d..3a23ce1cac 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2250,6 +2250,22 @@ void LLTextEditor::insertText(const std::string &new_text)
 	setEnabled( enabled );
 }
 
+void LLTextEditor::insertText(LLWString &new_text)
+{
+	BOOL enabled = getEnabled();
+	setEnabled( TRUE );
+
+	// Delete any selected characters (the insertion replaces them)
+	if( hasSelection() )
+	{
+		deleteSelection(TRUE);
+	}
+
+	setCursorPos(mCursorPos + insert( mCursorPos, new_text, FALSE, LLTextSegmentPtr() ));
+
+	setEnabled( enabled );
+}
+
 void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo)
 {
 	// Save old state
@@ -2838,3 +2854,13 @@ void LLTextEditor::clear()
 	getViewModel()->setDisplay(LLWStringUtil::null);
 	clearSegments();
 }
+
+bool LLTextEditor::canLoadOrSaveToFile()
+{
+	return !mReadOnly;
+}
+
+S32 LLTextEditor::spacesPerTab()
+{
+	return SPACES_PER_TAB;
+}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 9e4b95003b..40821ae9fb 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -92,6 +92,8 @@ public:
 
 	void	setParseHighlights(BOOL parsing) {mParseHighlights=parsing;}
 
+	static S32		spacesPerTab();
+
 	// mousehandler overrides
 	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
@@ -140,6 +142,8 @@ public:
 	virtual void	selectAll();
 	virtual BOOL	canSelectAll()	const;
 
+	virtual bool	canLoadOrSaveToFile();
+
 	void			selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE);
 	BOOL			replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
 	void			replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive);
@@ -158,6 +162,7 @@ public:
 
 	// inserts text at cursor
 	void			insertText(const std::string &text);
+	void			insertText(LLWString &text);
 
 	void			appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
 	// Non-undoable
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 0801871409..3cbc4e5648 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -58,7 +58,7 @@ LLFilePicker LLFilePicker::sInstance;
 #define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
 #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
 #define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"
-#define SCRIPT_FILTER L"Script files (*.lsl; *.txt)\0*.lsl;*.txt\0"
+#define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0"
 #endif
 
 //
@@ -502,16 +502,6 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
 			L"Compressed Images (*.j2c)\0*.j2c\0" \
 			L"\0";
 		break;
-	case FFSAVE_SCRIPT:
-		if (filename.empty())
-		{
-			wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE);
-		}
-		mOFN.lpstrDefExt = L"txt";
-		mOFN.lpstrFilter = 
-			L"LSL Files (*.lsl; *.txt)\0*.lsl;*.txt\0"
-			L"\0";
-		break;
 	default:
 		return FALSE;
 	}
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 072df39514..16b582d188 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -507,11 +507,11 @@ void LLScriptEdCore::initMenu()
 
 	menuItem = getChild<LLMenuItemCallGL>("LoadFromFile");
 	menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnLoadFromFile, this));
-//	menuItem->setEnabledCallback(NULL);
+	menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::enableLoadFromFileMenu, this));
 
 	menuItem = getChild<LLMenuItemCallGL>("SaveToFile");
 	menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnSaveToFile, this));
-	menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::hasChanged, this));
+	menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::enableSaveToFileMenu, this));
 }
 
 void LLScriptEdCore::setScriptText(const std::string& text, BOOL is_valid)
@@ -1107,9 +1107,17 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask)
 
 void LLScriptEdCore::onBtnLoadFromFile( void* data )
 {
-
 	LLScriptEdCore* self = (LLScriptEdCore*) data;
-	
+/*
+	if( self->isDirty())
+	{
+		llwarns << "Script has unsaved changes, loading from disc aborted." << llendl;
+		LLStringBase<char>::format_map_t args;
+		args["[REASON]"] = std::string("Existing script has unsaved changes. You must save this script before loading from disc.");
+		gViewerWindow->alertXml("LoadDiskScriptFailReason", args);		
+		return;
+	}
+*/
 	LLFilePicker& file_picker = LLFilePicker::instance();
 	if( !file_picker.getOpenFile( LLFilePicker::FFLOAD_SCRIPT ) )
 	{
@@ -1121,16 +1129,27 @@ void LLScriptEdCore::onBtnLoadFromFile( void* data )
 	std::ifstream fin(filename.c_str());
 
 	std::string line;
+	std::string text;
 	std::string linetotal;
-	self->mEditor->clear();
 	while (!fin.eof())
 	{ 
 		getline(fin,line);
-		line=line+"\n";
-		self->mEditor->insertText(line);
-
+		text += line;
+		if (!fin.eof())
+		{
+			text += "\n";
+		}
 	}
 	fin.close();
+
+	// Only replace the script if there is something to replace with.
+	if (text.length() > 0)
+	{
+		self->mEditor->selectAll();
+		LLWString script(utf8str_to_wstring(text));
+		LLWStringUtil::replaceTabsWithSpaces(script, self->mEditor->spacesPerTab());
+		self->mEditor->insertText(script);
+	}
 }
 
 void LLScriptEdCore::onBtnSaveToFile( void* userdata )
@@ -1157,6 +1176,27 @@ void LLScriptEdCore::onBtnSaveToFile( void* userdata )
 	}
 }
 
+bool LLScriptEdCore::canLoadOrSaveToFile( void* userdata )
+{
+	LLScriptEdCore* self = (LLScriptEdCore*) userdata;
+	return self->mEditor->canLoadOrSaveToFile();
+}
+
+// static
+bool LLScriptEdCore::enableSaveToFileMenu(void* userdata)
+{
+	LLScriptEdCore* self = (LLScriptEdCore*)userdata;
+	if (!self || !self->mEditor) return FALSE;
+	return self->mEditor->canLoadOrSaveToFile();
+}
+
+// static 
+bool LLScriptEdCore::enableLoadFromFileMenu(void* userdata)
+{
+	LLScriptEdCore* self = (LLScriptEdCore*)userdata;
+	if (!self || !self->mEditor) return FALSE;
+	return self->mEditor->canLoadOrSaveToFile();
+}
 
 /// ---------------------------------------------------------------------------
 /// LLScriptEdContainer
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index f50e9322b0..7563cecd9d 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -79,6 +79,7 @@ public:
 	/*virtual*/	BOOL	postBuild();
 	BOOL			canClose();
 	void			setEnableEditing(bool enable);
+	bool			canLoadOrSaveToFile( void* userdata );
 
 	void            setScriptText(const std::string& text, BOOL is_valid);
 	bool			loadScriptText(const std::string& filename);
@@ -101,6 +102,9 @@ public:
 	static void		onBtnLoadFromFile(void*);
 	static void		onBtnSaveToFile(void*);
 
+	static bool		enableSaveToFileMenu(void* userdata);
+	static bool		enableLoadFromFileMenu(void* userdata);
+
 	virtual bool	hasAccelerators() const { return true; }
 
 private:
-- 
cgit v1.2.3


From 413cd15f070c6c0406026c96e0b70698120366ef Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Thu, 24 Nov 2011 12:48:17 +0000
Subject: Fixed accidental change to HELLO_WORLD script.

---
 indra/newview/llpreviewscript.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 16b582d188..0a429269ba 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -90,15 +90,15 @@
 const std::string HELLO_LSL =
 	"default\n"
 	"{\n"
-	"\tstate_entry()\n"
-    "\t{\n"
-    "\t\tllOwnerSay(\"Hello, Avatar!\");\n"
-    "\t}\n"
+	"	state_entry()\n"
+    "	{\n"
+    "		llOwnerSay(\"Hello, Avatar!\");\n"
+    "	}\n"
 	"\n"
-	"\ttouch_start(integer total_number)\n"
-	"\t{\n"
-	"\t\tllSay(llDetectedKey(0), \"Touched.\");\n"
-	"\t}\n"
+	"	touch_start(integer total_number)\n"
+	"	{\n"
+	"		llSay(llDetectedKey(0), \"Touched.\");\n"
+	"	}\n"
 	"}\n";
 const std::string HELP_LSL_PORTAL_TOPIC = "LSL_Portal";
 
-- 
cgit v1.2.3


From 570d02dc7e41c3e08477e7f759d632db78690eb4 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 29 Nov 2011 16:57:37 -0800
Subject: Initial merchant outbox button

---
 indra/newview/CMakeLists.txt                       |   2 +
 indra/newview/app_settings/commands.xml            |  10 ++
 indra/newview/llfloateroutbox.cpp                  |  68 +++++++++++
 indra/newview/llfloateroutbox.h                    |  56 +++++++++
 indra/newview/llviewerfloaterreg.cpp               |   2 +
 indra/newview/skins/default/textures/textures.xml  |   1 +
 .../default/textures/toolbar_icons/outbox.png      | Bin 0 -> 2987 bytes
 .../default/xui/en/floater_merchant_outbox.xml     | 134 +++++++++++++++++++++
 .../skins/default/xui/en/floater_toybox.xml        |  12 +-
 indra/newview/skins/default/xui/en/strings.xml     |   2 +
 10 files changed, 281 insertions(+), 6 deletions(-)
 create mode 100644 indra/newview/llfloateroutbox.cpp
 create mode 100644 indra/newview/llfloateroutbox.h
 create mode 100644 indra/newview/skins/default/textures/toolbar_icons/outbox.png
 create mode 100644 indra/newview/skins/default/xui/en/floater_merchant_outbox.xml

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 26e6c485f3..83db4548de 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -216,6 +216,7 @@ set(viewer_SOURCE_FILES
     llfloaternotificationsconsole.cpp
     llfloaterobjectweights.cpp
     llfloateropenobject.cpp
+    llfloateroutbox.cpp
     llfloaterpay.cpp
     llfloaterperms.cpp
     llfloaterpostprocess.cpp
@@ -789,6 +790,7 @@ set(viewer_HEADER_FILES
     llfloaternotificationsconsole.h
     llfloaterobjectweights.h
     llfloateropenobject.h
+    llfloateroutbox.h
     llfloaterpay.h
     llfloaterperms.h
     llfloaterpostprocess.h
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index a44b895f7b..c12d22adc3 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -135,6 +135,16 @@
            is_running_function="Floater.IsOpen"
            is_running_parameters="moveview"
            />
+  <command name="outbox"
+           available_in_toybox="true"
+           icon="Command_Outbox_Icon"
+           label_ref="Command_Outbox_Label"
+           tooltip_ref="Command_Outbox_Tooltip"
+           execute_function="Floater.ToggleOrBringToFront"
+           execute_parameters="outbox"
+           is_running_function="Floater.IsOpen"
+           is_running_parameters="outbox"
+           />
   <command name="people"
            available_in_toybox="true"
            icon="Command_People_Icon"
diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
new file mode 100644
index 0000000000..8fea3d674e
--- /dev/null
+++ b/indra/newview/llfloateroutbox.cpp
@@ -0,0 +1,68 @@
+/** 
+ * @file llfloateroutbox.cpp
+ * @brief Implementation of the merchant outbox window
+ *
+ * $LicenseInfo:firstyear=2001&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 "llfloateroutbox.h"
+
+#include "llfloaterreg.h"
+#include "lltransientfloatermgr.h"
+
+
+///----------------------------------------------------------------------------
+/// LLFloaterOutbox
+///----------------------------------------------------------------------------
+
+LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
+	: LLFloater(key)
+	, mPanelOutboxInventory(NULL)
+{
+	LLTransientFloaterMgr::getInstance()->addControlView(this);
+}
+
+LLFloaterOutbox::~LLFloaterOutbox()
+{
+	LLTransientFloaterMgr::getInstance()->removeControlView(this);
+}
+
+BOOL LLFloaterOutbox::postBuild()
+{
+	return TRUE;
+}
+
+void LLFloaterOutbox::onOpen(const LLSD& key)
+{
+	//LLFirstUse::useInventory();
+}
+
+void LLFloaterOutbox::onClose(bool app_quitting)
+{
+	LLFloater::onClose(app_quitting);
+	if (mKey.asInteger() > 1)
+	{
+		destroy();
+	}
+}
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
new file mode 100644
index 0000000000..cb5c2be81c
--- /dev/null
+++ b/indra/newview/llfloateroutbox.h
@@ -0,0 +1,56 @@
+/** 
+ * @file llfloateroutbox.h
+ * @brief LLFloaterOutbox
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&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
+ * ABILITY 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 LL_LLFLOATEROUTBOX_H
+#define LL_LLFLOATEROUTBOX_H
+
+#include "llfloater.h"
+#include "llfoldertype.h"
+
+class LLInventoryPanel;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFloaterOutbox
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLFloaterOutbox : public LLFloater
+{
+public:
+	LLFloaterOutbox(const LLSD& key);
+	~LLFloaterOutbox();
+
+	BOOL postBuild();
+
+	// Inherited functionality
+	/*virtual*/ void onOpen(const LLSD& key);
+	/*virtual*/ void onClose(bool app_quitting);
+
+private:
+	LLInventoryPanel* mPanelOutboxInventory;
+};
+
+#endif // LL_LLFLOATEROUTBOX_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index acbc5f8fb6..24070018c2 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -82,6 +82,7 @@
 #include "llfloaternotificationsconsole.h"
 #include "llfloaterobjectweights.h"
 #include "llfloateropenobject.h"
+#include "llfloateroutbox.h"
 #include "llfloaterpay.h"
 #include "llfloaterperms.h"
 #include "llfloaterpostprocess.h"
@@ -237,6 +238,7 @@ void LLViewerFloaterReg::registerFloaters()
 
 	LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>);
 	LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
+	LLFloaterReg::add("outbox", "floater_merchant_outbox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutbox>);
 	LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>);
 	LLFloaterPayUtil::registerFloater();
 
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 8702ebde2a..5da1276881 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -137,6 +137,7 @@ with the same filename but different name
   <texture name="Command_MiniCart_Icon"     file_name="toolbar_icons/mini_cart.png"    preload="true" />
   <texture name="Command_MiniMap_Icon"      file_name="toolbar_icons/mini_map.png"     preload="true" />
   <texture name="Command_Move_Icon"         file_name="toolbar_icons/move.png"         preload="true" />
+  <texture name="Command_Outbox_Icon"       file_name="toolbar_icons/outbox.png"       preload="true" />
   <texture name="Command_People_Icon"       file_name="toolbar_icons/people.png"       preload="true" />
   <texture name="Command_Picks_Icon"        file_name="toolbar_icons/picks.png"        preload="true" />
   <texture name="Command_Places_Icon"       file_name="toolbar_icons/places.png"       preload="true" />
diff --git a/indra/newview/skins/default/textures/toolbar_icons/outbox.png b/indra/newview/skins/default/textures/toolbar_icons/outbox.png
new file mode 100644
index 0000000000..9fcf46794d
Binary files /dev/null and b/indra/newview/skins/default/textures/toolbar_icons/outbox.png differ
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
new file mode 100644
index 0000000000..2f8a83c072
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<floater
+ open_positioning="cascading"
+ can_close="true"
+ can_resize="true"
+ height="400"
+ help_topic="floater_merchant_outbox"
+ min_width="333"
+ min_height="440"
+ name="floater_merchant_outbox"
+ save_rect="true"
+ save_visibility="true"
+ reuse_instance="true"
+ title="MERCHANT OUTBOX"
+ width="333" >
+ <panel
+      follows="all"
+      layout="topleft"
+      left="0"
+      name="marketplace_outbox"
+      class="panel_marketplace_outbox"
+      top="0"
+      label=""
+      height="400"
+      width="330">
+     <string name="OutboxLabelWithArg">Merchant outbox ([NUM])</string>
+     <string name="OutboxLabelNoArg">Merchant outbox</string>
+     <button
+        label="Merchant outbox"
+        font="SansSerifMedium"
+        name="outbox_btn"
+        height="35"
+        width="308"
+        image_unselected="MarketplaceBtn_Off"
+        image_selected="MarketplaceBtn_Selected"
+        halign="left"
+        handle_right_mouse="false"
+        follows="top|left|right"
+        is_toggle="true"
+        tab_stop="false"
+        pad_left="35"
+        top="0"
+        left="10" />
+     <button
+         image_unselected="OutboxPush_Off"
+         image_selected="OutboxPush_Selected"
+         image_hover_selected="OutboxPush_Selected_Over"
+         image_hover_unselected="OutboxPush_Over"
+         image_disabled_selected="OutboxPush_Selected_Disabled"
+         image_disabled="OutboxPush_Disabled"
+         image_pressed="OutboxPush_Press"
+         image_pressed_selected="OutboxPush_Selected_Press"
+         label=""
+         tool_tip="Push to my Marketplace Storefront"
+         is_toggle="false"
+         name="outbox_sync_btn"
+         follows="top|right"
+         tab_stop="false"
+         halign="center"
+         top="6"
+         left="-50"
+         height="23"
+         width="32"
+         enabled="false" />
+     <loading_indicator
+        follows="top|right"
+        name="outbox_sync_indicator"
+        top="6"
+        left="-50"
+        height="23"
+        width="32"
+        images_per_sec="1.15"
+        tab_stop="false"
+        visible="false">
+         <images>
+             <image name="OutboxPush_Progress_1"/>
+             <image name="OutboxPush_Progress_2"/>
+             <image name="OutboxPush_Progress_3"/>
+             <image name="OutboxPush_Progress_4"/>
+             <image name="OutboxPush_Progress_5"/>
+             <image name="OutboxPush_Progress_6"/>
+         </images>
+     </loading_indicator>
+     <panel
+        follows="all"
+        left="10"
+        bottom="400"
+        width="308"
+        top="35"
+        bg_opaque_color="InventoryBackgroundColor"
+        background_visible="true"
+        background_opaque="true"
+        >
+		<panel
+			name="outbox_inventory_placeholder_panel"
+			follows="all"
+			layout="topleft"
+			top="0"
+			left="0"
+			width="308"
+			height="365"
+			bg_opaque_color="InventoryBackgroundColor"
+			background_visible="true"
+			background_opaque="true"
+			>
+			<text
+				name="outbox_inventory_placeholder_title"
+				type="string"
+				follows="all"
+				layout="topleft"
+				top="10"
+				left="0"
+				width="308"
+				height="25"
+				wrap="true"
+				halign="center"
+				font="SansSerifBold">
+				Loading...
+			</text>
+			<text
+				name="outbox_inventory_placeholder_text"
+				type="string"
+				follows="all"
+				layout="topleft"
+				top="35"
+				left="0"
+				width="308"
+				height="130"
+				wrap="true"
+				halign="left" />
+		</panel>
+    </panel>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_toybox.xml b/indra/newview/skins/default/xui/en/floater_toybox.xml
index 493d44a9cf..72e6187a14 100644
--- a/indra/newview/skins/default/xui/en/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/en/floater_toybox.xml
@@ -5,7 +5,7 @@
   can_minimize="false"
   can_resize="false"
   default_tab_group="1"
-  height="330"
+  height="375"
   help_topic="toybox"
   layout="topleft"
   legacy_header_height="18"
@@ -46,7 +46,7 @@
       Buttons will appear as shown or as icon-only depending on each toolbar's settings.
   </text>
   <toolbar
-    bottom="265"
+    bottom="310"
     button_display_mode="icons_with_text"
     follows="all"
     left="20"
@@ -82,11 +82,11 @@
   <panel
     bevel_style="none"
     border="true"
-    bottom="266"
+    bottom="311"
     follows="left|bottom|right"
     left="20"
     right="-20"
-    top="266" />
+    top="311" />
   <button
     follows="left|bottom|right"
     height="23"
@@ -95,7 +95,7 @@
     layout="topleft"
     left="185"
     name="btn_clear_all"
-    top="285"
+    top="330"
     width="130">
     <button.commit_callback function="Toybox.ClearAll" />
   </button>
@@ -107,7 +107,7 @@
     layout="topleft"
     left="335"
     name="btn_restore_defaults"
-    top="285"
+    top="330"
     width="130">
     <button.commit_callback function="Toybox.RestoreDefaults" />
   </button>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index befcc5dd87..105c6095e6 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3675,6 +3675,7 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Marketplace_Label">Marketplace</string>
   <string name="Command_MiniMap_Label">Mini-map</string>
   <string name="Command_Move_Label">Move</string>
+  <string name="Command_Outbox_Label">Merchant outbox</string>
   <string name="Command_People_Label">People</string>
   <string name="Command_Picks_Label">Picks</string>
   <string name="Command_Places_Label">Places</string>
@@ -3700,6 +3701,7 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Marketplace_Tooltip">Go shopping</string>
   <string name="Command_MiniMap_Tooltip">Show nearby people</string>
   <string name="Command_Move_Tooltip">Moving your avatar</string>
+  <string name="Command_Outbox_Tooltip">Transfer items to your marketplace for sale</string>
   <string name="Command_People_Tooltip">Friends, groups, and nearby people</string>
   <string name="Command_Picks_Tooltip">Places to show as favorites in your profile</string>
   <string name="Command_Places_Tooltip">Places you've saved</string>
-- 
cgit v1.2.3


From 5535722ea5c2f64a25ca569c930e969f2e989af9 Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Thu, 1 Dec 2011 12:31:56 +0000
Subject: STORM-1708 Linux UI additions

---
 indra/newview/llfilepicker.cpp                 | 14 +++++++++++++-
 indra/newview/skins/default/xui/en/strings.xml |  5 +++--
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 3cbc4e5648..d259e02452 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -1197,7 +1197,12 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
 	add_common_filters_to_gtkchooser(gfilter, picker, filtername);
 	return filtername;
 }
-
+ 
+static std::string add_script_filter_to_gtkchooser(GtkWindow *picker)
+{
+	return add_simple_mime_filter_to_gtkchooser(picker,  "text/plain",
+							LLTrans::getString("script_files") + " (*.lsl)");
+}
 
 BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )
 {
@@ -1263,6 +1268,10 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename
 				 LLTrans::getString("compressed_image_files") + " (*.j2c)");
 			suggest_ext = ".j2c";
 			break;
+		case FFSAVE_SCRIPT:
+			caption += add_script_filter_to_gtkchooser(picker);
+			suggest_ext = ".lsl";
+			break;
 		default:;
 			break;
 		}
@@ -1328,6 +1337,9 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
 		case FFLOAD_IMAGE:
 			filtername = add_imageload_filter_to_gtkchooser(picker);
 			break;
+		case FFLOAD_SCRIPT:
+			filtername = add_script_filter_to_gtkchooser(picker);
+			break;
 		default:;
 			break;
 		}
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index befcc5dd87..0d26465dfa 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -427,9 +427,10 @@ Please try logging in again in a minute.</string>
 	<string name="compressed_image_files">Compressed Images</string>
 	<string name="load_files">Load Files</string>
 	<string name="choose_the_directory">Choose Directory</string>
+  <string name="script_files">Scripts</string>
 
-	<!-- LSL Usage Hover Tips -->
-	<!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window).
+  <!-- LSL Usage Hover Tips -->
+  <!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window).
              This has no effect on viewer code, but prevents Linden Lab internal localization tool from scraping these strings.  -->
 	<string name="LSLTipSleepTime" translate="false">
 Sleeps script for [SLEEP_TIME] seconds.
-- 
cgit v1.2.3


From 591891306366e683416b187207fa2b94bdc263a8 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 5 Dec 2011 13:37:37 -0800
Subject: First pass at connecting to the new marketplace API

---
 indra/newview/llinventorybridge.cpp                |   2 +-
 indra/newview/llmarketplacefunctions.cpp           |  24 ++--
 indra/newview/llmarketplacefunctions.h             |  17 ++-
 indra/newview/llpanelmarketplaceoutbox.cpp         | 158 ++++++++++++++++-----
 indra/newview/llpanelmarketplaceoutbox.h           |  19 ++-
 indra/newview/llsidepanelinventory.cpp             |   2 +-
 indra/newview/llviewermedia.cpp                    |  61 --------
 .../newview/skins/default/xui/en/notifications.xml |  18 ++-
 .../skins/default/xui/en/sidepanel_inventory.xml   |   4 +-
 9 files changed, 170 insertions(+), 135 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 0eaa0a4627..017dabe2ad 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -71,7 +71,7 @@
 #include "llwearablelist.h"
 
 // Marketplace outbox current disabled
-#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_PANEL
+#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1	// keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL
 
 typedef std::pair<LLUUID, LLUUID> two_uuids_t;
 typedef std::list<two_uuids_t> two_uuids_list_t;
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 99b0389413..1c189f6ee2 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -50,8 +50,9 @@ std::string getMarketplaceBaseURL()
 		}
 	}
 
-	url += "api/1/users/";
+	url += "api/1/";
 	url += gAgent.getID().getString();
+	url += "/inventory";
 
 	return url;
 }
@@ -60,29 +61,20 @@ std::string getMarketplaceURL_InventoryImport()
 {
 	std::string url = getMarketplaceBaseURL();
 
-	url += "/inventory_import";
-
-	return url;
-}
-
-std::string getMarketplaceURL_UserStatus()
-{
-	std::string url = getMarketplaceBaseURL();
-
-	url += "/user_status";
+	url += "/import";
 
 	return url;
 }
 
 
-static bool gMarketplaceSyncEnabled = true;
+static bool gMarketplaceImportEnabled = true;
 
-bool getMarketplaceSyncEnabled()
+bool getMarketplaceImportEnabled()
 {
-	return gMarketplaceSyncEnabled;
+	return gMarketplaceImportEnabled;
 }
 
-void setMarketplaceSyncEnabled(bool syncEnabled)
+void setMarketplaceImportEnabled(bool importEnabled)
 {
-	gMarketplaceSyncEnabled = syncEnabled;
+	gMarketplaceImportEnabled = importEnabled;
 }
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index e80e6a471c..fda2fbb935 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -30,11 +30,20 @@
 
 
 std::string getMarketplaceURL_InventoryImport();
-std::string getMarketplaceURL_UserStatus();
-
-bool getMarketplaceSyncEnabled();
-void setMarketplaceSyncEnabled(bool syncEnabled);
 
+bool getMarketplaceImportEnabled();
+void setMarketplaceImportEnabled(bool syncEnabled);
+
+namespace MarketplaceErrorCodes
+{
+	enum eCodes
+	{
+		IMPORT_DONE = 200,
+		IMPORT_PROCESSING = 202,
+		IMPORT_DONE_WITH_ERRORS = 409,
+		IMPORT_JOB_FAILED = 410,
+	};
+}
 
 #endif // LL_LLMARKETPLACEFUNCTIONS_H
 
diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
index 0ad4d56051..3c8817c199 100644
--- a/indra/newview/llpanelmarketplaceoutbox.cpp
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -59,9 +59,12 @@ const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultPara
 LLPanelMarketplaceOutbox::LLPanelMarketplaceOutbox(const Params& p)
 	: LLPanel(p)
 	, mInventoryPanel(NULL)
-	, mSyncButton(NULL)
-	, mSyncIndicator(NULL)
-	, mSyncInProgress(false)
+	, mImportButton(NULL)
+	, mImportFrameTimer(0)
+	, mImportGetPending(false)
+	, mImportIndicator(NULL)
+	, mImportInProgress(false)
+	, mOutboxButton(NULL)
 {
 }
 
@@ -81,11 +84,13 @@ BOOL LLPanelMarketplaceOutbox::postBuild()
 
 void LLPanelMarketplaceOutbox::handleLoginComplete()
 {
-	mSyncButton = getChild<LLButton>("outbox_sync_btn");
-	mSyncButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onSyncButtonClicked, this));
-	mSyncButton->setEnabled(getMarketplaceSyncEnabled() && !isOutboxEmpty());
+	mImportButton = getChild<LLButton>("outbox_import_btn");
+	mImportButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onImportButtonClicked, this));
+	mImportButton->setEnabled(getMarketplaceImportEnabled() && !isOutboxEmpty());
 	
-	mSyncIndicator = getChild<LLLoadingIndicator>("outbox_sync_indicator");
+	mImportIndicator = getChild<LLLoadingIndicator>("outbox_import_indicator");
+	
+	mOutboxButton = getChild<LLButton>("outbox_btn");
 }
 
 void LLPanelMarketplaceOutbox::onFocusReceived()
@@ -164,9 +169,9 @@ bool LLPanelMarketplaceOutbox::isOutboxEmpty() const
 	return (getTotalItemCount() == 0);
 }
 
-bool LLPanelMarketplaceOutbox::isSyncInProgress() const
+bool LLPanelMarketplaceOutbox::isImportInProgress() const
 {
-	return mSyncInProgress;
+	return mImportInProgress;
 }
 
 
@@ -185,25 +190,55 @@ void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
 		waitForEventOn(self, "mainloop");
 	}
 
-	outboxPanel->onSyncComplete(true, LLSD::emptyMap());
+	outboxPanel->onImportPostComplete(MarketplaceErrorCodes::IMPORT_DONE, LLSD::emptyMap());
 
 	gTimeDelayDebugFunc = "";
 }
 
 
-class LLInventorySyncResponder : public LLHTTPClient::Responder
+class LLInventoryImportPostResponder : public LLHTTPClient::Responder
 {
 public:
-	LLInventorySyncResponder(LLPanelMarketplaceOutbox * outboxPanel)
+	LLInventoryImportPostResponder(LLPanelMarketplaceOutbox * outboxPanel)
 		: LLCurl::Responder()
 		, mOutboxPanel(outboxPanel)
 	{
 	}
-
+	
 	void completed(U32 status, const std::string& reason, const LLSD& content)
 	{
-		llinfos << "inventory_import complete status: " << status << ", reason: " << reason << llendl;
+		llinfos << "inventory/import post status: " << status << ", reason: " << reason << llendl;
+		
+		if (isGoodStatus(status))
+		{
+			// Complete success
+			llinfos << "success" << llendl;
+		}	
+		else
+		{
+			llwarns << "failed" << llendl;
+		}
+		
+		mOutboxPanel->onImportPostComplete(status, content);
+	}
+
+private:
+	LLPanelMarketplaceOutbox *	mOutboxPanel;	
+};
 
+class LLInventoryImportGetResponder : public LLHTTPClient::Responder
+{
+public:
+	LLInventoryImportGetResponder(LLPanelMarketplaceOutbox * outboxPanel)
+		: LLCurl::Responder()
+		, mOutboxPanel(outboxPanel)
+	{
+	}
+
+	void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		llinfos << "inventory/import get status: " << status << ", reason: " << reason << llendl;
+		
 		if (isGoodStatus(status))
 		{
 			// Complete success
@@ -214,37 +249,67 @@ public:
 			llwarns << "failed" << llendl;
 		}
 
-		mOutboxPanel->onSyncComplete(isGoodStatus(status), content);
+		mOutboxPanel->onImportGetComplete(status, content);
 	}
 
 private:
 	LLPanelMarketplaceOutbox *	mOutboxPanel;
 };
 
-void LLPanelMarketplaceOutbox::onSyncButtonClicked()
+void LLPanelMarketplaceOutbox::onImportButtonClicked()
 {
-	// Get the sync animation going
-	mSyncInProgress = true;
-	updateSyncButtonStatus();
+	// Get the import animation going
+	mImportInProgress = true;
+	mImportFrameTimer = 0;
+
+	updateImportButtonStatus();
 
 	// Make the url for the inventory import request
 	std::string url = getMarketplaceURL_InventoryImport();
 
-	llinfos << "http get:  " << url << llendl;
-	LLHTTPClient::get(url, new LLInventorySyncResponder(this), LLViewerMedia::getHeaders());
+	llinfos << "http post:  " << url << llendl;
+	LLHTTPClient::post(url, LLSD(), new LLInventoryImportPostResponder(this), LLViewerMedia::getHeaders());
 
 	// Set a timer (for testing only)
     //gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this));
 }
 
-void LLPanelMarketplaceOutbox::onSyncComplete(bool goodStatus, const LLSD& content)
+void LLPanelMarketplaceOutbox::onImportPostComplete(U32 status, const LLSD& content)
 {
-	mSyncInProgress = false;
-	updateSyncButtonStatus();
+	llinfos << "onImportPostComplete status = " << status << llendl;
+	llinfos << "onImportPostComplete content = " << content.asString() << llendl;
+}
+
+void LLPanelMarketplaceOutbox::onImportGetComplete(U32 status, const LLSD& content)
+{
+	mImportGetPending = false;	
+	mImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
+	updateImportButtonStatus();
+	
+	if (!mImportInProgress)
+	{
+		if (status == MarketplaceErrorCodes::IMPORT_DONE)
+		{
+			LLNotificationsUtil::add("OutboxImportComplete", LLSD::emptyMap(), LLSD::emptyMap());
+		}
+		else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
+		{
+			LLNotificationsUtil::add("OutboxImportHadErrors", LLSD::emptyMap(), LLSD::emptyMap());
+		}
+		else
+		{
+			llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
+			LLNotificationsUtil::add("OutboxImportFailed", LLSD::emptyMap(), LLSD::emptyMap());
+		}
+	}
+	
+	return;
+	
+	
 	
 	const LLSD& errors_list = content["errors"];
 
-	if (goodStatus && (errors_list.size() == 0))
+	if (errors_list.size() == 0)
 	{
 		LLNotificationsUtil::add("OutboxUploadComplete", LLSD::emptyMap(), LLSD::emptyMap());
 	}
@@ -287,23 +352,23 @@ void LLPanelMarketplaceOutbox::onSyncComplete(bool goodStatus, const LLSD& conte
 	}
 }
 
-void LLPanelMarketplaceOutbox::updateSyncButtonStatus()
+void LLPanelMarketplaceOutbox::updateImportButtonStatus()
 {
-	if (isSyncInProgress())
+	if (isImportInProgress())
 	{
-		mSyncButton->setVisible(false);
+		mImportButton->setVisible(false);
 
-		mSyncIndicator->setVisible(true);
-		mSyncIndicator->reset();
-		mSyncIndicator->start();
+		mImportIndicator->setVisible(true);
+		mImportIndicator->reset();
+		mImportIndicator->start();
 	}
 	else
 	{
-		mSyncIndicator->stop();
-		mSyncIndicator->setVisible(false);
+		mImportIndicator->stop();
+		mImportIndicator->setVisible(false);
 
-		mSyncButton->setVisible(true);
-		mSyncButton->setEnabled(getMarketplaceSyncEnabled() && !isOutboxEmpty());
+		mImportButton->setVisible(true);
+		mImportButton->setEnabled(getMarketplaceImportEnabled() && !isOutboxEmpty());
 	}
 }
 
@@ -335,17 +400,32 @@ void LLPanelMarketplaceOutbox::draw()
 
 		LLStringUtil::format_map_t args;
 		args["[NUM]"] = item_count_str;
-		getChild<LLButton>("outbox_btn")->setLabel(getString("OutboxLabelWithArg", args));
+		mOutboxButton->setLabel(getString("OutboxLabelWithArg", args));
 	}
 	else
 	{
-		getChild<LLButton>("outbox_btn")->setLabel(getString("OutboxLabelNoArg"));
+		mOutboxButton->setLabel(getString("OutboxLabelNoArg"));
 	}
 	
-	if (!isSyncInProgress())
+	if (!isImportInProgress())
 	{
-		mSyncButton->setEnabled(getMarketplaceSyncEnabled() && not_empty);
+		mImportButton->setEnabled(getMarketplaceImportEnabled() && not_empty);
 	}
+	else
+	{
+		++mImportFrameTimer;
+		
+		if ((mImportFrameTimer % 50 == 0) && !mImportGetPending)
+		{
+			mImportGetPending = true;
+
+			std::string url = getMarketplaceURL_InventoryImport();
+			
+			llinfos << "http get:  " << url << llendl;
+			LLHTTPClient::get(url, new LLInventoryImportGetResponder(this), LLViewerMedia::getHeaders());
+		}
+	}
+
 	
 	LLPanel::draw();
 }
diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h
index c6b4a5abe2..a776ee0919 100644
--- a/indra/newview/llpanelmarketplaceoutbox.h
+++ b/indra/newview/llpanelmarketplaceoutbox.h
@@ -59,9 +59,10 @@ public:
 	U32 getTotalItemCount() const;
 
 	bool isOutboxEmpty() const;
-	bool isSyncInProgress() const;
+	bool isImportInProgress() const;
 
-	void onSyncComplete(bool goodStatus, const LLSD& content);
+	void onImportPostComplete(U32 status, const LLSD& content);
+	void onImportGetComplete(U32 status, const LLSD& content);
 
 	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 								   EDragAndDropType cargo_type,
@@ -70,8 +71,8 @@ public:
 								   std::string& tooltip_msg);
 
 protected:
-	void onSyncButtonClicked();
-	void updateSyncButtonStatus();
+	void onImportButtonClicked();
+	void updateImportButtonStatus();
 
 	void handleLoginComplete();
 	void onFocusReceived();
@@ -80,9 +81,13 @@ protected:
 private:
 	LLInventoryPanel *		mInventoryPanel;
 
-	LLButton *				mSyncButton;
-	LLLoadingIndicator *	mSyncIndicator;
-	bool					mSyncInProgress;
+	LLButton *				mImportButton;
+	U32						mImportFrameTimer;
+	bool					mImportGetPending;
+	LLLoadingIndicator *	mImportIndicator;
+	bool					mImportInProgress;
+	
+	LLButton *				mOutboxButton;
 };
 
 
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index d556b8523e..19a81b93bf 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -69,7 +69,7 @@ static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_
 #define AUTO_EXPAND_INBOX	0
 
 // Temporarily disabling the outbox until we straighten out the API
-#define ENABLE_MERCHANT_OUTBOX_PANEL		1	// keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+#define ENABLE_MERCHANT_OUTBOX_PANEL		1	// keep in sync with ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
 
 static const char * const INBOX_BUTTON_NAME = "inbox_btn";
 static const char * const OUTBOX_BUTTON_NAME = "outbox_btn";
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index a5bd0223cc..02d8036666 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1386,64 +1386,6 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom
 }
 
 
-// This is defined in two files but I don't want to create a dependence between this and llsidepanelinventory
-// just to be able to temporarily disable the outbox.
-#define ENABLE_INVENTORY_DISPLAY_OUTBOX		1	// keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
-
-class LLInventoryUserStatusResponder : public LLHTTPClient::Responder
-{
-public:
-	LLInventoryUserStatusResponder()
-		: LLCurl::Responder()
-	{
-	}
-
-	void completed(U32 status, const std::string& reason, const LLSD& content)
-	{
-		if (isGoodStatus(status))
-		{
-			std::string merchantStatus = content[gAgent.getID().getString()].asString();
-			llinfos << "Marketplace merchant status: " << merchantStatus << llendl;
-
-			// Save the merchant status before turning on the display
-			gSavedSettings.setString("InventoryMarketplaceUserStatus", merchantStatus);
-
-			// Complete success
-			gSavedSettings.setBOOL("InventoryDisplayInbox", true);
-
-#if ENABLE_INVENTORY_DISPLAY_OUTBOX
-			gSavedSettings.setBOOL("InventoryDisplayOutbox", true);
-#endif
-
-			setMarketplaceSyncEnabled(true);
-		}
-		else if (status == 401)
-		{
-			// API is available for use but OpenID authorization failed
-			gSavedSettings.setBOOL("InventoryDisplayInbox", true);
-
-			setMarketplaceSyncEnabled(false);
-		}
-		else
-		{
-			setMarketplaceSyncEnabled(false);
-
-			// API in unavailable
-			llinfos << "Marketplace API is unavailable -- Inbox may be disabled, status = " << status << ", reason = " << reason << llendl;
-		}
-	}
-};
-
-
-void doOnetimeEarlyHTTPRequests()
-{
-	std::string url = getMarketplaceURL_UserStatus();
-
-	llinfos << "http get: " << url << llendl;
-	LLHTTPClient::get(url, new LLInventoryUserStatusResponder(), LLViewerMedia::getHeaders());
-}
-
-
 LLSD LLViewerMedia::getHeaders()
 {
 	LLSD headers = LLSD::emptyMap();
@@ -1502,9 +1444,6 @@ void LLViewerMedia::setOpenIDCookie()
 		LLHTTPClient::get(profile_url,  
 			new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
 			headers);
-
-		// FUI: No longer perform the user_status query
-		//doOnetimeEarlyHTTPRequests();
 	}
 }
 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index d925bf8f96..46a6da2450 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -213,9 +213,9 @@ Save changes to current clothing/body part?
 
   <notification
    icon="alertmodal.tga"
-   name="OutboxUploadComplete"
+   name="OutboxImportComplete"
    type="alertmodal">
-Marketplace upload complete.
+Marketplace import complete.
         <usetemplate
          name="okbutton"
          yestext="Hooray!"/>
@@ -223,14 +223,24 @@ Marketplace upload complete.
 
   <notification
    icon="alertmodal.tga"
-   name="OutboxUploadHadErrors"
+   name="OutboxImportHadErrors"
    type="alertmodal">
-Marketplace upload completed with errors!  Please correct the problems in your outbox and retry.  Thanks.
+Marketplace import completed with errors!  Please correct the problems in your outbox and retry.  Thanks.
         <usetemplate
          name="okbutton"
          yestext="Boo!"/>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="OutboxImportFailed"
+   type="alertmodal">
+Marketplace import failed!  Please try again later.  Thanks.
+        <usetemplate
+         name="okbutton"
+         yestext="Rats!"/>
+  </notification>
+
     
 
     <notification
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index b52784d6bc..9f3c57fa0f 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -205,7 +205,7 @@
                          label=""
                          tool_tip="Push to my Marketplace Storefront"
                          is_toggle="false"
-                         name="outbox_sync_btn"
+                         name="outbox_import_btn"
                          follows="top|right"
                          tab_stop="false"
                          halign="center"
@@ -216,7 +216,7 @@
                          enabled="false" />
                      <loading_indicator
                         follows="top|right"
-                        name="outbox_sync_indicator"
+                        name="outbox_import_indicator"
                         top="6"
                         left="-50"
                         height="23"
-- 
cgit v1.2.3


From b4e106ec35920fdc7aa3c98d7de1778ed309c906 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 5 Dec 2011 17:07:40 -0500
Subject: SH-2747 FIX

---
 indra/newview/llavatariconctrl.cpp | 3 +++
 1 file changed, 3 insertions(+)
 mode change 100644 => 100755 indra/newview/llavatariconctrl.cpp

diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
old mode 100644
new mode 100755
index 42e7decec1..b539ac38ed
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -75,6 +75,9 @@ void LLAvatarIconIDCache::load	()
 		LLUUID icon_id;
 		LLDate date;
 
+		if (line.length()<=uuid_len*2)
+			continue; // short line, bail out to prevent substr calls throwing exception.
+
 		std::string avatar_id_str = line.substr(0,uuid_len);
 		std::string icon_id_str = line.substr(uuid_len,uuid_len);
 		
-- 
cgit v1.2.3


From 3236cbd585860f76a14c4837c70cb5823a4fd7d5 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 5 Dec 2011 14:23:49 -0800
Subject: Windows build fix

---
 indra/newview/llpanelmarketplaceoutbox.cpp | 89 +++++++++++++++---------------
 1 file changed, 43 insertions(+), 46 deletions(-)

diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
index 3c8817c199..6a2bf58701 100644
--- a/indra/newview/llpanelmarketplaceoutbox.cpp
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -303,53 +303,50 @@ void LLPanelMarketplaceOutbox::onImportGetComplete(U32 status, const LLSD& conte
 		}
 	}
 	
-	return;
-	
-	
-	
-	const LLSD& errors_list = content["errors"];
-
-	if (errors_list.size() == 0)
-	{
-		LLNotificationsUtil::add("OutboxUploadComplete", LLSD::emptyMap(), LLSD::emptyMap());
-	}
-	else
-	{
-		LLNotificationsUtil::add("OutboxUploadHadErrors", LLSD::emptyMap(), LLSD::emptyMap());
-	}
-
-	llinfos << "Marketplace upload llsd:" << llendl;
-	llinfos << ll_pretty_print_sd(content) << llendl;
-	llinfos << llendl;
 
-	const LLSD& imported_list = content["imported"];
-	LLSD::array_const_iterator it = imported_list.beginArray();
-	for ( ; it != imported_list.endArray(); ++it)
-	{
-		LLUUID imported_folder = (*it).asUUID();
-		llinfos << "Successfully uploaded folder " << imported_folder.asString() << " to marketplace." << llendl;
-	}
-
-	for (it = errors_list.beginArray(); it != errors_list.endArray(); ++it)
-	{
-		const LLSD& item_error_map = (*it);
-
-		LLUUID error_folder = item_error_map["folder_id"].asUUID();
-		const std::string& error_string = item_error_map["identifier"].asString();
-		LLUUID error_item = item_error_map["item_id"].asUUID();
-		const std::string& error_item_name = item_error_map["item_name"].asString();
-		const std::string& error_message = item_error_map["message"].asString();
-
-		llinfos << "Error item " << error_folder.asString() << ", " << error_string << ", "
-				<< error_item.asString() << ", " << error_item_name << ", " << error_message << llendl;
-		
-		LLFolderViewFolder * item_folder = mInventoryPanel->getRootFolder()->getFolderByID(error_folder);
-		LLOutboxFolderViewFolder * outbox_item_folder = dynamic_cast<LLOutboxFolderViewFolder *>(item_folder);
-
-		llassert(outbox_item_folder);
-
-		outbox_item_folder->setErrorString(error_string);
-	}
+	//const LLSD& errors_list = content["errors"];
+
+	//if (errors_list.size() == 0)
+	//{
+	//	LLNotificationsUtil::add("OutboxUploadComplete", LLSD::emptyMap(), LLSD::emptyMap());
+	//}
+	//else
+	//{
+	//	LLNotificationsUtil::add("OutboxUploadHadErrors", LLSD::emptyMap(), LLSD::emptyMap());
+	//}
+
+	//llinfos << "Marketplace upload llsd:" << llendl;
+	//llinfos << ll_pretty_print_sd(content) << llendl;
+	//llinfos << llendl;
+
+	//const LLSD& imported_list = content["imported"];
+	//LLSD::array_const_iterator it = imported_list.beginArray();
+	//for ( ; it != imported_list.endArray(); ++it)
+	//{
+	//	LLUUID imported_folder = (*it).asUUID();
+	//	llinfos << "Successfully uploaded folder " << imported_folder.asString() << " to marketplace." << llendl;
+	//}
+
+	//for (it = errors_list.beginArray(); it != errors_list.endArray(); ++it)
+	//{
+	//	const LLSD& item_error_map = (*it);
+
+	//	LLUUID error_folder = item_error_map["folder_id"].asUUID();
+	//	const std::string& error_string = item_error_map["identifier"].asString();
+	//	LLUUID error_item = item_error_map["item_id"].asUUID();
+	//	const std::string& error_item_name = item_error_map["item_name"].asString();
+	//	const std::string& error_message = item_error_map["message"].asString();
+
+	//	llinfos << "Error item " << error_folder.asString() << ", " << error_string << ", "
+	//			<< error_item.asString() << ", " << error_item_name << ", " << error_message << llendl;
+	//	
+	//	LLFolderViewFolder * item_folder = mInventoryPanel->getRootFolder()->getFolderByID(error_folder);
+	//	LLOutboxFolderViewFolder * outbox_item_folder = dynamic_cast<LLOutboxFolderViewFolder *>(item_folder);
+
+	//	llassert(outbox_item_folder);
+
+	//	outbox_item_folder->setErrorString(error_string);
+	//}
 }
 
 void LLPanelMarketplaceOutbox::updateImportButtonStatus()
-- 
cgit v1.2.3


From 01d68a9f1572fba971ace6944a91a85e7c379d1e Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Mon, 5 Dec 2011 16:28:13 -0700
Subject: call LLViewerTexture::isMemoryForTextureLow() less often and only for
 ATI cards.

---
 indra/newview/llviewertexture.cpp | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index f4bbc2b067..addf1147f2 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -420,8 +420,17 @@ F32 texmem_middle_bound_scale = 0.925f;
 //static 
 bool LLViewerTexture::isMemoryForTextureLow()
 {
-	const static S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB
-	const static S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB
+	const F32 WAIT_TIME = 1.0f ; //second
+	static LLFrameTimer timer ;
+
+	if(timer.getElapsedTimeF32() < WAIT_TIME) //call this once per second.
+	{
+		return false;
+	}
+	timer.reset() ;
+
+	const S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB
+	const S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB	
 
 	bool low_mem = false ;
 	if (gGLManager.mHasATIMemInfo)
@@ -433,6 +442,15 @@ bool LLViewerTexture::isMemoryForTextureLow()
 		{
 			low_mem = true ;
 		}
+
+		if(!low_mem) //check main memory, only works for windows.
+		{
+			LLMemory::updateMemoryInfo() ;
+			if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy)
+			{
+				low_mem = true ;
+			}
+		}
 	}
 #if 0  //ignore nVidia cards
 	else if (gGLManager.mHasNVXMemInfo)
@@ -445,16 +463,7 @@ bool LLViewerTexture::isMemoryForTextureLow()
 			low_mem = true ;
 		}
 	}
-#endif
-
-	if(!low_mem) //check main memory, only works for windows.
-	{
-		LLMemory::updateMemoryInfo() ;
-		if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy)
-		{
-			low_mem = true ;
-		}
-	}
+#endif	
 
 	return low_mem ;
 }
-- 
cgit v1.2.3


From 78233d1bf9930575ee7250257ac68603f41f568a Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Mon, 5 Dec 2011 17:55:40 -0600
Subject: SH-2652 WIP -- Add timers to relevant areas, pause render pipeline
 while occlusion queries from previous frame are still pending and perform
 texture decode work.

---
 indra/llcommon/llqueuedthread.cpp    |  4 ++--
 indra/llcommon/llqueuedthread.h      |  4 ++--
 indra/llcommon/llworkerthread.cpp    |  2 +-
 indra/llcommon/llworkerthread.h      |  2 +-
 indra/llimage/llimageworker.cpp      |  2 +-
 indra/llimage/llimageworker.h        |  2 +-
 indra/llmessage/llcurl.cpp           |  2 +-
 indra/llmessage/llcurl.h             |  2 +-
 indra/newview/llappviewer.cpp        |  8 +++++---
 indra/newview/llspatialpartition.cpp | 26 ++++++++++++++++++++++++++
 indra/newview/llspatialpartition.h   |  2 ++
 indra/newview/lltexturecache.cpp     |  2 +-
 indra/newview/lltexturecache.h       |  2 +-
 indra/newview/lltexturefetch.cpp     |  2 +-
 indra/newview/lltexturefetch.h       |  2 +-
 indra/newview/llviewertexture.cpp    | 14 +++++++++++++-
 16 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 5dee7a3541..1738c16dea 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -109,7 +109,7 @@ void LLQueuedThread::shutdown()
 
 // MAIN THREAD
 // virtual
-S32 LLQueuedThread::update(U32 max_time_ms)
+S32 LLQueuedThread::update(F32 max_time_ms)
 {
 	if (!mStarted)
 	{
@@ -122,7 +122,7 @@ S32 LLQueuedThread::update(U32 max_time_ms)
 	return updateQueue(max_time_ms);
 }
 
-S32 LLQueuedThread::updateQueue(U32 max_time_ms)
+S32 LLQueuedThread::updateQueue(F32 max_time_ms)
 {
 	F64 max_time = (F64)max_time_ms * .001;
 	LLTimer timer;
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index 499d13a792..d3704b0fe2 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -173,8 +173,8 @@ protected:
 public:
 	bool waitForResult(handle_t handle, bool auto_complete = true);
 
-	virtual S32 update(U32 max_time_ms);
-	S32 updateQueue(U32 max_time_ms);
+	virtual S32 update(F32 max_time_ms);
+	S32 updateQueue(F32 max_time_ms);
 	
 	void waitOnPending();
 	void printQueueStats();
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index 4988bdf570..3d05a30ac2 100644
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -81,7 +81,7 @@ void LLWorkerThread::clearDeleteList()
 }
 
 // virtual
-S32 LLWorkerThread::update(U32 max_time_ms)
+S32 LLWorkerThread::update(F32 max_time_ms)
 {
 	S32 res = LLQueuedThread::update(max_time_ms);
 	// Delete scheduled workers
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index 78a4781d15..be46394d6e 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -86,7 +86,7 @@ public:
 	LLWorkerThread(const std::string& name, bool threaded = true, bool should_pause = false);
 	~LLWorkerThread();
 
-	/*virtual*/ S32 update(U32 max_time_ms);
+	/*virtual*/ S32 update(F32 max_time_ms);
 	
 	handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
 	
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index 28dc3bd313..ad2eb0f69c 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -46,7 +46,7 @@ LLImageDecodeThread::~LLImageDecodeThread()
 
 // MAIN THREAD
 // virtual
-S32 LLImageDecodeThread::update(U32 max_time_ms)
+S32 LLImageDecodeThread::update(F32 max_time_ms)
 {
 	LLMutexLock lock(mCreationMutex);
 	for (creation_list_t::iterator iter = mCreationList.begin();
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
index c684222fa5..1bfb0ddfd3 100644
--- a/indra/llimage/llimageworker.h
+++ b/indra/llimage/llimageworker.h
@@ -78,7 +78,7 @@ public:
 	handle_t decodeImage(LLImageFormatted* image,
 						 U32 priority, S32 discard, BOOL needs_aux,
 						 Responder* responder);
-	S32 update(U32 max_time_ms);
+	S32 update(F32 max_time_ms);
 
 	// Used by unit tests to check the consistency of the thread instance
 	S32 tut_size();
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 7ca25d07fc..ce0632668c 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -841,7 +841,7 @@ LLCurlThread::~LLCurlThread()
 {
 }
 
-S32 LLCurlThread::update(U32 max_time_ms)
+S32 LLCurlThread::update(F32 max_time_ms)
 {	
 	return LLQueuedThread::update(max_time_ms);
 }
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index a275db3e53..2c95279438 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -344,7 +344,7 @@ public:
 	LLCurlThread(bool threaded = true) ;
 	virtual ~LLCurlThread() ;
 
-	S32 update(U32 max_time_ms);
+	S32 update(F32 max_time_ms);
 
 	void addMulti(LLCurl::Multi* multi) ;
 	void killMulti(LLCurl::Multi* multi) ;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e80475f096..9455bf9875 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1345,17 +1345,19 @@ bool LLAppViewer::mainLoop()
 				{
 					S32 work_pending = 0;
 					S32 io_pending = 0;
+					F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f);
+
 					{
 						LLFastTimer ftm(FTM_TEXTURE_CACHE);
- 						work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
+ 						work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
 					}
 					{
 						LLFastTimer ftm(FTM_DECODE);
-	 					work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
+	 					work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
 					}
 					{
 						LLFastTimer ftm(FTM_DECODE);
-	 					work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
+	 					work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
 					}
 
 					{
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 3e16ccf3da..fb107a302a 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -28,6 +28,10 @@
 
 #include "llspatialpartition.h"
 
+#include "llappviewer.h"
+#include "lltexturecache.h"
+#include "lltexturefetch.h"
+#include "llimageworker.h"
 #include "llviewerwindow.h"
 #include "llviewerobjectlist.h"
 #include "llvovolume.h"
@@ -1221,6 +1225,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
 	for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
 	{
 		mOcclusionQuery[i] = 0;
+		mOcclusionIssued[i] = 0;
 		mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0;
 		mVisible[i] = 0;
 	}
@@ -1543,6 +1548,8 @@ BOOL LLSpatialGroup::rebound()
 }
 
 static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion");
+static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Wait");
+
 void LLSpatialGroup::checkOcclusion()
 {
 	if (LLPipeline::sUseOcclusion > 1)
@@ -1560,6 +1567,22 @@ void LLSpatialGroup::checkOcclusion()
 			if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
 			{
 				glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+
+				if (mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount)
+				{ //query was issued last frame, wait until it's available
+					S32 max_loop = 1024;
+					LLFastTimer t(FTM_OCCLUSION_WAIT);
+					while (!available && max_loop-- > 0)
+					{
+						F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f);
+						//do some usefu work while we wait
+						LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
+						LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
+						LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
+						
+						glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+					}
+				}
 			}
 			else
 			{
@@ -1679,6 +1702,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
 					{
 						LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS);
 						
+						//store which frame this query was issued on
+						mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount;
+
 						{
 							LLFastTimer t(FTM_OCCLUSION_BEGIN_QUERY);
 							glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);					
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index f0c8a372ee..899547ae4d 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -396,6 +396,8 @@ protected:
 
 	U32 mState;
 	U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS];
+	U32 mOcclusionIssued[LLViewerCamera::NUM_CAMERAS];
+
 	S32 mLODHash;
 	static S32 sLODSeed;
 
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index e7a176f4f9..8632890bbb 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -760,7 +760,7 @@ LLTextureCache::~LLTextureCache()
 //////////////////////////////////////////////////////////////////////////////
 
 //virtual
-S32 LLTextureCache::update(U32 max_time_ms)
+S32 LLTextureCache::update(F32 max_time_ms)
 {
 	static LLFrameTimer timer ;
 	static const F32 MAX_TIME_INTERVAL = 300.f ; //seconds.
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 64e3a2658c..dd0cc9b4bd 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -101,7 +101,7 @@ public:
 	LLTextureCache(bool threaded);
 	~LLTextureCache();
 
-	/*virtual*/ S32 update(U32 max_time_ms);	
+	/*virtual*/ S32 update(F32 max_time_ms);	
 	
 	void purgeCache(ELLPath location);
 	void setReadOnly(BOOL read_only) ;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 56dfb61c4f..f18aa8b4e6 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -2204,7 +2204,7 @@ void LLTextureFetch::commonUpdate()
 
 // MAIN THREAD
 //virtual
-S32 LLTextureFetch::update(U32 max_time_ms)
+S32 LLTextureFetch::update(F32 max_time_ms)
 {
 	static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS");
 
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index d101da1f4b..35df7d816f 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -55,7 +55,7 @@ public:
 
 	class TFRequest;
 	
-	/*virtual*/ S32 update(U32 max_time_ms);	
+	/*virtual*/ S32 update(F32 max_time_ms);	
 	void shutDownTextureCacheThread() ; //called in the main thread after the TextureCacheThread shuts down.
 	void shutDownImageDecodeThread() ;  //called in the main thread after the ImageDecodeThread shuts down.
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index b0f5361a79..1863992a22 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -417,9 +417,13 @@ const S32 min_non_tex_system_mem = (128<<20); // 128 MB
 F32 texmem_lower_bound_scale = 0.85f;
 F32 texmem_middle_bound_scale = 0.925f;
 
+static LLFastTimer::DeclareTimer FTM_TEXTURE_MEMORY_CHECK("Memory Check");
+
 //static 
 bool LLViewerTexture::isMemoryForTextureLow()
 {
+	LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK);
+
 	const static S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB
 	const static S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB
 
@@ -459,6 +463,9 @@ bool LLViewerTexture::isMemoryForTextureLow()
 	return low_mem ;
 }
 
+static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_MEDIA("Media");
+static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_TEST("Test");
+
 //static
 void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity)
 {
@@ -467,9 +474,14 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
 	LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
 	if (tester)
 	{
+		LLFastTimer t(FTM_TEXTURE_UPDATE_TEST);
 		tester->update() ;
 	}
-	LLViewerMediaTexture::updateClass() ;
+
+	{
+		LLFastTimer t(FTM_TEXTURE_UPDATE_MEDIA);
+		LLViewerMediaTexture::updateClass() ;
+	}
 
 	sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes
 	sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes
-- 
cgit v1.2.3


From 1a93abb9013d6960f1ff9eb491480f547c780ff0 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Mon, 5 Dec 2011 18:55:01 -0600
Subject: SH-2652 Bump fast timer location.

---
 indra/newview/llviewertexture.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 2e1dc95483..126d0f75e8 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -423,7 +423,6 @@ static LLFastTimer::DeclareTimer FTM_TEXTURE_MEMORY_CHECK("Memory Check");
 bool LLViewerTexture::isMemoryForTextureLow()
 {
 	const F32 WAIT_TIME = 1.0f ; //second
-	LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK);
 	static LLFrameTimer timer ;
 
 	if(timer.getElapsedTimeF32() < WAIT_TIME) //call this once per second.
@@ -432,6 +431,8 @@ bool LLViewerTexture::isMemoryForTextureLow()
 	}
 	timer.reset() ;
 
+	LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK);
+
 	const S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB
 	const S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB	
 
-- 
cgit v1.2.3


From b89c1ac482eeef7a4ab050186a6c425a5167c504 Mon Sep 17 00:00:00 2001
From: Jonathan Yap <none@none>
Date: Tue, 6 Dec 2011 09:53:09 -0500
Subject: STORM-1727 Dates displayed incorrectly in group profile. year "2035"

---
 doc/contributions.txt                   | 1 +
 indra/newview/llpanelgrouplandmoney.cpp | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 9f6de781b4..aa8f006044 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -589,6 +589,7 @@ Jonathan Yap
 	STORM-1659
 	STORM-1674
 	STORM-1685
+	STORM-1727
 Kadah Coba
 	STORM-1060
 Jondan Lundquist
diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index e66dd5690c..363443646d 100644
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -1062,7 +1062,7 @@ void LLGroupMoneyDetailsTabEventHandler::processReply(LLMessageSystem* msg,
 
 	// We don't do time zone corrections of the calculated number of seconds
 	// because we don't have a full time stamp, only a date.
-	substitution["datetime"] = LLDateUtil::secondsSinceEpochFromString("%A %b %d, %Y", start_date);
+	substitution["datetime"] = LLDateUtil::secondsSinceEpochFromString("%Y-%m-%d", start_date);
 	LLStringUtil::format (time_str, substitution);
 
 	if ( interval_days != mImplementationp->mIntervalLength || 
@@ -1217,7 +1217,7 @@ void LLGroupMoneySalesTabEventHandler::processReply(LLMessageSystem* msg,
 
 		// We don't do time zone corrections of the calculated number of seconds
 		// because we don't have a full time stamp, only a date.
-		substitution["datetime"] = LLDateUtil::secondsSinceEpochFromString("%A %b %d, %Y", start_date);
+		substitution["datetime"] = LLDateUtil::secondsSinceEpochFromString("%Y-%m-%d", start_date);
 		LLStringUtil::format (time_str, substitution);
 
 		text = time_str + "\n\n";
-- 
cgit v1.2.3


From a78894285aebe73025445078ebeba45f262e16e4 Mon Sep 17 00:00:00 2001
From: Jonathan Yap <none@none>
Date: Tue, 6 Dec 2011 10:03:26 -0500
Subject: STORM-1725 Truncation of UI element Preferences->General->Busy mode
 response

---
 doc/contributions.txt                                            | 1 +
 indra/newview/skins/default/xui/en/panel_preferences_general.xml | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 9f6de781b4..4ca2f5aab3 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -589,6 +589,7 @@ Jonathan Yap
 	STORM-1659
 	STORM-1674
 	STORM-1685
+	STORM-1725
 Kadah Coba
 	STORM-1060
 Jondan Lundquist
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index 4079a80924..9827180aa7 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -420,7 +420,7 @@
      follows="left|top"
      height="29"
      layout="topleft"
-     left="50"
+     left="30"
      name="busy_response"
      width="470"
      word_wrap="true">
-- 
cgit v1.2.3


From 22e46e4be76a448a27c59fedfeb84081d6624df8 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Tue, 6 Dec 2011 12:57:57 -0600
Subject: Fix for RenderResolutionDivisor no longer working correctly.

---
 indra/newview/pipeline.cpp | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 657cdc0e07..00acc3e511 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -6333,17 +6333,10 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 	}
 
-	U32 res_mod = RenderResolutionDivisor;
-
 	LLVector2 tc1(0,0);
 	LLVector2 tc2((F32) mScreen.getWidth()*2,
 				  (F32) mScreen.getHeight()*2);
 
-	if (res_mod > 1)
-	{
-		tc2 /= (F32) res_mod;
-	}
-
 	LLFastTimer ftm(FTM_RENDER_BLOOM);
 	gGL.color4f(1,1,1,1);
 	LLGLDepthTest depth(GL_FALSE);
@@ -6807,7 +6800,13 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 				mFXAABuffer.bindTexture(0, channel);
 				gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
 			}
-						
+			
+			gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+			gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+			gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+			gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+			glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
 			F32 scale_x = (F32) width/mFXAABuffer.getWidth();
 			F32 scale_y = (F32) height/mFXAABuffer.getHeight();
 			shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
@@ -6827,11 +6826,6 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 	}
 	else
 	{
-		if (res_mod > 1)
-		{
-			tc2 /= (F32) res_mod;
-		}
-
 		U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
 		LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
 		buff->allocateBuffer(3,0,TRUE);
-- 
cgit v1.2.3


From a255fadfab359931d591c6a874abbea5fcf13526 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 6 Dec 2011 11:19:58 -0800
Subject: Updated to trigger a 'get' to establish marketplace session cookie
 when outbox panel created.

---
 indra/newview/llmarketplacefunctions.cpp           |   4 +-
 indra/newview/llpanelmarketplaceoutbox.cpp         | 194 +++++++++++++--------
 indra/newview/llpanelmarketplaceoutbox.h           |   6 +-
 indra/newview/llviewermedia.cpp                    |   1 +
 .../newview/skins/default/xui/en/notifications.xml |   2 +-
 5 files changed, 129 insertions(+), 78 deletions(-)

diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 1c189f6ee2..2f8c5bc9ee 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -52,7 +52,7 @@ std::string getMarketplaceBaseURL()
 
 	url += "api/1/";
 	url += gAgent.getID().getString();
-	url += "/inventory";
+	url += "/inventory/";
 
 	return url;
 }
@@ -61,7 +61,7 @@ std::string getMarketplaceURL_InventoryImport()
 {
 	std::string url = getMarketplaceBaseURL();
 
-	url += "/import";
+	url += "import/";
 
 	return url;
 }
diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
index 6a2bf58701..99d744891a 100644
--- a/indra/newview/llpanelmarketplaceoutbox.cpp
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -140,6 +140,11 @@ LLInventoryPanel * LLPanelMarketplaceOutbox::setupInventoryPanel()
 	// Hide the placeholder text
 	outbox_inventory_placeholder->setVisible(FALSE);
 	
+	// Establish marketplace cookies for http client
+	establishMarketplaceSessionCookie();
+	
+	updateImportButtonStatus();
+	
 	return mInventoryPanel;
 }
 
@@ -195,6 +200,28 @@ void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
 	gTimeDelayDebugFunc = "";
 }
 
+std::string gImportPollingFunc = "";
+
+void importPoll(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
+{
+	waitForEventOn(self, "mainloop");
+	
+	while (outboxPanel->isImportInProgress())
+	{
+		LLTimer delayTimer;
+		delayTimer.reset();
+		delayTimer.setTimerExpirySec(5.0f);
+		
+		while (!delayTimer.hasExpired())
+		{
+			waitForEventOn(self, "mainloop");
+		}
+		
+		//outboxPanel->
+	}
+	
+	gImportPollingFunc = "";
+}
 
 class LLInventoryImportPostResponder : public LLHTTPClient::Responder
 {
@@ -207,16 +234,16 @@ public:
 	
 	void completed(U32 status, const std::string& reason, const LLSD& content)
 	{
-		llinfos << "inventory/import post status: " << status << ", reason: " << reason << llendl;
+		llinfos << "*** Marketplace *** " << "inventory/import post status: " << status << ", reason: " << reason << llendl;
 		
 		if (isGoodStatus(status))
 		{
 			// Complete success
-			llinfos << "success" << llendl;
+			llinfos << "*** Marketplace *** " << "success" << llendl;
 		}	
 		else
 		{
-			llwarns << "failed" << llendl;
+			llwarns << "*** Marketplace *** " << "failed" << llendl;
 		}
 		
 		mOutboxPanel->onImportPostComplete(status, content);
@@ -229,64 +256,119 @@ private:
 class LLInventoryImportGetResponder : public LLHTTPClient::Responder
 {
 public:
-	LLInventoryImportGetResponder(LLPanelMarketplaceOutbox * outboxPanel)
+	LLInventoryImportGetResponder(LLPanelMarketplaceOutbox * outboxPanel, bool ignoreResults)
 		: LLCurl::Responder()
+		, mIgnoreResults(ignoreResults)
 		, mOutboxPanel(outboxPanel)
 	{
 	}
 
 	void completed(U32 status, const std::string& reason, const LLSD& content)
 	{
-		llinfos << "inventory/import get status: " << status << ", reason: " << reason << llendl;
+		llinfos << "*** Marketplace *** " << "inventory/import get status: " << status << ", reason: " << reason << llendl;
 		
 		if (isGoodStatus(status))
 		{
 			// Complete success
-			llinfos << "success" << llendl;
+			llinfos << "*** Marketplace *** " << "success" << llendl;
 		}	
 		else
 		{
-			llwarns << "failed" << llendl;
+			llwarns << "*** Marketplace *** " << "failed" << llendl;
 		}
 
-		mOutboxPanel->onImportGetComplete(status, content);
+		mOutboxPanel->onImportGetComplete(status, content, mIgnoreResults);
 	}
 
 private:
+	bool						mIgnoreResults;
 	LLPanelMarketplaceOutbox *	mOutboxPanel;
 };
 
-void LLPanelMarketplaceOutbox::onImportButtonClicked()
+void LLPanelMarketplaceOutbox::importPostTrigger()
 {
-	// Get the import animation going
 	mImportInProgress = true;
 	mImportFrameTimer = 0;
-
-	updateImportButtonStatus();
-
+	
 	// Make the url for the inventory import request
 	std::string url = getMarketplaceURL_InventoryImport();
-
-	llinfos << "http post:  " << url << llendl;
-	LLHTTPClient::post(url, LLSD(), new LLInventoryImportPostResponder(this), LLViewerMedia::getHeaders());
-
+	
+	LLSD headers = LLViewerMedia::getHeaders();
+	headers["Connection"] = "Keep-Alive";
+	
+	llinfos << "*** Marketplace *** " << "http post:  " << url << llendl;
+	llinfos << "*** Marketplace *** " << "headers: " << ll_pretty_print_sd(headers) << llendl;
+	
+	LLHTTPClient::post(url, LLSD(), new LLInventoryImportPostResponder(this), headers);
+	
 	// Set a timer (for testing only)
     //gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this));
 }
 
+void LLPanelMarketplaceOutbox::importGetTrigger()
+{
+	mImportGetPending = true;
+	
+	std::string url = getMarketplaceURL_InventoryImport();
+	LLSD headers = LLViewerMedia::getHeaders();
+	
+	llinfos << "*** Marketplace *** " << "http get:  " << url << llendl;
+	llinfos << "*** Marketplace *** " << "headers: " << ll_pretty_print_sd(headers) << llendl;
+	
+	const bool do_not_ignore_results = false;
+	
+	LLHTTPClient::get(url, new LLInventoryImportGetResponder(this, do_not_ignore_results), headers);
+}
+
+void LLPanelMarketplaceOutbox::establishMarketplaceSessionCookie()
+{
+	mImportInProgress = true;
+	mImportGetPending = true;
+	
+	std::string url = getMarketplaceURL_InventoryImport();
+	LLSD headers = LLViewerMedia::getHeaders();
+	
+	const bool ignore_results = true;
+	
+	LLHTTPClient::get(url, new LLInventoryImportGetResponder(this, ignore_results), headers);
+}
+
 void LLPanelMarketplaceOutbox::onImportPostComplete(U32 status, const LLSD& content)
 {
-	llinfos << "onImportPostComplete status = " << status << llendl;
-	llinfos << "onImportPostComplete content = " << content.asString() << llendl;
+	llinfos << "*** Marketplace *** " << "status = " << status << llendl;
+	llinfos << "*** Marketplace *** " << "content = " << ll_pretty_print_sd(content) << llendl;
+
+	mImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
+	updateImportButtonStatus();
+	
+	if (!mImportInProgress)
+	{
+		char status_string[16];
+		sprintf(status_string, "%d", status);
+
+		LLSD subs;
+		subs["ERROR_CODE"] = status_string;
+
+		LLNotificationsUtil::add("OutboxImportFailed", subs, LLSD::emptyMap());
+	}
+
+	// The POST request returns the IMPORT_DONE code on success
+	//if (status == MarketplaceErrorCodes::IMPORT_DONE)
+	//{
+	//	gImportPollingFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox importPoll", boost::bind(&importPoll, _1, this));
+	//}
 }
 
-void LLPanelMarketplaceOutbox::onImportGetComplete(U32 status, const LLSD& content)
+void LLPanelMarketplaceOutbox::onImportGetComplete(U32 status, const LLSD& content, bool ignoreResults)
 {
+	llinfos << "*** Marketplace *** " << "status = " << status << llendl;
+	llinfos << "*** Marketplace *** " << "content = " << ll_pretty_print_sd(content) << llendl;
+
 	mImportGetPending = false;	
 	mImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
 	updateImportButtonStatus();
 	
-	if (!mImportInProgress)
+	if (!mImportInProgress && !ignoreResults)
 	{
 		if (status == MarketplaceErrorCodes::IMPORT_DONE)
 		{
@@ -298,55 +380,16 @@ void LLPanelMarketplaceOutbox::onImportGetComplete(U32 status, const LLSD& conte
 		}
 		else
 		{
-			llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
+			char status_string[16];
+			sprintf(status_string, "%d", status);
+			
+			LLSD subs;
+			subs["ERROR_CODE"] = status_string;
+			
+			//llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
 			LLNotificationsUtil::add("OutboxImportFailed", LLSD::emptyMap(), LLSD::emptyMap());
 		}
 	}
-	
-
-	//const LLSD& errors_list = content["errors"];
-
-	//if (errors_list.size() == 0)
-	//{
-	//	LLNotificationsUtil::add("OutboxUploadComplete", LLSD::emptyMap(), LLSD::emptyMap());
-	//}
-	//else
-	//{
-	//	LLNotificationsUtil::add("OutboxUploadHadErrors", LLSD::emptyMap(), LLSD::emptyMap());
-	//}
-
-	//llinfos << "Marketplace upload llsd:" << llendl;
-	//llinfos << ll_pretty_print_sd(content) << llendl;
-	//llinfos << llendl;
-
-	//const LLSD& imported_list = content["imported"];
-	//LLSD::array_const_iterator it = imported_list.beginArray();
-	//for ( ; it != imported_list.endArray(); ++it)
-	//{
-	//	LLUUID imported_folder = (*it).asUUID();
-	//	llinfos << "Successfully uploaded folder " << imported_folder.asString() << " to marketplace." << llendl;
-	//}
-
-	//for (it = errors_list.beginArray(); it != errors_list.endArray(); ++it)
-	//{
-	//	const LLSD& item_error_map = (*it);
-
-	//	LLUUID error_folder = item_error_map["folder_id"].asUUID();
-	//	const std::string& error_string = item_error_map["identifier"].asString();
-	//	LLUUID error_item = item_error_map["item_id"].asUUID();
-	//	const std::string& error_item_name = item_error_map["item_name"].asString();
-	//	const std::string& error_message = item_error_map["message"].asString();
-
-	//	llinfos << "Error item " << error_folder.asString() << ", " << error_string << ", "
-	//			<< error_item.asString() << ", " << error_item_name << ", " << error_message << llendl;
-	//	
-	//	LLFolderViewFolder * item_folder = mInventoryPanel->getRootFolder()->getFolderByID(error_folder);
-	//	LLOutboxFolderViewFolder * outbox_item_folder = dynamic_cast<LLOutboxFolderViewFolder *>(item_folder);
-
-	//	llassert(outbox_item_folder);
-
-	//	outbox_item_folder->setErrorString(error_string);
-	//}
 }
 
 void LLPanelMarketplaceOutbox::updateImportButtonStatus()
@@ -380,12 +423,21 @@ U32 LLPanelMarketplaceOutbox::getTotalItemCount() const
 		if (outbox_folder)
 		{
 			item_count += outbox_folder->getFoldersCount();
+			item_count += outbox_folder->getItemsCount();
 		}
 	}
 
 	return item_count;
 }
 
+void LLPanelMarketplaceOutbox::onImportButtonClicked()
+{
+	importPostTrigger();
+	
+	// Get the import animation going
+	updateImportButtonStatus();
+}
+
 void LLPanelMarketplaceOutbox::draw()
 {
 	const U32 item_count = getTotalItemCount();
@@ -414,15 +466,9 @@ void LLPanelMarketplaceOutbox::draw()
 		
 		if ((mImportFrameTimer % 50 == 0) && !mImportGetPending)
 		{
-			mImportGetPending = true;
-
-			std::string url = getMarketplaceURL_InventoryImport();
-			
-			llinfos << "http get:  " << url << llendl;
-			LLHTTPClient::get(url, new LLInventoryImportGetResponder(this), LLViewerMedia::getHeaders());
+			importGetTrigger();
 		}
 	}
-
 	
 	LLPanel::draw();
 }
diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h
index a776ee0919..9cbb9cf21b 100644
--- a/indra/newview/llpanelmarketplaceoutbox.h
+++ b/indra/newview/llpanelmarketplaceoutbox.h
@@ -62,7 +62,7 @@ public:
 	bool isImportInProgress() const;
 
 	void onImportPostComplete(U32 status, const LLSD& content);
-	void onImportGetComplete(U32 status, const LLSD& content);
+	void onImportGetComplete(U32 status, const LLSD& content, bool ignoreResults);
 
 	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 								   EDragAndDropType cargo_type,
@@ -77,6 +77,10 @@ protected:
 	void handleLoginComplete();
 	void onFocusReceived();
 	void onSelectionChange();
+	
+	void importPostTrigger();
+	void importGetTrigger();
+	void establishMarketplaceSessionCookie();
 
 private:
 	LLInventoryPanel *		mInventoryPanel;
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 02d8036666..eb7a4aa538 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1390,6 +1390,7 @@ LLSD LLViewerMedia::getHeaders()
 {
 	LLSD headers = LLSD::emptyMap();
 	headers["Accept"] = "*/*";
+	headers["Content-Type"] = "application/xml";
 	headers["Cookie"] = sOpenIDCookie;
 	headers["User-Agent"] = getCurrentUserAgent();
 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 46a6da2450..8d0d76b58e 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -235,7 +235,7 @@ Marketplace import completed with errors!  Please correct the problems in your o
    icon="alertmodal.tga"
    name="OutboxImportFailed"
    type="alertmodal">
-Marketplace import failed!  Please try again later.  Thanks.
+Marketplace import failed with error [ERROR_CODE]!  Please try again later.  Thanks.
         <usetemplate
          name="okbutton"
          yestext="Rats!"/>
-- 
cgit v1.2.3


From 40f9de414fbd5755b7c040f786030157cf083771 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 6 Dec 2011 11:45:21 -0800
Subject: Added code to set up the marketplace session cookie and use it for
 subsequent posts and gets to the inventory import API

---
 indra/newview/llpanelmarketplaceoutbox.cpp | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
index 99d744891a..d4b0bead4c 100644
--- a/indra/newview/llpanelmarketplaceoutbox.cpp
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -50,6 +50,8 @@
 
 static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox");
 
+static std::string sMarketplaceCookie;
+
 const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultParams() 
 { 
 	return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceOutbox>(); 
@@ -263,6 +265,15 @@ public:
 	{
 	}
 
+	void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	{
+		std::string cookie = content["set-cookie"].asString();
+		
+		llinfos << "*** Marketplace *** " << "inventory/import headers set-cookie: " << cookie << llendl;
+		
+		sMarketplaceCookie = cookie;
+	}
+
 	void completed(U32 status, const std::string& reason, const LLSD& content)
 	{
 		llinfos << "*** Marketplace *** " << "inventory/import get status: " << status << ", reason: " << reason << llendl;
@@ -295,6 +306,7 @@ void LLPanelMarketplaceOutbox::importPostTrigger()
 	
 	LLSD headers = LLViewerMedia::getHeaders();
 	headers["Connection"] = "Keep-Alive";
+	headers["Cookie"] = sMarketplaceCookie;
 	
 	llinfos << "*** Marketplace *** " << "http post:  " << url << llendl;
 	llinfos << "*** Marketplace *** " << "headers: " << ll_pretty_print_sd(headers) << llendl;
@@ -311,6 +323,7 @@ void LLPanelMarketplaceOutbox::importGetTrigger()
 	
 	std::string url = getMarketplaceURL_InventoryImport();
 	LLSD headers = LLViewerMedia::getHeaders();
+	headers["Cookie"] = sMarketplaceCookie;
 	
 	llinfos << "*** Marketplace *** " << "http get:  " << url << llendl;
 	llinfos << "*** Marketplace *** " << "headers: " << ll_pretty_print_sd(headers) << llendl;
-- 
cgit v1.2.3


From 83cc0becf859275a810da4ce0ccb0d7f8147d614 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 6 Dec 2011 11:51:09 -0800
Subject: Turning off marketplace logging verbosity by default

---
 indra/newview/llpanelmarketplaceoutbox.cpp | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
index d4b0bead4c..d7e4ed8bec 100644
--- a/indra/newview/llpanelmarketplaceoutbox.cpp
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -48,9 +48,14 @@
 #include "llfolderview.h"
 #include "llinventoryfunctions.h"
 
+
+// Turn this on to get a bunch of console output for marketplace API calls, headers and status
+#define DEBUG_MARKETPLACE_HTTP_API	0
+
+
 static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox");
 
-static std::string sMarketplaceCookie;
+static std::string sMarketplaceCookie = "";
 
 const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultParams() 
 { 
@@ -236,6 +241,7 @@ public:
 	
 	void completed(U32 status, const std::string& reason, const LLSD& content)
 	{
+#if DEBUG_MARKETPLACE_HTTP_API
 		llinfos << "*** Marketplace *** " << "inventory/import post status: " << status << ", reason: " << reason << llendl;
 		
 		if (isGoodStatus(status))
@@ -247,6 +253,7 @@ public:
 		{
 			llwarns << "*** Marketplace *** " << "failed" << llendl;
 		}
+#endif // DEBUG_MARKETPLACE_HTTP_API
 		
 		mOutboxPanel->onImportPostComplete(status, content);
 	}
@@ -269,13 +276,16 @@ public:
 	{
 		std::string cookie = content["set-cookie"].asString();
 		
+#if DEBUG_MARKETPLACE_HTTP_API
 		llinfos << "*** Marketplace *** " << "inventory/import headers set-cookie: " << cookie << llendl;
+#endif // DEBUG_MARKETPLACE_HTTP_API
 		
 		sMarketplaceCookie = cookie;
 	}
 
 	void completed(U32 status, const std::string& reason, const LLSD& content)
 	{
+#if DEBUG_MARKETPLACE_HTTP_API
 		llinfos << "*** Marketplace *** " << "inventory/import get status: " << status << ", reason: " << reason << llendl;
 		
 		if (isGoodStatus(status))
@@ -287,6 +297,7 @@ public:
 		{
 			llwarns << "*** Marketplace *** " << "failed" << llendl;
 		}
+#endif // DEBUG_MARKETPLACE_HTTP_API
 
 		mOutboxPanel->onImportGetComplete(status, content, mIgnoreResults);
 	}
@@ -308,8 +319,10 @@ void LLPanelMarketplaceOutbox::importPostTrigger()
 	headers["Connection"] = "Keep-Alive";
 	headers["Cookie"] = sMarketplaceCookie;
 	
+#if DEBUG_MARKETPLACE_HTTP_API
 	llinfos << "*** Marketplace *** " << "http post:  " << url << llendl;
 	llinfos << "*** Marketplace *** " << "headers: " << ll_pretty_print_sd(headers) << llendl;
+#endif // DEBUG_MARKETPLACE_HTTP_API
 	
 	LLHTTPClient::post(url, LLSD(), new LLInventoryImportPostResponder(this), headers);
 	
@@ -325,8 +338,10 @@ void LLPanelMarketplaceOutbox::importGetTrigger()
 	LLSD headers = LLViewerMedia::getHeaders();
 	headers["Cookie"] = sMarketplaceCookie;
 	
+#if DEBUG_MARKETPLACE_HTTP_API
 	llinfos << "*** Marketplace *** " << "http get:  " << url << llendl;
 	llinfos << "*** Marketplace *** " << "headers: " << ll_pretty_print_sd(headers) << llendl;
+#endif // DEBUG_MARKETPLACE_HTTP_API
 	
 	const bool do_not_ignore_results = false;
 	
@@ -348,8 +363,10 @@ void LLPanelMarketplaceOutbox::establishMarketplaceSessionCookie()
 
 void LLPanelMarketplaceOutbox::onImportPostComplete(U32 status, const LLSD& content)
 {
+#if DEBUG_MARKETPLACE_HTTP_API
 	llinfos << "*** Marketplace *** " << "status = " << status << llendl;
 	llinfos << "*** Marketplace *** " << "content = " << ll_pretty_print_sd(content) << llendl;
+#endif // DEBUG_MARKETPLACE_HTTP_API
 
 	mImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
 	updateImportButtonStatus();
@@ -374,8 +391,10 @@ void LLPanelMarketplaceOutbox::onImportPostComplete(U32 status, const LLSD& cont
 
 void LLPanelMarketplaceOutbox::onImportGetComplete(U32 status, const LLSD& content, bool ignoreResults)
 {
+#if DEBUG_MARKETPLACE_HTTP_API
 	llinfos << "*** Marketplace *** " << "status = " << status << llendl;
 	llinfos << "*** Marketplace *** " << "content = " << ll_pretty_print_sd(content) << llendl;
+#endif // DEBUG_MARKETPLACE_HTTP_API
 
 	mImportGetPending = false;	
 	mImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
-- 
cgit v1.2.3


From 1a18184f50a3c98573ceb06d6ff3ca7bd42f6fc3 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 6 Dec 2011 16:45:30 -0700
Subject: fix for SH-2526: Second Life client quickly allocates all available
 RAM and crashes

---
 indra/llaudio/llaudioengine.cpp | 23 +++++++++++++++++++----
 indra/llaudio/llaudioengine.h   |  1 +
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index 5e540ad8c5..5fa28cb902 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -1264,6 +1264,7 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32
 	mSyncSlave(false),
 	mQueueSounds(false),
 	mPlayedOnce(false),
+	mCorrupted(false),
 	mType(type),
 	mChannelp(NULL),
 	mCurrentDatap(NULL),
@@ -1296,16 +1297,25 @@ void LLAudioSource::setChannel(LLAudioChannel *channelp)
 
 void LLAudioSource::update()
 {
+	if(mCorrupted)
+	{
+		return ; //no need to update
+	}
+
 	if (!getCurrentBuffer())
 	{
 		if (getCurrentData())
 		{
 			// Hack - try and load the sound.  Will do this as a callback
 			// on decode later.
-			if (getCurrentData()->load())
+			if (getCurrentData()->load() && getCurrentData()->getBuffer())
 			{
 				play(getCurrentData()->getID());
-			}			
+			}
+			else
+			{
+				mCorrupted = true ;
+			}
 		}
 	}
 }
@@ -1421,6 +1431,11 @@ bool LLAudioSource::play(const LLUUID &audio_uuid)
 
 bool LLAudioSource::isDone() const
 {
+	if(mCorrupted)
+	{
+		return true ;
+	}
+
 	const F32 MAX_AGE = 60.f;
 	const F32 MAX_UNPLAYED_AGE = 15.f;
 	const F32 MAX_MUTED_AGE = 11.f;
@@ -1736,7 +1751,7 @@ LLAudioData::LLAudioData(const LLUUID &uuid) :
 	}
 }
 
-
+//return false when the audio file is corrupted.
 bool LLAudioData::load()
 {
 	// For now, just assume we're going to use one buffer per audiodata.
@@ -1752,7 +1767,7 @@ bool LLAudioData::load()
 	{
 		// No free buffers, abort.
 		llinfos << "Not able to allocate a new audio buffer, aborting." << llendl;
-		return false;
+		return true;
 	}
 
 	std::string uuid_str;
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index 30d2490635..a47ee7ca7c 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -334,6 +334,7 @@ protected:
 	bool			mSyncSlave;
 	bool			mQueueSounds;
 	bool			mPlayedOnce;
+	bool            mCorrupted;
 	S32             mType;
 	LLVector3d		mPositionGlobal;
 	LLVector3		mVelocity;
-- 
cgit v1.2.3


From 494005c66e8627ce4a84f49ec3d2b11fb9949f7b Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 7 Dec 2011 11:49:50 -0800
Subject: toned down spammy error message when slplugin isn't working

---
 indra/newview/llviewermedia.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 263d8b4146..b43e002e0a 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1955,7 +1955,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 		}
 	}
 	
-	LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL;
+	LL_WARNS_ONCE("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL;
 	LLSD args;
 	args["MIME_TYPE"] = media_type;
 	LLNotificationsUtil::add("NoPlugin", args);
-- 
cgit v1.2.3


From 9890e5cbed50c8388f8159a73c8ce672a61bd576 Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Wed, 7 Dec 2011 21:37:08 +0000
Subject: STORM-1708 Darwin UI additions

---
 indra/newview/llfilepicker.cpp | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index d259e02452..ceb4060bc2 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -625,6 +625,14 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB
 								result = false;
 							}
 						}
+						else if (filter == FFLOAD_SCRIPT)
+						{
+							if (fileInfo.filetype != 'LSL ' &&
+								(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("lsl"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) )
+							{
+								result = false;
+							}
+						}
 						
 						if (fileInfo.extension)
 						{
@@ -771,6 +779,12 @@ OSStatus	LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& fi
 			extension = CFSTR(".j2c");
 			break;
 		
+		case FFSAVE_SCRIPT:
+			type = 'LSL ';
+			creator = '\?\?\?\?';
+			extension = CFSTR(".lsl");
+			break;
+		
 		case FFSAVE_ALL:
 		default:
 			type = '\?\?\?\?';
-- 
cgit v1.2.3


From f9f247c5a6f2f7d3b730244f8fc10c880cdb1bed Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 7 Dec 2011 16:36:26 -0600
Subject: SH-2084 Don't error out on framebuffer mismatch -- probably causing a
 crash when some post-snapshot or minimize/restore operation gets out of
 phase.

---
 indra/llrender/llrendertarget.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 1aa12614ea..ef2a7395da 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -457,7 +457,8 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
 	gGL.flush();
 	if (!source.mFBO || !mFBO)
 	{
-		llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
+		llwarns << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
+		return;
 	}
 
 	
-- 
cgit v1.2.3


From e0a994d1f298b109dfac4cfd592e631d453f3045 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Wed, 7 Dec 2011 15:48:57 -0700
Subject: fix for SH-2516: Full Bright Geometry Rendering Increases Rapidly,
 Destroying Frame Rate.

---
 indra/newview/llviewertexture.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 126d0f75e8..61236edc86 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -3163,8 +3163,13 @@ void LLViewerLODTexture::processTextureStats()
 		S32 current_discard = getDiscardLevel();
 		if (sDesiredDiscardBias > 0.0f && mBoostLevel < LLViewerTexture::BOOST_SCULPTED && current_discard >= 0)
 		{
+			if(desired_discard_bias_max <= sDesiredDiscardBias && !mForceToSaveRawImage)
+			{
+				//needs to release texture memory urgently
+				scaleDown() ;
+			}
 			// Limit the amount of GL memory bound each frame
-			if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale &&
+			else if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale &&
 				(!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
 			{
 				scaleDown() ;
-- 
cgit v1.2.3


From e860925818fe9376fa9abb0520680dba986ab42e Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 7 Dec 2011 15:03:45 -0800
Subject: Crash workaround when opening toats windows after a long session.

---
 indra/llui/llview.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 486babb0ab..d2966fbe98 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1090,6 +1090,11 @@ void LLView::drawChildren()
 		{
 			child_list_reverse_iter_t child = child_iter++;
 			LLView *viewp = *child;
+			
+			if (viewp == NULL)
+			{
+				continue;
+			}
 
 			if (viewp->getVisible() && viewp->getRect().isValid())
 			{
-- 
cgit v1.2.3


From 35020db3a9310742c9759673e3aa1bbb1d7aa02f Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 7 Dec 2011 15:04:39 -0800
Subject: Refactored marketplace inventory import HTTP requests and surrounding
 support to remove it from the UI panel code.

---
 indra/newview/llappviewer.cpp              |   4 +
 indra/newview/llmarketplacefunctions.cpp   | 302 ++++++++++++++++++++++++++--
 indra/newview/llmarketplacefunctions.h     |  43 +++-
 indra/newview/llpanelmarketplaceoutbox.cpp | 304 ++++-------------------------
 indra/newview/llpanelmarketplaceoutbox.h   |  14 +-
 5 files changed, 362 insertions(+), 305 deletions(-)

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index cbaddd74c4..401e9ef600 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -45,6 +45,7 @@
 #include "llwindow.h"
 #include "llviewerstats.h"
 #include "llviewerstatsrecorder.h"
+#include "llmarketplacefunctions.h"
 #include "llmd5.h"
 #include "llmeshrepository.h"
 #include "llpumpio.h"
@@ -4393,6 +4394,9 @@ void LLAppViewer::idle()
 
 	// update media focus
 	LLViewerMediaFocus::getInstance()->update();
+	
+	// Update marketplace importer
+	LLMarketplaceInventoryImporter::update();
 
 	// objects and camera should be in sync, do LOD calculations now
 	{
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 2f8c5bc9ee..b9e02a36b4 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -29,52 +29,312 @@
 #include "llmarketplacefunctions.h"
 
 #include "llagent.h"
+#include "llhttpclient.h"
+#include "llviewermedia.h"
 #include "llviewernetwork.h"
 
 
-std::string getMarketplaceBaseURL()
+//
+// Helpers
+//
+
+namespace LLMarketplaceImport
 {
-	std::string url = "https://marketplace.secondlife.com/";
+	// Basic interface for this namespace
+
+	bool inProgress();
+	bool resultPending();
+	U32 getResultStatus();
+	const LLSD& getResults();
+
+	void establishMarketplaceSessionCookie();
+	void pollStatus();
+	void triggerImport();
+	
+	// Internal state variables
+
+	static std::string sMarketplaceCookie = "";
+	static bool sImportInProgress = false;
+	static bool sImportGetPending = false;
+	static U32 sImportResultStatus = 0;
+	static LLSD sImportResults = LLSD::emptyMap();
+		
+	
+	// Internal helper functions
+	
+	std::string getBaseURL()
+	{
+		std::string url = "https://marketplace.secondlife.com/";
+
+		if (!LLGridManager::getInstance()->isInProductionGrid())
+		{
+			std::string gridLabel = utf8str_tolower(LLGridManager::getInstance()->getGridLabel());
+			
+			if (gridLabel == "damballah")
+			{
+				url = "https://marketplace.secondlife-staging.com/";
+			}
+			else
+			{
+				url = llformat("https://marketplace.%s.lindenlab.com/", gridLabel.c_str());
+			}
+		}
+
+		url += "api/1/";
+		url += gAgent.getID().getString();
+		url += "/inventory/";
+
+		return url;
+	}
+
+	std::string getInventoryImportURL()
+	{
+		std::string url = getBaseURL();
 
-	if (!LLGridManager::getInstance()->isInProductionGrid())
+		url += "import/";
+
+		return url;
+	}
+	
+	// Responders
+	
+	class LLImportPostResponder : public LLHTTPClient::Responder
+	{
+	public:
+		LLImportPostResponder() : LLCurl::Responder() {}
+		
+		void completed(U32 status, const std::string& reason, const LLSD& content)
+		{
+			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
+			sImportResultStatus = status;
+		}
+	};
+	
+	class LLImportGetResponder : public LLHTTPClient::Responder
+	{
+	public:
+		LLImportGetResponder() : LLCurl::Responder() {}
+		
+		void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+		{
+			sMarketplaceCookie = content["set-cookie"].asString();
+		}
+		
+		void completed(U32 status, const std::string& reason, const LLSD& content)
+		{
+			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
+			sImportGetPending = false;
+			sImportResultStatus = status;
+			sImportResults = content;
+		}
+	};
+	
+	// Coroutine testing
+/*
+	std::string gTimeDelayDebugFunc = "";
+	
+	void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
 	{
-		std::string gridLabel = utf8str_tolower(LLGridManager::getInstance()->getGridLabel());
+		waitForEventOn(self, "mainloop");
+		
+		LLTimer delayTimer;
+		delayTimer.reset();
+		delayTimer.setTimerExpirySec(5.0f);
 		
-		if (gridLabel == "damballah")
+		while (!delayTimer.hasExpired())
 		{
-			url = "https://marketplace.secondlife-staging.com/";
+			waitForEventOn(self, "mainloop");
 		}
-		else
+		
+		outboxPanel->onImportPostComplete(MarketplaceErrorCodes::IMPORT_DONE, LLSD::emptyMap());
+		
+		gTimeDelayDebugFunc = "";
+	}
+	
+	std::string gImportPollingFunc = "";
+	
+	void importPoll(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
+	{
+		waitForEventOn(self, "mainloop");
+		
+		while (outboxPanel->isImportInProgress())
 		{
-			url = llformat("https://marketplace.%s.lindenlab.com/", gridLabel.c_str());
+			LLTimer delayTimer;
+			delayTimer.reset();
+			delayTimer.setTimerExpirySec(5.0f);
+			
+			while (!delayTimer.hasExpired())
+			{
+				waitForEventOn(self, "mainloop");
+			}
+			
+			//outboxPanel->
 		}
+		
+		gImportPollingFunc = "";
 	}
+	
+*/	
+	
+	// Basic API
 
-	url += "api/1/";
-	url += gAgent.getID().getString();
-	url += "/inventory/";
+	bool inProgress()
+	{
+		return sImportInProgress;
+	}
+	
+	bool resultPending()
+	{
+		return sImportGetPending;
+	}
+	
+	U32 getResultStatus()
+	{
+		return sImportResultStatus;
+	}
+	
+	const LLSD& getResults()
+	{
+		return sImportResults;
+	}
+	
+	void establishMarketplaceSessionCookie()
+	{
+		sImportInProgress = true;
+		sImportGetPending = true;
+		
+		std::string url = getInventoryImportURL();
+		
+		LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders());
+	}
+	
+	void pollStatus()
+	{
+		sImportGetPending = true;
 
-	return url;
+		std::string url = getInventoryImportURL();
+
+		// Make the headers for the post
+		LLSD headers = LLSD::emptyMap();
+		headers["Accept"] = "*/*";
+		headers["Cookie"] = sMarketplaceCookie;
+		headers["Content-Type"] = "application/xml";
+		headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
+		
+		LLHTTPClient::get(url, new LLImportGetResponder(), headers);
+	}
+	
+	void triggerImport()
+	{
+		sImportInProgress = true;		
+		sImportResultStatus = MarketplaceErrorCodes::IMPORT_PROCESSING;
+		sImportResults = LLSD::emptyMap();
+
+		std::string url = getInventoryImportURL();
+		
+		// Make the headers for the post
+		LLSD headers = LLSD::emptyMap();
+		headers["Accept"] = "*/*";
+		headers["Connection"] = "Keep-Alive";
+		headers["Cookie"] = sMarketplaceCookie;
+		headers["Content-Type"] = "application/xml";
+		headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
+		
+		LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers);
+		
+		// Set a timer (for testing only)
+		//gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this));
+	}
 }
 
-std::string getMarketplaceURL_InventoryImport()
+
+//
+// Interface class
+//
+
+
+//static
+void LLMarketplaceInventoryImporter::update()
 {
-	std::string url = getMarketplaceBaseURL();
+	if (instanceExists())
+	{
+		LLMarketplaceInventoryImporter::instance().updateImport();
+	}
+}
 
-	url += "import/";
+LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter()
+	: mImportInProgress(false)
+	, mInitialized(false)
+	, mStatusChangedSignal(NULL)
+	, mStatusReportSignal(NULL)
+{
+}
 
-	return url;
+void LLMarketplaceInventoryImporter::initialize()
+{
+	if (!mInitialized)
+	{
+		LLMarketplaceImport::establishMarketplaceSessionCookie();
+	}
 }
 
+boost::signals2::connection LLMarketplaceInventoryImporter::setStatusChangedCallback(const status_changed_signal_t::slot_type& cb)
+{
+	if (mStatusChangedSignal == NULL)
+	{
+		mStatusChangedSignal = new status_changed_signal_t();
+	}
 
-static bool gMarketplaceImportEnabled = true;
+	return mStatusChangedSignal->connect(cb);
+}
 
-bool getMarketplaceImportEnabled()
+boost::signals2::connection LLMarketplaceInventoryImporter::setStatusReportCallback(const status_report_signal_t::slot_type& cb)
 {
-	return gMarketplaceImportEnabled;
+	if (mStatusReportSignal == NULL)
+	{
+		mStatusReportSignal = new status_report_signal_t();
+	}
+
+	return mStatusReportSignal->connect(cb);
 }
 
-void setMarketplaceImportEnabled(bool importEnabled)
+bool LLMarketplaceInventoryImporter::triggerImport()
 {
-	gMarketplaceImportEnabled = importEnabled;
+	LLMarketplaceImport::triggerImport();
+	
+	return LLMarketplaceImport::inProgress();
 }
+
+void LLMarketplaceInventoryImporter::updateImport()
+{
+	const bool in_progress = LLMarketplaceImport::inProgress();
+	
+	if (in_progress && !LLMarketplaceImport::resultPending())
+	{
+		LLMarketplaceImport::pollStatus();
+	}	
+	
+	if (mImportInProgress != in_progress)
+	{
+		mImportInProgress = in_progress;
+		
+		if (mStatusChangedSignal)
+		{
+			(*mStatusChangedSignal)(mImportInProgress);
+		}
+		
+		// If we are no longer in progress, report results
+		if (!mImportInProgress && mStatusReportSignal)
+		{
+			if (mInitialized)
+			{
+				(*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults());
+			}
+			else
+			{
+				mInitialized = true;
+			}
+		}
+	}
+}
+
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index fda2fbb935..5ca0bdfe77 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -29,14 +29,16 @@
 #define LL_LLMARKETPLACEFUNCTIONS_H
 
 
-std::string getMarketplaceURL_InventoryImport();
+#include <llsd.h>
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+
+#include "llsingleton.h"
 
-bool getMarketplaceImportEnabled();
-void setMarketplaceImportEnabled(bool syncEnabled);
 
 namespace MarketplaceErrorCodes
 {
-	enum eCodes
+	enum eCode
 	{
 		IMPORT_DONE = 200,
 		IMPORT_PROCESSING = 202,
@@ -45,7 +47,38 @@ namespace MarketplaceErrorCodes
 	};
 }
 
-#endif // LL_LLMARKETPLACEFUNCTIONS_H
 
+class LLMarketplaceInventoryImporter
+	: public LLSingleton<LLMarketplaceInventoryImporter>
+{
+public:
+	static void update();
+	
+	LLMarketplaceInventoryImporter();
+	
+	void initialize();
+
+	typedef boost::signals2::signal<void (bool)> status_changed_signal_t;
+	typedef boost::signals2::signal<void (U32, const LLSD&)> status_report_signal_t;
 
+	boost::signals2::connection setStatusChangedCallback(const status_changed_signal_t::slot_type& cb);
+	boost::signals2::connection setStatusReportCallback(const status_report_signal_t::slot_type& cb);
+	
+	bool triggerImport();
+	bool isImportInProgress() const { return mImportInProgress; }
+	
+protected:
+	void updateImport();
+	
+private:
+	bool mImportInProgress;
+	bool mInitialized;
+	
+	status_changed_signal_t *	mStatusChangedSignal;
+	status_report_signal_t *	mStatusReportSignal;
+};
+
+
+
+#endif // LL_LLMARKETPLACEFUNCTIONS_H
 
diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
index d7e4ed8bec..e3af7fd906 100644
--- a/indra/newview/llpanelmarketplaceoutbox.cpp
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -55,8 +55,6 @@
 
 static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox");
 
-static std::string sMarketplaceCookie = "";
-
 const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultParams() 
 { 
 	return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceOutbox>(); 
@@ -67,10 +65,7 @@ LLPanelMarketplaceOutbox::LLPanelMarketplaceOutbox(const Params& p)
 	: LLPanel(p)
 	, mInventoryPanel(NULL)
 	, mImportButton(NULL)
-	, mImportFrameTimer(0)
-	, mImportGetPending(false)
 	, mImportIndicator(NULL)
-	, mImportInProgress(false)
 	, mOutboxButton(NULL)
 {
 }
@@ -93,7 +88,7 @@ void LLPanelMarketplaceOutbox::handleLoginComplete()
 {
 	mImportButton = getChild<LLButton>("outbox_import_btn");
 	mImportButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onImportButtonClicked, this));
-	mImportButton->setEnabled(getMarketplaceImportEnabled() && !isOutboxEmpty());
+	mImportButton->setEnabled(!isOutboxEmpty());
 	
 	mImportIndicator = getChild<LLLoadingIndicator>("outbox_import_indicator");
 	
@@ -147,286 +142,73 @@ LLInventoryPanel * LLPanelMarketplaceOutbox::setupInventoryPanel()
 	// Hide the placeholder text
 	outbox_inventory_placeholder->setVisible(FALSE);
 	
-	// Establish marketplace cookies for http client
-	establishMarketplaceSessionCookie();
+	// Set up marketplace importer
+	LLMarketplaceInventoryImporter::getInstance()->initialize();
+	LLMarketplaceInventoryImporter::getInstance()->setStatusChangedCallback(boost::bind(&LLPanelMarketplaceOutbox::importStatusChanged, this, _1));
+	LLMarketplaceInventoryImporter::getInstance()->setStatusReportCallback(boost::bind(&LLPanelMarketplaceOutbox::importReportResults, this, _1, _2));
 	
 	updateImportButtonStatus();
 	
 	return mInventoryPanel;
 }
 
-BOOL LLPanelMarketplaceOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
-								   EDragAndDropType cargo_type,
-								   void* cargo_data,
-								   EAcceptance* accept,
-								   std::string& tooltip_msg)
+void LLPanelMarketplaceOutbox::importReportResults(U32 status, const LLSD& content)
 {
-	BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
-
-	if (!handled && mInventoryPanel && mInventoryPanel->getRootFolder())
+	if (status == MarketplaceErrorCodes::IMPORT_DONE)
 	{
-		handled = mInventoryPanel->getRootFolder()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
-
-		if (handled)
-		{
-			mInventoryPanel->getRootFolder()->setDragAndDropThisFrame();
-		}
+		LLNotificationsUtil::add("OutboxImportComplete", LLSD::emptyMap(), LLSD::emptyMap());
 	}
-
-	return handled;
-}
-
-bool LLPanelMarketplaceOutbox::isOutboxEmpty() const
-{
-	return (getTotalItemCount() == 0);
-}
-
-bool LLPanelMarketplaceOutbox::isImportInProgress() const
-{
-	return mImportInProgress;
-}
-
-
-std::string gTimeDelayDebugFunc = "";
-
-void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
-{
-	waitForEventOn(self, "mainloop");
-
-	LLTimer delayTimer;
-	delayTimer.reset();
-	delayTimer.setTimerExpirySec(5.0f);
-
-	while (!delayTimer.hasExpired())
+	else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
 	{
-		waitForEventOn(self, "mainloop");
+		LLNotificationsUtil::add("OutboxImportHadErrors", LLSD::emptyMap(), LLSD::emptyMap());
 	}
-
-	outboxPanel->onImportPostComplete(MarketplaceErrorCodes::IMPORT_DONE, LLSD::emptyMap());
-
-	gTimeDelayDebugFunc = "";
-}
-
-std::string gImportPollingFunc = "";
-
-void importPoll(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
-{
-	waitForEventOn(self, "mainloop");
-	
-	while (outboxPanel->isImportInProgress())
+	else
 	{
-		LLTimer delayTimer;
-		delayTimer.reset();
-		delayTimer.setTimerExpirySec(5.0f);
+		char status_string[16];
+		sprintf(status_string, "%d", status);
 		
-		while (!delayTimer.hasExpired())
-		{
-			waitForEventOn(self, "mainloop");
-		}
+		LLSD subs;
+		subs["ERROR_CODE"] = status_string;
 		
-		//outboxPanel->
+		//llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
+		LLNotificationsUtil::add("OutboxImportFailed", LLSD::emptyMap(), LLSD::emptyMap());
 	}
-	
-	gImportPollingFunc = "";
 }
 
-class LLInventoryImportPostResponder : public LLHTTPClient::Responder
+void LLPanelMarketplaceOutbox::importStatusChanged(bool inProgress)
 {
-public:
-	LLInventoryImportPostResponder(LLPanelMarketplaceOutbox * outboxPanel)
-		: LLCurl::Responder()
-		, mOutboxPanel(outboxPanel)
-	{
-	}
-	
-	void completed(U32 status, const std::string& reason, const LLSD& content)
-	{
-#if DEBUG_MARKETPLACE_HTTP_API
-		llinfos << "*** Marketplace *** " << "inventory/import post status: " << status << ", reason: " << reason << llendl;
-		
-		if (isGoodStatus(status))
-		{
-			// Complete success
-			llinfos << "*** Marketplace *** " << "success" << llendl;
-		}	
-		else
-		{
-			llwarns << "*** Marketplace *** " << "failed" << llendl;
-		}
-#endif // DEBUG_MARKETPLACE_HTTP_API
-		
-		mOutboxPanel->onImportPostComplete(status, content);
-	}
-
-private:
-	LLPanelMarketplaceOutbox *	mOutboxPanel;	
-};
+	updateImportButtonStatus();
+}
 
-class LLInventoryImportGetResponder : public LLHTTPClient::Responder
+BOOL LLPanelMarketplaceOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+								   EDragAndDropType cargo_type,
+								   void* cargo_data,
+								   EAcceptance* accept,
+								   std::string& tooltip_msg)
 {
-public:
-	LLInventoryImportGetResponder(LLPanelMarketplaceOutbox * outboxPanel, bool ignoreResults)
-		: LLCurl::Responder()
-		, mIgnoreResults(ignoreResults)
-		, mOutboxPanel(outboxPanel)
-	{
-	}
+	BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
 
-	void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	if (!handled && mInventoryPanel && mInventoryPanel->getRootFolder())
 	{
-		std::string cookie = content["set-cookie"].asString();
-		
-#if DEBUG_MARKETPLACE_HTTP_API
-		llinfos << "*** Marketplace *** " << "inventory/import headers set-cookie: " << cookie << llendl;
-#endif // DEBUG_MARKETPLACE_HTTP_API
-		
-		sMarketplaceCookie = cookie;
-	}
+		handled = mInventoryPanel->getRootFolder()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
 
-	void completed(U32 status, const std::string& reason, const LLSD& content)
-	{
-#if DEBUG_MARKETPLACE_HTTP_API
-		llinfos << "*** Marketplace *** " << "inventory/import get status: " << status << ", reason: " << reason << llendl;
-		
-		if (isGoodStatus(status))
-		{
-			// Complete success
-			llinfos << "*** Marketplace *** " << "success" << llendl;
-		}	
-		else
+		if (handled)
 		{
-			llwarns << "*** Marketplace *** " << "failed" << llendl;
+			mInventoryPanel->getRootFolder()->setDragAndDropThisFrame();
 		}
-#endif // DEBUG_MARKETPLACE_HTTP_API
-
-		mOutboxPanel->onImportGetComplete(status, content, mIgnoreResults);
-	}
-
-private:
-	bool						mIgnoreResults;
-	LLPanelMarketplaceOutbox *	mOutboxPanel;
-};
-
-void LLPanelMarketplaceOutbox::importPostTrigger()
-{
-	mImportInProgress = true;
-	mImportFrameTimer = 0;
-	
-	// Make the url for the inventory import request
-	std::string url = getMarketplaceURL_InventoryImport();
-	
-	LLSD headers = LLViewerMedia::getHeaders();
-	headers["Connection"] = "Keep-Alive";
-	headers["Cookie"] = sMarketplaceCookie;
-	
-#if DEBUG_MARKETPLACE_HTTP_API
-	llinfos << "*** Marketplace *** " << "http post:  " << url << llendl;
-	llinfos << "*** Marketplace *** " << "headers: " << ll_pretty_print_sd(headers) << llendl;
-#endif // DEBUG_MARKETPLACE_HTTP_API
-	
-	LLHTTPClient::post(url, LLSD(), new LLInventoryImportPostResponder(this), headers);
-	
-	// Set a timer (for testing only)
-    //gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this));
-}
-
-void LLPanelMarketplaceOutbox::importGetTrigger()
-{
-	mImportGetPending = true;
-	
-	std::string url = getMarketplaceURL_InventoryImport();
-	LLSD headers = LLViewerMedia::getHeaders();
-	headers["Cookie"] = sMarketplaceCookie;
-	
-#if DEBUG_MARKETPLACE_HTTP_API
-	llinfos << "*** Marketplace *** " << "http get:  " << url << llendl;
-	llinfos << "*** Marketplace *** " << "headers: " << ll_pretty_print_sd(headers) << llendl;
-#endif // DEBUG_MARKETPLACE_HTTP_API
-	
-	const bool do_not_ignore_results = false;
-	
-	LLHTTPClient::get(url, new LLInventoryImportGetResponder(this, do_not_ignore_results), headers);
-}
-
-void LLPanelMarketplaceOutbox::establishMarketplaceSessionCookie()
-{
-	mImportInProgress = true;
-	mImportGetPending = true;
-	
-	std::string url = getMarketplaceURL_InventoryImport();
-	LLSD headers = LLViewerMedia::getHeaders();
-	
-	const bool ignore_results = true;
-	
-	LLHTTPClient::get(url, new LLInventoryImportGetResponder(this, ignore_results), headers);
-}
-
-void LLPanelMarketplaceOutbox::onImportPostComplete(U32 status, const LLSD& content)
-{
-#if DEBUG_MARKETPLACE_HTTP_API
-	llinfos << "*** Marketplace *** " << "status = " << status << llendl;
-	llinfos << "*** Marketplace *** " << "content = " << ll_pretty_print_sd(content) << llendl;
-#endif // DEBUG_MARKETPLACE_HTTP_API
-
-	mImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
-	updateImportButtonStatus();
-	
-	if (!mImportInProgress)
-	{
-		char status_string[16];
-		sprintf(status_string, "%d", status);
-
-		LLSD subs;
-		subs["ERROR_CODE"] = status_string;
-
-		LLNotificationsUtil::add("OutboxImportFailed", subs, LLSD::emptyMap());
 	}
 
-	// The POST request returns the IMPORT_DONE code on success
-	//if (status == MarketplaceErrorCodes::IMPORT_DONE)
-	//{
-	//	gImportPollingFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox importPoll", boost::bind(&importPoll, _1, this));
-	//}
+	return handled;
 }
 
-void LLPanelMarketplaceOutbox::onImportGetComplete(U32 status, const LLSD& content, bool ignoreResults)
+bool LLPanelMarketplaceOutbox::isOutboxEmpty() const
 {
-#if DEBUG_MARKETPLACE_HTTP_API
-	llinfos << "*** Marketplace *** " << "status = " << status << llendl;
-	llinfos << "*** Marketplace *** " << "content = " << ll_pretty_print_sd(content) << llendl;
-#endif // DEBUG_MARKETPLACE_HTTP_API
-
-	mImportGetPending = false;	
-	mImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
-	updateImportButtonStatus();
-	
-	if (!mImportInProgress && !ignoreResults)
-	{
-		if (status == MarketplaceErrorCodes::IMPORT_DONE)
-		{
-			LLNotificationsUtil::add("OutboxImportComplete", LLSD::emptyMap(), LLSD::emptyMap());
-		}
-		else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
-		{
-			LLNotificationsUtil::add("OutboxImportHadErrors", LLSD::emptyMap(), LLSD::emptyMap());
-		}
-		else
-		{
-			char status_string[16];
-			sprintf(status_string, "%d", status);
-			
-			LLSD subs;
-			subs["ERROR_CODE"] = status_string;
-			
-			//llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
-			LLNotificationsUtil::add("OutboxImportFailed", LLSD::emptyMap(), LLSD::emptyMap());
-		}
-	}
+	return (getTotalItemCount() == 0);
 }
 
 void LLPanelMarketplaceOutbox::updateImportButtonStatus()
 {
-	if (isImportInProgress())
+	if (LLMarketplaceInventoryImporter::instance().isImportInProgress())
 	{
 		mImportButton->setVisible(false);
 
@@ -440,7 +222,7 @@ void LLPanelMarketplaceOutbox::updateImportButtonStatus()
 		mImportIndicator->setVisible(false);
 
 		mImportButton->setVisible(true);
-		mImportButton->setEnabled(getMarketplaceImportEnabled() && !isOutboxEmpty());
+		mImportButton->setEnabled(!isOutboxEmpty());
 	}
 }
 
@@ -464,7 +246,7 @@ U32 LLPanelMarketplaceOutbox::getTotalItemCount() const
 
 void LLPanelMarketplaceOutbox::onImportButtonClicked()
 {
-	importPostTrigger();
+	LLMarketplaceInventoryImporter::instance().triggerImport();
 	
 	// Get the import animation going
 	updateImportButtonStatus();
@@ -488,19 +270,5 @@ void LLPanelMarketplaceOutbox::draw()
 		mOutboxButton->setLabel(getString("OutboxLabelNoArg"));
 	}
 	
-	if (!isImportInProgress())
-	{
-		mImportButton->setEnabled(getMarketplaceImportEnabled() && not_empty);
-	}
-	else
-	{
-		++mImportFrameTimer;
-		
-		if ((mImportFrameTimer % 50 == 0) && !mImportGetPending)
-		{
-			importGetTrigger();
-		}
-	}
-	
 	LLPanel::draw();
 }
diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h
index 9cbb9cf21b..6f038118b3 100644
--- a/indra/newview/llpanelmarketplaceoutbox.h
+++ b/indra/newview/llpanelmarketplaceoutbox.h
@@ -59,10 +59,6 @@ public:
 	U32 getTotalItemCount() const;
 
 	bool isOutboxEmpty() const;
-	bool isImportInProgress() const;
-
-	void onImportPostComplete(U32 status, const LLSD& content);
-	void onImportGetComplete(U32 status, const LLSD& content, bool ignoreResults);
 
 	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 								   EDragAndDropType cargo_type,
@@ -78,18 +74,14 @@ protected:
 	void onFocusReceived();
 	void onSelectionChange();
 	
-	void importPostTrigger();
-	void importGetTrigger();
-	void establishMarketplaceSessionCookie();
-
+	void importReportResults(U32 status, const LLSD& content);
+	void importStatusChanged(bool inProgress);
+	
 private:
 	LLInventoryPanel *		mInventoryPanel;
 
 	LLButton *				mImportButton;
-	U32						mImportFrameTimer;
-	bool					mImportGetPending;
 	LLLoadingIndicator *	mImportIndicator;
-	bool					mImportInProgress;
 	
 	LLButton *				mOutboxButton;
 };
-- 
cgit v1.2.3


From 468543c944b073af41a3cf7f6dfe73f097c2eb2d Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Thu, 8 Dec 2011 10:33:23 +0000
Subject: Reverting the changes to default script which leaked in from another
 project ;-)

---
 indra/newview/llpreviewscript.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 0a429269ba..62603a2e07 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -90,15 +90,15 @@
 const std::string HELLO_LSL =
 	"default\n"
 	"{\n"
-	"	state_entry()\n"
-    "	{\n"
-    "		llOwnerSay(\"Hello, Avatar!\");\n"
-    "	}\n"
+	"    state_entry()\n"
+    "    {\n"
+    "        llSay(0, \"Hello, Avatar!\");\n"
+    "    }\n"
 	"\n"
-	"	touch_start(integer total_number)\n"
-	"	{\n"
-	"		llSay(llDetectedKey(0), \"Touched.\");\n"
-	"	}\n"
+	"    touch_start(integer total_number)\n"
+	"    {\n"
+	"        llSay(0, \"Touched.\");\n"
+	"    }\n"
 	"}\n";
 const std::string HELP_LSL_PORTAL_TOPIC = "LSL_Portal";
 
-- 
cgit v1.2.3


From f75708a9c8a549da0f243d47cc02208821dab5ef Mon Sep 17 00:00:00 2001
From: Paul ProductEngine <pguslisty@productengine.com>
Date: Thu, 8 Dec 2011 18:48:22 +0200
Subject: EXP-1598 FIXED (items from a second inventory window cannot be
 shared)

- Now select proper inventory floater (from all opened inventory floaters) to share items from.
---
 indra/newview/llinventorypanel.cpp     | 27 ++++++++++-----------------
 indra/newview/llpanelmaininventory.cpp |  9 ++++++++-
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index d06374d232..80b53d5702 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -1105,30 +1105,23 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
 		return FALSE;
 	}
 
-	LLSidepanelInventory *sidepanel_inventory =	LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
+	LLSidepanelInventory *inventory_panel =	LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
 
-	// A. If the inventory side panel floater is open, use that preferably.
-	if (is_inventorysp_active())
-	{
-		// Get the floater's z order to compare it to other inventory floaters' order later.
-		res = sidepanel_inventory->getActivePanel();
-		z_min = gFloaterView->getZOrder(floater_inventory);
-		active_inv_floaterp = floater_inventory;
-	}
-
-	// B. Iterate through the inventory floaters and return whichever is on top.
+	// Iterate through the inventory floaters and return whichever is on top.
 	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
 	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
 	{
-		LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter);
-		if (iv && iv->getVisible())
+		LLFloaterSidePanelContainer* inventory_floater = dynamic_cast<LLFloaterSidePanelContainer*>(*iter);
+		inventory_panel = inventory_floater->findChild<LLSidepanelInventory>("main_panel");
+
+		if (inventory_floater && inventory_panel && inventory_floater->getVisible())
 		{
-			S32 z_order = gFloaterView->getZOrder(iv);
+			S32 z_order = gFloaterView->getZOrder(inventory_floater);
 			if (z_order < z_min)
 			{
-				res = iv->getPanel();
+				res = inventory_panel->getActivePanel();
 				z_min = z_order;
-				active_inv_floaterp = iv;
+				active_inv_floaterp = inventory_floater;
 			}
 		}
 	}
@@ -1145,7 +1138,7 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
 	{
 		floater_inventory->openFloater();
 
-		res = sidepanel_inventory->getActivePanel();
+		res = inventory_panel->getActivePanel();
 	}
 
 	return res;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 9944b51902..68ef13cd68 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -28,6 +28,7 @@
 #include "llpanelmaininventory.h"
 
 #include "llagent.h"
+#include "llagentcamera.h"
 #include "llavataractions.h"
 #include "lldndbutton.h"
 #include "lleconomy.h"
@@ -294,7 +295,13 @@ void LLPanelMainInventory::closeAllFolders()
 
 void LLPanelMainInventory::newWindow()
 {
-	LLFloaterInventory::showAgentInventory();
+	static S32 instance_num = 0;
+	instance_num = (instance_num + 1) % S32_MAX;
+
+	if (!gAgentCamera.cameraMouselook())
+	{
+		LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num));
+	}
 }
 
 void LLPanelMainInventory::doCreate(const LLSD& userdata)
-- 
cgit v1.2.3


From 86847b753befbca31e4aadeff111acd398f9612d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 8 Dec 2011 15:33:27 -0800
Subject: fix for build error

---
 indra/llmessage/llsdmessagereader.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp
index 3ab62a8c57..3d8ca2ad9f 100644
--- a/indra/llmessage/llsdmessagereader.cpp
+++ b/indra/llmessage/llsdmessagereader.cpp
@@ -294,7 +294,7 @@ S32 getElementSize(const LLSD& llsd)
 	default:                        // TypeLLSDTypeEnd, TypeLLSDNumTypes, etc.
 		return 0;
 	}
-	return 0;
+	//return 0;
 }
 
 //virtual 
-- 
cgit v1.2.3


From ca4eab69b9b1ed42f3128635ef1f278600b59118 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Thu, 8 Dec 2011 17:49:56 -0600
Subject: SH-2680 Bring back blurred edges on objects closer than the near
 focal plane.

---
 .../app_settings/shaders/class1/deferred/cofF.glsl |  7 ++--
 .../shaders/class1/deferred/dofCombineF.glsl       |  2 +-
 .../shaders/class1/deferred/postDeferredF.glsl     | 40 +++++++++++++++++++---
 3 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
index 88fe3c3dee..e612efba61 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
@@ -57,7 +57,7 @@ float getDepth(vec2 pos_screen)
 
 float calc_cof(float depth)
 {
-	float sc = abs(depth-focal_distance)/-depth*blur_constant;
+	float sc = (depth-focal_distance)/-depth*blur_constant;
 		
 	sc /= magnification;
 	
@@ -79,9 +79,10 @@ void main()
 	vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
 	
 	float sc = calc_cof(depth);
-	sc = min(abs(sc), max_cof);
+	sc = min(sc, max_cof);
+	sc = max(sc, -max_cof);
 	
 	vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
 	gl_FragColor.rgb = diff.rgb + bloom.rgb;
-	gl_FragColor.a = sc/max_cof;
+	gl_FragColor.a = sc/max_cof*0.5+0.5;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
index 21453aefaa..01e3505359 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
@@ -48,7 +48,7 @@ void main()
 	
 	vec4 diff = texture2DRect(lightMap, vary_fragcoord.xy);
 
-	float a = min(diff.a * max_cof*res_scale*res_scale, 1.0);
+	float a = min(abs(diff.a*2.0-1.0) * max_cof*res_scale*res_scale, 1.0);
 
 	if (a > 0.25 && a < 0.75)
 	{ //help out the transition a bit
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
index 4603d99c5e..18d451bf87 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -42,7 +42,7 @@ void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc)
 {
 	vec4 s = texture2DRect(diffuseRect, tc);
 
-	float sc = s.a*max_cof;
+	float sc = abs(s.a*2.0-1.0)*max_cof;
 
 	if (sc > min_sc) //sampled pixel is more "out of focus" than current sample radius
 	{
@@ -57,6 +57,20 @@ void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc)
 	}
 }
 
+void dofSampleNear(inout vec4 diff, inout float w, float min_sc, vec2 tc)
+{
+	vec4 s = texture2DRect(diffuseRect, tc);
+
+	float wg = 0.25;
+
+	// de-weight dull areas to make highlights 'pop'
+	wg += s.r+s.g+s.b;
+
+	diff += wg*s;
+		
+	w += wg;
+}
+
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
@@ -66,12 +80,30 @@ void main()
 	{ 
 		float w = 1.0;
 		
-		float sc = diff.a*max_cof;
-				
+		float sc = (diff.a*2.0-1.0)*max_cof;
+			
 		float PI = 3.14159265358979323846264;
 
 		// sample quite uniformly spaced points within a circle, for a circular 'bokeh'		
+		if (sc > 0.5)
+		{
+			while (sc > 0.5)
+			{
+				int its = int(max(1.0,(sc*3.7)));
+				for (int i=0; i<its; ++i)
+				{
+					float ang = sc+i*2*PI/its; // sc is added for rotary perturbance
+					float samp_x = sc*sin(ang);
+					float samp_y = sc*cos(ang);
+					// you could test sample coords against an interesting non-circular aperture shape here, if desired.
+					dofSampleNear(diff, w, sc, vary_fragcoord.xy + vec2(samp_x,samp_y));
+				}
+				sc -= 1.0;
+			}
+		}
+		else if (sc < -0.5)
 		{
+			sc = abs(sc);
 			while (sc > 0.5)
 			{
 				int its = int(max(1.0,(sc*3.7)));
@@ -86,7 +118,7 @@ void main()
 				sc -= 1.0;
 			}
 		}
-		
+
 		diff /= w;
 	}
 		
-- 
cgit v1.2.3


From 67f1321f31d5988e7b383cfbf4fbd6537f3d2710 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 8 Dec 2011 16:46:30 -0800
Subject: Initial functional merchant outbox floater

---
 indra/newview/llfloateroutbox.cpp                  | 309 ++++++++++++++++++++-
 indra/newview/llfloateroutbox.h                    |  44 ++-
 indra/newview/llmarketplacefunctions.cpp           |   7 +-
 indra/newview/llsidepanelinventory.cpp             |   2 +-
 .../default/xui/en/floater_merchant_outbox.xml     | 137 ++++-----
 5 files changed, 416 insertions(+), 83 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 8fea3d674e..79cd90ba1c 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -29,40 +29,333 @@
 #include "llfloateroutbox.h"
 
 #include "llfloaterreg.h"
+#include "llfolderview.h"
+#include "llinventoryobserver.h"
+#include "llinventorypanel.h"
+#include "llloadingindicator.h"
+#include "llmarketplacefunctions.h"
+#include "llnotificationsutil.h"
+#include "lltextbox.h"
 #include "lltransientfloatermgr.h"
+#include "lltrans.h"
+#include "llviewernetwork.h"
 
 
+///----------------------------------------------------------------------------
+/// LLOutboxAddedObserver helper class
+///----------------------------------------------------------------------------
+
+class LLOutboxAddedObserver : public LLInventoryCategoryAddedObserver
+{
+public:
+	LLOutboxAddedObserver(LLFloaterOutbox * outboxFloater)
+		: LLInventoryCategoryAddedObserver()
+		, mOutboxFloater(outboxFloater)
+	{
+	}
+	
+	void done()
+	{
+		for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it)
+		{
+			LLViewerInventoryCategory* added_category = *it;
+			
+			LLFolderType::EType added_category_type = added_category->getPreferredType();
+			
+			if (added_category_type == LLFolderType::FT_OUTBOX)
+			{
+				mOutboxFloater->setupOutbox(added_category->getUUID());
+			}
+		}
+	}
+	
+private:
+	LLFloaterOutbox *	mOutboxFloater;
+};
+
 ///----------------------------------------------------------------------------
 /// LLFloaterOutbox
 ///----------------------------------------------------------------------------
 
 LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
 	: LLFloater(key)
-	, mPanelOutboxInventory(NULL)
+	, mCategoriesObserver(NULL)
+	, mCategoryAddedObserver(NULL)
+	, mOutboxId(LLUUID::null)
+	, mOutboxInventoryPanel(NULL)
+	, mOutboxItemCount(0)
+	, mInventoryDisablePanel(NULL)
+	, mInventoryFolderCountText(NULL)
+	, mInventoryImportInProgress(NULL)
+	, mInventoryPlaceholder(NULL)
+	, mInventoryText(NULL)
+	, mInventoryTitle(NULL)
+	, mImportButton(NULL)
 {
-	LLTransientFloaterMgr::getInstance()->addControlView(this);
 }
 
 LLFloaterOutbox::~LLFloaterOutbox()
 {
-	LLTransientFloaterMgr::getInstance()->removeControlView(this);
+//	delete mCategoriesObserver;
+//	delete mCategoryAddedObserver;
 }
 
 BOOL LLFloaterOutbox::postBuild()
 {
+	mInventoryDisablePanel = getChild<LLView>("outbox_inventory_disable_panel");
+	mInventoryFolderCountText = getChild<LLTextBox>("outbox_folder_count");
+	mInventoryImportInProgress = getChild<LLLoadingIndicator>("import_progress_indicator");
+	mInventoryPlaceholder = getChild<LLView>("outbox_inventory_placeholder_panel");
+	mInventoryText = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_text");
+	mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_title");
+	
+	mImportButton = getChild<LLButton>("outbox_import_btn");
+	mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this));
+
 	return TRUE;
 }
 
 void LLFloaterOutbox::onOpen(const LLSD& key)
 {
-	//LLFirstUse::useInventory();
+	//
+	// Initialize the marketplace import API
+	//
+
+	LLMarketplaceInventoryImporter::getInstance()->initialize();
+	LLMarketplaceInventoryImporter::getInstance()->setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
+	LLMarketplaceInventoryImporter::getInstance()->setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
+	
+	//
+	// Look for an outbox and set up the inventory API
+	//
+
+	const bool do_not_create_folder = false;
+	const bool do_not_find_in_library = false;
+	
+	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library);
+	
+	if (outbox_id.isNull())
+	{
+		// Observe category creation to catch outbox creation
+		mCategoryAddedObserver = new LLOutboxAddedObserver(this);
+		gInventory.addObserver(mCategoryAddedObserver);
+	}
+	else
+	{
+		setupOutbox(outbox_id);
+	}
+	
+	updateView();
+}
+
+void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
+{	
+	llassert(mOutboxId.isNull());
+	llassert(mCategoriesObserver == NULL);
+	
+	mOutboxId = outboxId;
+	
+	// No longer need to observe new category creation
+	if (mCategoryAddedObserver != NULL)
+	{
+		gInventory.removeObserver(mCategoryAddedObserver);
+	}	
+	
+	// Create observer for outbox modifications
+	mCategoriesObserver = new LLInventoryCategoriesObserver();
+	gInventory.addObserver(mCategoriesObserver);
+	
+	mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this));
+	
+	//
+	// Set up the outbox inventory view
+	//
+	
+	mOutboxInventoryPanel = 
+		LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml",
+														  mInventoryPlaceholder->getParent(),
+														  LLInventoryPanel::child_registry_t::instance());
+	
+	llassert(mOutboxInventoryPanel);
+	
+	// Reshape the inventory to the proper size
+	LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect();
+	mOutboxInventoryPanel->setShape(inventory_placeholder_rect);
+	
+	// Set the sort order newest to oldest
+	mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);	
+	mOutboxInventoryPanel->getFilter()->markDefault();
+	
+	// Set selection callback for proper update of inventory status buttons
+	//mOutboxInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceOutbox::onSelectionChange, this));
+	
+	// Set up the note to display when the outbox is empty
+	mOutboxInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryOutboxNoItems");
+}
+
+void LLFloaterOutbox::updateView()
+{
+	if (mOutboxItemCount > 0)
+	{
+		mOutboxInventoryPanel->setVisible(TRUE);
+		mInventoryPlaceholder->setVisible(FALSE);
+	}
+	else
+	{
+		mOutboxInventoryPanel->setVisible(FALSE);
+		mInventoryPlaceholder->setVisible(TRUE);
+
+		std::string outbox_text;
+		std::string outbox_title;
+		std::string outbox_tooltip;
+		
+		if (mOutboxId.notNull())
+		{
+			outbox_text = LLTrans::getString("InventoryOutboxNoItems");
+			outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle");
+			outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip");
+		}
+		else
+		{
+			//
+			// The string to become a merchant contains 3 URL's which need the domain name patched in.
+			//
+			
+			std::string domain = "secondlife.com";
+			
+			if (!LLGridManager::getInstance()->isInProductionGrid())
+			{
+				std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
+				domain = llformat("%s.lindenlab.com", utf8str_tolower(gridLabel).c_str());
+			}
+			
+			LLStringUtil::format_map_t domain_arg;
+			domain_arg["[DOMAIN_NAME]"] = domain;
+			
+			std::string marketplace_url = LLTrans::getString("MarketplaceURL", domain_arg);
+			std::string marketplace_url_create = LLTrans::getString("MarketplaceURL_CreateStore", domain_arg);
+			std::string marketplace_url_info = LLTrans::getString("MarketplaceURL_LearnMore", domain_arg);
+			
+			LLStringUtil::format_map_t args1, args2, args3;
+			args1["[MARKETPLACE_URL]"] = marketplace_url;
+			args2["[LEARN_MORE_URL]"] = marketplace_url_info;
+			args3["[CREATE_STORE_URL]"] = marketplace_url_create;
+			
+			// NOTE: This is dumb, ridiculous and very finicky.  The order of these is very important
+			//       to have these three string substitutions work properly.
+			outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", args1);
+			LLStringUtil::format(outbox_text, args2);
+			LLStringUtil::format(outbox_text, args3);
+			
+			outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle");
+			outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip");
+		}
+		
+		mInventoryText->setValue(outbox_text);
+		mInventoryTitle->setValue(outbox_title);
+		mInventoryPlaceholder->getParent()->setToolTip(outbox_tooltip);
+	}
+}
+
+BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+										EDragAndDropType cargo_type,
+										void* cargo_data,
+										EAcceptance* accept,
+										std::string& tooltip_msg)
+{
+	// Pass drag and drop to this floater to the outbox inventory control
+
+	S32 local_x = x - mOutboxInventoryPanel->getRect().mLeft;
+	S32 local_y = y - mOutboxInventoryPanel->getRect().mBottom;
+
+	return mOutboxInventoryPanel->handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+}
+
+void LLFloaterOutbox::onImportButtonClicked()
+{
+	LLMarketplaceInventoryImporter::instance().triggerImport();
+}
+
+void LLFloaterOutbox::onOutboxChanged()
+{
+	llassert(!mOutboxId.isNull());
+	
+	U32 item_count = 0;
+	
+	const LLFolderViewFolder * outbox_folder = mOutboxInventoryPanel->getRootFolder();
+	
+	if (outbox_folder)
+	{
+		item_count += outbox_folder->getFoldersCount();
+		item_count += outbox_folder->getItemsCount();
+	}
+	
+	mOutboxItemCount = item_count;
+
+	switch (mOutboxItemCount)
+	{
+		case 0:	mInventoryFolderCountText->setText(getString("OutboxFolderCount0"));	break;
+		case 1:	mInventoryFolderCountText->setText(getString("OutboxFolderCount1"));	break;
+		default:
+		{
+			std::string item_count_str = llformat("%d", mOutboxItemCount);
+			
+			LLStringUtil::format_map_t args;
+			args["[NUM]"] = item_count_str;
+
+			mInventoryFolderCountText->setText(getString("OutboxFolderCountN", args));
+			break;
+		}
+	}
+
+	mImportButton->setEnabled(mOutboxItemCount > 0);
+
+	updateView();
 }
 
-void LLFloaterOutbox::onClose(bool app_quitting)
+void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
 {
-	LLFloater::onClose(app_quitting);
-	if (mKey.asInteger() > 1)
+	if (status == MarketplaceErrorCodes::IMPORT_DONE)
+	{
+		LLNotificationsUtil::add("OutboxImportComplete", LLSD::emptyMap(), LLSD::emptyMap());
+	}
+	else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
+	{
+		LLNotificationsUtil::add("OutboxImportHadErrors", LLSD::emptyMap(), LLSD::emptyMap());
+	}
+	else
 	{
-		destroy();
+		char status_string[16];
+		sprintf(status_string, "%d", status);
+		
+		LLSD subs;
+		subs["ERROR_CODE"] = status_string;
+		
+		//llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
+		LLNotificationsUtil::add("OutboxImportFailed", LLSD::emptyMap(), LLSD::emptyMap());
 	}
 }
+
+void LLFloaterOutbox::importStatusChanged(bool inProgress)
+{
+	if (inProgress)
+	{
+		mImportButton->setEnabled(false);
+		
+		mInventoryDisablePanel->setVisible(true);
+
+		mInventoryImportInProgress->setVisible(true);
+		mInventoryImportInProgress->reset();
+		mInventoryImportInProgress->start();
+	}
+	else
+	{
+		mImportButton->setEnabled(mOutboxItemCount > 0);
+		
+		mInventoryDisablePanel->setVisible(false);
+
+		mInventoryImportInProgress->stop();
+		mInventoryImportInProgress->setVisible(false);
+	}
+}
+
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index cb5c2be81c..1e8567ef12 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -31,7 +31,15 @@
 #include "llfloater.h"
 #include "llfoldertype.h"
 
+
+class LLButton;
+class LLInventoryCategoriesObserver;
+class LLInventoryCategoryAddedObserver;
 class LLInventoryPanel;
+class LLLoadingIndicator;
+class LLTextBox;
+class LLView;
+
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLFloaterOutbox
@@ -42,15 +50,43 @@ class LLFloaterOutbox : public LLFloater
 public:
 	LLFloaterOutbox(const LLSD& key);
 	~LLFloaterOutbox();
+	
+	void setupOutbox(const LLUUID& outboxId);
 
+	// virtuals
 	BOOL postBuild();
+	void onOpen(const LLSD& key);
+	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+						   EDragAndDropType cargo_type,
+						   void* cargo_data,
+						   EAcceptance* accept,
+						   std::string& tooltip_msg);
 
-	// Inherited functionality
-	/*virtual*/ void onOpen(const LLSD& key);
-	/*virtual*/ void onClose(bool app_quitting);
+protected:
+	void importReportResults(U32 status, const LLSD& content);
+	void importStatusChanged(bool inProgress);
+	
+	void onImportButtonClicked();
+	void onOutboxChanged();
+	
+	void updateView();
 
 private:
-	LLInventoryPanel* mPanelOutboxInventory;
+	LLInventoryCategoriesObserver *		mCategoriesObserver;
+	LLInventoryCategoryAddedObserver *	mCategoryAddedObserver;
+
+	LLUUID				mOutboxId;
+	LLInventoryPanel *	mOutboxInventoryPanel;
+	U32					mOutboxItemCount;
+	
+	LLView *				mInventoryDisablePanel;
+	LLTextBox *				mInventoryFolderCountText;
+	LLLoadingIndicator *	mInventoryImportInProgress;
+	LLView *				mInventoryPlaceholder;
+	LLTextBox *				mInventoryText;
+	LLTextBox *				mInventoryTitle;
+	
+	LLButton *		mImportButton;
 };
 
 #endif // LL_LLFLOATEROUTBOX_H
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index b9e02a36b4..9c67c589b8 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -55,6 +55,7 @@ namespace LLMarketplaceImport
 
 	static std::string sMarketplaceCookie = "";
 	static bool sImportInProgress = false;
+	static bool sImportPostPending = false;
 	static bool sImportGetPending = false;
 	static U32 sImportResultStatus = 0;
 	static LLSD sImportResults = LLSD::emptyMap();
@@ -106,6 +107,7 @@ namespace LLMarketplaceImport
 		void completed(U32 status, const std::string& reason, const LLSD& content)
 		{
 			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
+			sImportPostPending = false;
 			sImportResultStatus = status;
 		}
 	};
@@ -185,7 +187,7 @@ namespace LLMarketplaceImport
 	
 	bool resultPending()
 	{
-		return sImportGetPending;
+		return (sImportPostPending || sImportGetPending);
 	}
 	
 	U32 getResultStatus()
@@ -226,7 +228,8 @@ namespace LLMarketplaceImport
 	
 	void triggerImport()
 	{
-		sImportInProgress = true;		
+		sImportInProgress = true;
+		sImportPostPending = true;
 		sImportResultStatus = MarketplaceErrorCodes::IMPORT_PROCESSING;
 		sImportResults = LLSD::emptyMap();
 
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 19a81b93bf..9c551be2d5 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -926,7 +926,7 @@ U32 LLSidepanelInventory::getSelectedCount()
 	{
 		selection_list = mInventoryPanelInbox->getRootFolder()->getSelectionList();
 
-	count += selection_list.size();
+		count += selection_list.size();
 	}
 
 	if ((count == 0) && mOutboxEnabled && (mInventoryPanelOutbox != NULL))
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index 2f8a83c072..86e27cbc71 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -3,90 +3,33 @@
  open_positioning="cascading"
  can_close="true"
  can_resize="true"
- height="400"
+ height="440"
  help_topic="floater_merchant_outbox"
- min_width="333"
- min_height="440"
+ min_width="300"
+ min_height="240"
  name="floater_merchant_outbox"
  save_rect="true"
  save_visibility="true"
  reuse_instance="true"
  title="MERCHANT OUTBOX"
  width="333" >
+ <string name="OutboxFolderCount0">0 folders</string>
+ <string name="OutboxFolderCount1">1 folder</string>
+ <string name="OutboxFolderCountN">[NUM] folders</string>
  <panel
       follows="all"
       layout="topleft"
       left="0"
-      name="marketplace_outbox"
-      class="panel_marketplace_outbox"
       top="0"
       label=""
-      height="400"
-      width="330">
-     <string name="OutboxLabelWithArg">Merchant outbox ([NUM])</string>
-     <string name="OutboxLabelNoArg">Merchant outbox</string>
-     <button
-        label="Merchant outbox"
-        font="SansSerifMedium"
-        name="outbox_btn"
-        height="35"
-        width="308"
-        image_unselected="MarketplaceBtn_Off"
-        image_selected="MarketplaceBtn_Selected"
-        halign="left"
-        handle_right_mouse="false"
-        follows="top|left|right"
-        is_toggle="true"
-        tab_stop="false"
-        pad_left="35"
-        top="0"
-        left="10" />
-     <button
-         image_unselected="OutboxPush_Off"
-         image_selected="OutboxPush_Selected"
-         image_hover_selected="OutboxPush_Selected_Over"
-         image_hover_unselected="OutboxPush_Over"
-         image_disabled_selected="OutboxPush_Selected_Disabled"
-         image_disabled="OutboxPush_Disabled"
-         image_pressed="OutboxPush_Press"
-         image_pressed_selected="OutboxPush_Selected_Press"
-         label=""
-         tool_tip="Push to my Marketplace Storefront"
-         is_toggle="false"
-         name="outbox_sync_btn"
-         follows="top|right"
-         tab_stop="false"
-         halign="center"
-         top="6"
-         left="-50"
-         height="23"
-         width="32"
-         enabled="false" />
-     <loading_indicator
-        follows="top|right"
-        name="outbox_sync_indicator"
-        top="6"
-        left="-50"
-        height="23"
-        width="32"
-        images_per_sec="1.15"
-        tab_stop="false"
-        visible="false">
-         <images>
-             <image name="OutboxPush_Progress_1"/>
-             <image name="OutboxPush_Progress_2"/>
-             <image name="OutboxPush_Progress_3"/>
-             <image name="OutboxPush_Progress_4"/>
-             <image name="OutboxPush_Progress_5"/>
-             <image name="OutboxPush_Progress_6"/>
-         </images>
-     </loading_indicator>
+      height="440"
+      width="333">
      <panel
         follows="all"
         left="10"
         bottom="400"
-        width="308"
-        top="35"
+        width="313"
+        top="0"
         bg_opaque_color="InventoryBackgroundColor"
         background_visible="true"
         background_opaque="true"
@@ -98,7 +41,7 @@
 			top="0"
 			left="0"
 			width="308"
-			height="365"
+			height="400"
 			bg_opaque_color="InventoryBackgroundColor"
 			background_visible="true"
 			background_opaque="true"
@@ -129,6 +72,64 @@
 				wrap="true"
 				halign="left" />
 		</panel>
+    </panel>
+	<panel
+		name="outbox_inventory_disable_panel"
+        follows="all"
+        left="0"
+        bottom="440"
+        width="333"
+        top="0"
+        bg_opaque_color="White_50"
+        background_visible="true"
+        background_opaque="true"
+		visible="false"
+        />
+	<loading_indicator
+		 follows="all"
+		 height="65"
+		 layout="topleft"
+		 left="140"
+		 name="import_progress_indicator"
+		 top="180"
+		 visible="false"
+		 width="45" />
+	<panel
+        follows="bottom|left|right"
+        left="10"
+        bottom="435"
+        width="313"
+        top="405"
+        bg_opaque_color="InventoryBackgroundColor"
+        background_visible="true"
+        background_opaque="true"
+        >
+		<text
+			name="outbox_folder_count"
+			type="string"
+			follows="all"
+			layout="topleft"
+			top="7"
+			left="5"
+			width="100"
+			height="20"
+			wrap="true"
+			halign="left"
+			valign="baseline"
+			font="SansSerifBold" />
+		<button
+			 label="Send to Marketplace"
+			 tool_tip="Push to my Marketplace Storefront"
+			 is_toggle="false"
+			 name="outbox_import_btn"
+			 follows="bottom|right"
+			 tab_stop="false"
+			 halign="center"
+			 top="3"
+			 left="110"
+			 height="25"
+			 width="200"
+			 enabled="false" />
     </panel>
  </panel>
 </floater>
-- 
cgit v1.2.3


From 0aa2c7343ac2af195e80c8f52b9ef67da785fa00 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 8 Dec 2011 20:36:47 -0800
Subject: EXP-1512 FIX changing UI size changes cursor position in notecards

---
 indra/llui/lltextbase.cpp | 31 ++++++++++++++++++++++++++++++-
 indra/llui/lltextbase.h   |  2 ++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 3b768166f1..1f890b625f 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -598,7 +598,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
 
 	pos = getEditableIndex(pos, true);
 
-	segment_set_t::iterator seg_iter = getSegIterContaining(pos);
+	segment_set_t::iterator seg_iter = getEditableSegIterContaining(pos);
 
 	LLTextSegmentPtr default_segment;
 
@@ -1510,8 +1510,37 @@ void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg
 	}
 }
 
+LLTextBase::segment_set_t::iterator LLTextBase::getEditableSegIterContaining(S32 index)
+{
+	segment_set_t::iterator it = getSegIterContaining(index);
+	if (it == mSegments.end()) return it;
+
+	if (!(*it)->canEdit() 
+		&& index == (*it)->getStart() 
+		&& it != mSegments.begin())
+	{
+		it--;
+	}
+	return it;
+}
+
+LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaining(S32 index) const
+{
+	segment_set_t::const_iterator it = getSegIterContaining(index);
+	if (it == mSegments.end()) return it;
+
+	if (!(*it)->canEdit() 
+		&& index == (*it)->getStart() 
+		&& it != mSegments.begin())
+	{
+		it--;
+	}
+	return it;
+}
+
 LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
 {
+
 	static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment();
 
 	if (index > getLength()) { return mSegments.end(); }
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index b699601908..0549141b72 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -461,6 +461,8 @@ protected:
 	void                			getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
 	void                			getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp );
 	LLTextSegmentPtr    			getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line = true);
+	segment_set_t::iterator			getEditableSegIterContaining(S32 index);
+	segment_set_t::const_iterator	getEditableSegIterContaining(S32 index) const;
 	segment_set_t::iterator			getSegIterContaining(S32 index);
 	segment_set_t::const_iterator	getSegIterContaining(S32 index) const;
 	void                			clearSegments();
-- 
cgit v1.2.3


From 6fd96dd2632c8e94cfda926816fb81faf6f574c5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 8 Dec 2011 20:37:03 -0800
Subject: made undo/redo/paste accept key repeat

---
 indra/newview/skins/default/xui/en/menu_edit.xml   | 3 +++
 indra/newview/skins/default/xui/en/menu_viewer.xml | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/indra/newview/skins/default/xui/en/menu_edit.xml b/indra/newview/skins/default/xui/en/menu_edit.xml
index fab76c497c..99061e089a 100644
--- a/indra/newview/skins/default/xui/en/menu_edit.xml
+++ b/indra/newview/skins/default/xui/en/menu_edit.xml
@@ -6,6 +6,7 @@
   <menu_item_call
    label="Undo"
    name="Undo"
+   allow_key_repeat="true"
    shortcut="control|Z">
     <menu_item_call.on_click
      function="Edit.Undo" />
@@ -15,6 +16,7 @@
   <menu_item_call
    label="Redo"
    name="Redo"
+   allow_key_repeat="true"
    shortcut="control|Y">
     <menu_item_call.on_click
      function="Edit.Redo" />
@@ -43,6 +45,7 @@
   <menu_item_call
    label="Paste"
    name="Paste"
+   allow_key_repeat="true"
    shortcut="control|V">
     <menu_item_call.on_click
      function="Edit.Paste" />
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 1834be2d48..f23d48f8c5 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1154,6 +1154,7 @@
          enabled="false"
          label="Undo"
          name="Undo"
+         allow_key_repeat="true"
          shortcut="control|Z">
             <on_click
              function="Edit.Undo"
@@ -1165,6 +1166,7 @@
          enabled="false"
          label="Redo"
          name="Redo"
+         allow_key_repeat="true"
          shortcut="control|Y">
             <on_click
              function="Edit.Redo"
-- 
cgit v1.2.3


From 04d5ba4ab982eed493502dca228134191acb78da Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Fri, 9 Dec 2011 09:51:25 +0000
Subject: General cleanup of new code (removing commented lines, experimetal
 stuff), adding some comments per RB feedback.

---
 indra/newview/llpreviewscript.cpp              | 15 ++------
 indra/newview/skins/default/xui/en/strings.xml | 52 +++++++++++++-------------
 2 files changed, 30 insertions(+), 37 deletions(-)

diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 62603a2e07..cab30b1295 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1108,19 +1108,12 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask)
 void LLScriptEdCore::onBtnLoadFromFile( void* data )
 {
 	LLScriptEdCore* self = (LLScriptEdCore*) data;
-/*
-	if( self->isDirty())
-	{
-		llwarns << "Script has unsaved changes, loading from disc aborted." << llendl;
-		LLStringBase<char>::format_map_t args;
-		args["[REASON]"] = std::string("Existing script has unsaved changes. You must save this script before loading from disc.");
-		gViewerWindow->alertXml("LoadDiskScriptFailReason", args);		
-		return;
-	}
-*/
+
+	// TODO Maybe add a dialogue warning here if the current file has unsaved changes.
 	LLFilePicker& file_picker = LLFilePicker::instance();
 	if( !file_picker.getOpenFile( LLFilePicker::FFLOAD_SCRIPT ) )
 	{
+		//File picking cancelled by user, so nothing to do.
 		return;
 	}
 
@@ -1147,7 +1140,6 @@ void LLScriptEdCore::onBtnLoadFromFile( void* data )
 	{
 		self->mEditor->selectAll();
 		LLWString script(utf8str_to_wstring(text));
-		LLWStringUtil::replaceTabsWithSpaces(script, self->mEditor->spacesPerTab());
 		self->mEditor->insertText(script);
 	}
 }
@@ -1164,6 +1156,7 @@ void LLScriptEdCore::onBtnSaveToFile( void* userdata )
 		LLFilePicker& file_picker = LLFilePicker::instance();
 		if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_SCRIPT ) )
 		{
+			//File picking cancelled by user, so nothing to do.
 			return;
 		}
 
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 0d26465dfa..f962ff0aee 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -88,7 +88,7 @@ We are very sorry for the inconvenience.</string>
 Logins are currently restricted to employees only.
 Check www.secondlife.com/status for updates.</string>
 	<string name="LoginFailedPremiumOnly">Second Life logins are temporarily restricted in order to make sure that those in-world have the best possible experience.
-	 	
+
 People with free accounts will not be able to access Second Life during this time, to make room for those who have paid for Second Life.</string>
 	<string name="LoginFailedComputerProhibited">Second Life cannot be accessed from this computer.
 If you feel this is an error, please contact
@@ -168,7 +168,7 @@ Please try logging in again in a minute.</string>
 	<string name="TooltipOutboxWorn">You are wearing one or more of these objects. Remove them from your avatar and try moving them again.</string>
 	<string name="TooltipOutboxFolderLevels">This folder has too many levels of subfolders. Rearrange the interior folders to a maximum of 4 levels deep (Root Folder contains A contains B contains C).</string>
 	<string name="TooltipOutboxTooManyObjects">This folder contains more than 200 objects. Box some of the items to reduce the object count.</string>
-	
+
 	<!-- tooltips for Urls -->
 	<string name="TooltipHttpUrl">Click to view this web page</string>
 	<string name="TooltipSLURL">Click to view this location's information</string>
@@ -188,7 +188,7 @@ Please try logging in again in a minute.</string>
 	<string name="TooltipObjectIMUrl">Click to view this object's description</string>
 	<string name="TooltipMapUrl">Click to view this location on a map</string>
 	<string name="TooltipSLAPP">Click to run the secondlife:// command</string>
-	<string name="CurrentURL" value=" CurrentURL: [CurrentURL]" />	
+	<string name="CurrentURL" value=" CurrentURL: [CurrentURL]" />
 
 	<!-- text for SLURL labels -->
 	<string name="SLurlLabelTeleport">Teleport to</string>
@@ -427,7 +427,7 @@ Please try logging in again in a minute.</string>
 	<string name="compressed_image_files">Compressed Images</string>
 	<string name="load_files">Load Files</string>
 	<string name="choose_the_directory">Choose Directory</string>
-  <string name="script_files">Scripts</string>
+	<string name="script_files">Scripts</string>
 
   <!-- LSL Usage Hover Tips -->
   <!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window).
@@ -1951,7 +1951,7 @@ Returns a string with the requested data about the region
   <string name="physics">Physics</string>
   <string name="invalid">invalid</string>
   <string name="none">none</string>
-  
+
   <!-- Not Worn Wearable Types -->
 	<string name="shirt_not_worn">Shirt not worn</string>
 	<string name="pants_not_worn">Pants not worn</string>
@@ -1988,7 +1988,7 @@ Returns a string with the requested data about the region
 
   <!-- Wearable List-->
   <string name="NewWearable">New [WEARABLE_ITEM]</string>
-  
+
 	<!-- LLGroupNotify -->
 	<!-- used in the construction of a Group Notice blue dialog box, buttons, tooltip etc. Seems to be no longer utilized by code in Viewer 2.0 -->
 	<string name="next">Next</string>
@@ -2314,7 +2314,7 @@ Returns a string with the requested data about the region
 	<string name="ScriptLimitsRequestWrongRegion">Error: script information is only available in your current region</string>
 	<string name="ScriptLimitsRequestWaiting">Retrieving information...</string>
 	<string name="ScriptLimitsRequestDontOwnParcel">You do not have permission to examine this parcel</string>
-	
+
 	<string name="SITTING_ON">Sitting On</string>
 	<string name="ATTACH_CHEST">Chest</string>
 	<string name="ATTACH_HEAD">Head</string>
@@ -2354,7 +2354,7 @@ Returns a string with the requested data about the region
 	<string name="ATTACH_HUD_BOTTOM_LEFT">HUD Bottom Left</string>
 	<string name="ATTACH_HUD_BOTTOM">HUD Bottom</string>
 	<string name="ATTACH_HUD_BOTTOM_RIGHT">HUD Bottom Right</string>
-			
+
 	<!-- script editor -->
 	<string name="CursorPos">Line [LINE], Column [COLUMN]</string>
 
@@ -2367,7 +2367,7 @@ Returns a string with the requested data about the region
 
 	<!-- panel contents -->
 	<string name="PanelContentsTooltip">Content of object</string>
-	<string name="PanelContentsNewScript">New Script</string>	
+	<string name="PanelContentsNewScript">New Script</string>
 
   <!-- panel preferences general -->
   <string name="BusyModeResponseDefault">The Resident you messaged is in &apos;busy mode&apos; which means they have requested not to be disturbed.  Your message will still be shown in their IM panel for later viewing.</string>
@@ -2397,7 +2397,7 @@ Returns a string with the requested data about the region
 	<!-- panel classified -->
 	<string name="ClassifiedClicksTxt">Clicks: [TELEPORT] teleport, [MAP] map, [PROFILE] profile</string>
 	<string name="ClassifiedUpdateAfterPublish">(will update after publish)</string>
-  
+
   <!-- panel picks -->
   <string name="NoPicksClassifiedsText">You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified.</string>
   <string name="NoAvatarPicksClassifiedsText">User has no picks or classifieds</string>
@@ -3274,7 +3274,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
     You have blocked this Resident. Sending a message will automatically unblock them.
   </string>
   <!--Some times string name is getting from the body of server response.
-  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post. 
+  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
   In case of the EXT-3115 issue 'generic' is passed into the gIMMgr::showSessionStartError as a string name.
   Also there are some other places where "generic" is used.
   So, let add string with name="generic" with the same value as "generic_request_error" -->
@@ -3300,7 +3300,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
     You are not a session moderator.
   </string>
   <!--Some times string name is getting from the body of server response.
-  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post. 
+  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
   In case of the EXT-3562 issue 'muted' is passed into the gIMMgr::showSessionStartError as a string name.
   So, let add string with name="muted" with the same value as "muted_error" -->
   <string name="muted">
@@ -3313,12 +3313,12 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
     Unable to add users to chat session with [RECIPIENT].
   </string>
   <!--Some times string name is getting from the body of server response.
-  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post. 
+  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
   In case of the EXT-3562 issue 'message' is passed into the gIMMgr::showSessionStartError as a string name.
   So, let add string with name="message" with the same value as "message_session_event" -->
   <string name="message">
     Unable to send your message to the chat session with [RECIPIENT].
-  </string>  
+  </string>
   <string name="message_session_event">
     Unable to send your message to the chat session with [RECIPIENT].
   </string>
@@ -3326,7 +3326,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
     Error while moderating.
   </string>
   <!--Some times string name is getting from the body of server response.
-  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post. 
+  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
   In case of the EXT-3459 issue 'removed' is passed into the gIMMgr::showSessionStartError as a string name.
   So, let add string with name="removed" with the same value as "removed_from_group" -->
   <string name="removed">
@@ -3347,9 +3347,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 	<string name="session_initialization_timed_out_error">
 		The session initialization is timed out
 	</string>
-  
+
   <string name="Home position set.">Home position set.</string>
-  
+
   <string name="voice_morphing_url">http://secondlife.com/landing/voicemorphing</string>
 
   <!-- Financial operations strings -->
@@ -3367,20 +3367,20 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <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>
   <string name="this_costs">This costs L$ [AMOUNT]</string>
   <string name="buying_selected_land">Buying selected land for L$ [AMOUNT]</string>
   <string name="this_object_costs">This object costs L$ [AMOUNT]</string>
-  
+
   <string name="group_role_everyone">Everyone</string>
   <string name="group_role_officers">Officers</string>
   <string name="group_role_owners">Owners</string>
   <string name="group_member_status_online">Online</string>
 
   <string name="uploading_abuse_report">Uploading...
-  
+
 Abuse Report</string>
 
   <!-- names for new inventory items-->
@@ -3474,23 +3474,23 @@ Abuse Report</string>
 
   <!-- birth date format shared by avatar inspector and profile panels -->
   <string name="AvatarBirthDateFormat">[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt]</string>
-  
+
   <string name="DefaultMimeType">none/none</string>
   <string name="texture_load_dimensions_error">Can't load images larger than [WIDTH]*[HEIGHT]</string>
 
   <!-- language specific white-space characters, delimiters, spacers, item separation symbols -->
   <string name="sentences_separator" value=" "></string>
   <string name="words_separator" value=", "/>
-  
+
   <string name="server_is_down">
 	Despite our best efforts, something unexpected has gone wrong.
 
-	Please check status.secondlifegrid.net to see if there is a known problem with the service.  
+	Please check status.secondlifegrid.net to see if there is a known problem with the service.
         If you continue to experience problems, please check your network and firewall setup.
   </string>
 
-  <!-- overriding datetime formating. 
-	didn't translate if this is not needed for current localization 
+  <!-- overriding datetime formating.
+	didn't translate if this is not needed for current localization
   -->
   <string name="dateTimeWeekdaysNames">Sunday:Monday:Tuesday:Wednesday:Thursday:Friday:Saturday</string>
   <string name="dateTimeWeekdaysShortNames">Sun:Mon:Tue:Wed:Thu:Fri:Sat</string>
@@ -3523,7 +3523,7 @@ Abuse Report</string>
   <string name="DeleteItem">Delete selected item?</string>
 
   <string name="EmptyOutfitText">There are no items in this outfit</string>
- 
+
  <!-- External editor status codes -->
  <string name="ExternalEditorNotSet">Select an editor using the ExternalEditor setting.</string>
  <string name="ExternalEditorNotFound">Cannot find the external editor you specified.
-- 
cgit v1.2.3


From 702410cef75e0cc10258964b86b093f2205ef462 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Fri, 9 Dec 2011 17:59:29 +0200
Subject: EXP-1671 FIXED Enable/disable the translation checkbox in the nearby
 chat floater whenever translation preferences change.

The checkbox is also updated when the nearby chat floater is opened.
---
 indra/newview/llfloatertranslationsettings.cpp |  2 ++
 indra/newview/llnearbychatbar.cpp              | 12 ++++++++++++
 indra/newview/llnearbychatbar.h                |  2 ++
 indra/newview/lltranslate.cpp                  | 18 ++++++++++++++++++
 indra/newview/lltranslate.h                    | 16 ++++++++++++++++
 5 files changed, 50 insertions(+)

diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp
index 959edff713..428a02e9f0 100644
--- a/indra/newview/llfloatertranslationsettings.cpp
+++ b/indra/newview/llfloatertranslationsettings.cpp
@@ -29,6 +29,7 @@
 #include "llfloatertranslationsettings.h"
 
 // Viewer includes
+#include "llnearbychatbar.h"
 #include "lltranslate.h"
 #include "llviewercontrol.h" // for gSavedSettings
 
@@ -292,5 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK()
 	gSavedSettings.setString("TranslationService", getSelectedService());
 	gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey());
 	gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey());
+	LLNearbyChatBar::getInstance()->enableTranslationCheckbox(LLTranslate::isTranslationConfigured());
 	closeFloater(false);
 }
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 114472ba56..4f8559718f 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -48,6 +48,7 @@
 #include "llrootview.h"
 #include "llviewerchat.h"
 #include "llnearbychat.h"
+#include "lltranslate.h"
 
 #include "llresizehandle.h"
 
@@ -112,6 +113,12 @@ BOOL LLNearbyChatBar::postBuild()
 	return TRUE;
 }
 
+// virtual
+void LLNearbyChatBar::onOpen(const LLSD& key)
+{
+	enableTranslationCheckbox(LLTranslate::isTranslationConfigured());
+}
+
 bool LLNearbyChatBar::applyRectControl()
 {
 	bool rect_controlled = LLFloater::applyRectControl();
@@ -156,6 +163,11 @@ void LLNearbyChatBar::showHistory()
 	}
 }
 
+void LLNearbyChatBar::enableTranslationCheckbox(BOOL enable)
+{
+	getChild<LLUICtrl>("translate_chat_checkbox")->setEnabled(enable);
+}
+
 void LLNearbyChatBar::draw()
 {
 	displaySpeakingIndicator();
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index e9734899b3..866e07f123 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -43,6 +43,7 @@ public:
 	~LLNearbyChatBar() {}
 
 	virtual BOOL postBuild();
+	/*virtual*/ void onOpen(const LLSD& key);
 
 	static LLNearbyChatBar* getInstance();
 
@@ -60,6 +61,7 @@ public:
 	static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate);
 
 	void showHistory();
+	void enableTranslationCheckbox(BOOL enable);
 	/*virtual*/void setMinimized(BOOL b);
 
 protected:
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 7eb54271f4..c1cc9c7bc4 100755
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -95,6 +95,12 @@ bool LLGoogleTranslationHandler::parseResponse(
 	return parseTranslation(root, translation, detected_lang);
 }
 
+// virtual
+bool LLGoogleTranslationHandler::isConfigured() const
+{
+	return !getAPIKey().empty();
+}
+
 // static
 void LLGoogleTranslationHandler::parseErrorResponse(
 	const Json::Value& root,
@@ -218,6 +224,12 @@ bool LLBingTranslationHandler::parseResponse(
 	return true;
 }
 
+// virtual
+bool LLBingTranslationHandler::isConfigured() const
+{
+	return !getAPIKey().empty();
+}
+
 // static
 std::string LLBingTranslationHandler::getAPIKey()
 {
@@ -331,6 +343,12 @@ std::string LLTranslate::getTranslateLanguage()
 	return language;
 }
 
+// static
+bool LLTranslate::isTranslationConfigured()
+{
+	return getPreferredHandler().isConfigured();
+}
+
 // static
 const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
 {
diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h
index c2330daa81..424bc14587 100755
--- a/indra/newview/lltranslate.h
+++ b/indra/newview/lltranslate.h
@@ -89,6 +89,11 @@ public:
 		std::string& detected_lang,
 		std::string& err_msg) const = 0;
 
+	/**
+	 * @return if the handler is configured to function properly
+	 */
+	virtual bool isConfigured() const = 0;
+
 	virtual ~LLTranslationAPIHandler() {}
 
 protected:
@@ -115,6 +120,7 @@ public:
 		std::string& translation,
 		std::string& detected_lang,
 		std::string& err_msg) const;
+	/*virtual*/ bool isConfigured() const;
 
 private:
 	static void parseErrorResponse(
@@ -148,6 +154,7 @@ public:
 		std::string& translation,
 		std::string& detected_lang,
 		std::string& err_msg) const;
+	/*virtual*/ bool isConfigured() const;
 private:
 	static std::string getAPIKey();
 };
@@ -275,8 +282,17 @@ public :
 	 * @param key       Key to verify.
 	 */
 	static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key);
+
+	/**
+	 * @return translation target language
+	 */
 	static std::string getTranslateLanguage();
 
+	/**
+	 * @return true if translation is configured properly.
+	 */
+	static bool isTranslationConfigured();
+
 private:
 	static const LLTranslationAPIHandler& getPreferredHandler();
 	static const LLTranslationAPIHandler& getHandler(EService service);
-- 
cgit v1.2.3


From 723ce604560f71622d0381e47230b87f07262d99 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Fri, 9 Dec 2011 12:23:04 -0600
Subject: Backed out changeset fafd857891b1

---
 indra/llcommon/llthread.h  | 11 ++--------
 indra/llmessage/llcurl.cpp | 54 +++++++++++++++++++++++++---------------------
 2 files changed, 31 insertions(+), 34 deletions(-)

diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index b0a1c9e12b..40291a2569 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -187,18 +187,11 @@ public:
 	LLMutexLock(LLMutex* mutex)
 	{
 		mMutex = mutex;
-
-		if(mMutex)
-		{
-			mMutex->lock();
-		}
+		mMutex->lock();
 	}
 	~LLMutexLock()
 	{
-		if(mMutex)
-		{
-			mMutex->unlock();
-		}
+		mMutex->unlock();
 	}
 private:
 	LLMutex* mMutex;
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 228f039132..7ca25d07fc 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -585,30 +585,37 @@ void LLCurl::Multi::unlock()
 
 void LLCurl::Multi::markDead()
 {
-	LLMutexLock lock(mDeletionMutexp) ;
-	
+	if(mDeletionMutexp)
+	{
+		mDeletionMutexp->lock() ;
+	}
+
 	mDead = TRUE ;
+
+	if(mDeletionMutexp)
+	{
+		mDeletionMutexp->unlock() ;
+	}
 }
 
 void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
 {
-	LLMutexLock lock(mMutexp) ;
-
+	lock() ;
 	mState = state ;
 	if(mState == STATE_READY)
 	{
 		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ;
 	}
+	unlock() ;
 }
 
 LLCurl::Multi::ePerformState LLCurl::Multi::getState()
 {
 	ePerformState state ;
 
-	{
-		LLMutexLock lock(mMutexp) ;
-		state = mState ;
-	}
+	lock() ;
+	state = mState ;
+	unlock() ;
 
 	return state ;
 }
@@ -628,15 +635,13 @@ bool LLCurl::Multi::waitToComplete()
 
 	bool completed ;
 
+	lock() ;
+	completed = (STATE_COMPLETED == mState) ;
+	if(!completed)
 	{
-		LLMutexLock lock(mMutexp) ;
-
-		completed = (STATE_COMPLETED == mState) ;
-		if(!completed)
-		{
-			LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;
-		}
+		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;
 	}
+	unlock() ;
 
 	return completed;
 }
@@ -650,8 +655,10 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
 //return true if dead
 bool LLCurl::Multi::doPerform()
 {
-	LLMutexLock lock(mDeletionMutexp) ;
-	
+	if(mDeletionMutexp)
+	{
+		mDeletionMutexp->lock() ;
+	}
 	bool dead = mDead ;
 
 	if(mDead)
@@ -668,8 +675,6 @@ bool LLCurl::Multi::doPerform()
 				call_count < MULTI_PERFORM_CALL_REPEAT;
 				call_count++)
 		{
-			LLMutexLock lock(mMutexp) ;
-
 			CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
 			if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
 			{
@@ -683,6 +688,11 @@ bool LLCurl::Multi::doPerform()
 		setState(STATE_COMPLETED) ;
 	}
 
+	if(mDeletionMutexp)
+	{
+		mDeletionMutexp->unlock() ;
+	}
+
 	return dead ;
 }
 
@@ -754,8 +764,6 @@ LLCurl::Easy* LLCurl::Multi::allocEasy()
 
 bool LLCurl::Multi::addEasy(Easy* easy)
 {
-	LLMutexLock lock(mMutexp) ;
-
 	CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle());
 	check_curl_multi_code(mcode);
 	//if (mcode != CURLM_OK)
@@ -768,8 +776,6 @@ bool LLCurl::Multi::addEasy(Easy* easy)
 
 void LLCurl::Multi::easyFree(Easy* easy)
 {
-	LLMutexLock lock(mMutexp) ;
-
 	mEasyActiveList.erase(easy);
 	mEasyActiveMap.erase(easy->getCurlHandle());
 	if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE)
@@ -785,8 +791,6 @@ void LLCurl::Multi::easyFree(Easy* easy)
 
 void LLCurl::Multi::removeEasy(Easy* easy)
 {
-	LLMutexLock lock(mMutexp) ;
-
 	check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
 	easyFree(easy);
 }
-- 
cgit v1.2.3


From a7b04c9dd44274b3548402de2f4a9b8bc20e3e50 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 9 Dec 2011 10:31:16 -0800
Subject: * Removed old inventory window outbox. * Added centered progress
 indicator for outbox.

---
 indra/newview/llfloateroutbox.cpp                  |  38 +--
 indra/newview/llfloateroutbox.h                    |   2 +-
 indra/newview/llinventorybridge.cpp                |   2 +-
 indra/newview/llinventorypanel.cpp                 |   9 +-
 indra/newview/llpanelmaininventory.cpp             |   2 +-
 indra/newview/llpanelmarketplaceinbox.cpp          |   2 +-
 indra/newview/llpanelmarketplaceoutbox.cpp         |   4 +-
 indra/newview/llsidepanelinventory.cpp             | 272 +--------------------
 indra/newview/llsidepanelinventory.h               |  14 +-
 .../default/xui/en/floater_merchant_outbox.xml     |  60 +++--
 .../skins/default/xui/en/sidepanel_inventory.xml   | 135 +---------
 11 files changed, 80 insertions(+), 460 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 79cd90ba1c..6a3eaba016 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -32,7 +32,6 @@
 #include "llfolderview.h"
 #include "llinventoryobserver.h"
 #include "llinventorypanel.h"
-#include "llloadingindicator.h"
 #include "llmarketplacefunctions.h"
 #include "llnotificationsutil.h"
 #include "lltextbox.h"
@@ -96,15 +95,24 @@ LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
 
 LLFloaterOutbox::~LLFloaterOutbox()
 {
-//	delete mCategoriesObserver;
-//	delete mCategoryAddedObserver;
+	if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
+	{
+		gInventory.removeObserver(mCategoriesObserver);
+	}
+	delete mCategoriesObserver;
+	
+	if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
+	{
+		gInventory.removeObserver(mCategoryAddedObserver);
+	}
+	delete mCategoryAddedObserver;
 }
 
 BOOL LLFloaterOutbox::postBuild()
 {
 	mInventoryDisablePanel = getChild<LLView>("outbox_inventory_disable_panel");
 	mInventoryFolderCountText = getChild<LLTextBox>("outbox_folder_count");
-	mInventoryImportInProgress = getChild<LLLoadingIndicator>("import_progress_indicator");
+	mInventoryImportInProgress = getChild<LLView>("import_progress_indicator");
 	mInventoryPlaceholder = getChild<LLView>("outbox_inventory_placeholder_panel");
 	mInventoryText = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_text");
 	mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_title");
@@ -264,6 +272,11 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 										std::string& tooltip_msg)
 {
 	// Pass drag and drop to this floater to the outbox inventory control
+	
+	if (LLMarketplaceInventoryImporter::getInstance()->isImportInProgress())
+	{
+		return FALSE;
+	}
 
 	S32 local_x = x - mOutboxInventoryPanel->getRect().mLeft;
 	S32 local_y = y - mOutboxInventoryPanel->getRect().mBottom;
@@ -317,11 +330,11 @@ void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
 {
 	if (status == MarketplaceErrorCodes::IMPORT_DONE)
 	{
-		LLNotificationsUtil::add("OutboxImportComplete", LLSD::emptyMap(), LLSD::emptyMap());
+		LLNotificationsUtil::add("OutboxImportComplete");
 	}
 	else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
 	{
-		LLNotificationsUtil::add("OutboxImportHadErrors", LLSD::emptyMap(), LLSD::emptyMap());
+		LLNotificationsUtil::add("OutboxImportHadErrors");
 	}
 	else
 	{
@@ -329,10 +342,10 @@ void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
 		sprintf(status_string, "%d", status);
 		
 		LLSD subs;
-		subs["ERROR_CODE"] = status_string;
+		subs["[ERROR_CODE]"] = status_string;
 		
 		//llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
-		LLNotificationsUtil::add("OutboxImportFailed", LLSD::emptyMap(), LLSD::emptyMap());
+		LLNotificationsUtil::add("OutboxImportFailed", subs);
 	}
 }
 
@@ -343,19 +356,14 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress)
 		mImportButton->setEnabled(false);
 		
 		mInventoryDisablePanel->setVisible(true);
-
 		mInventoryImportInProgress->setVisible(true);
-		mInventoryImportInProgress->reset();
-		mInventoryImportInProgress->start();
 	}
 	else
 	{
-		mImportButton->setEnabled(mOutboxItemCount > 0);
-		
+		mInventoryImportInProgress->setVisible(false);
 		mInventoryDisablePanel->setVisible(false);
 
-		mInventoryImportInProgress->stop();
-		mInventoryImportInProgress->setVisible(false);
+		mImportButton->setEnabled(mOutboxItemCount > 0);
 	}
 }
 
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index 1e8567ef12..9b6568c69c 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -81,7 +81,7 @@ private:
 	
 	LLView *				mInventoryDisablePanel;
 	LLTextBox *				mInventoryFolderCountText;
-	LLLoadingIndicator *	mInventoryImportInProgress;
+	LLView *				mInventoryImportInProgress;
 	LLView *				mInventoryPlaceholder;
 	LLTextBox *				mInventoryText;
 	LLTextBox *				mInventoryTitle;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 017dabe2ad..33b9af7a78 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -71,7 +71,7 @@
 #include "llwearablelist.h"
 
 // Marketplace outbox current disabled
-#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1	// keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL
+#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1
 
 typedef std::pair<LLUUID, LLUUID> two_uuids_t;
 typedef std::list<two_uuids_t> two_uuids_list_t;
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 80b53d5702..af1d2b8528 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -1157,7 +1157,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L
 		LLViewerInventoryCategory * cat = gInventory.getCategory(obj_id);
 		
 		bool in_inbox = false;
-		bool in_outbox = false;
 		
 		LLViewerInventoryCategory * parent_cat = NULL;
 		
@@ -1173,10 +1172,9 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L
 		if (parent_cat)
 		{
 			in_inbox = (LLFolderType::FT_INBOX == parent_cat->getPreferredType());
-			in_outbox = (LLFolderType::FT_OUTBOX == parent_cat->getPreferredType());
 		}
 		
-		if (in_inbox || in_outbox)
+		if (in_inbox)
 		{
 			LLSidepanelInventory * sidepanel_inventory =	LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
 			LLInventoryPanel * inventory_panel = NULL;
@@ -1186,11 +1184,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L
 				sidepanel_inventory->openInbox();
 				inventory_panel = sidepanel_inventory->getInboxPanel();
 			}
-			else
-			{
-				sidepanel_inventory->openOutbox();
-				inventory_panel = sidepanel_inventory->getOutboxPanel();
-			}
 
 			if (inventory_panel)
 			{
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 68ef13cd68..374afb90be 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -593,7 +593,7 @@ void LLPanelMainInventory::onFocusReceived()
 		return;
 	}
 
-	sidepanel_inventory->clearSelections(false, true, true);
+	sidepanel_inventory->clearSelections(false, true);
 }
 
 void LLPanelMainInventory::setFilterTextFromFilter() 
diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp
index 7cb4bbf891..a5e964f563 100644
--- a/indra/newview/llpanelmarketplaceinbox.cpp
+++ b/indra/newview/llpanelmarketplaceinbox.cpp
@@ -109,7 +109,7 @@ void LLPanelMarketplaceInbox::onFocusReceived()
 	LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
 	if (sidepanel_inventory)
 	{
-		sidepanel_inventory->clearSelections(true, false, true);
+		sidepanel_inventory->clearSelections(true, false);
 	}
 
 	gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());
diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
index e3af7fd906..6c2363eb7f 100644
--- a/indra/newview/llpanelmarketplaceoutbox.cpp
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -84,6 +84,8 @@ BOOL LLPanelMarketplaceOutbox::postBuild()
 	return TRUE;
 }
 
+// DO WE NEED THIS FILE AT ALL?
+
 void LLPanelMarketplaceOutbox::handleLoginComplete()
 {
 	mImportButton = getChild<LLButton>("outbox_import_btn");
@@ -100,7 +102,7 @@ void LLPanelMarketplaceOutbox::onFocusReceived()
 	LLSidepanelInventory * sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
 	if (sidepanel_inventory)
 	{
-		sidepanel_inventory->clearSelections(true, true, false);
+		sidepanel_inventory->clearSelections(true, true);
 	}
 }
 
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 9c551be2d5..eade91798b 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -47,7 +47,6 @@
 #include "lloutfitobserver.h"
 #include "llpanelmaininventory.h"
 #include "llpanelmarketplaceinbox.h"
-#include "llpanelmarketplaceoutbox.h"
 #include "llselectmgr.h"
 #include "llsidepaneliteminfo.h"
 #include "llsidepaneltaskinfo.h"
@@ -68,26 +67,17 @@ static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_
 // No longer want the inbox panel to auto-expand since it creates issues with the "new" tag time stamp
 #define AUTO_EXPAND_INBOX	0
 
-// Temporarily disabling the outbox until we straighten out the API
-#define ENABLE_MERCHANT_OUTBOX_PANEL		1	// keep in sync with ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
-
 static const char * const INBOX_BUTTON_NAME = "inbox_btn";
-static const char * const OUTBOX_BUTTON_NAME = "outbox_btn";
-
 static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel";
-static const char * const OUTBOX_LAYOUT_PANEL_NAME = "outbox_layout_panel";
-
 static const char * const INBOX_OUTBOX_LAYOUT_PANEL_NAME = "inbox_outbox_layout_panel";
 static const char * const MAIN_INVENTORY_LAYOUT_PANEL_NAME = "main_inventory_layout_panel";
 
 static const char * const INBOX_INVENTORY_PANEL = "inventory_inbox";
-static const char * const OUTBOX_INVENTORY_PANEL = "inventory_outbox";
 
 static const char * const INBOX_OUTBOX_LAYOUT_STACK_NAME = "inbox_outbox_layout_stack";
 static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack";
 
 static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox";
-static const char * const MARKETPLACE_OUTBOX_PANEL = "marketplace_outbox";
 
 //
 // Helpers
@@ -116,10 +106,6 @@ public:
 					mSidepanelInventory->enableInbox(true);
 					mSidepanelInventory->observeInboxModifications(added_category->getUUID());
 					break;
-				case LLFolderType::FT_OUTBOX:
-					mSidepanelInventory->enableOutbox(true);
-					mSidepanelInventory->observeOutboxModifications(added_category->getUUID());
-					break;
 				default:
 					break;
 			}
@@ -138,10 +124,8 @@ LLSidepanelInventory::LLSidepanelInventory()
 	: LLPanel()
 	, mItemPanel(NULL)
 	, mInventoryPanelInbox(NULL)
-	, mInventoryPanelOutbox(NULL)
 	, mPanelMainInventory(NULL)
 	, mInboxEnabled(false)
-	, mOutboxEnabled(false)
 	, mCategoriesObserver(NULL)
 	, mInboxOutboxAddedObserver(NULL)
 {
@@ -172,15 +156,6 @@ void handleInventoryDisplayInboxChanged()
 	}
 }
 
-void handleInventoryDisplayOutboxChanged()
-{
-	LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
-	if (sidepanel_inventory)
-	{
-		sidepanel_inventory->enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox"));
-	}
-}
-
 BOOL LLSidepanelInventory::postBuild()
 {
 	// UI elements from inventory panel
@@ -255,30 +230,23 @@ BOOL LLSidepanelInventory::postBuild()
 		
 		LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME);
 
-		// Collapse both inbox and outbox panels
+		// Collapse inbox panel
 		inout_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true);
-		inout_stack->collapsePanel(getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME), true);
 		
 		// Set up button states and callbacks
 		LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME);
-		LLButton * outbox_button = getChild<LLButton>(OUTBOX_BUTTON_NAME);
 
 		inbox_button->setToggleState(false);
-		outbox_button->setToggleState(false);
-
 		inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this));
-		outbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleOutboxBtn, this));
 
-		// Set the inbox and outbox visible based on debug settings (final setting comes from http request below)
+		// Set the inbox visible based on debug settings (final setting comes from http request below)
 		enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
-		enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox"));
 
-		// Trigger callback for after login so we can setup to track inbox and outbox changes after initial inventory load
+		// Trigger callback for after login so we can setup to track inbox changes after initial inventory load
 		LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::updateInboxOutbox, this));
 	}
 
 	gSavedSettings.getControl("InventoryDisplayInbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayInboxChanged));
-	gSavedSettings.getControl("InventoryDisplayOutbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayOutboxChanged));
 
 	// Update the verbs buttons state.
 	updateVerbs();
@@ -289,40 +257,27 @@ BOOL LLSidepanelInventory::postBuild()
 void LLSidepanelInventory::updateInboxOutbox()
 {
 	//
-	// Track inbox and outbox folder changes
+	// Track inbox folder changes
 	//
 
 	const bool do_not_create_folder = false;
 	const bool do_not_find_in_library = false;
 
 	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library);
-	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library);
 	
 	// Set up observer to listen for creation of inbox and outbox if at least one of them doesn't exist
-	if (inbox_id.isNull() || outbox_id.isNull())
+	if (inbox_id.isNull())
 	{
 		observeInboxOutboxCreation();
 	}
-
 	// Set up observer for inbox changes, if we have an inbox already
-	if (!inbox_id.isNull())
+	else 
 	{
 		// Enable the display of the inbox if it exists
 		enableInbox(true);
 
 		observeInboxModifications(inbox_id);
 	}
-	
-#if ENABLE_MERCHANT_OUTBOX_PANEL
-	// Set up observer for outbox changes, if we have an outbox already
-	if (!outbox_id.isNull())
-	{
-		// Enable the display of the outbox if it exists
-		enableOutbox(true);
-
-		observeOutboxModifications(outbox_id);
-	}
-#endif
 }
 
 void LLSidepanelInventory::observeInboxOutboxCreation()
@@ -342,7 +297,7 @@ void LLSidepanelInventory::observeInboxOutboxCreation()
 void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID)
 {
 	//
-	// Track inbox and outbox folder changes
+	// Track inbox folder changes
 	//
 	
 	if (inboxID.isNull())
@@ -373,35 +328,6 @@ void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID)
 	mInventoryPanelInbox = inbox->setupInventoryPanel();
 }
 
-
-void LLSidepanelInventory::observeOutboxModifications(const LLUUID& outboxID)
-{
-	//
-	// Track outbox folder changes
-	//
-	
-	if (outboxID.isNull())
-	{
-		llwarns << "Attempting to track modifications to non-existant outbox" << llendl;
-		return;
-	}
-	
-	if (mCategoriesObserver == NULL)
-	{
-		mCategoriesObserver = new LLInventoryCategoriesObserver();
-		gInventory.addObserver(mCategoriesObserver);
-	}
-	
-	mCategoriesObserver->addCategory(outboxID, boost::bind(&LLSidepanelInventory::onOutboxChanged, this, outboxID));
-	
-	//
-	// Set up the outbox inventory view
-	//
-	
-	LLPanelMarketplaceOutbox * outbox = getChild<LLPanelMarketplaceOutbox>(MARKETPLACE_OUTBOX_PANEL);
-	mInventoryPanelOutbox = outbox->setupInventoryPanel();
-}
-
 void LLSidepanelInventory::enableInbox(bool enabled)
 {
 	mInboxEnabled = enabled;
@@ -414,39 +340,6 @@ void LLSidepanelInventory::enableInbox(bool enabled)
 		LLLayoutPanel * inout_layout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME);
 
 		inout_layout_panel->setVisible(TRUE);
-		
-		if (mOutboxEnabled)
-		{
-			S32 inbox_min_dim = inbox_layout_panel->getMinDim();
-			S32 outbox_min_dim = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME)->getMinDim();
-			
-			inout_layout_panel->setMinDim(inbox_min_dim + outbox_min_dim);
-		}
-	}
-}
-
-void LLSidepanelInventory::enableOutbox(bool enabled)
-{
-	mOutboxEnabled = enabled;
-	
-	LLLayoutPanel * outbox_layout_panel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME);
-	outbox_layout_panel->setVisible(enabled);
-
-	if (mOutboxEnabled)
-	{
-		LLLayoutPanel * inout_layout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME);
-		
-		inout_layout_panel->setVisible(TRUE);
-		
-		if (mInboxEnabled)
-		{
-			S32 inbox_min_dim = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME)->getMinDim();
-			S32 outbox_min_dim = outbox_layout_panel->getMinDim();
-			
-			inout_layout_panel->setMinDim(inbox_min_dim + outbox_min_dim);
-		}
-		
-		updateOutboxUserStatus();
 	}
 }
 
@@ -459,30 +352,12 @@ void LLSidepanelInventory::openInbox()
 	}
 }
 
-void LLSidepanelInventory::openOutbox()
-{
-	if (mOutboxEnabled)
-	{
-		getChild<LLButton>(OUTBOX_BUTTON_NAME)->setToggleState(true);
-		onToggleOutboxBtn();
-	}
-}
-
 void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id)
 {
 	// Trigger a load of the entire inbox so we always know the contents and their creation dates for sorting
 	LLInventoryModelBackgroundFetch::instance().start(inbox_id);
 
 #if AUTO_EXPAND_INBOX
-	// If the outbox is expanded, don't auto-expand the inbox
-	if (mOutboxEnabled)
-	{
-		if (getChild<LLButton>(OUTBOX_BUTTON_NAME)->getToggleState())
-		{
-			return;
-		}
-	}
-
 	// Expand the inbox since we have fresh items and the outbox is not expanded
 	if (mInboxEnabled)
 	{
@@ -492,21 +367,9 @@ void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id)
 #endif
 }
 
-void LLSidepanelInventory::onOutboxChanged(const LLUUID& outbox_id)
-{
-	// Expand the outbox since we have new items in it
-	if (mOutboxEnabled)
-	{
-		getChild<LLButton>(OUTBOX_BUTTON_NAME)->setToggleState(true);
-		onToggleOutboxBtn();
-	}	
-}
-
-bool LLSidepanelInventory::manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel,
-							 LLButton * otherButton, LLLayoutPanel * otherPanel)
+bool LLSidepanelInventory::manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel)
 {
 	bool expand = pressedButton->getToggleState();
-	bool otherExpanded = otherButton->getToggleState();
 
 	LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
 	LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME);
@@ -516,27 +379,12 @@ bool LLSidepanelInventory::manageInboxOutboxPanels(LLButton * pressedButton, LLL
 	inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, expand);
 	inv_stack->collapsePanel(inout_panel, !expand);
 
-	// Collapse other marketplace panel if it is expanded
-	if (expand && otherExpanded)
-	{
-		// Reshape pressedPanel to the otherPanel's height so we preserve the marketplace panel size
-		pressedPanel->reshape(pressedPanel->getRect().getWidth(), otherPanel->getRect().getHeight());
-
-		inout_stack->collapsePanel(otherPanel, true);
-		otherButton->setToggleState(false);
-	}
-	else
 	{
 		// NOTE: This is an attempt to reshape the inventory panel to the proper size but it doesn't seem to propagate
 		// properly to the child panels.
 
 		S32 new_height = inout_panel->getRect().getHeight();
 
-		if (otherPanel->getVisible())
-		{
-			new_height -= otherPanel->getMinDim();
-		}
-
 		pressedPanel->reshape(pressedPanel->getRect().getWidth(), new_height);
 	}
 
@@ -550,10 +398,8 @@ void LLSidepanelInventory::onToggleInboxBtn()
 {
 	LLButton* inboxButton = getChild<LLButton>(INBOX_BUTTON_NAME);
 	LLLayoutPanel* inboxPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
-	LLButton* outboxButton = getChild<LLButton>(OUTBOX_BUTTON_NAME);
-	LLLayoutPanel* outboxPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME);
 
-	const bool inbox_expanded = manageInboxOutboxPanels(inboxButton, inboxPanel, outboxButton, outboxPanel);
+	const bool inbox_expanded = manageInboxOutboxPanels(inboxButton, inboxPanel);
 
 	if (inbox_expanded && inboxPanel->isInVisibleChain())
 	{
@@ -561,16 +407,6 @@ void LLSidepanelInventory::onToggleInboxBtn()
 	}
 }
 
-void LLSidepanelInventory::onToggleOutboxBtn()
-{
-	LLButton* inboxButton = getChild<LLButton>(INBOX_BUTTON_NAME);
-	LLLayoutPanel* inboxPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
-	LLButton* outboxButton = getChild<LLButton>(OUTBOX_BUTTON_NAME);
-	LLLayoutPanel* outboxPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME);
-
-	manageInboxOutboxPanels(outboxButton, outboxPanel, inboxButton, inboxPanel);
-}
-
 void LLSidepanelInventory::onOpen(const LLSD& key)
 {
 	LLFirstUse::newInventory(false);
@@ -740,77 +576,6 @@ void LLSidepanelInventory::showInventoryPanel()
 	updateVerbs();
 }
 
-void LLSidepanelInventory::updateOutboxUserStatus()
-{
-	const bool isMerchant = (gSavedSettings.getString("InventoryMarketplaceUserStatus") == "merchant");
-	const bool hasOutbox = !gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false).isNull();
-	
-	LLView * outbox_placeholder = getChild<LLView>("outbox_inventory_placeholder_panel");
-	LLView * outbox_placeholder_parent = outbox_placeholder->getParent();
-	
-	LLTextBox * outbox_title_box = outbox_placeholder->getChild<LLTextBox>("outbox_inventory_placeholder_title");
-	LLTextBox * outbox_text_box = outbox_placeholder->getChild<LLTextBox>("outbox_inventory_placeholder_text");
-
-	std::string outbox_text;
-	std::string outbox_title;
-	std::string outbox_tooltip;
-
-	if (isMerchant)
-	{
-		if (hasOutbox)
-		{
-			outbox_text = LLTrans::getString("InventoryOutboxNoItems");
-			outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle");
-			outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip");
-		}
-		else
-		{
-			outbox_text = LLTrans::getString("InventoryOutboxCreationError");
-			outbox_title = LLTrans::getString("InventoryOutboxCreationErrorTitle");
-			outbox_tooltip = LLTrans::getString("InventoryOutboxCreationErrorTooltip");
-		}
-	}
-	else
-	{
-		//
-		// The string to become a merchant contains 3 URL's which need the domain name patched in.
-		//
-		
-		std::string domain = "secondlife.com";
-		
-		if (!LLGridManager::getInstance()->isInProductionGrid())
-		{
-			std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
-			domain = llformat("%s.lindenlab.com", utf8str_tolower(gridLabel).c_str());
-		}
-		
-		LLStringUtil::format_map_t domain_arg;
-		domain_arg["[DOMAIN_NAME]"] = domain;
-
-		std::string marketplace_url = LLTrans::getString("MarketplaceURL", domain_arg);
-		std::string marketplace_url_create = LLTrans::getString("MarketplaceURL_CreateStore", domain_arg);
-		std::string marketplace_url_info = LLTrans::getString("MarketplaceURL_LearnMore", domain_arg);
-		
-		LLStringUtil::format_map_t args1, args2, args3;
-		args1["[MARKETPLACE_URL]"] = marketplace_url;
-		args2["[LEARN_MORE_URL]"] = marketplace_url_info;
-		args3["[CREATE_STORE_URL]"] = marketplace_url_create;
-		
-		// NOTE: This is dumb, ridiculous and very finicky.  The order of these is very important
-		//       to have these three string substitutions work properly.
-		outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", args1);
-		LLStringUtil::format(outbox_text, args2);
-		LLStringUtil::format(outbox_text, args3);
-
-		outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle");
-		outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip");
-	}
-	
-	outbox_text_box->setValue(outbox_text);
-	outbox_title_box->setValue(outbox_title);
-	outbox_placeholder_parent->setToolTip(outbox_tooltip);
-}
-
 void LLSidepanelInventory::updateVerbs()
 {
 	mInfoBtn->setEnabled(FALSE);
@@ -929,13 +694,6 @@ U32 LLSidepanelInventory::getSelectedCount()
 		count += selection_list.size();
 	}
 
-	if ((count == 0) && mOutboxEnabled && (mInventoryPanelOutbox != NULL))
-	{
-		selection_list = mInventoryPanelOutbox->getRootFolder()->getSelectionList();
-		
-		count += selection_list.size();
-	}
-
 	return count;
 }
 
@@ -957,7 +715,7 @@ BOOL LLSidepanelInventory::isMainInventoryPanelActive() const
 	return mInventoryPanel->getVisible();
 }
 
-void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox, bool clearOutbox)
+void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox)
 {
 	if (clearMain)
 	{
@@ -974,11 +732,6 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox, bool
 		mInventoryPanelInbox->clearSelection();
 	}
 	
-	if (clearOutbox && mOutboxEnabled && (mInventoryPanelOutbox != NULL))
-	{
-		mInventoryPanelOutbox->clearSelection();
-	}
-	
 	updateVerbs();
 }
 
@@ -991,10 +744,5 @@ std::set<LLUUID> LLSidepanelInventory::getInboxOrOutboxSelectionList()
 		inventory_selected_uuids = mInventoryPanelInbox->getRootFolder()->getSelectionList();
 	}
 	
-	if (inventory_selected_uuids.empty() && mOutboxEnabled && (mInventoryPanelOutbox != NULL))
-	{
-		inventory_selected_uuids = mInventoryPanelOutbox->getRootFolder()->getSelectionList();
-	}
-	
 	return inventory_selected_uuids;
 }
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h
index 2c6f807013..915db727d6 100644
--- a/indra/newview/llsidepanelinventory.h
+++ b/indra/newview/llsidepanelinventory.h
@@ -52,19 +52,17 @@ private:
 public:
 	void observeInboxOutboxCreation();
 	void observeInboxModifications(const LLUUID& inboxID);
-	void observeOutboxModifications(const LLUUID& outboxID);
 
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void onOpen(const LLSD& key);
 
 	LLInventoryPanel* getActivePanel(); // Returns an active inventory panel, if any.
 	LLInventoryPanel* getInboxPanel() const { return mInventoryPanelInbox; }
-	LLInventoryPanel* getOutboxPanel() const { return mInventoryPanelOutbox; }
 
 	LLPanelMainInventory* getMainInventoryPanel() const { return mPanelMainInventory; }
 	BOOL isMainInventoryPanelActive() const;
 
-	void clearSelections(bool clearMain, bool clearInbox, bool clearOutbox);
+	void clearSelections(bool clearMain, bool clearInbox);
 	std::set<LLUUID> getInboxOrOutboxSelectionList();
 
 	void showItemInfoPanel();
@@ -75,18 +73,13 @@ public:
 	bool canShare();
 
 	void onToggleInboxBtn();
-	void onToggleOutboxBtn();
 
 	void enableInbox(bool enabled);
-	void enableOutbox(bool enabled);
 	
 	void openInbox();
-	void openOutbox();
 	
 	bool isInboxEnabled() const { return mInboxEnabled; }
-	bool isOutboxEnabled() const { return mOutboxEnabled; }
 
-	void updateOutboxUserStatus();
 	void updateVerbs();
 
 protected:
@@ -100,9 +93,8 @@ protected:
 	bool canWearSelected(); // check whether selected items can be worn
 
 	void onInboxChanged(const LLUUID& inbox_id);
-	void onOutboxChanged(const LLUUID& outbox_id);
 
-	bool manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel, LLButton * otherButton, LLLayoutPanel * otherPanel);
+	bool manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel);
 
 	//
 	// UI Elements
@@ -110,7 +102,6 @@ protected:
 private:
 	LLPanel*					mInventoryPanel; // Main inventory view
 	LLInventoryPanel*			mInventoryPanelInbox;
-	LLInventoryPanel*			mInventoryPanelOutbox;
 	LLSidepanelItemInfo*		mItemPanel; // Individual item view
 	LLSidepanelTaskInfo*		mTaskPanel; // Individual in-world object view
 	LLPanelMainInventory*		mPanelMainInventory;
@@ -135,7 +126,6 @@ private:
 	LLButton*					mShopBtn;
 
 	bool						mInboxEnabled;
-	bool						mOutboxEnabled;
 
 	LLInventoryCategoriesObserver* 			mCategoriesObserver;
 	LLInboxOutboxAddedObserver*				mInboxOutboxAddedObserver;
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index 86e27cbc71..f0b29f2248 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -6,7 +6,7 @@
  height="440"
  help_topic="floater_merchant_outbox"
  min_width="300"
- min_height="240"
+ min_height="100"
  name="floater_merchant_outbox"
  save_rect="true"
  save_visibility="true"
@@ -49,7 +49,7 @@
 			<text
 				name="outbox_inventory_placeholder_title"
 				type="string"
-				follows="all"
+				follows="top|left|right"
 				layout="topleft"
 				top="10"
 				left="0"
@@ -63,7 +63,7 @@
 			<text
 				name="outbox_inventory_placeholder_text"
 				type="string"
-				follows="all"
+				follows="top|left|right"
 				layout="topleft"
 				top="35"
 				left="0"
@@ -73,27 +73,6 @@
 				halign="left" />
 		</panel>
     </panel>
-	<panel
-		name="outbox_inventory_disable_panel"
-        follows="all"
-        left="0"
-        bottom="440"
-        width="333"
-        top="0"
-        bg_opaque_color="White_50"
-        background_visible="true"
-        background_opaque="true"
-		visible="false"
-        />
-	<loading_indicator
-		 follows="all"
-		 height="65"
-		 layout="topleft"
-		 left="140"
-		 name="import_progress_indicator"
-		 top="180"
-		 visible="false"
-		 width="45" />
 	<panel
         follows="bottom|left|right"
         left="10"
@@ -116,7 +95,7 @@
 			wrap="true"
 			halign="left"
 			valign="baseline"
-			font="SansSerifBold" />
+			font="SansSerif" />
 		<button
 			 label="Send to Marketplace"
 			 tool_tip="Push to my Marketplace Storefront"
@@ -131,5 +110,36 @@
 			 width="200"
 			 enabled="false" />
     </panel>
+	<panel
+		name="outbox_inventory_disable_panel"
+        follows="all"
+        left="0"
+        bottom="440"
+        width="333"
+        top="0"
+        bg_opaque_color="White_50"
+        background_visible="true"
+        background_opaque="true"
+		visible="false"
+        />
+	<layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false">
+		<layout_panel />
+		<layout_panel height="45" auto_resize="false">
+			<layout_stack orientation="horizontal" left="0" height="45" top="0" width="333" follows="all">
+				<layout_panel width="0" />
+				<layout_panel width="45" auto_resize="false">
+					<loading_indicator
+						 height="45"
+						 layout="topleft"
+						 left="0"
+						 top="0"
+						 width="45"
+						 />
+				</layout_panel>
+				<layout_panel width="0" />
+			</layout_stack>
+		 </layout_panel>
+		 <layout_panel />
+	</layout_stack>
  </panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index 9f3c57fa0f..0b14fd0459 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -153,139 +153,8 @@
                     </panel>
                  </panel>
              </layout_panel>
-             <layout_panel
-                 width="330"
-                 layout="topleft"
-                 auto_resize="true"
-                 user_resize="false"
-                 follows="all"
-                 name="outbox_layout_panel"
-                 visible="false"
-                 min_dim="35"
-                 max_dim="200"
-                 expanded_min_dim="90"
-                 height="200">
-                 <panel
-                      follows="all"
-                      layout="topleft"
-                      left="0"
-                      name="marketplace_outbox"
-                      class="panel_marketplace_outbox"
-                      top="0"
-                      label=""
-                      height="200"
-                      width="330">
-                     <string name="OutboxLabelWithArg">Merchant outbox ([NUM])</string>
-                     <string name="OutboxLabelNoArg">Merchant outbox</string>
-                     <button
-                        label="Merchant outbox"
-                        font="SansSerifMedium"
-                        name="outbox_btn"
-                        height="35"
-                        width="308"
-                        image_unselected="MarketplaceBtn_Off"
-                        image_selected="MarketplaceBtn_Selected"
-                        halign="left"
-                        handle_right_mouse="false"
-                        follows="top|left|right"
-                        is_toggle="true"
-                        tab_stop="false"
-                        pad_left="35"
-                        top="0"
-                        left="10" />
-                     <button
-                         image_unselected="OutboxPush_Off"
-                         image_selected="OutboxPush_Selected"
-                         image_hover_selected="OutboxPush_Selected_Over"
-                         image_hover_unselected="OutboxPush_Over"
-                         image_disabled_selected="OutboxPush_Selected_Disabled"
-                         image_disabled="OutboxPush_Disabled"
-                         image_pressed="OutboxPush_Press"
-                         image_pressed_selected="OutboxPush_Selected_Press"
-                         label=""
-                         tool_tip="Push to my Marketplace Storefront"
-                         is_toggle="false"
-                         name="outbox_import_btn"
-                         follows="top|right"
-                         tab_stop="false"
-                         halign="center"
-                         top="6"
-                         left="-50"
-                         height="23"
-                         width="32"
-                         enabled="false" />
-                     <loading_indicator
-                        follows="top|right"
-                        name="outbox_import_indicator"
-                        top="6"
-                        left="-50"
-                        height="23"
-                        width="32"
-                        images_per_sec="1.15"
-                        tab_stop="false"
-                        visible="false">
-                         <images>
-                             <image name="OutboxPush_Progress_1"/>
-                             <image name="OutboxPush_Progress_2"/>
-                             <image name="OutboxPush_Progress_3"/>
-                             <image name="OutboxPush_Progress_4"/>
-                             <image name="OutboxPush_Progress_5"/>
-                             <image name="OutboxPush_Progress_6"/>
-                         </images>
-                     </loading_indicator>
-                     <panel
-                        follows="all"
-                        left="10"
-                        bottom="200"
-                        width="308"
-                        top="35"
-                        bg_opaque_color="InventoryBackgroundColor"
-                        background_visible="true"
-                        background_opaque="true"
-                        >
-						<panel
-							name="outbox_inventory_placeholder_panel"
-							follows="all"
-							layout="topleft"
-							top="0"
-							left="0"
-							width="308"
-							height="165"
-							bg_opaque_color="InventoryBackgroundColor"
-							background_visible="true"
-							background_opaque="true"
-							>
-							<text
-								name="outbox_inventory_placeholder_title"
-								type="string"
-								follows="all"
-								layout="topleft"
-								top="10"
-								left="0"
-								width="308"
-								height="25"
-								wrap="true"
-								halign="center"
-								font="SansSerifBold">
-								Loading...
-							</text>
-							<text
-								name="outbox_inventory_placeholder_text"
-								type="string"
-								follows="all"
-								layout="topleft"
-								top="35"
-								left="0"
-								width="308"
-								height="130"
-								wrap="true"
-								halign="left" />
-						</panel>
-                    </panel>
-                 </panel>
-             </layout_panel>
-						 </layout_stack>
-						 </layout_panel>
+			 </layout_stack>
+			 </layout_panel>
          </layout_stack>
 		<panel
 		     follows="bottom|left|right"
-- 
cgit v1.2.3


From 8878a5e561f292a8afcd933eaafb2c4c65b7bf7f Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 9 Dec 2011 12:29:33 -0800
Subject: * Changed background opacity of outbox and inventory to match. *
 Removed superfluous marketplace layout stack, leftover from inbox/outbox in
 same inventory window.

---
 indra/newview/llavataractions.cpp                  |  2 +-
 indra/newview/llfloateroutbox.cpp                  | 40 +++++-----
 indra/newview/llfloateroutbox.h                    |  1 -
 indra/newview/llsidepanelinventory.cpp             | 92 +++++++---------------
 indra/newview/llsidepanelinventory.h               | 14 ++--
 .../default/xui/en/floater_merchant_outbox.xml     | 20 +----
 .../skins/default/xui/en/panel_main_inventory.xml  |  7 --
 .../default/xui/en/panel_outbox_inventory.xml      |  1 -
 .../skins/default/xui/en/sidepanel_inventory.xml   | 50 +++---------
 9 files changed, 69 insertions(+), 158 deletions(-)

diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 8ca621538f..e7e098e423 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -707,7 +707,7 @@ std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()
 		LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
 		if (sidepanel_inventory)
 		{
-			inventory_selected_uuids = sidepanel_inventory->getInboxOrOutboxSelectionList();
+			inventory_selected_uuids = sidepanel_inventory->getInboxSelectionList();
 		}
 	}
 
diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 6a3eaba016..619be87187 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -83,7 +83,6 @@ LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
 	, mOutboxId(LLUUID::null)
 	, mOutboxInventoryPanel(NULL)
 	, mOutboxItemCount(0)
-	, mInventoryDisablePanel(NULL)
 	, mInventoryFolderCountText(NULL)
 	, mInventoryImportInProgress(NULL)
 	, mInventoryPlaceholder(NULL)
@@ -110,7 +109,6 @@ LLFloaterOutbox::~LLFloaterOutbox()
 
 BOOL LLFloaterOutbox::postBuild()
 {
-	mInventoryDisablePanel = getChild<LLView>("outbox_inventory_disable_panel");
 	mInventoryFolderCountText = getChild<LLTextBox>("outbox_folder_count");
 	mInventoryImportInProgress = getChild<LLView>("import_progress_indicator");
 	mInventoryPlaceholder = getChild<LLView>("outbox_inventory_placeholder_panel");
@@ -136,21 +134,24 @@ void LLFloaterOutbox::onOpen(const LLSD& key)
 	//
 	// Look for an outbox and set up the inventory API
 	//
-
-	const bool do_not_create_folder = false;
-	const bool do_not_find_in_library = false;
-	
-	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library);
 	
-	if (outbox_id.isNull())
-	{
-		// Observe category creation to catch outbox creation
-		mCategoryAddedObserver = new LLOutboxAddedObserver(this);
-		gInventory.addObserver(mCategoryAddedObserver);
-	}
-	else
+	if (mOutboxId.isNull())
 	{
-		setupOutbox(outbox_id);
+		const bool do_not_create_folder = false;
+		const bool do_not_find_in_library = false;
+		
+		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library);
+		
+		if (outbox_id.isNull())
+		{
+			// Observe category creation to catch outbox creation
+			mCategoryAddedObserver = new LLOutboxAddedObserver(this);
+			gInventory.addObserver(mCategoryAddedObserver);
+		}
+		else
+		{
+			setupOutbox(outbox_id);
+		}
 	}
 	
 	updateView();
@@ -164,10 +165,11 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
 	mOutboxId = outboxId;
 	
 	// No longer need to observe new category creation
-	if (mCategoryAddedObserver != NULL)
+	if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
 	{
 		gInventory.removeObserver(mCategoryAddedObserver);
-	}	
+		delete mCategoryAddedObserver;
+	}
 	
 	// Create observer for outbox modifications
 	mCategoriesObserver = new LLInventoryCategoriesObserver();
@@ -286,6 +288,8 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 
 void LLFloaterOutbox::onImportButtonClicked()
 {
+	mOutboxInventoryPanel->clearSelection();
+
 	LLMarketplaceInventoryImporter::instance().triggerImport();
 }
 
@@ -355,13 +359,11 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress)
 	{
 		mImportButton->setEnabled(false);
 		
-		mInventoryDisablePanel->setVisible(true);
 		mInventoryImportInProgress->setVisible(true);
 	}
 	else
 	{
 		mInventoryImportInProgress->setVisible(false);
-		mInventoryDisablePanel->setVisible(false);
 
 		mImportButton->setEnabled(mOutboxItemCount > 0);
 	}
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index 9b6568c69c..3d2ce86144 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -79,7 +79,6 @@ private:
 	LLInventoryPanel *	mOutboxInventoryPanel;
 	U32					mOutboxItemCount;
 	
-	LLView *				mInventoryDisablePanel;
 	LLTextBox *				mInventoryFolderCountText;
 	LLView *				mInventoryImportInProgress;
 	LLView *				mInventoryPlaceholder;
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index eade91798b..5cda381d10 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -69,12 +69,10 @@ static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_
 
 static const char * const INBOX_BUTTON_NAME = "inbox_btn";
 static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel";
-static const char * const INBOX_OUTBOX_LAYOUT_PANEL_NAME = "inbox_outbox_layout_panel";
 static const char * const MAIN_INVENTORY_LAYOUT_PANEL_NAME = "main_inventory_layout_panel";
 
 static const char * const INBOX_INVENTORY_PANEL = "inventory_inbox";
 
-static const char * const INBOX_OUTBOX_LAYOUT_STACK_NAME = "inbox_outbox_layout_stack";
 static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack";
 
 static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox";
@@ -83,10 +81,10 @@ static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox";
 // Helpers
 //
 
-class LLInboxOutboxAddedObserver : public LLInventoryCategoryAddedObserver
+class LLInboxAddedObserver : public LLInventoryCategoryAddedObserver
 {
 public:
-	LLInboxOutboxAddedObserver(LLSidepanelInventory * sidepanelInventory)
+	LLInboxAddedObserver(LLSidepanelInventory * sidepanelInventory)
 		: LLInventoryCategoryAddedObserver()
 		, mSidepanelInventory(sidepanelInventory)
 	{
@@ -127,7 +125,7 @@ LLSidepanelInventory::LLSidepanelInventory()
 	, mPanelMainInventory(NULL)
 	, mInboxEnabled(false)
 	, mCategoriesObserver(NULL)
-	, mInboxOutboxAddedObserver(NULL)
+	, mInboxAddedObserver(NULL)
 {
 	//buildFromFile( "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
 }
@@ -140,11 +138,11 @@ LLSidepanelInventory::~LLSidepanelInventory()
 	}
 	delete mCategoriesObserver;
 	
-	if (mInboxOutboxAddedObserver && gInventory.containsObserver(mInboxOutboxAddedObserver))
+	if (mInboxAddedObserver && gInventory.containsObserver(mInboxAddedObserver))
 	{
-		gInventory.removeObserver(mInboxOutboxAddedObserver);
+		gInventory.removeObserver(mInboxAddedObserver);
 	}
-	delete mInboxOutboxAddedObserver;
+	delete mInboxAddedObserver;
 }
 
 void handleInventoryDisplayInboxChanged()
@@ -217,21 +215,16 @@ BOOL LLSidepanelInventory::postBuild()
 		}
 	}
 	
-	// Marketplace inbox/outbox setup
+	// Received items inbox setup
 	{
 		LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
 
 		// Disable user_resize on main inventory panel by default
 		inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false);
-		inv_stack->setPanelUserResize(INBOX_OUTBOX_LAYOUT_PANEL_NAME, false);
-
-		// Collapse marketplace panel by default
-		inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME), true);
-		
-		LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME);
+		inv_stack->setPanelUserResize(INBOX_LAYOUT_PANEL_NAME, false);
 
 		// Collapse inbox panel
-		inout_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true);
+		inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true);
 		
 		// Set up button states and callbacks
 		LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME);
@@ -243,7 +236,7 @@ BOOL LLSidepanelInventory::postBuild()
 		enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
 
 		// Trigger callback for after login so we can setup to track inbox changes after initial inventory load
-		LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::updateInboxOutbox, this));
+		LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::updateInbox, this));
 	}
 
 	gSavedSettings.getControl("InventoryDisplayInbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayInboxChanged));
@@ -254,7 +247,7 @@ BOOL LLSidepanelInventory::postBuild()
 	return TRUE;
 }
 
-void LLSidepanelInventory::updateInboxOutbox()
+void LLSidepanelInventory::updateInbox()
 {
 	//
 	// Track inbox folder changes
@@ -265,10 +258,10 @@ void LLSidepanelInventory::updateInboxOutbox()
 
 	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library);
 	
-	// Set up observer to listen for creation of inbox and outbox if at least one of them doesn't exist
+	// Set up observer to listen for creation of inbox if at least one of them doesn't exist
 	if (inbox_id.isNull())
 	{
-		observeInboxOutboxCreation();
+		observeInboxCreation();
 	}
 	// Set up observer for inbox changes, if we have an inbox already
 	else 
@@ -280,17 +273,17 @@ void LLSidepanelInventory::updateInboxOutbox()
 	}
 }
 
-void LLSidepanelInventory::observeInboxOutboxCreation()
+void LLSidepanelInventory::observeInboxCreation()
 {
 	//
-	// Set up observer to track inbox and outbox folder creation
+	// Set up observer to track inbox folder creation
 	//
 	
-	if (mInboxOutboxAddedObserver == NULL)
+	if (mInboxAddedObserver == NULL)
 	{
-		mInboxOutboxAddedObserver = new LLInboxOutboxAddedObserver(this);
+		mInboxAddedObserver = new LLInboxAddedObserver(this);
 		
-		gInventory.addObserver(mInboxOutboxAddedObserver);
+		gInventory.addObserver(mInboxAddedObserver);
 	}
 }
 
@@ -334,13 +327,6 @@ void LLSidepanelInventory::enableInbox(bool enabled)
 	
 	LLLayoutPanel * inbox_layout_panel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
 	inbox_layout_panel->setVisible(enabled);
-
-	if (mInboxEnabled)
-	{
-		LLLayoutPanel * inout_layout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME);
-
-		inout_layout_panel->setVisible(TRUE);
-	}
 }
 
 void LLSidepanelInventory::openInbox()
@@ -358,7 +344,7 @@ void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id)
 	LLInventoryModelBackgroundFetch::instance().start(inbox_id);
 
 #if AUTO_EXPAND_INBOX
-	// Expand the inbox since we have fresh items and the outbox is not expanded
+	// Expand the inbox since we have fresh items
 	if (mInboxEnabled)
 	{
 		getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true);
@@ -367,39 +353,19 @@ void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id)
 #endif
 }
 
-bool LLSidepanelInventory::manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel)
-{
-	bool expand = pressedButton->getToggleState();
-
-	LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
-	LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME);
-	LLLayoutPanel* inout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME);
-
-	// Enable user_resize on main inventory panel only when a marketplace box is expanded
-	inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, expand);
-	inv_stack->collapsePanel(inout_panel, !expand);
-
-	{
-		// NOTE: This is an attempt to reshape the inventory panel to the proper size but it doesn't seem to propagate
-		// properly to the child panels.
-
-		S32 new_height = inout_panel->getRect().getHeight();
-
-		pressedPanel->reshape(pressedPanel->getRect().getWidth(), new_height);
-	}
-
-	// Expand/collapse the indicated panel
-	inout_stack->collapsePanel(pressedPanel, !expand);
-
-	return expand;
-}
-
 void LLSidepanelInventory::onToggleInboxBtn()
 {
 	LLButton* inboxButton = getChild<LLButton>(INBOX_BUTTON_NAME);
 	LLLayoutPanel* inboxPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
-
-	const bool inbox_expanded = manageInboxOutboxPanels(inboxButton, inboxPanel);
+	LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+	
+	const bool inbox_expanded = inboxButton->getToggleState();
+	
+	// Enable user_resize on main inventory panel only when inbox is expanded
+	inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, inbox_expanded);
+	
+	// Expand/collapse the indicated panel
+	inv_stack->collapsePanel(inboxPanel, !inbox_expanded);
 
 	if (inbox_expanded && inboxPanel->isInVisibleChain())
 	{
@@ -735,7 +701,7 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox)
 	updateVerbs();
 }
 
-std::set<LLUUID> LLSidepanelInventory::getInboxOrOutboxSelectionList()
+std::set<LLUUID> LLSidepanelInventory::getInboxSelectionList()
 {
 	std::set<LLUUID> inventory_selected_uuids;
 	
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h
index 915db727d6..a33607f50d 100644
--- a/indra/newview/llsidepanelinventory.h
+++ b/indra/newview/llsidepanelinventory.h
@@ -31,7 +31,7 @@
 
 class LLButton;
 class LLFolderViewItem;
-class LLInboxOutboxAddedObserver;
+class LLInboxAddedObserver;
 class LLInventoryCategoriesObserver;
 class LLInventoryItem;
 class LLInventoryPanel;
@@ -47,10 +47,10 @@ public:
 	virtual ~LLSidepanelInventory();
 
 private:
-	void updateInboxOutbox();
+	void updateInbox();
 	
 public:
-	void observeInboxOutboxCreation();
+	void observeInboxCreation();
 	void observeInboxModifications(const LLUUID& inboxID);
 
 	/*virtual*/ BOOL postBuild();
@@ -63,7 +63,7 @@ public:
 	BOOL isMainInventoryPanelActive() const;
 
 	void clearSelections(bool clearMain, bool clearInbox);
-	std::set<LLUUID> getInboxOrOutboxSelectionList();
+	std::set<LLUUID> getInboxSelectionList();
 
 	void showItemInfoPanel();
 	void showTaskInfoPanel();
@@ -94,8 +94,6 @@ protected:
 
 	void onInboxChanged(const LLUUID& inbox_id);
 
-	bool manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel);
-
 	//
 	// UI Elements
 	//
@@ -127,8 +125,8 @@ private:
 
 	bool						mInboxEnabled;
 
-	LLInventoryCategoriesObserver* 			mCategoriesObserver;
-	LLInboxOutboxAddedObserver*				mInboxOutboxAddedObserver;
+	LLInventoryCategoriesObserver* 	mCategoriesObserver;
+	LLInboxAddedObserver*			mInboxAddedObserver;
 };
 
 #endif //LL_LLSIDEPANELINVENTORY_H
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index f0b29f2248..0368601bf4 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -6,7 +6,7 @@
  height="440"
  help_topic="floater_merchant_outbox"
  min_width="300"
- min_height="100"
+ min_height="200"
  name="floater_merchant_outbox"
  save_rect="true"
  save_visibility="true"
@@ -31,8 +31,6 @@
         width="313"
         top="0"
         bg_opaque_color="InventoryBackgroundColor"
-        background_visible="true"
-        background_opaque="true"
         >
 		<panel
 			name="outbox_inventory_placeholder_panel"
@@ -43,8 +41,6 @@
 			width="308"
 			height="400"
 			bg_opaque_color="InventoryBackgroundColor"
-			background_visible="true"
-			background_opaque="true"
 			>
 			<text
 				name="outbox_inventory_placeholder_title"
@@ -80,8 +76,6 @@
         width="313"
         top="405"
         bg_opaque_color="InventoryBackgroundColor"
-        background_visible="true"
-        background_opaque="true"
         >
 		<text
 			name="outbox_folder_count"
@@ -110,18 +104,6 @@
 			 width="200"
 			 enabled="false" />
     </panel>
-	<panel
-		name="outbox_inventory_disable_panel"
-        follows="all"
-        left="0"
-        bottom="440"
-        width="333"
-        top="0"
-        bg_opaque_color="White_50"
-        background_visible="true"
-        background_opaque="true"
-		visible="false"
-        />
 	<layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false">
 		<layout_panel />
 		<layout_panel height="45" auto_resize="false">
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index e6c5110999..3007be7d5e 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
- background_visible="true"
  default_tab_group="1"
  follows="all"
  height="423"
@@ -51,10 +50,6 @@
    top="18"
    width="303" />
   <tab_container
-     bg_alpha_color="DkGray"
-     bg_opaque_color="DkGray"
-     background_visible="true"
-     background_opaque="true"
      follows="all"
      halign="center"
      height="339"
@@ -71,7 +66,6 @@
      bg_opaque_color="DkGray2"
      bg_alpha_color="DkGray2"
      background_visible="true"
-     background_opaque="true"
      border="false"
      bevel_style="none"
      follows="all"
@@ -90,7 +84,6 @@
      bg_opaque_color="DkGray2"
      bg_alpha_color="DkGray2"
      background_visible="true"
-     background_opaque="true"
      border="false"
      bevel_style="none"
      follows="all"
diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
index 66117615e4..a3d39e55af 100644
--- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
@@ -8,7 +8,6 @@
     bg_opaque_color="DkGray2"
     bg_alpha_color="DkGray2"
     background_visible="true"
-    background_opaque="true"
     border="false"
     bevel_style="none"
     show_item_link_overlays="true"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index 0b14fd0459..a26eb23a5d 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
-	  background_visible="true"
 	  follows="all"
 	  height="570"
 	  label="Things"
@@ -30,7 +29,7 @@
               width="330">
              <layout_panel
                  name="main_inventory_layout_panel"
-								 layout="topleft"
+                 layout="topleft"
                  min_dim="150"
                  width="330"
                  follows="bottom|left|right"
@@ -48,41 +47,18 @@
                       height="300"
                       width="330" />
              </layout_panel>
-					   <layout_panel
+			 <layout_panel
                  width="330"
-								 layout="topleft"
-                 auto_resize="true"
-                 user_resize="false"
-                 follows="bottom|left|right"
-                 name="inbox_outbox_layout_panel"
-                 visible="false"
-                 min_dim="35"
-                 max_dim="235"
-                 expanded_min_dim="125"
-                 height="235">
-							 <layout_stack
-										follows="left|right|top|bottom"
-										layout="topleft"
-										left="0"
-										top="0"
-										orientation="vertical"
-										name="inbox_outbox_layout_stack"
-                    open_time_constant="0.02"
-                    close_time_constant="0.02"
-										height="235"
-										width="330">
-								 <layout_panel
-                 width="330"
-								 layout="topleft"
+				 layout="topleft"
                  auto_resize="true"
                  user_resize="false"
                  follows="left|right|top"
                  name="inbox_layout_panel"
                  visible="false"
                  min_dim="35"
-                 max_dim="200"
+                 max_dim="235"
                  expanded_min_dim="90"
-                 height="200">
+                 height="235">
                  <panel
                       follows="all"
                       layout="topleft"
@@ -91,13 +67,13 @@
                       class="panel_marketplace_inbox"
                       top="0"
                       label=""
-                      height="200"
+                      height="235"
                       width="330">
                      <string name="InboxLabelWithArg">Received items ([NUM])</string>
                      <string name="InboxLabelNoArg">Received items</string>
                      <button
                         label="Received items"
-												font="SansSerifMedium"
+						font="SansSerifMedium"
                         name="inbox_btn"
                         height="35"
                         width="308"
@@ -129,7 +105,7 @@
                      <panel
                         follows="all"
                         left="10"
-                        bottom="200"
+                        bottom="235"
                         width="308"
                         top="35"
                         bg_opaque_color="InventoryBackgroundColor"
@@ -145,7 +121,7 @@
 							top="0"
 							left="0"
 							width="308"
-							height="165"
+							height="200"
 							wrap="true"
 							halign="center">
 							Purchases from the marketplace will be delivered here.
@@ -153,8 +129,6 @@
                     </panel>
                  </panel>
              </layout_panel>
-			 </layout_stack>
-			 </layout_panel>
          </layout_stack>
 		<panel
 		     follows="bottom|left|right"
@@ -275,8 +249,7 @@
 			</layout_stack>
 		</panel>
 	</panel>
-
-<panel
+	<panel
 		 follows="all"
 		 layout="topleft"
 		 left="0"
@@ -289,8 +262,7 @@
 		 visible="false"
 		 width="330">
 	</panel>
-
-<panel
+	<panel
 		 follows="all"
 		 layout="topleft"
 		 left="0"
-- 
cgit v1.2.3


From cc92db1f353de96f6d27863b92671b2d847536f4 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 9 Dec 2011 16:19:03 -0800
Subject: Moved outbox import confirmations to window shades on the merchant
 outbox floater, rather than modal dialogs.

---
 indra/llui/llwindowshade.cpp                       |  5 ++
 indra/llui/llwindowshade.h                         |  2 +
 indra/newview/llfloateroutbox.cpp                  | 61 +++++++++++++++++++++-
 indra/newview/llfloateroutbox.h                    |  8 +++
 indra/newview/llnotificationhandler.h              | 10 +++-
 indra/newview/llnotificationmanager.cpp            |  2 +
 indra/newview/skins/default/textures/textures.xml  | 19 ++-----
 .../newview/skins/default/xui/en/notifications.xml | 35 ++++++++-----
 8 files changed, 112 insertions(+), 30 deletions(-)

diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp
index cf76202215..b21c088a1f 100644
--- a/indra/llui/llwindowshade.cpp
+++ b/indra/llui/llwindowshade.cpp
@@ -297,6 +297,11 @@ void LLWindowShade::hide()
 	setMouseOpaque(false);
 }
 
+bool LLWindowShade::isShown() const
+{
+	return getChildRef<LLLayoutPanel>("notification_area").getVisible();
+}
+
 void LLWindowShade::onCloseNotification()
 {
 	LLNotifications::instance().cancel(mNotification);
diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h
index 09ffc2cd54..cb8f223a84 100644
--- a/indra/llui/llwindowshade.h
+++ b/indra/llui/llwindowshade.h
@@ -48,6 +48,8 @@ public:
 	void show();
 	/*virtual*/ void draw();
 	void hide();
+	
+	bool isShown() const;
 
 private:
 	friend class LLUICtrlFactory;
diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 619be87187..8d64214e8c 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -33,11 +33,32 @@
 #include "llinventoryobserver.h"
 #include "llinventorypanel.h"
 #include "llmarketplacefunctions.h"
+#include "llnotificationhandler.h"
 #include "llnotificationsutil.h"
 #include "lltextbox.h"
 #include "lltransientfloatermgr.h"
 #include "lltrans.h"
 #include "llviewernetwork.h"
+#include "llwindowshade.h"
+
+
+///----------------------------------------------------------------------------
+/// LLOutboxNotification class
+///----------------------------------------------------------------------------
+
+bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify)
+{
+	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+	if (notification)
+	{
+		LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox");
+
+		outbox_floater->showNotification(notification);
+	}
+
+	return false;
+}
 
 
 ///----------------------------------------------------------------------------
@@ -89,6 +110,7 @@ LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
 	, mInventoryText(NULL)
 	, mInventoryTitle(NULL)
 	, mImportButton(NULL)
+	, mWindowShade(NULL)
 {
 }
 
@@ -121,6 +143,16 @@ BOOL LLFloaterOutbox::postBuild()
 	return TRUE;
 }
 
+void LLFloaterOutbox::onClose(bool app_quitting)
+{
+	if (mWindowShade)
+	{
+		delete mWindowShade;
+
+		mWindowShade = NULL;
+	}
+}
+
 void LLFloaterOutbox::onOpen(const LLSD& key)
 {
 	//
@@ -275,7 +307,8 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 {
 	// Pass drag and drop to this floater to the outbox inventory control
 	
-	if (LLMarketplaceInventoryImporter::getInstance()->isImportInProgress())
+	if (LLMarketplaceInventoryImporter::getInstance()->isImportInProgress() || 
+		(mWindowShade && mWindowShade->isShown()))
 	{
 		return FALSE;
 	}
@@ -369,3 +402,29 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress)
 	}
 }
 
+void LLFloaterOutbox::showNotification(LLNotificationPtr notify)
+{
+	if (mWindowShade)
+	{
+		delete mWindowShade;
+	}
+	
+	LLRect floater_rect = getLocalRect();
+	floater_rect.mTop -= getHeaderHeight();
+	floater_rect.stretch(-5, 0);
+	
+	LLWindowShade::Params params;
+	params.name = "notification_shade";
+	params.rect = floater_rect;
+	params.follows.flags = FOLLOWS_ALL;
+	params.notification = notify;
+	params.modal = true;
+	params.can_close = false;
+	params.text_color = LLColor4::white;
+	
+	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
+	
+	addChild(mWindowShade);
+	mWindowShade->show();
+}
+
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index 3d2ce86144..8023434675 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -30,6 +30,7 @@
 
 #include "llfloater.h"
 #include "llfoldertype.h"
+#include "llnotificationptr.h"
 
 
 class LLButton;
@@ -37,8 +38,10 @@ class LLInventoryCategoriesObserver;
 class LLInventoryCategoryAddedObserver;
 class LLInventoryPanel;
 class LLLoadingIndicator;
+class LLNotification;
 class LLTextBox;
 class LLView;
+class LLWindowShade;
 
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -55,12 +58,15 @@ public:
 
 	// virtuals
 	BOOL postBuild();
+	void onClose(bool app_quitting);
 	void onOpen(const LLSD& key);
 	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 						   EDragAndDropType cargo_type,
 						   void* cargo_data,
 						   EAcceptance* accept,
 						   std::string& tooltip_msg);
+	
+	void showNotification(LLNotificationPtr notify);
 
 protected:
 	void importReportResults(U32 status, const LLSD& content);
@@ -86,6 +92,8 @@ private:
 	LLTextBox *				mInventoryTitle;
 	
 	LLButton *		mImportButton;
+	
+	LLWindowShade *	mWindowShade;
 };
 
 #endif // LL_LLFLOATEROUTBOX_H
diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
index 28a69f2373..23dbb6b047 100644
--- a/indra/newview/llnotificationhandler.h
+++ b/indra/newview/llnotificationhandler.h
@@ -283,9 +283,17 @@ class LLBrowserNotification : public LLSingleton<LLBrowserNotification>
 {
 public:
 	virtual bool processNotification(const LLSD& notify);
+};
 	
+/**
+ * Handler for outbox notifications
+ */
+class LLOutboxNotification : public LLSingleton<LLOutboxNotification>
+{
+public:
+	virtual bool processNotification(const LLSD& notify);
 };
-
+	
 class LLHandlerUtil
 {
 public:
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
index 6988227128..6105eff8ea 100644
--- a/indra/newview/llnotificationmanager.cpp
+++ b/indra/newview/llnotificationmanager.cpp
@@ -62,6 +62,7 @@ void LLNotificationManager::init()
 	LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer"));
 	LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint"));
 	LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser"));
+	LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox"));
   
 	LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
 	LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
@@ -72,6 +73,7 @@ void LLNotificationManager::init()
 	LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
 	LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1));
 	LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1));
+	LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1));
 
 	mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD()));
 	mNotifyHandlers["notifytip"] =  boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD()));
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 5da1276881..e4a8622a4b 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -387,22 +387,9 @@ with the same filename but different name
   <texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" />
   <texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" />
 
-  <texture name="OutboxPush_Disabled" file_name="icons/OutboxPush_Disabled.png" preload="true" />
-  <texture name="OutboxPush_Off" file_name="icons/OutboxPush_Off.png" preload="true" />
-  <texture name="OutboxPush_On" file_name="icons/OutboxPush_On.png" preload="true" />
-  <texture name="OutboxPush_On_Over" file_name="icons/OutboxPush_On_Over.png" preload="true" />
-  <texture name="OutboxPush_Over" file_name="icons/OutboxPush_Over.png" preload="true" />
-  <texture name="OutboxPush_Press" file_name="icons/OutboxPush_Press.png" preload="true" />
-  <texture name="OutboxPush_Progress_1" file_name="icons/OutboxPush_Progress_1.png" preload="true" />
-  <texture name="OutboxPush_Progress_2" file_name="icons/OutboxPush_Progress_2.png" preload="true" />
-  <texture name="OutboxPush_Progress_3" file_name="icons/OutboxPush_Progress_3.png" preload="true" />
-  <texture name="OutboxPush_Progress_4" file_name="icons/OutboxPush_Progress_4.png" preload="true" />
-  <texture name="OutboxPush_Progress_5" file_name="icons/OutboxPush_Progress_5.png" preload="true" />
-  <texture name="OutboxPush_Progress_6" file_name="icons/OutboxPush_Progress_6.png" preload="true" />
-  <texture name="OutboxPush_Selected" file_name="icons/OutboxPush_Selected.png" preload="true" />
-  <texture name="OutboxPush_Selected_Disabled" file_name="icons/OutboxPush_Selected_Disabled.png" preload="true" />
-  <texture name="OutboxPush_Selected_Over" file_name="icons/OutboxPush_Selected_Over.png" preload="true" />
-  <texture name="OutboxPush_Selected_Press" file_name="icons/OutboxPush_Selected_Press.png" preload="true" />
+  <texture name="OutboxStatus_Success" file_name="green_checkmark.png" preload="false" />
+  <texture name="OutboxStatus_Warning" file_name="icons/pop_up_caution.png" preload="false" />
+  <texture name="OutboxStatus_Error" file_name="red_x.png" preload="false" />
 
   <texture name="PanOrbit_Off" file_name="bottomtray/PanOrbit_Off.png" preload="false" />
 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 8d0d76b58e..b174d51421 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -212,33 +212,44 @@ Save changes to current clothing/body part?
     </notification>
 
   <notification
-   icon="alertmodal.tga"
+   icon="OutboxStatus_Success"
    name="OutboxImportComplete"
-   type="alertmodal">
-Marketplace import complete.
+   type="outbox">
+Success
+
+All folders were successfully sent to the Marketplace.
+
         <usetemplate
          name="okbutton"
-         yestext="Hooray!"/>
+         yestext="OK"/>
   </notification>
 
   <notification
-   icon="alertmodal.tga"
+   icon="OutboxStatus_Warning"
    name="OutboxImportHadErrors"
-   type="alertmodal">
-Marketplace import completed with errors!  Please correct the problems in your outbox and retry.  Thanks.
+   type="outbox">
+Some folders did not transfer
+
+Errors occurred when some folders were sent to the Marketplace.  Those folders are still in your Merchant Outbox.  See the error log for more information.
+
         <usetemplate
          name="okbutton"
-         yestext="Boo!"/>
+         yestext="OK"/>
   </notification>
 
   <notification
-   icon="alertmodal.tga"
+   icon="OutboxStatus_Error"
    name="OutboxImportFailed"
-   type="alertmodal">
-Marketplace import failed with error [ERROR_CODE]!  Please try again later.  Thanks.
+   type="outbox">
+Transfer failed
+
+No folders were sent to the Marketplace because of a system or network error.  Try again later.
+
+Error [ERROR_CODE]
+
         <usetemplate
          name="okbutton"
-         yestext="Rats!"/>
+         yestext="OK"/>
   </notification>
 
     
-- 
cgit v1.2.3


From 6114ce2d27a3c776a59d1f09ad05d9b2f100a35d Mon Sep 17 00:00:00 2001
From: Seth ProductEngine <slitovchuk@productengine.com>
Date: Mon, 12 Dec 2011 13:32:23 +0200
Subject: EXP-1672 FIXED Added check for LLChicletBar instance existence not to
 create a new one when viewer exits. Could not reproduce the crash. This is a
 possible fix for EXP-1672. The message before the crash in all client logs
 was: "WARNING: LLSingleton<class LLChicletBar>::getInstance: Trying to access
 deleted singleton class LLChicletBar creating new instance"

---
 indra/newview/llchiclet.cpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index a076374903..9626b93690 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -296,6 +296,13 @@ void LLIMWellChiclet::createMenu()
 
 void LLIMWellChiclet::messageCountChanged(const LLSD& session_data)
 {
+	// The singleton class LLChicletBar instance might be already deleted
+	// so don't create a new one.
+	if (!LLChicletBar::instanceExists())
+	{
+		return;
+	}
+
 	const LLUUID& session_id = session_data["session_id"];
 	const S32 counter = LLChicletBar::getInstance()->getTotalUnreadIMCount();
 	const bool im_not_visible = !LLFloaterReg::instanceVisible("im_container")
-- 
cgit v1.2.3


From 40a74eb5b77493e66587a01b6655d405c75e3a59 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 12 Dec 2011 12:32:22 -0800
Subject: EXP-1711 FIX LLWindowShade doesn't stack multiple notifications

---
 indra/llui/lllayoutstack.h                 |   3 +-
 indra/llui/llpanel.h                       |   2 +
 indra/llui/llwindowshade.cpp               | 207 ++++++++++++++++++-----------
 indra/llui/llwindowshade.h                 |  10 +-
 indra/newview/llmediactrl.cpp              |  46 +++----
 indra/newview/llpanelprimmediacontrols.cpp |   3 +-
 6 files changed, 163 insertions(+), 108 deletions(-)

diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index ede6149a80..3b308a359d 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -191,13 +191,12 @@ public:
 		return min_dim;
 	}
 
+	F32 getCollapseFactor();
 	void setOrientation(LLLayoutStack::ELayoutOrientation orientation) { mOrientation = orientation; }
 
 protected:
 	LLLayoutPanel(const Params& p);
 	
-	F32 getCollapseFactor();
-
 	bool	mExpandedMinDimSpecified;
 	S32		mExpandedMinDim;
 	
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index cd33938226..f620201020 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -135,6 +135,8 @@ public:
 	const LLColor4&	getBackgroundColor() const { return mBgOpaqueColor; }
 	void			setTransparentColor(const LLColor4& color) { mBgAlphaColor = color; }
 	const LLColor4& getTransparentColor() const { return mBgAlphaColor; }
+	void			setBackgroundImage(LLUIImage* image) { mBgOpaqueImage = image; }
+	void			setTransparentImage(LLUIImage* image) { mBgAlphaImage = image; }
 	LLPointer<LLUIImage> getBackgroundImage() const { return mBgOpaqueImage; }
 	LLPointer<LLUIImage> getTransparentImage() const { return mBgAlphaImage; }
 	LLColor4		getBackgroundImageOverlay() { return mBgOpaqueImageOverlay; }
diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp
index cf76202215..0b4cfe68a6 100644
--- a/indra/llui/llwindowshade.cpp
+++ b/indra/llui/llwindowshade.cpp
@@ -37,6 +37,8 @@
 const S32 MIN_NOTIFICATION_AREA_HEIGHT = 30;
 const S32 MAX_NOTIFICATION_AREA_HEIGHT = 100;
 
+static LLDefaultChildRegistry::Register<LLWindowShade> r("window_shade");
+
 LLWindowShade::Params::Params()
 :	bg_image("bg_image"),
 	modal("modal", false),
@@ -48,7 +50,6 @@ LLWindowShade::Params::Params()
 
 LLWindowShade::LLWindowShade(const LLWindowShade::Params& params)
 :	LLUICtrl(params),
-	mNotification(params.notification),
 	mModal(params.modal),
 	mFormHeight(0),
 	mTextColor(params.text_color)
@@ -72,7 +73,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params)
 	addChild(stackp);
 
 	LLLayoutPanel::Params panel_p;
-	panel_p.rect = LLRect(0, 30, 800, 0);
+	panel_p.rect = LLRect(0, MIN_NOTIFICATION_AREA_HEIGHT, 800, 0);
 	panel_p.name = "notification_area";
 	panel_p.visible = false;
 	panel_p.user_resize = false;
@@ -107,11 +108,11 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params)
 
 	LLIconCtrl::Params icon_p;
 	icon_p.name = "notification_icon";
-	icon_p.rect = LLRect(5, 23, 21, 8);
+	icon_p.rect = LLRect(5, 25, 21, 10);
 	panel->addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_p));
 
 	LLTextBox::Params text_p;
-	text_p.rect = LLRect(31, 20, panel->getRect().getWidth() - 5, 0);
+	text_p.rect = LLRect(31, 23, panel->getRect().getWidth() - 5, 3);
 	text_p.follows.flags = FOLLOWS_ALL;
 	text_p.text_color = mTextColor;
 	text_p.font = LLFontGL::getFontSansSerifSmall();
@@ -125,41 +126,132 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params)
 	panel_p.auto_resize = false;
 	panel_p.user_resize = false;
 	panel_p.name="form_elements";
-	panel_p.rect = LLRect(0, 30, 130, 0);
+	panel_p.rect = LLRect(0, MIN_NOTIFICATION_AREA_HEIGHT, 130, 0);
 	LLLayoutPanel* form_elements_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
 	stackp->addChild(form_elements_panel);
 
-	if (params.can_close)
+	panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
+	panel_p.auto_resize = false;
+	panel_p.user_resize = false;
+	panel_p.rect = LLRect(0, MIN_NOTIFICATION_AREA_HEIGHT, 25, 0);
+	panel_p.name = "close_panel";
+	LLLayoutPanel* close_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
+	stackp->addChild(close_panel);
+
+	LLButton::Params button_p;
+	button_p.name = "close_notification";
+	button_p.rect = LLRect(5, 23, 21, 7);
+	button_p.image_color.control="DkGray_66";
+	button_p.image_unselected.name="Icon_Close_Foreground";
+	button_p.image_selected.name="Icon_Close_Press";
+	button_p.click_callback.function = boost::bind(&LLWindowShade::onCloseNotification, this);
+
+	close_panel->addChild(LLUICtrlFactory::create<LLButton>(button_p));
+	
+	close_panel->setVisible(params.can_close);
+}
+
+void LLWindowShade::draw()
+{
+	LLRect message_rect = getChild<LLTextBox>("notification_text")->getTextBoundingRect();
+
+	LLLayoutPanel* notification_area = getChild<LLLayoutPanel>("notification_area");
+
+	notification_area->reshape(notification_area->getRect().getWidth(), 
+		llclamp(message_rect.getHeight() + 15, 
+				llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT),
+				MAX_NOTIFICATION_AREA_HEIGHT));
+
+	LLUICtrl::draw();
+
+	while(!mNotifications.empty() && !mNotifications.back()->isActive())
+	{
+		mNotifications.pop_back();
+		// go ahead and hide 
+		hide();
+	}
+
+	if (mNotifications.empty())
+	{
+		hide();
+	}
+	else if (notification_area->getCollapseFactor() < 0.01f)
+	{
+		displayLatestNotification();
+	}
+
+	if (!notification_area->getVisible() && (notification_area->getCollapseFactor() < 0.001f))
+	{
+		getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(false);
+		setMouseOpaque(false);
+	}
+}
+
+void LLWindowShade::hide()
+{
+	getChildRef<LLLayoutPanel>("notification_area").setVisible(false);
+}
+
+void LLWindowShade::onCloseNotification()
+{
+	if (!mNotifications.empty())
+		LLNotifications::instance().cancel(mNotifications.back());
+}
+
+void LLWindowShade::onClickIgnore(LLUICtrl* ctrl)
+{
+	LLNotificationPtr notify = getCurrentNotification();
+	if (!notify) return;
+
+	bool check = ctrl->getValue().asBoolean();
+	if (notify->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
 	{
-		panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
-		panel_p.auto_resize = false;
-		panel_p.user_resize = false;
-		panel_p.rect = LLRect(0, 30, 25, 0);
-		LLLayoutPanel* close_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
-		stackp->addChild(close_panel);
-
-		LLButton::Params button_p;
-		button_p.name = "close_notification";
-		button_p.rect = LLRect(5, 23, 21, 7);
-		button_p.image_color.control="DkGray_66";
-		button_p.image_unselected.name="Icon_Close_Foreground";
-		button_p.image_selected.name="Icon_Close_Press";
-		button_p.click_callback.function = boost::bind(&LLWindowShade::onCloseNotification, this);
-
-		close_panel->addChild(LLUICtrlFactory::create<LLButton>(button_p));
+		// question was "show again" so invert value to get "ignore"
+		check = !check;
 	}
+	notify->setIgnored(check);
+}
+
+void LLWindowShade::onClickNotificationButton(const std::string& name)
+{
+	LLNotificationPtr notify = getCurrentNotification();
+	if (!notify) return;
 
-	LLSD payload = mNotification->getPayload();
+	mNotificationResponse[name] = true;
 
-	LLNotificationFormPtr formp = mNotification->getForm();
+	notify->respond(mNotificationResponse);
+}
+
+void LLWindowShade::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name)
+{
+	mNotificationResponse[name] = ctrl->getValue().asString();
+}
+
+void LLWindowShade::show(LLNotificationPtr notification)
+{
+	mNotifications.push_back(notification);
+
+	displayLatestNotification();
+}
+
+void LLWindowShade::displayLatestNotification()
+{
+	if (mNotifications.empty()) return;
+
+	LLNotificationPtr notification = mNotifications.back();
+
+	LLSD payload = notification->getPayload();
+
+	LLNotificationFormPtr formp = notification->getForm();
 	LLLayoutPanel& notification_area = getChildRef<LLLayoutPanel>("notification_area");
-	notification_area.getChild<LLUICtrl>("notification_icon")->setValue(mNotification->getIcon());
-	notification_area.getChild<LLUICtrl>("notification_text")->setValue(mNotification->getMessage());
-	notification_area.getChild<LLUICtrl>("notification_text")->setToolTip(mNotification->getMessage());
+	notification_area.getChild<LLUICtrl>("notification_icon")->setValue(notification->getIcon());
+	notification_area.getChild<LLUICtrl>("notification_text")->setValue(notification->getMessage());
+	notification_area.getChild<LLUICtrl>("notification_text")->setToolTip(notification->getMessage());
 
 	LLNotificationForm::EIgnoreType ignore_type = formp->getIgnoreType(); 
 	LLLayoutPanel& form_elements = notification_area.getChildRef<LLLayoutPanel>("form_elements");
 	form_elements.deleteAllChildren();
+	form_elements.reshape(form_elements.getRect().getWidth(), MIN_NOTIFICATION_AREA_HEIGHT);
 
 	const S32 FORM_PADDING_HORIZONTAL = 10;
 	const S32 FORM_PADDING_VERTICAL = 3;
@@ -229,7 +321,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params)
 			label_p.v_pad = 5;
 			LLTextBox* textbox = LLUICtrlFactory::create<LLTextBox>(label_p);
 			textbox->reshapeToFitText();
-			textbox->reshape(textbox->getRect().getWidth(), form_elements.getRect().getHeight() - 2 * FORM_PADDING_VERTICAL); 
+			textbox->reshape(textbox->getRect().getWidth(), MIN_NOTIFICATION_AREA_HEIGHT - 2 * FORM_PADDING_VERTICAL); 
 			form_elements.addChild(textbox);
 			cur_x = textbox->getRect().mRight + FORM_PADDING_HORIZONTAL;
 
@@ -249,7 +341,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params)
 		}
 	}
 
-	mFormHeight = form_elements.getRect().getHeight() - (cur_y - FORM_PADDING_VERTICAL) + WIDGET_HEIGHT;
+	mFormHeight = form_elements.getRect().getHeight() - (cur_y - WIDGET_HEIGHT - FORM_PADDING_VERTICAL);
 	form_elements.reshape(form_width, mFormHeight);
 	form_elements.setMinDim(form_width);
 
@@ -261,68 +353,33 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params)
 	{
 		(*it)->translate(0, delta_y);
 	}
-}
 
-void LLWindowShade::show()
-{
 	getChildRef<LLLayoutPanel>("notification_area").setVisible(true);
 	getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(mModal);
 
 	setMouseOpaque(mModal);
 }
 
-void LLWindowShade::draw()
+void LLWindowShade::setBackgroundImage(LLUIImage* image)
 {
-	LLRect message_rect = getChild<LLTextBox>("notification_text")->getTextBoundingRect();
-
-	LLLayoutPanel* notification_area = getChild<LLLayoutPanel>("notification_area");
-
-	notification_area->reshape(notification_area->getRect().getWidth(), 
-		llclamp(message_rect.getHeight() + 10, 
-				llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT),
-				MAX_NOTIFICATION_AREA_HEIGHT));
-
-	LLUICtrl::draw();
-	if (mNotification && !mNotification->isActive())
-	{
-		hide();
-	}
+	getChild<LLLayoutPanel>("notification_area")->setTransparentImage(image);
 }
 
-void LLWindowShade::hide()
+void LLWindowShade::setTextColor(LLColor4 color)
 {
-	getChildRef<LLLayoutPanel>("notification_area").setVisible(false);
-	getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(false);
-
-	setMouseOpaque(false);
+	getChild<LLTextBox>("notification_text")->setColor(color);
 }
 
-void LLWindowShade::onCloseNotification()
+void LLWindowShade::setCanClose(bool can_close)
 {
-	LLNotifications::instance().cancel(mNotification);
+	getChildView("close_panel")->setVisible(can_close);
 }
 
-void LLWindowShade::onClickIgnore(LLUICtrl* ctrl)
+LLNotificationPtr LLWindowShade::getCurrentNotification()
 {
-	bool check = ctrl->getValue().asBoolean();
-	if (mNotification && mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
+	if (mNotifications.empty())
 	{
-		// question was "show again" so invert value to get "ignore"
-		check = !check;
+		return LLNotificationPtr();
 	}
-	mNotification->setIgnored(check);
-}
-
-void LLWindowShade::onClickNotificationButton(const std::string& name)
-{
-	if (!mNotification) return;
-
-	mNotificationResponse[name] = true;
-
-	mNotification->respond(mNotificationResponse);
-}
-
-void LLWindowShade::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name)
-{
-	mNotificationResponse[name] = ctrl->getValue().asString();
-}
+	return mNotifications.back();
+}
\ No newline at end of file
diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h
index 09ffc2cd54..1dcab4e32f 100644
--- a/indra/llui/llwindowshade.h
+++ b/indra/llui/llwindowshade.h
@@ -36,7 +36,6 @@ class LLWindowShade : public LLUICtrl
 public:
 	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
 	{
-		Mandatory<LLNotificationPtr>	notification;
 		Optional<LLUIImage*>			bg_image;
 		Optional<LLUIColor>				text_color;
 		Optional<bool>					modal,
@@ -45,11 +44,16 @@ public:
 		Params();
 	};
 
-	void show();
+	void show(LLNotificationPtr);
 	/*virtual*/ void draw();
 	void hide();
+	void setBackgroundImage(LLUIImage* image);
+	void setTextColor(LLColor4 color);
+	void setCanClose(bool can_close);
 
 private:
+	void displayLatestNotification();
+	LLNotificationPtr getCurrentNotification();
 	friend class LLUICtrlFactory;
 
 	LLWindowShade(const Params& p);
@@ -60,7 +64,7 @@ private:
 	void onEnterNotificationText(LLUICtrl* ctrl, const std::string& name);
 	void onClickIgnore(LLUICtrl* ctrl);
 
-	LLNotificationPtr	mNotification;
+	std::vector<LLNotificationPtr>	mNotifications;
 	LLSD				mNotificationResponse;
 	bool				mModal;
 	S32					mFormHeight;
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 74fa5d350a..7650fe9229 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -133,10 +133,15 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
 		navigateHome();
 	}
 		
-	// FIXME: How do we create a bevel now?
-//	LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 );
-//	mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN );
-//	addChild( mBorder );
+	LLWindowShade::Params params;
+	params.name = "notification_shade";
+	params.rect = getLocalRect();
+	params.follows.flags = FOLLOWS_ALL;
+	params.modal = true;
+
+	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
+
+	addChild(mWindowShade);
 }
 
 LLMediaCtrl::~LLMediaCtrl()
@@ -1092,39 +1097,28 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response)
 
 void LLMediaCtrl::showNotification(LLNotificationPtr notify)
 {
-	delete mWindowShade;
+	LLWindowShade* shade = getChild<LLWindowShade>("notification_shade");
 
-	LLWindowShade::Params params;
-	params.name = "notification_shade";
-	params.rect = getLocalRect();
-	params.follows.flags = FOLLOWS_ALL;
-	params.notification = notify;
-	params.modal = true;
-	//HACK: don't hardcode this
 	if (notify->getIcon() == "Popup_Caution")
 	{
-		params.bg_image.name = "Yellow_Gradient";
-		params.text_color = LLColor4::black;
+		shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient"));
+		shade->setTextColor(LLColor4::black);
+		shade->setCanClose(true);
 	}
-	else
-	//HACK: another one since XUI doesn't support what we need right now
-	if (notify->getName() == "AuthRequest")
+	else if (notify->getName() == "AuthRequest")
 	{
-		params.bg_image.name = "Yellow_Gradient";
-		params.text_color = LLColor4::black;
-		params.can_close = false;
+		shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient"));
+		shade->setTextColor(LLColor4::black);
+		shade->setCanClose(false);
 	}
 	else
 	{
 		//HACK: make this a property of the notification itself, "cancellable"
-		params.can_close = false;
-		params.text_color.control = "LabelTextColor";
+		shade->setCanClose(false);
+		shade->setTextColor(LLUIColorTable::instance().getColor("LabelTextColor"));
 	}
 
-	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
-
-	addChild(mWindowShade);
-	mWindowShade->show();
+	mWindowShade->show(notify);
 }
 
 void LLMediaCtrl::hideNotification()
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 933b40ec79..39c0628cbe 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -1351,7 +1351,6 @@ void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify)
 	LLWindowShade::Params params;
 	params.rect = mMediaRegion->getLocalRect();
 	params.follows.flags = FOLLOWS_ALL;
-	params.notification = notify;
 
 	//HACK: don't hardcode this
 	if (notify->getIcon() == "Popup_Caution")
@@ -1369,7 +1368,7 @@ void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify)
 	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
 
 	mMediaRegion->addChild(mWindowShade);
-	mWindowShade->show();
+	mWindowShade->show(notify);
 }
 
 void LLPanelPrimMediaControls::hideNotification()
-- 
cgit v1.2.3


From e826cbd90750fd38565e4e44390948f36254cf1f Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 12 Dec 2011 15:02:52 -0800
Subject: EXP-1682 FIX EXP-1683 FIX EXP-1705 FIX EXP-1707 FIX

* Outbox folder count now uses inventory API directly rather than inventory folder view for folder count and item status
* Asynchronous fetches are triggered for the outbox content when the window is opened and when it receives focus
* Marketplace URL's for empty and non-merchant outbox view have been updated
* "Copy to Merchant Outbox" and "Delete" context menu items should be fully functional now with item counts, etc.
---
 indra/newview/llfloateroutbox.cpp              | 135 +++++++++++++------------
 indra/newview/llfloateroutbox.h                |  10 +-
 indra/newview/llmarketplacefunctions.cpp       | 101 +++++++++++-------
 indra/newview/llmarketplacefunctions.h         |   4 +
 indra/newview/skins/default/xui/en/strings.xml |  24 +++--
 5 files changed, 162 insertions(+), 112 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 8d64214e8c..b10ef0ba64 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -30,6 +30,7 @@
 
 #include "llfloaterreg.h"
 #include "llfolderview.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llinventoryobserver.h"
 #include "llinventorypanel.h"
 #include "llmarketplacefunctions.h"
@@ -139,6 +140,8 @@ BOOL LLFloaterOutbox::postBuild()
 	
 	mImportButton = getChild<LLButton>("outbox_import_btn");
 	mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this));
+	
+	LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this));
 
 	return TRUE;
 }
@@ -187,10 +190,30 @@ void LLFloaterOutbox::onOpen(const LLSD& key)
 	}
 	
 	updateView();
+	
+	//
+	// Trigger fetch of outbox contents
+	//
+	
+	fetchOutboxContents();
+}
+
+void LLFloaterOutbox::onFocusReceived()
+{
+	fetchOutboxContents();
+}
+
+void LLFloaterOutbox::fetchOutboxContents()
+{
+	if (mOutboxId.notNull())
+	{
+		LLInventoryModelBackgroundFetch::instance().start(mOutboxId);
+	}
 }
 
 void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
-{	
+{
+	llassert(outboxId.notNull());
 	llassert(mOutboxId.isNull());
 	llassert(mCategoriesObserver == NULL);
 	
@@ -228,15 +251,47 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
 	mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);	
 	mOutboxInventoryPanel->getFilter()->markDefault();
 	
-	// Set selection callback for proper update of inventory status buttons
-	//mOutboxInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceOutbox::onSelectionChange, this));
+	fetchOutboxContents();
+}
+
+void LLFloaterOutbox::updateItemCount()
+{
+	S32 item_count = 0;
+
+	if (mOutboxId.notNull())
+	{
+		LLInventoryModel::cat_array_t * cats;
+		LLInventoryModel::item_array_t * items;
+		gInventory.getDirectDescendentsOf(mOutboxId, cats, items);
+
+		item_count = cats->count() + items->count();
+	}
+	
+	mOutboxItemCount = item_count;
+
+	switch (mOutboxItemCount)
+	{
+		case 0:	mInventoryFolderCountText->setText(getString("OutboxFolderCount0"));	break;
+		case 1:	mInventoryFolderCountText->setText(getString("OutboxFolderCount1"));	break;
+		default:
+		{
+			std::string item_count_str = llformat("%d", mOutboxItemCount);
+			
+			LLStringUtil::format_map_t args;
+			args["[NUM]"] = item_count_str;
+			
+			mInventoryFolderCountText->setText(getString("OutboxFolderCountN", args));
+			break;
+		}
+	}
 	
-	// Set up the note to display when the outbox is empty
-	mOutboxInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryOutboxNoItems");
+	mImportButton->setEnabled(mOutboxItemCount > 0);
 }
 
 void LLFloaterOutbox::updateView()
 {
+	updateItemCount();
+
 	if (mOutboxItemCount > 0)
 	{
 		mOutboxInventoryPanel->setVisible(TRUE);
@@ -251,44 +306,17 @@ void LLFloaterOutbox::updateView()
 		std::string outbox_title;
 		std::string outbox_tooltip;
 		
+		LLStringUtil::format_map_t subs = getMarketplaceStringSubstitutions();
+		
 		if (mOutboxId.notNull())
 		{
-			outbox_text = LLTrans::getString("InventoryOutboxNoItems");
+			outbox_text = LLTrans::getString("InventoryOutboxNoItems", subs);
 			outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle");
 			outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip");
 		}
 		else
 		{
-			//
-			// The string to become a merchant contains 3 URL's which need the domain name patched in.
-			//
-			
-			std::string domain = "secondlife.com";
-			
-			if (!LLGridManager::getInstance()->isInProductionGrid())
-			{
-				std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
-				domain = llformat("%s.lindenlab.com", utf8str_tolower(gridLabel).c_str());
-			}
-			
-			LLStringUtil::format_map_t domain_arg;
-			domain_arg["[DOMAIN_NAME]"] = domain;
-			
-			std::string marketplace_url = LLTrans::getString("MarketplaceURL", domain_arg);
-			std::string marketplace_url_create = LLTrans::getString("MarketplaceURL_CreateStore", domain_arg);
-			std::string marketplace_url_info = LLTrans::getString("MarketplaceURL_LearnMore", domain_arg);
-			
-			LLStringUtil::format_map_t args1, args2, args3;
-			args1["[MARKETPLACE_URL]"] = marketplace_url;
-			args2["[LEARN_MORE_URL]"] = marketplace_url_info;
-			args3["[CREATE_STORE_URL]"] = marketplace_url_create;
-			
-			// NOTE: This is dumb, ridiculous and very finicky.  The order of these is very important
-			//       to have these three string substitutions work properly.
-			outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", args1);
-			LLStringUtil::format(outbox_text, args2);
-			LLStringUtil::format(outbox_text, args3);
-			
+			outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", subs);
 			outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle");
 			outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip");
 		}
@@ -306,7 +334,7 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 										std::string& tooltip_msg)
 {
 	// Pass drag and drop to this floater to the outbox inventory control
-	
+
 	if (LLMarketplaceInventoryImporter::getInstance()->isImportInProgress() || 
 		(mWindowShade && mWindowShade->isShown()))
 	{
@@ -329,37 +357,8 @@ void LLFloaterOutbox::onImportButtonClicked()
 void LLFloaterOutbox::onOutboxChanged()
 {
 	llassert(!mOutboxId.isNull());
-	
-	U32 item_count = 0;
-	
-	const LLFolderViewFolder * outbox_folder = mOutboxInventoryPanel->getRootFolder();
-	
-	if (outbox_folder)
-	{
-		item_count += outbox_folder->getFoldersCount();
-		item_count += outbox_folder->getItemsCount();
-	}
-	
-	mOutboxItemCount = item_count;
-
-	switch (mOutboxItemCount)
-	{
-		case 0:	mInventoryFolderCountText->setText(getString("OutboxFolderCount0"));	break;
-		case 1:	mInventoryFolderCountText->setText(getString("OutboxFolderCount1"));	break;
-		default:
-		{
-			std::string item_count_str = llformat("%d", mOutboxItemCount);
-			
-			LLStringUtil::format_map_t args;
-			args["[NUM]"] = item_count_str;
-
-			mInventoryFolderCountText->setText(getString("OutboxFolderCountN", args));
-			break;
-		}
-	}
-
-	mImportButton->setEnabled(mOutboxItemCount > 0);
 
+	fetchOutboxContents();
 	updateView();
 }
 
@@ -384,6 +383,8 @@ void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
 		//llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
 		LLNotificationsUtil::add("OutboxImportFailed", subs);
 	}
+	
+	updateView();
 }
 
 void LLFloaterOutbox::importStatusChanged(bool inProgress)
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index 8023434675..5222db1142 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -58,8 +58,6 @@ public:
 
 	// virtuals
 	BOOL postBuild();
-	void onClose(bool app_quitting);
-	void onOpen(const LLSD& key);
 	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 						   EDragAndDropType cargo_type,
 						   void* cargo_data,
@@ -69,12 +67,20 @@ public:
 	void showNotification(LLNotificationPtr notify);
 
 protected:
+	void fetchOutboxContents();
+
 	void importReportResults(U32 status, const LLSD& content);
 	void importStatusChanged(bool inProgress);
 	
+	void onClose(bool app_quitting);
+	void onOpen(const LLSD& key);
+
+	void onFocusReceived();
+
 	void onImportButtonClicked();
 	void onOutboxChanged();
 	
+	void updateItemCount();
 	void updateView();
 
 private:
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 9c67c589b8..225bb059c9 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -30,6 +30,7 @@
 
 #include "llagent.h"
 #include "llhttpclient.h"
+#include "lltrans.h"
 #include "llviewermedia.h"
 #include "llviewernetwork.h"
 
@@ -38,6 +39,59 @@
 // Helpers
 //
 
+static std::string getMarketplaceDomain()
+{
+	std::string domain = "secondlife.com";
+	
+	if (!LLGridManager::getInstance()->isInProductionGrid())
+	{
+		const std::string& grid_label = LLGridManager::getInstance()->getGridLabel();
+		const std::string& grid_label_lower = utf8str_tolower(grid_label);
+		
+		if (grid_label_lower == "damballah")
+		{
+			domain = "secondlife-staging.com";
+		}
+		else
+		{
+			domain = llformat("%s.lindenlab.com", grid_label_lower.c_str());
+		}
+	}
+	
+	return domain;
+}
+
+static std::string getMarketplaceURL(const std::string& urlStringName)
+{
+	LLStringUtil::format_map_t domain_arg;
+	domain_arg["[MARKETPLACE_DOMAIN_NAME]"] = getMarketplaceDomain();
+	
+	std::string marketplace_url = LLTrans::getString(urlStringName, domain_arg);
+	
+	return marketplace_url;
+}
+
+LLStringUtil::format_map_t getMarketplaceStringSubstitutions()
+{
+	std::string marketplace_url = getMarketplaceURL("MarketplaceURL");
+	std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore");
+	std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard");
+	std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore");
+	
+	LLStringUtil::format_map_t agent_map;
+	agent_map["[AGENT_ID]"] = gAgent.getID().getString();
+	
+	LLStringUtil::format(marketplace_url_dashboard, agent_map);
+	
+	LLStringUtil::format_map_t marketplace_sub_map;
+	marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url;
+	marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create;
+	marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info;
+	marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard;
+	
+	return marketplace_sub_map;
+}
+
 namespace LLMarketplaceImport
 {
 	// Basic interface for this namespace
@@ -61,42 +115,6 @@ namespace LLMarketplaceImport
 	static LLSD sImportResults = LLSD::emptyMap();
 		
 	
-	// Internal helper functions
-	
-	std::string getBaseURL()
-	{
-		std::string url = "https://marketplace.secondlife.com/";
-
-		if (!LLGridManager::getInstance()->isInProductionGrid())
-		{
-			std::string gridLabel = utf8str_tolower(LLGridManager::getInstance()->getGridLabel());
-			
-			if (gridLabel == "damballah")
-			{
-				url = "https://marketplace.secondlife-staging.com/";
-			}
-			else
-			{
-				url = llformat("https://marketplace.%s.lindenlab.com/", gridLabel.c_str());
-			}
-		}
-
-		url += "api/1/";
-		url += gAgent.getID().getString();
-		url += "/inventory/";
-
-		return url;
-	}
-
-	std::string getInventoryImportURL()
-	{
-		std::string url = getBaseURL();
-
-		url += "import/";
-
-		return url;
-	}
-	
 	// Responders
 	
 	class LLImportPostResponder : public LLHTTPClient::Responder
@@ -200,6 +218,17 @@ namespace LLMarketplaceImport
 		return sImportResults;
 	}
 	
+	static std::string getInventoryImportURL()
+	{
+		std::string url = getMarketplaceURL("MarketplaceURL");
+		
+		url += "api/1/";
+		url += gAgent.getID().getString();
+		url += "/inventory/import/";
+		
+		return url;
+	}
+	
 	void establishMarketplaceSessionCookie()
 	{
 		sImportInProgress = true;
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index 5ca0bdfe77..f501f1ee8b 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -34,6 +34,10 @@
 #include <boost/signals2.hpp>
 
 #include "llsingleton.h"
+#include "llstring.h"
+
+
+LLStringUtil::format_map_t getMarketplaceStringSubstitutions();
 
 
 namespace MarketplaceErrorCodes
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b8d5f93320..7dd965de84 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2029,18 +2029,28 @@ Returns a string with the requested data about the region
 	<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
 	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
 	<string name="InventoryInboxNoItems">When you purchase or otherwise receive an item, it will appear here so you can drag it to a folder in your inventory, or delete it if you do not wish to keep it.</string>
-	<string name="MarketplaceURL">http://marketplace.[DOMAIN_NAME]</string>
-	<string name="MarketplaceURL_CreateStore">http://marketplace.[DOMAIN_NAME]/create_store</string>
-	<string name="MarketplaceURL_LearnMore">http://marketplace.[DOMAIN_NAME]/learn_more</string>
+	<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]</string>
+	<string name="MarketplaceURL_CreateStore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/create_store</string>
+	<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/[AGENT_ID]/store/dashboard</string>
+	<string name="MarketplaceURL_LearnMore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more</string>
 	<string name="InventoryOutboxCreationErrorTitle">Your Merchant Outbox is not properly configured</string>
 	<string name="InventoryOutboxCreationErrorTooltip">Merchant Outbox configuration error</string>
 	<string name="InventoryOutboxCreationError">Please contact Customer Service to correct the problem.</string>
-	<string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace</string>
+	<string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace.</string>
 	<string name="InventoryOutboxNotMerchantTooltip">Become a merchant!</string>
-	<string name="InventoryOutboxNotMerchant">[[MARKETPLACE_URL] The Second Life Marketplace] offers more than one million virtual products for sale, all of them created by Residents. You, too, can sell items you create, as well as some of the items you have purchased. It’s easy and setup is free.  [[LEARN_MORE_URL] Learn more] or [[CREATE_STORE_URL] create a store] on the Marketplace to get started.</string>
-	<string name="InventoryOutboxNoItemsTitle">A new way to send items to the Marketplace</string>
+	<string name="InventoryOutboxNotMerchant">
+	The Second Life Marketplace offers more than one million virtual products for sale, all of them created by Residents like you.  You too can create items and sell them on the Marketplace.  Creating a store is easy and free of charge.
+	
+	[[MARKETPLACE_URL] Visit the Marketplace]
+	[[MARKETPLACE_LEARN_MORE_URL] Learn more about creating a store]
+	</string>
+	<string name="InventoryOutboxNoItemsTitle">Your outbox is empty.</string>
 	<string name="InventoryOutboxNoItemsTooltip">Drag and drop items here to prepare them for sale on the Marketplace</string>
-	<string name="InventoryOutboxNoItems">Drag items or folders that you wish to sell into this area.  A copy of the item will appear, leaving your inventory unchanged, unless you have dragged a no-copy item.  When you are ready to send the items to the Marketplace, click the Upload button. Once your items have been moved to your Marketplace Inventory, they will disappear from this folder.</string>
+	<string name="InventoryOutboxNoItems">
+	Drag folders to this area.  When you are ready to send them to the Marketplace for sale, click the "Send to Marketplace" button below.
+	
+	[[MARKETPLACE_DASHBOARD_URL] Go to your Merchant Dashboard]
+	</string>
 
 	<string name="Marketplace Error None">No errors</string>
 	<string name="Marketplace Error Not Merchant">Error: Before sending items to the Marketplace you will need to set yourself up as a merchant (free of charge).</string>
-- 
cgit v1.2.3


From 2b2a03b3c5e983f6dee85602a41acaf4d515a4db Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Mon, 12 Dec 2011 17:12:47 -0600
Subject: SH-2511 Fix for bumpmapped objects flickering.

---
 indra/newview/lldrawpoolbump.cpp | 79 +++++++++++++++++++---------------------
 1 file changed, 38 insertions(+), 41 deletions(-)

diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index b696b90d84..b58efe62ab 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -1036,51 +1036,48 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText
 	llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
 
 	LLViewerTexture* bump = NULL;
-	const F32 BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD = 1000;
-	if( src_image->getMaxVirtualSize() > BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD )
-	{
-		bump_image_map_t* entries_list = NULL;
-		void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
+	
+	bump_image_map_t* entries_list = NULL;
+	void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
 
-		switch( bump_code )
-		{
-		case BE_BRIGHTNESS:
-			entries_list = &mBrightnessEntries;
-			callback_func = LLBumpImageList::onSourceBrightnessLoaded;
-			break;
-		case BE_DARKNESS:
-			entries_list = &mDarknessEntries;
-			callback_func = LLBumpImageList::onSourceDarknessLoaded;
-			break;
-		default:
-			llassert(0);
-			return NULL;
-		}
+	switch( bump_code )
+	{
+	case BE_BRIGHTNESS:
+		entries_list = &mBrightnessEntries;
+		callback_func = LLBumpImageList::onSourceBrightnessLoaded;
+		break;
+	case BE_DARKNESS:
+		entries_list = &mDarknessEntries;
+		callback_func = LLBumpImageList::onSourceDarknessLoaded;
+		break;
+	default:
+		llassert(0);
+		return NULL;
+	}
 
-		bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
-		if (iter != entries_list->end() && iter->second.notNull())
-		{
-			bump = iter->second;
-		}
-		else
-		{
-			LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
-			raw->clear(0x77, 0x77, 0xFF, 0xFF);
+	bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
+	if (iter != entries_list->end() && iter->second.notNull())
+	{
+		bump = iter->second;
+	}
+	else
+	{
+		LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
+		raw->clear(0x77, 0x77, 0xFF, 0xFF);
 
-			(*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
-			bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
-		}
+		(*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
+		bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
+	}
 
-		if (!src_image->hasCallbacks())
-		{ //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again
-			if (src_image->getWidth() != bump->getWidth() ||
-				src_image->getHeight() != bump->getHeight())// ||
-				//(LLPipeline::sRenderDeferred && bump->getComponents() != 4))
-			{
-				src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
-				src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL );
-				src_image->forceToSaveRawImage(0) ;
-			}
+	if (!src_image->hasCallbacks())
+	{ //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again
+		if (src_image->getWidth() != bump->getWidth() ||
+			src_image->getHeight() != bump->getHeight())// ||
+			//(LLPipeline::sRenderDeferred && bump->getComponents() != 4))
+		{
+			src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
+			src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL );
+			src_image->forceToSaveRawImage(0) ;
 		}
 	}
 
-- 
cgit v1.2.3


From 35feb03d27036f82a6bca60c1be8d864de990646 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 12 Dec 2011 15:50:10 -0800
Subject: EXP-1711 FIX LLWindowShade doesn't stack multiple notifications added
 configurable shade color to window_shade

---
 indra/llui/llwindowshade.cpp                                | 3 ++-
 indra/llui/llwindowshade.h                                  | 3 ++-
 indra/newview/skins/default/xui/en/widgets/window_shade.xml | 2 ++
 3 files changed, 6 insertions(+), 2 deletions(-)
 create mode 100644 indra/newview/skins/default/xui/en/widgets/window_shade.xml

diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp
index 0b4cfe68a6..1e8b47de29 100644
--- a/indra/llui/llwindowshade.cpp
+++ b/indra/llui/llwindowshade.cpp
@@ -43,6 +43,7 @@ LLWindowShade::Params::Params()
 :	bg_image("bg_image"),
 	modal("modal", false),
 	text_color("text_color"),
+	shade_color("shade_color"),
 	can_close("can_close", true)
 {
 	changeDefault(mouse_opaque, false);
@@ -90,7 +91,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params)
 	panel_p.name = "background_area";
 	panel_p.mouse_opaque = false;
 	panel_p.background_visible = false;
-	panel_p.bg_alpha_color = LLColor4(0.f, 0.f, 0.f, 0.2f);
+	panel_p.bg_alpha_color = params.shade_color;
 	LLLayoutPanel* dummy_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
 	stackp->addChild(dummy_panel);
 
diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h
index 1dcab4e32f..1ae84028dd 100644
--- a/indra/llui/llwindowshade.h
+++ b/indra/llui/llwindowshade.h
@@ -37,7 +37,8 @@ public:
 	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
 	{
 		Optional<LLUIImage*>			bg_image;
-		Optional<LLUIColor>				text_color;
+		Optional<LLUIColor>				text_color,
+										shade_color;
 		Optional<bool>					modal,
 										can_close;
 
diff --git a/indra/newview/skins/default/xui/en/widgets/window_shade.xml b/indra/newview/skins/default/xui/en/widgets/window_shade.xml
new file mode 100644
index 0000000000..23eb2f13fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/window_shade.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<window_shade shade_color="0 0 0 0.5"/>
-- 
cgit v1.2.3


From e859c3446b5c631fe0a9806434aa19b64a0d9113 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 12 Dec 2011 16:06:22 -0800
Subject: Added missing line end to satisfy coding policy

---
 indra/llui/llwindowshade.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp
index 1e8b47de29..ae8b30b1ba 100644
--- a/indra/llui/llwindowshade.cpp
+++ b/indra/llui/llwindowshade.cpp
@@ -383,4 +383,5 @@ LLNotificationPtr LLWindowShade::getCurrentNotification()
 		return LLNotificationPtr();
 	}
 	return mNotifications.back();
-}
\ No newline at end of file
+}
+
-- 
cgit v1.2.3


From d3f06b296203c08c900c4e569ce5df0ac2f27715 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 12 Dec 2011 17:04:58 -0800
Subject: Fixed marketplace URL trailing '/' and updated to latest window shade
 code from viewer-experience

---
 indra/newview/llfloateroutbox.cpp              | 4 ++--
 indra/newview/skins/default/xui/en/strings.xml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index b10ef0ba64..972e1e8cdc 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -418,14 +418,14 @@ void LLFloaterOutbox::showNotification(LLNotificationPtr notify)
 	params.name = "notification_shade";
 	params.rect = floater_rect;
 	params.follows.flags = FOLLOWS_ALL;
-	params.notification = notify;
 	params.modal = true;
 	params.can_close = false;
+	params.shade_color = LLColor4::white % 0.25f;
 	params.text_color = LLColor4::white;
 	
 	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
 	
 	addChild(mWindowShade);
-	mWindowShade->show();
+	mWindowShade->show(notify);
 }
 
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 7dd965de84..3c7465cd7c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2029,7 +2029,7 @@ Returns a string with the requested data about the region
 	<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
 	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
 	<string name="InventoryInboxNoItems">When you purchase or otherwise receive an item, it will appear here so you can drag it to a folder in your inventory, or delete it if you do not wish to keep it.</string>
-	<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]</string>
+	<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string>
 	<string name="MarketplaceURL_CreateStore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/create_store</string>
 	<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/[AGENT_ID]/store/dashboard</string>
 	<string name="MarketplaceURL_LearnMore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more</string>
-- 
cgit v1.2.3


From 181eaa8196d19d5d0c1db17fe27bd2bdee11525b Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 12 Dec 2011 17:22:47 -0800
Subject: EXP-1648 FIX

* Merchant outbox no longer crashes for non-merchants.
* Folder count is hidden for non-merchants.
* Drag and drop to merchant outbox floater is disabled for non-merchants.
---
 indra/newview/llfloateroutbox.cpp              | 38 ++++++++++++++++----------
 indra/newview/skins/default/xui/en/strings.xml |  1 +
 2 files changed, 24 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 972e1e8cdc..b15380d427 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -269,22 +269,25 @@ void LLFloaterOutbox::updateItemCount()
 	
 	mOutboxItemCount = item_count;
 
-	switch (mOutboxItemCount)
+	if (mOutboxInventoryPanel)
 	{
-		case 0:	mInventoryFolderCountText->setText(getString("OutboxFolderCount0"));	break;
-		case 1:	mInventoryFolderCountText->setText(getString("OutboxFolderCount1"));	break;
-		default:
+		switch (mOutboxItemCount)
 		{
-			std::string item_count_str = llformat("%d", mOutboxItemCount);
-			
-			LLStringUtil::format_map_t args;
-			args["[NUM]"] = item_count_str;
-			
-			mInventoryFolderCountText->setText(getString("OutboxFolderCountN", args));
-			break;
+			case 0:	mInventoryFolderCountText->setText(getString("OutboxFolderCount0"));	break;
+			case 1:	mInventoryFolderCountText->setText(getString("OutboxFolderCount1"));	break;
+			default:
+			{
+				std::string item_count_str = llformat("%d", mOutboxItemCount);
+				
+				LLStringUtil::format_map_t args;
+				args["[NUM]"] = item_count_str;
+				
+				mInventoryFolderCountText->setText(getString("OutboxFolderCountN", args));
+				break;
+			}
 		}
 	}
-	
+
 	mImportButton->setEnabled(mOutboxItemCount > 0);
 }
 
@@ -299,7 +302,11 @@ void LLFloaterOutbox::updateView()
 	}
 	else
 	{
-		mOutboxInventoryPanel->setVisible(FALSE);
+		if (mOutboxInventoryPanel)
+		{
+			mOutboxInventoryPanel->setVisible(FALSE);
+		}
+
 		mInventoryPlaceholder->setVisible(TRUE);
 
 		std::string outbox_text;
@@ -335,8 +342,9 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 {
 	// Pass drag and drop to this floater to the outbox inventory control
 
-	if (LLMarketplaceInventoryImporter::getInstance()->isImportInProgress() || 
-		(mWindowShade && mWindowShade->isShown()))
+	if ((mOutboxInventoryPanel == NULL) ||
+		(mWindowShade && mWindowShade->isShown()) ||
+		LLMarketplaceInventoryImporter::getInstance()->isImportInProgress())
 	{
 		return FALSE;
 	}
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 3c7465cd7c..d8da56d338 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2042,6 +2042,7 @@ Returns a string with the requested data about the region
 	The Second Life Marketplace offers more than one million virtual products for sale, all of them created by Residents like you.  You too can create items and sell them on the Marketplace.  Creating a store is easy and free of charge.
 	
 	[[MARKETPLACE_URL] Visit the Marketplace]
+
 	[[MARKETPLACE_LEARN_MORE_URL] Learn more about creating a store]
 	</string>
 	<string name="InventoryOutboxNoItemsTitle">Your outbox is empty.</string>
-- 
cgit v1.2.3


From aba090ab9027e5a5c1e9eb114ecca12b9eafa978 Mon Sep 17 00:00:00 2001
From: Paul ProductEngine <pguslisty@productengine.com>
Date: Tue, 13 Dec 2011 17:27:54 +0200
Subject: EXP-1599 FIXED (Sharing multiple selected inventory folders only
 shares one folder (no warning for user))

- In case of sharing multiple folders, make the confirmation dialog contain a warning that only one folder can be shared at a time.
---
 indra/newview/llavataractions.cpp                    | 19 ++++++++++++++++++-
 indra/newview/skins/default/xui/en/notifications.xml | 20 ++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 8ca621538f..7abecc643b 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -680,12 +680,29 @@ namespace action_give_inventory
 		std::string items;
 		build_items_string(inventory_selected_uuids, items);
 
+		int folders_count = 0;
+		std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+
+		//traverse through selected inventory items and count folders among them
+		for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it)
+		{
+			LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
+			if (NULL != inv_cat)
+			{
+				folders_count++;
+			}
+		}
+
+		// EXP-1599
+		// In case of sharing multiple folders, make the confirmation
+		// dialog contain a warning that only one folder can be shared at a time.
+		std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation";
 		LLSD substitutions;
 		substitutions["RESIDENTS"] = residents;
 		substitutions["ITEMS"] = items;
 		LLShareInfo::instance().mAvatarNames = avatar_names;
 		LLShareInfo::instance().mAvatarUuids = avatar_uuids;
-		LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, LLSD(), &give_inventory_cb);
+		LLNotificationsUtil::add(notification, substitutions, LLSD(), &give_inventory_cb);
 	}
 }
 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 0ba4b84abe..5b985c9981 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6942,6 +6942,26 @@ With the following Residents:
      yestext="OK"/>
   </notification>
   
+  <notification
+   icon="notifytip.tga"
+   name="ShareFolderConfirmation"
+   type="alertmodal">
+Only one folder at a time can be shared.
+
+Are you sure you want to share the following items:
+
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
+
+With the following Residents:
+
+[RESIDENTS]
+  <tag>confirm</tag>
+	<usetemplate
+     name="okcancelbuttons"
+     notext="Cancel"
+     yestext="Ok"/>
+  </notification>
+  
   <notification
    icon="notifytip.tga"
    name="ItemsShared"
-- 
cgit v1.2.3


From 9fcdec3e34d689ccfb74fb4905fa975f5819270a Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 13 Dec 2011 11:15:01 -0800
Subject: EXP-1679 FIX -- Collapse links that are dragged to the outbox

* Links are automatically tracked back to their source when dragged to the outbox
* Worn items are now allowed into the outbox
---
 indra/newview/llinventorybridge.cpp    | 25 +++++++++++---
 indra/newview/llinventoryfunctions.cpp | 63 +++++++++++++++++++++-------------
 2 files changed, 61 insertions(+), 27 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 33b9af7a78..3f12e8b1d3 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -72,6 +72,7 @@
 
 // Marketplace outbox current disabled
 #define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1
+#define BLOCK_WORN_ITEMS_IN_OUTBOX 0
 
 typedef std::pair<LLUUID, LLUUID> two_uuids_t;
 typedef std::list<two_uuids_t> two_uuids_list_t;
@@ -1101,6 +1102,8 @@ BOOL LLInvFVBridge::canListOnMarketplace() const
 BOOL LLInvFVBridge::canListOnMarketplaceNow() const
 {
 #if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+
+#if BLOCK_WORN_ITEMS_IN_OUTBOX
 	if (get_is_item_worn(mUUID))
 	{
 		return FALSE;
@@ -1112,6 +1115,7 @@ BOOL LLInvFVBridge::canListOnMarketplaceNow() const
 	{
 		return FALSE;
 	}
+#endif // BLOCK_WORN_ITEMS_IN_OUTBOX
 
 	return TRUE;
 #else
@@ -1787,19 +1791,32 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
 
 static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_msg)
 {
-	bool worn = get_is_item_worn(inv_item->getUUID());
+	// Collapse links directly to items/folders
+	LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
+	LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
+	if (linked_item != NULL)
+	{
+		inv_item = linked_item;
+	}
+	
 	bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
 
 	if (!allow_transfer)
 	{
 		tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer");
+		return false;
 	}
-	else if(worn)
+
+#if BLOCK_WORN_ITEMS_IN_OUTBOX
+	bool worn = get_is_item_worn(inv_item->getUUID());
+	if (worn)
 	{
 		tooltip_msg = LLTrans::getString("TooltipOutboxWorn");
+		return false;
 	}
-	
-	return !worn && allow_transfer;
+#endif
+
+	return true;
 }
 
 
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 5fb3f15cd5..7040fef65e 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -595,32 +595,49 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
 
 void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder)
 {
-	if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
+	// Collapse links directly to items/folders
+	LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
+	LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
+	if (linked_category != NULL)
 	{
-		// when moving item directly into outbox create folder with that name
-		if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
-		{
-			dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName());
-			gInventory.notifyObservers();
-		}
-
-		copy_inventory_item(
-			gAgent.getID(),
-			inv_item->getPermissions().getOwner(),
-			inv_item->getUUID(),
-			dest_folder,
-			inv_item->getName(),
-			LLPointer<LLInventoryCallback>(NULL));
+		copy_folder_to_outbox(linked_category, dest_folder, top_level_folder);
 	}
 	else
-	{	
-		LLSD args;
-		args["ITEM_NAME"] = inv_item->getName();
-		LLSD payload;
-		payload["item_id"] = inv_item->getUUID();
-		payload["dest_folder_id"] = dest_folder;
-		payload["top_level_folder"] = top_level_folder;
-		LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2));
+	{
+		LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
+		if (linked_item != NULL)
+		{
+			inv_item = (LLInventoryItem *) linked_item;
+		}
+		
+		// Check for copy permissions
+		if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
+		{
+			// when moving item directly into outbox create folder with that name
+			if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
+			{
+				dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName());
+				gInventory.notifyObservers();
+			}
+			
+			copy_inventory_item(
+								gAgent.getID(),
+								inv_item->getPermissions().getOwner(),
+								inv_item->getUUID(),
+								dest_folder,
+								inv_item->getName(),
+								LLPointer<LLInventoryCallback>(NULL));
+		}
+		else
+		{	
+			LLSD args;
+			args["ITEM_NAME"] = inv_item->getName();
+			LLSD payload;
+			payload["item_id"] = inv_item->getUUID();
+			payload["dest_folder_id"] = dest_folder;
+			payload["top_level_folder"] = top_level_folder;
+			LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2));
+		}
 	}
 }
 
-- 
cgit v1.2.3


From 2f14bed8b2610f53c28881a9e2e19fd7a0be51fa Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 13 Dec 2011 11:40:36 -0800
Subject: EXP-1714 FIX -- Add rename option to context menu on outbox folders

---
 indra/newview/llinventorybridge.cpp | 95 ++++++++++++++++++-------------------
 1 file changed, 47 insertions(+), 48 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3f12e8b1d3..aabe851f79 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -617,7 +617,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 		}
 	}
 
-	// Don't allow items to be pasted directly into the COF or the inbox
+	// Don't allow items to be pasted directly into the COF or the inbox/outbox
 	if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder())
 	{
 		items.push_back(std::string("Paste"));
@@ -2892,6 +2892,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	}
 	else if(isOutboxFolder())
 	{
+		mItems.push_back(std::string("Rename"));
 		mItems.push_back(std::string("Delete"));
 	}
 	else if(isAgentInventory()) // do not allow creating in library
@@ -3741,29 +3742,29 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	menuentry_vec_t items;
 	menuentry_vec_t disabled_items;
 
-	if(isItemInTrash())
-	{
-		addTrashContextMenuOptions(items, disabled_items);
-	}	
-	else if(isOutboxFolder())
+	if (isOutboxFolder())
 	{
 		items.push_back(std::string("Delete"));
 	}
 	else
 	{
-		items.push_back(std::string("Share"));
-		if (!canShare())
+		if (isItemInTrash())
 		{
-			disabled_items.push_back(std::string("Share"));
-		}
-		items.push_back(std::string("Sound Open"));
-		items.push_back(std::string("Properties"));
+			addTrashContextMenuOptions(items, disabled_items);
+		}	
+		else
+		{
+			items.push_back(std::string("Share"));
+			if (!canShare())
+			{
+				disabled_items.push_back(std::string("Share"));
+			}
+			items.push_back(std::string("Sound Open"));
+			items.push_back(std::string("Properties"));
 
-		getClipboardEntries(true, items, disabled_items, flags);
-	}
+			getClipboardEntries(true, items, disabled_items, flags);
+		}
 
-	if (!isOutboxFolder())
-	{
 		items.push_back(std::string("Sound Separator"));
 		items.push_back(std::string("Sound Play"));
 	}
@@ -3799,29 +3800,29 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	menuentry_vec_t disabled_items;
 
 	lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
-	if(isItemInTrash())
-	{
-		addTrashContextMenuOptions(items, disabled_items);
-	}	
-	else if(isOutboxFolder())
+	if(isOutboxFolder())
 	{
 		items.push_back(std::string("Delete"));
 	}
 	else
 	{
-		items.push_back(std::string("Share"));
-		if (!canShare())
+		if(isItemInTrash())
 		{
-			disabled_items.push_back(std::string("Share"));
-		}
-		items.push_back(std::string("Landmark Open"));
-		items.push_back(std::string("Properties"));
+			addTrashContextMenuOptions(items, disabled_items);
+		}	
+		else
+		{
+			items.push_back(std::string("Share"));
+			if (!canShare())
+			{
+				disabled_items.push_back(std::string("Share"));
+			}
+			items.push_back(std::string("Landmark Open"));
+			items.push_back(std::string("Properties"));
 
-		getClipboardEntries(true, items, disabled_items, flags);
-	}
+			getClipboardEntries(true, items, disabled_items, flags);
+		}
 
-	if (!isOutboxFolder())
-	{
 		items.push_back(std::string("Landmark Separator"));
 		items.push_back(std::string("About Landmark"));
 	}
@@ -4354,36 +4355,35 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	menuentry_vec_t disabled_items;
 
 	lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl;
-	if(isItemInTrash())
-	{
-		addTrashContextMenuOptions(items, disabled_items);
-	}	
-	else if(isOutboxFolder())
+	if(isOutboxFolder())
 	{
 		items.push_back(std::string("Delete"));
 	}
 	else
 	{
-		items.push_back(std::string("Share"));
-		if (!canShare())
+		if(isItemInTrash())
 		{
-			disabled_items.push_back(std::string("Share"));
-		}
-		items.push_back(std::string("Animation Open"));
-		items.push_back(std::string("Properties"));
+			addTrashContextMenuOptions(items, disabled_items);
+		}	
+		else
+		{
+			items.push_back(std::string("Share"));
+			if (!canShare())
+			{
+				disabled_items.push_back(std::string("Share"));
+			}
+			items.push_back(std::string("Animation Open"));
+			items.push_back(std::string("Properties"));
 
-		getClipboardEntries(true, items, disabled_items, flags);
-	}
+			getClipboardEntries(true, items, disabled_items, flags);
+		}
 
-	if (!isOutboxFolder())
-	{
 		items.push_back(std::string("Animation Separator"));
 		items.push_back(std::string("Animation Play"));
 		items.push_back(std::string("Animation Audition"));
 	}
 
 	hide_context_entries(menu, items, disabled_items);
-
 }
 
 // virtual
@@ -5377,7 +5377,6 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 		getClipboardEntries(true, items, disabled_items, flags);
 	}
 
-
 	hide_context_entries(menu, items, disabled_items);
 }
 
-- 
cgit v1.2.3


From 4e92846cd5ca304537ef3105a880f0c14ba02e3c Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Tue, 13 Dec 2011 14:37:20 -0600
Subject: SH-1427 Fix for redundantly applying light intensity to deferred
 lights.

---
 indra/newview/pipeline.cpp | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 00acc3e511..8449e74fb6 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -7452,8 +7452,7 @@ void LLPipeline::renderDeferredLighting()
 					F32 s = volume->getLightRadius()*1.5f;
 
 					LLColor3 col = volume->getLightColor();
-					col *= volume->getLightIntensity();
-
+					
 					if (col.magVecSquared() < 0.001f)
 					{
 						continue;
@@ -7566,8 +7565,7 @@ void LLPipeline::renderDeferredLighting()
 					setupSpotLight(gDeferredSpotLightProgram, drawablep);
 					
 					LLColor3 col = volume->getLightColor();
-					col *= volume->getLightIntensity();
-
+					
 					//vertex positions are encoded so the 3 bits of their vertex index 
 					//correspond to their axis facing, with bit position 3,2,1 matching
 					//axis facing x,y,z, bit set meaning positive facing, bit clear 
@@ -7676,8 +7674,7 @@ void LLPipeline::renderDeferredLighting()
 					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
 
 					LLColor3 col = volume->getLightColor();
-					col *= volume->getLightIntensity();
-
+					
 					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
 					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
 					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
-- 
cgit v1.2.3


From a96271e3c2958a95040a1348934bd3f056f374ab Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 13 Dec 2011 13:09:53 -0800
Subject: EXP-1716 FIX -- Merchant outbox drag and drop always creates new
 folder

* Items dragged to child folder now appear under that folder rather than in new separate top-level folder.
---
 indra/newview/llinventorybridge.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index aabe851f79..3d20b99c9b 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3461,7 +3461,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			}
 			else if (move_is_into_outbox && !move_is_from_outbox)
 			{
-				copy_item_to_outbox(inv_item, outbox_id, LLUUID::null);
+				copy_item_to_outbox(inv_item, mUUID, LLUUID::null);
 			}
 			// NORMAL or TRASH folder
 			// (move the item, restamp if into trash)
-- 
cgit v1.2.3


From 0c0ff35d19969cc762dce510a4d5ee4649d96a24 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 13 Dec 2011 13:11:55 -0800
Subject: EXP-1551 FIX Ability to toggle button flashing added
 "EnableButtonFlashing" setting

---
 indra/llui/llbutton.cpp                 | 18 +++++++++++++-----
 indra/llui/lltabcontainer.cpp           | 13 +++++++------
 indra/newview/app_settings/settings.xml | 11 +++++++++++
 3 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 93d8282aa7..f0d92d597a 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -589,15 +589,23 @@ void LLButton::getOverlayImageSize(S32& overlay_width, S32& overlay_height)
 // virtual
 void LLButton::draw()
 {
+	static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true);
 	F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency();
 	bool flash = FALSE;
 
-	if( mFlashing )
+	if( mFlashing)
 	{
-		F32 elapsed = mFlashingTimer.getElapsedTimeF32();
-		S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f);
-		// flash on or off?
-		flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f);
+		if ( sEnableButtonFlashing)
+		{
+			F32 elapsed = mFlashingTimer.getElapsedTimeF32();
+			S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f);
+			// flash on or off?
+			flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f);
+		}
+		else
+		{ // otherwise just highlight button in flash color
+			flash = true;
+		}
 	}
 
 	bool pressed_by_keyboard = FALSE;
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index d5f8707381..5fc2cc350d 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -98,24 +98,25 @@ class LLCustomButtonIconCtrl : public LLButton
 {
 public:
 	struct Params
-	: public LLInitParam::Block<Params, LLButton::Params>
+	:	public LLInitParam::Block<Params, LLButton::Params>
 	{
 		// LEFT, RIGHT, TOP, BOTTOM paddings of LLIconCtrl in this class has same value
 		Optional<S32>					icon_ctrl_pad;
 
-		Params():
-		icon_ctrl_pad("icon_ctrl_pad", 1)
+		Params()
+		:	icon_ctrl_pad("icon_ctrl_pad", 1)
 		{}
 	};
 
 protected:
 	friend class LLUICtrlFactory;
-	LLCustomButtonIconCtrl(const Params& p):
-		LLButton(p),
+
+	LLCustomButtonIconCtrl(const Params& p)
+	:	LLButton(p),
 		mIcon(NULL),
 		mIconAlignment(LLFontGL::HCENTER),
 		mIconCtrlPad(p.icon_ctrl_pad)
-		{}
+	{}
 
 public:
 
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index aa8ad53a3d..1ea623791d 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1150,6 +1150,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>EnableButtonFlashing</key>
+    <map>
+      <key>Comment</key>
+      <string>Allow UI to flash buttons to get your attention</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>ButtonHPad</key>
     <map>
       <key>Comment</key>
-- 
cgit v1.2.3


From 2dc7df91ade45d8952473f7de5068e8705440e29 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Tue, 13 Dec 2011 15:23:55 -0600
Subject: SH-2743 Fix for shader compiler error on some GL 3.x implementations.

---
 indra/llrender/llshadermgr.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index ac9dc9544d..85c4bab7a9 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -579,7 +579,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 		text[count++] = strdup("#define ATTRIBUTE attribute\n");
 		text[count++] = strdup("#define VARYING varying\n");
 	}
-	else if (version < 3.f)
+	else if (version < 3.3f)
 	{
 		//set version to 1.20
 		text[count++] = strdup("#version 120\n");
-- 
cgit v1.2.3


From d7fabfee19e536dd8df356fd4531437ccb3630d5 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 13 Dec 2011 13:56:41 -0800
Subject: EXP-1715 FIX -- Merchant outbox drag and drop has offset between
 mouse position and selected folder EXP-1717 FIX -- Drag and drop within the
 outbox can result in an item created at the top level of the outbox

Folders are now created for items dragged around within the merchant outbox if their drop target is the top level outbox inventory panel itself.
---
 indra/newview/llfloateroutbox.cpp      | 22 ++++++++++++++--------
 indra/newview/llinventorybridge.cpp    |  4 ++++
 indra/newview/llinventoryfunctions.cpp | 21 ++++++++++++++++++---
 indra/newview/llinventoryfunctions.h   |  1 +
 4 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index b15380d427..eb11933368 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -248,7 +248,7 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
 	mOutboxInventoryPanel->setShape(inventory_placeholder_rect);
 	
 	// Set the sort order newest to oldest
-	mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);	
+	mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME);	
 	mOutboxInventoryPanel->getFilter()->markDefault();
 	
 	fetchOutboxContents();
@@ -340,19 +340,25 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 										EAcceptance* accept,
 										std::string& tooltip_msg)
 {
-	// Pass drag and drop to this floater to the outbox inventory control
-
 	if ((mOutboxInventoryPanel == NULL) ||
 		(mWindowShade && mWindowShade->isShown()) ||
 		LLMarketplaceInventoryImporter::getInstance()->isImportInProgress())
 	{
 		return FALSE;
 	}
-
-	S32 local_x = x - mOutboxInventoryPanel->getRect().mLeft;
-	S32 local_y = y - mOutboxInventoryPanel->getRect().mBottom;
-
-	return mOutboxInventoryPanel->handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+	
+	BOOL handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL);
+	
+	// Pass drag and drop to this floater to the outbox inventory control if no other children handle it
+	if (!handled)
+	{
+		S32 local_x = x - mOutboxInventoryPanel->getRect().mLeft;
+		S32 local_y = y - mOutboxInventoryPanel->getRect().mBottom;
+		
+		handled = mOutboxInventoryPanel->handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+	}
+	
+	return handled;
 }
 
 void LLFloaterOutbox::onImportButtonClicked()
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3d20b99c9b..4bc846faeb 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3463,6 +3463,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			{
 				copy_item_to_outbox(inv_item, mUUID, LLUUID::null);
 			}
+			else if (move_is_into_outbox && move_is_from_outbox)
+			{
+				move_item_within_outbox(inv_item, mUUID);
+			}
 			// NORMAL or TRASH folder
 			// (move the item, restamp if into trash)
 			else
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 7040fef65e..6c5325620e 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -588,7 +588,6 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
 				parent = next_parent;
 			}
 		}
-
 	}
 }
 
@@ -620,8 +619,7 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
 				gInventory.notifyObservers();
 			}
 			
-			copy_inventory_item(
-								gAgent.getID(),
+			copy_inventory_item(gAgent.getID(),
 								inv_item->getPermissions().getOwner(),
 								inv_item->getUUID(),
 								dest_folder,
@@ -641,6 +639,23 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
 	}
 }
 
+void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder)
+{
+	// when moving item directly into outbox create folder with that name
+	if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
+	{
+		dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName());
+		gInventory.notifyObservers();
+	}
+	
+	LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
+
+	change_item_parent(&gInventory,
+					   viewer_inv_item,
+					   dest_folder,
+					   false);
+}
+
 void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder)
 {
 	LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName());
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 7b452537f8..9f0ee0571a 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -75,6 +75,7 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
 void append_path(const LLUUID& id, std::string& path);
 
 void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder);
+void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder);
 
 void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder);
 
-- 
cgit v1.2.3


From bb39e3fa3cc2cd9617d63b93bcf1d6da364cd917 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 13 Dec 2011 16:42:14 -0800
Subject: EXP-1718 FIX -- Drag and drop within the outbox can result in folders
 being out of order

* Outbox updates now result in a resort to keep drag and drop items and folders properly sorted
* New icon for merchant outbox
* New behavior to accept drag and drop files over the entire merchant outbox floater
---
 indra/newview/llfloateroutbox.cpp                  |  38 ++++++++++++++-------
 indra/newview/llfolderview.cpp                     |   6 ++--
 .../default/textures/toolbar_icons/outbox.png      | Bin 2987 -> 1521 bytes
 3 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index eb11933368..984f47abb0 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -158,14 +158,6 @@ void LLFloaterOutbox::onClose(bool app_quitting)
 
 void LLFloaterOutbox::onOpen(const LLSD& key)
 {
-	//
-	// Initialize the marketplace import API
-	//
-
-	LLMarketplaceInventoryImporter::getInstance()->initialize();
-	LLMarketplaceInventoryImporter::getInstance()->setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
-	LLMarketplaceInventoryImporter::getInstance()->setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
-	
 	//
 	// Look for an outbox and set up the inventory API
 	//
@@ -224,6 +216,7 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
 	{
 		gInventory.removeObserver(mCategoryAddedObserver);
 		delete mCategoryAddedObserver;
+		mCategoryAddedObserver = NULL;
 	}
 	
 	// Create observer for outbox modifications
@@ -252,6 +245,14 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
 	mOutboxInventoryPanel->getFilter()->markDefault();
 	
 	fetchOutboxContents();
+	
+	//
+	// Initialize the marketplace import API
+	//
+	
+	LLMarketplaceInventoryImporter::getInstance()->initialize();
+	LLMarketplaceInventoryImporter::getInstance()->setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
+	LLMarketplaceInventoryImporter::getInstance()->setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
 }
 
 void LLFloaterOutbox::updateItemCount()
@@ -350,12 +351,20 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 	BOOL handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL);
 	
 	// Pass drag and drop to this floater to the outbox inventory control if no other children handle it
-	if (!handled)
+	if (!handled || (*accept == ACCEPT_NO))
 	{
-		S32 local_x = x - mOutboxInventoryPanel->getRect().mLeft;
-		S32 local_y = y - mOutboxInventoryPanel->getRect().mBottom;
+		S32 local_x;
+		S32 local_y;
+		
+		LLFolderView * outbox_root_folder = mOutboxInventoryPanel->getRootFolder();
+		localPointToOtherView(x, y, &local_x, &local_y, outbox_root_folder);
 		
-		handled = mOutboxInventoryPanel->handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+		const LLRect& outbox_rect = outbox_root_folder->getRect();
+
+		local_x = llclamp(local_x, outbox_rect.mLeft + 1, outbox_rect.mRight - 1);
+		local_y = llclamp(local_y, outbox_rect.mBottom + 1, outbox_rect.mTop - 1);
+
+		handled = outbox_root_folder->LLFolderViewFolder::handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
 	}
 	
 	return handled;
@@ -371,6 +380,11 @@ void LLFloaterOutbox::onImportButtonClicked()
 void LLFloaterOutbox::onOutboxChanged()
 {
 	llassert(!mOutboxId.isNull());
+	
+	if (mOutboxInventoryPanel)
+	{
+		mOutboxInventoryPanel->requestSort();
+	}
 
 	fetchOutboxContents();
 	updateView();
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 6ec2598e44..b8515c2953 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -1945,9 +1945,9 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 	if (!handled)
 	{
 		if (getListener()->getUUID().notNull())
-	{
-		handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
-	}
+		{
+			handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+		}
 		else
 		{
 			if (!mFolders.empty())
diff --git a/indra/newview/skins/default/textures/toolbar_icons/outbox.png b/indra/newview/skins/default/textures/toolbar_icons/outbox.png
index 9fcf46794d..0f3db1c47c 100644
Binary files a/indra/newview/skins/default/textures/toolbar_icons/outbox.png and b/indra/newview/skins/default/textures/toolbar_icons/outbox.png differ
-- 
cgit v1.2.3


From bff737ebefdfeeb17a81e1c3c4741d3e9aab2862 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 13 Dec 2011 17:03:25 -0800
Subject: EXP-1724 FIX -- Merchant outbox needs to be available from the Me
 menu

---
 indra/newview/skins/default/xui/en/menu_viewer.xml | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 1834be2d48..3c98f8e892 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -164,11 +164,18 @@
       <menu_item_separator/>
 
       <menu_item_call
-         label="Buy L$"
+         label="Buy L$..."
          name="Buy and Sell L$">
         <menu_item_call.on_click
          function="BuyCurrency" />
       </menu_item_call>
+      <menu_item_call
+         label="Merchant Outbox..."
+         name="MerchantOutbox">
+        <menu_item_call.on_click
+         function="Floater.ToggleOrBringToFront"
+         parameter="outbox" />
+      </menu_item_call>
       <menu_item_call
            label="Account dashboard..."
            name="Manage My Account">
-- 
cgit v1.2.3


From 399f8dd1913530488744046794a74d6c7e61ffa3 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 14 Dec 2011 14:37:38 -0800
Subject: EXP-1723 -- Improved drag and drop behavior for outbox floater.

---
 indra/newview/llfloateroutbox.cpp   | 36 ++++++++++++++++---------
 indra/newview/llfolderviewitem.cpp  | 52 ++++++++++++++++++++++---------------
 indra/newview/llfolderviewitem.h    |  5 ++++
 indra/newview/llinventorybridge.cpp | 10 +------
 indra/newview/llinventorybridge.h   |  2 --
 5 files changed, 61 insertions(+), 44 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 984f47abb0..725e521e58 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -30,6 +30,7 @@
 
 #include "llfloaterreg.h"
 #include "llfolderview.h"
+#include "llinventorybridge.h"
 #include "llinventorymodelbackgroundfetch.h"
 #include "llinventoryobserver.h"
 #include "llinventorypanel.h"
@@ -348,23 +349,34 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 		return FALSE;
 	}
 	
-	BOOL handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL);
+	LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+	BOOL handled = (handled_view != NULL);
 	
-	// Pass drag and drop to this floater to the outbox inventory control if no other children handle it
+	// Pass all drag and drop for this floater to the outbox inventory control
 	if (!handled || (*accept == ACCEPT_NO))
 	{
-		S32 local_x;
-		S32 local_y;
+		// Always assume we are going to move the drag and drop operation to the outbox root folder
+		bool move_to_root = true;
 		
-		LLFolderView * outbox_root_folder = mOutboxInventoryPanel->getRootFolder();
-		localPointToOtherView(x, y, &local_x, &local_y, outbox_root_folder);
-		
-		const LLRect& outbox_rect = outbox_root_folder->getRect();
-
-		local_x = llclamp(local_x, outbox_rect.mLeft + 1, outbox_rect.mRight - 1);
-		local_y = llclamp(local_y, outbox_rect.mBottom + 1, outbox_rect.mTop - 1);
+		// If the inventory panel is visible, then only override it to the outbox root if we're outside the inventory panel
+		// (otherwise the inventory panel itself will handle the drag and drop operation, without any override)
+		if (mOutboxInventoryPanel->getVisible())
+		{
+			S32 inv_x, inv_y;
+			localPointToOtherView(x, y, &inv_x, &inv_y, mOutboxInventoryPanel);
+			
+			const LLRect& inv_rect = mOutboxInventoryPanel->getRect();
 
-		handled = outbox_root_folder->LLFolderViewFolder::handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+			move_to_root = !inv_rect.pointInRect(inv_x, inv_y);
+		}
+		
+		// Handle the drag and drop directly to the root of the outbox
+		if (move_to_root)
+		{
+			LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder();
+			
+			handled = root_folder->handleDragAndDropToRoot(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+		}
 	}
 	
 	return handled;
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index f27fd035db..526800d4be 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -2276,33 +2276,16 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,
 										   EAcceptance* accept,
 										   std::string& tooltip_msg)
 {
-	LLFolderView* root_view = getRoot();
-
 	BOOL handled = FALSE;
-	if(mIsOpen)
+
+	if (mIsOpen)
 	{
-		handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
-			cargo_data, accept, tooltip_msg) != NULL;
+		handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL);
 	}
 
 	if (!handled)
 	{
-		BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data, tooltip_msg);
-
-		if (accepted) 
-		{
-			mDragAndDropTarget = TRUE;
-			*accept = ACCEPT_YES_MULTI;
-		}
-		else 
-		{
-			*accept = ACCEPT_NO;
-		}
-
-		if (!drop && accepted)
-		{
-			root_view->autoOpenTest(this);
-		}
+		handleDragAndDropToRoot(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
 
 		lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl;
 	}
@@ -2310,6 +2293,33 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,
 	return TRUE;
 }
 
+BOOL LLFolderViewFolder::handleDragAndDropToRoot(MASK mask,
+												 BOOL drop,
+												 EDragAndDropType cargo_type,
+												 void* cargo_data,
+												 EAcceptance* accept,
+												 std::string& tooltip_msg)
+{
+	BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
+	
+	if (accepted) 
+	{
+		mDragAndDropTarget = TRUE;
+		*accept = ACCEPT_YES_MULTI;
+	}
+	else 
+	{
+		*accept = ACCEPT_NO;
+	}
+	
+	if (!drop && accepted)
+	{
+		getRoot()->autoOpenTest(this);
+	}
+	
+	return TRUE;
+}
+
 
 BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask )
 {
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 3433e3f7f3..02461fb144 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -547,6 +547,11 @@ public:
 		void* cargo_data,
 		EAcceptance* accept,
 		std::string& tooltip_msg);
+	BOOL handleDragAndDropToRoot(MASK mask, BOOL drop,
+								 EDragAndDropType cargo_type,
+								 void* cargo_data,
+								 EAcceptance* accept,
+								 std::string& tooltip_msg);
 	virtual void draw();
 
 	time_t getCreationDate() const;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 4bc846faeb..d6b520d75e 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1820,14 +1820,6 @@ static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_m
 }
 
 
-
-void LLFolderBridge::dropFolderToOutbox(LLInventoryCategory* inv_cat)
-{
-	copy_folder_to_outbox(inv_cat, getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false), inv_cat->getUUID());	
-}
-
-
-
 int get_folder_levels(LLInventoryCategory* inv_cat)
 {
 	LLInventoryModel::cat_array_t* cats;
@@ -2046,7 +2038,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 			}
 			else if (move_is_into_outbox && !move_is_from_outbox)
 			{
-				dropFolderToOutbox(inv_cat);
+				copy_folder_to_outbox(inv_cat, mUUID, inv_cat->getUUID());
 			}
 			else
 			{
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 2d625befb4..126a28f74c 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -306,8 +306,6 @@ protected:
 
 	void dropToFavorites(LLInventoryItem* inv_item);
 	void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit);
-	void dropToOutbox(LLInventoryItem* inv_item);
-	void dropFolderToOutbox(LLInventoryCategory* inv_cat);
 
 	//--------------------------------------------------------------------
 	// Messy hacks for handling folder options
-- 
cgit v1.2.3


From 9fa68f0da363cd3c20dbb079f5d2901a45dfea5f Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 14 Dec 2011 17:55:36 -0600
Subject: SH-2743 Fix for shader compiler error on some GL 3.x implementations.

---
 indra/llrender/llglslshader.cpp                        |  2 +-
 indra/llrender/llglslshader.h                          |  1 +
 indra/llrender/llshadermgr.cpp                         | 18 ++++++++++++------
 .../shaders/class1/deferred/alphaSkinnedV.glsl         |  3 ---
 indra/newview/llviewershadermgr.cpp                    |  5 ++++-
 5 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 5a6f3d8292..6b2852670a 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -66,7 +66,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
 LLShaderFeatures::LLShaderFeatures()
 : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
 hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
-hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false),
+hasGamma(false), hasLighting(false), isAlphaLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false),
 hasAlphaMask(false)
 {
 }
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 2a6c050eac..00b4b0dbd4 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -36,6 +36,7 @@ public:
 	bool calculatesLighting;
 	bool calculatesAtmospherics;
 	bool hasLighting; // implies no transport (it's possible to have neither though)
+	bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions)
 	bool isShiny;
 	bool isFullbright; // implies no lighting
 	bool isSpecular;
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 85c4bab7a9..1a03aeebb7 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -107,10 +107,13 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			{
 				return FALSE;
 			}
-			
-			if (!shader->attachObject("lighting/sumLightsSpecularV.glsl"))
+		
+			if (!features->isAlphaLighting)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/sumLightsSpecularV.glsl"))
+				{
+					return FALSE;
+				}
 			}
 			
 			if (!shader->attachObject("lighting/lightSpecularV.glsl"))
@@ -125,9 +128,12 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 				return FALSE;
 			}
 			
-			if (!shader->attachObject("lighting/sumLightsV.glsl"))
+			if (!features->isAlphaLighting)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/sumLightsV.glsl"))
+				{
+					return FALSE;
+				}
 			}
 			
 			if (!shader->attachObject("lighting/lightV.glsl"))
@@ -296,7 +302,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 				}
 				shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
 			}
-		}		
+		}
 	}
 	
 	// NOTE order of shader object attaching is VERY IMPORTANT!!!
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
index b09441f7eb..0170ad4b55 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
@@ -30,7 +30,6 @@ ATTRIBUTE vec3 normal;
 ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec2 texcoord0;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 mat4 getObjectSkinnedTransform();
 void calcAtmospherics(vec3 inPositionEye);
 
@@ -38,8 +37,6 @@ float calcDirectionalLight(vec3 n, vec3 l);
 
 vec3 atmosAmbient(vec3 light);
 vec3 atmosAffectDirectionalLight(float lightIntensity);
-vec3 scaleDownLight(vec3 light);
-vec3 scaleUpLight(vec3 light);
 
 VARYING vec3 vary_position;
 VARYING vec3 vary_ambient;
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index bddc07b395..5de363e03c 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -1103,11 +1103,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader";
 		gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true;
-		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true;
 		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1235,6 +1236,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
 		gDeferredAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
 		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
 		{
@@ -1398,6 +1400,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true;
 		gDeferredAvatarAlphaProgram.mShaderFiles.clear();
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB));
-- 
cgit v1.2.3


From 90e6336b27ae962052a68ec17205e7b1f87bdb4e Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 15 Dec 2011 09:51:26 -0800
Subject: EXP-1725 FIX -- Carriage return or tab characters shown in Outbox
 text on Windows

* Removed tabs from outbox strings.
---
 indra/newview/skins/default/xui/en/strings.xml | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index d8da56d338..b83571a106 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2039,18 +2039,18 @@ Returns a string with the requested data about the region
 	<string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace.</string>
 	<string name="InventoryOutboxNotMerchantTooltip">Become a merchant!</string>
 	<string name="InventoryOutboxNotMerchant">
-	The Second Life Marketplace offers more than one million virtual products for sale, all of them created by Residents like you.  You too can create items and sell them on the Marketplace.  Creating a store is easy and free of charge.
-	
-	[[MARKETPLACE_URL] Visit the Marketplace]
+The Second Life Marketplace offers more than one million virtual products for sale, all of them created by Residents like you.  You too can create items and sell them on the Marketplace.  Creating a store is easy and free of charge.
+
+[[MARKETPLACE_URL] Visit the Marketplace]
 
-	[[MARKETPLACE_LEARN_MORE_URL] Learn more about creating a store]
+[[MARKETPLACE_LEARN_MORE_URL] Learn more about creating a store]
 	</string>
 	<string name="InventoryOutboxNoItemsTitle">Your outbox is empty.</string>
 	<string name="InventoryOutboxNoItemsTooltip">Drag and drop items here to prepare them for sale on the Marketplace</string>
 	<string name="InventoryOutboxNoItems">
-	Drag folders to this area.  When you are ready to send them to the Marketplace for sale, click the "Send to Marketplace" button below.
-	
-	[[MARKETPLACE_DASHBOARD_URL] Go to your Merchant Dashboard]
+Drag folders to this area.  When you are ready to send them to the Marketplace for sale, click the "Send to Marketplace" button below.
+
+[[MARKETPLACE_DASHBOARD_URL] Go to your Merchant Dashboard]
 	</string>
 
 	<string name="Marketplace Error None">No errors</string>
-- 
cgit v1.2.3


From 2e564abcd682c348de3a2d3a50ef58df545c143b Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 15 Dec 2011 14:26:42 -0800
Subject: EXP-1730 FIX EXP-1731 FIX EXP-1735 FIX EXP-1736 FIX EXP-1737 FIX
 EXP-1738 FIX EXP-1739 FIX

* Users can no longer drag and drop items to the outbox from in world, notecards or the library.
* Drag and drop now blocks the creation of hierarchies that are too deep, too many folders or contain too many items.
* Settings now exist to specify drag and drop limitations to the outbox, named:
       InventoryOutboxMaxFolderDepth (4)
       InventoryOutboxMaxFolderCount (20)
       InventoryOutboxMaxItemCount (200)
---
 indra/newview/app_settings/settings.xml        |  32 +++-
 indra/newview/llinventorybridge.cpp            | 208 ++++++++++++++++++-------
 indra/newview/llinventorymodel.cpp             |  32 ++++
 indra/newview/llinventorymodel.h               |   3 +
 indra/newview/skins/default/xui/en/strings.xml |   2 +
 5 files changed, 214 insertions(+), 63 deletions(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index aa8ad53a3d..a6d859aab2 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4260,16 +4260,38 @@
 		<key>Value</key>
 		<integer>0</integer>
 	</map>
-    <key>InventoryMarketplaceUserStatus</key>
+    <key>InventoryOutboxMaxFolderCount</key>
     <map>
       <key>Comment</key>
-      <string>Marketplace user status.</string>
+      <string>Maximum number of subfolders allowed in a listing in the merchant outbox.</string>
       <key>Persist</key>
-      <integer>1</integer>
+      <integer>0</integer>
       <key>Type</key>
-      <string>String</string>
+      <string>U32</string>
       <key>Value</key>
-      <string />
+      <integer>20</integer>
+    </map>
+    <key>InventoryOutboxMaxFolderDepth</key>
+    <map>
+      <key>Comment</key>
+      <string>Maximum number of nested levels of subfolders allowed in a listing in the merchant outbox.</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>4</integer>
+    </map>
+    <key>InventoryOutboxMaxItemCount</key>
+    <map>
+      <key>Comment</key>
+      <string>Maximum number of items allowed in a listing in the merchant outbox.</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>200</integer>
     </map>
     <key>InventorySortOrder</key>
     <map>
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index d6b520d75e..26e7dab270 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1815,7 +1815,7 @@ static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_m
 		return false;
 	}
 #endif
-
+	
 	return true;
 }
 
@@ -1874,28 +1874,28 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 	if (!isAgentAvatarValid()) return FALSE;
 	if (!isAgentInventory()) return FALSE; // cannot drag categories into library
 
+	const LLUUID &cat_id = inv_cat->getUUID();
+	const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+	const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+	
+	const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+	const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); 
+	const BOOL move_is_from_outbox = model->isObjectDescendentOf(cat_id, outbox_id);
 
 	// check to make sure source is agent inventory, and is represented there.
 	LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
-	const BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
+	const BOOL is_agent_inventory = (model->getCategory(cat_id) != NULL)
 		&& (LLToolDragAndDrop::SOURCE_AGENT == source);
 
-	const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
-	const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
-
 	BOOL accept = FALSE;
 	if (is_agent_inventory)
 	{
-		const LLUUID &cat_id = inv_cat->getUUID();
 		const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false);
 		const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
-		const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
 
 		const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
 		const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT);
 		const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
-		const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); 
-		const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_cat->getUUID(), outbox_id);
 
 		//--------------------------------------------------------------------------------
 		// Determine if folder can be moved.
@@ -1950,24 +1950,58 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 		}
 		if (move_is_into_outbox)
 		{
-			for (S32 i=0; i < descendent_items.count(); ++i)
+			int nested_folder_levels = (get_folder_path_length(outbox_id, mUUID) - 1) + get_folder_levels(inv_cat);
+			
+			if (nested_folder_levels >= gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"))
 			{
-				LLInventoryItem* item = descendent_items[i];
-				if (!can_move_to_outbox(item, tooltip_msg))
-				{
-					is_movable = FALSE;
-					break; 
-				}
+				tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels");
+				is_movable = FALSE;
 			}
+			else
+			{
+				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
+				
+				int existing_item_count = 0;
+				int existing_folder_count = 0;
+				
+				if (master_folder != NULL)
+				{
+					LLInventoryModel::cat_array_t existing_categories;
+					LLInventoryModel::item_array_t existing_items;
 
-			int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat);
+					gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE);
+					
+					existing_item_count = existing_items.count();
+					existing_folder_count = existing_categories.count();
+				}
 
-			if (nested_folder_levels > 4)
-			{
-				tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels");
-				is_movable = FALSE;
+				const int nested_folder_count = existing_folder_count + descendent_categories.count();
+				const int nested_item_count = existing_item_count + descendent_items.count();
+				
+				if (nested_folder_count >= gSavedSettings.getU32("InventoryOutboxMaxFolderCount"))
+				{
+					tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders");
+					is_movable = FALSE;
+				}
+				else if (nested_item_count >= gSavedSettings.getU32("InventoryOutboxMaxItemCount"))
+				{
+					tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects");
+					is_movable = FALSE;
+				}
+				
+				if (is_movable == TRUE);
+				{
+					for (S32 i=0; i < descendent_items.count(); ++i)
+					{
+						LLInventoryItem* item = descendent_items[i];
+						if (!can_move_to_outbox(item, tooltip_msg))
+						{
+							is_movable = FALSE;
+							break; 
+						}
+					}
+				}
 			}
-			
 		}
 
 		// 
@@ -2008,7 +2042,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 						// Recursively create links in target outfit.
 						LLInventoryModel::cat_array_t cats;
 						LLInventoryModel::item_array_t items;
-						gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
+						gInventory.collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
 						LLAppearanceMgr::instance().linkAll(mUUID,items,NULL);
 					}
 				}
@@ -2026,7 +2060,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 						const std::string empty_description = "";
 						link_inventory_item(
 							gAgent.getID(),
-							inv_cat->getUUID(),
+							cat_id,
 							mUUID,
 							inv_cat->getName(),
 							empty_description,
@@ -2038,13 +2072,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 			}
 			else if (move_is_into_outbox && !move_is_from_outbox)
 			{
-				copy_folder_to_outbox(inv_cat, mUUID, inv_cat->getUUID());
+				copy_folder_to_outbox(inv_cat, mUUID, cat_id);
 			}
 			else
 			{
-				if (gInventory.isObjectDescendentOf(inv_cat->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
+				if (gInventory.isObjectDescendentOf(cat_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
 				{
-					set_dad_inbox_object(inv_cat->getUUID());
+					set_dad_inbox_object(cat_id);
 				}
 
 				// Reparent the folder and restamp children if it's moving
@@ -2059,15 +2093,28 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 	}
 	else if (LLToolDragAndDrop::SOURCE_WORLD == source)
 	{
-		// content category has same ID as object itself
-		LLUUID object_id = inv_cat->getUUID();
-		LLUUID category_id = mUUID;
-		accept = move_inv_category_world_to_agent(object_id, category_id, drop);
+		if (move_is_into_outbox)
+		{
+			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+			accept = FALSE;
+		}
+		else
+		{
+			accept = move_inv_category_world_to_agent(cat_id, mUUID, drop);
+		}
 	}
 	else if (LLToolDragAndDrop::SOURCE_LIBRARY == source)
 	{
-		// Accept folders that contain complete outfits.
-		accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(inv_cat->getUUID());
+		if (move_is_into_outbox)
+		{
+			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNoTransferLibrary");
+			accept = FALSE;
+		}
+		else
+		{
+			// Accept folders that contain complete outfits.
+			accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(cat_id);
+		}		
 
 		if (accept && drop)
 		{
@@ -3317,8 +3364,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 {
 	LLInventoryModel* model = getInventoryModel();
 
-	if(!model || !inv_item) return FALSE;
-	if(!isAgentInventory()) return FALSE; // cannot drag into library
+	if (!model || !inv_item) return FALSE;
+	if (!isAgentInventory()) return FALSE; // cannot drag into library
 	if (!isAgentAvatarValid()) return FALSE;
 
 	const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
@@ -3386,10 +3433,14 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		accept = TRUE;
 
 		if (!is_movable) 
+		{
 			accept = FALSE;
-		if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites)
+		}
+		else if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites)
+		{
 			accept = FALSE;
-		if (move_is_into_current_outfit || move_is_into_outfit)
+		}
+		else if (move_is_into_current_outfit || move_is_into_outfit)
 		{
 			accept = can_move_to_outfit(inv_item, move_is_into_current_outfit);
 		}
@@ -3400,9 +3451,32 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		else if (move_is_into_outbox)
 		{
 			accept = can_move_to_outbox(inv_item, tooltip_msg);
+			
+			if (accept)
+			{
+				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
+				
+				int existing_item_count = 0;
+				
+				if (master_folder != NULL)
+				{
+					LLInventoryModel::cat_array_t existing_categories;
+					LLInventoryModel::item_array_t existing_items;
+					
+					gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE);
+					
+					existing_item_count = existing_items.count();
+				}
+				
+				if (existing_item_count >= gSavedSettings.getU32("InventoryOutboxMaxItemCount"))
+				{
+					tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects");
+					accept = FALSE;
+				}
+			}
 		}
 
-		if(accept && drop)
+		if (accept && drop)
 		{
 			if (inv_item->getType() == LLAssetType::AT_GESTURE
 				&& LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
@@ -3451,13 +3525,16 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			{
 				dropToOutfit(inv_item, move_is_into_current_outfit);
 			}
-			else if (move_is_into_outbox && !move_is_from_outbox)
+			else if (move_is_into_outbox)
 			{
-				copy_item_to_outbox(inv_item, mUUID, LLUUID::null);
-			}
-			else if (move_is_into_outbox && move_is_from_outbox)
-			{
-				move_item_within_outbox(inv_item, mUUID);
+				if (move_is_from_outbox)
+				{
+					move_item_within_outbox(inv_item, mUUID);
+				}
+				else
+				{
+					copy_item_to_outbox(inv_item, mUUID, LLUUID::null);
+				}
 			}
 			// NORMAL or TRASH folder
 			// (move the item, restamp if into trash)
@@ -3478,7 +3555,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 
 			// 
 			//--------------------------------------------------------------------------------
-
 		}
 	}
 	else if (LLToolDragAndDrop::SOURCE_WORLD == source)
@@ -3487,7 +3563,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		// anonymous objects, it would be possible to bypass
 		// permissions.
 		object = gObjectList.findObject(inv_item->getParentUUID());
-		if(!object)
+		if (!object)
 		{
 			llinfos << "Object not found for drop." << llendl;
 			return FALSE;
@@ -3497,10 +3573,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		// move/copy this item.
 		LLPermissions perm(inv_item->getPermissions());
 		BOOL is_move = FALSE;
-		if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
+		if ((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
 			&& perm.allowTransferTo(gAgent.getID())))
 			// || gAgent.isGodlike())
-
 		{
 			accept = TRUE;
 		}
@@ -3516,7 +3591,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		// Don't allow placing an original item into Current Outfit or an outfit folder
 		// because they must contain only links to wearable items.
 		// *TODO: Probably we should create a link to an item if it was dragged to outfit or COF.
-		if(move_is_into_current_outfit || move_is_into_outfit)
+		if (move_is_into_current_outfit || move_is_into_outfit)
 		{
 			accept = FALSE;
 		}
@@ -3527,8 +3602,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		{
 			accept = FALSE;
 		}
-
-		if(drop && accept)
+		else if (move_is_into_outbox)
+		{
+			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+			accept = FALSE;
+		}
+		
+		if (accept && drop)
 		{
 			LLMoveInv* move_inv = new LLMoveInv;
 			move_inv->mObjectID = inv_item->getParentUUID();
@@ -3550,15 +3630,22 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 				LLNotifications::instance().forceResponse(params, 0);
 			}
 		}
-
 	}
 	else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
 	{
-		// Don't allow placing an original item from a notecard to Current Outfit or an outfit folder
-		// because they must contain only links to wearable items.
-		accept = !(move_is_into_current_outfit || move_is_into_outfit);
-
-		if(accept && drop)
+		if (move_is_into_outbox)
+		{
+			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+			accept = FALSE;
+		}
+		else
+		{
+			// Don't allow placing an original item from a notecard to Current Outfit or an outfit folder
+			// because they must contain only links to wearable items.
+			accept = !(move_is_into_current_outfit || move_is_into_outfit);
+		}
+		
+		if (accept && drop)
 		{
 			copy_inventory_from_notecard(mUUID,  // Drop to the chosen destination folder
 										 LLToolDragAndDrop::getInstance()->getObjectID(),
@@ -3573,7 +3660,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		{
 			accept = TRUE;
 
-			if (move_is_into_current_outfit || move_is_into_outfit)
+			if (move_is_into_outbox)
+			{
+				tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+				accept = FALSE;
+			}
+			else if (move_is_into_current_outfit || move_is_into_outfit)
 			{
 				accept = can_move_to_outfit(inv_item, move_is_into_current_outfit);
 			}
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index dc25689fa3..2fb9c53857 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -217,6 +217,38 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons
 	return NULL;
 }
 
+//
+// Search up the parent chain until we get to the specified parent, then return the first child category under it
+//
+const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LLUUID& master_parent_id, const LLUUID& obj_id) const
+{
+	if (master_parent_id == obj_id)
+	{
+		return NULL;
+	}
+
+	const LLViewerInventoryCategory* current_cat = getCategory(obj_id);
+
+	if (current_cat == NULL)
+	{
+		current_cat = getCategory(getObject(obj_id)->getParentUUID());
+	}
+	
+	while (current_cat != NULL)
+	{
+		const LLUUID& current_parent_id = current_cat->getParentUUID();
+		
+		if (current_parent_id == master_parent_id)
+		{
+			return current_cat;
+		}
+		
+		current_cat = getCategory(current_parent_id);
+	}
+
+	return NULL;
+}
+
 // Get the object by id. Returns NULL if not found.
 LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const
 {
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 340c1b0c22..1740c4151d 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -238,6 +238,9 @@ public:
 	
 	// Get whatever special folder this object is a child of, if any.
 	const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const;
+	
+	// Get first descendant of the child object under the specified parent
+	const LLViewerInventoryCategory *getFirstDescendantOf(const LLUUID& master_parent_id, const LLUUID& obj_id) const;
 
 	// Get the object by id. Returns NULL if not found.
 	//   NOTE: Use the pointer returned for read operations - do
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b83571a106..0d9a7e5c41 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -165,8 +165,10 @@ Please try logging in again in a minute.</string>
 	<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
 	<string name="TooltipPrice" value="L$[AMOUNT]: "/>
 	<string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred to another user.</string>
+	<string name="TooltipOutboxNotInInventory">You can only transfer objects in your inventory to your merchant outbox.</string>
 	<string name="TooltipOutboxWorn">You are wearing one or more of these objects. Remove them from your avatar and try moving them again.</string>
 	<string name="TooltipOutboxFolderLevels">This folder has too many levels of subfolders. Rearrange the interior folders to a maximum of 4 levels deep (Root Folder contains A contains B contains C).</string>
+	<string name="TooltipOutboxTooManyFolders">This folder has too many subfolders. Reorganize the interior to a maximum of 20 folders.</string>
 	<string name="TooltipOutboxTooManyObjects">This folder contains more than 200 objects. Box some of the items to reduce the object count.</string>
 	
 	<!-- tooltips for Urls -->
-- 
cgit v1.2.3


From b6af1b47f15992b60ddb4c718f03ae6d2040cc19 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 15 Dec 2011 15:09:02 -0800
Subject: Windows build fix and fixes for off-by-1 errors in limitations

---
 indra/newview/llinventorybridge.cpp | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 26e7dab270..64b5a9deba 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1950,9 +1950,9 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 		}
 		if (move_is_into_outbox)
 		{
-			int nested_folder_levels = (get_folder_path_length(outbox_id, mUUID) - 1) + get_folder_levels(inv_cat);
+			int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat);
 			
-			if (nested_folder_levels >= gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"))
+			if (nested_folder_levels > gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"))
 			{
 				tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels");
 				is_movable = FALSE;
@@ -1962,7 +1962,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
 				
 				int existing_item_count = 0;
-				int existing_folder_count = 0;
+				int existing_folder_count = 1;  // +1 for this folder being dragged now
 				
 				if (master_folder != NULL)
 				{
@@ -1971,25 +1971,25 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 
 					gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE);
 					
-					existing_item_count = existing_items.count();
-					existing_folder_count = existing_categories.count();
+					existing_item_count += existing_items.count();
+					existing_folder_count += existing_categories.count();
 				}
 
 				const int nested_folder_count = existing_folder_count + descendent_categories.count();
 				const int nested_item_count = existing_item_count + descendent_items.count();
 				
-				if (nested_folder_count >= gSavedSettings.getU32("InventoryOutboxMaxFolderCount"))
+				if (nested_folder_count > gSavedSettings.getU32("InventoryOutboxMaxFolderCount"))
 				{
 					tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders");
 					is_movable = FALSE;
 				}
-				else if (nested_item_count >= gSavedSettings.getU32("InventoryOutboxMaxItemCount"))
+				else if (nested_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount"))
 				{
 					tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects");
 					is_movable = FALSE;
 				}
 				
-				if (is_movable == TRUE);
+				if (is_movable == TRUE)
 				{
 					for (S32 i=0; i < descendent_items.count(); ++i)
 					{
@@ -3456,7 +3456,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			{
 				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
 				
-				int existing_item_count = 0;
+				int existing_item_count = 1; // +1 for this item being dragged now
 				
 				if (master_folder != NULL)
 				{
@@ -3465,10 +3465,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 					
 					gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE);
 					
-					existing_item_count = existing_items.count();
+					existing_item_count += existing_items.count();
 				}
 				
-				if (existing_item_count >= gSavedSettings.getU32("InventoryOutboxMaxItemCount"))
+				if (existing_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount"))
 				{
 					tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects");
 					accept = FALSE;
-- 
cgit v1.2.3


From da94592d00ae5099c181050c7415a91ae0bff4f6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 15 Dec 2011 15:39:54 -0800
Subject: dummy commit to fix TeamCity

---
 indra/newview/skins/paths.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/skins/paths.xml b/indra/newview/skins/paths.xml
index e6d68488ea..3c0da041c7 100644
--- a/indra/newview/skins/paths.xml
+++ b/indra/newview/skins/paths.xml
@@ -1,4 +1,4 @@
-<paths>
+<paths> 
 	<directory>
     <subdir>xui</subdir>
     <subdir>en</subdir>
-- 
cgit v1.2.3


From f1edfc73efa526735b2a80d47e2381a2b46295df Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 15 Dec 2011 16:21:35 -0800
Subject: EXP-1726 FIX -- Rename option present in context menu when selecting
 multiple folders in Outbox

---
 indra/newview/llinventorybridge.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 64b5a9deba..adf1d6254d 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2933,10 +2933,15 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	{
 		mItems.push_back(std::string("Rename"));
 		mItems.push_back(std::string("Delete"));
+		
+		if ((flags & FIRST_SELECTED_ITEM) == 0)
+		{
+			mDisabledItems.push_back(std::string("Rename"));
+		}
 	}
 	else if(isAgentInventory()) // do not allow creating in library
 	{
-		LLViewerInventoryCategory *cat =  getCategory();
+		LLViewerInventoryCategory *cat = getCategory();
 		// BAP removed protected check to re-enable standard ops in untyped folders.
 		// Not sure what the right thing is to do here.
 		if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
-- 
cgit v1.2.3


From 4ec112bfce19d4bf09ef79b3b3195dda24148730 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 15 Dec 2011 21:39:48 -0700
Subject: fix for SH-2738 and SH-2777, might also help SH-2723: heap corruption
 SH-2738: Texture fetching freezes due to LLcurl SH-2777: viewer crashed on
 logout in LLCurl::Easy::releaseEasyHandle

---
 indra/llcommon/llthread.h  |  7 ++++--
 indra/llmessage/llcurl.cpp | 63 ++++++++++++++++++++++++++++------------------
 indra/llmessage/llcurl.h   |  2 ++
 3 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 40291a2569..f0e0de6173 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -187,11 +187,14 @@ public:
 	LLMutexLock(LLMutex* mutex)
 	{
 		mMutex = mutex;
-		mMutex->lock();
+		
+		if(mMutex)
+			mMutex->lock();
 	}
 	~LLMutexLock()
 	{
-		mMutex->unlock();
+		if(mMutex)
+			mMutex->unlock();
 	}
 private:
 	LLMutex* mMutex;
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index ce0632668c..874f4673ca 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -219,11 +219,15 @@ namespace boost
 
 std::set<CURL*> LLCurl::Easy::sFreeHandles;
 std::set<CURL*> LLCurl::Easy::sActiveHandles;
+LLMutex* LLCurl::Easy::sHandleMutexp = NULL ;
 
 //static
 CURL* LLCurl::Easy::allocEasyHandle()
 {
 	CURL* ret = NULL;
+
+	LLMutexLock lock(sHandleMutexp) ;
+
 	if (sFreeHandles.empty())
 	{
 		ret = curl_easy_init();
@@ -251,6 +255,7 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle)
 		llerrs << "handle cannot be NULL!" << llendl;
 	}
 
+	LLMutexLock lock(sHandleMutexp) ;
 	if (sActiveHandles.find(handle) != sActiveHandles.end())
 	{
 		sActiveHandles.erase(handle);
@@ -519,7 +524,8 @@ LLCurl::Multi::Multi()
 	  mState(STATE_READY),
 	  mDead(FALSE),
 	  mMutexp(NULL),
-	  mDeletionMutexp(NULL)
+	  mDeletionMutexp(NULL),
+	  mEasyMutexp(NULL)
 {
 	mCurlMultiHandle = curl_multi_init();
 	if (!mCurlMultiHandle)
@@ -534,6 +540,7 @@ LLCurl::Multi::Multi()
 	{
 		mMutexp = new LLMutex(NULL) ;
 		mDeletionMutexp = new LLMutex(NULL) ;
+		mEasyMutexp = new LLMutex(NULL) ;
 	}
 	LLCurl::getCurlThread()->addMulti(this) ;
 
@@ -563,6 +570,8 @@ LLCurl::Multi::~Multi()
 	mMutexp = NULL ;
 	delete mDeletionMutexp ;
 	mDeletionMutexp = NULL ;
+	delete mEasyMutexp ;
+	mEasyMutexp = NULL ;
 
 	--gCurlMultiCount;
 }
@@ -585,17 +594,9 @@ void LLCurl::Multi::unlock()
 
 void LLCurl::Multi::markDead()
 {
-	if(mDeletionMutexp)
-	{
-		mDeletionMutexp->lock() ;
-	}
-
+	LLMutexLock lock(mDeletionMutexp) ;
+	
 	mDead = TRUE ;
-
-	if(mDeletionMutexp)
-	{
-		mDeletionMutexp->unlock() ;
-	}
 }
 
 void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
@@ -655,10 +656,8 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
 //return true if dead
 bool LLCurl::Multi::doPerform()
 {
-	if(mDeletionMutexp)
-	{
-		mDeletionMutexp->lock() ;
-	}
+	LLMutexLock lock(mDeletionMutexp) ;
+	
 	bool dead = mDead ;
 
 	if(mDead)
@@ -675,6 +674,7 @@ bool LLCurl::Multi::doPerform()
 				call_count < MULTI_PERFORM_CALL_REPEAT;
 				call_count++)
 		{
+			LLMutexLock lock(mMutexp) ;
 			CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
 			if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
 			{
@@ -688,11 +688,6 @@ bool LLCurl::Multi::doPerform()
 		setState(STATE_COMPLETED) ;
 	}
 
-	if(mDeletionMutexp)
-	{
-		mDeletionMutexp->unlock() ;
-	}
-
 	return dead ;
 }
 
@@ -743,19 +738,21 @@ S32 LLCurl::Multi::process()
 
 LLCurl::Easy* LLCurl::Multi::allocEasy()
 {
-	Easy* easy = 0;
+	Easy* easy = 0;	
 
 	if (mEasyFreeList.empty())
-	{
+	{		
 		easy = Easy::getEasy();
 	}
 	else
 	{
+		LLMutexLock lock(mEasyMutexp) ;
 		easy = *(mEasyFreeList.begin());
 		mEasyFreeList.erase(easy);
 	}
 	if (easy)
 	{
+		LLMutexLock lock(mEasyMutexp) ;
 		mEasyActiveList.insert(easy);
 		mEasyActiveMap[easy->getCurlHandle()] = easy;
 	}
@@ -764,6 +761,7 @@ LLCurl::Easy* LLCurl::Multi::allocEasy()
 
 bool LLCurl::Multi::addEasy(Easy* easy)
 {
+	LLMutexLock lock(mMutexp) ;
 	CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle());
 	check_curl_multi_code(mcode);
 	//if (mcode != CURLM_OK)
@@ -776,22 +774,30 @@ bool LLCurl::Multi::addEasy(Easy* easy)
 
 void LLCurl::Multi::easyFree(Easy* easy)
 {
+	mEasyMutexp->lock() ;
 	mEasyActiveList.erase(easy);
 	mEasyActiveMap.erase(easy->getCurlHandle());
+
 	if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE)
-	{
-		easy->resetState();
+	{		
 		mEasyFreeList.insert(easy);
+		mEasyMutexp->unlock() ;
+
+		easy->resetState();
 	}
 	else
 	{
+		mEasyMutexp->unlock() ;
 		delete easy;
 	}
 }
 
 void LLCurl::Multi::removeEasy(Easy* easy)
 {
-	check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
+	{
+		LLMutexLock lock(mMutexp) ;
+		check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
+	}
 	easyFree(easy);
 }
 
@@ -1290,6 +1296,10 @@ void LLCurl::initClass(bool multi_threaded)
 #endif
 
 	sCurlThread = new LLCurlThread(multi_threaded) ;
+	if(multi_threaded)
+	{
+		Easy::sHandleMutexp = new LLMutex(NULL) ;
+	}
 }
 
 void LLCurl::cleanupClass()
@@ -1319,6 +1329,9 @@ void LLCurl::cleanupClass()
 
 	Easy::sFreeHandles.clear();
 
+	delete Easy::sHandleMutexp ;
+	Easy::sHandleMutexp = NULL ;
+
 	llassert(Easy::sActiveHandles.empty());
 }
 
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 2c95279438..eb814bc608 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -253,6 +253,7 @@ private:
 
 	static std::set<CURL*> sFreeHandles;
 	static std::set<CURL*> sActiveHandles;
+	static LLMutex*        sHandleMutexp ;
 };
 
 class LLCurl::Multi
@@ -316,6 +317,7 @@ private:
 	BOOL mDead ;
 	LLMutex* mMutexp ;
 	LLMutex* mDeletionMutexp ;
+	LLMutex* mEasyMutexp ;
 };
 
 class LLCurlThread : public LLQueuedThread
-- 
cgit v1.2.3


From efec138037d7271effd89536d824bec270985909 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 15 Dec 2011 21:39:48 -0700
Subject: fix for SH-2738 and SH-2777, might also help SH-2723: heap corruption
 SH-2738: Texture fetching freezes due to LLcurl SH-2777: viewer crashed on
 logout in LLCurl::Easy::releaseEasyHandle

---
 indra/llcommon/llthread.h  |  7 ++++--
 indra/llmessage/llcurl.cpp | 63 ++++++++++++++++++++++++++++------------------
 indra/llmessage/llcurl.h   |  2 ++
 3 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 40291a2569..f0e0de6173 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -187,11 +187,14 @@ public:
 	LLMutexLock(LLMutex* mutex)
 	{
 		mMutex = mutex;
-		mMutex->lock();
+		
+		if(mMutex)
+			mMutex->lock();
 	}
 	~LLMutexLock()
 	{
-		mMutex->unlock();
+		if(mMutex)
+			mMutex->unlock();
 	}
 private:
 	LLMutex* mMutex;
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 7ca25d07fc..d86bf7a0a1 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -219,11 +219,15 @@ namespace boost
 
 std::set<CURL*> LLCurl::Easy::sFreeHandles;
 std::set<CURL*> LLCurl::Easy::sActiveHandles;
+LLMutex* LLCurl::Easy::sHandleMutexp = NULL ;
 
 //static
 CURL* LLCurl::Easy::allocEasyHandle()
 {
 	CURL* ret = NULL;
+
+	LLMutexLock lock(sHandleMutexp) ;
+
 	if (sFreeHandles.empty())
 	{
 		ret = curl_easy_init();
@@ -251,6 +255,7 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle)
 		llerrs << "handle cannot be NULL!" << llendl;
 	}
 
+	LLMutexLock lock(sHandleMutexp) ;
 	if (sActiveHandles.find(handle) != sActiveHandles.end())
 	{
 		sActiveHandles.erase(handle);
@@ -519,7 +524,8 @@ LLCurl::Multi::Multi()
 	  mState(STATE_READY),
 	  mDead(FALSE),
 	  mMutexp(NULL),
-	  mDeletionMutexp(NULL)
+	  mDeletionMutexp(NULL),
+	  mEasyMutexp(NULL)
 {
 	mCurlMultiHandle = curl_multi_init();
 	if (!mCurlMultiHandle)
@@ -534,6 +540,7 @@ LLCurl::Multi::Multi()
 	{
 		mMutexp = new LLMutex(NULL) ;
 		mDeletionMutexp = new LLMutex(NULL) ;
+		mEasyMutexp = new LLMutex(NULL) ;
 	}
 	LLCurl::getCurlThread()->addMulti(this) ;
 
@@ -563,6 +570,8 @@ LLCurl::Multi::~Multi()
 	mMutexp = NULL ;
 	delete mDeletionMutexp ;
 	mDeletionMutexp = NULL ;
+	delete mEasyMutexp ;
+	mEasyMutexp = NULL ;
 
 	--gCurlMultiCount;
 }
@@ -585,17 +594,9 @@ void LLCurl::Multi::unlock()
 
 void LLCurl::Multi::markDead()
 {
-	if(mDeletionMutexp)
-	{
-		mDeletionMutexp->lock() ;
-	}
-
+	LLMutexLock lock(mDeletionMutexp) ;
+	
 	mDead = TRUE ;
-
-	if(mDeletionMutexp)
-	{
-		mDeletionMutexp->unlock() ;
-	}
 }
 
 void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
@@ -655,10 +656,8 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
 //return true if dead
 bool LLCurl::Multi::doPerform()
 {
-	if(mDeletionMutexp)
-	{
-		mDeletionMutexp->lock() ;
-	}
+	LLMutexLock lock(mDeletionMutexp) ;
+	
 	bool dead = mDead ;
 
 	if(mDead)
@@ -675,6 +674,7 @@ bool LLCurl::Multi::doPerform()
 				call_count < MULTI_PERFORM_CALL_REPEAT;
 				call_count++)
 		{
+			LLMutexLock lock(mMutexp) ;
 			CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
 			if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
 			{
@@ -688,11 +688,6 @@ bool LLCurl::Multi::doPerform()
 		setState(STATE_COMPLETED) ;
 	}
 
-	if(mDeletionMutexp)
-	{
-		mDeletionMutexp->unlock() ;
-	}
-
 	return dead ;
 }
 
@@ -743,19 +738,21 @@ S32 LLCurl::Multi::process()
 
 LLCurl::Easy* LLCurl::Multi::allocEasy()
 {
-	Easy* easy = 0;
+	Easy* easy = 0;	
 
 	if (mEasyFreeList.empty())
-	{
+	{		
 		easy = Easy::getEasy();
 	}
 	else
 	{
+		LLMutexLock lock(mEasyMutexp) ;
 		easy = *(mEasyFreeList.begin());
 		mEasyFreeList.erase(easy);
 	}
 	if (easy)
 	{
+		LLMutexLock lock(mEasyMutexp) ;
 		mEasyActiveList.insert(easy);
 		mEasyActiveMap[easy->getCurlHandle()] = easy;
 	}
@@ -764,6 +761,7 @@ LLCurl::Easy* LLCurl::Multi::allocEasy()
 
 bool LLCurl::Multi::addEasy(Easy* easy)
 {
+	LLMutexLock lock(mMutexp) ;
 	CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle());
 	check_curl_multi_code(mcode);
 	//if (mcode != CURLM_OK)
@@ -776,22 +774,30 @@ bool LLCurl::Multi::addEasy(Easy* easy)
 
 void LLCurl::Multi::easyFree(Easy* easy)
 {
+	mEasyMutexp->lock() ;
 	mEasyActiveList.erase(easy);
 	mEasyActiveMap.erase(easy->getCurlHandle());
+
 	if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE)
-	{
-		easy->resetState();
+	{		
 		mEasyFreeList.insert(easy);
+		mEasyMutexp->unlock() ;
+
+		easy->resetState();
 	}
 	else
 	{
+		mEasyMutexp->unlock() ;
 		delete easy;
 	}
 }
 
 void LLCurl::Multi::removeEasy(Easy* easy)
 {
-	check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
+	{
+		LLMutexLock lock(mMutexp) ;
+		check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
+	}
 	easyFree(easy);
 }
 
@@ -1290,6 +1296,10 @@ void LLCurl::initClass(bool multi_threaded)
 #endif
 
 	sCurlThread = new LLCurlThread(multi_threaded) ;
+	if(multi_threaded)
+	{
+		Easy::sHandleMutexp = new LLMutex(NULL) ;
+	}
 }
 
 void LLCurl::cleanupClass()
@@ -1319,6 +1329,9 @@ void LLCurl::cleanupClass()
 
 	Easy::sFreeHandles.clear();
 
+	delete Easy::sHandleMutexp ;
+	Easy::sHandleMutexp = NULL ;
+
 	llassert(Easy::sActiveHandles.empty());
 }
 
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index a275db3e53..5d54b5fe12 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -253,6 +253,7 @@ private:
 
 	static std::set<CURL*> sFreeHandles;
 	static std::set<CURL*> sActiveHandles;
+	static LLMutex*        sHandleMutexp ;
 };
 
 class LLCurl::Multi
@@ -316,6 +317,7 @@ private:
 	BOOL mDead ;
 	LLMutex* mMutexp ;
 	LLMutex* mDeletionMutexp ;
+	LLMutex* mEasyMutexp ;
 };
 
 class LLCurlThread : public LLQueuedThread
-- 
cgit v1.2.3


From 16778677868620874b8b042f6c62712c9d28f2fb Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 16 Dec 2011 10:43:57 -0800
Subject: EXP-1738 FIX EXP-1739 FIX

* Initial pass to block drag and drop of multiple items when resultant outbox folder would contain too many items or folders.
---
 indra/newview/llinventorybridge.cpp | 5 +++--
 indra/newview/lltooldraganddrop.h   | 2 ++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index adf1d6254d..ff980955e0 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -60,6 +60,7 @@
 #include "llpreviewtexture.h"
 #include "llselectmgr.h"
 #include "llsidepanelappearance.h"
+#include "lltooldraganddrop.h"
 #include "lltrans.h"
 #include "llviewerassettype.h"
 #include "llviewerfoldertype.h"
@@ -1962,7 +1963,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
 				
 				int existing_item_count = 0;
-				int existing_folder_count = 1;  // +1 for this folder being dragged now
+				int existing_folder_count = LLToolDragAndDrop::instance().getCargoIDsCount();
 				
 				if (master_folder != NULL)
 				{
@@ -3461,7 +3462,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			{
 				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
 				
-				int existing_item_count = 1; // +1 for this item being dragged now
+				int existing_item_count = LLToolDragAndDrop::instance().getCargoIDsCount();
 				
 				if (master_folder != NULL)
 				{
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 92f007a251..273d23d1a0 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -86,6 +86,8 @@ public:
 	EAcceptance getLastAccept() { return mLastAccept; }
 
 	boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); }
+	
+	uuid_vec_t::size_type getCargoIDsCount() const { return mCargoIDs.size(); }
 
 protected:
 	enum EDropTarget
-- 
cgit v1.2.3


From c0b4ec6fe72d703191b28749cfd30262d131b245 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Fri, 16 Dec 2011 17:43:30 -0600
Subject: SH-2694 Fix for FPS drop when mousing over flexi objects (don't use
 an octree for flexi raycast)

---
 indra/llmath/lloctree.h              | 36 ++++++++-------
 indra/llmath/llvolume.cpp            | 85 +++++++++++++++++++++++++++++++-----
 indra/newview/llspatialpartition.cpp | 26 ++++++-----
 3 files changed, 111 insertions(+), 36 deletions(-)

diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index 3c1ae45d68..1b11e83b4a 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -80,8 +80,8 @@ public:
 	typedef LLOctreeTraveler<T>									oct_traveler;
 	typedef LLTreeTraveler<T>									tree_traveler;
 	typedef typename std::set<LLPointer<T> >					element_list;
-	typedef typename std::set<LLPointer<T> >::iterator			element_iter;
-	typedef typename std::set<LLPointer<T> >::const_iterator	const_element_iter;
+	typedef typename element_list::iterator						element_iter;
+	typedef typename element_list::const_iterator	const_element_iter;
 	typedef typename std::vector<LLTreeListener<T>*>::iterator	tree_listener_iter;
 	typedef typename std::vector<LLOctreeNode<T>* >				child_list;
 	typedef LLTreeNode<T>		BaseType;
@@ -114,6 +114,8 @@ public:
 			mOctant = ((oct_node*) mParent)->getOctant(mCenter);
 		}
 
+		mElementCount = 0;
+
 		clearChildren();
 	}
 
@@ -219,11 +221,11 @@ public:
 	void accept(oct_traveler* visitor)				{ visitor->visit(this); }
 	virtual bool isLeaf() const						{ return mChild.empty(); }
 	
-	U32 getElementCount() const						{ return mData.size(); }
+	U32 getElementCount() const						{ return mElementCount; }
 	element_list& getData()							{ return mData; }
 	const element_list& getData() const				{ return mData; }
 	
-	U32 getChildCount()	const						{ return mChild.size(); }
+	U32 getChildCount()	const						{ return mChildCount; }
 	oct_node* getChild(U32 index)					{ return mChild[index]; }
 	const oct_node* getChild(U32 index) const		{ return mChild[index]; }
 	child_list& getChildren()						{ return mChild; }
@@ -300,17 +302,13 @@ public:
 			if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
 				(data->getBinRadius() > getSize()[0] &&	parent && parent->getElementCount() >= gOctreeMaxCapacity))) 
 			{ //it belongs here
-#if LL_OCTREE_PARANOIA_CHECK
 				//if this is a redundant insertion, error out (should never happen)
-				if (mData.find(data) != mData.end())
-				{
-					llwarns << "Redundant octree insertion detected. " << data << llendl;
-					return false;
-				}
-#endif
+				llassert(mData.find(data) == mData.end());
 
 				mData.insert(data);
 				BaseType::insert(data);
+
+				mElementCount = mData.size();
 				return true;
 			}
 			else
@@ -346,6 +344,8 @@ public:
 				{
 					mData.insert(data);
 					BaseType::insert(data);
+
+					mElementCount = mData.size();
 					return true;
 				}
 
@@ -399,6 +399,7 @@ public:
 		if (mData.find(data) != mData.end())
 		{	//we have data
 			mData.erase(data);
+			mElementCount = mData.size();
 			notifyRemoval(data);
 			checkAlive();
 			return true;
@@ -436,6 +437,7 @@ public:
         if (mData.find(data) != mData.end())
 		{
 			mData.erase(data);
+			mElementCount = mData.size();
 			notifyRemoval(data);
 			llwarns << "FOUND!" << llendl;
 			checkAlive();
@@ -452,7 +454,7 @@ public:
 	void clearChildren()
 	{
 		mChild.clear();
-
+		mChildCount = 0;
 		U32* foo = (U32*) mChildMap;
 		foo[0] = foo[1] = 0xFFFFFFFF;
 	}
@@ -512,9 +514,10 @@ public:
 		}
 #endif
 
-		mChildMap[child->getOctant()] = (U8) mChild.size();
+		mChildMap[child->getOctant()] = mChildCount;
 
 		mChild.push_back(child);
+		++mChildCount;
 		child->setParent(this);
 
 		if (!silent)
@@ -534,21 +537,20 @@ public:
 			oct_listener* listener = getOctListener(i);
 			listener->handleChildRemoval(this, getChild(index));
 		}
-
 		
-
 		if (destroy)
 		{
 			mChild[index]->destroy();
 			delete mChild[index];
 		}
 		mChild.erase(mChild.begin() + index);
+		--mChildCount;
 
 		//rebuild child map
 		U32* foo = (U32*) mChildMap;
 		foo[0] = foo[1] = 0xFFFFFFFF;
 
-		for (U32 i = 0; i < mChild.size(); ++i)
+		for (U32 i = 0; i < mChildCount; ++i)
 		{
 			mChildMap[mChild[i]->getOctant()] = i;
 		}
@@ -601,8 +603,10 @@ protected:
 
 	child_list mChild;
 	U8 mChildMap[8];
+	U32 mChildCount;
 
 	element_list mData;
+	U32 mElementCount;
 		
 }; 
 
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index da0fa32963..0c6cf1dfae 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -4617,18 +4617,83 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en
 				genBinormals(i);
 			}
 
-			if (!face.mOctree)
-			{
-				face.createOctree();
-			}
-			
-			//LLVector4a* p = (LLVector4a*) face.mPositions;
+			if (isUnique())
+			{ //don't bother with an octree for flexi volumes
+				U32 tri_count = face.mNumIndices/3;
+
+				for (U32 j = 0; j < tri_count; ++j)
+				{
+					U16 idx0 = face.mIndices[j*3+0];
+					U16 idx1 = face.mIndices[j*3+1];
+					U16 idx2 = face.mIndices[j*3+2];
 
-			LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal);
-			intersect.traverse(face.mOctree);
-			if (intersect.mHitFace)
+					const LLVector4a& v0 = face.mPositions[idx0];
+					const LLVector4a& v1 = face.mPositions[idx1];
+					const LLVector4a& v2 = face.mPositions[idx2];
+				
+					F32 a,b,t;
+
+					if (LLTriangleRayIntersect(v0, v1, v2,
+							start, dir, a, b, t))
+					{
+						if ((t >= 0.f) &&      // if hit is after start
+							(t <= 1.f) &&      // and before end
+							(t < closest_t))   // and this hit is closer
+						{
+							closest_t = t;
+							hit_face = i;
+
+							if (intersection != NULL)
+							{
+								LLVector4a intersect = dir;
+								intersect.mul(closest_t);
+								intersect.add(start);
+								intersection->set(intersect.getF32ptr());
+							}
+
+
+							if (tex_coord != NULL)
+							{
+								LLVector2* tc = (LLVector2*) face.mTexCoords;
+								*tex_coord = ((1.f - a - b)  * tc[idx0] +
+									a              * tc[idx1] +
+									b              * tc[idx2]);
+
+							}
+
+							if (normal!= NULL)
+							{
+								LLVector4* norm = (LLVector4*) face.mNormals;
+
+								*normal		= ((1.f - a - b)  * LLVector3(norm[idx0]) + 
+									a              * LLVector3(norm[idx1]) +
+									b              * LLVector3(norm[idx2]));
+							}
+
+							if (bi_normal != NULL)
+							{
+								LLVector4* binormal = (LLVector4*) face.mBinormals;
+								*bi_normal = ((1.f - a - b)  * LLVector3(binormal[idx0]) + 
+										a              * LLVector3(binormal[idx1]) +
+										b              * LLVector3(binormal[idx2]));
+							}
+						}
+					}
+				}
+			}
+			else
 			{
-				hit_face = i;
+				if (!face.mOctree)
+				{
+					face.createOctree();
+				}
+			
+				LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal);
+				intersect.traverse(face.mOctree);
+				if (intersect.mHitFace)
+				{
+					hit_face = i;
+				}
 			}
 		}		
 	}
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index fb107a302a..900f126049 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -3775,11 +3775,7 @@ void renderRaycast(LLDrawable* drawablep)
 				for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
 				{
 					const LLVolumeFace& face = volume->getVolumeFace(i);
-					if (!face.mOctree)
-					{
-						((LLVolumeFace*) &face)->createOctree(); 
-					}
-
+					
 					gGL.pushMatrix();
 					gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);					
 					gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix);
@@ -3802,9 +3798,6 @@ void renderRaycast(LLDrawable* drawablep)
 					LLVector4a dir;
 					dir.setSub(enda, starta);
 
-					F32 t = 1.f;
-
-					LLRenderOctreeRaycast render(starta, dir, &t);
 					gGL.flush();
 					glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);				
 
@@ -3816,8 +3809,21 @@ void renderRaycast(LLDrawable* drawablep)
 						gGL.syncMatrices();
 						glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
 					}
-						
-					render.traverse(face.mOctree);
+					
+					if (!volume->isUnique())
+					{
+						F32 t = 1.f;
+
+						if (!face.mOctree)
+						{
+							((LLVolumeFace*) &face)->createOctree(); 
+						}
+
+						LLRenderOctreeRaycast render(starta, dir, &t);
+					
+						render.traverse(face.mOctree);
+					}
+
 					gGL.popMatrix();		
 					glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 				}
-- 
cgit v1.2.3


From 5b6fe3a8388ae8f3b0e49899a1ff4a0b5aca35fd Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 16 Dec 2011 16:35:21 -0800
Subject: EXP-1730 FIX -- Library items can be dragged and dropped to Outbox
 floater and folders are not created for items

* Updated to proper tooltip string
---
 indra/newview/llinventorybridge.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index ff980955e0..3f12067048 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2108,7 +2108,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 	{
 		if (move_is_into_outbox)
 		{
-			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNoTransferLibrary");
+			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
 		}
 		else
-- 
cgit v1.2.3


From 97a2663cf9fc28a9b651d423f4eb0e506b3c507d Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 19 Dec 2011 11:25:14 -0800
Subject: EXP-1745 FIX -- removed the merchant outbox from the toolbox

---
 indra/newview/app_settings/commands.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index c12d22adc3..1d1d39c786 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -136,7 +136,7 @@
            is_running_parameters="moveview"
            />
   <command name="outbox"
-           available_in_toybox="true"
+           available_in_toybox="false"
            icon="Command_Outbox_Icon"
            label_ref="Command_Outbox_Label"
            tooltip_ref="Command_Outbox_Tooltip"
-- 
cgit v1.2.3


From 58f9982fbc94ed2f039f0cd32579fa572f87e8ba Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Mon, 19 Dec 2011 15:35:38 -0600
Subject: SH-2738 Add comment documenting need to not make main thread wait on
 curl_multi_perform

---
 indra/llmessage/llcurl.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 874f4673ca..20f0c6c602 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -675,6 +675,10 @@ bool LLCurl::Multi::doPerform()
 				call_count++)
 		{
 			LLMutexLock lock(mMutexp) ;
+
+			//WARNING: curl_multi_perform will block for many hundreds of milliseconds
+			// NEVER call this from the main thread, and NEVER allow the main thread to 
+			// wait on a mutex held by this thread while curl_multi_perform is executing
 			CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
 			if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
 			{
-- 
cgit v1.2.3


From ac01fb0e0378476fd572ba24151d73840f119519 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 19 Dec 2011 13:55:53 -0800
Subject: EXP-1683 FIX -- Add main inventory context menu option Copy To Outbox

* The logic to determine whether or not the "Copy to Merchant Outbox" item is available is now tied to drag and drop functionality.
---
 indra/newview/llinventorybridge.cpp | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3f12067048..d8e0529501 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1102,26 +1102,33 @@ BOOL LLInvFVBridge::canListOnMarketplace() const
 
 BOOL LLInvFVBridge::canListOnMarketplaceNow() const
 {
+	BOOL can_list = FALSE;
+	
 #if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
 
-#if BLOCK_WORN_ITEMS_IN_OUTBOX
-	if (get_is_item_worn(mUUID))
-	{
-		return FALSE;
-	}
+	const LLInventoryObject* obj = getInventoryObject();
 
-	// Loop through all items worn by avatar and check to see if they are descendants
-	// of the item we are trying to list on the marketplace
-	if (get_is_parent_to_worn_item(mUUID))
+	if (obj)
 	{
-		return FALSE;
+		// Get outbox id
+		const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+		LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id);
+
+		if (outbox_itemp)
+		{
+			MASK mask = 0x0;
+			BOOL drop = FALSE;
+			EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
+			void * cargo_data = (void *) obj;
+			std::string tooltip_msg;
+			
+			can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
+		}
 	}
-#endif // BLOCK_WORN_ITEMS_IN_OUTBOX
 
-	return TRUE;
-#else
-	return FALSE;
 #endif
+
+	return can_list;
 }
 
 
-- 
cgit v1.2.3


From a0929f39caba9c2b7be8184f217c8e2a811857eb Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 19 Dec 2011 13:58:36 -0800
Subject: EXP-1170 FIX -- Right click context menu to Copy to Outbox shown if
 user is not a merchant

* The context menu option is no longer shown if the user does not have an outbox.
---
 indra/newview/llinventorybridge.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index d8e0529501..7665ad6e88 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1087,6 +1087,12 @@ BOOL LLInvFVBridge::canListOnMarketplace() const
 	{
 		return FALSE;
 	}
+	
+	const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+	if (outbox_id.isNull())
+	{
+		return FALSE;
+	}
 
 	LLViewerInventoryItem * item = model->getItem(mUUID);
 	if (item && !item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
-- 
cgit v1.2.3


From 43e3603cd763f5f501c8c5dc008d8a00d0744c53 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Mon, 19 Dec 2011 16:55:21 -0600
Subject: SH-2738 Don't lock unless we really need to

---
 indra/llmessage/llcurl.cpp | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index d86bf7a0a1..988c12d6fb 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -612,13 +612,7 @@ void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
 
 LLCurl::Multi::ePerformState LLCurl::Multi::getState()
 {
-	ePerformState state ;
-
-	lock() ;
-	state = mState ;
-	unlock() ;
-
-	return state ;
+	return mState;
 }
 	
 bool LLCurl::Multi::isCompleted() 
@@ -636,14 +630,12 @@ bool LLCurl::Multi::waitToComplete()
 
 	bool completed ;
 
-	lock() ;
 	completed = (STATE_COMPLETED == mState) ;
 	if(!completed)
 	{
 		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;
 	}
-	unlock() ;
-
+	
 	return completed;
 }
 
-- 
cgit v1.2.3


From 5affaf264da937cdf825bf174c3905a6063b5336 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Mon, 19 Dec 2011 16:55:21 -0600
Subject: SH-2738 Don't lock unless we really need to

---
 indra/llmessage/llcurl.cpp | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 20f0c6c602..05f3869a11 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -612,13 +612,7 @@ void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
 
 LLCurl::Multi::ePerformState LLCurl::Multi::getState()
 {
-	ePerformState state ;
-
-	lock() ;
-	state = mState ;
-	unlock() ;
-
-	return state ;
+	return mState;
 }
 	
 bool LLCurl::Multi::isCompleted() 
@@ -636,14 +630,12 @@ bool LLCurl::Multi::waitToComplete()
 
 	bool completed ;
 
-	lock() ;
 	completed = (STATE_COMPLETED == mState) ;
 	if(!completed)
 	{
 		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;
 	}
-	unlock() ;
-
+	
 	return completed;
 }
 
-- 
cgit v1.2.3


From 6c26fdea4d62f723c3bdbec9ded032e6d77301b8 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 19 Dec 2011 16:46:26 -0800
Subject: EXP-1741 FIX -- Learn more link goes to page not found from Outbox
 for user that is not a merchant an Agni EXP-1746 FIX -- Update Outbox
 messaging EXP-1748 FIX -- Close down on messaging with Spinner MKT-3403
 support -- viewer tooltips updated to match errors in marketplace

* Copy has been updated to match the design per Leo and Brooke
* Marketplace URL's have also been updated
* The outbox floater now reports a status string in the existing folder count control
---
 indra/newview/llfloateroutbox.cpp                  | 43 ++++++++++++++++------
 indra/newview/llfloateroutbox.h                    | 23 +++++++-----
 indra/newview/llinventorybridge.cpp                |  2 +-
 .../default/xui/en/floater_merchant_outbox.xml     | 12 +++---
 indra/newview/skins/default/xui/en/strings.xml     | 37 ++++++++-----------
 5 files changed, 68 insertions(+), 49 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 725e521e58..239ba7ad4d 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -103,15 +103,16 @@ LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
 	: LLFloater(key)
 	, mCategoriesObserver(NULL)
 	, mCategoryAddedObserver(NULL)
-	, mOutboxId(LLUUID::null)
-	, mOutboxInventoryPanel(NULL)
-	, mOutboxItemCount(0)
+	, mImportBusy(false)
+	, mImportButton(NULL)
 	, mInventoryFolderCountText(NULL)
 	, mInventoryImportInProgress(NULL)
 	, mInventoryPlaceholder(NULL)
 	, mInventoryText(NULL)
 	, mInventoryTitle(NULL)
-	, mImportButton(NULL)
+	, mOutboxId(LLUUID::null)
+	, mOutboxInventoryPanel(NULL)
+	, mOutboxItemCount(0)
 	, mWindowShade(NULL)
 {
 }
@@ -251,12 +252,22 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
 	// Initialize the marketplace import API
 	//
 	
+	mImportBusy = true;
+	setStatusString(getString("OutboxInitializing"));
+
 	LLMarketplaceInventoryImporter::getInstance()->initialize();
 	LLMarketplaceInventoryImporter::getInstance()->setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
 	LLMarketplaceInventoryImporter::getInstance()->setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
 }
 
-void LLFloaterOutbox::updateItemCount()
+void LLFloaterOutbox::setStatusString(const std::string& statusString)
+{
+	llassert(mInventoryFolderCountText != NULL);
+
+	mInventoryFolderCountText->setText(statusString);
+}
+
+void LLFloaterOutbox::updateFolderCount()
 {
 	S32 item_count = 0;
 
@@ -275,8 +286,8 @@ void LLFloaterOutbox::updateItemCount()
 	{
 		switch (mOutboxItemCount)
 		{
-			case 0:	mInventoryFolderCountText->setText(getString("OutboxFolderCount0"));	break;
-			case 1:	mInventoryFolderCountText->setText(getString("OutboxFolderCount1"));	break;
+			case 0:	setStatusString(getString("OutboxFolderCount0"));	break;
+			case 1:	setStatusString(getString("OutboxFolderCount1"));	break;
 			default:
 			{
 				std::string item_count_str = llformat("%d", mOutboxItemCount);
@@ -284,7 +295,7 @@ void LLFloaterOutbox::updateItemCount()
 				LLStringUtil::format_map_t args;
 				args["[NUM]"] = item_count_str;
 				
-				mInventoryFolderCountText->setText(getString("OutboxFolderCountN", args));
+				setStatusString(getString("OutboxFolderCountN", args));
 				break;
 			}
 		}
@@ -295,7 +306,10 @@ void LLFloaterOutbox::updateItemCount()
 
 void LLFloaterOutbox::updateView()
 {
-	updateItemCount();
+	if (!mImportBusy)
+	{
+		updateFolderCount();
+	}
 
 	if (mOutboxItemCount > 0)
 	{
@@ -431,15 +445,22 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress)
 {
 	if (inProgress)
 	{
-		mImportButton->setEnabled(false);
+		if (!mImportBusy)
+		{
+			setStatusString(getString("OutboxImporting"));
+		}
 		
+		mImportBusy = true;
+		mImportButton->setEnabled(false);
 		mInventoryImportInProgress->setVisible(true);
 	}
 	else
 	{
+		mImportBusy = false;
+		mImportButton->setEnabled(mOutboxItemCount > 0);
 		mInventoryImportInProgress->setVisible(false);
 
-		mImportButton->setEnabled(mOutboxItemCount > 0);
+		updateView();
 	}
 }
 
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index 5222db1142..5cb487be64 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -80,25 +80,28 @@ protected:
 	void onImportButtonClicked();
 	void onOutboxChanged();
 	
-	void updateItemCount();
+	void setStatusString(const std::string& statusString);
+	
+	void updateFolderCount();
 	void updateView();
 
 private:
 	LLInventoryCategoriesObserver *		mCategoriesObserver;
 	LLInventoryCategoryAddedObserver *	mCategoryAddedObserver;
-
+	
+	bool			mImportBusy;
+	LLButton *		mImportButton;
+	
+	LLTextBox *		mInventoryFolderCountText;
+	LLView *		mInventoryImportInProgress;
+	LLView *		mInventoryPlaceholder;
+	LLTextBox *		mInventoryText;
+	LLTextBox *		mInventoryTitle;
+	
 	LLUUID				mOutboxId;
 	LLInventoryPanel *	mOutboxInventoryPanel;
 	U32					mOutboxItemCount;
 	
-	LLTextBox *				mInventoryFolderCountText;
-	LLView *				mInventoryImportInProgress;
-	LLView *				mInventoryPlaceholder;
-	LLTextBox *				mInventoryText;
-	LLTextBox *				mInventoryTitle;
-	
-	LLButton *		mImportButton;
-	
 	LLWindowShade *	mWindowShade;
 };
 
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 7665ad6e88..4e26f09978 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -73,7 +73,7 @@
 
 // Marketplace outbox current disabled
 #define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1
-#define BLOCK_WORN_ITEMS_IN_OUTBOX 0
+#define BLOCK_WORN_ITEMS_IN_OUTBOX 1
 
 typedef std::pair<LLUUID, LLUUID> two_uuids_t;
 typedef std::list<two_uuids_t> two_uuids_list_t;
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index 0368601bf4..eb68339022 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -16,6 +16,8 @@
  <string name="OutboxFolderCount0">0 folders</string>
  <string name="OutboxFolderCount1">1 folder</string>
  <string name="OutboxFolderCountN">[NUM] folders</string>
+ <string name="OutboxImporting">Sending items...</string>
+ <string name="OutboxInitializing">Initializing...</string>
  <panel
       follows="all"
       layout="topleft"
@@ -82,13 +84,13 @@
 			type="string"
 			follows="all"
 			layout="topleft"
-			top="7"
+			top="10"
 			left="5"
-			width="100"
+			width="150"
 			height="20"
 			wrap="true"
 			halign="left"
-			valign="baseline"
+			valign="bottom"
 			font="SansSerif" />
 		<button
 			 label="Send to Marketplace"
@@ -99,9 +101,9 @@
 			 tab_stop="false"
 			 halign="center"
 			 top="3"
-			 left="110"
+			 left="160"
 			 height="25"
-			 width="200"
+			 width="150"
 			 enabled="false" />
     </panel>
 	<layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 0d9a7e5c41..18ca3033e9 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -164,12 +164,13 @@ Please try logging in again in a minute.</string>
 	<string name="TooltipLand">Land:</string>
 	<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
 	<string name="TooltipPrice" value="L$[AMOUNT]: "/>
-	<string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred to another user.</string>
-	<string name="TooltipOutboxNotInInventory">You can only transfer objects in your inventory to your merchant outbox.</string>
-	<string name="TooltipOutboxWorn">You are wearing one or more of these objects. Remove them from your avatar and try moving them again.</string>
-	<string name="TooltipOutboxFolderLevels">This folder has too many levels of subfolders. Rearrange the interior folders to a maximum of 4 levels deep (Root Folder contains A contains B contains C).</string>
-	<string name="TooltipOutboxTooManyFolders">This folder has too many subfolders. Reorganize the interior to a maximum of 20 folders.</string>
-	<string name="TooltipOutboxTooManyObjects">This folder contains more than 200 objects. Box some of the items to reduce the object count.</string>
+
+	<string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred.</string>
+	<string name="TooltipOutboxNotInInventory">Your merchant outbox can only accept items directly from your inventory</string>
+	<string name="TooltipOutboxWorn">You can not put items you are wearing into your merchant outbox</string>
+	<string name="TooltipOutboxFolderLevels">Depth of nested folders exceeds 3</string>
+	<string name="TooltipOutboxTooManyFolders">Subfolder count in top-level folder exceeds 20</string>
+	<string name="TooltipOutboxTooManyObjects">Item count in top-level folder exceeds 200</string>
 	
 	<!-- tooltips for Urls -->
 	<string name="TooltipHttpUrl">Click to view this web page</string>
@@ -2032,33 +2033,25 @@ Returns a string with the requested data about the region
 	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
 	<string name="InventoryInboxNoItems">When you purchase or otherwise receive an item, it will appear here so you can drag it to a folder in your inventory, or delete it if you do not wish to keep it.</string>
 	<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string>
-	<string name="MarketplaceURL_CreateStore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/create_store</string>
-	<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/[AGENT_ID]/store/dashboard</string>
+	<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string>
+	<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string>
 	<string name="MarketplaceURL_LearnMore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more</string>
-	<string name="InventoryOutboxCreationErrorTitle">Your Merchant Outbox is not properly configured</string>
-	<string name="InventoryOutboxCreationErrorTooltip">Merchant Outbox configuration error</string>
-	<string name="InventoryOutboxCreationError">Please contact Customer Service to correct the problem.</string>
 	<string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace.</string>
-	<string name="InventoryOutboxNotMerchantTooltip">Become a merchant!</string>
+	<string name="InventoryOutboxNotMerchantTooltip"></string>
 	<string name="InventoryOutboxNotMerchant">
-The Second Life Marketplace offers more than one million virtual products for sale, all of them created by Residents like you.  You too can create items and sell them on the Marketplace.  Creating a store is easy and free of charge.
-
-[[MARKETPLACE_URL] Visit the Marketplace]
-
-[[MARKETPLACE_LEARN_MORE_URL] Learn more about creating a store]
+If you'd like to become a merchant, you'll need to [[MARKETPLACE_CREATE_STORE_URL] create a Marketplace store].
 	</string>
 	<string name="InventoryOutboxNoItemsTitle">Your outbox is empty.</string>
-	<string name="InventoryOutboxNoItemsTooltip">Drag and drop items here to prepare them for sale on the Marketplace</string>
+	<string name="InventoryOutboxNoItemsTooltip"></string>
 	<string name="InventoryOutboxNoItems">
-Drag folders to this area.  When you are ready to send them to the Marketplace for sale, click the "Send to Marketplace" button below.
-
-[[MARKETPLACE_DASHBOARD_URL] Go to your Merchant Dashboard]
+Drag folders to this area and click "Send to Marketplace" to list them for sale on the [[MARKETPLACE_DASHBOARD_URL] Marketplace].
 	</string>
 
 	<string name="Marketplace Error None">No errors</string>
 	<string name="Marketplace Error Not Merchant">Error: Before sending items to the Marketplace you will need to set yourself up as a merchant (free of charge).</string>
 	<string name="Marketplace Error Empty Folder">Error: This folder has no contents.</string>
-	<string name="Marketplace Error Unassociated Products">Error: This item failed to upload because your merchant account has too many items unassociated with products.  To fix this error, login to the marketplace website and reduce your unassociated item count.</string>
+	<string name="Marketplace Error Unassociated Products">Error: This item failed to upload because your merchant account has too many items unassociated with products.  To fix this error, log in to the marketplace website and reduce your unassociated item count.</string>
+
 	<string name="Marketplace Error Object Limit">Error: This item contains too many objects.  Fix this error by placing objects together in boxes to reduce the total count to less than 200.</string>
 	<string name="Marketplace Error Folder Depth">Error: This item contains too many levels of nested folders.  Reorganize it to a maximum of 3 levels of nested folders.</string>
 	<string name="Marketplace Error Unsellable Item">Error: This item can not be sold on the marketplace.</string>
-- 
cgit v1.2.3


From 744484699cec728f60463755d409fbde681429ea Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 19 Dec 2011 17:29:17 -0800
Subject: EXP-1749 FIX -- Merchant outbox import completion messages are to be
 modal dialogs

* Merchant outbox completion messages now shown as modal dialogs rather than window shades.
---
 indra/newview/llfloateroutbox.cpp                  | 42 ++++++++++++++++------
 indra/newview/llfloateroutbox.h                    |  2 +-
 .../newview/skins/default/xui/en/notifications.xml |  4 +--
 3 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 239ba7ad4d..b97cc54dd1 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -36,6 +36,7 @@
 #include "llinventorypanel.h"
 #include "llmarketplacefunctions.h"
 #include "llnotificationhandler.h"
+#include "llnotificationmanager.h"
 #include "llnotificationsutil.h"
 #include "lltextbox.h"
 #include "lltransientfloatermgr.h"
@@ -43,6 +44,8 @@
 #include "llviewernetwork.h"
 #include "llwindowshade.h"
 
+#define USE_WINDOWSHADE_DIALOGS	0
+
 
 ///----------------------------------------------------------------------------
 /// LLOutboxNotification class
@@ -50,14 +53,9 @@
 
 bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify)
 {
-	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
-
-	if (notification)
-	{
-		LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox");
-
-		outbox_floater->showNotification(notification);
-	}
+	LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox");
+	
+	outbox_floater->showNotification(notify);
 
 	return false;
 }
@@ -413,6 +411,7 @@ void LLFloaterOutbox::onOutboxChanged()
 	}
 
 	fetchOutboxContents();
+
 	updateView();
 }
 
@@ -464,8 +463,19 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress)
 	}
 }
 
-void LLFloaterOutbox::showNotification(LLNotificationPtr notify)
+void LLFloaterOutbox::showNotification(const LLSD& notify)
 {
+	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+	
+	if (!notification)
+	{
+		llerrs << "Unable to find outbox notification!" << notify.asString() << llendl;
+		
+		return;
+	}
+
+#if USE_WINDOWSHADE_DIALOGS
+
 	if (mWindowShade)
 	{
 		delete mWindowShade;
@@ -487,6 +497,18 @@ void LLFloaterOutbox::showNotification(LLNotificationPtr notify)
 	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
 	
 	addChild(mWindowShade);
-	mWindowShade->show(notify);
+	mWindowShade->show(notification);
+	
+#else
+	
+	LLNotificationsUI::LLEventHandler * handler =
+		LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal");
+	
+	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler *>(handler);
+	llassert(sys_handler);
+	
+	sys_handler->processNotification(notify);
+	
+#endif
 }
 
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index 5cb487be64..cc4a7207ca 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -64,7 +64,7 @@ public:
 						   EAcceptance* accept,
 						   std::string& tooltip_msg);
 	
-	void showNotification(LLNotificationPtr notify);
+	void showNotification(const LLSD& notify);
 
 protected:
 	void fetchOutboxContents();
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 871a9d4a1d..858764006f 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -203,8 +203,8 @@ Save changes to current clothing/body part?
    icon="alertmodal.tga"
      name="ConfirmNoCopyToOutbox"
      type="alertmodal">
-        You don't have permission to copy this item to the Marketplace Outbox. Are you sure you want to move the following item?
-        [ITEM_NAME]
+You don't have permission to copy this item to the Marketplace Outbox. Are you sure you want to move the following item?
+[ITEM_NAME]
         <usetemplate
          name="okcancelbuttons"
          notext="No"
-- 
cgit v1.2.3


From cfc6ac76e1c700c0810629b005f45747c4144867 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 20 Dec 2011 11:04:10 -0700
Subject: more tuning of llcurl code targeting crashes like SH-2777.

---
 indra/llmessage/llcurl.cpp | 43 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 988c12d6fb..2b351d351e 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -603,11 +603,12 @@ void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
 {
 	lock() ;
 	mState = state ;
+	unlock() ;
+
 	if(mState == STATE_READY)
 	{
 		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ;
-	}
-	unlock() ;
+	}	
 }
 
 LLCurl::Multi::ePerformState LLCurl::Multi::getState()
@@ -628,9 +629,7 @@ bool LLCurl::Multi::waitToComplete()
 		return true ;
 	}
 
-	bool completed ;
-
-	completed = (STATE_COMPLETED == mState) ;
+	bool completed = (STATE_COMPLETED == mState) ;
 	if(!completed)
 	{
 		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;
@@ -641,6 +640,8 @@ bool LLCurl::Multi::waitToComplete()
 
 CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
 {
+	LLMutexLock lock(mMutexp) ;
+
 	CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue);
 	return curlmsg;
 }
@@ -702,10 +703,19 @@ S32 LLCurl::Multi::process()
 		if (msg->msg == CURLMSG_DONE)
 		{
 			U32 response = 0;
-			easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle);
-			if (iter != mEasyActiveMap.end())
+			Easy* easy = NULL ;
+
+			{
+				LLMutexLock lock(mEasyMutexp) ;
+				easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle);
+				if (iter != mEasyActiveMap.end())
+				{
+					easy = iter->second;
+				}
+			}
+
+			if(easy)
 			{
-				Easy* easy = iter->second;
 				response = easy->report(msg->data.result);
 				removeEasy(easy);
 			}
@@ -766,20 +776,31 @@ bool LLCurl::Multi::addEasy(Easy* easy)
 
 void LLCurl::Multi::easyFree(Easy* easy)
 {
-	mEasyMutexp->lock() ;
+	if(mEasyMutexp)
+	{
+		mEasyMutexp->lock() ;
+	}
+
 	mEasyActiveList.erase(easy);
 	mEasyActiveMap.erase(easy->getCurlHandle());
 
 	if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE)
 	{		
 		mEasyFreeList.insert(easy);
-		mEasyMutexp->unlock() ;
+		
+		if(mEasyMutexp)
+		{
+			mEasyMutexp->unlock() ;
+		}
 
 		easy->resetState();
 	}
 	else
 	{
-		mEasyMutexp->unlock() ;
+		if(mEasyMutexp)
+		{
+			mEasyMutexp->unlock() ;
+		}
 		delete easy;
 	}
 }
-- 
cgit v1.2.3


From 1620ad6d00a77b2089e0ae5f6de30f9a954c6167 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 20 Dec 2011 11:04:10 -0700
Subject: more tuning of llcurl code targeting crashes like SH-2777.

---
 indra/llmessage/llcurl.cpp | 43 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 05f3869a11..5027e8fa84 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -603,11 +603,12 @@ void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
 {
 	lock() ;
 	mState = state ;
+	unlock() ;
+
 	if(mState == STATE_READY)
 	{
 		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ;
-	}
-	unlock() ;
+	}	
 }
 
 LLCurl::Multi::ePerformState LLCurl::Multi::getState()
@@ -628,9 +629,7 @@ bool LLCurl::Multi::waitToComplete()
 		return true ;
 	}
 
-	bool completed ;
-
-	completed = (STATE_COMPLETED == mState) ;
+	bool completed = (STATE_COMPLETED == mState) ;
 	if(!completed)
 	{
 		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;
@@ -641,6 +640,8 @@ bool LLCurl::Multi::waitToComplete()
 
 CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
 {
+	LLMutexLock lock(mMutexp) ;
+
 	CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue);
 	return curlmsg;
 }
@@ -706,10 +707,19 @@ S32 LLCurl::Multi::process()
 		if (msg->msg == CURLMSG_DONE)
 		{
 			U32 response = 0;
-			easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle);
-			if (iter != mEasyActiveMap.end())
+			Easy* easy = NULL ;
+
+			{
+				LLMutexLock lock(mEasyMutexp) ;
+				easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle);
+				if (iter != mEasyActiveMap.end())
+				{
+					easy = iter->second;
+				}
+			}
+
+			if(easy)
 			{
-				Easy* easy = iter->second;
 				response = easy->report(msg->data.result);
 				removeEasy(easy);
 			}
@@ -770,20 +780,31 @@ bool LLCurl::Multi::addEasy(Easy* easy)
 
 void LLCurl::Multi::easyFree(Easy* easy)
 {
-	mEasyMutexp->lock() ;
+	if(mEasyMutexp)
+	{
+		mEasyMutexp->lock() ;
+	}
+
 	mEasyActiveList.erase(easy);
 	mEasyActiveMap.erase(easy->getCurlHandle());
 
 	if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE)
 	{		
 		mEasyFreeList.insert(easy);
-		mEasyMutexp->unlock() ;
+		
+		if(mEasyMutexp)
+		{
+			mEasyMutexp->unlock() ;
+		}
 
 		easy->resetState();
 	}
 	else
 	{
-		mEasyMutexp->unlock() ;
+		if(mEasyMutexp)
+		{
+			mEasyMutexp->unlock() ;
+		}
 		delete easy;
 	}
 }
-- 
cgit v1.2.3


From 5dc8e44c767f839e3d2d1d926bfdeee969f2492e Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Tue, 20 Dec 2011 20:44:38 +0200
Subject: EXP-1499 FIXED Added some NULL checks in notifications UI code to
 avoid a crash on exit.

The crash happened if connection timed out while there were unread object inventory offers.
---
 indra/newview/llchiclet.cpp       |  6 ++++++
 indra/newview/llscriptfloater.cpp | 11 +++++++++--
 indra/newview/llsyswellwindow.cpp | 13 ++++++++++++-
 indra/newview/llsyswellwindow.h   |  1 +
 4 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index a076374903..045c9017be 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -250,6 +250,12 @@ LLIMWellChiclet::LLIMWellChiclet(const Params& p)
 
 LLIMWellChiclet::~LLIMWellChiclet()
 {
+	LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance();
+	if (im_well_window)
+	{
+		im_well_window->setSysWellChiclet(NULL);
+	}
+
 	LLIMMgr::getInstance()->removeSessionObserver(this);
 }
 
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 85a7e75271..6f98be1cb8 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -408,9 +408,16 @@ void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id)
 	}
 
 	// remove related chiclet
-	LLChicletBar::getInstance()->getChicletPanel()->removeChiclet(notification_id);
+	if (LLChicletBar::instanceExists())
+	{
+		LLChicletBar::getInstance()->getChicletPanel()->removeChiclet(notification_id);
+	}
 
-	LLIMWellWindow::getInstance()->removeObjectRow(notification_id);
+	LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance();
+	if (im_well_window)
+	{
+		im_well_window->removeObjectRow(notification_id);
+	}
 
 	mNotifications.erase(notification_id);
 
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 3aa6a3b7e5..0cb6c85012 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -159,6 +159,7 @@ void LLSysWellWindow::setVisible(BOOL visible)
 	LLTransientDockableFloater::setVisible(visible);
 
 	// update notification channel state	
+	initChannel(); // make sure the channel still exists
 	if(mChannel)
 	{
 		mChannel->updateShowToastsState();
@@ -598,6 +599,13 @@ LLIMWellWindow* LLIMWellWindow::getInstance(const LLSD& key /*= LLSD()*/)
 	return LLFloaterReg::getTypedInstance<LLIMWellWindow>("im_well_window", key);
 }
 
+
+// static
+LLIMWellWindow* LLIMWellWindow::findInstance(const LLSD& key /*= LLSD()*/)
+{
+	return LLFloaterReg::findTypedInstance<LLIMWellWindow>("im_well_window", key);
+}
+
 BOOL LLIMWellWindow::postBuild()
 {
 	BOOL rv = LLSysWellWindow::postBuild();
@@ -751,7 +759,10 @@ void LLIMWellWindow::removeObjectRow(const LLUUID& notification_id)
 {
 	if (mMessageList->removeItemByValue(notification_id))
 	{
-		mSysWellChiclet->updateWidget(isWindowEmpty());
+		if (mSysWellChiclet)
+		{
+			mSysWellChiclet->updateWidget(isWindowEmpty());
+		}
 	}
 	else
 	{
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 52e5370505..272e9cfcb1 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -153,6 +153,7 @@ public:
 	~LLIMWellWindow();
 
 	static LLIMWellWindow* getInstance(const LLSD& key = LLSD());
+	static LLIMWellWindow* findInstance(const LLSD& key = LLSD());
 	static void initClass() { getInstance(); }
 
 	/*virtual*/ BOOL postBuild();
-- 
cgit v1.2.3


From 11e192d9a72274d24e2a50799904c7a64ab33e27 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 20 Dec 2011 11:43:02 -0800
Subject: EXP-1738 FIX -- Disable drag and drop to folders in the outbox that
 would create a hierarchy that contains too many folders EXP-1743 FIX --
 Tooltip errors given when dragging and dropping folders onto themselves in
 Merchant Outbox

* Top level folder now reflected in folder count for total folders
* Earlier rejections now honored in drag and drop code so outbox-specific tooltips only show up when appropriate
---
 indra/newview/llinventorybridge.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 4e26f09978..2ff6563a09 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1918,9 +1918,9 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 		BOOL is_movable = TRUE;
 		if (LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()))
 			is_movable = FALSE;
-		if (move_is_into_outfit)
+		else if (move_is_into_outfit)
 			is_movable = FALSE;
-		if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))
+		else if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))
 			is_movable = FALSE;
 		LLInventoryModel::cat_array_t descendent_categories;
 		LLInventoryModel::item_array_t descendent_items;
@@ -1935,7 +1935,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 				break;
 			}
 		}
-		if (move_is_into_trash)
+		if (is_movable && move_is_into_trash)
 		{
 			for (S32 i=0; i < descendent_items.count(); ++i)
 			{
@@ -1947,7 +1947,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 				}
 			}
 		}
-		if (move_is_into_landmarks)
+		if (is_movable && move_is_into_landmarks)
 		{
 			for (S32 i=0; i < descendent_items.count(); ++i)
 			{
@@ -1962,7 +1962,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 				}
 			}
 		}
-		if (move_is_into_outbox)
+		if (is_movable && move_is_into_outbox)
 		{
 			int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat);
 			
@@ -1976,7 +1976,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
 				
 				int existing_item_count = 0;
-				int existing_folder_count = LLToolDragAndDrop::instance().getCargoIDsCount();
+				int existing_folder_count = 1 + LLToolDragAndDrop::instance().getCargoIDsCount();  // +1 for master folder
 				
 				if (master_folder != NULL)
 				{
-- 
cgit v1.2.3


From ec06aa129f839cc98aaa8006d6467241281da9fa Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 20 Dec 2011 15:02:21 -0700
Subject: add mutex to protect curl_multi-init()

---
 indra/llmessage/llcurl.cpp | 19 ++++++++++++++++---
 indra/llmessage/llcurl.h   |  3 +++
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 2b351d351e..f569630766 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -517,7 +517,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 }
 
 ////////////////////////////////////////////////////////////////////////////
-
+LLMutex* LLCurl::Multi::sMultiInitMutexp = NULL ;
 LLCurl::Multi::Multi()
 	: mQueued(0),
 	  mErrorCount(0),
@@ -527,11 +527,11 @@ LLCurl::Multi::Multi()
 	  mDeletionMutexp(NULL),
 	  mEasyMutexp(NULL)
 {
-	mCurlMultiHandle = curl_multi_init();
+	mCurlMultiHandle = initMulti();
 	if (!mCurlMultiHandle)
 	{
 		llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
-		mCurlMultiHandle = curl_multi_init();
+		mCurlMultiHandle = initMulti();
 	}
 	
 	llassert_always(mCurlMultiHandle);	
@@ -576,6 +576,13 @@ LLCurl::Multi::~Multi()
 	--gCurlMultiCount;
 }
 
+CURLM* LLCurl::Multi::initMulti()
+{
+	LLMutexLock lock(sMultiInitMutexp) ;
+
+	return curl_multi_init() ;
+}
+
 void LLCurl::Multi::lock()
 {
 	if(mMutexp)
@@ -853,11 +860,17 @@ void LLCurlThread::CurlRequest::finishRequest(bool completed)
 LLCurlThread::LLCurlThread(bool threaded) :
 	LLQueuedThread("curlthread", threaded)
 {
+	if(!LLCurl::Multi::sMultiInitMutexp)
+	{
+		LLCurl::Multi::sMultiInitMutexp = new LLMutex(NULL) ;
+	}
 }
 	
 //virtual 
 LLCurlThread::~LLCurlThread() 
 {
+	delete LLCurl::Multi::sMultiInitMutexp ;
+	LLCurl::Multi::sMultiInitMutexp = NULL ;
 }
 
 S32 LLCurlThread::update(U32 max_time_ms)
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 5d54b5fe12..705cdcbbcc 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -299,6 +299,7 @@ public:
 	S32 mQueued;
 	S32 mErrorCount;
 	
+	static CURLM* initMulti() ;
 private:
 	void easyFree(LLCurl::Easy*);
 	
@@ -318,6 +319,8 @@ private:
 	LLMutex* mMutexp ;
 	LLMutex* mDeletionMutexp ;
 	LLMutex* mEasyMutexp ;
+
+	static LLMutex* sMultiInitMutexp ;
 };
 
 class LLCurlThread : public LLQueuedThread
-- 
cgit v1.2.3


From 2a3b7f295fa82d5d4826cfd912fd07ebbe5f9c21 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 20 Dec 2011 14:41:30 -0800
Subject: EXP-1755 FIX -- Can move items to Merchant Outbox during Outbox synch
 using Copy to Merchant Outbox context menu

* "Copy to Merchant Outbox" context menu option no longer available when marketplace import is in progress.
---
 indra/newview/llinventorybridge.cpp | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 2ff6563a09..96c527859c 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -53,6 +53,7 @@
 #include "llinventorymodel.h"
 #include "llinventorymodelbackgroundfetch.h"
 #include "llinventorypanel.h"
+#include "llmarketplacefunctions.h"
 #include "llnotifications.h"
 #include "llnotificationsutil.h"
 #include "llpreviewanim.h"
@@ -1132,6 +1133,15 @@ BOOL LLInvFVBridge::canListOnMarketplaceNow() const
 		}
 	}
 
+	// Do not allow listing while import is in progress
+	if (LLMarketplaceInventoryImporter::instanceExists())
+	{
+		if (LLMarketplaceInventoryImporter::instance().isImportInProgress())
+		{
+			can_list = FALSE;
+		}
+	}
+
 #endif
 
 	return can_list;
-- 
cgit v1.2.3


From 52fab641041ed1ba409a03fee77a0cdaec86dea2 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 20 Dec 2011 16:16:49 -0800
Subject: * Added "InventoryOutboxLogging" debug setting to log merchant outbox
 related web API calls.  Each message begins with the tag "SLM".

---
 indra/newview/app_settings/settings.xml            | 11 ++++++
 indra/newview/llmarketplacefunctions.cpp           | 39 ++++++++++++++++++++--
 .../default/xui/en/floater_merchant_outbox.xml     |  2 +-
 3 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index c51197bbf1..e5bb686123 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4271,6 +4271,17 @@
 		<key>Value</key>
 		<integer>0</integer>
 	</map>
+	<key>InventoryOutboxLogging</key>
+	<map>
+		<key>Comment</key>
+		<string>Enable debug output associated with the Merchant Outbox.</string>
+		<key>Persist</key>
+		<integer>1</integer>
+		<key>Type</key>
+		<string>Boolean</string>
+		<key>Value</key>
+		<integer>0</integer>
+	</map>
     <key>InventoryOutboxMaxFolderCount</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 225bb059c9..9a83c5fcb7 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -31,6 +31,7 @@
 #include "llagent.h"
 #include "llhttpclient.h"
 #include "lltrans.h"
+#include "llviewercontrol.h"
 #include "llviewermedia.h"
 #include "llviewernetwork.h"
 
@@ -108,12 +109,13 @@ namespace LLMarketplaceImport
 	// Internal state variables
 
 	static std::string sMarketplaceCookie = "";
+	static LLSD sImportId = LLSD::emptyMap();
 	static bool sImportInProgress = false;
 	static bool sImportPostPending = false;
 	static bool sImportGetPending = false;
 	static U32 sImportResultStatus = 0;
 	static LLSD sImportResults = LLSD::emptyMap();
-		
+
 	
 	// Responders
 	
@@ -124,9 +126,17 @@ namespace LLMarketplaceImport
 		
 		void completed(U32 status, const std::string& reason, const LLSD& content)
 		{
+			if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
+			{
+				llinfos << " SLM POST status: " << status << llendl;
+				llinfos << " SLM POST reason: " << reason << llendl;
+				llinfos << " SLM POST content: " << content.asString() << llendl;
+			}
+
 			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
 			sImportPostPending = false;
 			sImportResultStatus = status;
+			sImportId = content;
 		}
 	};
 	
@@ -142,6 +152,13 @@ namespace LLMarketplaceImport
 		
 		void completed(U32 status, const std::string& reason, const LLSD& content)
 		{
+			if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
+			{
+				llinfos << " SLM GET status: " << status << llendl;
+				llinfos << " SLM GET reason: " << reason << llendl;
+				llinfos << " SLM GET content: " << content.asString() << llendl;
+			}
+
 			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
 			sImportGetPending = false;
 			sImportResultStatus = status;
@@ -236,6 +253,11 @@ namespace LLMarketplaceImport
 		
 		std::string url = getInventoryImportURL();
 		
+		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
+		{
+			llinfos << " SLM GET: " << url << llendl;
+		}
+
 		LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders());
 	}
 	
@@ -245,18 +267,26 @@ namespace LLMarketplaceImport
 
 		std::string url = getInventoryImportURL();
 
+		url += sImportId.asString();
+
 		// Make the headers for the post
 		LLSD headers = LLSD::emptyMap();
 		headers["Accept"] = "*/*";
 		headers["Cookie"] = sMarketplaceCookie;
-		headers["Content-Type"] = "application/xml";
+		headers["Content-Type"] = "application/llsd+xml";
 		headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
 		
+		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
+		{
+			llinfos << " SLM GET: " << url << llendl;
+		}
+
 		LLHTTPClient::get(url, new LLImportGetResponder(), headers);
 	}
 	
 	void triggerImport()
 	{
+		sImportId = LLSD::emptyMap();
 		sImportInProgress = true;
 		sImportPostPending = true;
 		sImportResultStatus = MarketplaceErrorCodes::IMPORT_PROCESSING;
@@ -272,6 +302,11 @@ namespace LLMarketplaceImport
 		headers["Content-Type"] = "application/xml";
 		headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
 		
+		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
+		{
+			llinfos << " SLM POST: " << url << llendl;
+		}
+
 		LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers);
 		
 		// Set a timer (for testing only)
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index eb68339022..02394e8ac3 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -16,7 +16,7 @@
  <string name="OutboxFolderCount0">0 folders</string>
  <string name="OutboxFolderCount1">1 folder</string>
  <string name="OutboxFolderCountN">[NUM] folders</string>
- <string name="OutboxImporting">Sending items...</string>
+ <string name="OutboxImporting">Sending folders...</string>
  <string name="OutboxInitializing">Initializing...</string>
  <panel
       follows="all"
-- 
cgit v1.2.3


From 1a5194264451371270a7d94d528c2102be25c503 Mon Sep 17 00:00:00 2001
From: eli <none@none>
Date: Tue, 20 Dec 2011 16:50:23 -0800
Subject: sync with viewer-development

---
 .../skins/default/xui/en/floater_im_session.xml    |  2 +-
 indra/newview/skins/default/xui/en/menu_viewer.xml | 24 +++++++++++-----------
 .../newview/skins/default/xui/en/notifications.xml |  9 ++++++++
 .../default/xui/en/panel_adhoc_control_panel.xml   |  6 +++---
 .../skins/default/xui/en/panel_cof_wearables.xml   |  1 +
 .../skins/default/xui/en/panel_edit_skin.xml       | 12 +++++------
 indra/newview/skins/default/xui/en/strings.xml     |  5 +++++
 7 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 5fe8f3c114..a2739a8339 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -3,7 +3,7 @@
  legacy_header_height="18"
  background_visible="true"
  default_tab_group="1"
- height="350"
+ height="355"
  help_topic="floater_im_box"
  layout="topleft"
  name="panel_im"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 1834be2d48..0aa5c72f2a 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1713,7 +1713,17 @@
              function="ToggleControl"
              parameter="MouseSmooth" />
         </menu_item_check>
-
+            <menu_item_call
+             enabled="false"
+             label="Release Keys"
+             name="Release Keys">
+                <menu_item_call.on_click
+                 function="Tools.ReleaseKeys"
+                 parameter="" />
+                <menu_item_call.on_enable
+                 function="Tools.EnableReleaseKeys"
+                 parameter="" />
+            </menu_item_call>
         <menu_item_separator/>
 
         <menu
@@ -1743,17 +1753,7 @@
              function="Floater.Toggle"
              parameter="search" />
             </menu_item_check>
-            <menu_item_call
-             enabled="false"
-             label="Release Keys"
-             name="Release Keys">
-                <menu_item_call.on_click
-                 function="Tools.ReleaseKeys"
-                 parameter="" />
-                <menu_item_call.on_enable
-                 function="Tools.EnableReleaseKeys"
-                 parameter="" />
-            </menu_item_call>
+
             <!-- This second, alternative shortcut for Show Advanced Menu is for backward compatibility.  The main shortcut has been changed so it's Linux-friendly, where the old shortcut is typically eaten by the window manager. -->
             <menu_item_check
                label="Show Advanced Menu - legacy shortcut"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 0ba4b84abe..a7705c8bac 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5516,6 +5516,15 @@ Please select at least one type of content to search (General, Moderate, or Adul
 [MESSAGE]
   </notification>
 
+  <notification
+   icon="notify.tga"
+   name="PaymentFailure"
+   persist="true"
+   type="notify">
+    <tag>funds</tag>
+[MESSAGE]
+  </notification>
+
    <!-- EventNotification couldn't be persist since server decide is it necessary to notify 
    user about subscribed event via LLEventNotifier-->
   <notification
diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
index e70abc0975..93cafd4a53 100644
--- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
@@ -58,7 +58,7 @@
              label="Call"
              name="call_btn"
              width="130"
-             top="5" />
+             top="0" />
         </layout_panel>
         <layout_panel
          auto_resize="false"
@@ -75,7 +75,7 @@
              height="20"
              label="Leave Call"
              name="end_call_btn"
-             top="5"/>
+             top="0"/>
         </layout_panel>
         <layout_panel
          auto_resize="false"
@@ -92,7 +92,7 @@
              height="20"
              label="Voice Controls"
              name="voice_ctrls_btn"
-             top="5"
+             top="0"
              use_ellipses="true" />
         </layout_panel>
     </layout_stack>
diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml
index beea53437a..aa8e3d07a6 100644
--- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml
+++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml
@@ -37,6 +37,7 @@
              top="0"
              width="311" />
         </accordion_tab>
+         <!-- The Attachments title is overwritten by the definition of "Attachments remain" in strings.xml -->
         <accordion_tab
          layout="topleft"
          name="tab_attachments"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_skin.xml b/indra/newview/skins/default/xui/en/panel_edit_skin.xml
index 45591ba2ad..b61f65a3d1 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_skin.xml
@@ -27,10 +27,10 @@
         default_image_name="Default"
         follows="left|top"
         height="80"
-        label="Head Tattoos"
+        label="Head"
         layout="topleft"
         left="25"
-        name="Head Tattoos"
+        name="Head"
         tool_tip="Click to choose a picture"
         top="10"
         width="74" >
@@ -43,10 +43,10 @@
         default_image_name="Default"
         follows="left|top"
         height="80"
-        label="Upper Tattoos"
+        label="Upper body"
         layout="topleft"
         left_pad="20"
-        name="Upper Tattoos"
+        name="Upper Body"
         tool_tip="Click to choose a picture"
         top="10"
         width="74" >
@@ -59,10 +59,10 @@
         default_image_name="Default"
         follows="left|top"
         height="80"
-        label="Lower Tattoos"
+        label="Lower body"
         layout="topleft"
         left_pad="20"
-        name="Lower Tattoos"
+        name="Lower Body"
         tool_tip="Click to choose a picture"
         top="10"
         width="74" >
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index c25d1f57d6..9752a07b66 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2133,6 +2133,7 @@ Returns a string with the requested data about the region
 	<string name="InvFolder All">All</string>
 
 	<string name="no_attachments">No attachments worn</string>
+    <string name="Attachments remain">Attachments ([COUNT] slots remain)</string>
 
 	<!-- inventory FVBridge -->
 	<!--  This is used in llpanelinventory.cpp when constructing a context menu for an item for Sale  -->
@@ -3358,6 +3359,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <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="you_paid_failure_ldollars">You failed to pay [NAME] L$[AMOUNT] [REASON].</string>
+  <string name="you_paid_failure_ldollars_no_info">You failed to pay L$[AMOUNT].</string>
+  <string name="you_paid_failure_ldollars_no_reason">You failed to pay [NAME] L$[AMOUNT].</string>
+  <string name="you_paid_failure_ldollars_no_name">You failed to pay 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>
-- 
cgit v1.2.3


From 2455a4bb00b399e5cd5f22e9b177ca2aeaad2ba2 Mon Sep 17 00:00:00 2001
From: Seth ProductEngine <slitovchuk@productengine.com>
Date: Wed, 21 Dec 2011 14:09:56 +0200
Subject: EXP-1695 FIXED currency format in Group Profile > Land/Asset and New
 Group.

---
 indra/newview/llpanelgrouplandmoney.cpp                    |  3 +--
 indra/newview/skins/default/xui/en/panel_group_general.xml | 13 +++++++++++--
 indra/newview/skins/default/xui/en/strings.xml             |  2 +-
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index e66dd5690c..b6c0c2ee24 100644
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -1447,8 +1447,7 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg,
 
 		text.append(time_str);
 		text.append(".\n\n");
-		text.append(llformat("%-23sL$%6d\n", LLTrans::getString("GroupMoneyBalance").c_str(), balance ));
-		text.append(1, '\n');
+		text.append(llformat("%-24s %6d L$\n\n", LLTrans::getString("GroupMoneyBalance").c_str(), balance ));
 	}
 
 	// [DEV-29503] Hide the individual info since
diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml
index 38b680ba86..adde982c60 100644
--- a/indra/newview/skins/default/xui/en/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_general.xml
@@ -225,13 +225,22 @@ Hover your mouse over the options for more help.
          height="23"
          increment="1"
          label_width="15"
-         label="L$"
          layout="topleft"
          max_val="99999"
          left="30"
          name="spin_enrollment_fee"
          tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked."
-         width="170" />
+         width="150" />
+        <text
+         follows="left|top"
+         type="string"
+         height="16"
+         left_pad="2"
+         name="currency_label"
+         top_delta="5"
+         width="18">
+         L$
+        </text>
         <combo_box
          follows="left|top"
          height="23"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index c25d1f57d6..ac5b027ea1 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2271,7 +2271,7 @@ Returns a string with the requested data about the region
 	<string name="NextStipendDay"       value="The next stipend day is " />
 	<string name="GroupPlanningDate">[mthnum,datetime,utc]/[day,datetime,utc]/[year,datetime,utc]</string>
 	<string name="GroupIndividualShare" value="                      Group       Individual Share" />
-	<string name="GroupColumn"          value="                      Group" />
+	<string name="GroupColumn"          value="Group" />
 	<string name="Balance">Balance</string>
 	<string name="Credits">Credits</string>
 	<string name="Debits">Debits</string>
-- 
cgit v1.2.3


From 0ccf2b5a1c08c897326c0ce47caa48e30ec4b5fa Mon Sep 17 00:00:00 2001
From: Seth ProductEngine <slitovchuk@productengine.com>
Date: Wed, 21 Dec 2011 14:10:02 +0200
Subject: EXP-1693 FIXED the date localization in Item Profile window, Voice
 Morphs window and in scroll list widget in general. - Added a customizable
 date format string to be used for scroll list cell of "date" type. - The date
 localization does not change the value of a scroll list cell changing only
 its string representation. - Added using localized week days and month names
 from strings.xml for all locales not only Ja and Pl as it was before. -
 Changed the date format in Item Profile window (French locale) as noted in
 the issue description. - For this fix the French locale still needs the
 localization of the following strings in strings.xml: 	<string
 name="dateTimeWeekdaysNames"> 	<string name="dateTimeWeekdaysShortNames"> 
 <string name="dateTimeMonthNames"> 	<string
 name="dateTimeMonthShortNames"> 	<string name="dateTimeDayFormat"> 
 <string name="dateTimeAM"> 	<string name="dateTimePM">

---
 indra/llcommon/llstring.cpp                        |  5 +++++
 indra/llui/llscrolllistcell.cpp                    | 10 +++++++++-
 indra/newview/llappviewer.cpp                      | 23 ++++++++--------------
 indra/newview/skins/default/xui/en/strings.xml     |  3 +++
 .../skins/default/xui/fr/sidepanel_item_info.xml   |  2 +-
 5 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index e7fe656808..1193a4ef8d 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -1122,6 +1122,11 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
 		struct tm * gmt = gmtime (&loc_seconds);
 		replacement = LLStringOps::sMonthList[gmt->tm_mon];
 	}
+	else if(LLStringOps::sMonthShortList.size() == 12 && code == "%b")
+	{
+		struct tm * gmt = gmtime (&loc_seconds);
+		replacement = LLStringOps::sMonthShortList[gmt->tm_mon];
+	}
 	else if( !LLStringOps::sDayFormat.empty() && code == "%d" )
 	{
 		struct tm * gmt = gmtime (&loc_seconds);
diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
index 9d25c7180d..786e18b187 100644
--- a/indra/llui/llscrolllistcell.cpp
+++ b/indra/llui/llscrolllistcell.cpp
@@ -29,6 +29,8 @@
 
 #include "llscrolllistcell.h"
 
+#include "lltrans.h"
+
 #include "llcheckboxctrl.h"
 #include "llui.h"	// LLUIImage
 #include "lluictrlfactory.h"
@@ -428,7 +430,13 @@ LLScrollListDate::LLScrollListDate( const LLScrollListCell::Params& p)
 void LLScrollListDate::setValue(const LLSD& value)
 {
 	mDate = value.asDate();
-	LLScrollListText::setValue(mDate.asRFC1123());
+
+	std::string date_str = LLTrans::getString("ScrollListCellDateFormat");
+	LLSD substitution;
+	substitution["datetime"] = mDate.secondsSinceEpoch();
+	LLStringUtil::format(date_str, substitution);
+
+	LLScrollListText::setValue(date_str);
 }
 
 const LLSD LLScrollListDate::getValue() const
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b45f9c55fb..9595e82a07 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1043,21 +1043,14 @@ bool LLAppViewer::init()
 
 	LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
 
-	//EXT-7013 - On windows for some locale (Japanese) standard 
-	//datetime formatting functions didn't support some parameters such as "weekday".
-	//Names for days and months localized in xml are also useful for Polish locale(STORM-107).
-	std::string language = gSavedSettings.getString("Language");
-	if(language == "ja" || language == "pl")
-	{
-		LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
-		LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
-		LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
-		LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
-		LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
-
-		LLStringOps::sAM = LLTrans::getString("dateTimeAM");
-		LLStringOps::sPM = LLTrans::getString("dateTimePM");
-	}
+	LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
+	LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
+	LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
+	LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
+	LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
+
+	LLStringOps::sAM = LLTrans::getString("dateTimeAM");
+	LLStringOps::sPM = LLTrans::getString("dateTimePM");
 
 	LLAgentLanguage::init();
 
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index ac5b027ea1..e31fd167bc 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3498,6 +3498,9 @@ Abuse Report</string>
   <string name="dateTimeDayFormat">[MDAY]</string>
   <string name="dateTimeAM">AM</string>
   <string name="dateTimePM">PM</string>
+  
+  <!-- Format string for displaying a localized date in a scroll list cell of type "date" -->
+  <string name="ScrollListCellDateFormat">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</string>
 
   <!--  currency formatting -->
   <string name="LocalEstimateUSD">US$ [AMOUNT]</string>
diff --git a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml
index 95649d3934..0b5333fc80 100644
--- a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml
+++ b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml
@@ -13,7 +13,7 @@
 		Le propriétaire peut :
 	</panel.string>
 	<panel.string name="acquiredDate">
-		[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+		[wkday,datetime,local] [day,datetime,local] [mth,datetime,local] [year,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local]
 	</panel.string>
 	<panel.string name="origin_inventory">
 		(inventaire)
-- 
cgit v1.2.3


From 14c09c3ce597e47f5c41bb45246e89a1f31d89b0 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 21 Dec 2011 10:06:26 -0500
Subject: Add unit-test module for LLProcessLauncher. As always with llcommon,
 this is expressed as an "integration test" to sidestep a circular dependency:
 the llcommon build depends on its unit tests, but all our unit tests depend
 on llcommon. Initial test code is more for human verification than automated
 verification: does APR's child-process management in fact support nonblocking
 operations?

---
 indra/llcommon/CMakeLists.txt                   |   1 +
 indra/llcommon/tests/llprocesslauncher_test.cpp | 144 ++++++++++++++++++++++++
 2 files changed, 145 insertions(+)
 create mode 100644 indra/llcommon/tests/llprocesslauncher_test.cpp

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 0a3eaec5c5..c8e1827584 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -326,6 +326,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llprocesslauncher "" "${test_libs}")
 
   # *TODO - reenable these once tcmalloc libs no longer break the build.
   #ADD_BUILD_TEST(llallocator llcommon)
diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
new file mode 100644
index 0000000000..3b5602f620
--- /dev/null
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -0,0 +1,144 @@
+/**
+ * @file   llprocesslauncher_test.cpp
+ * @author Nat Goodspeed
+ * @date   2011-12-19
+ * @brief  Test for llprocesslauncher.
+ * 
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Copyright (c) 2011, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llprocesslauncher.h"
+// STL headers
+#include <vector>
+// std headers
+// external library headers
+#include "llapr.h"
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+// other Linden headers
+#include "../test/lltut.h"
+
+class APR
+{
+public:
+    APR():
+        pool(NULL)
+    {
+        apr_initialize();
+        apr_pool_create(&pool, NULL);
+    }
+
+    ~APR()
+    {
+        apr_terminate();
+    }
+
+    std::string strerror(apr_status_t rv)
+    {
+        char errbuf[256];
+        apr_strerror(rv, errbuf, sizeof(errbuf));
+        return errbuf;
+    }
+
+    apr_pool_t *pool;
+};
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct llprocesslauncher_data
+    {
+        void aprchk(apr_status_t rv)
+        {
+            ensure_equals(apr.strerror(rv), rv, APR_SUCCESS);
+        }
+
+        APR apr;
+    };
+    typedef test_group<llprocesslauncher_data> llprocesslauncher_group;
+    typedef llprocesslauncher_group::object object;
+    llprocesslauncher_group llprocesslaunchergrp("llprocesslauncher");
+
+    template<> template<>
+    void object::test<1>()
+    {
+        set_test_name("raw APR nonblocking I/O");
+
+        apr_procattr_t *procattr = NULL;
+        aprchk(apr_procattr_create(&procattr, apr.pool));
+        aprchk(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK));
+        aprchk(apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH));
+
+        std::vector<const char*> argv;
+        apr_proc_t child;
+        argv.push_back("python");
+        argv.push_back("-c");
+        argv.push_back("raise RuntimeError('Hello from Python!')");
+        argv.push_back(NULL);
+
+        aprchk(apr_proc_create(&child, argv[0],
+                               static_cast<const char* const*>(&argv[0]),
+                               NULL, // if we wanted to pass explicit environment
+                               procattr,
+                               apr.pool));
+
+        typedef std::pair<std::string, apr_file_t*> DescFile;
+        typedef std::vector<DescFile> DescFileVec;
+        DescFileVec outfiles;
+        outfiles.push_back(DescFile("out", child.out));
+        outfiles.push_back(DescFile("err", child.err));
+
+        while (! outfiles.empty())
+        {
+            DescFileVec iterfiles(outfiles);
+            for (size_t i = 0; i < iterfiles.size(); ++i)
+            {
+                char buf[4096];
+
+                apr_status_t rv = apr_file_gets(buf, sizeof(buf), iterfiles[i].second);
+                if (APR_STATUS_IS_EOF(rv))
+                {
+                    std::cout << "(EOF on " << iterfiles[i].first << ")\n";
+                    outfiles.erase(outfiles.begin() + i);
+                    continue;
+                }
+                if (rv != APR_SUCCESS)
+                {
+                    std::cout << "(waiting; apr_file_gets(" << iterfiles[i].first << ") => " << rv << ": " << apr.strerror(rv) << ")\n";
+                    continue;
+                }
+                // Is it even possible to get APR_SUCCESS but read 0 bytes?
+                // Hope not, but defend against that anyway.
+                if (buf[0])
+                {
+                    std::cout << iterfiles[i].first << ": " << buf;
+                    // Just for pretty output... if we only read a partial
+                    // line, terminate it.
+                    if (buf[strlen(buf) - 1] != '\n')
+                        std::cout << "...\n";
+                }
+            }
+            sleep(1);
+        }
+        apr_file_close(child.in);
+        apr_file_close(child.out);
+        apr_file_close(child.err);
+
+        int rc = 0;
+        apr_exit_why_e why;
+        apr_status_t rv;
+        while (! APR_STATUS_IS_CHILD_DONE(rv = apr_proc_wait(&child, &rc, &why, APR_NOWAIT)))
+        {
+            std::cout << "child not done (" << rv << "): " << apr.strerror(rv) << '\n';
+            sleep(0.5);
+        }
+        std::cout << "child done: rv = " << rv << " (" << apr.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
+    }
+} // namespace tut
-- 
cgit v1.2.3


From 7832d8eccb00d32b6122e5851238e962f65af1e8 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 21 Dec 2011 11:12:48 -0500
Subject: Fix llprocesslauncher_test.cpp to work on Windows.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 3b5602f620..4d14e1be53 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -12,6 +12,7 @@
 // Precompiled header
 #include "linden_common.h"
 // associated header
+#define WIN32_LEAN_AND_MEAN
 #include "llprocesslauncher.h"
 // STL headers
 #include <vector>
@@ -23,6 +24,10 @@
 // other Linden headers
 #include "../test/lltut.h"
 
+#if defined(LL_WINDOWS)
+#define sleep _sleep
+#endif
+
 class APR
 {
 public:
-- 
cgit v1.2.3


From 5546041301a67da6e471a433b29374bc75a4f0d0 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 21 Dec 2011 15:55:14 -0600
Subject: SH-2794 WIP -- work on getting glMapBuffer and friends to behave

---
 indra/llrender/llvertexbuffer.cpp       |  52 ++++++---
 indra/llrender/llvertexbuffer.h         |  22 ++--
 indra/newview/llface.cpp                | 194 ++++++++++++++++++++++++--------
 indra/newview/llfloatermodelpreview.cpp |  12 +-
 indra/newview/llvosurfacepatch.cpp      |   2 +-
 5 files changed, 199 insertions(+), 83 deletions(-)

diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 20a450fbfb..f8c2a55820 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -148,7 +148,7 @@ U32 wpo2(U32 i)
 	return r;
 }
 
-U8* LLVBOPool::allocate(U32& name, U32 size)
+volatile U8* LLVBOPool::allocate(U32& name, U32 size)
 {
 	llassert(nhpo2(size) == size);
 
@@ -159,7 +159,7 @@ U8* LLVBOPool::allocate(U32& name, U32 size)
 		mFreeList.resize(i+1);
 	}
 
-	U8* ret = NULL;
+	volatile U8* ret = NULL;
 
 	if (mFreeList[i].empty())
 	{
@@ -188,7 +188,7 @@ U8* LLVBOPool::allocate(U32& name, U32 size)
 	return ret;
 }
 
-void LLVBOPool::release(U32 name, U8* buffer, U32 size)
+void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
 {
 	llassert(nhpo2(size) == size);
 
@@ -221,7 +221,7 @@ void LLVBOPool::cleanup()
 
 			if (r.mClientData)
 			{
-				ll_aligned_free_16(r.mClientData);
+				ll_aligned_free_16((void*) r.mClientData);
 			}
 
 			l.pop_front();
@@ -1042,7 +1042,7 @@ void LLVertexBuffer::destroyGLBuffer()
 		}
 		else
 		{
-			FREE_MEM(sPrivatePoolp, mMappedData) ;
+			FREE_MEM(sPrivatePoolp, (void*) mMappedData) ;
 			mMappedData = NULL;
 			mEmpty = TRUE;
 		}
@@ -1063,7 +1063,7 @@ void LLVertexBuffer::destroyGLIndices()
 		}
 		else
 		{
-			FREE_MEM(sPrivatePoolp, mMappedIndexData) ;
+			FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData) ;
 			mMappedIndexData = NULL;
 			mEmpty = TRUE;
 		}
@@ -1282,8 +1282,11 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
 	return true;
 }
 
+static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER_RANGE("VBO Map Range");
+static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER("VBO Map");
+
 // Map for data access
-U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
+volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
 {
 	bindGLBuffer(true);
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
@@ -1346,13 +1349,14 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 			}
 			else
 			{
-				U8* src = NULL;
+				volatile U8* src = NULL;
 				waitFence();
 				if (gGLManager.mHasMapBufferRange)
 				{
 					if (map_range)
 					{
 #ifdef GL_ARB_map_buffer_range
+						LLFastTimer t(FTM_VBO_MAP_BUFFER_RANGE);
 						S32 offset = mOffsets[type] + sTypeSize[type]*index;
 						S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
 						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, 
@@ -1376,6 +1380,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 							}
 						}
 
+						LLFastTimer t(FTM_VBO_MAP_BUFFER);
 						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, 
 							GL_MAP_WRITE_BIT | 
 							GL_MAP_FLUSH_EXPLICIT_BIT);
@@ -1403,7 +1408,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 
 				llassert(src != NULL);
 
-				mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
+				mMappedData = LL_NEXT_ALIGNED_ADDRESS<volatile U8>(src);
 				mAlignedOffset = mMappedData - src;
 			
 				stop_glerror();
@@ -1458,7 +1463,11 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 	}
 }
 
-U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
+
+static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX_RANGE("IBO Map Range");
+static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX("IBO Map");
+
+volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
 	bindGLIndices(true);
@@ -1530,13 +1539,14 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 			}
 			else
 			{
-				U8* src = NULL;
+				volatile U8* src = NULL;
 				waitFence();
 				if (gGLManager.mHasMapBufferRange)
 				{
 					if (map_range)
 					{
 #ifdef GL_ARB_map_buffer_range
+						LLFastTimer t(FTM_VBO_MAP_INDEX_RANGE);
 						S32 offset = sizeof(U16)*index;
 						S32 length = sizeof(U16)*count;
 						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, 
@@ -1548,6 +1558,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 					else
 					{
 #ifdef GL_ARB_map_buffer_range
+						LLFastTimer t(FTM_VBO_MAP_INDEX);
 						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, 
 							GL_MAP_WRITE_BIT | 
 							GL_MAP_FLUSH_EXPLICIT_BIT);
@@ -1569,6 +1580,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 				}
 				else
 				{
+					LLFastTimer t(FTM_VBO_MAP_INDEX);
 					map_range = false;
 					src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
 				}
@@ -1619,6 +1631,8 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 	}
 }
 
+static LLFastTimer::DeclareTimer FTM_VBO_UNMAP("VBO Unmap");
+
 void LLVertexBuffer::unmapBuffer()
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
@@ -1627,6 +1641,8 @@ void LLVertexBuffer::unmapBuffer()
 		return ; //nothing to unmap
 	}
 
+	LLFastTimer t(FTM_VBO_UNMAP);
+
 	bool updated_all = false ;
 
 	if (mMappedData && mVertexLocked)
@@ -1644,7 +1660,7 @@ void LLVertexBuffer::unmapBuffer()
 					const MappedRegion& region = mMappedVertexRegions[i];
 					S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
 					S32 length = sTypeSize[region.mType]*region.mCount;
-					glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, mMappedData+offset);
+					glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedData+offset);
 					stop_glerror();
 				}
 
@@ -1653,7 +1669,7 @@ void LLVertexBuffer::unmapBuffer()
 			else
 			{
 				stop_glerror();
-				glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
+				glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (U8*) mMappedData);
 				stop_glerror();
 			}
 		}
@@ -1708,7 +1724,7 @@ void LLVertexBuffer::unmapBuffer()
 					const MappedRegion& region = mMappedIndexRegions[i];
 					S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
 					S32 length = sizeof(U16)*region.mCount;
-					glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, mMappedIndexData+offset);
+					glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedIndexData+offset);
 					stop_glerror();
 				}
 
@@ -1717,7 +1733,7 @@ void LLVertexBuffer::unmapBuffer()
 			else
 			{
 				stop_glerror();
-				glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
+				glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (U8*) mMappedIndexData);
 				stop_glerror();
 			}
 		}
@@ -1778,7 +1794,7 @@ template <class T,S32 type> struct VertexBufferStrider
 	{
 		if (type == LLVertexBuffer::TYPE_INDEX)
 		{
-			U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
+			volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
 
 			if (ptr == NULL)
 			{
@@ -1794,7 +1810,7 @@ template <class T,S32 type> struct VertexBufferStrider
 		{
 			S32 stride = LLVertexBuffer::sTypeSize[type];
 
-			U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
+			volatile U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
 
 			if (ptr == NULL)
 			{
@@ -2109,7 +2125,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER);
 	stop_glerror();
-	U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
+	volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
 
 	/*if ((data_mask & mTypeMask) != data_mask)
 	{
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 3e6f6a959a..5b93a0389f 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -60,10 +60,10 @@ public:
 	U32 mType;
 
 	//size MUST be a power of 2
-	U8* allocate(U32& name, U32 size);
+	volatile U8* allocate(U32& name, U32 size);
 	
 	//size MUST be the size provided to allocate that returned the given name
-	void release(U32 name, U8* buffer, U32 size);
+	void release(U32 name, volatile U8* buffer, U32 size);
 	
 	//destroy all records in mFreeList
 	void cleanup();
@@ -72,7 +72,7 @@ public:
 	{
 	public:
 		U32 mGLName;
-		U8* mClientData;
+		volatile U8* mClientData;
 	};
 
 	typedef std::list<Record> record_list_t;
@@ -208,8 +208,8 @@ public:
 	LLVertexBuffer(U32 typemask, S32 usage);
 	
 	// map for data access
-	U8*		mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
-	U8*		mapIndexBuffer(S32 index, S32 count, bool map_range);
+	volatile U8*		mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
+	volatile U8*		mapIndexBuffer(S32 index, S32 count, bool map_range);
 
 	// set for rendering
 	virtual void	setBuffer(U32 data_mask); 	// calls  setupVertexBuffer() if data_mask is not 0
@@ -244,14 +244,14 @@ public:
 	S32 getNumVerts() const					{ return mNumVerts; }
 	S32 getNumIndices() const				{ return mNumIndices; }
 	
-	U8* getIndicesPointer() const			{ return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
-	U8* getVerticesPointer() const			{ return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
+	volatile U8* getIndicesPointer() const			{ return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
+	volatile U8* getVerticesPointer() const			{ return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
 	U32 getTypeMask() const					{ return mTypeMask; }
 	bool hasDataType(S32 type) const		{ return ((1 << type) & getTypeMask()); }
 	S32 getSize() const;
 	S32 getIndicesSize() const				{ return mIndicesSize; }
-	U8* getMappedData() const				{ return mMappedData; }
-	U8* getMappedIndices() const			{ return mMappedIndexData; }
+	volatile U8* getMappedData() const				{ return mMappedData; }
+	volatile U8* getMappedIndices() const			{ return mMappedIndexData; }
 	S32 getOffset(S32 type) const			{ return mOffsets[type]; }
 	S32 getUsage() const					{ return mUsage; }
 
@@ -278,8 +278,8 @@ protected:
 	U32		mGLIndices;		// GL IBO handle
 	U32		mGLArray;		// GL VAO handle
 	
-	U8*		mMappedData;	// pointer to currently mapped data (NULL if unmapped)
-	U8*		mMappedIndexData;	// pointer to currently mapped indices (NULL if unmapped)
+	volatile U8* mMappedData;	// pointer to currently mapped data (NULL if unmapped)
+	volatile U8* mMappedIndexData;	// pointer to currently mapped indices (NULL if unmapped)
 	BOOL	mVertexLocked;			// if TRUE, vertex buffer is being or has been written to in client memory
 	BOOL	mIndexLocked;			// if TRUE, index buffer is being or has been written to in client memory
 	BOOL	mFinal;			// if TRUE, buffer can not be mapped again
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 6dbeae6677..941b8db2cf 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -693,6 +693,49 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of
 	tex_coord.mV[1] = t;
 }
 
+// Transform the texture coordinates for this face.
+static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVector4Logical& mask, const LLVector4a& rot0, const LLVector4a& rot1, const LLVector4a& offset, const LLVector4a& scale) 
+{
+	//tex coord is two coords, <s0, t0, s1, t1>
+	LLVector4a st;
+
+	// Texture transforms are done about the center of the face.
+	st.setAdd(tex_coord, trans);
+	
+	// Handle rotation
+	LLVector4a rot_st;
+		
+	// <s0 * cosAng, s0*-sinAng, s1*cosAng, s1*-sinAng>
+	LLVector4a s0;
+	s0.splat(st, 0);
+	LLVector4a s1;
+	s1.splat(st, 2);
+	LLVector4a ss;
+	ss.setSelectWithMask(mask, s1, s0);
+
+	LLVector4a a; 
+	a.setMul(rot0, ss);
+	
+	// <t0*sinAng, t0*cosAng, t1*sinAng, t1*cosAng>
+	LLVector4a t0;
+	t0.splat(st, 1);
+	LLVector4a t1;
+	t1.splat(st, 3);
+	LLVector4a tt;
+	tt.setSelectWithMask(mask, t1, t0);
+
+	LLVector4a b;
+	b.setMul(rot1, tt);
+		
+	st.setAdd(a,b);
+
+	// Then scale
+	st.mul(scale);
+
+	// Then offset
+	tex_coord.setAdd(st, offset);
+}
+
 
 bool less_than_max_mag(const LLVector4a& vec)
 {
@@ -1060,6 +1103,16 @@ static LLFastTimer::DeclareTimer FTM_FACE_GEOM_EMISSIVE("Emissive");
 static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights");
 static LLFastTimer::DeclareTimer FTM_FACE_GEOM_BINORMAL("Binormal");
 static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index");
+static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX_TAIL("Tail");
+static LLFastTimer::DeclareTimer FTM_FACE_POSITION_STORE("Pos");
+static LLFastTimer::DeclareTimer FTM_FACE_TEXTURE_INDEX_STORE("TexIdx");
+static LLFastTimer::DeclareTimer FTM_FACE_POSITION_PAD("Pad");
+static LLFastTimer::DeclareTimer FTM_FACE_TEX_DEFAULT("Default");
+static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK("Quick");
+static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_NO_XFORM("No Xform");
+static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_XFORM("Xform");
+
+static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_PLANAR("Quick Planar");
 
 BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 							   const S32 &f,
@@ -1104,16 +1157,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	}
 
 	LLStrider<LLVector3> vert;
-	LLVector4a* vertices = NULL;
 	LLStrider<LLVector2> tex_coords;
 	LLStrider<LLVector2> tex_coords2;
-	LLVector4a* normals = NULL;
 	LLStrider<LLVector3> norm;
 	LLStrider<LLColor4U> colors;
-	LLVector4a* binormals = NULL;
 	LLStrider<LLVector3> binorm;
 	LLStrider<U16> indicesp;
-	LLVector4a* weights = NULL;
 	LLStrider<LLVector4> wght;
 
 	BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
@@ -1202,7 +1251,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		LLFastTimer t(FTM_FACE_GEOM_INDEX);
 		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, map_range);
 
-		__m128i* dst = (__m128i*) indicesp.get();
+		volatile __m128i* dst = (__m128i*) indicesp.get();
 		__m128i* src = (__m128i*) vf.mIndices;
 		__m128i offset = _mm_set1_epi16(index_offset);
 
@@ -1211,12 +1260,17 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		for (S32 i = 0; i < end; i++)
 		{
 			__m128i res = _mm_add_epi16(src[i], offset);
-			_mm_storeu_si128(dst+i, res);
+			_mm_storeu_si128((__m128i*) dst++, res);
 		}
 
-		for (S32 i = end*8; i < num_indices; ++i)
 		{
-			indicesp[i] = vf.mIndices[i]+index_offset;
+			LLFastTimer t(FTM_FACE_GEOM_INDEX_TAIL);
+			U16* idx = (U16*) dst;
+
+			for (S32 i = end*8; i < num_indices; ++i)
+			{
+				*idx++ = vf.mIndices[i]+index_offset;
+			}
 		}
 
 		if (map_range)
@@ -1373,19 +1427,48 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 			if (texgen != LLTextureEntry::TEX_GEN_PLANAR)
 			{
+				LLFastTimer t(FTM_FACE_TEX_QUICK);
 				if (!do_tex_mat)
 				{
 					if (!do_xform)
 					{
+						LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM);
 						LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32));
 					}
 					else
 					{
-						for (S32 i = 0; i < num_vertices; i++)
+						LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM);
+						F32* dst = (F32*) tex_coords.get();
+						LLVector4a* src = (LLVector4a*) vf.mTexCoords;
+
+						LLVector4a trans;
+						trans.splat(-0.5f);
+
+						LLVector4a rot0;
+						rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang);
+
+						LLVector4a rot1;
+						rot1.set(sin_ang, cos_ang, sin_ang, cos_ang);
+
+						LLVector4a scale;
+						scale.set(ms, mt, ms, mt);
+
+						LLVector4a offset;
+						offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f);
+
+						LLVector4Logical mask;
+						mask.clear();
+						mask.setElement<2>();
+						mask.setElement<3>();
+
+						U32 count = num_vertices/2 + num_vertices%2;
+
+						for (S32 i = 0; i < count; i++)
 						{	
-							LLVector2 tc(vf.mTexCoords[i]);
-							xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
-							*tex_coords++ = tc;	
+							LLVector4a res = *src++;
+							xform4a(res, trans, mask, rot0, rot1, offset, scale);
+							res.store4a(dst);
+							dst += 4;
 						}
 					}
 				}
@@ -1407,6 +1490,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			}
 			else
 			{ //no bump, no atlas, tex gen planar
+				LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR);
 				if (do_tex_mat)
 				{
 					for (S32 i = 0; i < num_vertices; i++)
@@ -1451,6 +1535,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		}
 		else
 		{ //either bump mapped or in atlas, just do the whole expensive loop
+			LLFastTimer t(FTM_FACE_TEX_DEFAULT);
 			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range);
 
 			std::vector<LLVector2> bump_tc;
@@ -1642,44 +1727,55 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		llassert(num_vertices > 0);
 		
 		mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range);
-		vertices = (LLVector4a*) vert.get();
-	
+			
+
 		LLMatrix4a mat_vert;
 		mat_vert.loadu(mat_vert_in);
 
 		LLVector4a* src = vf.mPositions;
-		LLVector4a* dst = vertices;
+		volatile F32* dst = (volatile F32*) vert.get();
 
-		LLVector4a* end = dst+num_vertices;
-		do
-		{	
-			mat_vert.affineTransform(*src++, *dst++);
-		}
-		while(dst < end);
+		volatile F32* end = dst+num_vertices*4;
+		LLVector4a res;
 
-		F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0);
+		LLVector4a texIdx;
 
+		F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0);
 		llassert(index <= LLGLSLShader::sIndexedTextureChannels-1);
-		F32 *index_dst = (F32*) vertices;
-		F32 *index_end = (F32*) end;
 
-		index_dst += 3;
-		index_end += 3;
-		do
+		LLVector4Logical mask;
+		mask.clear();
+		mask.setElement<3>();
+		
+		texIdx.set(0,0,0,index);
+
 		{
-			*index_dst = index;
-			index_dst += 4;
+			LLFastTimer t(FTM_FACE_POSITION_STORE);
+			LLVector4a tmp;
+
+			do
+			{	
+				mat_vert.affineTransform(*src++, res);
+				tmp.setSelectWithMask(mask, texIdx, res);
+				tmp.store4a((F32*) dst);
+				dst += 4;
+			}
+			while(dst < end);
 		}
-		while (index_dst < index_end);
-		
-		S32 aligned_pad_vertices = mGeomCount - num_vertices;
-		LLVector4a* last_vec = end - 1;
-		while (aligned_pad_vertices > 0)
+
 		{
-			--aligned_pad_vertices;
-			*dst++ = *last_vec;
+			LLFastTimer t(FTM_FACE_POSITION_PAD);
+			S32 aligned_pad_vertices = mGeomCount - num_vertices;
+			res.set(res[0], res[1], res[2], 0.f);
+
+			while (aligned_pad_vertices > 0)
+			{
+				--aligned_pad_vertices;
+				res.store4a((F32*) dst);
+				dst += 4;
+			}
 		}
-		
+
 		if (map_range)
 		{
 			mVertexBuffer->flush();
@@ -1690,14 +1786,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	{
 		LLFastTimer t(FTM_FACE_GEOM_NORMAL);
 		mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range);
-		normals = (LLVector4a*) norm.get();
+		F32* normals = (F32*) norm.get();
 	
 		for (S32 i = 0; i < num_vertices; i++)
 		{	
 			LLVector4a normal;
 			mat_normal.rotate(vf.mNormals[i], normal);
 			normal.normalize3fast();
-			normals[i] = normal;
+			normal.store4a(normals);
+			normals += 4;
 		}
 
 		if (map_range)
@@ -1710,14 +1807,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	{
 		LLFastTimer t(FTM_FACE_GEOM_BINORMAL);
 		mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range);
-		binormals = (LLVector4a*) binorm.get();
+		F32* binormals = (F32*) binorm.get();
 		
 		for (S32 i = 0; i < num_vertices; i++)
 		{	
 			LLVector4a binormal;
 			mat_normal.rotate(vf.mBinormals[i], binormal);
 			binormal.normalize3fast();
-			binormals[i] = binormal;
+			binormal.store4a(binormals);
+			binormals += 4;
 		}
 
 		if (map_range)
@@ -1730,8 +1828,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	{
 		LLFastTimer t(FTM_FACE_GEOM_WEIGHTS);
 		mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range);
-		weights = (LLVector4a*) wght.get();
-		LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32));
+		F32* weights = (F32*) wght.get();
+		LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32));
 		if (map_range)
 		{
 			mVertexBuffer->flush();
@@ -1750,7 +1848,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		
 		src.loadua((F32*) vec);
 
-		LLVector4a* dst = (LLVector4a*) colors.get();
+		F32* dst = (F32*) colors.get();
 		S32 num_vecs = num_vertices/4;
 		if (num_vertices%4 > 0)
 		{
@@ -1759,7 +1857,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 		for (S32 i = 0; i < num_vecs; i++)
 		{	
-			dst[i] = src;
+			src.store4a(dst);
+			dst += 4;
 		}
 
 		if (map_range)
@@ -1789,7 +1888,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		
 		src.loadua((F32*) vec);
 
-		LLVector4a* dst = (LLVector4a*) emissive.get();
+		F32* dst = (F32*) emissive.get();
 		S32 num_vecs = num_vertices/4;
 		if (num_vertices%4 > 0)
 		{
@@ -1798,7 +1897,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 		for (S32 i = 0; i < num_vecs; i++)
 		{	
-			dst[i] = src;
+			src.store4a(dst);
+			dst += 4;
 		}
 
 		if (map_range)
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 64bdcccd9f..9122e5a8f5 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -3969,7 +3969,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
 				U32 num_indices = mVertexBuffer[5][mdl][i]->getNumIndices();
 				if (num_indices > 2)
 				{
-					glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f);
+					glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, (U8*) mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f);
 				}
 				tri_count += num_indices/3;
 				stop_gloderror();
@@ -4083,14 +4083,14 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
 				{
 					buff->allocateBuffer(sizes[i*2+1], sizes[i*2], true);
 					buff->setBuffer(type_mask);
-					glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, buff->getIndicesPointer());
+					glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, (U8*) buff->getIndicesPointer());
 					stop_gloderror();
 				}
 				else
 				{ //this face was eliminated, create a dummy triangle (one vertex, 3 indices, all 0)
 					buff->allocateBuffer(1, 3, true);
-					memset(buff->getMappedData(), 0, buff->getSize());
-					memset(buff->getIndicesPointer(), 0, buff->getIndicesSize());
+					memset((U8*) buff->getMappedData(), 0, buff->getSize());
+					memset((U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize());
 				}
 
 				buff->validateRange(0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
@@ -4880,8 +4880,8 @@ void LLModelPreview::addEmptyFace( LLModel* pTarget )
 	LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
 	
 	buff->allocateBuffer(1, 3, true);
-	memset( buff->getMappedData(), 0, buff->getSize() );
-	memset( buff->getIndicesPointer(), 0, buff->getIndicesSize() );
+	memset( (U8*) buff->getMappedData(), 0, buff->getSize() );
+	memset( (U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize() );
 		
 	buff->validateRange( 0, buff->getNumVerts()-1, buff->getNumIndices(), 0 );
 		
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index c3a2e6a712..bf6158eeaf 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -65,7 +65,7 @@ public:
 			return;
 		}
 
-		U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
+		volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
 
 		//assume tex coords 2 and 3 are present
 		U32 type_mask = mTypeMask | MAP_TEXCOORD2 | MAP_TEXCOORD3;
-- 
cgit v1.2.3


From 2fd0bc8648e71aa2f141fde4b3a6a0165f7ef4d6 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 21 Dec 2011 17:00:43 -0500
Subject: Change llprocesslauncher_test.cpp eyeballing to program verification.
 That is, where before we just flung stuff to stdout with the expectation that
 a human user would verify, replace with assertions in the test code itself.
 Quiet previous noise on stdout. Introduce a temp script file that produces
 output on both stdout and stderr, with sleep() calls so we predictably have
 to wait for it. Track and then verify the history of our interaction with the
 child process, noting especially EWOULDBLOCK attempts.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 97 ++++++++++++++++++++++---
 1 file changed, 85 insertions(+), 12 deletions(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 4d14e1be53..ca06b3164e 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -17,6 +17,7 @@
 // STL headers
 #include <vector>
 // std headers
+#include <errno.h>
 // external library headers
 #include "llapr.h"
 #include "apr_thread_proc.h"
@@ -71,11 +72,53 @@ namespace tut
     typedef llprocesslauncher_group::object object;
     llprocesslauncher_group llprocesslaunchergrp("llprocesslauncher");
 
+    struct Item
+    {
+        Item(): tries(0) {}
+        unsigned    tries;
+        std::string which;
+        std::string what;
+    };
+
     template<> template<>
     void object::test<1>()
     {
         set_test_name("raw APR nonblocking I/O");
 
+        // Create a script file in a temporary place.
+        const char* tempdir = NULL;
+        aprchk(apr_temp_dir_get(&tempdir, apr.pool));
+
+        // Construct a temp filename template in that directory.
+        char *tempname = NULL;
+        aprchk(apr_filepath_merge(&tempname, tempdir, "testXXXXXX", 0, apr.pool));
+
+        // Create a temp file from that template.
+        apr_file_t* fp = NULL;
+        aprchk(apr_file_mktemp(&fp, tempname, APR_CREATE | APR_WRITE | APR_EXCL, apr.pool));
+
+        // Write it.
+        const char script[] =
+            "import sys\n"
+            "import time\n"
+            "\n"
+            "time.sleep(2)\n"
+            "print >>sys.stdout, \"stdout after wait\"\n"
+            "sys.stdout.flush()\n"
+            "time.sleep(2)\n"
+            "print >>sys.stderr, \"stderr after wait\"\n"
+            "sys.stderr.flush()\n"
+            ;
+        apr_size_t len(sizeof(script)-1);
+        aprchk(apr_file_write(fp, script, &len));
+        aprchk(apr_file_close(fp));
+
+        // Arrange to track the history of our interaction with child: what we
+        // fetched, which pipe it came from, how many tries it took before we
+        // got it.
+        std::vector<Item> history;
+        history.push_back(Item());
+
         apr_procattr_t *procattr = NULL;
         aprchk(apr_procattr_create(&procattr, apr.pool));
         aprchk(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK));
@@ -84,8 +127,7 @@ namespace tut
         std::vector<const char*> argv;
         apr_proc_t child;
         argv.push_back("python");
-        argv.push_back("-c");
-        argv.push_back("raise RuntimeError('Hello from Python!')");
+        argv.push_back(tempname);
         argv.push_back(NULL);
 
         aprchk(apr_proc_create(&child, argv[0],
@@ -110,24 +152,35 @@ namespace tut
                 apr_status_t rv = apr_file_gets(buf, sizeof(buf), iterfiles[i].second);
                 if (APR_STATUS_IS_EOF(rv))
                 {
-                    std::cout << "(EOF on " << iterfiles[i].first << ")\n";
+//                  std::cout << "(EOF on " << iterfiles[i].first << ")\n";
+                    history.back().which = iterfiles[i].first;
+                    history.back().what  = "*eof*";
+                    history.push_back(Item());
                     outfiles.erase(outfiles.begin() + i);
                     continue;
                 }
-                if (rv != APR_SUCCESS)
+                if (rv == EWOULDBLOCK)
                 {
-                    std::cout << "(waiting; apr_file_gets(" << iterfiles[i].first << ") => " << rv << ": " << apr.strerror(rv) << ")\n";
+//                  std::cout << "(waiting; apr_file_gets(" << iterfiles[i].first << ") => " << rv << ": " << apr.strerror(rv) << ")\n";
+                    ++history.back().tries;
                     continue;
                 }
+                ensure_equals(rv, APR_SUCCESS);
                 // Is it even possible to get APR_SUCCESS but read 0 bytes?
                 // Hope not, but defend against that anyway.
                 if (buf[0])
                 {
-                    std::cout << iterfiles[i].first << ": " << buf;
-                    // Just for pretty output... if we only read a partial
-                    // line, terminate it.
-                    if (buf[strlen(buf) - 1] != '\n')
-                        std::cout << "...\n";
+//                  std::cout << iterfiles[i].first << ": " << buf;
+                    history.back().which = iterfiles[i].first;
+                    history.back().what.append(buf);
+                    if (buf[strlen(buf) - 1] == '\n')
+                        history.push_back(Item());
+                    else
+                    {
+                        // Just for pretty output... if we only read a partial
+                        // line, terminate it.
+//                      std::cout << "...\n";
+                    }
                 }
             }
             sleep(1);
@@ -141,9 +194,29 @@ namespace tut
         apr_status_t rv;
         while (! APR_STATUS_IS_CHILD_DONE(rv = apr_proc_wait(&child, &rc, &why, APR_NOWAIT)))
         {
-            std::cout << "child not done (" << rv << "): " << apr.strerror(rv) << '\n';
+//          std::cout << "child not done (" << rv << "): " << apr.strerror(rv) << '\n';
             sleep(0.5);
         }
-        std::cout << "child done: rv = " << rv << " (" << apr.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
+//      std::cout << "child done: rv = " << rv << " (" << apr.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
+        ensure_equals(rv, APR_CHILD_DONE);
+        ensure_equals(why, APR_PROC_EXIT);
+        ensure_equals(rc, 0);
+
+        // Remove temp script file
+        aprchk(apr_file_remove(tempname, apr.pool));
+
+        // Beyond merely executing all the above successfully, verify that we
+        // obtained expected output -- and that we duly got control while
+        // waiting, proving the non-blocking nature of these pipes.
+        ensure("blocking I/O on child pipe (0)", history[0].tries);
+        ensure_equals(history[0].which, "out");
+        ensure_equals(history[0].what,  "stdout after wait\n");
+        ensure("blocking I/O on child pipe (1)", history[1].tries);
+        ensure_equals(history[1].which, "out");
+        ensure_equals(history[1].what,  "*eof*");
+        ensure_equals(history[2].which, "err");
+        ensure_equals(history[2].what,  "stderr after wait\n");
+        ensure_equals(history[3].which, "err");
+        ensure_equals(history[3].what,  "*eof*");
     }
 } // namespace tut
-- 
cgit v1.2.3


From ef08cd9dc619f692ce4e13ba1268c117a75ab2bf Mon Sep 17 00:00:00 2001
From: "Debi King (Dessie)" <dessie@lindenlab.com>
Date: Wed, 21 Dec 2011 17:55:12 -0500
Subject: Added tag DRTVWR-106_3.2.5-beta1, 3.2.5-beta1 for changeset
 3d2d5d244c63

---
 .hgtags | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.hgtags b/.hgtags
index 539efb0ffc..97e0cc033c 100644
--- a/.hgtags
+++ b/.hgtags
@@ -232,3 +232,5 @@ a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
 3fe994349fae64fc40874bb59db387131eb35a41 DRTVWR-104_3.2.4-beta1
 3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-beta1
 8a44ff3d2104269ce76145c2772cf1bdff2a2abe 3.2.5-start
+3d2d5d244c6398a4214c666d5dd3965b0918709a DRTVWR-106_3.2.5-beta1
+3d2d5d244c6398a4214c666d5dd3965b0918709a 3.2.5-beta1
-- 
cgit v1.2.3


From 25ef0cd2236aeb2d0047881e11a0022c4355cd48 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 21 Dec 2011 20:42:11 -0500
Subject: Tweak llprocesslauncher_test.cpp to run properly on Windows. Fix EOL
 issues: "\r\n" vs. "\n". On Windows, requesting a read in nonblocking mode
 can produce EAGAIN instead of EWOULDBLOCK.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 27 ++++++++++++++-----------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index ca06b3164e..bdae81770f 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -27,6 +27,9 @@
 
 #if defined(LL_WINDOWS)
 #define sleep _sleep
+#define EOL "\r\n"
+#else
+#define EOL "\n"
 #endif
 
 class APR
@@ -99,15 +102,15 @@ namespace tut
 
         // Write it.
         const char script[] =
-            "import sys\n"
-            "import time\n"
-            "\n"
-            "time.sleep(2)\n"
-            "print >>sys.stdout, \"stdout after wait\"\n"
-            "sys.stdout.flush()\n"
-            "time.sleep(2)\n"
-            "print >>sys.stderr, \"stderr after wait\"\n"
-            "sys.stderr.flush()\n"
+            "import sys" EOL
+            "import time" EOL
+            EOL
+            "time.sleep(2)" EOL
+            "print >>sys.stdout, \"stdout after wait\"" EOL
+            "sys.stdout.flush()" EOL
+            "time.sleep(2)" EOL
+            "print >>sys.stderr, \"stderr after wait\"" EOL
+            "sys.stderr.flush()" EOL
             ;
         apr_size_t len(sizeof(script)-1);
         aprchk(apr_file_write(fp, script, &len));
@@ -159,7 +162,7 @@ namespace tut
                     outfiles.erase(outfiles.begin() + i);
                     continue;
                 }
-                if (rv == EWOULDBLOCK)
+                if (rv == EWOULDBLOCK || rv == EAGAIN)
                 {
 //                  std::cout << "(waiting; apr_file_gets(" << iterfiles[i].first << ") => " << rv << ": " << apr.strerror(rv) << ")\n";
                     ++history.back().tries;
@@ -210,12 +213,12 @@ namespace tut
         // waiting, proving the non-blocking nature of these pipes.
         ensure("blocking I/O on child pipe (0)", history[0].tries);
         ensure_equals(history[0].which, "out");
-        ensure_equals(history[0].what,  "stdout after wait\n");
+        ensure_equals(history[0].what,  "stdout after wait" EOL);
         ensure("blocking I/O on child pipe (1)", history[1].tries);
         ensure_equals(history[1].which, "out");
         ensure_equals(history[1].what,  "*eof*");
         ensure_equals(history[2].which, "err");
-        ensure_equals(history[2].what,  "stderr after wait\n");
+        ensure_equals(history[2].what,  "stderr after wait" EOL);
         ensure_equals(history[3].which, "err");
         ensure_equals(history[3].what,  "*eof*");
     }
-- 
cgit v1.2.3


From 7fe5cbc5c2c288214a94c2c243cea08f30d815f3 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 22 Dec 2011 10:44:49 -0700
Subject: trivial: some debug code for SH-2623:
 [PUBLIC_JIRA_USERS][crashhunters] crash at
 LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *)

---
 indra/newview/llviewertexturelist.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index cddf7dcfea..089f45ca89 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -534,6 +534,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
 	S32 count = mImageList.erase(image) ;
 	if(count != 1) 
 	{
+		llinfos << image->getID() << llendl ;
 		llerrs << "Error happens when remove image from mImageList: " << count << llendl ;
 	}
       
@@ -919,6 +920,8 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
 		image_list.push_back(imagep);
 		imagep->setInImageList(FALSE) ;
 	}
+
+	llassert_always(image_list.size() == mImageList.size()) ;
 	mImageList.clear();
 	for (std::vector<LLPointer<LLViewerFetchedTexture> >::iterator iter = image_list.begin();
 		 iter != image_list.end(); ++iter)
-- 
cgit v1.2.3


From 39c3efbda3bc4c7b415aa851ec4f42f05acda0cb Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 22 Dec 2011 16:20:19 -0500
Subject: Add child_status_callback() function and arrange to call
 periodically. At least on OS X 10.7, a call to apr_proc_wait(APR_NOWAIT) in
 fact seems to block the caller. So instead of polling apr_proc_wait(), use
 APR callback mechanism (apr_proc_other_child_register() et al.) and poll that
 using apr_proc_other_child_refresh_all(). Evidently this polls the underlying
 system waitpid(), but the internal call seems to better support nonblocking.
 On arrival in the child_status_callback(APR_OC_REASON_DEATH) call, though,
 apr_proc_wait() produces ECHILD: the child process in question has already
 been reaped. The OS-encoded wait() status does get passed to the callback,
 but then we have to use OS-dependent macros to tease apart voluntary
 termination vs. killed by signal... a bit of a hole in APR's abstraction
 layer. Wrap ensure_equals() calls with a macro to explain which comparison
 failed.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 161 ++++++++++++++++++++----
 1 file changed, 138 insertions(+), 23 deletions(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index bdae81770f..7d67d13960 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -22,14 +22,17 @@
 #include "llapr.h"
 #include "apr_thread_proc.h"
 #include "apr_file_io.h"
+#include <boost/foreach.hpp>
 // other Linden headers
 #include "../test/lltut.h"
+#include "stringize.h"
 
 #if defined(LL_WINDOWS)
 #define sleep _sleep
 #define EOL "\r\n"
 #else
 #define EOL "\n"
+#include <sys/wait.h>
 #endif
 
 class APR
@@ -57,6 +60,10 @@ public:
     apr_pool_t *pool;
 };
 
+#define ensure_equals_(left, right) \
+        ensure_equals(STRINGIZE(#left << " != " << #right), (left), (right))
+#define aprchk(expr) aprchk_(#expr, (expr))
+
 /*****************************************************************************
 *   TUT
 *****************************************************************************/
@@ -64,9 +71,10 @@ namespace tut
 {
     struct llprocesslauncher_data
     {
-        void aprchk(apr_status_t rv)
+        void aprchk_(const char* call, apr_status_t rv)
         {
-            ensure_equals(apr.strerror(rv), rv, APR_SUCCESS);
+            ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr.strerror(rv)),
+                          rv, APR_SUCCESS);
         }
 
         APR apr;
@@ -83,6 +91,91 @@ namespace tut
         std::string what;
     };
 
+#define tabent(symbol) { symbol, #symbol }
+    static struct ReasonCode
+    {
+        int code;
+        const char* name;
+    } reasons[] =
+    {
+        tabent(APR_OC_REASON_DEATH),
+        tabent(APR_OC_REASON_UNWRITABLE),
+        tabent(APR_OC_REASON_RESTART),
+        tabent(APR_OC_REASON_UNREGISTER),
+        tabent(APR_OC_REASON_LOST),
+        tabent(APR_OC_REASON_RUNNING)
+    };
+#undef tabent
+
+    struct WaitInfo
+    {
+        WaitInfo(apr_proc_t* child_):
+            child(child_),
+            rv(-1),                 // we haven't yet called apr_proc_wait()
+            rc(0),
+            why(apr_exit_why_e(0))
+        {}
+        apr_proc_t* child;          // which subprocess
+        apr_status_t rv;            // return from apr_proc_wait()
+        int rc;                     // child's exit code
+        apr_exit_why_e why;         // APR_PROC_EXIT, APR_PROC_SIGNAL, APR_PROC_SIGNAL_CORE
+    };
+
+    void child_status_callback(int reason, void* data, int status)
+    {
+        std::string reason_str;
+        BOOST_FOREACH(const ReasonCode& rcp, reasons)
+        {
+            if (reason == rcp.code)
+            {
+                reason_str = rcp.name;
+                break;
+            }
+        }
+        if (reason_str.empty())
+        {
+            reason_str = STRINGIZE("unknown reason " << reason);
+        }
+        std::cout << "child_status_callback(" << reason_str << ")\n";
+
+        if (reason == APR_OC_REASON_DEATH || reason == APR_OC_REASON_LOST)
+        {
+            // Somewhat oddly, APR requires that you explicitly unregister
+            // even when it already knows the child has terminated.
+            apr_proc_other_child_unregister(data);
+
+            WaitInfo* wi(static_cast<WaitInfo*>(data));
+            wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
+            if (wi->rv == ECHILD)
+            {
+                std::cout << "apr_proc_wait() got ECHILD during child_status_callback("
+                          << reason_str << ")\n";
+                // So -- is this why we have a 'status' param?
+                wi->rv = APR_CHILD_DONE; // pretend this call worked; fake results
+#if defined(LL_WINDOWS)
+                wi->why = APR_PROC_EXIT;
+                wi->rc  = status;         // correct??
+#else  // Posix
+                if (WIFEXITED(status))
+                {
+                    wi->why = APR_PROC_EXIT;
+                    wi->rc  = WEXITSTATUS(status);
+                }
+                else if (WIFSIGNALED(status))
+                {
+                    wi->why = APR_PROC_SIGNAL;
+                    wi->rc  = WTERMSIG(status);
+                }
+                else                // uh, shouldn't happen?
+                {
+                    wi->why = APR_PROC_EXIT;
+                    wi->rc  = status; // someone else will have to decode
+                }
+#endif // Posix
+            }
+        }
+    }
+
     template<> template<>
     void object::test<1>()
     {
@@ -106,10 +199,10 @@ namespace tut
             "import time" EOL
             EOL
             "time.sleep(2)" EOL
-            "print >>sys.stdout, \"stdout after wait\"" EOL
+            "print >>sys.stdout, 'stdout after wait'" EOL
             "sys.stdout.flush()" EOL
             "time.sleep(2)" EOL
-            "print >>sys.stderr, \"stderr after wait\"" EOL
+            "print >>sys.stderr, 'stderr after wait'" EOL
             "sys.stderr.flush()" EOL
             ;
         apr_size_t len(sizeof(script)-1);
@@ -122,6 +215,7 @@ namespace tut
         std::vector<Item> history;
         history.push_back(Item());
 
+        // Run the child process.
         apr_procattr_t *procattr = NULL;
         aprchk(apr_procattr_create(&procattr, apr.pool));
         aprchk(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK));
@@ -134,11 +228,23 @@ namespace tut
         argv.push_back(NULL);
 
         aprchk(apr_proc_create(&child, argv[0],
-                               static_cast<const char* const*>(&argv[0]),
+                               &argv[0],
                                NULL, // if we wanted to pass explicit environment
                                procattr,
                                apr.pool));
 
+        // We do not want this child process to outlive our APR pool. On
+        // destruction of the pool, forcibly kill the process. Tell APR to try
+        // SIGTERM and wait 3 seconds. If that didn't work, use SIGKILL.
+        apr_pool_note_subprocess(apr.pool, &child, APR_KILL_AFTER_TIMEOUT);
+
+        // arrange to call child_status_callback()
+        WaitInfo wi(&child);
+        apr_proc_other_child_register(&child, child_status_callback, &wi, child.in, apr.pool);
+
+        // Monitor two different output pipes. Because one will be closed
+        // before the other, keep them in a vector so we can drop whichever of
+        // them is closed first.
         typedef std::pair<std::string, apr_file_t*> DescFile;
         typedef std::vector<DescFile> DescFileVec;
         DescFileVec outfiles;
@@ -168,7 +274,7 @@ namespace tut
                     ++history.back().tries;
                     continue;
                 }
-                ensure_equals(rv, APR_SUCCESS);
+                aprchk_("apr_file_gets(buf, sizeof(buf), iterfiles[i].second)", rv);
                 // Is it even possible to get APR_SUCCESS but read 0 bytes?
                 // Hope not, but defend against that anyway.
                 if (buf[0])
@@ -186,24 +292,33 @@ namespace tut
                     }
                 }
             }
+            // Do this once per tick, as we expect the viewer will
+            apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
             sleep(1);
         }
         apr_file_close(child.in);
         apr_file_close(child.out);
         apr_file_close(child.err);
 
-        int rc = 0;
-        apr_exit_why_e why;
-        apr_status_t rv;
-        while (! APR_STATUS_IS_CHILD_DONE(rv = apr_proc_wait(&child, &rc, &why, APR_NOWAIT)))
+        // Okay, we've broken the loop because our pipes are all closed. If we
+        // haven't yet called wait, give the callback one more chance. This
+        // models the fact that unlike this small test program, the viewer
+        // will still be running.
+        if (wi.rv == -1)
+        {
+            std::cout << "last gasp apr_proc_other_child_refresh_all()\n";
+            apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
+        }
+
+        if (wi.rv == -1)
         {
-//          std::cout << "child not done (" << rv << "): " << apr.strerror(rv) << '\n';
-            sleep(0.5);
+            std::cout << "child_status_callback() wasn't called\n";
+            wi.rv = apr_proc_wait(wi.child, &wi.rc, &wi.why, APR_NOWAIT);
         }
 //      std::cout << "child done: rv = " << rv << " (" << apr.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
-        ensure_equals(rv, APR_CHILD_DONE);
-        ensure_equals(why, APR_PROC_EXIT);
-        ensure_equals(rc, 0);
+        ensure_equals_(wi.rv, APR_CHILD_DONE);
+        ensure_equals_(wi.why, APR_PROC_EXIT);
+        ensure_equals_(wi.rc, 0);
 
         // Remove temp script file
         aprchk(apr_file_remove(tempname, apr.pool));
@@ -212,14 +327,14 @@ namespace tut
         // obtained expected output -- and that we duly got control while
         // waiting, proving the non-blocking nature of these pipes.
         ensure("blocking I/O on child pipe (0)", history[0].tries);
-        ensure_equals(history[0].which, "out");
-        ensure_equals(history[0].what,  "stdout after wait" EOL);
+        ensure_equals_(history[0].which, "out");
+        ensure_equals_(history[0].what,  "stdout after wait" EOL);
         ensure("blocking I/O on child pipe (1)", history[1].tries);
-        ensure_equals(history[1].which, "out");
-        ensure_equals(history[1].what,  "*eof*");
-        ensure_equals(history[2].which, "err");
-        ensure_equals(history[2].what,  "stderr after wait" EOL);
-        ensure_equals(history[3].which, "err");
-        ensure_equals(history[3].what,  "*eof*");
+        ensure_equals_(history[1].which, "out");
+        ensure_equals_(history[1].what,  "*eof*");
+        ensure_equals_(history[2].which, "err");
+        ensure_equals_(history[2].what,  "stderr after wait" EOL);
+        ensure_equals_(history[3].which, "err");
+        ensure_equals_(history[3].what,  "*eof*");
     }
 } // namespace tut
-- 
cgit v1.2.3


From 62e77147b21bba59e7eda992f7f9c9052b6098d1 Mon Sep 17 00:00:00 2001
From: Seth ProductEngine <slitovchuk@productengine.com>
Date: Thu, 22 Dec 2011 23:27:56 +0200
Subject: EXP-1632 FIXED Added checking for valid agent avatar before selecting
 the avatar gender and loading the initial outfit.

---
 indra/newview/llstartup.cpp | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 36d6ff3ef2..7e02a41e7e 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2026,7 +2026,7 @@ bool idle_startup()
 		const F32 wearables_time = wearables_timer.getElapsedTimeF32();
 		const F32 MAX_WEARABLES_TIME = 10.f;
 
-		if (!gAgent.isGenderChosen())
+		if (!gAgent.isGenderChosen() && isAgentAvatarValid())
 		{
 			// No point in waiting for clothing, we don't even
 			// know what gender we are.  Pop a dialog to ask and
@@ -2541,6 +2541,12 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 		gender = SEX_FEMALE;
 	}
 
+	if (!isAgentAvatarValid())
+	{
+		llwarns << "Trying to load an initial outfit for an invalid agent avatar" << llendl;
+		return;
+	}
+
 	gAgentAvatarp->setSex(gender);
 
 	// try to find the outfit - if not there, create some default
-- 
cgit v1.2.3


From 6ccba8810102cc13def8057a82463c9787b21e57 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 22 Dec 2011 17:18:02 -0500
Subject: Never call apr_proc_wait() inside child_status_callback(). Quiet the
 temporary child_status_callback() output. Add a bit of diagnostic info if
 apr_proc_wait() returns anything but APR_CHILD_DONE.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 57 +++++++++++++------------
 1 file changed, 29 insertions(+), 28 deletions(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 7d67d13960..bd7666313e 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -71,10 +71,10 @@ namespace tut
 {
     struct llprocesslauncher_data
     {
-        void aprchk_(const char* call, apr_status_t rv)
+        void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
         {
             ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr.strerror(rv)),
-                          rv, APR_SUCCESS);
+                          rv, expected);
         }
 
         APR apr;
@@ -123,6 +123,7 @@ namespace tut
 
     void child_status_callback(int reason, void* data, int status)
     {
+/*==========================================================================*|
         std::string reason_str;
         BOOST_FOREACH(const ReasonCode& rcp, reasons)
         {
@@ -137,6 +138,7 @@ namespace tut
             reason_str = STRINGIZE("unknown reason " << reason);
         }
         std::cout << "child_status_callback(" << reason_str << ")\n";
+|*==========================================================================*/
 
         if (reason == APR_OC_REASON_DEATH || reason == APR_OC_REASON_LOST)
         {
@@ -145,34 +147,33 @@ namespace tut
             apr_proc_other_child_unregister(data);
 
             WaitInfo* wi(static_cast<WaitInfo*>(data));
-            wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
-            if (wi->rv == ECHILD)
-            {
-                std::cout << "apr_proc_wait() got ECHILD during child_status_callback("
-                          << reason_str << ")\n";
-                // So -- is this why we have a 'status' param?
-                wi->rv = APR_CHILD_DONE; // pretend this call worked; fake results
+            // It's just wrong to call apr_proc_wait() here. The only way APR
+            // knows to call us with APR_OC_REASON_DEATH is that it's already
+            // reaped this child process, so calling wait() will only produce
+            // "huh?" from the OS. We must rely on the status param passed in,
+            // which unfortunately comes straight from the OS wait() call.
+//          wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
+            wi->rv = APR_CHILD_DONE; // fake apr_proc_wait() results
 #if defined(LL_WINDOWS)
-                wi->why = APR_PROC_EXIT;
-                wi->rc  = status;         // correct??
+            wi->why = APR_PROC_EXIT;
+            wi->rc  = status;         // no encoding on Windows (no signals)
 #else  // Posix
-                if (WIFEXITED(status))
-                {
-                    wi->why = APR_PROC_EXIT;
-                    wi->rc  = WEXITSTATUS(status);
-                }
-                else if (WIFSIGNALED(status))
-                {
-                    wi->why = APR_PROC_SIGNAL;
-                    wi->rc  = WTERMSIG(status);
-                }
-                else                // uh, shouldn't happen?
-                {
-                    wi->why = APR_PROC_EXIT;
-                    wi->rc  = status; // someone else will have to decode
-                }
-#endif // Posix
+            if (WIFEXITED(status))
+            {
+                wi->why = APR_PROC_EXIT;
+                wi->rc  = WEXITSTATUS(status);
+            }
+            else if (WIFSIGNALED(status))
+            {
+                wi->why = APR_PROC_SIGNAL;
+                wi->rc  = WTERMSIG(status);
             }
+            else                    // uh, shouldn't happen?
+            {
+                wi->why = APR_PROC_EXIT;
+                wi->rc  = status;   // someone else will have to decode
+            }
+#endif // Posix
         }
     }
 
@@ -316,7 +317,7 @@ namespace tut
             wi.rv = apr_proc_wait(wi.child, &wi.rc, &wi.why, APR_NOWAIT);
         }
 //      std::cout << "child done: rv = " << rv << " (" << apr.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
-        ensure_equals_(wi.rv, APR_CHILD_DONE);
+        aprchk_("apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT)", wi.rv, APR_CHILD_DONE);
         ensure_equals_(wi.why, APR_PROC_EXIT);
         ensure_equals_(wi.rc, 0);
 
-- 
cgit v1.2.3


From 29273ffba68d254ce3e6d9939a854c778a377721 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 22 Dec 2011 17:27:53 -0500
Subject: Comment out lookup table used only by commented-out code. Otherwise
 the unreferenced declaration causes a fatal warning.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index bd7666313e..b3e0796191 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -91,6 +91,7 @@ namespace tut
         std::string what;
     };
 
+/*==========================================================================*|
 #define tabent(symbol) { symbol, #symbol }
     static struct ReasonCode
     {
@@ -106,6 +107,7 @@ namespace tut
         tabent(APR_OC_REASON_RUNNING)
     };
 #undef tabent
+|*==========================================================================*/
 
     struct WaitInfo
     {
-- 
cgit v1.2.3


From f6281d0d869c7f7248edcac015d48ae09a82b7ff Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Fri, 23 Dec 2011 14:18:01 +0200
Subject: EXP-1744 FIXED URL-like group display name was shown as hyperlink in
 the Leave Group confirmation dialog.

---
 indra/newview/skins/default/xui/de/notifications.xml | 2 +-
 indra/newview/skins/default/xui/en/notifications.xml | 2 +-
 indra/newview/skins/default/xui/es/notifications.xml | 2 +-
 indra/newview/skins/default/xui/fr/notifications.xml | 2 +-
 indra/newview/skins/default/xui/it/notifications.xml | 2 +-
 indra/newview/skins/default/xui/ja/notifications.xml | 2 +-
 indra/newview/skins/default/xui/pl/notifications.xml | 2 +-
 indra/newview/skins/default/xui/pt/notifications.xml | 2 +-
 indra/newview/skins/default/xui/ru/notifications.xml | 2 +-
 indra/newview/skins/default/xui/tr/notifications.xml | 2 +-
 indra/newview/skins/default/xui/zh/notifications.xml | 2 +-
 11 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index 72e7ec8eb4..a5fcd3e0b4 100644
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -1443,7 +1443,7 @@ Zur Installation des Updates muss [APP_NAME] neu gestartet werden.
 		<usetemplate ignoretext="Bestätigen, bevor Objekte an Ihre Eigentümer zurückgegeben werden" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Sie sind Mitglied der Gruppe [GROUP].
+		Sie sind Mitglied der Gruppe &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Diese Gruppe verlassen?
 		<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 5b985c9981..b90acffbc9 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -3409,7 +3409,7 @@ Are you sure you want to return the selected objects to their owners? Transferab
    icon="alert.tga"
    name="GroupLeaveConfirmMember"
    type="alert">
-You are currently a member of the group [GROUP].
+You are currently a member of the group &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Leave Group?
     <tag>group</tag>
     <tag>confirm</tag>
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 9591b424fc..0de56f9b6d 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -1437,7 +1437,7 @@ Debemos reiniciar [APP_NAME] para instalar la actualización.
 		<usetemplate ignoretext="Confirmar antes de devolver objetos a sus propietarios." name="okcancelignore" notext="Cancelar" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Actualmente, eres miembro del grupo [GROUP].
+		Actualmente, eres miembro del grupo &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 ¿Dejar el grupo?
 		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index d8d79d8dde..be6f1f8c31 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -1428,7 +1428,7 @@ Version [VERSION]
 		<usetemplate ignoretext="Confirmer avant de rendre les objets à leurs propriétaires" name="okcancelignore" notext="Annuler" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Vous êtes actuellement membre du groupe [GROUP].
+		Vous êtes actuellement membre du groupe &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Quitter le groupe ?
 		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index 2db0892cd6..fce027da0c 100644
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -1432,7 +1432,7 @@ Per installare l&apos;aggiornamento è necessario riavviare [APP_NAME].
 		<usetemplate ignoretext="Conferma prima di restituire gli oggetti ai relativi proprietari" name="okcancelignore" notext="Annulla" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Sei attualmente un membro del gruppo [GROUP].
+		Sei attualmente un membro del gruppo &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Vuoi lasciare il gruppo?
 		<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index 7dfa6d2f7a..141f2c8071 100644
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -1467,7 +1467,7 @@ http://secondlife.com/download から最新バージョンをダウンロード
 		<usetemplate ignoretext="オブジェクトを所有者に返却する前の確認" name="okcancelignore" notext="取り消し" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		現在あなたは [GROUP] のメンバーです。
+		現在あなたは &lt;nolink&gt;[GROUP]&lt;/nolink&gt; のメンバーです。
 このグループを抜けますか?
 		<usetemplate name="okcancelbuttons" notext="取り消し" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml
index e1fb6dd3f1..0194293642 100644
--- a/indra/newview/skins/default/xui/pl/notifications.xml
+++ b/indra/newview/skins/default/xui/pl/notifications.xml
@@ -1385,7 +1385,7 @@ W celu instalacji aktualizacji musi zostać wykonany restart [APP_NAME].
 		<usetemplate ignoretext="Potwierdź zanim zwrócisz obiekty do ich właścicieli" name="okcancelignore" notext="Anuluj" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Jesteś członkiem grupy [GROUP].
+		Jesteś członkiem grupy &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Chcesz opuścić grupę?
 		<usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index d3547beeb3..b53ebeb136 100644
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -1419,7 +1419,7 @@ Para instalar a atualização, será preciso reiniciar o [APP_NAME].
 		<usetemplate ignoretext="Confirmar antes de devolver objetos a seus donos" name="okcancelignore" notext="Cancelar" yestext="Retornar"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Você é atualmente um membro do grupo [GROUP].
+		Você é atualmente um membro do grupo &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Sair do grupo?
 		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Sair"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml
index 1be14160ed..f121743fe9 100644
--- a/indra/newview/skins/default/xui/ru/notifications.xml
+++ b/indra/newview/skins/default/xui/ru/notifications.xml
@@ -1431,7 +1431,7 @@ http://secondlife.com/download.
 		<usetemplate ignoretext="Подтверждать перед возвратом объектов владельцам" name="okcancelignore" notext="Отмена" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Вы являетесь участником группы [GROUP].
+		Вы являетесь участником группы &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Хотите покинуть группу?
 		<usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml
index 6908f6867f..c0dc67ed34 100644
--- a/indra/newview/skins/default/xui/tr/notifications.xml
+++ b/indra/newview/skins/default/xui/tr/notifications.xml
@@ -1431,7 +1431,7 @@ Güncellemeyi kurmak için [APP_NAME] uygulamasını yeniden başlatmalısınız
 		<usetemplate ignoretext="Nesneleri sahiplerine iade etmeden önce doğrulama iste" name="okcancelignore" notext="İptal" yestext="Tamam"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Şu anda [GROUP] grubunun bir üyesisiniz.
+		Şu anda &lt;nolink&gt;[GROUP]&lt;/nolink&gt; grubunun bir üyesisiniz.
 Gruptan ayrılmak istiyor musunuz?
 		<usetemplate name="okcancelbuttons" notext="İptal" yestext="Tamam"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml
index 17ff6288a5..3fa8ff3f78 100644
--- a/indra/newview/skins/default/xui/zh/notifications.xml
+++ b/indra/newview/skins/default/xui/zh/notifications.xml
@@ -1418,7 +1418,7 @@ We must restart [APP_NAME] to install the update.
 		<usetemplate ignoretext="在我退回物件給它們的擁有者前確認" name="okcancelignore" notext="取消" yestext="確定"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		你目前是 [GROUP] 群組的成員。
+		你目前是 &lt;nolink&gt;[GROUP]&lt;/nolink&gt; 群組的成員。
 是否要離開群組?
 		<usetemplate name="okcancelbuttons" notext="取消" yestext="確定"/>
 	</notification>
-- 
cgit v1.2.3


From 4c4543a464ff9e59909404983b5c4ebac71df3b2 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Fri, 23 Dec 2011 17:44:59 +0200
Subject: EXP-1732 FIXED "Refresh to Save" message displayed in auto-refresh
 mode.

---
 indra/newview/llfloatersnapshot.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 1b3290d5a8..1fac8624cc 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1490,6 +1490,12 @@ void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool ne
 {
 	if (!floater) return;
 
+	// Don't display the "Refresh to save" message if we're in auto-refresh mode.
+	if (gSavedSettings.getBOOL("AutoSnapshot"))
+	{
+		need = false;
+	}
+
 	floater->mRefreshLabel->setVisible(need);
 	floater->impl.mNeedRefresh = need;
 }
-- 
cgit v1.2.3


From 8a3aa3f6cac3da0ee962dac211580a7987a4fc31 Mon Sep 17 00:00:00 2001
From: Jonathan Yap <none@none>
Date: Fri, 23 Dec 2011 12:06:36 -0500
Subject: STORM-1790 Provide a Develop sub-menu to change the default logging
 level co-authored with Zi Ree

---
 doc/contributions.txt                              |  2 +
 indra/llcommon/llerror.cpp                         |  6 +++
 indra/llcommon/llerrorcontrol.h                    |  1 +
 indra/newview/llviewermenu.cpp                     | 27 +++++++++++
 indra/newview/skins/default/xui/en/menu_login.xml  | 53 +++++++++++++++++++++-
 indra/newview/skins/default/xui/en/menu_viewer.xml | 51 +++++++++++++++++++++
 6 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 1a3fc680bc..5eea015ae4 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -603,6 +603,7 @@ Jonathan Yap
 	STORM-653
 	STORM-1737
 	STORM-1733
+	STORM-1790
 Kadah Coba
 	STORM-1060
 Jondan Lundquist
@@ -1254,6 +1255,7 @@ Zi Ree
 	VWR-1140
 	VWR-24017
 	VWR-25588
+	STORM-1790
 Zipherius Turas
 	VWR-76
 	VWR-77
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index c35799bbb9..e4381dbbd6 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -617,6 +617,12 @@ namespace LLError
 		s.defaultLevel = level;
 	}
 
+	ELevel getDefaultLevel()
+	{
+		Settings& s = Settings::get();
+		return s.defaultLevel;
+	}
+
 	void setFunctionLevel(const std::string& function_name, ELevel level)
 	{
 		Globals& g = Globals::get();
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index fb75d45e2c..ed9de002f5 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -75,6 +75,7 @@ namespace LLError
 	
 	LL_COMMON_API void setPrintLocation(bool);
 	LL_COMMON_API void setDefaultLevel(LLError::ELevel);
+	LL_COMMON_API ELevel getDefaultLevel();
 	LL_COMMON_API void setFunctionLevel(const std::string& function_name, LLError::ELevel);
 	LL_COMMON_API void setClassLevel(const std::string& class_name, LLError::ELevel);
 	LL_COMMON_API void setFileLevel(const std::string& file_name, LLError::ELevel);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 3a1b8d7623..0104d35e53 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2203,6 +2203,30 @@ class LLAdvancedEnableToggleHackedGodmode : public view_listener_t
 //// Advanced menu
 ////-------------------------------------------------------------------
 
+
+//////////////////
+// DEVELOP MENU //
+//////////////////
+
+class LLDevelopCheckLoggingLevel : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		U32 level = userdata.asInteger();
+		return (static_cast<LLError::ELevel>(level) == LLError::getDefaultLevel());
+	}
+};
+
+class LLDevelopSetLoggingLevel : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		U32 level = userdata.asInteger();
+		LLError::setDefaultLevel(static_cast<LLError::ELevel>(level));
+		return true;
+	}
+};
+
 //////////////////
 // ADMIN MENU   //
 //////////////////
@@ -8195,6 +8219,9 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus");
 	view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus");
 
+	// Develop >Set logging level
+	view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel");
+	view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel");
 
 	// Admin >Object
 	view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 8ac1ac9e09..101e104eab 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -174,7 +174,58 @@
          function="Advanced.WebContentTest"
          parameter="http://google.com"/>
       </menu_item_call>
-      <menu_item_check
+      <menu
+       create_jump_keys="true"
+       label="Set Logging Level"
+       name="Set Logging Level"
+       tear_off="true">
+        <menu_item_check
+          label="Debug">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="0" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="0" />
+        </menu_item_check>
+        <menu_item_check
+          label="Info">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="1" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="1" />
+        </menu_item_check>
+        <menu_item_check
+          label="Warning">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="2" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="2" />
+        </menu_item_check>
+        <menu_item_check
+          label="Error">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="3" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="3" />
+        </menu_item_check>
+        <menu_item_check
+          label="None">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="4" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="4" />
+        </menu_item_check>
+      </menu>
+     <menu_item_check
         label="Show Grid Picker"
         name="Show Grid Picker"
         visible="false" 
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 0aa5c72f2a..0df123e140 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3367,6 +3367,57 @@
              function="ToggleControl"
              parameter="ShowConsoleWindow" />
         </menu_item_check>
+        <menu
+         create_jump_keys="true"
+         label="Set Logging Level"
+         name="Set Logging Level"
+         tear_off="true">
+          <menu_item_check
+            label="Debug">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="0" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="0" />
+          </menu_item_check>
+          <menu_item_check
+            label="Info">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="1" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="1" />
+          </menu_item_check>
+          <menu_item_check
+            label="Warning">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="2" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="2" />
+          </menu_item_check>
+          <menu_item_check
+            label="Error">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="3" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="3" />
+          </menu_item_check>
+          <menu_item_check
+            label="None">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="4" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="4" />
+          </menu_item_check>
+       </menu>
 
         <menu_item_separator/>
 
-- 
cgit v1.2.3


From 8cf297ab48cb1c13cb76c462e1c3eed572b12738 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Fri, 23 Dec 2011 20:16:48 +0200
Subject: EXP-1762 FIXED Pre-select current window resolution.

---
 indra/newview/llfloatersnapshot.cpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 1fac8624cc..56d53ebdf0 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -2052,6 +2052,13 @@ BOOL LLFloaterSnapshot::postBuild()
 	gFloaterView->removeChild(this);
 	gSnapshotFloaterView->addChild(this);
 
+	// Pre-select "Current Window" resolution.
+	getChild<LLComboBox>("profile_size_combo")->selectNthItem(0);
+	getChild<LLComboBox>("postcard_size_combo")->selectNthItem(0);
+	getChild<LLComboBox>("texture_size_combo")->selectNthItem(0);
+	getChild<LLComboBox>("local_size_combo")->selectNthItem(0);
+	getChild<LLComboBox>("local_format_combo")->selectNthItem(0);
+
 	impl.mPreviewHandle = previewp->getHandle();
 	impl.updateControls(this);
 	impl.updateLayout(this);
-- 
cgit v1.2.3


From cf7c6f93f28534fee2c13e29501b6ab6e7b77d61 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 23 Dec 2011 15:23:03 -0500
Subject: Make pipe-management logic more robust. Previous logic was vulnerable
 to the case in which both pipes reached EOF in the same loop iteration. Now
 we use std::list instead of std::vector, allowing us to iterate and delete
 with a single pass.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 43 ++++++++++++++++---------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index bd7666313e..d6d05ed769 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -16,6 +16,7 @@
 #include "llprocesslauncher.h"
 // STL headers
 #include <vector>
+#include <list>
 // std headers
 #include <errno.h>
 // external library headers
@@ -28,7 +29,7 @@
 #include "stringize.h"
 
 #if defined(LL_WINDOWS)
-#define sleep _sleep
+#define sleep(secs) _sleep((secs) * 1000)
 #define EOL "\r\n"
 #else
 #define EOL "\n"
@@ -244,44 +245,54 @@ namespace tut
         apr_proc_other_child_register(&child, child_status_callback, &wi, child.in, apr.pool);
 
         // Monitor two different output pipes. Because one will be closed
-        // before the other, keep them in a vector so we can drop whichever of
+        // before the other, keep them in a list so we can drop whichever of
         // them is closed first.
         typedef std::pair<std::string, apr_file_t*> DescFile;
-        typedef std::vector<DescFile> DescFileVec;
-        DescFileVec outfiles;
+        typedef std::list<DescFile> DescFileList;
+        DescFileList outfiles;
         outfiles.push_back(DescFile("out", child.out));
         outfiles.push_back(DescFile("err", child.err));
 
         while (! outfiles.empty())
         {
-            DescFileVec iterfiles(outfiles);
-            for (size_t i = 0; i < iterfiles.size(); ++i)
+            // This peculiar for loop is designed to let us erase(dfli). With
+            // a list, that invalidates only dfli itself -- but even so, we
+            // lose the ability to increment it for the next item. So at the
+            // top of every loop, while dfli is still valid, increment
+            // dflnext. Then before the next iteration, set dfli to dflnext.
+            for (DescFileList::iterator
+                     dfli(outfiles.begin()), dflnext(outfiles.begin()), dflend(outfiles.end());
+                 dfli != dflend; dfli = dflnext)
             {
+                // Only valid to increment dflnext once we're sure it's not
+                // already at dflend.
+                ++dflnext;
+
                 char buf[4096];
 
-                apr_status_t rv = apr_file_gets(buf, sizeof(buf), iterfiles[i].second);
+                apr_status_t rv = apr_file_gets(buf, sizeof(buf), dfli->second);
                 if (APR_STATUS_IS_EOF(rv))
                 {
-//                  std::cout << "(EOF on " << iterfiles[i].first << ")\n";
-                    history.back().which = iterfiles[i].first;
+//                  std::cout << "(EOF on " << dfli->first << ")\n";
+                    history.back().which = dfli->first;
                     history.back().what  = "*eof*";
                     history.push_back(Item());
-                    outfiles.erase(outfiles.begin() + i);
+                    outfiles.erase(dfli);
                     continue;
                 }
                 if (rv == EWOULDBLOCK || rv == EAGAIN)
                 {
-//                  std::cout << "(waiting; apr_file_gets(" << iterfiles[i].first << ") => " << rv << ": " << apr.strerror(rv) << ")\n";
+//                  std::cout << "(waiting; apr_file_gets(" << dfli->first << ") => " << rv << ": " << apr.strerror(rv) << ")\n";
                     ++history.back().tries;
                     continue;
                 }
-                aprchk_("apr_file_gets(buf, sizeof(buf), iterfiles[i].second)", rv);
+                aprchk_("apr_file_gets(buf, sizeof(buf), dfli->second)", rv);
                 // Is it even possible to get APR_SUCCESS but read 0 bytes?
                 // Hope not, but defend against that anyway.
                 if (buf[0])
                 {
-//                  std::cout << iterfiles[i].first << ": " << buf;
-                    history.back().which = iterfiles[i].first;
+//                  std::cout << dfli->first << ": " << buf;
+                    history.back().which = dfli->first;
                     history.back().what.append(buf);
                     if (buf[strlen(buf) - 1] == '\n')
                         history.push_back(Item());
@@ -295,7 +306,7 @@ namespace tut
             }
             // Do this once per tick, as we expect the viewer will
             apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
-            sleep(1);
+            sleep(0.5);
         }
         apr_file_close(child.in);
         apr_file_close(child.out);
@@ -313,7 +324,7 @@ namespace tut
 
         if (wi.rv == -1)
         {
-            std::cout << "child_status_callback() wasn't called\n";
+            std::cout << "child_status_callback(APR_OC_REASON_DEATH) wasn't called" << std::endl;
             wi.rv = apr_proc_wait(wi.child, &wi.rc, &wi.why, APR_NOWAIT);
         }
 //      std::cout << "child done: rv = " << rv << " (" << apr.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
-- 
cgit v1.2.3


From 8008d540e5177aa4fb0c802b157eec2695c8334a Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 23 Dec 2011 16:45:05 -0500
Subject: Should we expect EOF on one pipe before we finish reading the other?
 Defend test against the ambiguous answer to that question by not recording,
 or testing for, EOF history events. Enrich output for history-verification
 failures: display whole history array.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 61 +++++++++++++++++++------
 1 file changed, 48 insertions(+), 13 deletions(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 895325c705..dbbe54e9fa 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -246,6 +246,11 @@ namespace tut
         WaitInfo wi(&child);
         apr_proc_other_child_register(&child, child_status_callback, &wi, child.in, apr.pool);
 
+        // TODO:
+        // Stuff child.in until it (would) block to verify EWOULDBLOCK/EAGAIN.
+        // Have child script clear it later, then write one more line to prove
+        // that it gets through.
+
         // Monitor two different output pipes. Because one will be closed
         // before the other, keep them in a list so we can drop whichever of
         // them is closed first.
@@ -276,9 +281,9 @@ namespace tut
                 if (APR_STATUS_IS_EOF(rv))
                 {
 //                  std::cout << "(EOF on " << dfli->first << ")\n";
-                    history.back().which = dfli->first;
-                    history.back().what  = "*eof*";
-                    history.push_back(Item());
+//                  history.back().which = dfli->first;
+//                  history.back().what  = "*eof*";
+//                  history.push_back(Item());
                     outfiles.erase(dfli);
                     continue;
                 }
@@ -340,15 +345,45 @@ namespace tut
         // Beyond merely executing all the above successfully, verify that we
         // obtained expected output -- and that we duly got control while
         // waiting, proving the non-blocking nature of these pipes.
-        ensure("blocking I/O on child pipe (0)", history[0].tries);
-        ensure_equals_(history[0].which, "out");
-        ensure_equals_(history[0].what,  "stdout after wait" EOL);
-        ensure("blocking I/O on child pipe (1)", history[1].tries);
-        ensure_equals_(history[1].which, "out");
-        ensure_equals_(history[1].what,  "*eof*");
-        ensure_equals_(history[2].which, "err");
-        ensure_equals_(history[2].what,  "stderr after wait" EOL);
-        ensure_equals_(history[3].which, "err");
-        ensure_equals_(history[3].what,  "*eof*");
+        try
+        {
+            unsigned i = 0;
+            ensure("blocking I/O on child pipe (0)", history[i].tries);
+            ensure_equals_(history[i].which, "out");
+            ensure_equals_(history[i].what,  "stdout after wait" EOL);
+//          ++i;
+//          ensure_equals_(history[i].which, "out");
+//          ensure_equals_(history[i].what,  "*eof*");
+            ++i;
+            ensure("blocking I/O on child pipe (1)", history[i].tries);
+            ensure_equals_(history[i].which, "err");
+            ensure_equals_(history[i].what,  "stderr after wait" EOL);
+//          ++i;
+//          ensure_equals_(history[i].which, "err");
+//          ensure_equals_(history[i].what,  "*eof*");
+        }
+        catch (const failure&)
+        {
+            std::cout << "History:\n";
+            BOOST_FOREACH(const Item& item, history)
+            {
+                std::string what(item.what);
+                if ((! what.empty()) && what[what.length() - 1] == '\n')
+                {
+                    what.erase(what.length() - 1);
+                    if ((! what.empty()) && what[what.length() - 1] == '\r')
+                    {
+                        what.erase(what.length() - 1);
+                        what.append("\\r");
+                    }
+                    what.append("\\n");
+                }
+                std::cout << "  " << item.which << ": '" << what << "' ("
+                          << item.tries << " tries)\n";
+            }
+            std::cout << std::flush;
+            // re-raise same error; just want to enrich the output
+            throw;
+        }
     }
 } // namespace tut
-- 
cgit v1.2.3


From 97876f6118eadf6a2669826d68412cc020975a64 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 23 Dec 2011 17:38:34 -0500
Subject: Fix sleep(0.5) to sleep(1) -- truncation to int makes that dubious.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index dbbe54e9fa..4d8f850d92 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -313,7 +313,7 @@ namespace tut
             }
             // Do this once per tick, as we expect the viewer will
             apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
-            sleep(0.5);
+            sleep(1);
         }
         apr_file_close(child.in);
         apr_file_close(child.out);
-- 
cgit v1.2.3


From 032a5e45728597106e07d2d22de3799aaaaf4923 Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Sun, 25 Dec 2011 23:09:32 +0000
Subject: Replacing file filter for windows that was mistakenly removed.

---
 indra/newview/llfilepicker.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index ceb4060bc2..8024755e86 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -502,6 +502,14 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
 			L"Compressed Images (*.j2c)\0*.j2c\0" \
 			L"\0";
 		break;
+	case FFSAVE_SCRIPT:
+		if (filename.empty())
+		{
+			wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE);
+		}
+		mOFN.lpstrDefExt = L"txt";
+		mOFN.lpstrFilter = L"LSL Files (*.lsl)\0*.lsl\0" L"\0";
+		break;
 	default:
 		return FALSE;
 	}
-- 
cgit v1.2.3


From 1a537bb194279f448d343f83b653e1c200bb9041 Mon Sep 17 00:00:00 2001
From: Paul ProductEngine <pguslisty@productengine.com>
Date: Mon, 26 Dec 2011 15:57:42 +0200
Subject: EXP-1618 (Serious truncation in top-right status bar "Buy $S" and
 "Shop" buttons in many languages)

- Adjusted width of "shop" button in all locales. Had to override width parameter in xml files of all locales. If to set one value with extra room space for all locales it will look rather ugly for many locales including EN.
---
 indra/newview/skins/default/xui/de/panel_status_bar.xml | 2 +-
 indra/newview/skins/default/xui/en/panel_status_bar.xml | 3 +--
 indra/newview/skins/default/xui/es/panel_status_bar.xml | 2 +-
 indra/newview/skins/default/xui/fr/panel_status_bar.xml | 2 +-
 indra/newview/skins/default/xui/it/panel_status_bar.xml | 2 +-
 indra/newview/skins/default/xui/ja/panel_status_bar.xml | 2 +-
 indra/newview/skins/default/xui/pt/panel_status_bar.xml | 2 +-
 indra/newview/skins/default/xui/ru/panel_status_bar.xml | 2 +-
 indra/newview/skins/default/xui/tr/panel_status_bar.xml | 2 +-
 9 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml
index d34fcf70bc..2493d60df6 100644
--- a/indra/newview/skins/default/xui/de/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="20 L$"/>
 		<button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/>
-		<button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen"/>
+		<button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen" width="85"/>
 	</panel>
 	<text name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)">
 		24:00 H PST
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index 3239c4e531..d453a970e7 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -70,7 +70,7 @@
      pad_bottom="2"
      tool_tip="Click to buy more L$"
      top="0"
-     width="55" />
+     width="80" />
     <button
      halign="left"
      font="SansSerifSmall"
@@ -87,7 +87,6 @@
      left_pad="0"
      label_shadow="true"
      name="goShop"
-     pad_right="0"
      pad_bottom="2"
      tool_tip="Open Second Life Marketplace"
      top="0"
diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml
index d43790c8c6..79b2c32b23 100644
--- a/indra/newview/skins/default/xui/es/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="20 L$"/>
 		<button label="Comprar L$" name="buyL" tool_tip="Pulsa para comprar más L$"/>
-		<button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life"/>
+		<button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life" width="80"/>
 	</panel>
 	<text name="TimeText" tool_tip="Hora actual (Pacífico)">
 		24:00 AM PST
diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
index ac61eb7e52..c0d59a3182 100644
--- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="20 L$"/>
 		<button label="Acheter L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/>
-		<button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life."/>
+		<button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life." width="75"/>
 	</panel>
 	<text name="TimeText" tool_tip="Heure actuelle (Pacifique)">
 		00h00 PST
diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml
index fadaa575ea..4abc90113f 100644
--- a/indra/newview/skins/default/xui/it/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Clicca per aggiornare il tuo saldo in L$" value="L$ 20"/>
 		<button label="Acquista L$" name="buyL" tool_tip="Clicca per acquistare più L$"/>
-		<button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life"/>
+		<button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life" width="75"/>
 	</panel>
 	<text name="TimeText" tool_tip="Orario attuale (Pacifico)">
 		24:00, ora del Pacifico
diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
index 93689b81af..4fb876f690 100644
--- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="クリックして L$ 残高を更新" value="L$20"/>
 		<button label="L$ の購入" name="buyL" tool_tip="クリックして L$ を購入します"/>
-		<button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開く"/>
+		<button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開く"  width="40"/>
 	</panel>
 	<text name="TimeText" tool_tip="現在時刻(太平洋)">
 		24:00 AM PST
diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
index d5a3258ddc..22853f0643 100644
--- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Atualizar saldo de L$" value="L$20"/>
 		<button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/>
-		<button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life"/>
+		<button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life" width="80"/>
 	</panel>
 	<text name="TimeText" tool_tip="Hora atual (Pacífico)">
 		24:00 AM PST
diff --git a/indra/newview/skins/default/xui/ru/panel_status_bar.xml b/indra/newview/skins/default/xui/ru/panel_status_bar.xml
index 6822244196..babe5811ac 100644
--- a/indra/newview/skins/default/xui/ru/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ru/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Щелкните для обновления вашего баланса L$" value="L$20"/>
 		<button label="Купить L$" name="buyL" tool_tip="Щелкните для покупки L$"/>
-		<button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life"/>
+		<button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life" width="121"/>
 	</panel>
 	<text name="TimeText" tool_tip="Текущее время (тихоокеанское)">
 		00:00 (тихоокеанское время)
diff --git a/indra/newview/skins/default/xui/tr/panel_status_bar.xml b/indra/newview/skins/default/xui/tr/panel_status_bar.xml
index 63726b94e2..81c304a5d8 100644
--- a/indra/newview/skins/default/xui/tr/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/tr/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="L$ bakiyenizi yenilemek için buraya tıklayın" value="L$20"/>
 		<button label="L$ Satın Al" name="buyL" tool_tip="Daha fazla L$ satın almak için tıklayın"/>
-		<button label="Alışveriş yap" name="goShop" tool_tip="Second Life Pazaryeri Aç"/>
+		<button label="Alışveriş yap" name="goShop" tool_tip="Second Life Pazaryeri Aç" width="95"/>
 	</panel>
 	<text name="TimeText" tool_tip="Geçerli zaman (Pasifik)">
 		24:00 AM PST
-- 
cgit v1.2.3


From 969e9b3315f017ce178bc996a1cc025164d5ee69 Mon Sep 17 00:00:00 2001
From: Paul ProductEngine <pguslisty@productengine.com>
Date: Mon, 26 Dec 2011 16:01:13 +0200
Subject: EXP-1621 FIXED (Duplicated XUI ID: panel_snapshot_postcard.xml)

- Removed duplicated parameters
---
 indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
index d8ff043444..ebba292a93 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
@@ -16,14 +16,6 @@
      name="upload_message">
         Sending...
     </string>
-    <string
-     name="default_subject">
-        Postcard from [SECOND_LIFE].
-    </string>
-    <string
-     name="default_message">
-        Check this out!
-    </string>
     <icon
      follows="top|left"
      height="18"
-- 
cgit v1.2.3


From 6c1219a5e419215f5df260c8dc4b24b10fc4d6fb Mon Sep 17 00:00:00 2001
From: Paul ProductEngine <pguslisty@productengine.com>
Date: Mon, 26 Dec 2011 20:53:41 +0200
Subject: EXP-1624 FIXED ([TRANSLATED BUT IN EN] tooltip for chat floater in
 English: Shows/hides nearby chat log)

Reason:
- Panel name was missed in other locales.

Solution:
- Added panel name to other locales.
---
 indra/newview/skins/default/xui/de/floater_chat_bar.xml | 2 +-
 indra/newview/skins/default/xui/en/floater_chat_bar.xml | 1 +
 indra/newview/skins/default/xui/es/floater_chat_bar.xml | 2 +-
 indra/newview/skins/default/xui/fr/floater_chat_bar.xml | 2 +-
 indra/newview/skins/default/xui/it/floater_chat_bar.xml | 2 +-
 indra/newview/skins/default/xui/ja/floater_chat_bar.xml | 2 +-
 indra/newview/skins/default/xui/pt/floater_chat_bar.xml | 2 +-
 indra/newview/skins/default/xui/ru/floater_chat_bar.xml | 2 +-
 indra/newview/skins/default/xui/tr/floater_chat_bar.xml | 2 +-
 9 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/indra/newview/skins/default/xui/de/floater_chat_bar.xml b/indra/newview/skins/default/xui/de/floater_chat_bar.xml
index dc5a7cd681..2464a55665 100644
--- a/indra/newview/skins/default/xui/de/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/de/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="CHAT IN DER NÄHE">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Zum Chatten hier klicken." name="chat_box" tool_tip="Eingabetaste zum Sprechen, Strg+Eingabe zum Rufen"/>
 		<button name="show_nearby_chat" tool_tip="Chatprotokoll in der Nähe ein-/ausblenden"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml
index 8d0cecdac3..675f78d911 100644
--- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/en/floater_chat_bar.xml
@@ -30,6 +30,7 @@
     <panel width="300" 
            height="31" 
            left="0" 
+           name="bottom_panel"
            bottom="-1" 
            follows="left|right|bottom" 
            tab_group="1">
diff --git a/indra/newview/skins/default/xui/es/floater_chat_bar.xml b/indra/newview/skins/default/xui/es/floater_chat_bar.xml
index 5e5ef616b8..2e94805057 100644
--- a/indra/newview/skins/default/xui/es/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/es/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="CHAT">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Pulsa aquí para chatear." name="chat_box" tool_tip="Pulsa Enter para decirlo o Ctrl+Enter para gritarlo"/>
 		<button name="show_nearby_chat" tool_tip="Muestra o esconde el registro del chat"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml
index 88a2fb669b..c7d27c0589 100644
--- a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="CHAT PRÈS DE MOI">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Cliquer ici pour chatter." name="chat_box" tool_tip="Appuyer sur Entrée pour dire, Ctrl-Entrée pour crier"/>
 		<button name="show_nearby_chat" tool_tip="Affiche/Masque le journal de chats près de vous"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/it/floater_chat_bar.xml b/indra/newview/skins/default/xui/it/floater_chat_bar.xml
index 6c5c8fbea0..94c85b50c8 100644
--- a/indra/newview/skins/default/xui/it/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/it/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="CHAT NEI DINTORNI">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Clicca qui per la chat." name="chat_box" tool_tip="Premi Invio per parlare, Ctrl+Invio per gridare"/>
 		<button name="show_nearby_chat" tool_tip="Mostra/Nasconde il registro della chat nei dintorni"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml
index 9735afb101..504cea5931 100644
--- a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="近くのチャット">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="ここをクリックしてチャットを開始します。" name="chat_box" tool_tip="Enter キーを押して話し、Ctrl + Enter キーで叫びます。"/>
 		<button name="show_nearby_chat" tool_tip="近くのチャットログを表示・非表示"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/pt/floater_chat_bar.xml b/indra/newview/skins/default/xui/pt/floater_chat_bar.xml
index c089ab93f2..72016c6b40 100644
--- a/indra/newview/skins/default/xui/pt/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/pt/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="BATE-PAPO LOCAL">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Clique aqui para bater papo." name="chat_box" tool_tip="Tecle Enter para falar, Ctrl+Enter para gritar"/>
 		<button name="show_nearby_chat" tool_tip="Mostra/oculta o histórico do bate-papo local"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/ru/floater_chat_bar.xml b/indra/newview/skins/default/xui/ru/floater_chat_bar.xml
index eceab1775a..79b7b033fb 100644
--- a/indra/newview/skins/default/xui/ru/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/ru/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="ЛОКАЛЬНЫЙ ЧАТ">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Щелкните здесь для общения." name="chat_box" tool_tip="Нажмите Enter, чтобы сказать, Ctrl+Enter, чтобы прокричать"/>
 		<button name="show_nearby_chat" tool_tip="Показать/скрыть лог локального чата"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml
index d2385e6be3..dee17b7bc4 100644
--- a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="YAKINDAKİ SOHBET">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Sohbet etmek için buraya tıklayın." name="chat_box" tool_tip="Söylemek için Enter, bağırmak için Ctrl+Enter yapın"/>
 		<button name="show_nearby_chat" tool_tip="yakın sohbet günlüğünü gösterir/gizler"/>
 	</panel>
-- 
cgit v1.2.3


From 681ecc0d0fea674e1fd495198d0aa0ea4a4ddf4f Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Wed, 28 Dec 2011 18:35:00 +0200
Subject: EXP-1593 FIXED Navbar was displayed after exitting hide contorls
 mode, even if disabled via settings.

Apparently, the way we showed/hid the panels was wrong.
---
 indra/newview/llviewerwindow.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 31dfa1923c..b73be4ed43 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -130,6 +130,7 @@
 #include "llmorphview.h"
 #include "llmoveview.h"
 #include "llnavigationbar.h"
+#include "llpaneltopinfobar.h"
 #include "llpopupview.h"
 #include "llpreviewtexture.h"
 #include "llprogressview.h"
@@ -5001,8 +5002,8 @@ void LLViewerWindow::setUIVisibility(bool visible)
 		gToolBarView->setToolBarsVisible(visible);
 	}
 
-	mRootView->getChildView("topinfo_bar_container")->setVisible(visible);
-	mRootView->getChildView("nav_bar_container")->setVisible(visible);
+	LLNavigationBar::getInstance()->setVisible(visible ? gSavedSettings.getBOOL("ShowNavbarNavigationPanel") : FALSE);
+	LLPanelTopInfoBar::getInstance()->setVisible(visible? gSavedSettings.getBOOL("ShowMiniLocationPanel") : FALSE);
 	mRootView->getChildView("status_bar_container")->setVisible(visible);
 }
 
-- 
cgit v1.2.3


From 0380372a54e98f582fbe995537f4c5e0ec700865 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Fri, 30 Dec 2011 16:30:26 +0200
Subject: EXP-1523 WIP Defensive fix for a crash at
 LLFolderView::onItemsRemovalConfirmation().

---
 indra/newview/llfolderview.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 6ec2598e44..637ffd4d2c 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -1058,7 +1058,7 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL
 		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
 		{
 			item = *item_it;
-			if(item->isRemovable())
+			if (item && item->isRemovable())
 			{
 				items.push_back(item);
 			}
-- 
cgit v1.2.3


From cbeaf3d7a0dd7bdb739b8e72addd41410940a8f5 Mon Sep 17 00:00:00 2001
From: Paul ProductEngine <pguslisty@productengine.com>
Date: Fri, 30 Dec 2011 18:32:04 +0200
Subject: EXP-1586 FIXED (Nearby chat window no longer persists between viewer
 startups)

- Visibility state of chat floater is saved between sessions
- Also visibility state of chat history in nearby chat floater is saved too
---
 indra/newview/llnearbychatbar.cpp                  | 25 ++++++++++++++++++++++
 indra/newview/llnearbychatbar.h                    |  5 +++++
 .../skins/default/xui/en/floater_chat_bar.xml      |  1 +
 3 files changed, 31 insertions(+)

diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index eec0965384..cb08ca8862 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -109,6 +109,17 @@ BOOL LLNearbyChatBar::postBuild()
 	mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator");
 	mOutputMonitor->setVisible(FALSE);
 
+	gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE);
+
+	// If mVisibilityControl is not empty it means that the visibility state of floater is saved between sessions,
+	// i.e. save_visibility="true" for this floater.
+	// So if we need to restore visibility state of floater we also need to restore visibility state of nearby chat history.
+	if (!mVisibilityControl.empty())
+	{
+		// restore visibility of nearby chat history
+		mNearbyChat->setVisible(gSavedSettings.getBOOL("nearbychat_history_visibility"));
+	}
+
 	// Register for font change notifications
 	LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1));
 
@@ -141,6 +152,18 @@ bool LLNearbyChatBar::applyRectControl()
 	return rect_controlled;
 }
 
+void LLNearbyChatBar::saveChatHistoryVisibility()
+{
+	// save visibility state of nearby chat history panel if
+	// visibility of nearby chat floater is saved, i.e. save_visisbility="true"
+	// (if save_visisbility="true", mVisibilityControl == "floater_vis_chat_bar")
+	if (mVisibilityControl.size() > 1)
+	{
+		// save visibility of nearby chat history
+		gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible());
+	}
+}
+
 void LLNearbyChatBar::onChatFontChange(LLFontGL* fontp)
 {
 	// Update things with the new font whohoo
@@ -413,6 +436,8 @@ void LLNearbyChatBar::onToggleNearbyChatPanel()
 		enableResizeCtrls(true);
 		storeRectControl();
 	}
+
+	saveChatHistoryVisibility();
 }
 
 void LLNearbyChatBar::setMinimized(BOOL b)
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index baf12a06ea..84040b8aab 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -92,6 +92,11 @@ protected:
 	LLLocalSpeakerMgr*		mSpeakerMgr;
 
 	S32 mExpandedHeight;
+private:
+
+	// Saves visibility of chat history panel
+	// if save_visibility="true"
+	void saveChatHistoryVisibility();
 };
 
 #endif
diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml
index 675f78d911..63992462b3 100644
--- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/en/floater_chat_bar.xml
@@ -9,6 +9,7 @@
  single_instance="true"
  title="NEARBY CHAT"
  save_rect="true"
+ save_visibility="true"
  can_close="true"
  can_minimize="true"
  help_topic="chat_bar"
-- 
cgit v1.2.3


From ed431700ed7ddd57a3629a3cd6bfb9c39b6105e0 Mon Sep 17 00:00:00 2001
From: Seth ProductEngine <slitovchuk@productengine.com>
Date: Fri, 30 Dec 2011 22:31:19 +0200
Subject: EXP-1756 FIXED setting user defined window size via floater Window
 Size.

---
 indra/llwindow/llwindow.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index 1351bed547..2e9e31bfea 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -186,8 +186,8 @@ BOOL LLWindow::setSize(LLCoordScreen size)
 {
 	if (!getMaximized())
 	{
-		size.mX = llmin(size.mX, mMinWindowWidth);
-		size.mY = llmin(size.mY, mMinWindowHeight);
+		size.mX = llmax(size.mX, mMinWindowWidth);
+		size.mY = llmax(size.mY, mMinWindowHeight);
 	}
 	return setSizeImpl(size);
 }
-- 
cgit v1.2.3


From 3861249a749c99c2a7b05d15ef82f8ff21453d05 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 3 Jan 2012 09:41:16 -0800
Subject: use lazy deletion of views via die() method to avoid some potential
 crashes

---
 indra/llui/llmenugl.cpp                  |  7 ++++++-
 indra/llui/llview.cpp                    |  6 ++++++
 indra/newview/llfavoritesbar.cpp         |  4 ++--
 indra/newview/llfloatercolorpicker.cpp   |  2 +-
 indra/newview/llfloatersnapshot.cpp      |  2 +-
 indra/newview/llfolderview.cpp           |  4 ++--
 indra/newview/llgrouplist.cpp            |  2 +-
 indra/newview/llpanelpeople.cpp          | 10 +++++-----
 indra/newview/llpanelprofile.cpp         |  2 +-
 indra/newview/llpanelteleporthistory.cpp |  2 +-
 10 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index cb237fca7c..95ecbb1c94 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -947,9 +947,14 @@ LLMenuItemBranchGL::LLMenuItemBranchGL(const LLMenuItemBranchGL::Params& p)
 
 LLMenuItemBranchGL::~LLMenuItemBranchGL()
 {
-	delete mBranchHandle.get();
+	if (mBranchHandle.get())
+	{
+		mBranchHandle.get()->die();
+	}
 }
 
+
+
 // virtual
 LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse) const
 {
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 486babb0ab..1529381773 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -121,6 +121,7 @@ LLView::Params::Params()
 
 LLView::LLView(const LLView::Params& p)
 :	mVisible(p.visible),
+	mInDraw(false),
 	mName(p.name),
 	mParentView(NULL),
 	mReshapeFlags(FOLLOWS_NONE),
@@ -281,6 +282,8 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child)
 // virtual
 bool LLView::addChild(LLView* child, S32 tab_group)
 {
+	llassert_always(mInDraw == false);
+
 	if (!child)
 	{
 		return false;
@@ -330,6 +333,7 @@ bool LLView::addChildInBack(LLView* child, S32 tab_group)
 // remove the specified child from the view, and set it's parent to NULL.
 void LLView::removeChild(LLView* child)
 {
+	llassert_always(mInDraw == false);
 	//llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs
 	if (child->mParentView == this) 
 	{
@@ -1081,6 +1085,7 @@ void LLView::draw()
 
 void LLView::drawChildren()
 {
+	mInDraw = true;
 	if (!mChildList.empty())
 	{
 		LLView* rootp = LLUI::getRootView();		
@@ -1119,6 +1124,7 @@ void LLView::drawChildren()
 		}
 		--sDepth;
 	}
+	mInDraw = false;
 }
 
 void LLView::dirtyRect()
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 4f2fd47488..f4b6dc2c81 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -405,8 +405,8 @@ LLFavoritesBarCtrl::~LLFavoritesBarCtrl()
 {
 	gInventory.removeObserver(this);
 
-	delete mOverflowMenuHandle.get();
-	delete mContextMenuHandle.get();
+	if (mOverflowMenuHandle.get()) mOverflowMenuHandle.get()->die();
+	if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
 }
 
 BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index 659e52271a..05d73c2416 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -271,7 +271,7 @@ void LLFloaterColorPicker::destroyUI ()
 	if ( mSwatchView )
 	{
 		this->removeChild ( mSwatchView );
-		delete mSwatchView;
+		mSwatchView->die();;
 		mSwatchView = NULL;
 	}
 }
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 1b3290d5a8..2dd031b5d3 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1977,7 +1977,7 @@ LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key)
 // Destroys the object
 LLFloaterSnapshot::~LLFloaterSnapshot()
 {
-	delete impl.mPreviewHandle.get();
+	if (impl.mPreviewHandle.get()) impl.mPreviewHandle.get()->die();
 
 	//unfreeze everything else
 	gSavedSettings.setBOOL("FreezeTime", FALSE);
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 6ec2598e44..20fe85472f 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -299,7 +299,7 @@ LLFolderView::~LLFolderView( void )
 	mAutoOpenItems.removeAllNodes();
 	gIdleCallbacks.deleteFunction(idle, this);
 
-	delete mPopupMenuHandle.get();
+	if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
 
 	mAutoOpenItems.removeAllNodes();
 	clearSelection();
@@ -1969,7 +1969,7 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 void LLFolderView::deleteAllChildren()
 {
 	closeRenamer();
-	delete mPopupMenuHandle.get();
+	if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
 	mPopupMenuHandle = LLHandle<LLView>();
 	mScrollContainer = NULL;
 	mRenameItem = NULL;
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index f7ed1116cb..bbf66ca750 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -95,7 +95,7 @@ LLGroupList::LLGroupList(const Params& p)
 LLGroupList::~LLGroupList()
 {
 	gAgent.removeListener(this);
-	delete mContextMenuHandle.get();
+	if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
 }
 
 // virtual
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index d5e289e6e6..9c46f04abf 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -526,11 +526,11 @@ LLPanelPeople::~LLPanelPeople()
 		LLVoiceClient::getInstance()->removeObserver(this);
 	}
 
-	delete mGroupPlusMenuHandle.get();
-	delete mNearbyViewSortMenuHandle.get();
-	delete mFriendsViewSortMenuHandle.get();
-	delete mGroupsViewSortMenuHandle.get();
-	delete mRecentViewSortMenuHandle.get();
+	if (mGroupPlusMenuHandle.get()) mGroupPlusMenuHandle.get()->die();
+	if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die();
+	if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die();
+	if (mGroupsViewSortMenuHandle.get()) mGroupsViewSortMenuHandle.get()->die();
+	if (mRecentViewSortMenuHandle.get()) mRecentViewSortMenuHandle.get()->die();
 
 }
 
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index b1eeabb028..e2e7006773 100755
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -177,7 +177,7 @@ LLPanelProfile::ChildStack::~ChildStack()
 			LLView* viewp = *it;
 			if (viewp)
 			{
-				delete viewp;
+				viewp->die();
 			}
 		}
 		mStack.pop_back();
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index d3543daff0..1f1cccad85 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -388,7 +388,7 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()
 LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
 {
 	LLTeleportHistoryFlatItemStorage::instance().purge();
-	delete mGearMenuHandle.get();
+	if (mGearMenuHandle.get()) mGearMenuHandle.get()->die();
 	mTeleportHistoryChangedConnection.disconnect();
 }
 
-- 
cgit v1.2.3


From 1b1ad93c5d341eb564a7e6fc1ae9298473d8a98e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 3 Jan 2012 12:21:30 -0800
Subject: EXP-1512 FIX changing UI size changes cursor position in notecards
 fixed case where adding text between 2 consecutive newlines created gibberish

---
 indra/llui/lltextbase.cpp | 15 +++++++++++++--
 indra/llui/llview.h       |  2 ++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 1f890b625f..0040be45c7 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1513,6 +1513,8 @@ void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg
 LLTextBase::segment_set_t::iterator LLTextBase::getEditableSegIterContaining(S32 index)
 {
 	segment_set_t::iterator it = getSegIterContaining(index);
+	segment_set_t::iterator orig_it = it;
+
 	if (it == mSegments.end()) return it;
 
 	if (!(*it)->canEdit() 
@@ -1520,13 +1522,18 @@ LLTextBase::segment_set_t::iterator LLTextBase::getEditableSegIterContaining(S32
 		&& it != mSegments.begin())
 	{
 		it--;
+		if ((*it)->canEdit())
+		{
+			return it;
+		}
 	}
-	return it;
+	return orig_it;
 }
 
 LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaining(S32 index) const
 {
 	segment_set_t::const_iterator it = getSegIterContaining(index);
+	segment_set_t::const_iterator orig_it = it;
 	if (it == mSegments.end()) return it;
 
 	if (!(*it)->canEdit() 
@@ -1534,8 +1541,12 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaini
 		&& it != mSegments.begin())
 	{
 		it--;
+		if ((*it)->canEdit())
+		{
+			return it;
+		}
 	}
-	return it;
+	return orig_it;
 }
 
 LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index f21fb37e18..f1fac5f69c 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -612,6 +612,8 @@ private:
 
 	S32			mNextInsertionOrdinal;
 
+	bool		mInDraw;
+
 	static LLWindow* sWindow;	// All root views must know about their window.
 
 	typedef std::map<std::string, LLView*> default_widget_map_t;
-- 
cgit v1.2.3


From 377a9ab9ac3b098492cbd010f3091c713ac6dc83 Mon Sep 17 00:00:00 2001
From: Paul ProductEngine <pguslisty@productengine.com>
Date: Wed, 4 Jan 2012 14:50:15 +0200
Subject: EXP-1586 ADDITIONAL FIX (Nearby chat window no longer persists
 between viewer startups)

- Got rid of confusing conditions.
---
 indra/newview/llnearbychatbar.cpp | 23 ++---------------------
 indra/newview/llnearbychatbar.h   |  5 -----
 2 files changed, 2 insertions(+), 26 deletions(-)

diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index cb08ca8862..4512c14b7a 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -111,14 +111,7 @@ BOOL LLNearbyChatBar::postBuild()
 
 	gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE);
 
-	// If mVisibilityControl is not empty it means that the visibility state of floater is saved between sessions,
-	// i.e. save_visibility="true" for this floater.
-	// So if we need to restore visibility state of floater we also need to restore visibility state of nearby chat history.
-	if (!mVisibilityControl.empty())
-	{
-		// restore visibility of nearby chat history
-		mNearbyChat->setVisible(gSavedSettings.getBOOL("nearbychat_history_visibility"));
-	}
+	mNearbyChat->setVisible(gSavedSettings.getBOOL("nearbychat_history_visibility"));
 
 	// Register for font change notifications
 	LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1));
@@ -152,18 +145,6 @@ bool LLNearbyChatBar::applyRectControl()
 	return rect_controlled;
 }
 
-void LLNearbyChatBar::saveChatHistoryVisibility()
-{
-	// save visibility state of nearby chat history panel if
-	// visibility of nearby chat floater is saved, i.e. save_visisbility="true"
-	// (if save_visisbility="true", mVisibilityControl == "floater_vis_chat_bar")
-	if (mVisibilityControl.size() > 1)
-	{
-		// save visibility of nearby chat history
-		gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible());
-	}
-}
-
 void LLNearbyChatBar::onChatFontChange(LLFontGL* fontp)
 {
 	// Update things with the new font whohoo
@@ -437,7 +418,7 @@ void LLNearbyChatBar::onToggleNearbyChatPanel()
 		storeRectControl();
 	}
 
-	saveChatHistoryVisibility();
+	gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible());
 }
 
 void LLNearbyChatBar::setMinimized(BOOL b)
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index 84040b8aab..baf12a06ea 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -92,11 +92,6 @@ protected:
 	LLLocalSpeakerMgr*		mSpeakerMgr;
 
 	S32 mExpandedHeight;
-private:
-
-	// Saves visibility of chat history panel
-	// if save_visibility="true"
-	void saveChatHistoryVisibility();
 };
 
 #endif
-- 
cgit v1.2.3


From ce6bd89ca4fbc3d1d75725e8cfc8857e21052107 Mon Sep 17 00:00:00 2001
From: Ima Mechanique <none@none>
Date: Wed, 4 Jan 2012 15:16:35 +0000
Subject: Changes per Oz's suggestion on RB.

---
 indra/newview/llpreviewscript.cpp | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index cab30b1295..88727bf59b 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1154,18 +1154,15 @@ void LLScriptEdCore::onBtnSaveToFile( void* userdata )
 	if( self->mSaveCallback )
 	{
 		LLFilePicker& file_picker = LLFilePicker::instance();
-		if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_SCRIPT ) )
+		if( file_picker.getSaveFile( LLFilePicker::FFSAVE_SCRIPT ) )
 		{
-			//File picking cancelled by user, so nothing to do.
-			return;
+			std::string filename = file_picker.getFirstFile();
+			std::string scriptText=self->mEditor->getText();
+			std::ofstream fout(filename.c_str());
+			fout<<(scriptText);
+			fout.close();
+			self->mSaveCallback( self->mUserdata, FALSE );
 		}
-
-		std::string filename = file_picker.getFirstFile();
-		std::string scriptText=self->mEditor->getText();
-		std::ofstream fout(filename.c_str());
-		fout<<(scriptText);
-		fout.close();
-		self->mSaveCallback( self->mUserdata, FALSE );
 	}
 }
 
@@ -1187,8 +1184,7 @@ bool LLScriptEdCore::enableSaveToFileMenu(void* userdata)
 bool LLScriptEdCore::enableLoadFromFileMenu(void* userdata)
 {
 	LLScriptEdCore* self = (LLScriptEdCore*)userdata;
-	if (!self || !self->mEditor) return FALSE;
-	return self->mEditor->canLoadOrSaveToFile();
+	return (self && self->mEditor) ? self->mEditor->canLoadOrSaveToFile() : FALSE;
 }
 
 /// ---------------------------------------------------------------------------
-- 
cgit v1.2.3


From 94ad019ce3387b9c5207fe3207933697059dd2dd Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Wed, 4 Jan 2012 14:14:23 -0700
Subject: fix for SH-2823 and SH-2824: crash in curl:
 LLBufferArray::countAfter() and LLBufferArray::copyIntoBuffers reviewed by
 vir

---
 indra/llmessage/llurlrequest.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index a3a2b2b1b8..261e57e79e 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -64,7 +64,7 @@ public:
 	~LLURLRequestDetail();
 	std::string mURL;
 	LLCurlEasyRequest* mCurlRequest;
-	LLBufferArray* mResponseBuffer;
+	LLIOPipe::buffer_ptr_t mResponseBuffer;
 	LLChannelDescriptors mChannels;
 	U8* mLastRead;
 	U32 mBodyLimit;
@@ -75,7 +75,6 @@ public:
 
 LLURLRequestDetail::LLURLRequestDetail() :
 	mCurlRequest(NULL),
-	mResponseBuffer(NULL),
 	mLastRead(NULL),
 	mBodyLimit(0),
 	mByteAccumulator(0),
@@ -90,7 +89,6 @@ LLURLRequestDetail::~LLURLRequestDetail()
 {
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	delete mCurlRequest;
-	mResponseBuffer = NULL;
 	mLastRead = NULL;
 }
 
@@ -326,7 +324,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 
 		// *FIX: bit of a hack, but it should work. The configure and
 		// callback method expect this information to be ready.
-		mDetail->mResponseBuffer = buffer.get();
+		mDetail->mResponseBuffer = buffer;
 		mDetail->mChannels = channels;
 		if(!configure())
 		{
-- 
cgit v1.2.3


From 912833bafa9a59734432787158e36b66ee9586aa Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 4 Jan 2012 14:04:32 -0800
Subject: EXP-1738 FIX -- Disable drag and drop to folders in the outbox that
 would create a hierarchy that contains too many folders

* Updated drag and drop to correctly handle moving to and from outbox as opposed to within the outbox when dealing with
  folder and item count limitations related to depth and total folder count.
---
 indra/newview/llfloateroutbox.cpp              |   2 +-
 indra/newview/llfolderviewitem.cpp             |  14 ++--
 indra/newview/llfolderviewitem.h               |  10 +--
 indra/newview/llinventorybridge.cpp            | 101 +++++++++++++++++++------
 indra/newview/lltooldraganddrop.cpp            |   2 +
 indra/newview/skins/default/xui/en/strings.xml |   3 +
 6 files changed, 96 insertions(+), 36 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index b97cc54dd1..8ccebb36dc 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -387,7 +387,7 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 		{
 			LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder();
 			
-			handled = root_folder->handleDragAndDropToRoot(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+			handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
 		}
 	}
 	
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 526800d4be..dc42bb148d 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -2285,7 +2285,7 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,
 
 	if (!handled)
 	{
-		handleDragAndDropToRoot(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+		handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
 
 		lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl;
 	}
@@ -2293,12 +2293,12 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,
 	return TRUE;
 }
 
-BOOL LLFolderViewFolder::handleDragAndDropToRoot(MASK mask,
-												 BOOL drop,
-												 EDragAndDropType cargo_type,
-												 void* cargo_data,
-												 EAcceptance* accept,
-												 std::string& tooltip_msg)
+BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask,
+													   BOOL drop,
+													   EDragAndDropType cargo_type,
+													   void* cargo_data,
+													   EAcceptance* accept,
+													   std::string& tooltip_msg)
 {
 	BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
 	
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 02461fb144..0f8c3edef8 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -547,11 +547,11 @@ public:
 		void* cargo_data,
 		EAcceptance* accept,
 		std::string& tooltip_msg);
-	BOOL handleDragAndDropToRoot(MASK mask, BOOL drop,
-								 EDragAndDropType cargo_type,
-								 void* cargo_data,
-								 EAcceptance* accept,
-								 std::string& tooltip_msg);
+	BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop,
+									   EDragAndDropType cargo_type,
+									   void* cargo_data,
+									   EAcceptance* accept,
+									   std::string& tooltip_msg);
 	virtual void draw();
 
 	time_t getCreationDate() const;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 96c527859c..c94deed5e2 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1926,23 +1926,47 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 		//
 
 		BOOL is_movable = TRUE;
-		if (LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()))
+
+		if (is_movable && (mUUID == cat_id))
+		{
+			is_movable = FALSE;
+			tooltip_msg = LLTrans::getString("TooltipDragOntoSelf");
+		}
+		if (is_movable && (model->isObjectDescendentOf(mUUID, cat_id)))
+		{
+			is_movable = FALSE;
+			tooltip_msg = LLTrans::getString("TooltipDragOntoOwnChild");
+		}
+		if (is_movable && LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()))
+		{
 			is_movable = FALSE;
-		else if (move_is_into_outfit)
+			// tooltip?
+		}
+		if (is_movable && move_is_into_outfit)
+		{
 			is_movable = FALSE;
-		else if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))
+			// tooltip?
+		}
+		if (is_movable && (mUUID == model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE)))
+		{
 			is_movable = FALSE;
+			// tooltip?
+		}
+		
 		LLInventoryModel::cat_array_t descendent_categories;
 		LLInventoryModel::item_array_t descendent_items;
-		gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE);
-		for (S32 i=0; i < descendent_categories.count(); ++i)
+		if (is_movable)
 		{
-			LLInventoryCategory* category = descendent_categories[i];
-			if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+			model->collectDescendents(cat_id, descendent_categories, descendent_items, FALSE);
+			for (S32 i=0; i < descendent_categories.count(); ++i)
 			{
-				// Can't move "special folders" (e.g. Textures Folder).
-				is_movable = FALSE;
-				break;
+				LLInventoryCategory* category = descendent_categories[i];
+				if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+				{
+					// Can't move "special folders" (e.g. Textures Folder).
+					is_movable = FALSE;
+					break;
+				}
 			}
 		}
 		if (is_movable && move_is_into_trash)
@@ -1974,7 +1998,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 		}
 		if (is_movable && move_is_into_outbox)
 		{
-			int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat);
+			const int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat);
 			
 			if (nested_folder_levels > gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"))
 			{
@@ -1983,23 +2007,56 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 			}
 			else
 			{
-				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
-				
+				int dragged_folder_count = descendent_categories.count();
 				int existing_item_count = 0;
-				int existing_folder_count = 1 + LLToolDragAndDrop::instance().getCargoIDsCount();  // +1 for master folder
+				int existing_folder_count = 0;
+				
+				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
 				
 				if (master_folder != NULL)
 				{
+					if (model->isObjectDescendentOf(cat_id, master_folder->getUUID()))
+					{
+						// Don't use count because we're already inside the same category anyway
+						dragged_folder_count = 0;
+					}
+					else
+					{
+						existing_folder_count = 1; // Include the master folder in the count!
+
+						// If we're in the drop operation as opposed to the drag without drop, we are doing a
+						// single category at a time so don't block based on the total amount of cargo data items
+						if (drop)
+						{
+							dragged_folder_count += 1;
+						}
+						else
+						{
+							// NOTE: The cargo id's count is a total of categories AND items but we err on the side of
+							//       prevention rather than letting too many folders into the hierarchy of the outbox,
+							//       when we're dragging the item to a new parent
+							dragged_folder_count += LLToolDragAndDrop::instance().getCargoIDsCount();
+						}
+					}
+					
+					// Tally the total number of categories and items inside the master folder
+
 					LLInventoryModel::cat_array_t existing_categories;
 					LLInventoryModel::item_array_t existing_items;
 
-					gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE);
+					model->collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE);
 					
-					existing_item_count += existing_items.count();
 					existing_folder_count += existing_categories.count();
+					existing_item_count += existing_items.count();
+				}
+				else
+				{
+					// Assume a single category is being dragged to the outbox since we evaluate one at a time
+					// when not putting them under a parent item.
+					dragged_folder_count += 1;
 				}
 
-				const int nested_folder_count = existing_folder_count + descendent_categories.count();
+				const int nested_folder_count = existing_folder_count + dragged_folder_count;
 				const int nested_item_count = existing_item_count + descendent_items.count();
 				
 				if (nested_folder_count > gSavedSettings.getU32("InventoryOutboxMaxFolderCount"))
@@ -2031,10 +2088,8 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 		// 
 		//--------------------------------------------------------------------------------
 
-		accept = is_movable
-			&& (mUUID != cat_id)								// Can't move a folder into itself
-			&& (mUUID != inv_cat->getParentUUID())				// Avoid moves that would change nothing
-			&& !(model->isObjectDescendentOf(mUUID, cat_id));	// Avoid circularity
+		accept = is_movable;
+
 		if (accept && drop)
 		{
 			// Look for any gestures and deactivate them
@@ -2066,7 +2121,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 						// Recursively create links in target outfit.
 						LLInventoryModel::cat_array_t cats;
 						LLInventoryModel::item_array_t items;
-						gInventory.collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
+						model->collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
 						LLAppearanceMgr::instance().linkAll(mUUID,items,NULL);
 					}
 				}
@@ -2100,7 +2155,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 			}
 			else
 			{
-				if (gInventory.isObjectDescendentOf(cat_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
+				if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
 				{
 					set_dad_inbox_object(cat_id);
 				}
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 6910b8eced..6338ea477c 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -626,6 +626,8 @@ BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask)
 void LLToolDragAndDrop::handleDeselect()
 {
 	mToolTipMsg.clear();
+
+	LLToolTipMgr::instance().blockToolTips();
 }
 
 // protected
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 18ca3033e9..6672d479a2 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -172,6 +172,9 @@ Please try logging in again in a minute.</string>
 	<string name="TooltipOutboxTooManyFolders">Subfolder count in top-level folder exceeds 20</string>
 	<string name="TooltipOutboxTooManyObjects">Item count in top-level folder exceeds 200</string>
 	
+	<string name="TooltipDragOntoOwnChild">You can't move a folder into its child</string>
+	<string name="TooltipDragOntoSelf">You can't move a folder into itself</string>
+	
 	<!-- tooltips for Urls -->
 	<string name="TooltipHttpUrl">Click to view this web page</string>
 	<string name="TooltipSLURL">Click to view this location's information</string>
-- 
cgit v1.2.3


From e326b1e0fa8ccae7f62e4d028bd9cfeade2ff9d7 Mon Sep 17 00:00:00 2001
From: "Debi King (Dessie)" <dessie@lindenlab.com>
Date: Wed, 4 Jan 2012 17:41:54 -0500
Subject: Added tag DRTVWR-106_3.2.5-beta1, 3.2.5-beta1 for changeset
 3d2d5d244c63

---
 .hgtags | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.hgtags b/.hgtags
index 539efb0ffc..97e0cc033c 100644
--- a/.hgtags
+++ b/.hgtags
@@ -232,3 +232,5 @@ a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
 3fe994349fae64fc40874bb59db387131eb35a41 DRTVWR-104_3.2.4-beta1
 3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-beta1
 8a44ff3d2104269ce76145c2772cf1bdff2a2abe 3.2.5-start
+3d2d5d244c6398a4214c666d5dd3965b0918709a DRTVWR-106_3.2.5-beta1
+3d2d5d244c6398a4214c666d5dd3965b0918709a 3.2.5-beta1
-- 
cgit v1.2.3


From b99dfa7d468b37f19b8cc08a5d00b2eceddbfbb1 Mon Sep 17 00:00:00 2001
From: "Debi King (Dessie)" <dessie@lindenlab.com>
Date: Wed, 4 Jan 2012 17:42:40 -0500
Subject: Added tag DRTVWR-107_3.2.5-beta2, 3.2.5-beta2 for changeset
 65a2c1c8d855

---
 .hgtags | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.hgtags b/.hgtags
index 97e0cc033c..90566e16e8 100644
--- a/.hgtags
+++ b/.hgtags
@@ -234,3 +234,5 @@ a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
 8a44ff3d2104269ce76145c2772cf1bdff2a2abe 3.2.5-start
 3d2d5d244c6398a4214c666d5dd3965b0918709a DRTVWR-106_3.2.5-beta1
 3d2d5d244c6398a4214c666d5dd3965b0918709a 3.2.5-beta1
+65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d DRTVWR-107_3.2.5-beta2
+65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d 3.2.5-beta2
-- 
cgit v1.2.3


From 990b5aea2b92ac8c06651ad94db9506a42ba1be0 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 4 Jan 2012 17:34:11 -0800
Subject: EXP-1769 FIX -- Crash in ASSERT (mInDraw == false) - can trigger with
 selecting build tool

* Fixed build window to not fail assert at construction time.
---
 indra/newview/llfloatermediasettings.cpp | 11 +++++++----
 indra/newview/llfloatertools.cpp         |  4 +---
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp
index b5f1b967df..895e16adef 100644
--- a/indra/newview/llfloatermediasettings.cpp
+++ b/indra/newview/llfloatermediasettings.cpp
@@ -212,10 +212,13 @@ void LLFloaterMediaSettings::commitFields()
 //static 
 void LLFloaterMediaSettings::clearValues( bool editable)
 {
-	// clean up all panels before updating
-	sInstance->mPanelMediaSettingsGeneral	 ->clearValues(sInstance->mPanelMediaSettingsGeneral,  editable);
-	sInstance->mPanelMediaSettingsSecurity	 ->clearValues(sInstance->mPanelMediaSettingsSecurity,	editable);
-	sInstance->mPanelMediaSettingsPermissions->clearValues(sInstance->mPanelMediaSettingsPermissions,  editable);	
+	if (sInstance)
+	{
+		// clean up all panels before updating
+		sInstance->mPanelMediaSettingsGeneral	 ->clearValues(sInstance->mPanelMediaSettingsGeneral,  editable);
+		sInstance->mPanelMediaSettingsSecurity	 ->clearValues(sInstance->mPanelMediaSettingsSecurity,	editable);
+		sInstance->mPanelMediaSettingsPermissions->clearValues(sInstance->mPanelMediaSettingsPermissions,  editable);
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 1008b4a6e4..bd5b5f4eb0 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -529,7 +529,7 @@ void LLFloaterTools::refresh()
 	mPanelLandInfo->refresh();
 
 	// Refresh the advanced weights floater
-	LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::getTypedInstance<LLFloaterObjectWeights>("object_weights");
+	LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::findTypedInstance<LLFloaterObjectWeights>("object_weights");
 	if(object_weights_floater && object_weights_floater->getVisible())
 	{
 		object_weights_floater->refresh();
@@ -1409,9 +1409,7 @@ bool LLFloaterTools::deleteMediaConfirm(const LLSD& notification, const LLSD& re
 //
 void LLFloaterTools::clearMediaSettings()
 {
-	LLFloaterMediaSettings::getInstance();
 	LLFloaterMediaSettings::clearValues(false);
-
 }
 
 //////////////////////////////////////////////////////////////////////////////
-- 
cgit v1.2.3


From 9c8f6ba6a51b799d16e89e995bbcf3b0dcc15c62 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 4 Jan 2012 17:37:57 -0800
Subject: Modified CRASH assert to not occur in release mode per Richard

---
 indra/llui/llview.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 1529381773..542f57ee5f 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -282,7 +282,8 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child)
 // virtual
 bool LLView::addChild(LLView* child, S32 tab_group)
 {
-	llassert_always(mInDraw == false);
+	// NOTE: Changed this to not crash in release mode
+	llassert(mInDraw == false);
 
 	if (!child)
 	{
-- 
cgit v1.2.3


From ce1f95bade2eeec5732d3275bb54fd1612ab03fb Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Wed, 4 Jan 2012 21:06:54 -0700
Subject: trivial: debug code for SH-2828: [crashhunters] Crash in
 LLRefCount::unref(), bad stacks

---
 indra/newview/llviewerwindow.cpp | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 31dfa1923c..29f951da93 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1956,33 +1956,42 @@ void LLViewerWindow::shutdownViews()
 	// clean up warning logger
 	LLError::removeRecorder(RecordToChatConsole::getInstance());
 
+	llinfos << "Warning logger is cleaned." << llendl ;
+
 	delete mDebugText;
 	mDebugText = NULL;
 	
+	llinfos << "DebugText deleted." << llendl ;
+
 	// Cleanup global views
 	if (gMorphView)
 	{
 		gMorphView->setVisible(FALSE);
 	}
+	llinfos << "Global views cleaned." << llendl ;
 
 	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
 	// will crump with LL_ERRS.
 	LLModalDialog::shutdownModals();
-	
+	llinfos << "LLModalDialog shut down." << llendl; 
+
 	// destroy the nav bar, not currently part of gViewerWindow
 	// *TODO: Make LLNavigationBar part of gViewerWindow
 	if (LLNavigationBar::instanceExists())
 	{
 		delete LLNavigationBar::getInstance();
 	}
+	llinfos << "LLNavigationBar destroyed." << llendl ;
 
 	// destroy menus after instantiating navbar above, as it needs
 	// access to gMenuHolder
 	cleanup_menus();
+	llinfos << "menus destroyed." << llendl ;
 
 	// Delete all child views.
 	delete mRootView;
 	mRootView = NULL;
+	llinfos << "RootView deleted." << llendl ;
 
 	// Automatically deleted as children of mRootView.  Fix the globals.
 	gStatusBar = NULL;
-- 
cgit v1.2.3


From 263fd1345875eb0389e2ed0a8cbeb4e458a2d007 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 5 Jan 2012 10:57:09 -0800
Subject: Removed unused code for old outbox error reporting

---
 .../newview/llpanelmarketplaceoutboxinventory.cpp  | 99 ++--------------------
 indra/newview/llpanelmarketplaceoutboxinventory.h  | 26 +-----
 .../xui/en/widgets/outbox_folder_view_folder.xml   | 10 ---
 3 files changed, 8 insertions(+), 127 deletions(-)

diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp
index ed1206aec8..1dd68b7758 100644
--- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp
+++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp
@@ -46,50 +46,6 @@ static LLDefaultChildRegistry::Register<LLOutboxInventoryPanel> r1("outbox_inven
 static LLDefaultChildRegistry::Register<LLOutboxFolderViewFolder> r2("outbox_folder_view_folder");
 
 
-//
-// Marketplace errors
-//
-
-enum
-{
-	MKTERR_NONE = 0,
-
-	MKTERR_NOT_MERCHANT,
-	MKTERR_FOLDER_EMPTY,
-	MKTERR_UNASSOCIATED_PRODUCTS,
-	MKTERR_OBJECT_LIMIT,
-	MKTERR_FOLDER_DEPTH,
-	MKTERR_UNSELLABLE_ITEM,
-	MKTERR_INTERNAL_IMPORT,
-
-	MKTERR_COUNT
-};
-
-static const std::string MARKETPLACE_ERROR_STRINGS[MKTERR_COUNT] =
-{
-	"NO_ERROR",
-	"NOT_MERCHANT_ERROR",
-	"FOLDER_EMPTY_ERROR",
-	"UNASSOCIATED_PRODUCTS_ERROR",
-	"OBJECT_LIMIT_ERROR",
-	"FOLDER_DEPTH_ERROR",
-	"UNSELLABLE_ITEM_FOUND",
-	"INTERNAL_IMPORT_ERROR",
-};
-
-static const std::string MARKETPLACE_ERROR_NAMES[MKTERR_COUNT] =
-{
-	"Marketplace Error None",
-	"Marketplace Error Not Merchant",
-	"Marketplace Error Empty Folder",
-	"Marketplace Error Unassociated Products",
-	"Marketplace Error Object Limit",
-	"Marketplace Error Folder Depth",
-	"Marketplace Error Unsellable Item",
-	"Marketplace Error Internal Import",
-};
-
-
 //
 // LLOutboxInventoryPanel Implementation
 //
@@ -206,63 +162,18 @@ LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge *
 
 LLOutboxFolderViewFolder::LLOutboxFolderViewFolder(const Params& p)
 	: LLFolderViewFolder(p)
-	, LLBadgeOwner(getHandle())
-	, mError(0)
-{
-	initBadgeParams(p.error_badge());
-}
-
-LLOutboxFolderViewFolder::~LLOutboxFolderViewFolder()
 {
 }
 
-// virtual
-void LLOutboxFolderViewFolder::draw()
-{
-	if (!badgeHasParent())
-	{
-		addBadgeToParentPanel();
-	}
-	
-	setBadgeVisibility(hasError());
-
-	LLFolderViewFolder::draw();
-}
-
-void LLOutboxFolderViewFolder::setErrorString(const std::string& errorString)
-{
-	S32 error_code = MKTERR_NONE;
-
-	for (S32 i = 1; i < MKTERR_COUNT; ++i)
-	{
-		if (MARKETPLACE_ERROR_STRINGS[i] == errorString)
-		{
-			error_code = i;
-			break;
-		}
-	}
-
-	setError(error_code);
-}
-
-void LLOutboxFolderViewFolder::setError(S32 errorCode)
-{
-	mError = errorCode;
-
-	if (hasError())
-	{
-		setToolTip(LLTrans::getString(MARKETPLACE_ERROR_NAMES[mError]));
-	}
-	else
-	{
-		setToolTip(LLStringExplicit(""));
-	}
-}
-
 //
 // LLOutboxFolderViewItem Implementation
 //
 
+LLOutboxFolderViewItem::LLOutboxFolderViewItem(const Params& p)
+	: LLFolderViewItem(p)
+{
+}
+
 BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask)
 {
 	return TRUE;
diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.h b/indra/newview/llpanelmarketplaceoutboxinventory.h
index 346680a79d..167f371f0e 100644
--- a/indra/newview/llpanelmarketplaceoutboxinventory.h
+++ b/indra/newview/llpanelmarketplaceoutboxinventory.h
@@ -28,7 +28,6 @@
 #define LL_OUTBOXINVENTORYPANEL_H
 
 
-#include "llbadgeowner.h"
 #include "llinventorypanel.h"
 #include "llfolderviewitem.h"
 
@@ -53,41 +52,22 @@ public:
 };
 
 
-class LLOutboxFolderViewFolder : public LLFolderViewFolder, public LLBadgeOwner
+class LLOutboxFolderViewFolder : public LLFolderViewFolder
 {
 public:
 	struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params>
 	{
-		Optional<LLBadge::Params>	error_badge;
-		
-		Params()
-			: error_badge("error_badge")
-		{
-		}
+		Params() {}
 	};
 	
 	LLOutboxFolderViewFolder(const Params& p);
-	~LLOutboxFolderViewFolder();
-
-	void draw();
-
-	void setErrorString(const std::string& errorString);
-	void setError(S32 errorCode);
-	
-	bool hasError() const { return (mError != 0); }
-
-protected:
-	S32 mError;
 };
 
 
 class LLOutboxFolderViewItem : public LLFolderViewItem
 {
 public:
-	LLOutboxFolderViewItem(const Params& p)
-		: LLFolderViewItem(p)
-	{
-	}
+	LLOutboxFolderViewItem(const Params& p);
 
 	// virtual
 	BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml
index 0792996107..d19c47f54f 100644
--- a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml
+++ b/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml
@@ -6,14 +6,4 @@
   item_top_pad="4"
   selection_image="Rounded_Square"
   >
-  <error_badge 
-    label=" " 
-    label_offset_horiz="-1"
-    location="right" 
-    padding_horiz="12.5" 
-    padding_vert="2"
-    location_offset_hcenter="-23"
-    image="Error_Tag_Background"
-    image_color="Black"
-    />
 </outbox_folder_view_folder>
-- 
cgit v1.2.3


From 26998a5e387edca7d89159673c3dc8cd1a8d7539 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 5 Jan 2012 12:42:58 -0800
Subject: EXP-1753 FIX -- Open Merchant Outbox floater when user selects copy
 to Merchant Outbox context menu option in Inventory

* Modified "copy to merchant outbox" and "move to merchant outbox" context menu actions to also open the merchant outbox floater
* Changed context menu behavior to always preserve disabled menu items on multiselect rather than occasionally ignoring it
---
 indra/newview/llinventorybridge.cpp    | 24 ++++++++++++------------
 indra/newview/llinventorybridge.h      |  3 +--
 indra/newview/llinventoryfunctions.cpp | 15 ++++++++++-----
 3 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index c94deed5e2..3b6dad7f5c 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -465,14 +465,13 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
 
 void hide_context_entries(LLMenuGL& menu, 
 						  const menuentry_vec_t &entries_to_show,
-						  const menuentry_vec_t &disabled_entries,
-						  BOOL append) // If append is TRUE, then new enabled entries 
+						  const menuentry_vec_t &disabled_entries) // If append is TRUE, then new enabled entries 
 {
 	const LLView::child_list_t *list = menu.getChildList();
 
 	// For removing double separators or leading separator.  Start at true so that
 	// if the first element is a separator, it will not be shown.
-	BOOL is_previous_entry_separator = TRUE;
+	bool is_previous_entry_separator = true;
 
 	for (LLView::child_list_t::const_iterator itor = list->begin(); 
 		 itor != list->end(); 
@@ -496,6 +495,7 @@ void hide_context_entries(LLMenuGL& menu,
 			if (*itor2 == name)
 			{
 				found = true;
+				break;
 			}
 		}
 
@@ -503,9 +503,8 @@ void hide_context_entries(LLMenuGL& menu,
 		// between two separators).
 		if (found)
 		{
-			const BOOL is_entry_separator = (dynamic_cast<LLMenuItemSeparatorGL *>(menu_item) != NULL);
-			if (is_entry_separator && is_previous_entry_separator)
-				found = false;
+			const bool is_entry_separator = (dynamic_cast<LLMenuItemSeparatorGL *>(menu_item) != NULL);
+			found = !(is_entry_separator && is_previous_entry_separator);
 			is_previous_entry_separator = is_entry_separator;
 		}
 		
@@ -523,15 +522,13 @@ void hide_context_entries(LLMenuGL& menu,
 			// A bit of a hack so we can remember that some UI element explicitly set this to be visible
 			// so that some other UI element from multi-select doesn't later set this invisible.
 			menu_item->pushVisible(TRUE);
-			if (append)
-			{
-				menu_item->setEnabled(TRUE);
-			}
+
 			for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
 			{
 				if (*itor2 == name)
 				{
 					menu_item->setEnabled(FALSE);
+					break;
 				}
 			}
 		}
@@ -2946,7 +2943,7 @@ void LLFolderBridge::folderOptionsMenu()
 	LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get());
 	if (menup)
 	{
-		hide_context_entries(*menup, mItems, mDisabledItems, TRUE);
+		hide_context_entries(*menup, mItems, mDisabledItems);
 
 		// Reposition the menu, in case we're adding items to an existing menu.
 		menup->needsArrange();
@@ -3025,11 +3022,14 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 		// Not sure what the right thing is to do here.
 		if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
 		{
-			if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox
+			if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox or outbox
 			{
 				// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
 				if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+				{
 					mItems.push_back(std::string("New Folder"));
+				}
+
 				mItems.push_back(std::string("New Script"));
 				mItems.push_back(std::string("New Note"));
 				mItems.push_back(std::string("New Gesture"));
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 126a28f74c..447d781f48 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -648,7 +648,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
 // are set as enabled.
 void hide_context_entries(LLMenuGL& menu, 
 						  const menuentry_vec_t &entries_to_show, 
-						  const menuentry_vec_t &disabled_entries,
-						  BOOL append = FALSE);
+						  const menuentry_vec_t &disabled_entries);
 
 #endif // LL_LLINVENTORYBRIDGE_H
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 6c5325620e..e8efac1ebf 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -530,6 +530,11 @@ void show_item_original(const LLUUID& item_uuid)
 	}
 }
 
+void open_outbox()
+{
+	LLFloaterReg::showInstance("outbox");
+}
+
 void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
 {
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -588,6 +593,8 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
 				parent = next_parent;
 			}
 		}
+		
+		open_outbox();
 	}
 }
 
@@ -625,6 +632,8 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
 								dest_folder,
 								inv_item->getName(),
 								LLPointer<LLInventoryCallback>(NULL));
+
+			open_outbox();
 		}
 		else
 		{	
@@ -682,11 +691,7 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold
 		copy_folder_to_outbox(category, new_folder_id, top_level_folder);
 	}
 
-	// delete the folder if we have emptied it
-	//if (cat_array->empty() && item_array->empty())
-	//{
-	//	remove_category(inventory_model, inv_cat->getUUID());
-	//}
+	open_outbox();
 }
 
 ///----------------------------------------------------------------------------
-- 
cgit v1.2.3


From 61b5f3143e4ea53c9f64e5a1a5ad19f2edf3e776 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 5 Jan 2012 15:43:23 -0500
Subject: Introduce LLStreamQueue to buffer nonblocking I/O. Add unit tests to
 verify basic functionality.

---
 indra/llcommon/CMakeLists.txt               |   3 +
 indra/llcommon/llstreamqueue.cpp            |  24 +++
 indra/llcommon/llstreamqueue.h              | 229 ++++++++++++++++++++++++++++
 indra/llcommon/tests/llstreamqueue_test.cpp | 177 +++++++++++++++++++++
 4 files changed, 433 insertions(+)
 create mode 100644 indra/llcommon/llstreamqueue.cpp
 create mode 100644 indra/llcommon/llstreamqueue.h
 create mode 100644 indra/llcommon/tests/llstreamqueue_test.cpp

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index c8e1827584..334f78cbff 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -88,6 +88,7 @@ set(llcommon_SOURCE_FILES
     llsingleton.cpp
     llstat.cpp
     llstacktrace.cpp
+    llstreamqueue.cpp
     llstreamtools.cpp
     llstring.cpp
     llstringtable.cpp
@@ -221,6 +222,7 @@ set(llcommon_HEADER_FILES
     llstat.h
     llstatenums.h
     llstl.h
+    llstreamqueue.h
     llstreamtools.h
     llstrider.h
     llstring.h
@@ -327,6 +329,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llprocesslauncher "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
 
   # *TODO - reenable these once tcmalloc libs no longer break the build.
   #ADD_BUILD_TEST(llallocator llcommon)
diff --git a/indra/llcommon/llstreamqueue.cpp b/indra/llcommon/llstreamqueue.cpp
new file mode 100644
index 0000000000..1116a2b6a2
--- /dev/null
+++ b/indra/llcommon/llstreamqueue.cpp
@@ -0,0 +1,24 @@
+/**
+ * @file   llstreamqueue.cpp
+ * @author Nat Goodspeed
+ * @date   2012-01-05
+ * @brief  Implementation for llstreamqueue.
+ * 
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Copyright (c) 2012, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llstreamqueue.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+
+// As of this writing, llstreamqueue.h is entirely template-based, therefore
+// we don't strictly need a corresponding .cpp file. However, our CMake test
+// macro assumes one. Here it is.
+bool llstreamqueue_cpp_ignored = true;
diff --git a/indra/llcommon/llstreamqueue.h b/indra/llcommon/llstreamqueue.h
new file mode 100644
index 0000000000..2fbc2067d2
--- /dev/null
+++ b/indra/llcommon/llstreamqueue.h
@@ -0,0 +1,229 @@
+/**
+ * @file   llstreamqueue.h
+ * @author Nat Goodspeed
+ * @date   2012-01-04
+ * @brief  Definition of LLStreamQueue
+ * 
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Copyright (c) 2012, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLSTREAMQUEUE_H)
+#define LL_LLSTREAMQUEUE_H
+
+#include <string>
+#include <list>
+#include <iosfwd>                   // std::streamsize
+#include <boost/iostreams/categories.hpp>
+
+/**
+ * This class is a growable buffer between a producer and consumer. It serves
+ * as a queue usable with Boost.Iostreams -- hence, a "stream queue."
+ *
+ * This is especially useful for buffering nonblocking I/O. For instance, we
+ * want application logic to be able to serialize LLSD to a std::ostream. We
+ * may write more data than the destination pipe can handle all at once, but
+ * it's imperative NOT to block the application-level serialization call. So
+ * we buffer it instead. Successive frames can try nonblocking writes to the
+ * destination pipe until all buffered data has been sent.
+ *
+ * Similarly, we want application logic be able to deserialize LLSD from a
+ * std::istream. Again, we must not block that deserialize call waiting for
+ * more data to arrive from the input pipe! Instead we build up a buffer over
+ * a number of frames, using successive nonblocking reads, until we have
+ * "enough" data to be able to present it through a std::istream.
+ *
+ * @note The use cases for this class overlap somewhat with those for the
+ * LLIOPipe/LLPumpIO hierarchies, and indeed we considered using those. This
+ * class has two virtues over the older machinery:
+ *
+ * # It's vastly simpler -- way fewer concepts. It's not clear to me whether
+ *   there were ever LLIOPipe/etc. use cases that demanded all the fanciness
+ *   rolled in, or whether they were simply overdesigned. In any case, no
+ *   remaining Lindens will admit to familiarity with those classes -- and
+ *   they're sufficiently obtuse that it would take considerable learning
+ *   curve to figure out how to use them properly. The bottom line is that
+ *   current management is not keen on any more engineers climbing that curve.
+ * # This class is designed around available components such as std::string,
+ *   std::list, Boost.Iostreams. There's less proprietary code.
+ */
+template <typename Ch>
+class LLGenericStreamQueue
+{
+public:
+    LLGenericStreamQueue():
+        mClosed(false)
+    {}
+
+    /**
+     * Boost.Iostreams Source Device facade for use with other Boost.Iostreams
+     * functionality. LLGenericStreamQueue doesn't quite fit any of the Boost
+     * 1.48 Iostreams concepts; instead it behaves as both a Sink and a
+     * Source. This is its Source facade.
+     */
+    struct Source
+    {
+        typedef Ch char_type;
+        typedef boost::iostreams::source_tag category;
+
+        /// Bind the underlying LLGenericStreamQueue
+        Source(LLGenericStreamQueue& sq):
+            mStreamQueue(sq)
+        {}
+
+        // Read up to n characters from the underlying data source into the
+        // buffer s, returning the number of characters read; return -1 to
+        // indicate EOF
+        std::streamsize read(Ch* s, std::streamsize n)
+        {
+            return mStreamQueue.read(s, n);
+        }
+
+        LLGenericStreamQueue& mStreamQueue;
+    };
+
+    /**
+     * Boost.Iostreams Sink Device facade for use with other Boost.Iostreams
+     * functionality. LLGenericStreamQueue doesn't quite fit any of the Boost
+     * 1.48 Iostreams concepts; instead it behaves as both a Sink and a
+     * Source. This is its Sink facade.
+     */
+    struct Sink
+    {
+        typedef Ch char_type;
+        typedef boost::iostreams::sink_tag category;
+
+        /// Bind the underlying LLGenericStreamQueue
+        Sink(LLGenericStreamQueue& sq):
+            mStreamQueue(sq)
+        {}
+
+        /// Write up to n characters from the buffer s to the output sequence,
+        /// returning the number of characters written
+        std::streamsize write(const Ch* s, std::streamsize n)
+        {
+            return mStreamQueue.write(s, n);
+        }
+
+        /// Send EOF to consumer
+        void close()
+        {
+            mStreamQueue.close();
+        }
+
+        LLGenericStreamQueue& mStreamQueue;
+    };
+
+    /// Present Boost.Iostreams Source facade
+    Source asSource() { return Source(*this); }
+    /// Present Boost.Iostreams Sink facade
+    Sink   asSink()   { return Sink(*this); }
+
+    /// append data to buffer
+    std::streamsize write(const Ch* s, std::streamsize n)
+    {
+        // Unclear how often we might be asked to write 0 bytes -- perhaps a
+        // naive caller responding to an unready nonblocking read. But if we
+        // do get such a call, don't add a completely empty BufferList entry.
+        if (n == 0)
+            return n;
+        // We could implement this using a single std::string object, a la
+        // ostringstream. But the trouble with appending to a string is that
+        // you might have to recopy all previous contents to grow its size. If
+        // we want this to scale to large data volumes, better to allocate
+        // individual pieces.
+        mBuffer.push_back(string(s, n));
+        return n;
+    }
+
+    /**
+     * Inform this LLGenericStreamQueue that no further data are forthcoming.
+     * For our purposes, close() is strictly a producer-side operation;
+     * there's little point in closing the consumer side.
+     */
+    void close()
+    {
+        mClosed = true;
+    }
+
+    /// consume data from buffer
+    std::streamsize read(Ch* s, std::streamsize n)
+    {
+        // read() is actually a convenience method for peek() followed by
+        // skip().
+        std::streamsize got(peek(s, n));
+        // We can only skip() as many characters as we can peek(); ignore
+        // skip() return here.
+        skip(n);
+        return got;
+    }
+
+    /// Retrieve data from buffer without consuming. Like read(), return -1 on
+    /// EOF.
+    std::streamsize peek(Ch* s, std::streamsize n) const;
+
+    /// Consume data from buffer without retrieving. Unlike read() and peek(),
+    /// at EOF we simply skip 0 characters.
+    std::streamsize skip(std::streamsize n);
+
+private:
+    typedef std::basic_string<Ch> string;
+    typedef std::list<string> BufferList;
+    BufferList mBuffer;
+    bool mClosed;
+};
+
+template <typename Ch>
+std::streamsize LLGenericStreamQueue<Ch>::peek(Ch* s, std::streamsize n) const
+{
+    // Here we may have to build up 'n' characters from an arbitrary
+    // number of individual BufferList entries.
+    typename BufferList::const_iterator bli(mBuffer.begin()), blend(mBuffer.end());
+    // Indicate EOF if producer has closed the pipe AND we've exhausted
+    // all previously-buffered data.
+    if (mClosed && bli == blend)
+    {
+        return -1;
+    }
+    // Here either producer hasn't yet closed, or we haven't yet exhausted
+    // remaining data.
+    std::streamsize needed(n), got(0);
+    // Loop until either we run out of BufferList entries or we've
+    // completely satisfied the request.
+    for ( ; bli != blend && needed; ++bli)
+    {
+        std::streamsize chunk(std::min(needed, std::streamsize(bli->length())));
+        std::copy(bli->begin(), bli->begin() + chunk, s);
+        needed -= chunk;
+        s      += chunk;
+        got    += chunk;
+    }
+    return got;
+}
+
+template <typename Ch>
+std::streamsize LLGenericStreamQueue<Ch>::skip(std::streamsize n)
+{
+    typename BufferList::iterator bli(mBuffer.begin()), blend(mBuffer.end());
+    std::streamsize toskip(n), skipped(0);
+    while (bli != blend && toskip >= bli->length())
+    {
+        std::streamsize chunk(bli->length());
+        typename BufferList::iterator zap(bli++);
+        mBuffer.erase(zap);
+        toskip  -= chunk;
+        skipped += chunk;
+    }
+    if (bli != blend && toskip)
+    {
+        bli->erase(bli->begin(), bli->begin() + toskip);
+        skipped += toskip;
+    }
+    return skipped;
+}
+
+typedef LLGenericStreamQueue<char>    LLStreamQueue;
+typedef LLGenericStreamQueue<wchar_t> LLWStreamQueue;
+
+#endif /* ! defined(LL_LLSTREAMQUEUE_H) */
diff --git a/indra/llcommon/tests/llstreamqueue_test.cpp b/indra/llcommon/tests/llstreamqueue_test.cpp
new file mode 100644
index 0000000000..e88c37d5be
--- /dev/null
+++ b/indra/llcommon/tests/llstreamqueue_test.cpp
@@ -0,0 +1,177 @@
+/**
+ * @file   llstreamqueue_test.cpp
+ * @author Nat Goodspeed
+ * @date   2012-01-05
+ * @brief  Test for llstreamqueue.
+ * 
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Copyright (c) 2012, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llstreamqueue.h"
+// STL headers
+#include <vector>
+// std headers
+// external library headers
+#include <boost/foreach.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+#include "stringize.h"
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct llstreamqueue_data
+    {
+        llstreamqueue_data():
+            // we want a buffer with actual bytes in it, not an empty vector
+            buffer(10)
+        {}
+        // As LLStreamQueue is merely a typedef for
+        // LLGenericStreamQueue<char>, and no logic in LLGenericStreamQueue is
+        // specific to the <char> instantiation, we're comfortable for now
+        // testing only the narrow-char version.
+        LLStreamQueue strq;
+        // buffer for use in multiple tests
+        std::vector<char> buffer;
+    };
+    typedef test_group<llstreamqueue_data> llstreamqueue_group;
+    typedef llstreamqueue_group::object object;
+    llstreamqueue_group llstreamqueuegrp("llstreamqueue");
+
+    template<> template<>
+    void object::test<1>()
+    {
+        set_test_name("empty LLStreamQueue");
+        ensure_equals("brand-new LLStreamQueue isn't empty",
+                      strq.asSource().read(&buffer[0], buffer.size()), 0);
+        strq.asSink().close();
+        ensure_equals("closed empty LLStreamQueue not at EOF",
+                      strq.asSource().read(&buffer[0], buffer.size()), -1);
+    }
+
+    template<> template<>
+    void object::test<2>()
+    {
+        set_test_name("one internal block, one buffer");
+        LLStreamQueue::Sink sink(strq.asSink());
+        ensure_equals("write(\"\")", sink.write("", 0), 0);
+        ensure_equals("0 write should leave LLStreamQueue empty",
+                      strq.peek(&buffer[0], buffer.size()), 0);
+        // The meaning of "atomic" is that it must be smaller than our buffer.
+        std::string atomic("atomic");
+        ensure("test data exceeds buffer", atomic.length() < buffer.size());
+        ensure_equals(STRINGIZE("write(\"" << atomic << "\")"),
+                      sink.write(&atomic[0], atomic.length()), atomic.length());
+        size_t peeklen(strq.peek(&buffer[0], buffer.size()));
+        ensure_equals(STRINGIZE("peek(\"" << atomic << "\")"),
+                      peeklen, atomic.length());
+        ensure_equals(STRINGIZE("peek(\"" << atomic << "\") result"),
+                      std::string(buffer.begin(), buffer.begin() + peeklen), atomic);
+        // peek() should not consume. Use a different buffer to prove it isn't
+        // just leftover data from the first peek().
+        std::vector<char> again(buffer.size());
+        peeklen = size_t(strq.peek(&again[0], again.size()));
+        ensure_equals(STRINGIZE("peek(\"" << atomic << "\") again"),
+                      peeklen, atomic.length());
+        ensure_equals(STRINGIZE("peek(\"" << atomic << "\") again result"),
+                      std::string(again.begin(), again.begin() + peeklen), atomic);
+        // now consume.
+        std::vector<char> third(buffer.size());
+        size_t readlen(strq.read(&third[0], third.size()));
+        ensure_equals(STRINGIZE("read(\"" << atomic << "\")"),
+                      readlen, atomic.length());
+        ensure_equals(STRINGIZE("read(\"" << atomic << "\") result"),
+                      std::string(third.begin(), third.begin() + readlen), atomic);
+        ensure_equals("peek() after read()", strq.peek(&buffer[0], buffer.size()), 0);
+    }
+
+    template<> template<>
+    void object::test<3>()
+    {
+        set_test_name("basic skip()");
+        std::string lovecraft("lovecraft");
+        ensure("test data exceeds buffer", lovecraft.length() < buffer.size());
+        ensure_equals(STRINGIZE("write(\"" << lovecraft << "\")"),
+                      strq.write(&lovecraft[0], lovecraft.length()), lovecraft.length());
+        size_t peeklen(strq.peek(&buffer[0], buffer.size()));
+        ensure_equals(STRINGIZE("peek(\"" << lovecraft << "\")"),
+                      peeklen, lovecraft.length());
+        ensure_equals(STRINGIZE("peek(\"" << lovecraft << "\") result"),
+                      std::string(buffer.begin(), buffer.begin() + peeklen), lovecraft);
+        std::streamsize skip1(4);
+        ensure_equals(STRINGIZE("skip(" << skip1 << ")"), strq.skip(skip1), skip1);
+        size_t readlen(strq.read(&buffer[0], buffer.size()));
+        ensure_equals(STRINGIZE("read(\"" << lovecraft.substr(skip1) << "\")"),
+                      readlen, lovecraft.length() - skip1);
+        ensure_equals(STRINGIZE("read(\"" << lovecraft.substr(skip1) << "\") result"),
+                      std::string(buffer.begin(), buffer.begin() + readlen),
+                      lovecraft.substr(skip1));
+        ensure_equals("unconsumed", strq.read(&buffer[0], buffer.size()), 0);
+    }
+
+    template<> template<>
+    void object::test<4>()
+    {
+        set_test_name("skip() multiple blocks");
+        std::string blocks[] = { "books of ", "H.P. ", "Lovecraft" };
+        std::streamsize skip(blocks[0].length() + blocks[1].length() + 4);
+        BOOST_FOREACH(const std::string& block, blocks)
+        {
+            strq.write(&block[0], block.length());
+        }
+        std::streamsize skiplen(strq.skip(skip));
+        ensure_equals(STRINGIZE("skip(" << skip << ")"), skiplen, skip);
+        size_t readlen(strq.read(&buffer[0], buffer.size()));
+        ensure_equals("read(\"craft\")", readlen, 5);
+        ensure_equals("read(\"craft\") result",
+                      std::string(buffer.begin(), buffer.begin() + readlen), "craft");
+    }
+
+    template<> template<>
+    void object::test<5>()
+    {
+        set_test_name("concatenate blocks");
+        std::string blocks[] = { "abcd", "efghij", "klmnopqrs" };
+        BOOST_FOREACH(const std::string& block, blocks)
+        {
+            strq.write(&block[0], block.length());
+        }
+        std::vector<char> longbuffer(30);
+        std::streamsize readlen(strq.read(&longbuffer[0], longbuffer.size()));
+        ensure_equals("read() multiple blocks",
+                      readlen, blocks[0].length() + blocks[1].length() + blocks[2].length());
+        ensure_equals("read() multiple blocks result",
+                      std::string(longbuffer.begin(), longbuffer.begin() + readlen),
+                      blocks[0] + blocks[1] + blocks[2]);
+    }
+
+    template<> template<>
+    void object::test<6>()
+    {
+        set_test_name("split blocks");
+        std::string blocks[] = { "abcdefghijklm", "nopqrstuvwxyz" };
+        BOOST_FOREACH(const std::string& block, blocks)
+        {
+            strq.write(&block[0], block.length());
+        }
+        strq.close();
+        std::streamsize readlen(strq.read(&buffer[0], buffer.size()));
+        ensure_equals("read() 0", readlen, buffer.size());
+        ensure_equals("read() 0 result", std::string(buffer.begin(), buffer.end()), "abcdefghij");
+        readlen = strq.read(&buffer[0], buffer.size());
+        ensure_equals("read() 1", readlen, buffer.size());
+        ensure_equals("read() 1 result", std::string(buffer.begin(), buffer.end()), "klmnopqrst");
+        readlen = strq.read(&buffer[0], buffer.size());
+        ensure_equals("read() 2", readlen, 6);
+        ensure_equals("read() 2 result",
+                      std::string(buffer.begin(), buffer.begin() + readlen), "uvwxyz");
+        ensure_equals("read() 3", strq.read(&buffer[0], buffer.size()), -1);
+    }
+} // namespace tut
-- 
cgit v1.2.3


From b0db21a8ae93283acc99491b9b14c2e8f1a35395 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 5 Jan 2012 15:40:27 -0800
Subject: EXP-1754 FIX -- Search text shown in Outbox floater after marketplace
 synch if all items removed.

* Added a setting to determine whether or not to display the standard empty inventory message.
  The message is on by default but turned off for the merchant outbox inventory panel.
---
 indra/newview/llfolderview.cpp                     |  5 ++--
 indra/newview/llfolderview.h                       |  2 ++
 indra/newview/llinventorypanel.cpp                 |  2 ++
 indra/newview/llinventorypanel.h                   |  3 +++
 .../newview/llpanelmarketplaceoutboxinventory.cpp  | 31 ----------------------
 .../xui/en/widgets/outbox_inventory_panel.xml      |  2 +-
 6 files changed, 11 insertions(+), 34 deletions(-)

diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 0af20f5de5..6cc136f58b 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -172,6 +172,7 @@ LLFolderView::Params::Params()
 	title("title"),
 	use_label_suffix("use_label_suffix"),
 	allow_multiselect("allow_multiselect", true),
+	show_empty_message("show_empty_message", true),
 	show_load_status("show_load_status", true),
 	use_ellipses("use_ellipses", false)
 {
@@ -185,6 +186,7 @@ LLFolderView::LLFolderView(const Params& p)
 	mScrollContainer( NULL ),
 	mPopupMenuHandle(),
 	mAllowMultiSelect(p.allow_multiselect),
+	mShowEmptyMessage(p.show_empty_message),
 	mShowFolderHierarchy(FALSE),
 	mSourceID(p.task_id),
 	mRenameItem( NULL ),
@@ -932,7 +934,7 @@ void LLFolderView::draw()
 		mStatusText.clear();
 		mStatusTextBox->setVisible( FALSE );
 	}
-	else
+	else if (mShowEmptyMessage)
 	{
 		if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
 		{
@@ -966,7 +968,6 @@ void LLFolderView::draw()
 			// See EXT-7564, EXT-7047.
 			arrangeFromRoot();
 		}
-		
 	}
 
 	// skip over LLFolderViewFolder::draw since we don't want the folder icon, label, 
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 8af01e9102..2da70f019c 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -75,6 +75,7 @@ public:
 		Optional<std::string>   title;
 		Optional<bool>			use_label_suffix,
 								allow_multiselect,
+								show_empty_message,
 								show_load_status,
 								use_ellipses;
 
@@ -282,6 +283,7 @@ protected:
 	selected_items_t				mSelectedItems;
 	BOOL							mKeyboardSelection;
 	BOOL							mAllowMultiSelect;
+	BOOL							mShowEmptyMessage;
 	BOOL							mShowFolderHierarchy;
 	LLUUID							mSourceID;
 
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index af1d2b8528..382569fa3a 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -132,6 +132,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
 	mAcceptsDragAndDrop(p.accepts_drag_and_drop),
 	mAllowMultiSelect(p.allow_multi_select),
 	mShowItemLinkOverlays(p.show_item_link_overlays),
+	mShowEmptyMessage(p.show_empty_message),
 	mShowLoadStatus(p.show_load_status),
 	mViewsInitialized(false),
 	mInvFVBridgeBuilder(NULL)
@@ -617,6 +618,7 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u
 	p.listener =  bridge;
 	p.use_label_suffix = useLabelSuffix;
 	p.allow_multiselect = mAllowMultiSelect;
+	p.show_empty_message = mShowEmptyMessage;
 	p.show_load_status = mShowLoadStatus;
 
 	return LLUICtrlFactory::create<LLFolderView>(p);
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 2a24327115..8279163762 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -84,6 +84,7 @@ public:
 		Optional<Filter>					filter;
 		Optional<std::string>               start_folder;
 		Optional<bool>						use_label_suffix;
+		Optional<bool>						show_empty_message;
 		Optional<bool>						show_load_status;
 		Optional<LLScrollContainer::Params>	scroll;
 		Optional<bool>						accepts_drag_and_drop;
@@ -96,6 +97,7 @@ public:
 			filter("filter"),
 			start_folder("start_folder"),
 			use_label_suffix("use_label_suffix", true),
+			show_empty_message("show_empty_message", true),
 			show_load_status("show_load_status"),
 			scroll("scroll"),
 			accepts_drag_and_drop("accepts_drag_and_drop")
@@ -188,6 +190,7 @@ protected:
 	BOOL						mAcceptsDragAndDrop;
 	BOOL 						mAllowMultiSelect;
 	BOOL 						mShowItemLinkOverlays; // Shows link graphic over inventory item icons
+	BOOL						mShowEmptyMessage;
 	BOOL						mShowLoadStatus;
 
 	LLFolderView*				mFolderRoot;
diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp
index 1dd68b7758..c14a0c8379 100644
--- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp
+++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp
@@ -67,37 +67,6 @@ void LLOutboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par
 	
 	LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false);
 	
-	// leslie -- temporary HACK to work around sim not creating outbox with proper system folder type
-	if (root_id.isNull())
-	{
-		std::string start_folder_name(params.start_folder());
-		
-		LLInventoryModel::cat_array_t* cats;
-		LLInventoryModel::item_array_t* items;
-		
-		gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
-		
-		if (cats)
-		{
-			for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
-			{
-				LLInventoryCategory* cat = *cat_it;
-				
-				if (cat->getName() == start_folder_name)
-				{
-					root_id = cat->getUUID();
-					break;
-				}
-			}
-		}
-		
-		if (root_id == LLUUID::null)
-		{
-			llwarns << "No category found that matches outbox inventory panel start_folder: " << start_folder_name << llendl;
-		}
-	}
-	// leslie -- end temporary HACK
-	
 	if (root_id == LLUUID::null)
 	{
 		llwarns << "Outbox inventory panel has no root folder!" << llendl;
diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml
index e3f2072819..3964569da2 100644
--- a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml
+++ b/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<outbox_inventory_panel show_load_status="false" />
+<outbox_inventory_panel show_empty_message="false" show_load_status="false" />
-- 
cgit v1.2.3


From af32a74b77ffc2110de821e0159de8eb5aa0f454 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 5 Jan 2012 16:30:15 -0800
Subject: EXP-1757 FIX -- Merchant Outbox shows as empty when first
 opening/initializing even when populated

* Updated merchant outbox floater to not wait for initialization to complete before displaying outbox inventory contents.
---
 indra/newview/CMakeLists.txt               |   2 -
 indra/newview/llfloateroutbox.cpp          |  13 +-
 indra/newview/llfloateroutbox.h            |   1 +
 indra/newview/llpanelmarketplaceoutbox.cpp | 276 -----------------------------
 indra/newview/llpanelmarketplaceoutbox.h   |  91 ----------
 5 files changed, 10 insertions(+), 373 deletions(-)
 delete mode 100644 indra/newview/llpanelmarketplaceoutbox.cpp
 delete mode 100644 indra/newview/llpanelmarketplaceoutbox.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 0a4874ae92..78cd33210f 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -372,7 +372,6 @@ set(viewer_SOURCE_FILES
     llpanelmaininventory.cpp
     llpanelmarketplaceinbox.cpp
     llpanelmarketplaceinboxinventory.cpp
-    llpanelmarketplaceoutbox.cpp
     llpanelmarketplaceoutboxinventory.cpp
     llpanelmediasettingsgeneral.cpp
     llpanelmediasettingspermissions.cpp
@@ -922,7 +921,6 @@ set(viewer_HEADER_FILES
     llpanelmaininventory.h
     llpanelmarketplaceinbox.h
     llpanelmarketplaceinboxinventory.h
-    llpanelmarketplaceoutbox.h
     llpanelmarketplaceoutboxinventory.h
     llpanelmediasettingsgeneral.h
     llpanelmediasettingspermissions.h
diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 8ccebb36dc..6ecf715588 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -280,6 +280,14 @@ void LLFloaterOutbox::updateFolderCount()
 	
 	mOutboxItemCount = item_count;
 
+	if (!mImportBusy)
+	{
+		updateFolderCountStatus();
+	}
+}
+
+void LLFloaterOutbox::updateFolderCountStatus()
+{
 	if (mOutboxInventoryPanel)
 	{
 		switch (mOutboxItemCount)
@@ -304,10 +312,7 @@ void LLFloaterOutbox::updateFolderCount()
 
 void LLFloaterOutbox::updateView()
 {
-	if (!mImportBusy)
-	{
-		updateFolderCount();
-	}
+	updateFolderCount();
 
 	if (mOutboxItemCount > 0)
 	{
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index cc4a7207ca..6b4021807c 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -83,6 +83,7 @@ protected:
 	void setStatusString(const std::string& statusString);
 	
 	void updateFolderCount();
+	void updateFolderCountStatus();
 	void updateView();
 
 private:
diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
deleted file mode 100644
index 6c2363eb7f..0000000000
--- a/indra/newview/llpanelmarketplaceoutbox.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/** 
- * @file llpanelmarketplaceoutbox.cpp
- * @brief Panel for marketplace outbox
- *
-* $LicenseInfo:firstyear=2011&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 "llpanelmarketplaceoutbox.h"
-#include "llpanelmarketplaceoutboxinventory.h"
-
-#include "llappviewer.h"
-#include "llbutton.h"
-#include "llcoros.h"
-#include "lleventcoro.h"
-#include "llfloatersidepanelcontainer.h"
-#include "llinventorypanel.h"
-#include "llloadingindicator.h"
-#include "llmarketplacefunctions.h"
-#include "llnotificationsutil.h"
-#include "llpanelmarketplaceinbox.h"
-#include "llsdutil.h"
-#include "llsidepanelinventory.h"
-#include "lltimer.h"
-#include "llviewernetwork.h"
-#include "llagent.h"
-#include "llviewermedia.h"
-#include "llfolderview.h"
-#include "llinventoryfunctions.h"
-
-
-// Turn this on to get a bunch of console output for marketplace API calls, headers and status
-#define DEBUG_MARKETPLACE_HTTP_API	0
-
-
-static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox");
-
-const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultParams() 
-{ 
-	return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceOutbox>(); 
-}
-
-// protected
-LLPanelMarketplaceOutbox::LLPanelMarketplaceOutbox(const Params& p)
-	: LLPanel(p)
-	, mInventoryPanel(NULL)
-	, mImportButton(NULL)
-	, mImportIndicator(NULL)
-	, mOutboxButton(NULL)
-{
-}
-
-LLPanelMarketplaceOutbox::~LLPanelMarketplaceOutbox()
-{
-}
-
-// virtual
-BOOL LLPanelMarketplaceOutbox::postBuild()
-{
-	LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceOutbox::handleLoginComplete, this));
-	
-	LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceOutbox::onFocusReceived, this));
-
-	return TRUE;
-}
-
-// DO WE NEED THIS FILE AT ALL?
-
-void LLPanelMarketplaceOutbox::handleLoginComplete()
-{
-	mImportButton = getChild<LLButton>("outbox_import_btn");
-	mImportButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onImportButtonClicked, this));
-	mImportButton->setEnabled(!isOutboxEmpty());
-	
-	mImportIndicator = getChild<LLLoadingIndicator>("outbox_import_indicator");
-	
-	mOutboxButton = getChild<LLButton>("outbox_btn");
-}
-
-void LLPanelMarketplaceOutbox::onFocusReceived()
-{
-	LLSidepanelInventory * sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
-	if (sidepanel_inventory)
-	{
-		sidepanel_inventory->clearSelections(true, true);
-	}
-}
-
-void LLPanelMarketplaceOutbox::onSelectionChange()
-{
-	LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
-	if (sidepanel_inventory)
-	{
-		sidepanel_inventory->updateVerbs();
-	}
-}
-
-LLInventoryPanel * LLPanelMarketplaceOutbox::setupInventoryPanel()
-{
-	LLView * outbox_inventory_placeholder = getChild<LLView>("outbox_inventory_placeholder_panel");
-	LLView * outbox_inventory_parent = outbox_inventory_placeholder->getParent();
-	
-	mInventoryPanel = 
-		LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml",
-														  outbox_inventory_parent,
-														  LLInventoryPanel::child_registry_t::instance());
-	
-	llassert(mInventoryPanel);
-	
-	// Reshape the inventory to the proper size
-	LLRect inventory_placeholder_rect = outbox_inventory_placeholder->getRect();
-	mInventoryPanel->setShape(inventory_placeholder_rect);
-	
-	// Set the sort order newest to oldest
-	mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);	
-	mInventoryPanel->getFilter()->markDefault();
-
-	// Set selection callback for proper update of inventory status buttons
-	mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceOutbox::onSelectionChange, this));
-	
-	// Set up the note to display when the outbox is empty
-	mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryOutboxNoItems");
-	
-	// Hide the placeholder text
-	outbox_inventory_placeholder->setVisible(FALSE);
-	
-	// Set up marketplace importer
-	LLMarketplaceInventoryImporter::getInstance()->initialize();
-	LLMarketplaceInventoryImporter::getInstance()->setStatusChangedCallback(boost::bind(&LLPanelMarketplaceOutbox::importStatusChanged, this, _1));
-	LLMarketplaceInventoryImporter::getInstance()->setStatusReportCallback(boost::bind(&LLPanelMarketplaceOutbox::importReportResults, this, _1, _2));
-	
-	updateImportButtonStatus();
-	
-	return mInventoryPanel;
-}
-
-void LLPanelMarketplaceOutbox::importReportResults(U32 status, const LLSD& content)
-{
-	if (status == MarketplaceErrorCodes::IMPORT_DONE)
-	{
-		LLNotificationsUtil::add("OutboxImportComplete", LLSD::emptyMap(), LLSD::emptyMap());
-	}
-	else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
-	{
-		LLNotificationsUtil::add("OutboxImportHadErrors", LLSD::emptyMap(), LLSD::emptyMap());
-	}
-	else
-	{
-		char status_string[16];
-		sprintf(status_string, "%d", status);
-		
-		LLSD subs;
-		subs["ERROR_CODE"] = status_string;
-		
-		//llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
-		LLNotificationsUtil::add("OutboxImportFailed", LLSD::emptyMap(), LLSD::emptyMap());
-	}
-}
-
-void LLPanelMarketplaceOutbox::importStatusChanged(bool inProgress)
-{
-	updateImportButtonStatus();
-}
-
-BOOL LLPanelMarketplaceOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
-								   EDragAndDropType cargo_type,
-								   void* cargo_data,
-								   EAcceptance* accept,
-								   std::string& tooltip_msg)
-{
-	BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
-
-	if (!handled && mInventoryPanel && mInventoryPanel->getRootFolder())
-	{
-		handled = mInventoryPanel->getRootFolder()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
-
-		if (handled)
-		{
-			mInventoryPanel->getRootFolder()->setDragAndDropThisFrame();
-		}
-	}
-
-	return handled;
-}
-
-bool LLPanelMarketplaceOutbox::isOutboxEmpty() const
-{
-	return (getTotalItemCount() == 0);
-}
-
-void LLPanelMarketplaceOutbox::updateImportButtonStatus()
-{
-	if (LLMarketplaceInventoryImporter::instance().isImportInProgress())
-	{
-		mImportButton->setVisible(false);
-
-		mImportIndicator->setVisible(true);
-		mImportIndicator->reset();
-		mImportIndicator->start();
-	}
-	else
-	{
-		mImportIndicator->stop();
-		mImportIndicator->setVisible(false);
-
-		mImportButton->setVisible(true);
-		mImportButton->setEnabled(!isOutboxEmpty());
-	}
-}
-
-U32 LLPanelMarketplaceOutbox::getTotalItemCount() const
-{
-	U32 item_count = 0;
-
-	if (mInventoryPanel)
-	{
-		const LLFolderViewFolder * outbox_folder = mInventoryPanel->getRootFolder();
-
-		if (outbox_folder)
-		{
-			item_count += outbox_folder->getFoldersCount();
-			item_count += outbox_folder->getItemsCount();
-		}
-	}
-
-	return item_count;
-}
-
-void LLPanelMarketplaceOutbox::onImportButtonClicked()
-{
-	LLMarketplaceInventoryImporter::instance().triggerImport();
-	
-	// Get the import animation going
-	updateImportButtonStatus();
-}
-
-void LLPanelMarketplaceOutbox::draw()
-{
-	const U32 item_count = getTotalItemCount();
-	const bool not_empty = (item_count > 0);
-
-	if (not_empty)
-	{
-		std::string item_count_str = llformat("%d", item_count);
-
-		LLStringUtil::format_map_t args;
-		args["[NUM]"] = item_count_str;
-		mOutboxButton->setLabel(getString("OutboxLabelWithArg", args));
-	}
-	else
-	{
-		mOutboxButton->setLabel(getString("OutboxLabelNoArg"));
-	}
-	
-	LLPanel::draw();
-}
diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h
deleted file mode 100644
index 6f038118b3..0000000000
--- a/indra/newview/llpanelmarketplaceoutbox.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/** 
- * @file llpanelmarketplaceoutbox.h
- * @brief Panel for marketplace outbox
- *
-* $LicenseInfo:firstyear=2011&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 LL_LLPANELMARKETPLACEOUTBOX_H
-#define LL_LLPANELMARKETPLACEOUTBOX_H
-
-#include "llpanel.h"
-
-
-class LLButton;
-class LLInventoryPanel;
-class LLLoadingIndicator;
-
-
-class LLPanelMarketplaceOutbox : public LLPanel
-{
-public:
-	
-	struct Params :	public LLInitParam::Block<Params, LLPanel::Params>
-	{};
-	
-	LOG_CLASS(LLPanelMarketplaceOutbox);
-
-	// RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8
-	static const LLPanelMarketplaceOutbox::Params& getDefaultParams();
-	
-	LLPanelMarketplaceOutbox(const Params& p = getDefaultParams());
-	~LLPanelMarketplaceOutbox();
-
-	/*virtual*/ BOOL postBuild();
-
-	/*virtual*/ void draw();
-
-	LLInventoryPanel * setupInventoryPanel();
-
-	U32 getTotalItemCount() const;
-
-	bool isOutboxEmpty() const;
-
-	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
-								   EDragAndDropType cargo_type,
-								   void* cargo_data,
-								   EAcceptance* accept,
-								   std::string& tooltip_msg);
-
-protected:
-	void onImportButtonClicked();
-	void updateImportButtonStatus();
-
-	void handleLoginComplete();
-	void onFocusReceived();
-	void onSelectionChange();
-	
-	void importReportResults(U32 status, const LLSD& content);
-	void importStatusChanged(bool inProgress);
-	
-private:
-	LLInventoryPanel *		mInventoryPanel;
-
-	LLButton *				mImportButton;
-	LLLoadingIndicator *	mImportIndicator;
-	
-	LLButton *				mOutboxButton;
-};
-
-
-#endif //LL_LLPANELMARKETPLACEOUTBOX_H
-
-- 
cgit v1.2.3


From 141089327649f9b89be4ac9cc2b50f56eee62a48 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 5 Jan 2012 21:26:06 -0700
Subject: fix for SH-2829: [crashhunters] Crash in
 LLWearable::importFile()/LLOverrideBakedTextureUpdate::LLOverrideBakedTextureUpdate()

---
 indra/newview/llagentwearablesfetch.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
index 1edc96e165..4097ff707c 100644
--- a/indra/newview/llagentwearablesfetch.cpp
+++ b/indra/newview/llagentwearablesfetch.cpp
@@ -111,6 +111,12 @@ void LLInitialWearablesFetch::add(InitialWearableData &data)
 
 void LLInitialWearablesFetch::processContents()
 {
+	if(!gAgentAvatarp) //no need to process wearables if the agent avatar is deleted.
+	{
+		delete this;
+		return ;
+	}
+
 	// Fetch the wearable items from the Current Outfit Folder
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t wearable_array;
-- 
cgit v1.2.3


From 837e38d8195b2928648c9c383bea1b3f1cf68fa5 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 5 Jan 2012 21:26:35 -0700
Subject: trivial: debug code for SH-2827: [crashhunters] Crash in
 LLPipeline::generateWaterReflection()

---
 indra/llrender/llrender.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index cd827f5091..03a9884c2b 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1434,6 +1434,8 @@ void LLRender::loadIdentity()
 	flush();
 
 	{
+		llassert_always(mMatrixMode < NUM_MATRIX_MODES) ;
+
 		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();
 		mMatHash[mMatrixMode]++;
 	}
-- 
cgit v1.2.3


From bd3a652eabf09a5843a6a0b8a9f60c4b402ecce5 Mon Sep 17 00:00:00 2001
From: Aura Linden <aura@lindenlab.com>
Date: Fri, 6 Jan 2012 07:46:53 -0500
Subject: Add capability-based create folder routine for more reliable
 inventory, with fix for copy and wear

---
 indra/newview/llfloateropenobject.cpp | 60 ++++++++++++++++++++----
 indra/newview/llfloateropenobject.h   | 11 +++++
 indra/newview/llinventorybridge.cpp   | 13 +++---
 indra/newview/llinventorymodel.cpp    | 87 +++++++++++++++++++++++++++++++++--
 indra/newview/llinventorymodel.h      |  4 +-
 indra/newview/llviewerregion.cpp      |  1 +
 6 files changed, 155 insertions(+), 21 deletions(-)

diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index 8b6619def2..4bfef8b45f 100644
--- a/indra/newview/llfloateropenobject.cpp
+++ b/indra/newview/llfloateropenobject.cpp
@@ -162,26 +162,66 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
 	{
 		parent_category_id = gInventory.getRootFolderID();
 	}
+	
+	LLCategoryCreate* cat_data = new LLCategoryCreate(object_id, wear);
+	
 	LLUUID category_id = gInventory.createNewCategory(parent_category_id, 
-		LLFolderType::FT_NONE, 
-		name);
+													  LLFolderType::FT_NONE, 
+													  name,
+													  callbackCreateInventoryCategory,
+													  (void*)cat_data);
+
+	//If we get a null category ID, we are using a capability in createNewCategory and we will
+	//handle the following in the callbackCreateInventoryCategory routine.
+	if ( category_id.notNull() )
+	{
+		delete cat_data;
+		
+		LLCatAndWear* data = new LLCatAndWear;
+		data->mCatID = category_id;
+		data->mWear = wear;
+		data->mFolderResponded = false;
+
+		// Copy and/or move the items into the newly created folder.
+		// Ignore any "you're going to break this item" messages.
+		BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE,
+														callbackMoveInventory, 
+														(void*)data);
+		if (!success)
+		{
+			delete data;
+			data = NULL;
 
-	LLCatAndWear* data = new LLCatAndWear;
-	data->mCatID = category_id;
-	data->mWear = wear;
+			LLNotificationsUtil::add("OpenObjectCannotCopy");
+		}
+	}
+}
 
+// static
+void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, void* data)
+{
+	LLCategoryCreate* cat_data = (LLCategoryCreate*)data;
+	
+	LLUUID category_id = result["folder_id"].asUUID();
+	LLCatAndWear* wear_data = new LLCatAndWear;
+
+	wear_data->mCatID = category_id;
+	wear_data->mWear = cat_data->mWear;
+	wear_data->mFolderResponded = true;
+	
 	// Copy and/or move the items into the newly created folder.
 	// Ignore any "you're going to break this item" messages.
-	BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE,
+	BOOL success = move_inv_category_world_to_agent(cat_data->mObjectID, category_id, TRUE,
 													callbackMoveInventory, 
-													(void*)data);
+													(void*)wear_data);
 	if (!success)
 	{
-		delete data;
-		data = NULL;
-
+		delete wear_data;
+		wear_data = NULL;
+		
 		LLNotificationsUtil::add("OpenObjectCannotCopy");
 	}
+	delete cat_data;	
 }
 
 // static
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index 0706e99f16..bf7fe69c65 100644
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -45,10 +45,20 @@ public:
 	
 	void dirty();
 	
+	class LLCategoryCreate
+	{
+		public:
+			LLCategoryCreate(LLUUID object_id, bool wear) : mObjectID(object_id), mWear(wear) {}
+		public:
+			LLUUID mObjectID;
+			bool mWear;
+	};
+	
 	struct LLCatAndWear
 	{
 		LLUUID mCatID;
 		bool mWear;
+		bool mFolderResponded;
 	};
 
 protected:
@@ -62,6 +72,7 @@ protected:
 
 	void onClickMoveToInventory();
 	void onClickMoveAndWear();
+	static void callbackCreateInventoryCategory(const LLSD& result, void* data);
 	static void callbackMoveInventory(S32 result, void* data);
 
 private:
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 0c092e9a56..eaf9b53eb9 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2305,15 +2305,15 @@ void LLRightClickInventoryFetchDescendentsObserver::done()
 class LLInventoryCopyAndWearObserver : public LLInventoryObserver
 {
 public:
-	LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :
-		mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {}
+	LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count, bool folder_added=false) :
+		mCatID(cat_id), mContentsCount(count), mFolderAdded(folder_added) {}
 	virtual ~LLInventoryCopyAndWearObserver() {}
 	virtual void changed(U32 mask);
 
 protected:
 	LLUUID mCatID;
 	int    mContentsCount;
-	BOOL   mFolderAdded;
+	bool   mFolderAdded;
 };
 
 
@@ -2341,7 +2341,6 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
 		if (mFolderAdded)
 		{
 			LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
-
 			if (NULL == category)
 			{
 				llwarns << "gInventory.getCategory(" << mCatID
@@ -3188,13 +3187,13 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
 
 	if(option == 0 && object)
 	{
-		if (cat_and_wear && cat_and_wear->mWear)
+		if (cat_and_wear && cat_and_wear->mWear) // && !cat_and_wear->mFolderResponded)
 		{
 			LLInventoryObject::object_list_t inventory_objects;
 			object->getInventoryContents(inventory_objects);
 			int contents_count = inventory_objects.size()-1; //subtract one for containing folder
-
-			LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count);
+			LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count, cat_and_wear->mFolderResponded);
+			
 			gInventory.addObserver(inventoryObserver);
 		}
 
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index dc25689fa3..568ec4c5e2 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -377,14 +377,67 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe
 	return rv;
 }
 
+class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
+{
+public:
+	LLCreateInventoryCategoryResponder(LLInventoryModel* model, 
+									   void (*callback)(const LLSD&, void*),
+									   void* user_data) :
+										mModel(model),
+										mCallback(callback), 
+										mData(user_data) 
+	{
+	}
+	
+	virtual void error(U32 status, const std::string& reason)
+	{
+		LL_WARNS("InvAPI") << "CreateInventoryCategory failed.   status = " << status << ", reasion = \"" << reason << "\"" << LL_ENDL;
+	}
+	
+	virtual void result(const LLSD& content)
+	{
+		//Server has created folder.
+		
+		LLUUID category_id = content["folder_id"].asUUID();
+		
+		
+		// Add the category to the internal representation
+		LLPointer<LLViewerInventoryCategory> cat =
+		new LLViewerInventoryCategory( category_id, 
+									  content["parent_id"].asUUID(),
+									  (LLFolderType::EType)content["type"].asInteger(),
+									  content["name"].asString(), 
+									  gAgent.getID() );
+		cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL);
+		cat->setDescendentCount(0);
+		LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
+		mModel->accountForUpdate(update);
+		mModel->updateCategory(cat);
+		
+		if (mCallback && mData)
+		{
+			mCallback(content, mData);
+		}
+		
+	}
+	
+private:
+	void (*mCallback)(const LLSD&, void*);
+	void* mData;
+	LLInventoryModel* mModel;
+};
+
 // Convenience function to create a new category. You could call
 // updateCategory() with a newly generated UUID category, but this
 // version will take care of details like what the name should be
 // based on preferred type. Returns the UUID of the new category.
 LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 										   LLFolderType::EType preferred_type,
-										   const std::string& pname)
+										   const std::string& pname,
+										   void (*callback)(const LLSD&, void*),	//Default to NULL
+										   void* user_data)							//Default to NULL
 {
+	
 	LLUUID id;
 	if(!isInventoryUsable())
 	{
@@ -408,6 +461,35 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 	{
 		name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
 	}
+	
+	if ( callback && user_data )  //callback required for acked message.
+	{
+		LLViewerRegion* viewer_region = gAgent.getRegion();
+		std::string url;
+		if ( viewer_region )
+			url = viewer_region->getCapability("CreateInventoryCategory");
+		
+		if (!url.empty())
+		{
+			//Let's use the new capability.
+			
+			LLSD request, body;
+			body["folder_id"] = id;
+			body["parent_id"] = parent_id;
+			body["type"] = (LLSD::Integer) preferred_type;
+			body["name"] = name;
+			
+			request["message"] = "CreateInventoryCategory";
+			request["payload"] = body;
+			
+	//		viewer_region->getCapAPI().post(request);
+			LLHTTPClient::post(
+							   url,
+							   body,
+							   new LLCreateInventoryCategoryResponder(this, callback, user_data) );
+			return LLUUID::null;
+		}
+	}
 
 	// Add the category to the internal representation
 	LLPointer<LLViewerInventoryCategory> cat =
@@ -1087,7 +1169,6 @@ void LLInventoryModel::notifyObservers()
 		 iter != mObservers.end(); )
 	{
 		LLInventoryObserver* observer = *iter;
-		
 		observer->changed(mModifyMask);
 
 		// safe way to increment since changed may delete entries! (@!##%@!@&*!)
@@ -2574,7 +2655,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 				<< titem->getParentUUID() << llendl;
 		U32 callback_id;
 		msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);
-		if(titem->getUUID().notNull())
+		if(titem->getUUID().notNull() ) // && callback_id.notNull() )
 		{
 			items.push_back(titem);
 			cblist.push_back(InventoryCallbackInfo(callback_id, titem->getUUID()));
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 340c1b0c22..0a564d353a 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -360,7 +360,9 @@ public:
 	// name based on type, pass in a NULL to the 'name' parameter.
 	LLUUID createNewCategory(const LLUUID& parent_id,
 							 LLFolderType::EType preferred_type,
-							 const std::string& name);
+							 const std::string& name,
+							 void (*callback)(const LLSD&, void*) = NULL,
+							 void* user_data = NULL );
 protected:
 	// Internal methods that add inventory and make sure that all of
 	// the internal data structures are consistent. These methods
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index ed943964f9..e3cb985ddb 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1493,6 +1493,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("AvatarPickerSearch");
 	capabilityNames.append("ChatSessionRequest");
 	capabilityNames.append("CopyInventoryFromNotecard");
+	capabilityNames.append("CreateInventoryCategory");
 	capabilityNames.append("DispatchRegionInfo");
 	capabilityNames.append("EstateChangeInfo");
 	capabilityNames.append("EventQueueGet");
-- 
cgit v1.2.3


From 377e35af14ec8e6aa689a9aa9817705b4d699e83 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 6 Jan 2012 09:19:10 -0800
Subject: looking for better fix to EXP-1695 [I18N] [INCORRECT CURRENCY
 LAYOUT/FORMAT] - Currency in  Group Profile > Land/Asset and New Group
 (French viewer) Backed out changeset: c01a6186b15c

---
 indra/newview/llpanelgrouplandmoney.cpp                    |  3 ++-
 indra/newview/skins/default/xui/en/panel_group_general.xml | 13 ++-----------
 indra/newview/skins/default/xui/en/strings.xml             |  2 +-
 3 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index b6c0c2ee24..e66dd5690c 100644
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -1447,7 +1447,8 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg,
 
 		text.append(time_str);
 		text.append(".\n\n");
-		text.append(llformat("%-24s %6d L$\n\n", LLTrans::getString("GroupMoneyBalance").c_str(), balance ));
+		text.append(llformat("%-23sL$%6d\n", LLTrans::getString("GroupMoneyBalance").c_str(), balance ));
+		text.append(1, '\n');
 	}
 
 	// [DEV-29503] Hide the individual info since
diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml
index adde982c60..38b680ba86 100644
--- a/indra/newview/skins/default/xui/en/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_general.xml
@@ -225,22 +225,13 @@ Hover your mouse over the options for more help.
          height="23"
          increment="1"
          label_width="15"
+         label="L$"
          layout="topleft"
          max_val="99999"
          left="30"
          name="spin_enrollment_fee"
          tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked."
-         width="150" />
-        <text
-         follows="left|top"
-         type="string"
-         height="16"
-         left_pad="2"
-         name="currency_label"
-         top_delta="5"
-         width="18">
-         L$
-        </text>
+         width="170" />
         <combo_box
          follows="left|top"
          height="23"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 2ae56bc729..492e51e0fd 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2272,7 +2272,7 @@ Returns a string with the requested data about the region
 	<string name="NextStipendDay"       value="The next stipend day is " />
 	<string name="GroupPlanningDate">[mthnum,datetime,utc]/[day,datetime,utc]/[year,datetime,utc]</string>
 	<string name="GroupIndividualShare" value="                      Group       Individual Share" />
-	<string name="GroupColumn"          value="Group" />
+	<string name="GroupColumn"          value="                      Group" />
 	<string name="Balance">Balance</string>
 	<string name="Credits">Credits</string>
 	<string name="Debits">Debits</string>
-- 
cgit v1.2.3


From 757a955bd700eb4f838762dcbe789a77ee052064 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 6 Jan 2012 12:07:52 -0800
Subject: Looking for better fix to EXP-1693 - date localization

Backed out changeset: 4f3024e9d629
---
 indra/llcommon/llstring.cpp                        |  5 -----
 indra/llui/llscrolllistcell.cpp                    | 10 +---------
 indra/newview/llappviewer.cpp                      | 23 ++++++++++++++--------
 indra/newview/skins/default/xui/en/strings.xml     |  3 ---
 .../skins/default/xui/fr/sidepanel_item_info.xml   |  2 +-
 5 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 1193a4ef8d..e7fe656808 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -1122,11 +1122,6 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
 		struct tm * gmt = gmtime (&loc_seconds);
 		replacement = LLStringOps::sMonthList[gmt->tm_mon];
 	}
-	else if(LLStringOps::sMonthShortList.size() == 12 && code == "%b")
-	{
-		struct tm * gmt = gmtime (&loc_seconds);
-		replacement = LLStringOps::sMonthShortList[gmt->tm_mon];
-	}
 	else if( !LLStringOps::sDayFormat.empty() && code == "%d" )
 	{
 		struct tm * gmt = gmtime (&loc_seconds);
diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
index 786e18b187..9d25c7180d 100644
--- a/indra/llui/llscrolllistcell.cpp
+++ b/indra/llui/llscrolllistcell.cpp
@@ -29,8 +29,6 @@
 
 #include "llscrolllistcell.h"
 
-#include "lltrans.h"
-
 #include "llcheckboxctrl.h"
 #include "llui.h"	// LLUIImage
 #include "lluictrlfactory.h"
@@ -430,13 +428,7 @@ LLScrollListDate::LLScrollListDate( const LLScrollListCell::Params& p)
 void LLScrollListDate::setValue(const LLSD& value)
 {
 	mDate = value.asDate();
-
-	std::string date_str = LLTrans::getString("ScrollListCellDateFormat");
-	LLSD substitution;
-	substitution["datetime"] = mDate.secondsSinceEpoch();
-	LLStringUtil::format(date_str, substitution);
-
-	LLScrollListText::setValue(date_str);
+	LLScrollListText::setValue(mDate.asRFC1123());
 }
 
 const LLSD LLScrollListDate::getValue() const
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 33d4563feb..0861fe85a8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1044,14 +1044,21 @@ bool LLAppViewer::init()
 
 	LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
 
-	LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
-	LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
-	LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
-	LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
-	LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
-
-	LLStringOps::sAM = LLTrans::getString("dateTimeAM");
-	LLStringOps::sPM = LLTrans::getString("dateTimePM");
+	//EXT-7013 - On windows for some locale (Japanese) standard 
+	//datetime formatting functions didn't support some parameters such as "weekday".
+	//Names for days and months localized in xml are also useful for Polish locale(STORM-107).
+	std::string language = gSavedSettings.getString("Language");
+	if(language == "ja" || language == "pl")
+	{
+		LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
+		LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
+		LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
+		LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
+		LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
+
+		LLStringOps::sAM = LLTrans::getString("dateTimeAM");
+		LLStringOps::sPM = LLTrans::getString("dateTimePM");
+	}
 
 	LLAgentLanguage::init();
 
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 492e51e0fd..9752a07b66 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3503,9 +3503,6 @@ Abuse Report</string>
   <string name="dateTimeDayFormat">[MDAY]</string>
   <string name="dateTimeAM">AM</string>
   <string name="dateTimePM">PM</string>
-  
-  <!-- Format string for displaying a localized date in a scroll list cell of type "date" -->
-  <string name="ScrollListCellDateFormat">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</string>
 
   <!--  currency formatting -->
   <string name="LocalEstimateUSD">US$ [AMOUNT]</string>
diff --git a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml
index 0b5333fc80..95649d3934 100644
--- a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml
+++ b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml
@@ -13,7 +13,7 @@
 		Le propriétaire peut :
 	</panel.string>
 	<panel.string name="acquiredDate">
-		[wkday,datetime,local] [day,datetime,local] [mth,datetime,local] [year,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local]
+		[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
 	</panel.string>
 	<panel.string name="origin_inventory">
 		(inventaire)
-- 
cgit v1.2.3


From 60df5e51dc977e28507b3446d649eac67556c050 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 6 Jan 2012 13:01:17 -0800
Subject: EXP-1220 GROUNDWORK -- Create context menu entry to allow import of
 selected item(s)

* Added a context menu for "Send to Marketplace" but disabled the code to show it
  until we decide to move forward with this feature.
* Made some progress unifying the context menu in the outbox for different types
  of items.  (mesh, audio, etc.)
---
 indra/newview/llinventorybridge.cpp                | 77 ++++++++++++++++++----
 indra/newview/llinventorybridge.h                  |  4 ++
 .../skins/default/xui/en/menu_inventory.xml        |  8 +++
 3 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3b6dad7f5c..70553ca676 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -74,6 +74,7 @@
 
 // Marketplace outbox current disabled
 #define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1
+#define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0
 #define BLOCK_WORN_ITEMS_IN_OUTBOX 1
 
 typedef std::pair<LLUUID, LLUUID> two_uuids_t;
@@ -130,6 +131,11 @@ bool isMarketplaceCopyAction(const std::string& action)
 	return (("copy_to_outbox" == action) || ("move_to_outbox" == action));
 }
 
+bool isMarketplaceSendAction(const std::string& action)
+{
+	return ("send_to_marketplace" == action);
+}
+
 // +=================================================+
 // |        LLInvFVBridge                            |
 // +=================================================+
@@ -657,7 +663,7 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	}	
 	else if(isOutboxFolder())
 	{
-		items.push_back(std::string("Delete"));
+		addOutboxContextMenuOptions(flags, items, disabled_items);
 	}
 	else
 	{
@@ -734,6 +740,32 @@ void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items)
 		items.push_back(std::string("Open"));
 }
 
+void LLInvFVBridge::addOutboxContextMenuOptions(U32 flags,
+												menuentry_vec_t &items,
+												menuentry_vec_t &disabled_items)
+{
+	items.push_back(std::string("Rename"));
+	items.push_back(std::string("Delete"));
+	
+	if ((flags & FIRST_SELECTED_ITEM) == 0)
+	{
+		disabled_items.push_back(std::string("Rename"));
+	}
+	
+#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
+	if (isOutboxFolderDirectParent())
+	{
+		items.push_back(std::string("Marketplace Separator"));
+		items.push_back(std::string("Marketplace Send"));
+		
+		if ((flags & FIRST_SELECTED_ITEM) == 0)
+		{
+			disabled_items.push_back(std::string("Marketplace Send"));
+		}
+	}
+#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
+}
+
 // *TODO: remove this
 BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
 {
@@ -854,6 +886,22 @@ BOOL LLInvFVBridge::isOutboxFolder() const
 	return gInventory.isObjectDescendentOf(mUUID, outbox_id);
 }
 
+BOOL LLInvFVBridge::isOutboxFolderDirectParent() const
+{
+	BOOL outbox_is_parent = FALSE;
+	
+	const LLInventoryCategory *cat = gInventory.getCategory(mUUID);
+
+	if (cat)
+	{
+		const LLUUID outbox_id = getOutboxFolder();
+		
+		outbox_is_parent = (outbox_id.notNull() && (outbox_id == cat->getParentUUID()));
+	}
+	
+	return outbox_is_parent;
+}
+
 const LLUUID LLInvFVBridge::getOutboxFolder() const
 {
 	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false);
@@ -2585,6 +2633,17 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
 		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false);
 		copy_folder_to_outbox(cat, outbox_id, cat->getUUID());
 	}
+#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
+	else if (isMarketplaceSendAction(action))
+	{
+		llinfos << "Send to marketplace action!" << llendl;
+
+		LLInventoryCategory * cat = gInventory.getCategory(mUUID);
+		if (!cat) return;
+		
+		send_to_marketplace(cat);
+	}
+#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
 }
 
 void LLFolderBridge::openItem()
@@ -3007,13 +3066,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	}
 	else if(isOutboxFolder())
 	{
-		mItems.push_back(std::string("Rename"));
-		mItems.push_back(std::string("Delete"));
-		
-		if ((flags & FIRST_SELECTED_ITEM) == 0)
-		{
-			mDisabledItems.push_back(std::string("Rename"));
-		}
+		addOutboxContextMenuOptions(flags, mItems, mDisabledItems);
 	}
 	else if(isAgentInventory()) // do not allow creating in library
 	{
@@ -3840,7 +3893,7 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	}	
 	else if(isOutboxFolder())
 	{
-		items.push_back(std::string("Delete"));
+		addOutboxContextMenuOptions(flags, items, disabled_items);
 	}
 	else
 	{
@@ -3916,7 +3969,7 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 
 	if (isOutboxFolder())
 	{
-		items.push_back(std::string("Delete"));
+		addOutboxContextMenuOptions(flags, items, disabled_items);
 	}
 	else
 	{
@@ -3974,7 +4027,7 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
 	if(isOutboxFolder())
 	{
-		items.push_back(std::string("Delete"));
+		addOutboxContextMenuOptions(flags, items, disabled_items);
 	}
 	else
 	{
@@ -5540,7 +5593,7 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	}
 	else if(isOutboxFolder())
 	{
-		items.push_back(std::string("Delete"));
+		addOutboxContextMenuOptions(flags, items, disabled_items);
 	}
 	else
 	{
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 447d781f48..2ab339b918 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -131,6 +131,9 @@ protected:
 	virtual void addDeleteContextMenuOptions(menuentry_vec_t &items,
 											 menuentry_vec_t &disabled_items);
 	virtual void addOpenRightClickMenuOption(menuentry_vec_t &items);
+	virtual void addOutboxContextMenuOptions(U32 flags,
+											 menuentry_vec_t &items,
+											 menuentry_vec_t &disabled_items);
 protected:
 	LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid);
 
@@ -144,6 +147,7 @@ protected:
 	BOOL isCOFFolder() const; // true if COF or descendent of
 	BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox
 	BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox
+	BOOL isOutboxFolderDirectParent() const;
 	const LLUUID getOutboxFolder() const;
 
 	virtual BOOL isItemPermissive() const;
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index fb85e5278a..31dcdfffbb 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -694,6 +694,14 @@
 		 parameter="move_to_outbox" />
 	</menu_item_call>
 	<menu_item_call
+	 label="Send to Marketplace"
+	 layout="topleft"
+	 name="Marketplace Send">
+		<menu_item_call.on_click
+		 function="Inventory.DoToSelected"
+		 parameter="send_to_marketplace" />
+	</menu_item_call>
+	<menu_item_call
      label="--no options--"
      layout="topleft"
      name="--no options--" />
-- 
cgit v1.2.3


From f64ad025e873fff1523d5e05ca1ec19c40bba837 Mon Sep 17 00:00:00 2001
From: eli <none@none>
Date: Fri, 6 Jan 2012 15:29:55 -0800
Subject: sync with viewer-development

---
 indra/newview/skins/default/xui/en/menu_login.xml  | 53 ++++++++++++++++++++-
 indra/newview/skins/default/xui/en/menu_viewer.xml | 51 ++++++++++++++++++++
 .../default/xui/en/panel_preferences_general.xml   |  2 +-
 .../skins/default/xui/en/panel_script_ed.xml       | 22 ++++++---
 indra/newview/skins/default/xui/en/strings.xml     | 55 +++++++++++-----------
 5 files changed, 148 insertions(+), 35 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 8ac1ac9e09..101e104eab 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -174,7 +174,58 @@
          function="Advanced.WebContentTest"
          parameter="http://google.com"/>
       </menu_item_call>
-      <menu_item_check
+      <menu
+       create_jump_keys="true"
+       label="Set Logging Level"
+       name="Set Logging Level"
+       tear_off="true">
+        <menu_item_check
+          label="Debug">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="0" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="0" />
+        </menu_item_check>
+        <menu_item_check
+          label="Info">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="1" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="1" />
+        </menu_item_check>
+        <menu_item_check
+          label="Warning">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="2" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="2" />
+        </menu_item_check>
+        <menu_item_check
+          label="Error">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="3" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="3" />
+        </menu_item_check>
+        <menu_item_check
+          label="None">
+          <menu_item_check.on_check
+            function="Develop.CheckLoggingLevel"
+            parameter="4" />
+          <menu_item_check.on_click
+           function="Develop.SetLoggingLevel"
+           parameter="4" />
+        </menu_item_check>
+      </menu>
+     <menu_item_check
         label="Show Grid Picker"
         name="Show Grid Picker"
         visible="false" 
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 0aa5c72f2a..0df123e140 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3367,6 +3367,57 @@
              function="ToggleControl"
              parameter="ShowConsoleWindow" />
         </menu_item_check>
+        <menu
+         create_jump_keys="true"
+         label="Set Logging Level"
+         name="Set Logging Level"
+         tear_off="true">
+          <menu_item_check
+            label="Debug">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="0" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="0" />
+          </menu_item_check>
+          <menu_item_check
+            label="Info">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="1" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="1" />
+          </menu_item_check>
+          <menu_item_check
+            label="Warning">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="2" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="2" />
+          </menu_item_check>
+          <menu_item_check
+            label="Error">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="3" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="3" />
+          </menu_item_check>
+          <menu_item_check
+            label="None">
+            <menu_item_check.on_check
+              function="Develop.CheckLoggingLevel"
+              parameter="4" />
+            <menu_item_check.on_click
+             function="Develop.SetLoggingLevel"
+             parameter="4" />
+          </menu_item_check>
+       </menu>
 
         <menu_item_separator/>
 
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index 4079a80924..9827180aa7 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -420,7 +420,7 @@
      follows="left|top"
      height="29"
      layout="topleft"
-     left="50"
+     left="30"
      name="busy_response"
      width="470"
      word_wrap="true">
diff --git a/indra/newview/skins/default/xui/en/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml
index 8d42024386..f6a8af0973 100644
--- a/indra/newview/skins/default/xui/en/panel_script_ed.xml
+++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml
@@ -54,12 +54,22 @@
              label="Save"
              layout="topleft"
              name="Save" />
-            <menu_item_separator
-             layout="topleft" />
-            <menu_item_call
-             label="Revert All Changes"
-             layout="topleft"
-             name="Revert All Changes" />
+          <menu_item_separator
+           layout="topleft" />
+          <menu_item_call
+           label="Revert All Changes"
+           layout="topleft"
+           name="Revert All Changes" />
+          <menu_item_separator
+           layout="topleft" />
+          <menu_item_call
+           label="Load from file..."
+           layout="topleft"
+           name="LoadFromFile" />
+          <menu_item_call
+           label="Save to file..."
+           layout="topleft"
+           name="SaveToFile" />
         </menu>
         <menu
          top="0"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 9752a07b66..2b0dcdfeca 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -88,7 +88,7 @@ We are very sorry for the inconvenience.</string>
 Logins are currently restricted to employees only.
 Check www.secondlife.com/status for updates.</string>
 	<string name="LoginFailedPremiumOnly">Second Life logins are temporarily restricted in order to make sure that those in-world have the best possible experience.
-	 	
+
 People with free accounts will not be able to access Second Life during this time, to make room for those who have paid for Second Life.</string>
 	<string name="LoginFailedComputerProhibited">Second Life cannot be accessed from this computer.
 If you feel this is an error, please contact
@@ -168,7 +168,7 @@ Please try logging in again in a minute.</string>
 	<string name="TooltipOutboxWorn">You are wearing one or more of these objects. Remove them from your avatar and try moving them again.</string>
 	<string name="TooltipOutboxFolderLevels">This folder has too many levels of subfolders. Rearrange the interior folders to a maximum of 4 levels deep (Root Folder contains A contains B contains C).</string>
 	<string name="TooltipOutboxTooManyObjects">This folder contains more than 200 objects. Box some of the items to reduce the object count.</string>
-	
+
 	<!-- tooltips for Urls -->
 	<string name="TooltipHttpUrl">Click to view this web page</string>
 	<string name="TooltipSLURL">Click to view this location's information</string>
@@ -188,7 +188,7 @@ Please try logging in again in a minute.</string>
 	<string name="TooltipObjectIMUrl">Click to view this object's description</string>
 	<string name="TooltipMapUrl">Click to view this location on a map</string>
 	<string name="TooltipSLAPP">Click to run the secondlife:// command</string>
-	<string name="CurrentURL" value=" CurrentURL: [CurrentURL]" />	
+	<string name="CurrentURL" value=" CurrentURL: [CurrentURL]" />
 
 	<!-- text for SLURL labels -->
 	<string name="SLurlLabelTeleport">Teleport to</string>
@@ -427,9 +427,10 @@ Please try logging in again in a minute.</string>
 	<string name="compressed_image_files">Compressed Images</string>
 	<string name="load_files">Load Files</string>
 	<string name="choose_the_directory">Choose Directory</string>
+	<string name="script_files">Scripts</string>
 
-	<!-- LSL Usage Hover Tips -->
-	<!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window).
+  <!-- LSL Usage Hover Tips -->
+  <!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window).
              This has no effect on viewer code, but prevents Linden Lab internal localization tool from scraping these strings.  -->
 	<string name="LSLTipSleepTime" translate="false">
 Sleeps script for [SLEEP_TIME] seconds.
@@ -1950,7 +1951,7 @@ Returns a string with the requested data about the region
   <string name="physics">Physics</string>
   <string name="invalid">invalid</string>
   <string name="none">none</string>
-  
+
   <!-- Not Worn Wearable Types -->
 	<string name="shirt_not_worn">Shirt not worn</string>
 	<string name="pants_not_worn">Pants not worn</string>
@@ -1987,7 +1988,7 @@ Returns a string with the requested data about the region
 
   <!-- Wearable List-->
   <string name="NewWearable">New [WEARABLE_ITEM]</string>
-  
+
 	<!-- LLGroupNotify -->
 	<!-- used in the construction of a Group Notice blue dialog box, buttons, tooltip etc. Seems to be no longer utilized by code in Viewer 2.0 -->
 	<string name="next">Next</string>
@@ -2314,7 +2315,7 @@ Returns a string with the requested data about the region
 	<string name="ScriptLimitsRequestWrongRegion">Error: script information is only available in your current region</string>
 	<string name="ScriptLimitsRequestWaiting">Retrieving information...</string>
 	<string name="ScriptLimitsRequestDontOwnParcel">You do not have permission to examine this parcel</string>
-	
+
 	<string name="SITTING_ON">Sitting On</string>
 	<string name="ATTACH_CHEST">Chest</string>
 	<string name="ATTACH_HEAD">Head</string>
@@ -2354,7 +2355,7 @@ Returns a string with the requested data about the region
 	<string name="ATTACH_HUD_BOTTOM_LEFT">HUD Bottom Left</string>
 	<string name="ATTACH_HUD_BOTTOM">HUD Bottom</string>
 	<string name="ATTACH_HUD_BOTTOM_RIGHT">HUD Bottom Right</string>
-			
+
 	<!-- script editor -->
 	<string name="CursorPos">Line [LINE], Column [COLUMN]</string>
 
@@ -2367,7 +2368,7 @@ Returns a string with the requested data about the region
 
 	<!-- panel contents -->
 	<string name="PanelContentsTooltip">Content of object</string>
-	<string name="PanelContentsNewScript">New Script</string>	
+	<string name="PanelContentsNewScript">New Script</string>
 
   <!-- panel preferences general -->
   <string name="BusyModeResponseDefault">The Resident you messaged is in &apos;busy mode&apos; which means they have requested not to be disturbed.  Your message will still be shown in their IM panel for later viewing.</string>
@@ -2397,7 +2398,7 @@ Returns a string with the requested data about the region
 	<!-- panel classified -->
 	<string name="ClassifiedClicksTxt">Clicks: [TELEPORT] teleport, [MAP] map, [PROFILE] profile</string>
 	<string name="ClassifiedUpdateAfterPublish">(will update after publish)</string>
-  
+
   <!-- panel picks -->
   <string name="NoPicksClassifiedsText">You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified.</string>
   <string name="NoAvatarPicksClassifiedsText">User has no picks or classifieds</string>
@@ -3274,7 +3275,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
     You have blocked this Resident. Sending a message will automatically unblock them.
   </string>
   <!--Some times string name is getting from the body of server response.
-  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post. 
+  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
   In case of the EXT-3115 issue 'generic' is passed into the gIMMgr::showSessionStartError as a string name.
   Also there are some other places where "generic" is used.
   So, let add string with name="generic" with the same value as "generic_request_error" -->
@@ -3300,7 +3301,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
     You are not a session moderator.
   </string>
   <!--Some times string name is getting from the body of server response.
-  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post. 
+  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
   In case of the EXT-3562 issue 'muted' is passed into the gIMMgr::showSessionStartError as a string name.
   So, let add string with name="muted" with the same value as "muted_error" -->
   <string name="muted">
@@ -3313,12 +3314,12 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
     Unable to add users to chat session with [RECIPIENT].
   </string>
   <!--Some times string name is getting from the body of server response.
-  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post. 
+  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
   In case of the EXT-3562 issue 'message' is passed into the gIMMgr::showSessionStartError as a string name.
   So, let add string with name="message" with the same value as "message_session_event" -->
   <string name="message">
     Unable to send your message to the chat session with [RECIPIENT].
-  </string>  
+  </string>
   <string name="message_session_event">
     Unable to send your message to the chat session with [RECIPIENT].
   </string>
@@ -3326,7 +3327,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
     Error while moderating.
   </string>
   <!--Some times string name is getting from the body of server response.
-  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post. 
+  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
   In case of the EXT-3459 issue 'removed' is passed into the gIMMgr::showSessionStartError as a string name.
   So, let add string with name="removed" with the same value as "removed_from_group" -->
   <string name="removed">
@@ -3347,9 +3348,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 	<string name="session_initialization_timed_out_error">
 		The session initialization is timed out
 	</string>
-  
+
   <string name="Home position set.">Home position set.</string>
-  
+
   <string name="voice_morphing_url">http://secondlife.com/landing/voicemorphing</string>
 
   <!-- Financial operations strings -->
@@ -3371,20 +3372,20 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <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>
   <string name="this_costs">This costs L$ [AMOUNT]</string>
   <string name="buying_selected_land">Buying selected land for L$ [AMOUNT]</string>
   <string name="this_object_costs">This object costs L$ [AMOUNT]</string>
-  
+
   <string name="group_role_everyone">Everyone</string>
   <string name="group_role_officers">Officers</string>
   <string name="group_role_owners">Owners</string>
   <string name="group_member_status_online">Online</string>
 
   <string name="uploading_abuse_report">Uploading...
-  
+
 Abuse Report</string>
 
   <!-- names for new inventory items-->
@@ -3478,23 +3479,23 @@ Abuse Report</string>
 
   <!-- birth date format shared by avatar inspector and profile panels -->
   <string name="AvatarBirthDateFormat">[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt]</string>
-  
+
   <string name="DefaultMimeType">none/none</string>
   <string name="texture_load_dimensions_error">Can't load images larger than [WIDTH]*[HEIGHT]</string>
 
   <!-- language specific white-space characters, delimiters, spacers, item separation symbols -->
   <string name="sentences_separator" value=" "></string>
   <string name="words_separator" value=", "/>
-  
+
   <string name="server_is_down">
 	Despite our best efforts, something unexpected has gone wrong.
 
-	Please check status.secondlifegrid.net to see if there is a known problem with the service.  
+	Please check status.secondlifegrid.net to see if there is a known problem with the service.
         If you continue to experience problems, please check your network and firewall setup.
   </string>
 
-  <!-- overriding datetime formating. 
-	didn't translate if this is not needed for current localization 
+  <!-- overriding datetime formating.
+	didn't translate if this is not needed for current localization
   -->
   <string name="dateTimeWeekdaysNames">Sunday:Monday:Tuesday:Wednesday:Thursday:Friday:Saturday</string>
   <string name="dateTimeWeekdaysShortNames">Sun:Mon:Tue:Wed:Thu:Fri:Sat</string>
@@ -3527,7 +3528,7 @@ Abuse Report</string>
   <string name="DeleteItem">Delete selected item?</string>
 
   <string name="EmptyOutfitText">There are no items in this outfit</string>
- 
+
  <!-- External editor status codes -->
  <string name="ExternalEditorNotSet">Select an editor using the ExternalEditor setting.</string>
  <string name="ExternalEditorNotFound">Cannot find the external editor you specified.
-- 
cgit v1.2.3


From c98bf3cd509dd7bf10837713a911f9932c476e1f Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 6 Jan 2012 15:50:43 -0800
Subject: Updated InventoryOutboxMaxFolderCount to 21 to allow top level folder
 and 20 subfolders in outbox items

---
 indra/newview/app_settings/settings.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index e5bb686123..a4806e3b77 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4291,7 +4291,7 @@
       <key>Type</key>
       <string>U32</string>
       <key>Value</key>
-      <integer>20</integer>
+      <integer>21</integer>
     </map>
     <key>InventoryOutboxMaxFolderDepth</key>
     <map>
-- 
cgit v1.2.3


From 8c0023eec46c8a9cdba674acf8c07b488dac6f7c Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 9 Jan 2012 08:40:42 -0500
Subject: Added tag 3.6.0-start for changeset a1012611a195

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index 424701983a..54dd41dbf0 100644
--- a/.hgtags
+++ b/.hgtags
@@ -244,3 +244,4 @@ bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release
 3d2d5d244c6398a4214c666d5dd3965b0918709a 3.2.5-beta1
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d DRTVWR-107_3.2.5-beta2
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d 3.2.5-beta2
+a1012611a195a41cbfb8e6b842e9aac5bd3306e8 3.6.0-start
-- 
cgit v1.2.3


From 41ceee848bbbaec892471b6396bd2d2383d10aa3 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 9 Jan 2012 08:41:36 -0500
Subject: increment viewer version to 3.2.7

---
 indra/llcommon/llversionviewer.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index ec378761c2..7bba3d298f 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
 
 const S32 LL_VERSION_MAJOR = 3;
 const S32 LL_VERSION_MINOR = 2;
-const S32 LL_VERSION_PATCH = 6;
+const S32 LL_VERSION_PATCH = 7;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";
-- 
cgit v1.2.3


From 3dfb1536fa3bb85f6648a76591e80c3feea9eb83 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 9 Jan 2012 08:41:36 -0500
Subject: increment viewer version to 3.2.7

---
 indra/llcommon/llversionviewer.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index ec378761c2..7bba3d298f 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
 
 const S32 LL_VERSION_MAJOR = 3;
 const S32 LL_VERSION_MINOR = 2;
-const S32 LL_VERSION_PATCH = 6;
+const S32 LL_VERSION_PATCH = 7;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";
-- 
cgit v1.2.3


From 1fb6dbbf8061c89131669286fef9940af5dffc76 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 9 Jan 2012 12:26:57 -0500
Subject: Backed out changeset 4fd359f2f1c3

---
 indra/llcommon/llversionviewer.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 7bba3d298f..ec378761c2 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
 
 const S32 LL_VERSION_MAJOR = 3;
 const S32 LL_VERSION_MINOR = 2;
-const S32 LL_VERSION_PATCH = 7;
+const S32 LL_VERSION_PATCH = 6;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";
-- 
cgit v1.2.3


From fc00c99532932ee1664bca1ff295e58240bc01b7 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 9 Jan 2012 12:29:13 -0500
Subject: remove incorrect tag

---
 .hgtags | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.hgtags b/.hgtags
index 54dd41dbf0..424701983a 100644
--- a/.hgtags
+++ b/.hgtags
@@ -244,4 +244,3 @@ bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release
 3d2d5d244c6398a4214c666d5dd3965b0918709a 3.2.5-beta1
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d DRTVWR-107_3.2.5-beta2
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d 3.2.5-beta2
-a1012611a195a41cbfb8e6b842e9aac5bd3306e8 3.6.0-start
-- 
cgit v1.2.3


From 4c5141c5677a2e98c1331026d4e119abee6ab2ae Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 9 Jan 2012 12:29:39 -0500
Subject: Added tag 3.2.6-start for changeset 2174ed1c7129

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index 424701983a..f4ffb61aa6 100644
--- a/.hgtags
+++ b/.hgtags
@@ -244,3 +244,4 @@ bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release
 3d2d5d244c6398a4214c666d5dd3965b0918709a 3.2.5-beta1
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d DRTVWR-107_3.2.5-beta2
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d 3.2.5-beta2
+2174ed1c7129562428a5cfe8651ed77b8d26ae18 3.2.6-start
-- 
cgit v1.2.3


From 651fdba651dc4ecbb9a40b7c841a13ac1b47e1cc Mon Sep 17 00:00:00 2001
From: eli <none@none>
Date: Mon, 9 Jan 2012 11:42:04 -0800
Subject: sync with viewer-development

---
 .../skins/default/xui/de/floater_chat_bar.xml      |  2 +-
 .../newview/skins/default/xui/de/notifications.xml |  2 +-
 .../skins/default/xui/de/panel_status_bar.xml      |  2 +-
 .../skins/default/xui/en/floater_chat_bar.xml      |  2 ++
 indra/newview/skins/default/xui/en/menu_edit.xml   |  3 +++
 indra/newview/skins/default/xui/en/menu_viewer.xml |  2 ++
 .../newview/skins/default/xui/en/notifications.xml | 22 +++++++++++++++++++++-
 .../default/xui/en/panel_snapshot_postcard.xml     |  8 --------
 .../skins/default/xui/en/panel_status_bar.xml      |  3 +--
 .../skins/default/xui/en/widgets/window_shade.xml  |  2 ++
 .../skins/default/xui/es/floater_chat_bar.xml      |  2 +-
 .../newview/skins/default/xui/es/notifications.xml |  2 +-
 .../skins/default/xui/es/panel_status_bar.xml      |  2 +-
 .../skins/default/xui/fr/floater_chat_bar.xml      |  2 +-
 .../newview/skins/default/xui/fr/notifications.xml |  2 +-
 .../skins/default/xui/fr/panel_status_bar.xml      |  2 +-
 .../skins/default/xui/it/floater_chat_bar.xml      |  2 +-
 .../newview/skins/default/xui/it/notifications.xml |  2 +-
 .../skins/default/xui/it/panel_status_bar.xml      |  2 +-
 .../skins/default/xui/ja/floater_chat_bar.xml      |  2 +-
 .../newview/skins/default/xui/ja/notifications.xml |  2 +-
 .../skins/default/xui/ja/panel_status_bar.xml      |  2 +-
 .../newview/skins/default/xui/pl/notifications.xml |  2 +-
 .../skins/default/xui/pt/floater_chat_bar.xml      |  2 +-
 .../newview/skins/default/xui/pt/notifications.xml |  2 +-
 .../skins/default/xui/pt/panel_status_bar.xml      |  2 +-
 .../skins/default/xui/ru/floater_chat_bar.xml      |  2 +-
 .../newview/skins/default/xui/ru/notifications.xml |  2 +-
 .../skins/default/xui/ru/panel_status_bar.xml      |  2 +-
 .../skins/default/xui/tr/floater_chat_bar.xml      |  2 +-
 .../newview/skins/default/xui/tr/notifications.xml |  2 +-
 .../skins/default/xui/tr/panel_status_bar.xml      |  2 +-
 .../newview/skins/default/xui/zh/notifications.xml |  2 +-
 33 files changed, 57 insertions(+), 37 deletions(-)
 create mode 100644 indra/newview/skins/default/xui/en/widgets/window_shade.xml

diff --git a/indra/newview/skins/default/xui/de/floater_chat_bar.xml b/indra/newview/skins/default/xui/de/floater_chat_bar.xml
index dc5a7cd681..2464a55665 100644
--- a/indra/newview/skins/default/xui/de/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/de/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="CHAT IN DER NÄHE">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Zum Chatten hier klicken." name="chat_box" tool_tip="Eingabetaste zum Sprechen, Strg+Eingabe zum Rufen"/>
 		<button name="show_nearby_chat" tool_tip="Chatprotokoll in der Nähe ein-/ausblenden"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index 72e7ec8eb4..a5fcd3e0b4 100644
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -1443,7 +1443,7 @@ Zur Installation des Updates muss [APP_NAME] neu gestartet werden.
 		<usetemplate ignoretext="Bestätigen, bevor Objekte an Ihre Eigentümer zurückgegeben werden" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Sie sind Mitglied der Gruppe [GROUP].
+		Sie sind Mitglied der Gruppe &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Diese Gruppe verlassen?
 		<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml
index d34fcf70bc..2493d60df6 100644
--- a/indra/newview/skins/default/xui/de/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="20 L$"/>
 		<button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/>
-		<button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen"/>
+		<button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen" width="85"/>
 	</panel>
 	<text name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)">
 		24:00 H PST
diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml
index 8d0cecdac3..63992462b3 100644
--- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/en/floater_chat_bar.xml
@@ -9,6 +9,7 @@
  single_instance="true"
  title="NEARBY CHAT"
  save_rect="true"
+ save_visibility="true"
  can_close="true"
  can_minimize="true"
  help_topic="chat_bar"
@@ -30,6 +31,7 @@
     <panel width="300" 
            height="31" 
            left="0" 
+           name="bottom_panel"
            bottom="-1" 
            follows="left|right|bottom" 
            tab_group="1">
diff --git a/indra/newview/skins/default/xui/en/menu_edit.xml b/indra/newview/skins/default/xui/en/menu_edit.xml
index fab76c497c..99061e089a 100644
--- a/indra/newview/skins/default/xui/en/menu_edit.xml
+++ b/indra/newview/skins/default/xui/en/menu_edit.xml
@@ -6,6 +6,7 @@
   <menu_item_call
    label="Undo"
    name="Undo"
+   allow_key_repeat="true"
    shortcut="control|Z">
     <menu_item_call.on_click
      function="Edit.Undo" />
@@ -15,6 +16,7 @@
   <menu_item_call
    label="Redo"
    name="Redo"
+   allow_key_repeat="true"
    shortcut="control|Y">
     <menu_item_call.on_click
      function="Edit.Redo" />
@@ -43,6 +45,7 @@
   <menu_item_call
    label="Paste"
    name="Paste"
+   allow_key_repeat="true"
    shortcut="control|V">
     <menu_item_call.on_click
      function="Edit.Paste" />
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 0df123e140..ec2dd10248 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1154,6 +1154,7 @@
          enabled="false"
          label="Undo"
          name="Undo"
+         allow_key_repeat="true"
          shortcut="control|Z">
             <on_click
              function="Edit.Undo"
@@ -1165,6 +1166,7 @@
          enabled="false"
          label="Redo"
          name="Redo"
+         allow_key_repeat="true"
          shortcut="control|Y">
             <on_click
              function="Edit.Redo"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index a7705c8bac..1daf2e6948 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -3409,7 +3409,7 @@ Are you sure you want to return the selected objects to their owners? Transferab
    icon="alert.tga"
    name="GroupLeaveConfirmMember"
    type="alert">
-You are currently a member of the group [GROUP].
+You are currently a member of the group &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Leave Group?
     <tag>group</tag>
     <tag>confirm</tag>
@@ -6951,6 +6951,26 @@ With the following Residents:
      yestext="OK"/>
   </notification>
   
+  <notification
+   icon="notifytip.tga"
+   name="ShareFolderConfirmation"
+   type="alertmodal">
+Only one folder at a time can be shared.
+
+Are you sure you want to share the following items:
+
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
+
+With the following Residents:
+
+[RESIDENTS]
+  <tag>confirm</tag>
+	<usetemplate
+     name="okcancelbuttons"
+     notext="Cancel"
+     yestext="Ok"/>
+  </notification>
+  
   <notification
    icon="notifytip.tga"
    name="ItemsShared"
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
index d8ff043444..ebba292a93 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
@@ -16,14 +16,6 @@
      name="upload_message">
         Sending...
     </string>
-    <string
-     name="default_subject">
-        Postcard from [SECOND_LIFE].
-    </string>
-    <string
-     name="default_message">
-        Check this out!
-    </string>
     <icon
      follows="top|left"
      height="18"
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index 3239c4e531..d453a970e7 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -70,7 +70,7 @@
      pad_bottom="2"
      tool_tip="Click to buy more L$"
      top="0"
-     width="55" />
+     width="80" />
     <button
      halign="left"
      font="SansSerifSmall"
@@ -87,7 +87,6 @@
      left_pad="0"
      label_shadow="true"
      name="goShop"
-     pad_right="0"
      pad_bottom="2"
      tool_tip="Open Second Life Marketplace"
      top="0"
diff --git a/indra/newview/skins/default/xui/en/widgets/window_shade.xml b/indra/newview/skins/default/xui/en/widgets/window_shade.xml
new file mode 100644
index 0000000000..23eb2f13fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/window_shade.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<window_shade shade_color="0 0 0 0.5"/>
diff --git a/indra/newview/skins/default/xui/es/floater_chat_bar.xml b/indra/newview/skins/default/xui/es/floater_chat_bar.xml
index 5e5ef616b8..2e94805057 100644
--- a/indra/newview/skins/default/xui/es/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/es/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="CHAT">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Pulsa aquí para chatear." name="chat_box" tool_tip="Pulsa Enter para decirlo o Ctrl+Enter para gritarlo"/>
 		<button name="show_nearby_chat" tool_tip="Muestra o esconde el registro del chat"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 9591b424fc..0de56f9b6d 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -1437,7 +1437,7 @@ Debemos reiniciar [APP_NAME] para instalar la actualización.
 		<usetemplate ignoretext="Confirmar antes de devolver objetos a sus propietarios." name="okcancelignore" notext="Cancelar" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Actualmente, eres miembro del grupo [GROUP].
+		Actualmente, eres miembro del grupo &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 ¿Dejar el grupo?
 		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml
index d43790c8c6..79b2c32b23 100644
--- a/indra/newview/skins/default/xui/es/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="20 L$"/>
 		<button label="Comprar L$" name="buyL" tool_tip="Pulsa para comprar más L$"/>
-		<button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life"/>
+		<button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life" width="80"/>
 	</panel>
 	<text name="TimeText" tool_tip="Hora actual (Pacífico)">
 		24:00 AM PST
diff --git a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml
index 88a2fb669b..c7d27c0589 100644
--- a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="CHAT PRÈS DE MOI">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Cliquer ici pour chatter." name="chat_box" tool_tip="Appuyer sur Entrée pour dire, Ctrl-Entrée pour crier"/>
 		<button name="show_nearby_chat" tool_tip="Affiche/Masque le journal de chats près de vous"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index d8d79d8dde..be6f1f8c31 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -1428,7 +1428,7 @@ Version [VERSION]
 		<usetemplate ignoretext="Confirmer avant de rendre les objets à leurs propriétaires" name="okcancelignore" notext="Annuler" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Vous êtes actuellement membre du groupe [GROUP].
+		Vous êtes actuellement membre du groupe &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Quitter le groupe ?
 		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
index ac61eb7e52..c0d59a3182 100644
--- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="20 L$"/>
 		<button label="Acheter L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/>
-		<button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life."/>
+		<button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life." width="75"/>
 	</panel>
 	<text name="TimeText" tool_tip="Heure actuelle (Pacifique)">
 		00h00 PST
diff --git a/indra/newview/skins/default/xui/it/floater_chat_bar.xml b/indra/newview/skins/default/xui/it/floater_chat_bar.xml
index 6c5c8fbea0..94c85b50c8 100644
--- a/indra/newview/skins/default/xui/it/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/it/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="CHAT NEI DINTORNI">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Clicca qui per la chat." name="chat_box" tool_tip="Premi Invio per parlare, Ctrl+Invio per gridare"/>
 		<button name="show_nearby_chat" tool_tip="Mostra/Nasconde il registro della chat nei dintorni"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index 2db0892cd6..fce027da0c 100644
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -1432,7 +1432,7 @@ Per installare l&apos;aggiornamento è necessario riavviare [APP_NAME].
 		<usetemplate ignoretext="Conferma prima di restituire gli oggetti ai relativi proprietari" name="okcancelignore" notext="Annulla" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Sei attualmente un membro del gruppo [GROUP].
+		Sei attualmente un membro del gruppo &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Vuoi lasciare il gruppo?
 		<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml
index fadaa575ea..4abc90113f 100644
--- a/indra/newview/skins/default/xui/it/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Clicca per aggiornare il tuo saldo in L$" value="L$ 20"/>
 		<button label="Acquista L$" name="buyL" tool_tip="Clicca per acquistare più L$"/>
-		<button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life"/>
+		<button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life" width="75"/>
 	</panel>
 	<text name="TimeText" tool_tip="Orario attuale (Pacifico)">
 		24:00, ora del Pacifico
diff --git a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml
index 9735afb101..504cea5931 100644
--- a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="近くのチャット">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="ここをクリックしてチャットを開始します。" name="chat_box" tool_tip="Enter キーを押して話し、Ctrl + Enter キーで叫びます。"/>
 		<button name="show_nearby_chat" tool_tip="近くのチャットログを表示・非表示"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index 7dfa6d2f7a..141f2c8071 100644
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -1467,7 +1467,7 @@ http://secondlife.com/download から最新バージョンをダウンロード
 		<usetemplate ignoretext="オブジェクトを所有者に返却する前の確認" name="okcancelignore" notext="取り消し" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		現在あなたは [GROUP] のメンバーです。
+		現在あなたは &lt;nolink&gt;[GROUP]&lt;/nolink&gt; のメンバーです。
 このグループを抜けますか?
 		<usetemplate name="okcancelbuttons" notext="取り消し" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
index 93689b81af..4fb876f690 100644
--- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="クリックして L$ 残高を更新" value="L$20"/>
 		<button label="L$ の購入" name="buyL" tool_tip="クリックして L$ を購入します"/>
-		<button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開く"/>
+		<button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開く"  width="40"/>
 	</panel>
 	<text name="TimeText" tool_tip="現在時刻(太平洋)">
 		24:00 AM PST
diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml
index e1fb6dd3f1..0194293642 100644
--- a/indra/newview/skins/default/xui/pl/notifications.xml
+++ b/indra/newview/skins/default/xui/pl/notifications.xml
@@ -1385,7 +1385,7 @@ W celu instalacji aktualizacji musi zostać wykonany restart [APP_NAME].
 		<usetemplate ignoretext="Potwierdź zanim zwrócisz obiekty do ich właścicieli" name="okcancelignore" notext="Anuluj" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Jesteś członkiem grupy [GROUP].
+		Jesteś członkiem grupy &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Chcesz opuścić grupę?
 		<usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/pt/floater_chat_bar.xml b/indra/newview/skins/default/xui/pt/floater_chat_bar.xml
index c089ab93f2..72016c6b40 100644
--- a/indra/newview/skins/default/xui/pt/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/pt/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="BATE-PAPO LOCAL">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Clique aqui para bater papo." name="chat_box" tool_tip="Tecle Enter para falar, Ctrl+Enter para gritar"/>
 		<button name="show_nearby_chat" tool_tip="Mostra/oculta o histórico do bate-papo local"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index d3547beeb3..b53ebeb136 100644
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -1419,7 +1419,7 @@ Para instalar a atualização, será preciso reiniciar o [APP_NAME].
 		<usetemplate ignoretext="Confirmar antes de devolver objetos a seus donos" name="okcancelignore" notext="Cancelar" yestext="Retornar"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Você é atualmente um membro do grupo [GROUP].
+		Você é atualmente um membro do grupo &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Sair do grupo?
 		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Sair"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
index d5a3258ddc..22853f0643 100644
--- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Atualizar saldo de L$" value="L$20"/>
 		<button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/>
-		<button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life"/>
+		<button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life" width="80"/>
 	</panel>
 	<text name="TimeText" tool_tip="Hora atual (Pacífico)">
 		24:00 AM PST
diff --git a/indra/newview/skins/default/xui/ru/floater_chat_bar.xml b/indra/newview/skins/default/xui/ru/floater_chat_bar.xml
index eceab1775a..79b7b033fb 100644
--- a/indra/newview/skins/default/xui/ru/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/ru/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="ЛОКАЛЬНЫЙ ЧАТ">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Щелкните здесь для общения." name="chat_box" tool_tip="Нажмите Enter, чтобы сказать, Ctrl+Enter, чтобы прокричать"/>
 		<button name="show_nearby_chat" tool_tip="Показать/скрыть лог локального чата"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml
index 1be14160ed..f121743fe9 100644
--- a/indra/newview/skins/default/xui/ru/notifications.xml
+++ b/indra/newview/skins/default/xui/ru/notifications.xml
@@ -1431,7 +1431,7 @@ http://secondlife.com/download.
 		<usetemplate ignoretext="Подтверждать перед возвратом объектов владельцам" name="okcancelignore" notext="Отмена" yestext="OK"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Вы являетесь участником группы [GROUP].
+		Вы являетесь участником группы &lt;nolink&gt;[GROUP]&lt;/nolink&gt;.
 Хотите покинуть группу?
 		<usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/ru/panel_status_bar.xml b/indra/newview/skins/default/xui/ru/panel_status_bar.xml
index 6822244196..babe5811ac 100644
--- a/indra/newview/skins/default/xui/ru/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ru/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="Щелкните для обновления вашего баланса L$" value="L$20"/>
 		<button label="Купить L$" name="buyL" tool_tip="Щелкните для покупки L$"/>
-		<button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life"/>
+		<button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life" width="121"/>
 	</panel>
 	<text name="TimeText" tool_tip="Текущее время (тихоокеанское)">
 		00:00 (тихоокеанское время)
diff --git a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml
index d2385e6be3..dee17b7bc4 100644
--- a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml
+++ b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="chat_bar" title="YAKINDAKİ SOHBET">
-	<panel>
+	<panel name="bottom_panel">
 		<line_editor label="Sohbet etmek için buraya tıklayın." name="chat_box" tool_tip="Söylemek için Enter, bağırmak için Ctrl+Enter yapın"/>
 		<button name="show_nearby_chat" tool_tip="yakın sohbet günlüğünü gösterir/gizler"/>
 	</panel>
diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml
index 6908f6867f..c0dc67ed34 100644
--- a/indra/newview/skins/default/xui/tr/notifications.xml
+++ b/indra/newview/skins/default/xui/tr/notifications.xml
@@ -1431,7 +1431,7 @@ Güncellemeyi kurmak için [APP_NAME] uygulamasını yeniden başlatmalısınız
 		<usetemplate ignoretext="Nesneleri sahiplerine iade etmeden önce doğrulama iste" name="okcancelignore" notext="İptal" yestext="Tamam"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		Şu anda [GROUP] grubunun bir üyesisiniz.
+		Şu anda &lt;nolink&gt;[GROUP]&lt;/nolink&gt; grubunun bir üyesisiniz.
 Gruptan ayrılmak istiyor musunuz?
 		<usetemplate name="okcancelbuttons" notext="İptal" yestext="Tamam"/>
 	</notification>
diff --git a/indra/newview/skins/default/xui/tr/panel_status_bar.xml b/indra/newview/skins/default/xui/tr/panel_status_bar.xml
index 63726b94e2..81c304a5d8 100644
--- a/indra/newview/skins/default/xui/tr/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/tr/panel_status_bar.xml
@@ -18,7 +18,7 @@
 	<panel name="balance_bg">
 		<text name="balance" tool_tip="L$ bakiyenizi yenilemek için buraya tıklayın" value="L$20"/>
 		<button label="L$ Satın Al" name="buyL" tool_tip="Daha fazla L$ satın almak için tıklayın"/>
-		<button label="Alışveriş yap" name="goShop" tool_tip="Second Life Pazaryeri Aç"/>
+		<button label="Alışveriş yap" name="goShop" tool_tip="Second Life Pazaryeri Aç" width="95"/>
 	</panel>
 	<text name="TimeText" tool_tip="Geçerli zaman (Pasifik)">
 		24:00 AM PST
diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml
index 17ff6288a5..3fa8ff3f78 100644
--- a/indra/newview/skins/default/xui/zh/notifications.xml
+++ b/indra/newview/skins/default/xui/zh/notifications.xml
@@ -1418,7 +1418,7 @@ We must restart [APP_NAME] to install the update.
 		<usetemplate ignoretext="在我退回物件給它們的擁有者前確認" name="okcancelignore" notext="取消" yestext="確定"/>
 	</notification>
 	<notification name="GroupLeaveConfirmMember">
-		你目前是 [GROUP] 群組的成員。
+		你目前是 &lt;nolink&gt;[GROUP]&lt;/nolink&gt; 群組的成員。
 是否要離開群組?
 		<usetemplate name="okcancelbuttons" notext="取消" yestext="確定"/>
 	</notification>
-- 
cgit v1.2.3


From 98a85b1bf2d7decf477d3d1076859fdeec6f1b46 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 9 Jan 2012 13:39:58 -0800
Subject: EXP-1159 FIX -- User can get No transfer items into Merchant Outbox
 by rezzing object from Outbox, including No Transfer item in contents, and
 then taking back into Inventory

* Drag and drop to the 3D world is now disabled from the outbox
---
 indra/newview/lltooldraganddrop.cpp            | 17 ++++++++++++++++-
 indra/newview/skins/default/xui/en/strings.xml | 21 +++++++++++----------
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 6338ea477c..5a4d177709 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -769,6 +769,21 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
 
 	if (!handled)
 	{
+		// Disallow drag and drop to 3D from the outbox
+		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false);
+		if (outbox_id.notNull())
+		{
+			for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++)
+			{
+				if (gInventory.isObjectDescendentOf(mCargoIDs[item_index], outbox_id))
+				{
+					*acceptance = ACCEPT_NO;
+					mToolTipMsg = LLTrans::getString("TooltipOutboxDragToWorld");
+					return;
+				}
+			}
+		}
+		
 		dragOrDrop3D( x, y, mask, drop, acceptance );
 	}
 }
@@ -867,7 +882,7 @@ void LLToolDragAndDrop::pick(const LLPickInfo& pick_info)
 			(U32)mLastAccept,
 			(U32)callMemberFunction(*this, 
 									LLDragAndDropDictionary::instance().get(dad_type, target))
-			(hit_obj, hit_face, pick_info.mKeyMask, FALSE));
+				(hit_obj, hit_face, pick_info.mKeyMask, FALSE));
 	}
 
 	if (mDrop && ((U32)mLastAccept >= ACCEPT_YES_COPY_SINGLE))
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 20d9463186..a78f3df5b6 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -18,7 +18,7 @@
 	<string name="StartupClearingCache">Clearing cache...</string>
 	<string name="StartupInitializingTextureCache">Initializing texture cache...</string>
 	<string name="StartupInitializingVFS">Initializing VFS...</string>
-  <string name="StartupRequireDriverUpdate">Graphics initialization failed. Please update your graphics driver!</string>
+	<string name="StartupRequireDriverUpdate">Graphics initialization failed. Please update your graphics driver!</string>
 
 	<!--  progress -->
 	<string name="ProgressRestoring">Restoring...</string>
@@ -35,9 +35,9 @@
 	<string name="LoginAttempt">Previous login attempt failed. Logging in, attempt [NUMBER]</string>
 	<string name="LoginPrecaching">Loading world...</string>
 	<string name="LoginInitializingBrowser">Initializing embedded web browser...</string>
-  <string name="LoginInitializingMultimedia">Initializing multimedia...</string>
-  <string name="LoginInitializingFonts">Loading fonts...</string>
-  <string name="LoginVerifyingCache">Verifying cache files (can take 60-90 seconds)...</string>
+	<string name="LoginInitializingMultimedia">Initializing multimedia...</string>
+	<string name="LoginInitializingFonts">Loading fonts...</string>
+	<string name="LoginVerifyingCache">Verifying cache files (can take 60-90 seconds)...</string>
 	<string name="LoginProcessingResponse">Processing response...</string>
 	<string name="LoginInitializingWorld">Initializing world...</string>
 	<string name="LoginDecodingImages">Decoding images...</string>
@@ -49,12 +49,12 @@
 	<string name="LoginWaitingForRegionHandshake">Waiting for region handshake...</string>
 	<string name="LoginConnectingToRegion">Connecting to region...</string>
 	<string name="LoginDownloadingClothing">Downloading clothing...</string>
-        <string name="InvalidCertificate">The server returned an invalid or corrupt certificate. Please contact the Grid administrator.</string>
-        <string name="CertInvalidHostname">An invalid hostname was used to access the server, please check your SLURL or Grid hostname.</string>
-        <string name="CertExpired">The certificate returned by the Grid appears to be expired.  Please check your system clock, or contact your Grid administrator.</string>
-        <string name="CertKeyUsage">The certificate returned by the server could not be used for SSL.  Please contact your Grid administrator.</string>
-        <string name="CertBasicConstraints">Too many certificates were in the servers Certificate chain.  Please contact your Grid administrator.</string>
-        <string name="CertInvalidSignature">The certificate signature returned by the Grid server could not be verified.  Please contact your Grid administrator.</string>
+	<string name="InvalidCertificate">The server returned an invalid or corrupt certificate. Please contact the Grid administrator.</string>
+	<string name="CertInvalidHostname">An invalid hostname was used to access the server, please check your SLURL or Grid hostname.</string>
+	<string name="CertExpired">The certificate returned by the Grid appears to be expired.  Please check your system clock, or contact your Grid administrator.</string>
+	<string name="CertKeyUsage">The certificate returned by the server could not be used for SSL.  Please contact your Grid administrator.</string>
+	<string name="CertBasicConstraints">Too many certificates were in the servers Certificate chain.  Please contact your Grid administrator.</string>
+	<string name="CertInvalidSignature">The certificate signature returned by the Grid server could not be verified.  Please contact your Grid administrator.</string>
 
 	<string name="LoginFailedNoNetwork">Network error: Could not establish connection, please check your network connection.</string>
 	<string name="LoginFailed">Login failed.</string>
@@ -165,6 +165,7 @@ Please try logging in again in a minute.</string>
 	<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
 	<string name="TooltipPrice" value="L$[AMOUNT]: "/>
 
+	<string name="TooltipOutboxDragToWorld">You can not rez items in your merchant outbox</string>
 	<string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred.</string>
 	<string name="TooltipOutboxNotInInventory">Your merchant outbox can only accept items directly from your inventory</string>
 	<string name="TooltipOutboxWorn">You can not put items you are wearing into your merchant outbox</string>
-- 
cgit v1.2.3


From c4a08e6c9d9f044532fcfd4eeeb8934f2c1f3dda Mon Sep 17 00:00:00 2001
From: callum <none@none>
Date: Mon, 9 Jan 2012 14:42:34 -0800
Subject: EXP-1511 FIX Preview image overlays ui elements in Upload image
 floater

---
 indra/newview/llfloaterimagepreview.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index 69de15d9ea..cc279049ca 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -63,6 +63,7 @@
 const S32 PREVIEW_BORDER_WIDTH = 2;
 const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
 const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
+const S32 PREVIEW_VPAD = 32;	// yuk, hard coded
 const S32 PREF_BUTTON_HEIGHT = 16 + 7 + 16;
 const S32 PREVIEW_TEXTURE_HEIGHT = 320;
 
@@ -99,7 +100,7 @@ BOOL LLFloaterImagePreview::postBuild()
 	childSetCommitCallback("clothing_type_combo", onPreviewTypeCommit, this);
 
 	mPreviewRect.set(PREVIEW_HPAD, 
-		PREVIEW_TEXTURE_HEIGHT,
+		PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD,
 		getRect().getWidth() - PREVIEW_HPAD, 
 		PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
 	mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f);
@@ -271,13 +272,13 @@ void LLFloaterImagePreview::draw()
 			gGL.begin( LLRender::QUADS );
 			{
 				gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mTop);
-				gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
+				gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
 				gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mBottom);
 				gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
 				gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mBottom);
 				gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
 				gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mTop);
-				gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
+				gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
 			}
 			gGL.end();
 
-- 
cgit v1.2.3


From a47e9bd97b9855ca8bb3309a73d33d9ae593fd7d Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Tue, 10 Jan 2012 16:35:36 +0200
Subject: EXP-1525 FIXED Potential fix for a crash at shutdown: added some
 error handling to saving inventory cache.

---
 indra/llcommon/llsys.cpp         | 18 ++++++++++++++----
 indra/newview/llinventorymodel.h |  1 +
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 19075afa68..6073bcd0a6 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -1364,11 +1364,21 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
 	src = LLFile::fopen(srcfile, "rb");		/* Flawfinder: ignore */
 	if (! src) goto err;
 
-	do
+	while ((bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE, src)) > 0)
 	{
-		bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE,src);
-		gzwrite(dst, buffer, bytes);
-	} while(feof(src) == 0);
+		if (gzwrite(dst, buffer, bytes) <= 0)
+		{
+			llwarns << "gzwrite failed: " << gzerror(dst, NULL) << llendl;
+			goto err;
+		}
+	}
+
+	if (ferror(src))
+	{
+		llwarns << "Error reading " << srcfile << llendl;
+		goto err;
+	}
+
 	gzclose(dst);
 	dst = NULL;
 #if LL_WINDOWS
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 340c1b0c22..f36ae50272 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -64,6 +64,7 @@ class LLInventoryCollectFunctor;
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 class LLInventoryModel
 {
+	LOG_CLASS(LLInventoryModel);
 public:
 	friend class LLInventoryModelFetchDescendentsResponder;
 
-- 
cgit v1.2.3


From 0434771b043a96b44a99db6acfdec232806f2331 Mon Sep 17 00:00:00 2001
From: Seth ProductEngine <slitovchuk@productengine.com>
Date: Tue, 10 Jan 2012 17:20:49 +0200
Subject: EXP-1766 FIXED Disabled updating agent AFK state if the viewer is
 disconnected. Possible crash fix.

---
 indra/newview/llviewerwindow.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index b73be4ed43..4499955dec 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1206,7 +1206,8 @@ void LLViewerWindow::handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask
 
 	mWindow->showCursorFromMouseMove();
 
-	if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME)
+	if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME
+		&& !gDisconnected)
 	{
 		gAgent.clearAFK();
 	}
-- 
cgit v1.2.3


From 7bc4085eb2275c84eb482ba1f5b8426f1ac6ba5f Mon Sep 17 00:00:00 2001
From: Jonathan Yap <none@none>
Date: Tue, 10 Jan 2012 12:03:20 -0500
Subject: STORM-1788 Clarify wording in About Land->Access and tooltips (and
 similar Estate panel)

---
 doc/contributions.txt                              |  1 +
 indra/newview/llfloaterland.cpp                    | 21 ------------
 .../skins/default/xui/en/floater_about_land.xml    | 38 ++++++----------------
 .../skins/default/xui/en/panel_region_estate.xml   | 10 +++---
 4 files changed, 16 insertions(+), 54 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 84f399cc89..ee8cbfa9f2 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -607,6 +607,7 @@ Jonathan Yap
 	STORM-1737
 	STORM-1733
 	STORM-1790
+	STORM-1788
 Kadah Coba
 	STORM-1060
 Jondan Lundquist
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index b13a9aab88..05c4903cba 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2475,27 +2475,6 @@ void LLPanelLandAccess::refresh()
 				mListBanned->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix);
 			}
 		}
-		
-		LLCheckBoxWithTBAcess* maturity_checkbox = (LLCheckBoxWithTBAcess*) getChild<LLCheckBoxCtrl>( "public_access");
-		LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
-		if(region)
-		{
-			LLTextBox* maturity_textbox = maturity_checkbox->getTextBox();
-			insert_maturity_into_textbox(maturity_textbox, gFloaterView->getParentFloater(this), getString("allow_public_access"));
-			maturity_checkbox->reshape(maturity_checkbox->getRect().getWidth(), maturity_checkbox->getRect().getHeight(), FALSE);
-		}
-		else
-		{
-			std::string maturity_string = getString("allow_public_access");
-			size_t maturity_pos = maturity_string.find(MATURITY);
-
-			if (maturity_pos != std::string::npos)
-			{
-				maturity_string.replace(maturity_pos, MATURITY.length(), std::string(""));
-			}
-
-			maturity_checkbox->setLabel(maturity_string);
-		}
 
 		if(parcel->getRegionDenyAnonymousOverride())
 		{
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 4772f744ea..0c741f3831 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -1955,36 +1955,18 @@ Only large parcels can be listed in search.
 			 name="access_estate_defined">
 				(Defined by the Estate)
 			</panel.string>
-      <panel.string
-       name="allow_public_access">
-        Allow Public Access ([MATURITY]) (Note: Unchecking this will create ban lines)
-      </panel.string>
             <panel.string
              name="estate_override">
                 One or more of these options is set at the estate level
             </panel.string>
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             height="16"
-             layout="topleft"
-             left="10"
-             name="Limit access to this parcel to:"
-             text_color="White"
-             top="10"
-             width="400">
-                Access To This Parcel
-            </text>
             <check_box
              follows="top|left"
              height="16"
              layout="topleft"
-             left_delta="0"
+             left="8"
              name="public_access"
-             top_pad="5"
-             label_text.valign="center"
-             label_text.v_pad="-2" 
+             label="Allow Public Access (Unchecking this will create ban lines)"
+             top_pad="10" 
              width="278" />
             <text
              type="string"
@@ -1994,28 +1976,28 @@ Only large parcels can be listed in search.
              layout="topleft"
              left_delta="20"
              name="Only Allow"
-             top="49"
+             top="30"
              width="325">
-                Restrict Access to Residents verified by:
+                Allow access only to Residents who:
             </text>
             <check_box
              follows="top|left"
              height="16"
-             label="Payment Information on File [ESTATE_PAYMENT_LIMIT]"
+             label="Have payment Information on File [ESTATE_PAYMENT_LIMIT]"
              layout="topleft"
              left_delta="0"
              name="limit_payment"
-             tool_tip="Ban unidentified Residents."
+             tool_tip="Residents must have payment information on file to access this parcel.  See the [SUPPORT_SITE] for more information."
              top_pad="4"
              width="278" />
             <check_box
              follows="top|left"
              height="16"
-             label="Age Verification [ESTATE_AGE_LIMIT]"
+             label="Have been age-verified [ESTATE_AGE_LIMIT]"
              layout="topleft"
              left_delta="0"
              name="limit_age_verified"
-             tool_tip="Ban Residents who have not verified their age. See the [SUPPORT_SITE] for more information."
+             tool_tip="Residents must be age verified to access this parcel. See the [SUPPORT_SITE] for more information."
              top_pad="4"
              width="278" />
             <check_box
@@ -2025,7 +2007,7 @@ Only large parcels can be listed in search.
              left="8"
              name="GroupCheck"
              tool_tip="Set group in the General tab."
-             top="109"
+             top="89"
              width="278" />
             <check_box
              enabled="false"
diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml
index 6b28639a77..bfd796a62b 100644
--- a/indra/newview/skins/default/xui/en/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml
@@ -134,26 +134,26 @@
      name="Only Allow"
      top_delta="-30"
      width="278">
-        Restrict Access to accounts verified by:
+        Allow access only to Residents who:
     </text>
     <check_box
      follows="top|left"
      height="16"
-     label="Payment Information on File"
+     label="Have payment information on file"
      layout="topleft"
      left_delta="0"
      name="limit_payment"
-     tool_tip="Ban unidentified Residents"
+     tool_tip="Residents must have payment information on file to access this estate.  See the [SUPPORT_SITE] for more information."
      top_pad="2"
      width="278" />
     <check_box
      follows="top|left"
      height="16"
-     label="Age Verification"
+     label="Have been age-verified"
      layout="topleft"
      left_delta="0"
      name="limit_age_verified"
-     tool_tip="Ban Residents who have not verified their age. See the [SUPPORT_SITE] for more information."
+     tool_tip="Residents must be age verified to access this estate. See the [SUPPORT_SITE] for more information."
      top_pad="2"
      width="278" />
 
-- 
cgit v1.2.3


From 9cdfecd9e1d9862d9dbd674faa1e28a793540079 Mon Sep 17 00:00:00 2001
From: callum <none@none>
Date: Tue, 10 Jan 2012 10:40:27 -0800
Subject: EXP-1765 (Add debug info) crash on startup at
 LLWindowWin32::switchContext()

---
 indra/llwindow/llwindowwin32.cpp | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 52c27b6736..954b9f2b15 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1083,6 +1083,37 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
 		return FALSE;
 	}
 
+	// (EXP-1765) dump pixel data to see if there is a pattern that leads to unreproducible crash
+	LL_INFOS("Window") << "--- begin pixel format dump ---" << llendl ;
+	LL_INFOS("Window") << "pixel_format is " << pixel_format << llendl ;
+	LL_INFOS("Window") << "pfd.nSize:            " << pfd.nSize << llendl ;
+	LL_INFOS("Window") << "pfd.nVersion:         " << pfd.nVersion << llendl ;
+	LL_INFOS("Window") << "pfd.dwFlags:          0x" << std::hex << pfd.dwFlags << std::dec << llendl ;
+	LL_INFOS("Window") << "pfd.iPixelType:       " << (int)pfd.iPixelType << llendl ;
+	LL_INFOS("Window") << "pfd.cColorBits:       " << (int)pfd.cColorBits << llendl ;
+	LL_INFOS("Window") << "pfd.cRedBits:         " << (int)pfd.cRedBits << llendl ;
+	LL_INFOS("Window") << "pfd.cRedShift:        " << (int)pfd.cRedShift << llendl ;
+	LL_INFOS("Window") << "pfd.cGreenBits:       " << (int)pfd.cGreenBits << llendl ;
+	LL_INFOS("Window") << "pfd.cGreenShift:      " << (int)pfd.cGreenShift << llendl ;
+	LL_INFOS("Window") << "pfd.cBlueBits:        " << (int)pfd.cBlueBits << llendl ;
+	LL_INFOS("Window") << "pfd.cBlueShift:       " << (int)pfd.cBlueShift << llendl ;
+	LL_INFOS("Window") << "pfd.cAlphaBits:       " << (int)pfd.cAlphaBits << llendl ;
+	LL_INFOS("Window") << "pfd.cAlphaShift:      " << (int)pfd.cAlphaShift << llendl ;
+	LL_INFOS("Window") << "pfd.cAccumBits:       " << (int)pfd.cAccumBits << llendl ;
+	LL_INFOS("Window") << "pfd.cAccumRedBits:    " << (int)pfd.cAccumRedBits << llendl ;
+	LL_INFOS("Window") << "pfd.cAccumGreenBits:  " << (int)pfd.cAccumGreenBits << llendl ;
+	LL_INFOS("Window") << "pfd.cAccumBlueBits:   " << (int)pfd.cAccumBlueBits << llendl ;
+	LL_INFOS("Window") << "pfd.cAccumAlphaBits:  " << (int)pfd.cAccumAlphaBits << llendl ;
+	LL_INFOS("Window") << "pfd.cDepthBits:       " << (int)pfd.cDepthBits << llendl ;
+	LL_INFOS("Window") << "pfd.cStencilBits:     " << (int)pfd.cStencilBits << llendl ;
+	LL_INFOS("Window") << "pfd.cAuxBuffers:      " << (int)pfd.cAuxBuffers << llendl ;
+	LL_INFOS("Window") << "pfd.iLayerType:       " << (int)pfd.iLayerType << llendl ;
+	LL_INFOS("Window") << "pfd.bReserved:        " << (int)pfd.bReserved << llendl ;
+	LL_INFOS("Window") << "pfd.dwLayerMask:      " << pfd.dwLayerMask << llendl ;
+	LL_INFOS("Window") << "pfd.dwVisibleMask:    " << pfd.dwVisibleMask << llendl ;
+	LL_INFOS("Window") << "pfd.dwDamageMask:     " << pfd.dwDamageMask << llendl ;
+	LL_INFOS("Window") << "--- end pixel format dump ---" << llendl ;
+
 	if (pfd.cColorBits < 32)
 	{
 		close();
-- 
cgit v1.2.3


From 16112a32e83c6d67acfffdbe339fa7b7b9dd4be3 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Tue, 10 Jan 2012 20:56:52 +0200
Subject: EXP-1783 FIXED Duplicated/missing IDs in menu_viewer.xml

---
 indra/newview/skins/default/xui/da/menu_viewer.xml |  68 ++++------
 indra/newview/skins/default/xui/de/menu_viewer.xml |  72 ++++------
 indra/newview/skins/default/xui/en/menu_viewer.xml | 147 ++++-----------------
 indra/newview/skins/default/xui/es/menu_viewer.xml |  70 ++++------
 indra/newview/skins/default/xui/fr/menu_viewer.xml |  72 ++++------
 indra/newview/skins/default/xui/it/menu_viewer.xml |  70 ++++------
 indra/newview/skins/default/xui/ja/menu_viewer.xml |  72 ++++------
 indra/newview/skins/default/xui/pl/menu_viewer.xml |  68 ++++------
 indra/newview/skins/default/xui/pt/menu_viewer.xml |  70 ++++------
 indra/newview/skins/default/xui/ru/menu_viewer.xml |  72 ++++------
 indra/newview/skins/default/xui/tr/menu_viewer.xml |  72 ++++------
 indra/newview/skins/default/xui/zh/menu_viewer.xml |  70 ++++------
 12 files changed, 336 insertions(+), 587 deletions(-)

diff --git a/indra/newview/skins/default/xui/da/menu_viewer.xml b/indra/newview/skins/default/xui/da/menu_viewer.xml
index ba18306686..d695cd1f89 100644
--- a/indra/newview/skins/default/xui/da/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/da/menu_viewer.xml
@@ -20,8 +20,6 @@
 			<menu_item_call label="Væk" name="Set Away"/>
 			<menu_item_call label="Optaget" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="Anmod om administrator status" name="Request Admin Options"/>
-		<menu_item_call label="Stop administrator status" name="Leave Admin Options"/>
 		<menu_item_call label="Afslut [APP_NAME]" name="Quit"/>
 	</menu>
 	<menu label="Kommunikér" name="Communicate">
@@ -36,11 +34,10 @@
 		<menu_item_check label="Søg" name="Search"/>
 		<menu_item_call label="Foto" name="Take Snapshot"/>
 		<menu_item_call label="Opret landemærke for dette sted" name="Create Landmark Here"/>
-		<menu label="Profil for sted" name="Land">
-			<menu_item_call label="Profil for sted" name="Place Profile"/>
-			<menu_item_call label="Om land" name="About Land"/>
-			<menu_item_call label="Region/Estate" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="Profil for sted" name="Place Profile"/>
+		<menu_item_call label="Om land" name="About Land"/>
+		<menu_item_call label="Region/Estate" name="Region/Estate"/>
 		<menu_item_call label="Køb dette land" name="Buy Land"/>
 		<menu_item_call label="Mit land" name="My Land"/>
 		<menu label="Vis" name="LandShow">
@@ -56,7 +53,7 @@
 		</menu>
 		<menu_item_call label="Teleport hjem" name="Teleport Home"/>
 		<menu_item_call label="Sæt dette sted som &apos;Hjem&apos;" name="Set Home to Here"/>
-		<menu label="Sol" name="Environment Settings">
+		<menu label="Sol" name="Sun">
 			<menu_item_call label="Solopgang" name="Sunrise"/>
 			<menu_item_call label="Middag" name="Noon"/>
 			<menu_item_call label="Solnedgang" name="Sunset"/>
@@ -155,22 +152,22 @@
 			<menu_item_check label="Vis muse-sigte" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="Gengivelsestyper" name="Rendering Types">
-			<menu_item_check label="Simpel" name="Simple"/>
-			<menu_item_check label="Alpha" name="Alpha"/>
-			<menu_item_check label="Træer" name="Tree"/>
-			<menu_item_check label="Avatarer" name="Character"/>
-			<menu_item_check label="Surface Patch" name="Surface Patch"/>
-			<menu_item_check label="Himmel" name="Sky"/>
-			<menu_item_check label="Vand" name="Water"/>
-			<menu_item_check label="Jord" name="Ground"/>
-			<menu_item_check label="Volume" name="Volume"/>
-			<menu_item_check label="Græs" name="Grass"/>
-			<menu_item_check label="Skyer" name="Clouds"/>
-			<menu_item_check label="Partikler" name="Particles"/>
-			<menu_item_check label="Bump" name="Bump"/>
+			<menu_item_check label="Simpel" name="Rendering Type Simple"/>
+			<menu_item_check label="Alpha" name="Rendering Type Alpha"/>
+			<menu_item_check label="Træer" name="Rendering Type Tree"/>
+			<menu_item_check label="Avatarer" name="Rendering Type Character"/>
+			<menu_item_check label="Surface Patch" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="Himmel" name="Rendering Type Sky"/>
+			<menu_item_check label="Vand" name="Rendering Type Water"/>
+			<menu_item_check label="Jord" name="Rendering Type Ground"/>
+			<menu_item_check label="Volume" name="Rendering Type Volume"/>
+			<menu_item_check label="Græs" name="Rendering Type Grass"/>
+			<menu_item_check label="Skyer" name="Rendering Type Clouds"/>
+			<menu_item_check label="Partikler" name="Rendering Type Particles"/>
+			<menu_item_check label="Bump" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="Gengivelsesegenskaber" name="Rendering Features">
-			<menu_item_check label="UI" name="UI"/>
+			<menu_item_check label="UI" name="ToggleUI"/>
 			<menu_item_check label="Valgte" name="Selected"/>
 			<menu_item_check label="Fremhævede" name="Highlighted"/>
 			<menu_item_check label="Dynamiske teksturer" name="Dynamic Textures"/>
@@ -182,10 +179,7 @@
 		<menu_item_call label="Tøm gruppe cache" name="ClearGroupCache"/>
 		<menu_item_check label="Muse udjævning" name="Mouse Smoothing"/>
 		<menu label="Shortcuts" name="Shortcuts">
-			<menu_item_call label="Billede (L$[COST])..." name="Upload Image"/>
-			<menu_item_check label="Søg" name="Search"/>
 			<menu_item_call label="Frigør taster" name="Release Keys"/>
-			<menu_item_call label="Sæt UI størrelse til standard" name="Set UI Size to Default"/>
 			<menu_item_check label="Vis avanceret menu (gammel genvej)" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Luk vindue" name="Close Window"/>
 			<menu_item_call label="Luk alle vinduer" name="Close All Windows"/>
@@ -194,13 +188,6 @@
 			<menu_item_check label="&quot;Joystick Flycam&quot;" name="Joystick Flycam"/>
 			<menu_item_call label="Nulstil udsyn" name="Reset View"/>
 			<menu_item_call label="Se på den sidste der chattede" name="Look at Last Chatter"/>
-			<menu label="Vælg byggeværktøj" name="Select Tool">
-				<menu_item_call label="Fokuseringsværktøj" name="Focus"/>
-				<menu_item_call label="Flyt værktøj" name="Move"/>
-				<menu_item_call label="Redigeringsværktøj" name="Edit"/>
-				<menu_item_call label="Opret værktøj" name="Create"/>
-				<menu_item_call label="Land værktøj" name="Land"/>
-			</menu>
 			<menu_item_call label="Zoom ind" name="Zoom In"/>
 			<menu_item_call label="Zoom standard" name="Zoom Default"/>
 			<menu_item_call label="Zoom ud" name="Zoom Out"/>
@@ -276,9 +263,8 @@
 			<menu_item_call label="Mist en netværkspakke" name="Drop a Packet"/>
 		</menu>
 		<menu_item_call label="Stød, skub &amp; slag" name="Bumps, Pushes &amp;amp; Hits"/>
-		<menu label="Verden" name="World">
+		<menu label="Verden" name="DevelopWorld">
 			<menu_item_check label="Vælg anden sol end region" name="Sim Sun Override"/>
-			<menu_item_check label="Pejlelys blink effekt" name="Cheesy Beacon"/>
 			<menu_item_check label="Fast vejr" name="Fixed Weather"/>
 			<menu_item_call label="Dump Region Object Cache" name="Dump Region Object Cache"/>
 		</menu>
@@ -300,11 +286,11 @@
 		</menu>
 		<menu label="Avatar" name="Character">
 			<menu label="Grab Baked Texture" name="Grab Baked Texture">
-				<menu_item_call label="Iris" name="Iris"/>
-				<menu_item_call label="Hovede" name="Head"/>
-				<menu_item_call label="Overkrop" name="Upper Body"/>
-				<menu_item_call label="Underkrop" name="Lower Body"/>
-				<menu_item_call label="Nederdel" name="Skirt"/>
+				<menu_item_call label="Iris" name="Grab Iris"/>
+				<menu_item_call label="Hovede" name="Grab Head"/>
+				<menu_item_call label="Overkrop" name="Grab Upper Body"/>
+				<menu_item_call label="Underkrop" name="Grab Lower Body"/>
+				<menu_item_call label="Nederdel" name="Grab Skirt"/>
 			</menu>
 			<menu label="Avatar tests" name="Character Tests">
 				<menu_item_call label="Skift avatar geometri" name="Toggle Character Geometry"/>
@@ -326,8 +312,8 @@
 		<menu_item_check label="Vis administrationsmenu" name="View Admin Options"/>
 	</menu>
 	<menu label="Administrér" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="Tag kopi" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="Tag kopi" name="Admin Take Copy"/>
 			<menu_item_call label="Gennemtving ejer til mig" name="Force Owner To Me"/>
 			<menu_item_call label="Gennemtving ejer tolerance" name="Force Owner Permissive"/>
 			<menu_item_call label="Slet" name="Delete"/>
diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml
index 90b2cfbc41..2341293804 100644
--- a/indra/newview/skins/default/xui/de/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/de/menu_viewer.xml
@@ -19,8 +19,6 @@
 			<menu_item_call label="Abwesend" name="Set Away"/>
 			<menu_item_call label="Beschäftigt" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="Admin-Status anfordern" name="Request Admin Options"/>
-		<menu_item_call label="Admin-Status verlassen" name="Leave Admin Options"/>
 		<menu_item_call label="L$ kaufen" name="Buy and Sell L$"/>
 		<menu_item_call label="Einstellungen..." name="Preferences"/>
 		<menu_item_call label="Symbolleisten..." name="Toolbars"/>
@@ -40,11 +38,10 @@
 		<menu_item_check label="Suchen" name="Search"/>
 		<menu_item_call label="Foto" name="Take Snapshot"/>
 		<menu_item_call label="Landmarke für diesen Ort setzen" name="Create Landmark Here"/>
-		<menu label="Ortsprofil" name="Land">
-			<menu_item_call label="Ortsprofil" name="Place Profile"/>
-			<menu_item_call label="Land-Info" name="About Land"/>
-			<menu_item_call label="Region/Grundbesitz" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="Ortsprofil" name="Place Profile"/>
+		<menu_item_call label="Land-Info" name="About Land"/>
+		<menu_item_call label="Region/Grundbesitz" name="Region/Estate"/>
 		<menu_item_call label="Dieses Land kaufen" name="Buy Land"/>
 		<menu_item_call label="Mein Land" name="My Land"/>
 		<menu label="Anzeigen" name="LandShow">
@@ -60,14 +57,14 @@
 		</menu>
 		<menu_item_call label="Teleport nach Hause" name="Teleport Home"/>
 		<menu_item_call label="Hier als Zuhause wählen" name="Set Home to Here"/>
-		<menu label="Sonne" name="Environment Settings">
+		<menu label="Sonne" name="Sun">
 			<menu_item_call label="Sonnenaufgang" name="Sunrise"/>
 			<menu_item_call label="Mittag" name="Noon"/>
 			<menu_item_call label="Sonnenuntergang" name="Sunset"/>
 			<menu_item_call label="Mitternacht" name="Midnight"/>
 		</menu>
 		<menu label="Umgebungs-Editor" name="Enviroment Editor">
-			<menu_item_call label="Umgebungseinstellungen..." name="Enviroment Settings"/>
+			<menu_item_call label="Umgebungseinstellungen..." name="Environment Settings"/>
 			<menu label="Wasser-Voreinstellungen" name="Water Presets">
 				<menu_item_call label="Neue Voreinstellung..." name="new_water_preset"/>
 				<menu_item_call label="Voreinstellung bearbeiten..." name="edit_water_preset"/>
@@ -173,22 +170,22 @@
 			<menu_item_check label="Fadenkreuz für Mouselook anzeigen" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="Darstellungstypen" name="Rendering Types">
-			<menu_item_check label="Einfach" name="Simple"/>
-			<menu_item_check label="Alpha" name="Alpha"/>
-			<menu_item_check label="Baum" name="Tree"/>
-			<menu_item_check label="Avatare" name="Character"/>
-			<menu_item_check label="Flächenpatch" name="Surface Patch"/>
-			<menu_item_check label="Himmel" name="Sky"/>
-			<menu_item_check label="Wasser" name="Water"/>
-			<menu_item_check label="Boden" name="Ground"/>
-			<menu_item_check label="Volumen" name="Volume"/>
-			<menu_item_check label="Gras" name="Grass"/>
-			<menu_item_check label="Wolken" name="Clouds"/>
-			<menu_item_check label="Partikel" name="Particles"/>
-			<menu_item_check label="Unebenheiten" name="Bump"/>
+			<menu_item_check label="Einfach" name="Rendering Type Simple"/>
+			<menu_item_check label="Alpha" name="Rendering Type Alpha"/>
+			<menu_item_check label="Baum" name="Rendering Type Tree"/>
+			<menu_item_check label="Avatare" name="Rendering Type Character"/>
+			<menu_item_check label="Flächenpatch" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="Himmel" name="Rendering Type Sky"/>
+			<menu_item_check label="Wasser" name="Rendering Type Water"/>
+			<menu_item_check label="Boden" name="Rendering Type Ground"/>
+			<menu_item_check label="Volumen" name="Rendering Type Volume"/>
+			<menu_item_check label="Gras" name="Rendering Type Grass"/>
+			<menu_item_check label="Wolken" name="Rendering Type Clouds"/>
+			<menu_item_check label="Partikel" name="Rendering Type Particles"/>
+			<menu_item_check label="Unebenheiten" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="Rendering-Eigenschaften" name="Rendering Features">
-			<menu_item_check label="UI" name="UI"/>
+			<menu_item_check label="UI" name="ToggleUI"/>
 			<menu_item_check label="Ausgewählt" name="Selected"/>
 			<menu_item_check label="Farblich hervorgehoben" name="Highlighted"/>
 			<menu_item_check label="Dynamische Texturen" name="Dynamic Textures"/>
@@ -201,10 +198,7 @@
 		<menu_item_call label="Gruppen-Cache löschen" name="ClearGroupCache"/>
 		<menu_item_check label="Weiche Mausbewegung" name="Mouse Smoothing"/>
 		<menu label="Tastaturkürzel" name="Shortcuts">
-			<menu_item_call label="Bild ([COST] L$)..." name="Upload Image"/>
-			<menu_item_check label="Suchen" name="Search"/>
 			<menu_item_call label="Tasten freigeben" name="Release Keys"/>
-			<menu_item_call label="UI-Größe auf Standard setzen" name="Set UI Size to Default"/>
 			<menu_item_check label="Erweitert-Menü anzeigen - veraltetet" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Fenster schließen" name="Close Window"/>
 			<menu_item_call label="Alle Fenster schließen" name="Close All Windows"/>
@@ -213,13 +207,6 @@
 			<menu_item_check label="Joystick-Flycam" name="Joystick Flycam"/>
 			<menu_item_call label="Ansicht zurücksetzen" name="Reset View"/>
 			<menu_item_call label="Letzten Chatter ansehen" name="Look at Last Chatter"/>
-			<menu label="Bauwerkzeug auswählen" name="Select Tool">
-				<menu_item_call label="Fokus-Werkzeug" name="Focus"/>
-				<menu_item_call label="Werkzeug „Bewegen“" name="Move"/>
-				<menu_item_call label="Bearbeiten" name="Edit"/>
-				<menu_item_call label="Werkzeug „Erstellen&quot;" name="Create"/>
-				<menu_item_call label="Land-Werkzeug" name="Land"/>
-			</menu>
 			<menu_item_call label="Hineinzoomen" name="Zoom In"/>
 			<menu_item_call label="Zoom-Standard" name="Zoom Default"/>
 			<menu_item_call label="Wegzoomen" name="Zoom Out"/>
@@ -333,9 +320,8 @@
 			<menu_item_call label="Aufnahme starten" name="Start Record"/>
 			<menu_item_call label="Aufnahme stoppen" name="Stop Record"/>
 		</menu>
-		<menu label="Welt" name="World">
+		<menu label="Welt" name="DevelopWorld">
 			<menu_item_check label="Sonnen-Override für Sim" name="Sim Sun Override"/>
-			<menu_item_check label="Pulsierender Strahl" name="Cheesy Beacon"/>
 			<menu_item_check label="Festgelegtes Wetter" name="Fixed Weather"/>
 			<menu_item_call label="Regionsobjekt-Cache ausgeben" name="Dump Region Object Cache"/>
 		</menu>
@@ -367,11 +353,11 @@
 		</menu>
 		<menu label="Avatar" name="Character">
 			<menu label="Geladene Textur nehmen" name="Grab Baked Texture">
-				<menu_item_call label="Iris" name="Iris"/>
-				<menu_item_call label="Kopf" name="Head"/>
-				<menu_item_call label="Oberkörper" name="Upper Body"/>
-				<menu_item_call label="Unterkörper" name="Lower Body"/>
-				<menu_item_call label="Rock" name="Skirt"/>
+				<menu_item_call label="Iris" name="Grab Iris"/>
+				<menu_item_call label="Kopf" name="Grab Head"/>
+				<menu_item_call label="Oberkörper" name="Grab Upper Body"/>
+				<menu_item_call label="Unterkörper" name="Grab Lower Body"/>
+				<menu_item_call label="Rock" name="Grab Skirt"/>
 			</menu>
 			<menu label="Avatar-Tests" name="Character Tests">
 				<menu_item_call label="Aussehen als XML speichern" name="Appearance To XML"/>
@@ -406,8 +392,8 @@
 		<menu_item_check label="Admin-Menü anzeigen" name="View Admin Options"/>
 	</menu>
 	<menu label="Admin" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="Kopie nehmen" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="Kopie nehmen" name="Admin Take Copy"/>
 			<menu_item_call label="Besitzer zu mir zwingen" name="Force Owner To Me"/>
 			<menu_item_call label="Erlaubnis des Besitzers erzwingen" name="Force Owner Permissive"/>
 			<menu_item_call label="Löschen" name="Delete"/>
@@ -443,7 +429,7 @@
 			<menu_item_call label="Physik" name="Physics"/>
 			<menu_item_call label="Alle Kleider" name="All Clothes"/>
 		</menu>
-		<menu label="Hilfe" name="Help">
+		<menu label="Hilfe" name="DeprecatedHelp">
 			<menu_item_call label="Offizielles Linden-Blog" name="Official Linden Blog"/>
 			<menu_item_call label="Scripting-Portal" name="Scripting Portal"/>
 			<menu label="Fehlermeldungen" name="Bug Reporting">
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 7d0ab33b66..3767560044 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -118,7 +118,7 @@
         </menu_item_call>
         <menu_item_call
          label="Walk / run / fly..."
-         name="Stop Animating My Avatar">
+         name="Walk / run / fly">
           <menu_item_call.on_click
            function="Floater.ToggleOrBringToFront"
            parameter="moveview" />
@@ -144,23 +144,6 @@
         </menu_item_call>
       </menu>
 
-      <menu_item_call
-       label="Request Admin Status"
-       name="Request Admin Options"
-       shortcut="control|alt|G"
-       visible="false">
-        <menu_item_call.on_click
-         function="Advanced.RequestAdminStatus" />
-      </menu_item_call>
-      <menu_item_call
-       label="Leave Admin Status"
-       name="Leave Admin Options"
-       shortcut="control|alt|shift|G"
-       visible="false">
-        <menu_item_call.on_click
-         function="Advanced.LeaveAdminStatus" />
-      </menu_item_call>
-
       <menu_item_separator/>
 
       <menu_item_call
@@ -525,7 +508,7 @@
         <menu
          create_jump_keys="true"
          label="Sun"
-         name="Environment Settings"
+         name="Sun"
          tear_off="true">
             <menu_item_call
              label="Sunrise"
@@ -1452,7 +1435,7 @@
          tear_off="true">
             <menu_item_check
              label="Simple"
-             name="Simple"
+             name="Rendering Type Simple"
              shortcut="control|alt|shift|1">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1463,7 +1446,7 @@
             </menu_item_check>
             <menu_item_check
              label="Alpha"
-             name="Alpha"
+             name="Rendering Type Alpha"
              shortcut="control|alt|shift|2">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1474,7 +1457,7 @@
             </menu_item_check>
             <menu_item_check
              label="Tree"
-             name="Tree"
+             name="Rendering Type Tree"
              shortcut="control|alt|shift|3">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1485,7 +1468,7 @@
             </menu_item_check>
             <menu_item_check
              label="Avatars"
-             name="Character"
+             name="Rendering Type Character"
              shortcut="control|alt|shift|4">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1496,7 +1479,7 @@
             </menu_item_check>
             <menu_item_check
              label="Surface Patch"
-             name="Surface Patch"
+             name="Rendering Type Surface Patch"
              shortcut="control|alt|shift|5">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1507,7 +1490,7 @@
             </menu_item_check>
             <menu_item_check
              label="Sky"
-             name="Sky"
+             name="Rendering Type Sky"
              shortcut="control|alt|shift|6">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1518,7 +1501,7 @@
             </menu_item_check>
             <menu_item_check
              label="Water"
-             name="Water"
+             name="Rendering Type Water"
              shortcut="control|alt|shift|7">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1529,7 +1512,7 @@
             </menu_item_check>
             <menu_item_check
              label="Ground"
-             name="Ground"
+             name="Rendering Type Ground"
              shortcut="control|alt|shift|8">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1540,7 +1523,7 @@
             </menu_item_check>
             <menu_item_check
              label="Volume"
-             name="Volume"
+             name="Rendering Type Volume"
              shortcut="control|alt|shift|9">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1551,7 +1534,7 @@
             </menu_item_check>
             <menu_item_check
              label="Grass"
-             name="Grass"
+             name="Rendering Type Grass"
              shortcut="control|alt|shift|0">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1562,7 +1545,7 @@
             </menu_item_check>
             <menu_item_check
              label="Clouds"
-             name="Clouds"
+             name="Rendering Type Clouds"
              shortcut="control|alt|shift|-">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1573,7 +1556,7 @@
             </menu_item_check>
             <menu_item_check
              label="Particles"
-             name="Particles"
+             name="Rendering Type Particles"
              shortcut="control|alt|shift|=">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1584,7 +1567,7 @@
             </menu_item_check>
             <menu_item_check
              label="Bump"
-             name="Bump"
+             name="Rendering Type Bump"
              shortcut="control|alt|shift|\">
                 <menu_item_check.on_check
                  function="Advanced.CheckRenderType"
@@ -1601,7 +1584,7 @@
          tear_off="true">
             <menu_item_check
              label="UI"
-             name="UI"
+             name="ToggleUI"
              shortcut="control|alt|F1">
                 <menu_item_check.on_check
                  function="Advanced.CheckFeature"
@@ -1734,28 +1717,6 @@
          name="Shortcuts"
          tear_off="true"
          visible="false">
-          <menu_item_call
-             label="Image (L$[COST])..."
-             name="Upload Image"
-             shortcut="control|U">
-            <menu_item_call.on_click
-               function="File.UploadImage"
-               parameter="" />
-            <menu_item_call.on_enable
-               function="File.EnableUpload" />
-            </menu_item_call>
-            <menu_item_check
-               label="Search"
-               name="Search"
-               shortcut="control|F">
-            <menu_item_check.on_check
-             function="Floater.Visible"
-             parameter="search" />
-            <menu_item_check.on_click
-             function="Floater.Toggle"
-             parameter="search" />
-            </menu_item_check>
-
             <!-- This second, alternative shortcut for Show Advanced Menu is for backward compatibility.  The main shortcut has been changed so it's Linux-friendly, where the old shortcut is typically eaten by the window manager. -->
             <menu_item_check
                label="Show Advanced Menu - legacy shortcut"
@@ -1842,55 +1803,6 @@
 
             <menu_item_separator/>
 
-            <menu
-             create_jump_keys="true"
-             label="Select Build Tool"
-             name="Select Tool"
-             tear_off="true">
-                <menu_item_call
-                 label="Focus Tool"
-                 name="Focus"
-                 shortcut="control|1">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="focus" />
-                </menu_item_call>
-                <menu_item_call
-                 label="Move Tool"
-                 name="Move"
-                 shortcut="control|2">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="move" />
-                </menu_item_call>
-                <menu_item_call
-                 label="Edit Tool"
-                 name="Edit"
-                 shortcut="control|3">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="edit" />
-                </menu_item_call>
-                <menu_item_call
-                 label="Create Tool"
-                 name="Create"
-                 shortcut="control|4">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="create" />
-                </menu_item_call>
-                <menu_item_call
-                 label="Land Tool"
-                 name="Land"
-                 shortcut="control|5">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="land" />
-                </menu_item_call>
-            </menu>
-
-            <menu_item_separator/>
-
             <menu_item_call
              label="Zoom In"
              name="Zoom In"
@@ -2853,7 +2765,7 @@
         <menu
          create_jump_keys="true"
          label="World"
-         name="World"
+         name="DevelopWorld"
          tear_off="true">
             <menu_item_check
              label="Sim Sun Override"
@@ -2865,16 +2777,6 @@
                  function="ToggleControl"
                  parameter="SkyOverrideSimSunPosition" />
             </menu_item_check>
-            <menu_item_check
-             label="Cheesy Beacon"
-             name="Cheesy Beacon">
-                <menu_item_check.on_check
-                 function="CheckControl"
-                 parameter="CheesyBeacon" />
-                <menu_item_check.on_click
-                 function="ToggleControl"
-                 parameter="CheesyBeacon" />
-            </menu_item_check>
             <menu_item_check
              label="Fixed Weather"
              name="Fixed Weather">
@@ -3099,7 +3001,7 @@
              tear_off="true">
                 <menu_item_call
                  label="Iris"
-                 name="Iris">
+                 name="Grab Iris">
                     <menu_item_call.on_click
                      function="Advanced.GrabBakedTexture"
                      parameter="iris" />
@@ -3109,7 +3011,7 @@
                 </menu_item_call>
                 <menu_item_call
                  label="Head"
-                 name="Head">
+                 name="Grab Head">
                     <menu_item_call.on_click
                      function="Advanced.GrabBakedTexture"
                      parameter="head" />
@@ -3119,7 +3021,7 @@
                 </menu_item_call>
                 <menu_item_call
                  label="Upper Body"
-                 name="Upper Body">
+                 name="Grab Upper Body">
                     <menu_item_call.on_click
                      function="Advanced.GrabBakedTexture"
                      parameter="upper" />
@@ -3129,7 +3031,7 @@
                 </menu_item_call>
                 <menu_item_call
                  label="Lower Body"
-                 name="Lower Body">
+                 name="Grab Lower Body">
                     <menu_item_call.on_click
                      function="Advanced.GrabBakedTexture"
                      parameter="lower" />
@@ -3139,7 +3041,7 @@
                 </menu_item_call>
                 <menu_item_call
                  label="Skirt"
-                 name="Skirt">
+                 name="Grab Skirt">
                     <menu_item_call.on_click
                      function="Advanced.GrabBakedTexture"
                      parameter="skirt" />
@@ -3407,10 +3309,11 @@
         <menu
          create_jump_keys="true"
          label="Object"
+         name="AdminObject"
          tear_off="true">
             <menu_item_call
              label="Take Copy"
-             name="Take Copy"
+             name="Admin Take Copy"
              shortcut="control|alt|shift|O">
                 <menu_item_call.on_click
                  function="Admin.ForceTakeCopy" />
@@ -3679,7 +3582,7 @@
         <menu
          create_jump_keys="true"
          label="Help"
-         name="Help"
+         name="DeprecatedHelp"
          tear_off="true">
             <menu_item_call
              label="Official Linden Blog"
diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml
index f5cc2b9389..635ed58a6f 100644
--- a/indra/newview/skins/default/xui/es/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/es/menu_viewer.xml
@@ -19,8 +19,6 @@
 			<menu_item_call label="Ausente" name="Set Away"/>
 			<menu_item_call label="Ocupado" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="Solicitar estatus de Administrador" name="Request Admin Options"/>
-		<menu_item_call label="Dejar el estatus de Administrador" name="Leave Admin Options"/>
 		<menu_item_call label="Comprar L$" name="Buy and Sell L$"/>
 		<menu_item_call label="Preferencias..." name="Preferences"/>
 		<menu_item_call label="Barras de herramientas..." name="Toolbars"/>
@@ -40,11 +38,10 @@
 		<menu_item_check label="Buscar" name="Search"/>
 		<menu_item_call label="Foto" name="Take Snapshot"/>
 		<menu_item_call label="Crear un hito de este sitio" name="Create Landmark Here"/>
-		<menu label="Perfil del lugar" name="Land">
-			<menu_item_call label="Perfil del lugar" name="Place Profile"/>
-			<menu_item_call label="Acerca del terreno" name="About Land"/>
-			<menu_item_call label="Región/Estado" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="Perfil del lugar" name="Place Profile"/>
+		<menu_item_call label="Acerca del terreno" name="About Land"/>
+		<menu_item_call label="Región/Estado" name="Region/Estate"/>
 		<menu_item_call label="Comprar este terreno" name="Buy Land"/>
 		<menu_item_call label="Mi terreno" name="My Land"/>
 		<menu label="Mostrar" name="LandShow">
@@ -60,14 +57,14 @@
 		</menu>
 		<menu_item_call label="Teleportar a la Base" name="Teleport Home"/>
 		<menu_item_call label="Fijar mi Base aquí" name="Set Home to Here"/>
-		<menu label="Sol" name="Environment Settings">
+		<menu label="Sol" name="Sun">
 			<menu_item_call label="Amanecer" name="Sunrise"/>
 			<menu_item_call label="Mediodía" name="Noon"/>
 			<menu_item_call label="Atardecer" name="Sunset"/>
 			<menu_item_call label="Medianoche" name="Midnight"/>
 		</menu>
 		<menu label="Editor de entorno" name="Enviroment Editor">
-			<menu_item_call label="Configuración de entorno..." name="Enviroment Settings"/>
+			<menu_item_call label="Configuración de entorno..." name="Environment Settings"/>
 			<menu label="Agua predefinida" name="Water Presets">
 				<menu_item_call label="Nuevo predefinido..." name="new_water_preset"/>
 				<menu_item_call label="Editar predefinido..." name="edit_water_preset"/>
@@ -173,22 +170,22 @@
 			<menu_item_check label="Mostrar el Punto de Mira en la vista subjetiva" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="Objetos representados" name="Rendering Types">
-			<menu_item_check label="Simple" name="Simple"/>
-			<menu_item_check label="Alfa" name="Alpha"/>
-			<menu_item_check label="Árbol" name="Tree"/>
-			<menu_item_check label="Avatares" name="Character"/>
-			<menu_item_check label="Parche de superficie" name="Surface Patch"/>
-			<menu_item_check label="Cielo" name="Sky"/>
-			<menu_item_check label="Agua" name="Water"/>
-			<menu_item_check label="Terreno" name="Ground"/>
-			<menu_item_check label="volumen" name="Volume"/>
-			<menu_item_check label="Hierba" name="Grass"/>
-			<menu_item_check label="Nubes" name="Clouds"/>
-			<menu_item_check label="Partículas" name="Particles"/>
-			<menu_item_check label="Efectos de relieve" name="Bump"/>
+			<menu_item_check label="Simple" name="Rendering Type Simple"/>
+			<menu_item_check label="Alfa" name="Rendering Type Alpha"/>
+			<menu_item_check label="Árbol" name="Rendering Type Tree"/>
+			<menu_item_check label="Avatares" name="Rendering Type Character"/>
+			<menu_item_check label="Parche de superficie" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="Cielo" name="Rendering Type Sky"/>
+			<menu_item_check label="Agua" name="Rendering Type Water"/>
+			<menu_item_check label="Terreno" name="Rendering Type Ground"/>
+			<menu_item_check label="volumen" name="Rendering Type Volume"/>
+			<menu_item_check label="Hierba" name="Rendering Type Grass"/>
+			<menu_item_check label="Nubes" name="Rendering Type Clouds"/>
+			<menu_item_check label="Partículas" name="Rendering Type Particles"/>
+			<menu_item_check label="Efectos de relieve" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="Rasgos renderizados" name="Rendering Features">
-			<menu_item_check label="UI" name="UI"/>
+			<menu_item_check label="UI" name="ToggleUI"/>
 			<menu_item_check label="Seleccionado" name="Selected"/>
 			<menu_item_check label="Realzados" name="Highlighted"/>
 			<menu_item_check label="Texturas dinámicas" name="Dynamic Textures"/>
@@ -200,10 +197,7 @@
 		<menu_item_call label="Vaciar la caché de grupo" name="ClearGroupCache"/>
 		<menu_item_check label="Vista subjetiva suavizada" name="Mouse Smoothing"/>
 		<menu label="Atajos de teclado" name="Shortcuts">
-			<menu_item_call label="Imagen ([COST] L$)..." name="Upload Image"/>
-			<menu_item_check label="Buscar" name="Search"/>
 			<menu_item_call label="Recuperar las teclas" name="Release Keys"/>
-			<menu_item_call label="Interfaz en el tamaño predeterminado" name="Set UI Size to Default"/>
 			<menu_item_check label="Mostrar el menú Avanzado - acceso directo antiguo" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Cerrar la ventana" name="Close Window"/>
 			<menu_item_call label="Cerrar todas las ventanas" name="Close All Windows"/>
@@ -212,13 +206,6 @@
 			<menu_item_check label="Flycam del joystick" name="Joystick Flycam"/>
 			<menu_item_call label="Volver a la vista por defecto" name="Reset View"/>
 			<menu_item_call label="Mirar al último que habló" name="Look at Last Chatter"/>
-			<menu label="Seleccionar la herramienta de construcción" name="Select Tool">
-				<menu_item_call label="Herramienta Visión" name="Focus"/>
-				<menu_item_call label="Herramienta Mover" name="Move"/>
-				<menu_item_call label="Herramienta Editar" name="Edit"/>
-				<menu_item_call label="Herramienta Crear" name="Create"/>
-				<menu_item_call label="Herramienta Terreno" name="Land"/>
-			</menu>
 			<menu_item_call label="Acercar el zoom" name="Zoom In"/>
 			<menu_item_call label="Zoom por defecto" name="Zoom Default"/>
 			<menu_item_call label="Alejar el zoom" name="Zoom Out"/>
@@ -296,9 +283,8 @@
 			<menu_item_call label="Drop a Packet" name="Drop a Packet"/>
 		</menu>
 		<menu_item_call label="Bumps, Pushes &amp; Hits" name="Bumps, Pushes &amp;amp; Hits"/>
-		<menu label="World" name="World">
+		<menu label="World" name="DevelopWorld">
 			<menu_item_check label="Region Sun Override" name="Sim Sun Override"/>
-			<menu_item_check label="Beacon flashing effect" name="Cheesy Beacon"/>
 			<menu_item_check label="Fixed Weather" name="Fixed Weather"/>
 			<menu_item_call label="Dump Region Object Cache" name="Dump Region Object Cache"/>
 		</menu>
@@ -320,11 +306,11 @@
 		</menu>
 		<menu label="Avatar" name="Character">
 			<menu label="Grab Baked Texture" name="Grab Baked Texture">
-				<menu_item_call label="Iris" name="Iris"/>
-				<menu_item_call label="Head" name="Head"/>
-				<menu_item_call label="Upper Body" name="Upper Body"/>
-				<menu_item_call label="Lower Body" name="Lower Body"/>
-				<menu_item_call label="Skirt" name="Skirt"/>
+				<menu_item_call label="Iris" name="Grab Iris"/>
+				<menu_item_call label="Head" name="Grab Head"/>
+				<menu_item_call label="Upper Body" name="Grab Upper Body"/>
+				<menu_item_call label="Lower Body" name="Grab Lower Body"/>
+				<menu_item_call label="GrabSkirt" name="Grab Skirt"/>
 			</menu>
 			<menu label="Character Tests" name="Character Tests">
 				<menu_item_call label="Toggle Character Geometry" name="Toggle Character Geometry"/>
@@ -346,8 +332,8 @@
 		<menu_item_check label="Show Admin Menu" name="View Admin Options"/>
 	</menu>
 	<menu label="Admin" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="Coger una copia" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="Coger una copia" name="Admin Take Copy"/>
 			<menu_item_call label="Force Owner To Me" name="Force Owner To Me"/>
 			<menu_item_call label="Force Owner Permissive" name="Force Owner Permissive"/>
 			<menu_item_call label="Eliminar" name="Delete"/>
diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml
index d3b48639e0..1640026c9d 100644
--- a/indra/newview/skins/default/xui/fr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml
@@ -19,8 +19,6 @@
 			<menu_item_call label="Absent" name="Set Away"/>
 			<menu_item_call label="Occupé" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="Demander le statut Admin" name="Request Admin Options"/>
-		<menu_item_call label="Quitter le statut Admin" name="Leave Admin Options"/>
 		<menu_item_call label="Acheter des L$" name="Buy and Sell L$"/>
 		<menu_item_call label="Préférences..." name="Preferences"/>
 		<menu_item_call label="Barres d&apos;outils..." name="Toolbars"/>
@@ -40,11 +38,10 @@
 		<menu_item_check label="Rechercher" name="Search"/>
 		<menu_item_call label="Photo" name="Take Snapshot"/>
 		<menu_item_call label="Créer un repère pour ce lieu" name="Create Landmark Here"/>
-		<menu label="Profil du lieu" name="Land">
-			<menu_item_call label="Profil du lieu" name="Place Profile"/>
-			<menu_item_call label="À propos du terrain" name="About Land"/>
-			<menu_item_call label="Région/Domaine" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="Profil du lieu" name="Place Profile"/>
+		<menu_item_call label="À propos du terrain" name="About Land"/>
+		<menu_item_call label="Région/Domaine" name="Region/Estate"/>
 		<menu_item_call label="Acheter ce terrain" name="Buy Land"/>
 		<menu_item_call label="Mes terrains" name="My Land"/>
 		<menu label="Afficher" name="LandShow">
@@ -60,14 +57,14 @@
 		</menu>
 		<menu_item_call label="Me téléporter chez moi" name="Teleport Home"/>
 		<menu_item_call label="Définir le domicile ici" name="Set Home to Here"/>
-		<menu label="Luminosité" name="Environment Settings">
+		<menu label="Luminosité" name="Sun">
 			<menu_item_call label="Aube" name="Sunrise"/>
 			<menu_item_call label="Milieu de journée" name="Noon"/>
 			<menu_item_call label="Coucher de soleil" name="Sunset"/>
 			<menu_item_call label="Minuit" name="Midnight"/>
 		</menu>
 		<menu label="Éditeur d&apos;environnement" name="Enviroment Editor">
-			<menu_item_call label="Paramètres d&apos;environnement..." name="Enviroment Settings"/>
+			<menu_item_call label="Paramètres d&apos;environnement..." name="Environment Settings"/>
 			<menu label="Préréglages de l&apos;eau" name="Water Presets">
 				<menu_item_call label="Nouveau préréglage..." name="new_water_preset"/>
 				<menu_item_call label="Modifier un préréglage..." name="edit_water_preset"/>
@@ -173,22 +170,22 @@
 			<menu_item_check label="Afficher le réticule de la vue subjective" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="Types de rendu" name="Rendering Types">
-			<menu_item_check label="Simple" name="Simple"/>
-			<menu_item_check label="Alpha" name="Alpha"/>
-			<menu_item_check label="Arbre" name="Tree"/>
-			<menu_item_check label="Avatars" name="Character"/>
-			<menu_item_check label="Patch de surface" name="Surface Patch"/>
-			<menu_item_check label="Ciel" name="Sky"/>
-			<menu_item_check label="Eau" name="Water"/>
-			<menu_item_check label="Sol" name="Ground"/>
-			<menu_item_check label="Volume" name="Volume"/>
-			<menu_item_check label="Herbe" name="Grass"/>
-			<menu_item_check label="Nuages" name="Clouds"/>
-			<menu_item_check label="Particules" name="Particles"/>
-			<menu_item_check label="Placage de relief" name="Bump"/>
+			<menu_item_check label="Simple" name="Rendering Type Simple"/>
+			<menu_item_check label="Alpha" name="Rendering Type Alpha"/>
+			<menu_item_check label="Arbre" name="Rendering Type Tree"/>
+			<menu_item_check label="Avatars" name="Rendering Type Character"/>
+			<menu_item_check label="Patch de surface" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="Ciel" name="Rendering Type Sky"/>
+			<menu_item_check label="Eau" name="Rendering Type Water"/>
+			<menu_item_check label="Sol" name="Rendering Type Ground"/>
+			<menu_item_check label="Volume" name="Rendering Type Volume"/>
+			<menu_item_check label="Herbe" name="Rendering Type Grass"/>
+			<menu_item_check label="Nuages" name="Rendering Type Clouds"/>
+			<menu_item_check label="Particules" name="Rendering Type Particles"/>
+			<menu_item_check label="Placage de relief" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="Fonctionnalités de rendu" name="Rendering Features">
-			<menu_item_check label="Interface" name="UI"/>
+			<menu_item_check label="Interface" name="ToggleUI"/>
 			<menu_item_check label="Sélection" name="Selected"/>
 			<menu_item_check label="En surbrillance" name="Highlighted"/>
 			<menu_item_check label="Textures dynamiques" name="Dynamic Textures"/>
@@ -201,10 +198,7 @@
 		<menu_item_call label="Effacer le cache du groupe" name="ClearGroupCache"/>
 		<menu_item_check label="Effet de lissage de la souris" name="Mouse Smoothing"/>
 		<menu label="Raccourcis" name="Shortcuts">
-			<menu_item_call label="Image ([COST] L$)..." name="Upload Image"/>
-			<menu_item_check label="Rechercher" name="Search"/>
 			<menu_item_call label="Relâcher les touches" name="Release Keys"/>
-			<menu_item_call label="Taille de l&apos;interface par défaut" name="Set UI Size to Default"/>
 			<menu_item_check label="Afficher le menu Avancé - raccourci existant" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Fermer la fenêtre" name="Close Window"/>
 			<menu_item_call label="Fermer toutes les fenêtres" name="Close All Windows"/>
@@ -213,13 +207,6 @@
 			<menu_item_check label="Joystick Flycam" name="Joystick Flycam"/>
 			<menu_item_call label="Réinitialiser la vue" name="Reset View"/>
 			<menu_item_call label="Regarder la dernière conversation" name="Look at Last Chatter"/>
-			<menu label="Sélectionner un outil de construction" name="Select Tool">
-				<menu_item_call label="Outil de mise au point" name="Focus"/>
-				<menu_item_call label="Outil de déplacement" name="Move"/>
-				<menu_item_call label="Outil de modification" name="Edit"/>
-				<menu_item_call label="Outil de création" name="Create"/>
-				<menu_item_call label="Outil Terrain" name="Land"/>
-			</menu>
 			<menu_item_call label="Zoomer en avant" name="Zoom In"/>
 			<menu_item_call label="Zoom par défaut" name="Zoom Default"/>
 			<menu_item_call label="Zoomer en arrière" name="Zoom Out"/>
@@ -333,9 +320,8 @@
 			<menu_item_call label="Commencer l&apos;enregistrement" name="Start Record"/>
 			<menu_item_call label="Arrêter l&apos;enregistrement" name="Stop Record"/>
 		</menu>
-		<menu label="Monde" name="World">
+		<menu label="Monde" name="DevelopWorld">
 			<menu_item_check label="Ignorer les paramètres du soleil de la sim" name="Sim Sun Override"/>
-			<menu_item_check label="Balise animée" name="Cheesy Beacon"/>
 			<menu_item_check label="Météo fixe" name="Fixed Weather"/>
 			<menu_item_call label="Vidage de cache d&apos;objet de la région" name="Dump Region Object Cache"/>
 		</menu>
@@ -367,11 +353,11 @@
 		</menu>
 		<menu label="Avatar" name="Character">
 			<menu label="Récupérer la texture fixée" name="Grab Baked Texture">
-				<menu_item_call label="Iris" name="Iris"/>
-				<menu_item_call label="Tête" name="Head"/>
-				<menu_item_call label="Haut du corps" name="Upper Body"/>
-				<menu_item_call label="Bas du corps" name="Lower Body"/>
-				<menu_item_call label="Jupe" name="Skirt"/>
+				<menu_item_call label="Iris" name="Grab Iris"/>
+				<menu_item_call label="Tête" name="Grab Head"/>
+				<menu_item_call label="Haut du corps" name="Grab Upper Body"/>
+				<menu_item_call label="Bas du corps" name="Grab Lower Body"/>
+				<menu_item_call label="Jupe" name="Grab Skirt"/>
 			</menu>
 			<menu label="Tests personnages" name="Character Tests">
 				<menu_item_call label="Apparence dans XML" name="Appearance To XML"/>
@@ -406,8 +392,8 @@
 		<menu_item_check label="Afficher le menu Admin" name="View Admin Options"/>
 	</menu>
 	<menu label="Admin" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="Prendre une copie" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="Prendre une copie" name="Admin Take Copy"/>
 			<menu_item_call label="Téléporter le propriétaire" name="Force Owner To Me"/>
 			<menu_item_call label="Forcer la permission du propriétaire" name="Force Owner Permissive"/>
 			<menu_item_call label="Supprimer" name="Delete"/>
@@ -443,7 +429,7 @@
 			<menu_item_call label="Propriétés physiques" name="Physics"/>
 			<menu_item_call label="Tous les habits" name="All Clothes"/>
 		</menu>
-		<menu label="Aide" name="Help">
+		<menu label="Aide" name="DeprecatedHelp">
 			<menu_item_call label="Blog officiel des Linden" name="Official Linden Blog"/>
 			<menu_item_call label="Portail d&apos;écriture de scripts" name="Scripting Portal"/>
 			<menu label="Signaler des bugs" name="Bug Reporting">
diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml
index 8792a0fc19..2cccd4aa9f 100644
--- a/indra/newview/skins/default/xui/it/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/it/menu_viewer.xml
@@ -19,8 +19,6 @@
 			<menu_item_call label="Assente" name="Set Away"/>
 			<menu_item_call label="Non disponibile" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="Richiedi diritti Admin" name="Request Admin Options"/>
-		<menu_item_call label="Lascia stato Admin" name="Leave Admin Options"/>
 		<menu_item_call label="Compra L$" name="Buy and Sell L$"/>
 		<menu_item_call label="Preferenze..." name="Preferences"/>
 		<menu_item_call label="Barre strumenti..." name="Toolbars"/>
@@ -40,11 +38,10 @@
 		<menu_item_check label="Cerca" name="Search"/>
 		<menu_item_call label="Istantanea" name="Take Snapshot"/>
 		<menu_item_call label="Crea punto di riferimento per questo luogo" name="Create Landmark Here"/>
-		<menu label="Profilo del luogo" name="Land">
-			<menu_item_call label="Profilo del luogo" name="Place Profile"/>
-			<menu_item_call label="Informazioni sui terreni" name="About Land"/>
-			<menu_item_call label="Regione/proprietà immobiliare" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="Profilo del luogo" name="Place Profile"/>
+		<menu_item_call label="Informazioni sui terreni" name="About Land"/>
+		<menu_item_call label="Regione/proprietà immobiliare" name="Region/Estate"/>
 		<menu_item_call label="Acquista questo terreno" name="Buy Land"/>
 		<menu_item_call label="Il mio terreno" name="My Land"/>
 		<menu label="Mostra" name="LandShow">
@@ -60,14 +57,14 @@
 		</menu>
 		<menu_item_call label="Teleport a Casa" name="Teleport Home"/>
 		<menu_item_call label="Imposta come Casa mia" name="Set Home to Here"/>
-		<menu label="Sole" name="Environment Settings">
+		<menu label="Sole" name="Sun">
 			<menu_item_call label="Alba" name="Sunrise"/>
 			<menu_item_call label="Mezzogiorno" name="Noon"/>
 			<menu_item_call label="Tramonto" name="Sunset"/>
 			<menu_item_call label="Mezzanotte" name="Midnight"/>
 		</menu>
 		<menu label="Editor ambiente" name="Enviroment Editor">
-			<menu_item_call label="Impostazioni ambiente..." name="Enviroment Settings"/>
+			<menu_item_call label="Impostazioni ambiente..." name="Environment Settings"/>
 			<menu label="Valori predefiniti acqua" name="Water Presets">
 				<menu_item_call label="Nuovo valore predefinito..." name="new_water_preset"/>
 				<menu_item_call label="Modifica valori predefiniti..." name="edit_water_preset"/>
@@ -173,22 +170,22 @@
 			<menu_item_check label="Mostra mirino visuale soggettiva" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="Modalità di rendering" name="Rendering Types">
-			<menu_item_check label="Semplice" name="Simple"/>
-			<menu_item_check label="Alpha (Trasparenza)" name="Alpha"/>
-			<menu_item_check label="Albero" name="Tree"/>
-			<menu_item_check label="Avatar" name="Character"/>
-			<menu_item_check label="Superficie chiusa" name="Surface Patch"/>
-			<menu_item_check label="Cielo" name="Sky"/>
-			<menu_item_check label="Acqua" name="Water"/>
-			<menu_item_check label="Suolo" name="Ground"/>
-			<menu_item_check label="Volume" name="Volume"/>
-			<menu_item_check label="Erba" name="Grass"/>
-			<menu_item_check label="Nuvole" name="Clouds"/>
-			<menu_item_check label="Particelle" name="Particles"/>
-			<menu_item_check label="Urti" name="Bump"/>
+			<menu_item_check label="Semplice" name="Rendering Type Simple"/>
+			<menu_item_check label="Alpha (Trasparenza)" name="Rendering Type Alpha"/>
+			<menu_item_check label="Albero" name="Rendering Type Tree"/>
+			<menu_item_check label="Avatar" name="Rendering Type Character"/>
+			<menu_item_check label="Superficie chiusa" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="Cielo" name="Rendering Type Sky"/>
+			<menu_item_check label="Acqua" name="Rendering Type Water"/>
+			<menu_item_check label="Suolo" name="Rendering Type Ground"/>
+			<menu_item_check label="Volume" name="Rendering Type Volume"/>
+			<menu_item_check label="Erba" name="Rendering Type Grass"/>
+			<menu_item_check label="Nuvole" name="Rendering Type Clouds"/>
+			<menu_item_check label="Particelle" name="Rendering Type Particles"/>
+			<menu_item_check label="Urti" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="Caratteristiche di rendering" name="Rendering Features">
-			<menu_item_check label="Interfaccia utente" name="UI"/>
+			<menu_item_check label="Interfaccia utente" name="ToggleUI"/>
 			<menu_item_check label="Selezionati" name="Selected"/>
 			<menu_item_check label="Evidenziato" name="Highlighted"/>
 			<menu_item_check label="Texture dinamiche" name="Dynamic Textures"/>
@@ -200,10 +197,7 @@
 		<menu_item_call label="Pulisci cache di gruppo" name="ClearGroupCache"/>
 		<menu_item_check label="Fluidità mouse" name="Mouse Smoothing"/>
 		<menu label="Scorciatoie" name="Shortcuts">
-			<menu_item_call label="Immagine ([COST]L$)..." name="Upload Image"/>
-			<menu_item_check label="Cerca" name="Search"/>
 			<menu_item_call label="Rilascia tasti" name="Release Keys"/>
-			<menu_item_call label="Imposta dimensioni dell&apos;interfaccia sui valori predefiniti" name="Set UI Size to Default"/>
 			<menu_item_check label="Mostra menu Avanzato - tasti di scelta rapida esistenti" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Chiudi finestra" name="Close Window"/>
 			<menu_item_call label="Chiudi tutte le finestre" name="Close All Windows"/>
@@ -212,13 +206,6 @@
 			<menu_item_check label="Joystick Flycam" name="Joystick Flycam"/>
 			<menu_item_call label="Reimposta vista" name="Reset View"/>
 			<menu_item_call label="Guarda l&apos;ultima conversazione" name="Look at Last Chatter"/>
-			<menu label="Seleziona strumento di costruzione" name="Select Tool">
-				<menu_item_call label="Strumento Ingrandisci" name="Focus"/>
-				<menu_item_call label="Strumento Movimento" name="Move"/>
-				<menu_item_call label="Strumento Modifica" name="Edit"/>
-				<menu_item_call label="Strumento Crea" name="Create"/>
-				<menu_item_call label="Strumento Terreno" name="Land"/>
-			</menu>
 			<menu_item_call label="Zoom avanti" name="Zoom In"/>
 			<menu_item_call label="Zoom predefinito" name="Zoom Default"/>
 			<menu_item_call label="Zoom indietro" name="Zoom Out"/>
@@ -296,9 +283,8 @@
 			<menu_item_call label="Lascia un pacchetto" name="Drop a Packet"/>
 		</menu>
 		<menu_item_call label="Urti, spinte e contatti" name="Bumps, Pushes &amp;amp; Hits"/>
-		<menu label="Mondo" name="World">
+		<menu label="Mondo" name="DevelopWorld">
 			<menu_item_check label="Esclusione al sole della regione" name="Sim Sun Override"/>
-			<menu_item_check label="Effetto marcatore lampeggiante" name="Cheesy Beacon"/>
 			<menu_item_check label="Clima fisso" name="Fixed Weather"/>
 			<menu_item_call label="Dump della cache oggetti regione" name="Dump Region Object Cache"/>
 		</menu>
@@ -320,11 +306,11 @@
 		</menu>
 		<menu label="Avatar" name="Character">
 			<menu label="Grab Baked Texture" name="Grab Baked Texture">
-				<menu_item_call label="Iride" name="Iris"/>
-				<menu_item_call label="Testa" name="Head"/>
-				<menu_item_call label="Parte superiore del corpo" name="Upper Body"/>
-				<menu_item_call label="Parte inferiore del corpo" name="Lower Body"/>
-				<menu_item_call label="Gonna" name="Skirt"/>
+				<menu_item_call label="Iride" name="Grab Iris"/>
+				<menu_item_call label="Testa" name="Grab Head"/>
+				<menu_item_call label="Parte superiore del corpo" name="Grab Upper Body"/>
+				<menu_item_call label="Parte inferiore del corpo" name="Grab Lower Body"/>
+				<menu_item_call label="Gonna" name="Grab Skirt"/>
 			</menu>
 			<menu label="Test personaggio" name="Character Tests">
 				<menu_item_call label="Alterna la geometria dei personaggi" name="Toggle Character Geometry"/>
@@ -346,8 +332,8 @@
 		<menu_item_check label="Mostra menu Admin" name="View Admin Options"/>
 	</menu>
 	<menu label="Admin" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="Prendi copia" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="Prendi copia" name="Admin Take Copy"/>
 			<menu_item_call label="Rendimi proprietario" name="Force Owner To Me"/>
 			<menu_item_call label="Forza permesso proprietario" name="Force Owner Permissive"/>
 			<menu_item_call label="Elimina" name="Delete"/>
diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml
index 125e9bb226..1dc25791d3 100644
--- a/indra/newview/skins/default/xui/ja/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml
@@ -19,8 +19,6 @@
 			<menu_item_call label="一時退席中" name="Set Away"/>
 			<menu_item_call label="取り込み中" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="管理者権限のリクエスト" name="Request Admin Options"/>
-		<menu_item_call label="管理者ステータス解除" name="Leave Admin Options"/>
 		<menu_item_call label="L$ の購入" name="Buy and Sell L$"/>
 		<menu_item_call label="環境設定..." name="Preferences"/>
 		<menu_item_call label="ツールバー..." name="Toolbars"/>
@@ -40,11 +38,10 @@
 		<menu_item_check label="検索" name="Search"/>
 		<menu_item_call label="スナップショット" name="Take Snapshot"/>
 		<menu_item_call label="現在地をランドマーク" name="Create Landmark Here"/>
-		<menu label="場所のプロフィール" name="Land">
-			<menu_item_call label="場所のプロフィール" name="Place Profile"/>
-			<menu_item_call label="土地情報" name="About Land"/>
-			<menu_item_call label="地域 / 不動産" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="場所のプロフィール" name="Place Profile"/>
+		<menu_item_call label="土地情報" name="About Land"/>
+		<menu_item_call label="地域 / 不動産" name="Region/Estate"/>
 		<menu_item_call label="この土地を購入" name="Buy Land"/>
 		<menu_item_call label="自分の土地" name="My Land"/>
 		<menu label="表示" name="LandShow">
@@ -60,14 +57,14 @@
 		</menu>
 		<menu_item_call label="ホームにテレポート" name="Teleport Home"/>
 		<menu_item_call label="現在地をホームに設定" name="Set Home to Here"/>
-		<menu label="太陽" name="Environment Settings">
+		<menu label="太陽" name="Sun">
 			<menu_item_call label="日の出" name="Sunrise"/>
 			<menu_item_call label="正午" name="Noon"/>
 			<menu_item_call label="日没" name="Sunset"/>
 			<menu_item_call label="深夜" name="Midnight"/>
 		</menu>
 		<menu label="自然環境エディター" name="Enviroment Editor">
-			<menu_item_call label="環境の設定..." name="Enviroment Settings"/>
+			<menu_item_call label="環境の設定..." name="Environment Settings"/>
 			<menu label="水の事前設定" name="Water Presets">
 				<menu_item_call label="新しい事前設定..." name="new_water_preset"/>
 				<menu_item_call label="事前設定を編集..." name="edit_water_preset"/>
@@ -173,22 +170,22 @@
 			<menu_item_check label="一人称視点のときに十字線を表示する" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="レンダリング(種類)" name="Rendering Types">
-			<menu_item_check label="シンプル" name="Simple"/>
-			<menu_item_check label="アルファ" name="Alpha"/>
-			<menu_item_check label="木" name="Tree"/>
-			<menu_item_check label="アバター" name="Character"/>
-			<menu_item_check label="サーフェスパッチ" name="Surface Patch"/>
-			<menu_item_check label="空" name="Sky"/>
-			<menu_item_check label="水" name="Water"/>
-			<menu_item_check label="地面" name="Ground"/>
-			<menu_item_check label="ボリューム" name="Volume"/>
-			<menu_item_check label="草" name="Grass"/>
-			<menu_item_check label="雲" name="Clouds"/>
-			<menu_item_check label="パーティクル" name="Particles"/>
-			<menu_item_check label="衝突" name="Bump"/>
+			<menu_item_check label="シンプル" name="Rendering Type Simple"/>
+			<menu_item_check label="アルファ" name="Rendering Type Alpha"/>
+			<menu_item_check label="木" name="Rendering Type Tree"/>
+			<menu_item_check label="アバター" name="Rendering Type Character"/>
+			<menu_item_check label="サーフェスパッチ" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="空" name="Rendering Type Sky"/>
+			<menu_item_check label="水" name="Rendering Type Water"/>
+			<menu_item_check label="地面" name="Rendering Type Ground"/>
+			<menu_item_check label="ボリューム" name="Rendering Type Volume"/>
+			<menu_item_check label="草" name="Rendering Type Grass"/>
+			<menu_item_check label="雲" name="Rendering Type Clouds"/>
+			<menu_item_check label="パーティクル" name="Rendering Type Particles"/>
+			<menu_item_check label="衝突" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="レンダリング(機能)" name="Rendering Features">
-			<menu_item_check label="UI" name="UI"/>
+			<menu_item_check label="UI" name="ToggleUI"/>
 			<menu_item_check label="選択済" name="Selected"/>
 			<menu_item_check label="ハイライト" name="Highlighted"/>
 			<menu_item_check label="ダイナミックテクスチャ" name="Dynamic Textures"/>
@@ -201,10 +198,7 @@
 		<menu_item_call label="グループキャッシュのクリア" name="ClearGroupCache"/>
 		<menu_item_check label="マウスの平滑化" name="Mouse Smoothing"/>
 		<menu label="ショートカット" name="Shortcuts">
-			<menu_item_call label="画像 (L$ [COST] )..." name="Upload Image"/>
-			<menu_item_check label="検索" name="Search"/>
 			<menu_item_call label="キーをリリース" name="Release Keys"/>
-			<menu_item_call label="UI のサイズをデフォルトに設定する" name="Set UI Size to Default"/>
 			<menu_item_check label="アドバンスメニューを表示 - レガシーのショートカット" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="ウィンドウを閉じる" name="Close Window"/>
 			<menu_item_call label="全てのウィンドウを閉じる" name="Close All Windows"/>
@@ -213,13 +207,6 @@
 			<menu_item_check label="ジョイスティックフライカム" name="Joystick Flycam"/>
 			<menu_item_call label="表示をリセットする" name="Reset View"/>
 			<menu_item_call label="最後の発言者を見る" name="Look at Last Chatter"/>
-			<menu label="制作ツールを選択する" name="Select Tool">
-				<menu_item_call label="焦点ツール" name="Focus"/>
-				<menu_item_call label="移動ツール" name="Move"/>
-				<menu_item_call label="編集ツール" name="Edit"/>
-				<menu_item_call label="作成ツール" name="Create"/>
-				<menu_item_call label="土地ツール" name="Land"/>
-			</menu>
 			<menu_item_call label="ズームイン" name="Zoom In"/>
 			<menu_item_call label="ズーム(デフォルト)" name="Zoom Default"/>
 			<menu_item_call label="ズームアウト" name="Zoom Out"/>
@@ -333,9 +320,8 @@
 			<menu_item_call label="記録開始" name="Start Record"/>
 			<menu_item_call label="記録停止" name="Stop Record"/>
 		</menu>
-		<menu label="世界" name="World">
+		<menu label="世界" name="DevelopWorld">
 			<menu_item_check label="シムの太陽の設定を無視する" name="Sim Sun Override"/>
-			<menu_item_check label="ビーコンを強調表示する" name="Cheesy Beacon"/>
 			<menu_item_check label="固定された天気" name="Fixed Weather"/>
 			<menu_item_call label="リージョンオブジェクトのキャッシュをダンプする" name="Dump Region Object Cache"/>
 		</menu>
@@ -367,11 +353,11 @@
 		</menu>
 		<menu label="アバター" name="Character">
 			<menu label="ベークドテクスチャを取得する" name="Grab Baked Texture">
-				<menu_item_call label="瞳" name="Iris"/>
-				<menu_item_call label="頭" name="Head"/>
-				<menu_item_call label="上半身" name="Upper Body"/>
-				<menu_item_call label="下半身" name="Lower Body"/>
-				<menu_item_call label="スカート" name="Skirt"/>
+				<menu_item_call label="瞳" name="Grab Iris"/>
+				<menu_item_call label="頭" name="Grab Head"/>
+				<menu_item_call label="上半身" name="Grab Upper Body"/>
+				<menu_item_call label="下半身" name="Grab Lower Body"/>
+				<menu_item_call label="スカート" name="Grab Skirt"/>
 			</menu>
 			<menu label="キャラクターテスト" name="Character Tests">
 				<menu_item_call label="容姿を XML に保存する" name="Appearance To XML"/>
@@ -406,8 +392,8 @@
 		<menu_item_check label="管理者メニューを表示する" name="View Admin Options"/>
 	</menu>
 	<menu label="管理者" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="コピーを取る" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="コピーを取る" name="Admin Take Copy"/>
 			<menu_item_call label="私を所有者にする" name="Force Owner To Me"/>
 			<menu_item_call label="所有者権限を実行する" name="Force Owner Permissive"/>
 			<menu_item_call label="削除" name="Delete"/>
@@ -443,7 +429,7 @@
 			<menu_item_call label="物理作用" name="Physics"/>
 			<menu_item_call label="すべての衣類" name="All Clothes"/>
 		</menu>
-		<menu label="ヘルプ" name="Help">
+		<menu label="ヘルプ" name="DeprecatedHelp">
 			<menu_item_call label="リンデン公式ブログ" name="Official Linden Blog"/>
 			<menu_item_call label="スクリプトポータル" name="Scripting Portal"/>
 			<menu label="バグの報告" name="Bug Reporting">
diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml
index c072ea9b5a..24c961fa26 100644
--- a/indra/newview/skins/default/xui/pl/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml
@@ -20,8 +20,6 @@
 			<menu_item_call label="Tryb oddalenia" name="Set Away"/>
 			<menu_item_call label="Tryb pracy" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="Zażądaj statusu administratora" name="Request Admin Options"/>
-		<menu_item_call label="Wyłącz atatus administratora" name="Leave Admin Options"/>
 		<menu_item_call label="Wyłącz [APP_NAME]" name="Quit"/>
 	</menu>
 	<menu label="Komunikacja" name="Communicate">
@@ -36,11 +34,10 @@
 		<menu_item_check label="Szukaj" name="Search"/>
 		<menu_item_call label="Zrób zdjęcie" name="Take Snapshot"/>
 		<menu_item_call label="Zapamiętaj to miejsce (LM)" name="Create Landmark Here"/>
-		<menu label="Miejsce" name="Land">
-			<menu_item_call label="Profil miejsca" name="Place Profile"/>
-			<menu_item_call label="O posiadłości" name="About Land"/>
-			<menu_item_call label="Region/Majątek" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="Profil miejsca" name="Place Profile"/>
+		<menu_item_call label="O posiadłości" name="About Land"/>
+		<menu_item_call label="Region/Majątek" name="Region/Estate"/>
 		<menu_item_call label="Kup posiadłość" name="Buy Land"/>
 		<menu_item_call label="Moje posiadłości" name="My Land"/>
 		<menu label="Pokaż" name="LandShow">
@@ -56,7 +53,7 @@
 		</menu>
 		<menu_item_call label="Teleportuj do Miejsca Startu" name="Teleport Home"/>
 		<menu_item_call label="Ustaw Miejsce Startu" name="Set Home to Here"/>
-		<menu label="Słońce" name="Environment Settings">
+		<menu label="Słońce" name="Sun">
 			<menu_item_call label="Wschód Słońca" name="Sunrise"/>
 			<menu_item_call label="Południe" name="Noon"/>
 			<menu_item_call label="Zachód Słońca" name="Sunset"/>
@@ -153,22 +150,22 @@
 			<menu_item_check label="Pokaż celownik myszki" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="Rodzaje renderowania" name="Rendering Types">
-			<menu_item_check label="Podstawowe" name="Simple"/>
-			<menu_item_check label="Maska alpha" name="Alpha"/>
-			<menu_item_check label="Drzewo" name="Tree"/>
-			<menu_item_check label="Awatary" name="Character"/>
-			<menu_item_check label="Płaszczyzna powierzchni" name="SurfacePath"/>
-			<menu_item_check label="Niebo" name="Sky"/>
-			<menu_item_check label="Woda" name="Water"/>
-			<menu_item_check label="Ziemia" name="Ground"/>
-			<menu_item_check label="Głośność" name="Volume"/>
-			<menu_item_check label="Trawa" name="Grass"/>
-			<menu_item_check label="Chmury" name="Clouds"/>
-			<menu_item_check label="Cząsteczki" name="Particles"/>
-			<menu_item_check label="Zderzenie" name="Bump"/>
+			<menu_item_check label="Podstawowe" name="Rendering Type Simple"/>
+			<menu_item_check label="Maska alpha" name="Rendering Type Alpha"/>
+			<menu_item_check label="Drzewo" name="Rendering Type Tree"/>
+			<menu_item_check label="Awatary" name="Rendering Type Character"/>
+			<menu_item_check label="Płaszczyzna powierzchni" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="Niebo" name="Rendering Type Sky"/>
+			<menu_item_check label="Woda" name="Rendering Type Water"/>
+			<menu_item_check label="Ziemia" name="Rendering Type Ground"/>
+			<menu_item_check label="Głośność" name="Rendering Type Volume"/>
+			<menu_item_check label="Trawa" name="Rendering Type Grass"/>
+			<menu_item_check label="Chmury" name="Rendering Type Clouds"/>
+			<menu_item_check label="Cząsteczki" name="Rendering Type Particles"/>
+			<menu_item_check label="Zderzenie" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="Opcje renderowania" name="Rendering Features">
-			<menu_item_check label="UI" name="UI"/>
+			<menu_item_check label="UI" name="ToggleUI"/>
 			<menu_item_check label="Zaznaczone" name="Selected"/>
 			<menu_item_check label="Podświetlenie" name="Highlighted"/>
 			<menu_item_check label="Tekstury dynamiczne" name="Dynamic Textures"/>
@@ -180,10 +177,7 @@
 		<menu_item_call label="Wyczyść bufor danych grupy" name="ClearGroupCache"/>
 		<menu_item_check label="Wygładzanie ruchu myszki" name="Mouse Smoothing"/>
 		<menu label="Skróty" name="Shortcuts">
-			<menu_item_call label="Obraz (L$[COST])..." name="Upload Image"/>
-			<menu_item_check label="Szukaj" name="Search"/>
 			<menu_item_call label="Zwolnij klawisze" name="Release Keys"/>
-			<menu_item_call label="Domyślne ustawienia rozmiaru interfejsu" name="Set UI Size to Default"/>
 			<menu_item_check label="Pokaż menu Zaawansowane - skrót" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Zamknij okno" name="Close Window"/>
 			<menu_item_call label="Zamknij wszystkie okna" name="Close All Windows"/>
@@ -192,13 +186,6 @@
 			<menu_item_check label="Wolna kamera" name="Joystick Flycam"/>
 			<menu_item_call label="Reset widoku" name="Reset View"/>
 			<menu_item_call label="Zobacz ostatniego rozmówcę" name="Look at Last Chatter"/>
-			<menu label="Wybierz narzędzie budowania" name="Select Tool">
-				<menu_item_call label="Narzędzie ogniskowej" name="Focus"/>
-				<menu_item_call label="Narzędzie ruchu" name="Move"/>
-				<menu_item_call label="Narzędzie edycji" name="Edit"/>
-				<menu_item_call label="Stwórz narzędzie" name="Create"/>
-				<menu_item_call label="Narzędzia posiadłości" name="Land"/>
-			</menu>
 			<menu_item_call label="Przybliż" name="Zoom In"/>
 			<menu_item_call label="Domyślne przybliżenie" name="Zoom Default"/>
 			<menu_item_call label="Oddal" name="Zoom Out"/>
@@ -267,9 +254,8 @@
 			<menu_item_call label="Upuść pakiet pamięci" name="Drop a Packet"/>
 		</menu>
 		<menu_item_call label="Zderzenia, popchnięcia &amp;  uderzenia" name="Bumps, Pushes &amp;amp; Hits"/>
-		<menu label="Świat" name="World">
+		<menu label="Świat" name="DevelopWorld">
 			<menu_item_check label="Domyślne ustawienia środowiska Regionu" name="Sim Sun Override"/>
-			<menu_item_check label="Efekty emiterów" name="Cheesy Beacon"/>
 			<menu_item_check label="Ustalona pogoda" name="Fixed Weather"/>
 			<menu_item_call label="Zachowaj bufor pamięci obiektów regionu" name="Dump Region Object Cache"/>
 		</menu>
@@ -291,11 +277,11 @@
 		</menu>
 		<menu label="Awatar" name="Character">
 			<menu label="Przesuń bakowaną teksturę" name="Grab Baked Texture">
-				<menu_item_call label="Tęczówka oka" name="Iris"/>
-				<menu_item_call label="Głowa" name="Head"/>
-				<menu_item_call label="Górna część ciała" name="Upper Body"/>
-				<menu_item_call label="Dolna część ciała" name="Lower Body"/>
-				<menu_item_call label="Spódnica" name="Skirt"/>
+				<menu_item_call label="Tęczówka oka" name="Grab Iris"/>
+				<menu_item_call label="Głowa" name="Grab Head"/>
+				<menu_item_call label="Górna część ciała" name="Grab Upper Body"/>
+				<menu_item_call label="Dolna część ciała" name="Grab Lower Body"/>
+				<menu_item_call label="Spódnica" name="Grab Skirt"/>
 			</menu>
 			<menu label="Testy postaci" name="Character Tests">
 				<menu_item_call label="Przesuń geometrię postaci" name="Toggle Character Geometry"/>
@@ -316,8 +302,8 @@
 		<menu_item_check label="Pokaż menu administratora" name="View Admin Options"/>
 	</menu>
 	<menu label="Administrator" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="Weź kopię" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="Weź kopię" name="Admin Take Copy"/>
 			<menu_item_call label="Reset właściciela" name="Force Owner To Me"/>
 			<menu_item_call label="Reset przyzwolenia właściciela" name="Force Owner Permissive"/>
 			<menu_item_call label="Usuń" name="Delete"/>
diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml
index 5ff2d49ac1..9ce55c6415 100644
--- a/indra/newview/skins/default/xui/pt/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml
@@ -19,8 +19,6 @@
 			<menu_item_call label="Ausente" name="Set Away"/>
 			<menu_item_call label="Ocupado" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="Request Admin Status" name="Request Admin Options"/>
-		<menu_item_call label="Sair do modo admin" name="Leave Admin Options"/>
 		<menu_item_call label="Comprar L$" name="Buy and Sell L$"/>
 		<menu_item_call label="Preferências..." name="Preferences"/>
 		<menu_item_call label="Barras de ferramentas..." name="Toolbars"/>
@@ -40,11 +38,10 @@
 		<menu_item_check label="Busca" name="Search"/>
 		<menu_item_call label="Foto" name="Take Snapshot"/>
 		<menu_item_call label="Criar marco deste lugar" name="Create Landmark Here"/>
-		<menu label="Perfil da região" name="Land">
-			<menu_item_call label="Perfil da região" name="Place Profile"/>
-			<menu_item_call label="Sobre terrenos" name="About Land"/>
-			<menu_item_call label="Região/Propriedade" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="Perfil da região" name="Place Profile"/>
+		<menu_item_call label="Sobre terrenos" name="About Land"/>
+		<menu_item_call label="Região/Propriedade" name="Region/Estate"/>
 		<menu_item_call label="Comprar este terreno" name="Buy Land"/>
 		<menu_item_call label="Meus terrenos" name="My Land"/>
 		<menu label="Mostrar" name="LandShow">
@@ -60,14 +57,14 @@
 		</menu>
 		<menu_item_call label="Teletransportar para meu início" name="Teleport Home"/>
 		<menu_item_call label="Definir como Início" name="Set Home to Here"/>
-		<menu label="Sol" name="Environment Settings">
+		<menu label="Sol" name="Sun">
 			<menu_item_call label="Amanhecer" name="Sunrise"/>
 			<menu_item_call label="Meio-dia" name="Noon"/>
 			<menu_item_call label="Pôr-do-Sol" name="Sunset"/>
 			<menu_item_call label="Meia-noite" name="Midnight"/>
 		</menu>
 		<menu label="Editor de ambientes" name="Enviroment Editor">
-			<menu_item_call label="Configurações de ambiente..." name="Enviroment Settings"/>
+			<menu_item_call label="Configurações de ambiente..." name="Environment Settings"/>
 			<menu label="Pré-configurações de água" name="Water Presets">
 				<menu_item_call label="Nova pré-configuração..." name="new_water_preset"/>
 				<menu_item_call label="Editar pré-configuração..." name="edit_water_preset"/>
@@ -173,22 +170,22 @@
 			<menu_item_check label="Mostrar retículo na vista subjetiva" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="Tipos de renderização" name="Rendering Types">
-			<menu_item_check label="Simples" name="Simple"/>
-			<menu_item_check label="Alpha" name="Alpha"/>
-			<menu_item_check label="Árvore" name="Tree"/>
-			<menu_item_check label="Avatares" name="Character"/>
-			<menu_item_check label="Patch de superfície" name="Surface Patch"/>
-			<menu_item_check label="Céu" name="Sky"/>
-			<menu_item_check label="Água" name="Water"/>
-			<menu_item_check label="Chão" name="Ground"/>
-			<menu_item_check label="Volume" name="Volume"/>
-			<menu_item_check label="Grama" name="Grass"/>
-			<menu_item_check label="Nuvens" name="Clouds"/>
-			<menu_item_check label="Partículas" name="Particles"/>
-			<menu_item_check label="Elevação" name="Bump"/>
+			<menu_item_check label="Simples" name="Rendering Type Simple"/>
+			<menu_item_check label="Alpha" name="Rendering Type Alpha"/>
+			<menu_item_check label="Árvore" name="Rendering Type Tree"/>
+			<menu_item_check label="Avatares" name="Rendering Type Character"/>
+			<menu_item_check label="Patch de superfície" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="Céu" name="Rendering Type Sky"/>
+			<menu_item_check label="Água" name="Rendering Type Water"/>
+			<menu_item_check label="Chão" name="Rendering Type Ground"/>
+			<menu_item_check label="Volume" name="Rendering Type Volume"/>
+			<menu_item_check label="Grama" name="Rendering Type Grass"/>
+			<menu_item_check label="Nuvens" name="Rendering Type Clouds"/>
+			<menu_item_check label="Partículas" name="Rendering Type Particles"/>
+			<menu_item_check label="Elevação" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="Recursos de renderização" name="Rendering Features">
-			<menu_item_check label="Interface" name="UI"/>
+			<menu_item_check label="Interface" name="ToggleUI"/>
 			<menu_item_check label="Selecionado" name="Selected"/>
 			<menu_item_check label="Realçado" name="Highlighted"/>
 			<menu_item_check label="Texturas dinâmicas" name="Dynamic Textures"/>
@@ -200,10 +197,7 @@
 		<menu_item_call label="Limpar cache de grupo" name="ClearGroupCache"/>
 		<menu_item_check label="Smoothing de mouse" name="Mouse Smoothing"/>
 		<menu label="Atalhos" name="Shortcuts">
-			<menu_item_call label="Imagem (L$[COST])..." name="Upload Image"/>
-			<menu_item_check label="Busca" name="Search"/>
 			<menu_item_call label="Soltar objeto" name="Release Keys"/>
-			<menu_item_call label="Interface tamanho padrão" name="Set UI Size to Default"/>
 			<menu_item_check label="Mostrar menu avançado - atalho antigo" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Fechar janela" name="Close Window"/>
 			<menu_item_call label="Fechar todas as janelas" name="Close All Windows"/>
@@ -212,13 +206,6 @@
 			<menu_item_check label="Flycam Joystick" name="Joystick Flycam"/>
 			<menu_item_call label="Visão padrão" name="Reset View"/>
 			<menu_item_call label="Olhar para quem fala por último" name="Look at Last Chatter"/>
-			<menu label="Selecionar ferramenta de construção" name="Select Tool">
-				<menu_item_call label="Ferramenta enfoque" name="Focus"/>
-				<menu_item_call label="Ferramenta de movimentação" name="Move"/>
-				<menu_item_call label="Ferramenta de edição" name="Edit"/>
-				<menu_item_call label="Ferramenta criar" name="Create"/>
-				<menu_item_call label="Ferramenta de terrenos" name="Land"/>
-			</menu>
 			<menu_item_call label="Mais zoom" name="Zoom In"/>
 			<menu_item_call label="Zoom padrão" name="Zoom Default"/>
 			<menu_item_call label="Menos zoom" name="Zoom Out"/>
@@ -296,9 +283,8 @@
 			<menu_item_call label="Drop a Packet" name="Drop a Packet"/>
 		</menu>
 		<menu_item_call label="Empurrões, trombadas e tapas" name="Bumps, Pushes &amp;amp; Hits"/>
-		<menu label="Mundo" name="World">
+		<menu label="Mundo" name="DevelopWorld">
 			<menu_item_check label="Impor sobre sol regional" name="Sim Sun Override"/>
-			<menu_item_check label="Efeito baliza piscando" name="Cheesy Beacon"/>
 			<menu_item_check label="Fixed Weather" name="Fixed Weather"/>
 			<menu_item_call label="Dump Region Object Cache" name="Dump Region Object Cache"/>
 		</menu>
@@ -320,11 +306,11 @@
 		</menu>
 		<menu label="Avatar" name="Character">
 			<menu label="Grab Baked Texture" name="Grab Baked Texture">
-				<menu_item_call label="Íris" name="Iris"/>
-				<menu_item_call label="Cabeça" name="Head"/>
-				<menu_item_call label="Cintura acima" name="Upper Body"/>
-				<menu_item_call label="Cintura para baixo" name="Lower Body"/>
-				<menu_item_call label="Saia" name="Skirt"/>
+				<menu_item_call label="Íris" name="Grab Iris"/>
+				<menu_item_call label="Cabeça" name="Grab Head"/>
+				<menu_item_call label="Cintura acima" name="Grab Upper Body"/>
+				<menu_item_call label="Cintura para baixo" name="Grab Lower Body"/>
+				<menu_item_call label="Saia" name="Grab Skirt"/>
 			</menu>
 			<menu label="Testes de personagem" name="Character Tests">
 				<menu_item_call label="Toggle Character Geometry" name="Toggle Character Geometry"/>
@@ -346,8 +332,8 @@
 		<menu_item_check label="Mostrar menu admin" name="View Admin Options"/>
 	</menu>
 	<menu label="Admin" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="Pegar uma cópia" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="Pegar uma cópia" name="Admin Take Copy"/>
 			<menu_item_call label="Force Owner To Me" name="Force Owner To Me"/>
 			<menu_item_call label="Force Owner Permissive" name="Force Owner Permissive"/>
 			<menu_item_call label="Excluir" name="Delete"/>
diff --git a/indra/newview/skins/default/xui/ru/menu_viewer.xml b/indra/newview/skins/default/xui/ru/menu_viewer.xml
index b9f403c04b..6e4d64eca7 100644
--- a/indra/newview/skins/default/xui/ru/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ru/menu_viewer.xml
@@ -17,8 +17,6 @@
 			<menu_item_call label="Нет на месте" name="Set Away"/>
 			<menu_item_call label="Не беспокоить" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="Запрос статуса администратора" name="Request Admin Options"/>
-		<menu_item_call label="Выход из статуса администратора" name="Leave Admin Options"/>
 		<menu_item_call label="Купить L$" name="Buy and Sell L$"/>
 		<menu_item_call label="Настройки..." name="Preferences"/>
 		<menu_item_call label="Панели инструментов..." name="Toolbars"/>
@@ -38,11 +36,10 @@
 		<menu_item_check label="Поиск" name="Search"/>
 		<menu_item_call label="Снимок" name="Take Snapshot"/>
 		<menu_item_call label="Добавить закладку на это место" name="Create Landmark Here"/>
-		<menu label="Профиль места" name="Land">
-			<menu_item_call label="Профиль места" name="Place Profile"/>
-			<menu_item_call label="О земле" name="About Land"/>
-			<menu_item_call label="Регион/землевладение" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="Профиль места" name="Place Profile"/>
+		<menu_item_call label="О земле" name="About Land"/>
+		<menu_item_call label="Регион/землевладение" name="Region/Estate"/>
 		<menu_item_call label="Купить эту землю" name="Buy Land"/>
 		<menu_item_call label="Моя земля" name="My Land"/>
 		<menu label="Показать" name="LandShow">
@@ -58,14 +55,14 @@
 		</menu>
 		<menu_item_call label="Телепортироваться домой" name="Teleport Home"/>
 		<menu_item_call label="Установить дом здесь" name="Set Home to Here"/>
-		<menu label="Солнце" name="Environment Settings">
+		<menu label="Солнце" name="Sun">
 			<menu_item_call label="Восход" name="Sunrise"/>
 			<menu_item_call label="Полдень" name="Noon"/>
 			<menu_item_call label="Закат" name="Sunset"/>
 			<menu_item_call label="Полночь" name="Midnight"/>
 		</menu>
 		<menu label="Редактор среды" name="Enviroment Editor">
-			<menu_item_call label="Настройки среды..." name="Enviroment Settings"/>
+			<menu_item_call label="Настройки среды..." name="Environment Settings"/>
 			<menu label="Настройки воды" name="Water Presets">
 				<menu_item_call label="Создать настройку..." name="new_water_preset"/>
 				<menu_item_call label="Изменить настройку..." name="edit_water_preset"/>
@@ -171,22 +168,22 @@
 			<menu_item_check label="Показывать прицел при обзоре мышью" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="Типы визуализации" name="Rendering Types">
-			<menu_item_check label="Обычная" name="Simple"/>
-			<menu_item_check label="Альфа" name="Alpha"/>
-			<menu_item_check label="Дерево" name="Tree"/>
-			<menu_item_check label="Аватары" name="Character"/>
-			<menu_item_check label="Исправление поверхности" name="Surface Patch"/>
-			<menu_item_check label="Небо" name="Sky"/>
-			<menu_item_check label="Вода" name="Water"/>
-			<menu_item_check label="Земля" name="Ground"/>
-			<menu_item_check label="Объем" name="Volume"/>
-			<menu_item_check label="Трава" name="Grass"/>
-			<menu_item_check label="Облака" name="Clouds"/>
-			<menu_item_check label="Частицы" name="Particles"/>
-			<menu_item_check label="Рельефное" name="Bump"/>
+			<menu_item_check label="Обычная" name="Rendering Type Simple"/>
+			<menu_item_check label="Альфа" name="Rendering Type Alpha"/>
+			<menu_item_check label="Дерево" name="Rendering Type Tree"/>
+			<menu_item_check label="Аватары" name="Rendering Type Character"/>
+			<menu_item_check label="Исправление поверхности" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="Небо" name="Rendering Type Sky"/>
+			<menu_item_check label="Вода" name="Rendering Type Water"/>
+			<menu_item_check label="Земля" name="Rendering Type Ground"/>
+			<menu_item_check label="Объем" name="Rendering Type Volume"/>
+			<menu_item_check label="Трава" name="Rendering Type Grass"/>
+			<menu_item_check label="Облака" name="Rendering Type Clouds"/>
+			<menu_item_check label="Частицы" name="Rendering Type Particles"/>
+			<menu_item_check label="Рельефное" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="Функции визуализации" name="Rendering Features">
-			<menu_item_check label="Интерфейс пользователя" name="UI"/>
+			<menu_item_check label="Интерфейс пользователя" name="ToggleUI"/>
 			<menu_item_check label="Выбрано" name="Selected"/>
 			<menu_item_check label="Выделено" name="Highlighted"/>
 			<menu_item_check label="Динамические текстуры" name="Dynamic Textures"/>
@@ -199,10 +196,7 @@
 		<menu_item_call label="Очистить кэш группы" name="ClearGroupCache"/>
 		<menu_item_check label="Сглаживание мышью" name="Mouse Smoothing"/>
 		<menu label="Горячие клавиши" name="Shortcuts">
-			<menu_item_call label="Изображение (L$[COST])..." name="Upload Image"/>
-			<menu_item_check label="Поиск" name="Search"/>
 			<menu_item_call label="Освободить клавиши" name="Release Keys"/>
-			<menu_item_call label="Сбросить размер интерфейса" name="Set UI Size to Default"/>
 			<menu_item_check label="Показать меню «Дополнительно» - старое сочетание клавиш" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Закрыть окно" name="Close Window"/>
 			<menu_item_call label="Закрыть все окна" name="Close All Windows"/>
@@ -211,13 +205,6 @@
 			<menu_item_check label="Обзор джойстиком" name="Joystick Flycam"/>
 			<menu_item_call label="Сброс обзора" name="Reset View"/>
 			<menu_item_call label="Смотреть на последнего говорившего" name="Look at Last Chatter"/>
-			<menu label="Выбрать инструменты" name="Select Tool">
-				<menu_item_call label="Фокус" name="Focus"/>
-				<menu_item_call label="Перемещение" name="Move"/>
-				<menu_item_call label="Редактирование" name="Edit"/>
-				<menu_item_call label="Создание" name="Create"/>
-				<menu_item_call label="Земля" name="Land"/>
-			</menu>
 			<menu_item_call label="Приблизить" name="Zoom In"/>
 			<menu_item_call label="Стандартный масштаб" name="Zoom Default"/>
 			<menu_item_call label="Отодвинуть" name="Zoom Out"/>
@@ -331,9 +318,8 @@
 			<menu_item_call label="Начать запись" name="Start Record"/>
 			<menu_item_call label="Остановить запись" name="Stop Record"/>
 		</menu>
-		<menu label="Мир" name="World">
+		<menu label="Мир" name="DevelopWorld">
 			<menu_item_check label="Перекрытие солнца в симуляторе" name="Sim Sun Override"/>
-			<menu_item_check label="Мигающий маяк" name="Cheesy Beacon"/>
 			<menu_item_check label="Неизменная погода" name="Fixed Weather"/>
 			<menu_item_call label="Вывод кэша региональных объектов" name="Dump Region Object Cache"/>
 		</menu>
@@ -365,11 +351,11 @@
 		</menu>
 		<menu label="Аватар" name="Character">
 			<menu label="Захват запеченных текстур" name="Grab Baked Texture">
-				<menu_item_call label="Радужка" name="Iris"/>
-				<menu_item_call label="Голова" name="Head"/>
-				<menu_item_call label="Верхняя часть тела" name="Upper Body"/>
-				<menu_item_call label="Нижняя часть тела" name="Lower Body"/>
-				<menu_item_call label="Юбка" name="Skirt"/>
+				<menu_item_call label="Радужка" name="Grab Iris"/>
+				<menu_item_call label="Голова" name="Grab Head"/>
+				<menu_item_call label="Верхняя часть тела" name="Grab Upper Body"/>
+				<menu_item_call label="Нижняя часть тела" name="Grab Lower Body"/>
+				<menu_item_call label="Юбка" name="Grab Skirt"/>
 			</menu>
 			<menu label="Проверка персонажа" name="Character Tests">
 				<menu_item_call label="Внешний вид в XML" name="Appearance To XML"/>
@@ -404,8 +390,8 @@
 		<menu_item_check label="Показать меню администратора" name="View Admin Options"/>
 	</menu>
 	<menu label="Администратор" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="Взять копию" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="Взять копию" name="Admin Take Copy"/>
 			<menu_item_call label="Назначить себя владельцем" name="Force Owner To Me"/>
 			<menu_item_call label="Назначить полноправным владельцем" name="Force Owner Permissive"/>
 			<menu_item_call label="Удалить" name="Delete"/>
@@ -441,7 +427,7 @@
 			<menu_item_call label="Физика" name="Physics"/>
 			<menu_item_call label="Вся одежда" name="All Clothes"/>
 		</menu>
-		<menu label="Справка" name="Help">
+		<menu label="Справка" name="DeprecatedHelp">
 			<menu_item_call label="Официальный блог Linden" name="Official Linden Blog"/>
 			<menu_item_call label="Портал скриптов" name="Scripting Portal"/>
 			<menu label="Сообщение об ошибке" name="Bug Reporting">
diff --git a/indra/newview/skins/default/xui/tr/menu_viewer.xml b/indra/newview/skins/default/xui/tr/menu_viewer.xml
index 75294e38d5..7ad5221bb0 100644
--- a/indra/newview/skins/default/xui/tr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/tr/menu_viewer.xml
@@ -17,8 +17,6 @@
 			<menu_item_call label="Uzakta" name="Set Away"/>
 			<menu_item_call label="Meşgul" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="Yönetici Durumu Talep Et" name="Request Admin Options"/>
-		<menu_item_call label="Yönetici Durumundan Ayrıl" name="Leave Admin Options"/>
 		<menu_item_call label="L$ Satın Al" name="Buy and Sell L$"/>
 		<menu_item_call label="Tercihler..." name="Preferences"/>
 		<menu_item_call label="Araç çubukları..." name="Toolbars"/>
@@ -38,11 +36,10 @@
 		<menu_item_check label="Ara" name="Search"/>
 		<menu_item_call label="Anlık Görüntü" name="Take Snapshot"/>
 		<menu_item_call label="Bu Yeri Yer İmlerine Ekle" name="Create Landmark Here"/>
-		<menu label="Profili Yerleştir" name="Land">
-			<menu_item_call label="Profili Yerleştir" name="Place Profile"/>
-			<menu_item_call label="Arazi Hakkında" name="About Land"/>
-			<menu_item_call label="Bölge/Gayrimenkul" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="Profili Yerleştir" name="Place Profile"/>
+		<menu_item_call label="Arazi Hakkında" name="About Land"/>
+		<menu_item_call label="Bölge/Gayrimenkul" name="Region/Estate"/>
 		<menu_item_call label="Bu Araziyi Satın Al" name="Buy Land"/>
 		<menu_item_call label="Arazim" name="My Land"/>
 		<menu label="Göster" name="LandShow">
@@ -58,14 +55,14 @@
 		</menu>
 		<menu_item_call label="Ana Konuma Işınla" name="Teleport Home"/>
 		<menu_item_call label="Ana Konumu Burası Olarak Seç" name="Set Home to Here"/>
-		<menu label="Güneş" name="Environment Settings">
+		<menu label="Güneş" name="Sun">
 			<menu_item_call label="Gün Doğumu" name="Sunrise"/>
 			<menu_item_call label="Gün Ortası" name="Noon"/>
 			<menu_item_call label="Gün Batımı" name="Sunset"/>
 			<menu_item_call label="Gece Yarısı" name="Midnight"/>
 		</menu>
 		<menu label="Ortam Düzenleyici" name="Enviroment Editor">
-			<menu_item_call label="Ortam Ayarları..." name="Enviroment Settings"/>
+			<menu_item_call label="Ortam Ayarları..." name="Environment Settings"/>
 			<menu label="Su Ön Ayarları" name="Water Presets">
 				<menu_item_call label="Yeni ön ayar..." name="new_water_preset"/>
 				<menu_item_call label="Ön ayarı düzenle..." name="edit_water_preset"/>
@@ -171,22 +168,22 @@
 			<menu_item_check label="Fare Üzerinden Görünüm Artı İşaretini Göster" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="İşleme Türleri" name="Rendering Types">
-			<menu_item_check label="Basit" name="Simple"/>
-			<menu_item_check label="Alfa" name="Alpha"/>
-			<menu_item_check label="Ağaç" name="Tree"/>
-			<menu_item_check label="Avatarlar" name="Character"/>
-			<menu_item_check label="Yüzey Yaması" name="Surface Patch"/>
-			<menu_item_check label="Gökyüzü" name="Sky"/>
-			<menu_item_check label="Su" name="Water"/>
-			<menu_item_check label="Toprak" name="Ground"/>
-			<menu_item_check label="Hacim" name="Volume"/>
-			<menu_item_check label="Çimen" name="Grass"/>
-			<menu_item_check label="Bulutlar" name="Clouds"/>
-			<menu_item_check label="Parçacıklar" name="Particles"/>
-			<menu_item_check label="Tümsek" name="Bump"/>
+			<menu_item_check label="Basit" name="Rendering Type Simple"/>
+			<menu_item_check label="Alfa" name="Rendering Type Alpha"/>
+			<menu_item_check label="Ağaç" name="Rendering Type Tree"/>
+			<menu_item_check label="Avatarlar" name="Rendering Type Character"/>
+			<menu_item_check label="Yüzey Yaması" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="Gökyüzü" name="Rendering Type Sky"/>
+			<menu_item_check label="Su" name="Rendering Type Water"/>
+			<menu_item_check label="Toprak" name="Rendering Type Ground"/>
+			<menu_item_check label="Hacim" name="Rendering Type Volume"/>
+			<menu_item_check label="Çimen" name="Rendering Type Grass"/>
+			<menu_item_check label="Bulutlar" name="Rendering Type Clouds"/>
+			<menu_item_check label="Parçacıklar" name="Rendering Type Particles"/>
+			<menu_item_check label="Tümsek" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="İşleme Özellikleri" name="Rendering Features">
-			<menu_item_check label="KA" name="UI"/>
+			<menu_item_check label="KA" name="ToggleUI"/>
 			<menu_item_check label="Seçili" name="Selected"/>
 			<menu_item_check label="Vurgulanmış" name="Highlighted"/>
 			<menu_item_check label="Dinamik Dokular" name="Dynamic Textures"/>
@@ -199,10 +196,7 @@
 		<menu_item_call label="Grup Ön Belleğini Temizle" name="ClearGroupCache"/>
 		<menu_item_check label="Fare Düzleştirme" name="Mouse Smoothing"/>
 		<menu label="Kısa Yollar" name="Shortcuts">
-			<menu_item_call label="Görüntü (L$[COST])..." name="Upload Image"/>
-			<menu_item_check label="Ara" name="Search"/>
 			<menu_item_call label="Bırakma Anahtarları" name="Release Keys"/>
-			<menu_item_call label="KA Büyüklüğünü Varsayılana Ayarla" name="Set UI Size to Default"/>
 			<menu_item_check label="Gelişmiş Menüyü Göster - eski kısayol" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Pencereyi Kapat" name="Close Window"/>
 			<menu_item_call label="Tüm Pencereleri Kapat" name="Close All Windows"/>
@@ -211,13 +205,6 @@
 			<menu_item_check label="Oyun Çubuğu Flycam" name="Joystick Flycam"/>
 			<menu_item_call label="Görünümü Sıfırla" name="Reset View"/>
 			<menu_item_call label="Son Sohbet Edene Bak" name="Look at Last Chatter"/>
-			<menu label="İnşa Et Aracını Seç" name="Select Tool">
-				<menu_item_call label="Odaklanma Aracı" name="Focus"/>
-				<menu_item_call label="Hareket Ettirme Aracı" name="Move"/>
-				<menu_item_call label="Düzenleme Aracı" name="Edit"/>
-				<menu_item_call label="Oluşturma Aracı" name="Create"/>
-				<menu_item_call label="Arazi Aracı" name="Land"/>
-			</menu>
 			<menu_item_call label="Yakınlaştır" name="Zoom In"/>
 			<menu_item_call label="Varsayılan Yakınlaştırma" name="Zoom Default"/>
 			<menu_item_call label="Uzaklaştırma" name="Zoom Out"/>
@@ -331,9 +318,8 @@
 			<menu_item_call label="Kaydı Başlat" name="Start Record"/>
 			<menu_item_call label="Kaydı Durdur" name="Stop Record"/>
 		</menu>
-		<menu label="Dünya" name="World">
+		<menu label="Dünya" name="DevelopWorld">
 			<menu_item_check label="Sim Güneşi Geçersiz Kıl" name="Sim Sun Override"/>
-			<menu_item_check label="Yanıp Sönen İşaret" name="Cheesy Beacon"/>
 			<menu_item_check label="Sabit Hava Durumu" name="Fixed Weather"/>
 			<menu_item_call label="Bölge Nesne Önbelleğinin Dökümünü Al" name="Dump Region Object Cache"/>
 		</menu>
@@ -365,11 +351,11 @@
 		</menu>
 		<menu label="Avatar" name="Character">
 			<menu label="Kaydedilmiş Dokuyu Al" name="Grab Baked Texture">
-				<menu_item_call label="İris" name="Iris"/>
-				<menu_item_call label="Baş" name="Head"/>
-				<menu_item_call label="Üst Gövde" name="Upper Body"/>
-				<menu_item_call label="Alt Gövde" name="Lower Body"/>
-				<menu_item_call label="Etek" name="Skirt"/>
+				<menu_item_call label="İris" name="Grab Iris"/>
+				<menu_item_call label="Baş" name="Grab Head"/>
+				<menu_item_call label="Üst Gövde" name="Grab Upper Body"/>
+				<menu_item_call label="Alt Gövde" name="Grab Lower Body"/>
+				<menu_item_call label="Etek" name="Grab Skirt"/>
 			</menu>
 			<menu label="Karakter Testleri" name="Character Tests">
 				<menu_item_call label="XML&apos;de Görünüm" name="Appearance To XML"/>
@@ -404,8 +390,8 @@
 		<menu_item_check label="Yönetici Menüsünü Göster" name="View Admin Options"/>
 	</menu>
 	<menu label="Yönetici" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="Kopya Al" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="Kopya Al" name="Admin Take Copy"/>
 			<menu_item_call label="Mülkiyetime Geçir" name="Force Owner To Me"/>
 			<menu_item_call label="İzinlerle Birlikte Mülkiyetime Geçir" name="Force Owner Permissive"/>
 			<menu_item_call label="Sil" name="Delete"/>
@@ -441,7 +427,7 @@
 			<menu_item_call label="Fizik" name="Physics"/>
 			<menu_item_call label="Tüm Giysiler" name="All Clothes"/>
 		</menu>
-		<menu label="Yardım" name="Help">
+		<menu label="Yardım" name="DeprecatedHelp">
 			<menu_item_call label="Resmi Linden Blog&apos;u" name="Official Linden Blog"/>
 			<menu_item_call label="Komut Dosyası Portalı" name="Scripting Portal"/>
 			<menu label="Hata Raporlama" name="Bug Reporting">
diff --git a/indra/newview/skins/default/xui/zh/menu_viewer.xml b/indra/newview/skins/default/xui/zh/menu_viewer.xml
index f7be781cac..b6bb79bcbc 100644
--- a/indra/newview/skins/default/xui/zh/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/zh/menu_viewer.xml
@@ -20,8 +20,6 @@
 			<menu_item_call label="離開" name="Set Away"/>
 			<menu_item_call label="忙碌" name="Set Busy"/>
 		</menu>
-		<menu_item_call label="要求 Admin 狀態" name="Request Admin Options"/>
-		<menu_item_call label="離開 Admin 狀態" name="Leave Admin Options"/>
 		<menu_item_call label="結束退出 [APP_NAME]" name="Quit"/>
 	</menu>
 	<menu label="溝通" name="Communicate">
@@ -36,11 +34,10 @@
 		<menu_item_check label="搜尋" name="Search"/>
 		<menu_item_call label="拍攝快照" name="Take Snapshot"/>
 		<menu_item_call label="將此處記下地標" name="Create Landmark Here"/>
-		<menu label="地點檔案" name="Land">
-			<menu_item_call label="地點檔案" name="Place Profile"/>
-			<menu_item_call label="關於土地" name="About Land"/>
-			<menu_item_call label="地區 / 領地" name="Region/Estate"/>
-		</menu>
+		<menu_item_separator/>
+		<menu_item_call label="地點檔案" name="Place Profile"/>
+		<menu_item_call label="關於土地" name="About Land"/>
+		<menu_item_call label="地區 / 領地" name="Region/Estate"/>
 		<menu_item_call label="購買這塊土地" name="Buy Land"/>
 		<menu_item_call label="我的土地" name="My Land"/>
 		<menu label="顯示" name="LandShow">
@@ -56,7 +53,7 @@
 		</menu>
 		<menu_item_call label="瞬間瞬間傳送回家" name="Teleport Home"/>
 		<menu_item_call label="設定家在此處" name="Set Home to Here"/>
-		<menu label="太陽" name="Environment Settings">
+		<menu label="太陽" name="Sun">
 			<menu_item_call label="日出" name="Sunrise"/>
 			<menu_item_call label="中午" name="Noon"/>
 			<menu_item_call label="日落" name="Sunset"/>
@@ -154,22 +151,22 @@
 			<menu_item_check label="顯示第一人稱視角準星" name="ShowCrosshairs"/>
 		</menu>
 		<menu label="Rendering Types" name="Rendering Types">
-			<menu_item_check label="簡單" name="Simple"/>
-			<menu_item_check label="半透明" name="Alpha"/>
-			<menu_item_check label="樹木" name="Tree"/>
-			<menu_item_check label="化身" name="Character"/>
-			<menu_item_check label="地表" name="SurfacePath"/>
-			<menu_item_check label="天空" name="Sky"/>
-			<menu_item_check label="水文" name="Water"/>
-			<menu_item_check label="地面" name="Ground"/>
-			<menu_item_check label="體積" name="Volume"/>
-			<menu_item_check label="草地" name="Grass"/>
-			<menu_item_check label="雲彩" name="Clouds"/>
-			<menu_item_check label="粒子效果" name="Particles"/>
-			<menu_item_check label="碰撞" name="Bump"/>
+			<menu_item_check label="簡單" name="Rendering Type Simple"/>
+			<menu_item_check label="半透明" name="Rendering Type Alpha"/>
+			<menu_item_check label="樹木" name="Rendering Type Tree"/>
+			<menu_item_check label="化身" name="Rendering Type Character"/>
+			<menu_item_check label="地表" name="Rendering Type Surface Patch"/>
+			<menu_item_check label="天空" name="Rendering Type Sky"/>
+			<menu_item_check label="水文" name="Rendering Type Water"/>
+			<menu_item_check label="地面" name="Rendering Type Ground"/>
+			<menu_item_check label="體積" name="Rendering Type Volume"/>
+			<menu_item_check label="草地" name="Rendering Type Grass"/>
+			<menu_item_check label="雲彩" name="Rendering Type Clouds"/>
+			<menu_item_check label="粒子效果" name="Rendering Type Particles"/>
+			<menu_item_check label="碰撞" name="Rendering Type Bump"/>
 		</menu>
 		<menu label="Rendering Features" name="Rendering Features">
-			<menu_item_check label="UI" name="UI"/>
+			<menu_item_check label="UI" name="ToggleUI"/>
 			<menu_item_check label="Selected" name="Selected"/>
 			<menu_item_check label="Highlighted" name="Highlighted"/>
 			<menu_item_check label="Dynamic Textures" name="Dynamic Textures"/>
@@ -182,10 +179,7 @@
 		<menu_item_call label="清除群組快取資料" name="ClearGroupCache"/>
 		<menu_item_check label="滑鼠平滑移動" name="Mouse Smoothing"/>
 		<menu label="快速鍵" name="Shortcuts">
-			<menu_item_call label="圖像(L$[COST])..." name="Upload Image"/>
-			<menu_item_check label="搜尋" name="Search"/>
 			<menu_item_call label="釋出按鍵" name="Release Keys"/>
-			<menu_item_call label="設定使用者界面大小至預設值" name="Set UI Size to Default"/>
 			<menu_item_check label="顯示進階選單 - 舊版捷徑" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="關閉視窗" name="Close Window"/>
 			<menu_item_call label="關閉全部視窗" name="Close All Windows"/>
@@ -194,13 +188,6 @@
 			<menu_item_check label="Joystick Flycam" name="Joystick Flycam"/>
 			<menu_item_call label="重設視角" name="Reset View"/>
 			<menu_item_call label="注視上一位聊天者" name="Look at Last Chatter"/>
-			<menu label="選擇建造工具" name="Select Tool">
-				<menu_item_call label="聚焦工具" name="Focus"/>
-				<menu_item_call label="移動工具" name="Move"/>
-				<menu_item_call label="編輯工具" name="Edit"/>
-				<menu_item_call label="創造工具" name="Create"/>
-				<menu_item_call label="土地工具" name="Land"/>
-			</menu>
 			<menu_item_call label="Zoom In" name="Zoom In"/>
 			<menu_item_call label="Zoom Default" name="Zoom Default"/>
 			<menu_item_call label="Zoom Out" name="Zoom Out"/>
@@ -306,9 +293,8 @@
 			<menu_item_call label="開始錄製" name="Start Record"/>
 			<menu_item_call label="停止錄製" name="Stop Record"/>
 		</menu>
-		<menu label="世界" name="World">
+		<menu label="世界" name="DevelopWorld">
 			<menu_item_check label="模擬器太陽設定覆蓋" name="Sim Sun Override"/>
-			<menu_item_check label="Cheesy Beacon" name="Cheesy Beacon"/>
 			<menu_item_check label="固定天氣" name="Fixed Weather"/>
 			<menu_item_call label="傾印地區物件快取" name="Dump Region Object Cache"/>
 		</menu>
@@ -340,11 +326,11 @@
 		</menu>
 		<menu label="化身" name="Character">
 			<menu label="Grab Baked Texture" name="Grab Baked Texture">
-				<menu_item_call label="Iris" name="Iris"/>
-				<menu_item_call label="頭部" name="Head"/>
-				<menu_item_call label="Upper Body" name="Upper Body"/>
-				<menu_item_call label="Lower Body" name="Lower Body"/>
-				<menu_item_call label="裙子" name="Skirt"/>
+				<menu_item_call label="Iris" name="Grab Iris"/>
+				<menu_item_call label="頭部" name="Grab Head"/>
+				<menu_item_call label="Upper Body" name="Grab Upper Body"/>
+				<menu_item_call label="Lower Body" name="Grab Lower Body"/>
+				<menu_item_call label="裙子" name="Grab Skirt"/>
 			</menu>
 			<menu label="Character Tests" name="Character Tests">
 				<menu_item_call label="Appearance To XML" name="Appearance To XML"/>
@@ -378,8 +364,8 @@
 		<menu_item_check label="Show Admin Menu" name="View Admin Options"/>
 	</menu>
 	<menu label="Admin" name="Admin">
-		<menu label="Object">
-			<menu_item_call label="取得副本" name="Take Copy"/>
+		<menu label="Object" name="AdminObject">
+			<menu_item_call label="取得副本" name="Admin Take Copy"/>
 			<menu_item_call label="強制擁有者為我" name="Force Owner To Me"/>
 			<menu_item_call label="Force Owner Permissive" name="Force Owner Permissive"/>
 			<menu_item_call label="刪除" name="Delete"/>
@@ -415,7 +401,7 @@
 			<menu_item_call label="身體物理" name="Physics"/>
 			<menu_item_call label="全部衣服" name="All Clothes"/>
 		</menu>
-		<menu label="幫助" name="Help">
+		<menu label="幫助" name="DeprecatedHelp">
 			<menu_item_call label="林登官方部落格" name="Official Linden Blog"/>
 			<menu_item_call label="Scripting Portal" name="Scripting Portal"/>
 			<menu label="臭蟲回報" name="Bug Reporting">
-- 
cgit v1.2.3


From b2b421acb6ddea83c9cc25c3593c534f7ff22e57 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 10 Jan 2012 16:15:57 -0800
Subject: Changed merchant outbox visibility to not persist between sessions.

---
 indra/newview/skins/default/xui/en/floater_merchant_outbox.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index 02394e8ac3..741515d56c 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -9,7 +9,7 @@
  min_height="200"
  name="floater_merchant_outbox"
  save_rect="true"
- save_visibility="true"
+ save_visibility="false"
  reuse_instance="true"
  title="MERCHANT OUTBOX"
  width="333" >
-- 
cgit v1.2.3


From 4be85a0e3dd2ef9f2ff6e9c6bb95238fca737b3c Mon Sep 17 00:00:00 2001
From: eli <none@none>
Date: Tue, 10 Jan 2012 17:08:20 -0800
Subject: FIX INTL-89 translation in 8 languages for Set29 including new files

---
 .../newview/skins/default/xui/de/floater_about.xml |  48 ++++----
 .../skins/default/xui/de/floater_about_land.xml    |  17 ++-
 .../skins/default/xui/de/floater_avatar.xml        |   2 +-
 .../skins/default/xui/de/floater_buy_currency.xml  |   2 +-
 .../skins/default/xui/de/floater_camera.xml        |   2 +-
 .../default/xui/de/floater_hardware_settings.xml   |   2 +-
 .../skins/default/xui/de/floater_model_preview.xml |   5 +-
 .../skins/default/xui/de/floater_model_wizard.xml  |   3 +
 .../skins/default/xui/de/floater_moveview.xml      |   2 +-
 .../skins/default/xui/de/floater_snapshot.xml      | 122 ++++++++++-----------
 .../skins/default/xui/de/floater_toybox.xml        |   3 +-
 .../xui/de/floater_translation_settings.xml        |  58 ++++++++++
 .../default/xui/de/floater_voice_controls.xml      |   8 +-
 .../newview/skins/default/xui/de/menu_toolbars.xml |   3 +-
 indra/newview/skins/default/xui/de/menu_viewer.xml |  58 +++++-----
 .../newview/skins/default/xui/de/notifications.xml |  34 ++++--
 .../skins/default/xui/de/panel_edit_skin.xml       |   6 +-
 .../default/xui/de/panel_postcard_message.xml      |  21 ++++
 .../default/xui/de/panel_postcard_settings.xml     |  23 ++++
 .../default/xui/de/panel_preferences_chat.xml      |  27 +----
 .../default/xui/de/panel_preferences_setup.xml     |   2 +-
 .../default/xui/de/panel_snapshot_inventory.xml    |  21 ++++
 .../skins/default/xui/de/panel_snapshot_local.xml  |  39 +++++++
 .../default/xui/de/panel_snapshot_options.xml      |   7 ++
 .../default/xui/de/panel_snapshot_postcard.xml     |  17 +++
 .../default/xui/de/panel_snapshot_profile.xml      |  28 +++++
 indra/newview/skins/default/xui/de/strings.xml     |  61 ++++++++++-
 .../skins/default/xui/de/teleport_strings.xml      |   4 +-
 .../newview/skins/default/xui/es/floater_about.xml |  48 ++++----
 .../skins/default/xui/es/floater_about_land.xml    |  17 ++-
 .../skins/default/xui/es/floater_avatar.xml        |   2 +-
 .../skins/default/xui/es/floater_camera.xml        |   2 +-
 .../default/xui/es/floater_hardware_settings.xml   |   2 +-
 .../skins/default/xui/es/floater_model_preview.xml |   3 +
 .../skins/default/xui/es/floater_model_wizard.xml  |   3 +
 .../skins/default/xui/es/floater_moveview.xml      |   2 +-
 .../skins/default/xui/es/floater_snapshot.xml      | 122 ++++++++++-----------
 .../skins/default/xui/es/floater_toybox.xml        |   3 +-
 .../xui/es/floater_translation_settings.xml        |  58 ++++++++++
 .../default/xui/es/floater_voice_controls.xml      |   8 +-
 .../newview/skins/default/xui/es/menu_toolbars.xml |   3 +-
 indra/newview/skins/default/xui/es/menu_viewer.xml |  58 +++++-----
 .../newview/skins/default/xui/es/notifications.xml |  38 +++++--
 .../skins/default/xui/es/panel_edit_skin.xml       |   6 +-
 .../skins/default/xui/es/panel_nearby_chat.xml     |   2 +-
 .../default/xui/es/panel_postcard_message.xml      |  21 ++++
 .../default/xui/es/panel_postcard_settings.xml     |  23 ++++
 .../default/xui/es/panel_preferences_chat.xml      |  27 +----
 .../default/xui/es/panel_preferences_setup.xml     |   2 +-
 .../default/xui/es/panel_snapshot_inventory.xml    |  21 ++++
 .../skins/default/xui/es/panel_snapshot_local.xml  |  39 +++++++
 .../default/xui/es/panel_snapshot_options.xml      |   7 ++
 .../default/xui/es/panel_snapshot_postcard.xml     |  17 +++
 .../default/xui/es/panel_snapshot_profile.xml      |  28 +++++
 indra/newview/skins/default/xui/es/strings.xml     |  61 ++++++++++-
 .../skins/default/xui/es/teleport_strings.xml      |   4 +-
 .../newview/skins/default/xui/fr/floater_about.xml |  48 ++++----
 .../skins/default/xui/fr/floater_about_land.xml    |  17 ++-
 .../skins/default/xui/fr/floater_avatar.xml        |   2 +-
 .../skins/default/xui/fr/floater_buy_currency.xml  |   8 +-
 .../skins/default/xui/fr/floater_camera.xml        |   2 +-
 .../default/xui/fr/floater_hardware_settings.xml   |   2 +-
 .../skins/default/xui/fr/floater_model_preview.xml |   5 +-
 .../skins/default/xui/fr/floater_model_wizard.xml  |   3 +
 .../skins/default/xui/fr/floater_moveview.xml      |   2 +-
 .../skins/default/xui/fr/floater_snapshot.xml      | 122 ++++++++++-----------
 .../skins/default/xui/fr/floater_toybox.xml        |   3 +-
 .../xui/fr/floater_translation_settings.xml        |  58 ++++++++++
 .../default/xui/fr/floater_voice_controls.xml      |   8 +-
 .../newview/skins/default/xui/fr/menu_toolbars.xml |   3 +-
 indra/newview/skins/default/xui/fr/menu_viewer.xml |  60 +++++-----
 .../newview/skins/default/xui/fr/notifications.xml |  42 ++++---
 .../skins/default/xui/fr/panel_edit_skin.xml       |   6 +-
 .../skins/default/xui/fr/panel_nearby_chat.xml     |   2 +-
 .../default/xui/fr/panel_postcard_message.xml      |  21 ++++
 .../default/xui/fr/panel_postcard_settings.xml     |  23 ++++
 .../default/xui/fr/panel_preferences_chat.xml      |  27 +----
 .../default/xui/fr/panel_preferences_setup.xml     |   2 +-
 .../default/xui/fr/panel_snapshot_inventory.xml    |  21 ++++
 .../skins/default/xui/fr/panel_snapshot_local.xml  |  39 +++++++
 .../default/xui/fr/panel_snapshot_options.xml      |   7 ++
 .../default/xui/fr/panel_snapshot_postcard.xml     |  17 +++
 .../default/xui/fr/panel_snapshot_profile.xml      |  28 +++++
 indra/newview/skins/default/xui/fr/strings.xml     |  61 ++++++++++-
 .../skins/default/xui/fr/teleport_strings.xml      |   4 +-
 .../newview/skins/default/xui/it/floater_about.xml |  48 ++++----
 .../skins/default/xui/it/floater_about_land.xml    |  17 ++-
 .../skins/default/xui/it/floater_avatar.xml        |   2 +-
 .../skins/default/xui/it/floater_buy_currency.xml  |   2 +-
 .../skins/default/xui/it/floater_camera.xml        |   2 +-
 .../default/xui/it/floater_hardware_settings.xml   |   2 +-
 .../skins/default/xui/it/floater_model_preview.xml |   3 +
 .../skins/default/xui/it/floater_model_wizard.xml  |   3 +
 .../skins/default/xui/it/floater_moveview.xml      |   2 +-
 .../skins/default/xui/it/floater_snapshot.xml      | 122 ++++++++++-----------
 .../skins/default/xui/it/floater_toybox.xml        |   3 +-
 .../xui/it/floater_translation_settings.xml        |  58 ++++++++++
 .../default/xui/it/floater_voice_controls.xml      |   8 +-
 .../newview/skins/default/xui/it/menu_toolbars.xml |   3 +-
 indra/newview/skins/default/xui/it/menu_viewer.xml |  66 +++++------
 .../newview/skins/default/xui/it/notifications.xml |  46 +++++---
 .../skins/default/xui/it/panel_edit_skin.xml       |   6 +-
 .../default/xui/it/panel_postcard_message.xml      |  21 ++++
 .../default/xui/it/panel_postcard_settings.xml     |  23 ++++
 .../default/xui/it/panel_preferences_chat.xml      |  27 +----
 .../default/xui/it/panel_preferences_setup.xml     |   2 +-
 .../default/xui/it/panel_snapshot_inventory.xml    |  21 ++++
 .../skins/default/xui/it/panel_snapshot_local.xml  |  39 +++++++
 .../default/xui/it/panel_snapshot_options.xml      |   7 ++
 .../default/xui/it/panel_snapshot_postcard.xml     |  17 +++
 .../default/xui/it/panel_snapshot_profile.xml      |  28 +++++
 indra/newview/skins/default/xui/it/strings.xml     |  61 ++++++++++-
 .../skins/default/xui/it/teleport_strings.xml      |   4 +-
 .../newview/skins/default/xui/ja/floater_about.xml |   2 +
 .../skins/default/xui/ja/floater_about_land.xml    |  17 ++-
 .../skins/default/xui/ja/floater_avatar.xml        |   2 +-
 .../skins/default/xui/ja/floater_buy_currency.xml  |   2 +-
 .../skins/default/xui/ja/floater_camera.xml        |   2 +-
 .../default/xui/ja/floater_hardware_settings.xml   |   4 +-
 .../skins/default/xui/ja/floater_model_preview.xml |   3 +
 .../skins/default/xui/ja/floater_model_wizard.xml  |   3 +
 .../skins/default/xui/ja/floater_moveview.xml      |   2 +-
 .../skins/default/xui/ja/floater_snapshot.xml      | 122 ++++++++++-----------
 .../skins/default/xui/ja/floater_toybox.xml        |   3 +-
 .../xui/ja/floater_translation_settings.xml        |  58 ++++++++++
 .../default/xui/ja/floater_voice_controls.xml      |   4 +-
 .../newview/skins/default/xui/ja/menu_toolbars.xml |   3 +-
 indra/newview/skins/default/xui/ja/menu_viewer.xml |  56 +++++-----
 .../newview/skins/default/xui/ja/notifications.xml |  40 +++++--
 .../skins/default/xui/ja/panel_edit_skin.xml       |   6 +-
 .../default/xui/ja/panel_postcard_message.xml      |  21 ++++
 .../default/xui/ja/panel_postcard_settings.xml     |  23 ++++
 .../default/xui/ja/panel_preferences_chat.xml      |  27 +----
 .../default/xui/ja/panel_preferences_general.xml   |   2 +-
 .../default/xui/ja/panel_preferences_setup.xml     |   2 +-
 .../default/xui/ja/panel_snapshot_inventory.xml    |  21 ++++
 .../skins/default/xui/ja/panel_snapshot_local.xml  |  39 +++++++
 .../default/xui/ja/panel_snapshot_options.xml      |   7 ++
 .../default/xui/ja/panel_snapshot_postcard.xml     |  17 +++
 .../default/xui/ja/panel_snapshot_profile.xml      |  28 +++++
 indra/newview/skins/default/xui/ja/strings.xml     |  61 ++++++++++-
 .../skins/default/xui/ja/teleport_strings.xml      |   4 +-
 .../newview/skins/default/xui/pt/floater_about.xml |  30 ++++-
 .../skins/default/xui/pt/floater_about_land.xml    |  17 ++-
 .../skins/default/xui/pt/floater_avatar.xml        |   2 +-
 .../skins/default/xui/pt/floater_buy_currency.xml  |   2 +-
 .../skins/default/xui/pt/floater_camera.xml        |   2 +-
 .../default/xui/pt/floater_hardware_settings.xml   |   2 +-
 .../skins/default/xui/pt/floater_model_preview.xml |   3 +
 .../skins/default/xui/pt/floater_model_wizard.xml  |   3 +
 .../skins/default/xui/pt/floater_moveview.xml      |   2 +-
 .../skins/default/xui/pt/floater_snapshot.xml      | 122 ++++++++++-----------
 .../skins/default/xui/pt/floater_toybox.xml        |   3 +-
 .../xui/pt/floater_translation_settings.xml        |  58 ++++++++++
 .../default/xui/pt/floater_voice_controls.xml      |   8 +-
 .../newview/skins/default/xui/pt/menu_toolbars.xml |   3 +-
 indra/newview/skins/default/xui/pt/menu_viewer.xml |  86 ++++++++-------
 .../newview/skins/default/xui/pt/notifications.xml |  40 +++++--
 .../skins/default/xui/pt/panel_edit_skin.xml       |   6 +-
 .../default/xui/pt/panel_postcard_message.xml      |  21 ++++
 .../default/xui/pt/panel_postcard_settings.xml     |  23 ++++
 .../default/xui/pt/panel_preferences_chat.xml      |  27 +----
 .../default/xui/pt/panel_preferences_setup.xml     |   2 +-
 .../default/xui/pt/panel_snapshot_inventory.xml    |  21 ++++
 .../skins/default/xui/pt/panel_snapshot_local.xml  |  39 +++++++
 .../default/xui/pt/panel_snapshot_options.xml      |   7 ++
 .../default/xui/pt/panel_snapshot_postcard.xml     |  17 +++
 .../default/xui/pt/panel_snapshot_profile.xml      |  28 +++++
 indra/newview/skins/default/xui/pt/strings.xml     |  61 ++++++++++-
 .../skins/default/xui/pt/teleport_strings.xml      |   4 +-
 .../newview/skins/default/xui/ru/floater_about.xml |  46 ++++----
 .../skins/default/xui/ru/floater_about_land.xml    |  17 ++-
 .../skins/default/xui/ru/floater_avatar.xml        |   2 +-
 .../skins/default/xui/ru/floater_buy_currency.xml  |   2 +-
 .../skins/default/xui/ru/floater_camera.xml        |   2 +-
 .../default/xui/ru/floater_hardware_settings.xml   |   2 +-
 .../skins/default/xui/ru/floater_model_preview.xml |   5 +-
 .../skins/default/xui/ru/floater_model_wizard.xml  |   3 +
 .../skins/default/xui/ru/floater_moveview.xml      |   2 +-
 .../skins/default/xui/ru/floater_snapshot.xml      | 121 ++++++++++----------
 .../skins/default/xui/ru/floater_toybox.xml        |   3 +-
 .../xui/ru/floater_translation_settings.xml        |  58 ++++++++++
 .../default/xui/ru/floater_voice_controls.xml      |   8 +-
 .../newview/skins/default/xui/ru/menu_toolbars.xml |   3 +-
 indra/newview/skins/default/xui/ru/menu_viewer.xml |  54 ++++-----
 .../newview/skins/default/xui/ru/notifications.xml |  38 +++++--
 .../skins/default/xui/ru/panel_edit_skin.xml       |   6 +-
 .../skins/default/xui/ru/panel_nearby_chat.xml     |   2 +-
 .../default/xui/ru/panel_postcard_message.xml      |  21 ++++
 .../default/xui/ru/panel_postcard_settings.xml     |  23 ++++
 .../default/xui/ru/panel_preferences_chat.xml      |  26 +----
 .../default/xui/ru/panel_preferences_general.xml   |   2 +-
 .../default/xui/ru/panel_preferences_setup.xml     |   2 +-
 .../default/xui/ru/panel_snapshot_inventory.xml    |  21 ++++
 .../skins/default/xui/ru/panel_snapshot_local.xml  |  39 +++++++
 .../default/xui/ru/panel_snapshot_options.xml      |   7 ++
 .../default/xui/ru/panel_snapshot_postcard.xml     |  17 +++
 .../default/xui/ru/panel_snapshot_profile.xml      |  28 +++++
 indra/newview/skins/default/xui/ru/strings.xml     |  59 +++++++++-
 .../skins/default/xui/ru/teleport_strings.xml      |   4 +-
 .../newview/skins/default/xui/tr/floater_about.xml |  48 ++++----
 .../skins/default/xui/tr/floater_about_land.xml    |  17 ++-
 .../skins/default/xui/tr/floater_avatar.xml        |   2 +-
 .../skins/default/xui/tr/floater_buy_currency.xml  |   2 +-
 .../skins/default/xui/tr/floater_camera.xml        |   2 +-
 .../default/xui/tr/floater_hardware_settings.xml   |   4 +-
 .../skins/default/xui/tr/floater_model_preview.xml |   3 +
 .../skins/default/xui/tr/floater_model_wizard.xml  |   3 +
 .../skins/default/xui/tr/floater_moveview.xml      |   2 +-
 .../skins/default/xui/tr/floater_snapshot.xml      | 121 ++++++++++----------
 .../skins/default/xui/tr/floater_toybox.xml        |   3 +-
 .../xui/tr/floater_translation_settings.xml        |  58 ++++++++++
 .../default/xui/tr/floater_voice_controls.xml      |   8 +-
 .../newview/skins/default/xui/tr/menu_toolbars.xml |   3 +-
 indra/newview/skins/default/xui/tr/menu_viewer.xml |  58 +++++-----
 .../newview/skins/default/xui/tr/notifications.xml |  38 +++++--
 .../skins/default/xui/tr/panel_edit_skin.xml       |   6 +-
 .../default/xui/tr/panel_postcard_message.xml      |  21 ++++
 .../default/xui/tr/panel_postcard_settings.xml     |  23 ++++
 .../default/xui/tr/panel_preferences_chat.xml      |  26 +----
 .../default/xui/tr/panel_preferences_setup.xml     |   2 +-
 .../default/xui/tr/panel_snapshot_inventory.xml    |  21 ++++
 .../skins/default/xui/tr/panel_snapshot_local.xml  |  39 +++++++
 .../default/xui/tr/panel_snapshot_options.xml      |   7 ++
 .../default/xui/tr/panel_snapshot_postcard.xml     |  17 +++
 .../default/xui/tr/panel_snapshot_profile.xml      |  28 +++++
 indra/newview/skins/default/xui/tr/strings.xml     |  61 ++++++++++-
 .../skins/default/xui/tr/teleport_strings.xml      |   4 +-
 228 files changed, 3552 insertions(+), 1456 deletions(-)
 create mode 100644 indra/newview/skins/default/xui/de/floater_translation_settings.xml
 create mode 100644 indra/newview/skins/default/xui/de/panel_postcard_message.xml
 create mode 100644 indra/newview/skins/default/xui/de/panel_postcard_settings.xml
 create mode 100644 indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml
 create mode 100644 indra/newview/skins/default/xui/de/panel_snapshot_local.xml
 create mode 100644 indra/newview/skins/default/xui/de/panel_snapshot_options.xml
 create mode 100644 indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml
 create mode 100644 indra/newview/skins/default/xui/de/panel_snapshot_profile.xml
 create mode 100644 indra/newview/skins/default/xui/es/floater_translation_settings.xml
 create mode 100644 indra/newview/skins/default/xui/es/panel_postcard_message.xml
 create mode 100644 indra/newview/skins/default/xui/es/panel_postcard_settings.xml
 create mode 100644 indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml
 create mode 100644 indra/newview/skins/default/xui/es/panel_snapshot_local.xml
 create mode 100644 indra/newview/skins/default/xui/es/panel_snapshot_options.xml
 create mode 100644 indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml
 create mode 100644 indra/newview/skins/default/xui/es/panel_snapshot_profile.xml
 create mode 100644 indra/newview/skins/default/xui/fr/floater_translation_settings.xml
 create mode 100644 indra/newview/skins/default/xui/fr/panel_postcard_message.xml
 create mode 100644 indra/newview/skins/default/xui/fr/panel_postcard_settings.xml
 create mode 100644 indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml
 create mode 100644 indra/newview/skins/default/xui/fr/panel_snapshot_local.xml
 create mode 100644 indra/newview/skins/default/xui/fr/panel_snapshot_options.xml
 create mode 100644 indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml
 create mode 100644 indra/newview/skins/default/xui/fr/panel_snapshot_profile.xml
 create mode 100644 indra/newview/skins/default/xui/it/floater_translation_settings.xml
 create mode 100644 indra/newview/skins/default/xui/it/panel_postcard_message.xml
 create mode 100644 indra/newview/skins/default/xui/it/panel_postcard_settings.xml
 create mode 100644 indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml
 create mode 100644 indra/newview/skins/default/xui/it/panel_snapshot_local.xml
 create mode 100644 indra/newview/skins/default/xui/it/panel_snapshot_options.xml
 create mode 100644 indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml
 create mode 100644 indra/newview/skins/default/xui/it/panel_snapshot_profile.xml
 create mode 100644 indra/newview/skins/default/xui/ja/floater_translation_settings.xml
 create mode 100644 indra/newview/skins/default/xui/ja/panel_postcard_message.xml
 create mode 100644 indra/newview/skins/default/xui/ja/panel_postcard_settings.xml
 create mode 100644 indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml
 create mode 100644 indra/newview/skins/default/xui/ja/panel_snapshot_local.xml
 create mode 100644 indra/newview/skins/default/xui/ja/panel_snapshot_options.xml
 create mode 100644 indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml
 create mode 100644 indra/newview/skins/default/xui/ja/panel_snapshot_profile.xml
 create mode 100644 indra/newview/skins/default/xui/pt/floater_translation_settings.xml
 create mode 100644 indra/newview/skins/default/xui/pt/panel_postcard_message.xml
 create mode 100644 indra/newview/skins/default/xui/pt/panel_postcard_settings.xml
 create mode 100644 indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml
 create mode 100644 indra/newview/skins/default/xui/pt/panel_snapshot_local.xml
 create mode 100644 indra/newview/skins/default/xui/pt/panel_snapshot_options.xml
 create mode 100644 indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml
 create mode 100644 indra/newview/skins/default/xui/pt/panel_snapshot_profile.xml
 create mode 100644 indra/newview/skins/default/xui/ru/floater_translation_settings.xml
 create mode 100644 indra/newview/skins/default/xui/ru/panel_postcard_message.xml
 create mode 100644 indra/newview/skins/default/xui/ru/panel_postcard_settings.xml
 create mode 100644 indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml
 create mode 100644 indra/newview/skins/default/xui/ru/panel_snapshot_local.xml
 create mode 100644 indra/newview/skins/default/xui/ru/panel_snapshot_options.xml
 create mode 100644 indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml
 create mode 100644 indra/newview/skins/default/xui/ru/panel_snapshot_profile.xml
 create mode 100644 indra/newview/skins/default/xui/tr/floater_translation_settings.xml
 create mode 100644 indra/newview/skins/default/xui/tr/panel_postcard_message.xml
 create mode 100644 indra/newview/skins/default/xui/tr/panel_postcard_settings.xml
 create mode 100644 indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml
 create mode 100644 indra/newview/skins/default/xui/tr/panel_snapshot_local.xml
 create mode 100644 indra/newview/skins/default/xui/tr/panel_snapshot_options.xml
 create mode 100644 indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml
 create mode 100644 indra/newview/skins/default/xui/tr/panel_snapshot_profile.xml

diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml
index 145cc1e30b..b4c28daac9 100644
--- a/indra/newview/skins/default/xui/de/floater_about.xml
+++ b/indra/newview/skins/default/xui/de/floater_about.xml
@@ -67,32 +67,34 @@ Voice-Serverversion: [VOICE_VERSION]
 		<panel label="Lizenzen" name="licenses_panel">
 			<text_editor name="credits_editor">
 				3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion.
-APR Copyright (C) 2000-2004 The Apache Software Foundation.
-Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
-cURL Copyright (C) 1996-2002, Daniel Stenberg (daniel@haxx.se).
-DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
-expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
-FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
-GL Copyright (C) 1999-2004 Brian Paul.
-GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University sowie David Luebke, Brenden Schubert, University of Virginia.
-google-perftools Copyright (c) 2005, Google Inc.
-Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
-jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW).
-jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
-ogg/vorbis Copyright (C) 2001, Xiphophorus.
-OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
-PCRE Copyright (c) 1997-2008 University of Cambridge.
-SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga.
-SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com).
-xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
-zlib Copyright (C) 1995-2002 Jean-loup Gailly und Mark Adler.
-google-perftools Copyright (c) 2005, Google Inc.
+        APR Copyright (C) 2000-2004 The Apache Software Foundation.
+        Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
+        cURL Copyright (C) 1996-2002, Daniel Stenberg (daniel@haxx.se).
+        DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
+        expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
+        FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
+        GL Copyright (C) 1999-2004 Brian Paul.
+        GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University sowie David Luebke, Brenden Schubert, University of Virginia.
+        google-perftools Copyright (c) 2005, Google Inc.
+        Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
+        jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW).
+        jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
+        ogg/vorbis Copyright (C) 2001, Xiphophorus.
+        OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
+        PCRE Copyright (c) 1997-2008 University of Cambridge.
+        SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga.
+        SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com).
+        xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
+        zlib Copyright (C) 1995-2002 Jean-loup Gailly und Mark Adler.
+        google-perftools Copyright (c) 2005, Google Inc.
 
-Second Life Viewer verwendet Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (und Lizenzgeber). Alle Rechte vorbehalten. Details siehe www.havok.com.
+        Second Life Viewer verwendet Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (und Lizenzgeber). Alle Rechte vorbehalten. Details siehe www.havok.com.
 
-Alle Rechte vorbehalten.  Details siehe licenses.txt.
+        Diese Software enthält von der NVIDIA Corporation bereitgestellten Quellcode.
 
-Audiocodierung für Voice-Chat: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
+        Alle Rechte vorbehalten.  Details siehe licenses.txt.
+
+        Audiocodierung für Voice-Chat: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
 			</text_editor>
 		</panel>
 	</tab_container>
diff --git a/indra/newview/skins/default/xui/de/floater_about_land.xml b/indra/newview/skins/default/xui/de/floater_about_land.xml
index 3cf3a16247..b893ab79e5 100644
--- a/indra/newview/skins/default/xui/de/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_about_land.xml
@@ -130,7 +130,7 @@
 				Traffic:
 			</text>
 			<text name="DwellText">
-				0
+				Laden...
 			</text>
 			<button label="Land kaufen" label_selected="Land kaufen..." name="Buy Land..."/>
 			<button label="Linden-Verkauf" label_selected="Linden-Verkauf..." name="Linden Sale..." tool_tip="Land muss Eigentum und auf Inhalt gesetzt sein und nicht zur Auktion stehen."/>
@@ -310,13 +310,15 @@ Nur große Parzellen können in der Suche aufgeführt werden.
 				Kein Stoßen (regional)
 			</panel.string>
 			<panel.string name="see_avs_text">
-				Auf dieser Parzelle Einwohner sehen und mit ihnen chatten
+				Avatare auf anderen Parzellen können
 			</panel.string>
 			<text name="allow_label">
 				Anderen Einwohnern gestatten:
 			</text>
-			<check_box label="Terrain bearbeiten" name="edit land check" tool_tip="Falls aktiviert, kann jeder Ihr Land terraformen. Am besten ist es, wenn Sie diese Option deaktiviert lassen. Sie können Ihr eigenes Land jederzeit bearbeiten."/>
-			<check_box label="Fliegen" name="check fly" tool_tip="Falls aktiviert, können Einwohner auf Ihrem Land fliegen. Falls nicht aktiviert, können Einwohner lediglich auf Ihr Land fliegen und dort landen (dann jedoch nicht wieder weiterfliegen) oder über Ihr Land hinweg fliegen."/>
+			<text name="allow_label0">
+				Fliegen:
+			</text>
+			<check_box label="Jeder" name="check fly" tool_tip="Falls aktiviert, können Einwohner auf Ihrem Land fliegen. Falls nicht aktiviert, können Einwohner lediglich auf Ihr Land fliegen und dort landen (dann jedoch nicht wieder weiterfliegen) oder über Ihr Land hinweg fliegen."/>
 			<text name="allow_label2">
 				Bauen:
 			</text>
@@ -332,9 +334,6 @@ Nur große Parzellen können in der Suche aufgeführt werden.
 			</text>
 			<check_box label="Jeder" name="check other scripts"/>
 			<check_box label="Gruppe" name="check group scripts"/>
-			<text name="land_options_label">
-				Landoptionen:
-			</text>
 			<check_box label="Sicher (kein Schaden)" name="check safe" tool_tip="Falls aktiviert, wird Land auf Option „Sicher“ eingestellt, Kampfschäden sind deaktiviert. Ansonsten sind Kampfschäden aktiviert."/>
 			<check_box label="Kein Stoßen" name="PushRestrictCheck" tool_tip="Verhindert Stoßen durch Skripte. Durch Aktivieren dieser Option verhindern Sie störendes Verhalten auf Ihrem Land."/>
 			<check_box label="Ort in Suche anzeigen (30 L$/Woche)" name="ShowDirectoryCheck" tool_tip="Diese Parzelle in Suchergebnissen anzeigen."/>
@@ -375,9 +374,9 @@ Nur große Parzellen können in der Suche aufgeführt werden.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Klicken Sie hier, um ein Bild auszuwählen"/>
 			<text name="allow_label5">
-				Einwohnern auf anderen Parzellen Folgendes gestatten:
+				Avatare auf dieser Parzelle sehen und mit ihnen chatten
 			</text>
-			<check_box label="Avatare sehen" name="SeeAvatarsCheck" tool_tip="Gestattet sowohl Einwohnern auf anderen Parzellen, Einwohner auf dieser Parzelle zu sehen und mit ihnen zu chatten, als auch Ihnen, diese Einwohner auf anderen Parzellen zu sehen und mit ihnen zu chatten."/>
+			<check_box label="Avatare sehen" name="SeeAvatarsCheck" tool_tip="Gestattet sowohl Avataren auf anderen Parzellen, Avatare auf dieser Parzelle zu sehen und mit ihnen zu chatten, als auch Ihnen, diese Avatare auf anderen Parzellen zu sehen und mit ihnen zu chatten."/>
 			<text name="landing_point">
 				Landepunkt: [LANDING]
 			</text>
diff --git a/indra/newview/skins/default/xui/de/floater_avatar.xml b/indra/newview/skins/default/xui/de/floater_avatar.xml
index 1470c4bcd6..ba0dd54d96 100644
--- a/indra/newview/skins/default/xui/de/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/de/floater_avatar.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Avatar" title="AVATAR-AUSWAHL"/>
+<floater name="Avatar" title="AVATAR AUSWÄHLEN"/>
diff --git a/indra/newview/skins/default/xui/de/floater_buy_currency.xml b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
index e766b622f7..65926c088c 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		[AMT] L$
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php?lang=de-DE Zahlungsart] | [http://www.secondlife.com/my/account/currency.php?lang=de-DE Währung]
+		[http://www.secondlife.com/my/account/payment_method_management.php Zahlungsart] | [http://www.secondlife.com/my/account/currency.php Währung]
 	</text>
 	<text name="exchange_rate_note">
 		Geben Sie den Betrag erneut ein, um die aktuellste Umtauschrate anzuzeigen.
diff --git a/indra/newview/skins/default/xui/de/floater_camera.xml b/indra/newview/skins/default/xui/de/floater_camera.xml
index 7e9ebdb643..163ef87d8c 100644
--- a/indra/newview/skins/default/xui/de/floater_camera.xml
+++ b/indra/newview/skins/default/xui/de/floater_camera.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="camera_floater" title="ANSICHT">
+<floater name="camera_floater" title="KAMERASTEUERUNGEN">
 	<floater.string name="rotate_tooltip">
 		Kamera um Fokus drehen
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/de/floater_hardware_settings.xml b/indra/newview/skins/default/xui/de/floater_hardware_settings.xml
index 9644bbbaea..ca081aafae 100644
--- a/indra/newview/skins/default/xui/de/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/de/floater_hardware_settings.xml
@@ -4,7 +4,7 @@
 		Filtern:
 	</text>
 	<check_box label="Anisotropische Filterung (langsamer, wenn aktiviert)" name="ani"/>
-	<text name="Antialiasing:">
+	<text name="antialiasing label">
 		Antialiasing:
 	</text>
 	<combo_box label="Antialiasing" name="fsaa">
diff --git a/indra/newview/skins/default/xui/de/floater_model_preview.xml b/indra/newview/skins/default/xui/de/floater_model_preview.xml
index 7f6cd9944f..4af8d67686 100644
--- a/indra/newview/skins/default/xui/de/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/de/floater_model_preview.xml
@@ -4,6 +4,9 @@
 	<string name="status_parse_error">
 		Fehler: Fehler beim DAE-Parsen – Details siehe Protokoll.
 	</string>
+	<string name="status_material_mismatch">
+		Fehler: Das Material des Modells ist keine Teilmenge des Referenzmodells.
+	</string>
 	<string name="status_reading_file">
 		Laden...
 	</string>
@@ -137,7 +140,7 @@
 				</panel>
 				<panel name="physics analysis">
 					<text name="method_label">
-						Schritt 2: Analyse
+						Schritt 2: Analysieren
 					</text>
 					<text name="analysis_method_label">
 						Methode:
diff --git a/indra/newview/skins/default/xui/de/floater_model_wizard.xml b/indra/newview/skins/default/xui/de/floater_model_wizard.xml
index 354a505901..a90f36f202 100644
--- a/indra/newview/skins/default/xui/de/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/de/floater_model_wizard.xml
@@ -20,6 +20,9 @@
 				Hochzuladende Modelldatei auswählen
 			</text>
 			<button label="Durchsuchen..." label_selected="Durchsuchen..." name="browse"/>
+			<text name="Model types">
+				Second Life unterstützt COLLADA-Dateien (.dae).
+			</text>
 			<text name="dimensions">
 				X         Y         Z
 			</text>
diff --git a/indra/newview/skins/default/xui/de/floater_moveview.xml b/indra/newview/skins/default/xui/de/floater_moveview.xml
index e8cc77c038..c1c8271310 100644
--- a/indra/newview/skins/default/xui/de/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/de/floater_moveview.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move_floater" title="BEWEGEN">
+<floater name="move_floater" title="GEHEN / RENNEN / FLIEGEN">
 	<string name="walk_forward_tooltip">
 		Vorwärts gehen (Nach-oben-Pfeil oder W drücken)
 	</string>
diff --git a/indra/newview/skins/default/xui/de/floater_snapshot.xml b/indra/newview/skins/default/xui/de/floater_snapshot.xml
index ae68c71a80..798461c007 100644
--- a/indra/newview/skins/default/xui/de/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/de/floater_snapshot.xml
@@ -3,73 +3,63 @@
 	<floater.string name="unknown">
 		unbekannt
 	</floater.string>
-	<radio_group label="Fototyp" name="snapshot_type_radio">
-		<radio_item label="E-Mail" name="postcard"/>
-		<radio_item label="Mein Inventar ([AMOUNT] L$)" name="texture"/>
-		<radio_item label="Auf meinem Computer speichern" name="local"/>
-	</radio_group>
+	<string name="postcard_progress_str">
+		E-Mail senden
+	</string>
+	<string name="profile_progress_str">
+		Posten
+	</string>
+	<string name="inventory_progress_str">
+		Speichern im Inventar
+	</string>
+	<string name="local_progress_str">
+		Speichern auf Computer
+	</string>
+	<string name="profile_succeeded_str">
+		Bild hochgeladen
+	</string>
+	<string name="postcard_succeeded_str">
+		E-Mail gesendet!
+	</string>
+	<string name="inventory_succeeded_str">
+		Im Inventar gespeichert!
+	</string>
+	<string name="local_succeeded_str">
+		Auf Computer gespeichert!
+	</string>
+	<string name="profile_failed_str">
+		Fehler beim Hochladen des Bilds in Ihr Profil.
+	</string>
+	<string name="postcard_failed_str">
+		Fehler beim Senden der E-Mail.
+	</string>
+	<string name="inventory_failed_str">
+		Fehler beim Speichern im Inventar.
+	</string>
+	<string name="local_failed_str">
+		Fehler beim Speichern auf dem Computer.
+	</string>
+	<button name="advanced_options_btn" tool_tip="Erweiterte Optionen"/>
+	<text name="image_res_text">
+		[WIDTH] x [HEIGHT] px
+	</text>
 	<text name="file_size_label">
 		[SIZE] KB
 	</text>
-	<button label="Foto aktualisieren" name="new_snapshot_btn"/>
-	<button label="Senden" name="send_btn"/>
-	<button label="Speichern ([AMOUNT] L$)" name="upload_btn"/>
-	<flyout_button label="Speichern" name="save_btn" tool_tip="Bild als Datei speichern">
-		<flyout_button.item label="Speichern" name="save_item"/>
-		<flyout_button.item label="Speichern unter..." name="saveas_item"/>
-	</flyout_button>
-	<button label="Mehr" name="more_btn" tool_tip="Erweiterte Optionen"/>
-	<button label="Weniger" name="less_btn" tool_tip="Erweiterte Optionen"/>
-	<button label="Abbrechen" name="discard_btn"/>
-	<text name="type_label2">
-		Größe
-	</text>
-	<text name="format_label">
-		Format
-	</text>
-	<combo_box label="Auflösung" name="postcard_size_combo">
-		<combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="Benutzerdefiniert" name="Custom"/>
-	</combo_box>
-	<combo_box label="Auflösung" name="texture_size_combo">
-		<combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
-		<combo_box.item label="Klein (128x128)" name="Small(128x128)"/>
-		<combo_box.item label="Mittel (256x256)" name="Medium(256x256)"/>
-		<combo_box.item label="Groß (512x512)" name="Large(512x512)"/>
-		<combo_box.item label="Benutzerdefiniert" name="Custom"/>
-	</combo_box>
-	<combo_box label="Auflösung" name="local_size_combo">
-		<combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
-		<combo_box.item label="320x240" name="320x240"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="1280x1024" name="1280x1024"/>
-		<combo_box.item label="1600x1200" name="1600x1200"/>
-		<combo_box.item label="Benutzerdefiniert" name="Custom"/>
-	</combo_box>
-	<combo_box label="Format" name="local_format_combo">
-		<combo_box.item label="PNG" name="PNG"/>
-		<combo_box.item label="JPEG" name="JPEG"/>
-		<combo_box.item label="BMP" name="BMP"/>
-	</combo_box>
-	<spinner label="Breite" name="snapshot_width"/>
-	<spinner label="Größe" name="snapshot_height"/>
-	<check_box label="Seitenverhältnis beibehalten" name="keep_aspect_check"/>
-	<slider label="Bildqualität" name="image_quality_slider"/>
-	<text name="layer_type_label">
-		Aufnehmen:
-	</text>
-	<combo_box label="Bildlayer" name="layer_types">
-		<combo_box.item label="Farben" name="Colors"/>
-		<combo_box.item label="Tiefe" name="Depth"/>
-	</combo_box>
-	<check_box label="Schnittstelle" name="ui_check"/>
-	<check_box label="HUDs" name="hud_check"/>
-	<check_box label="Nach dem Speichern offen lassen" name="keep_open_check"/>
-	<check_box label="Frame einfrieren (Vollbild)" name="freeze_frame_check"/>
-	<check_box label="Automatisch aktualisieren" name="auto_snapshot_check"/>
+	<panel name="advanced_options_panel">
+		<text name="advanced_options_label">
+			ERWEITERTE OPTIONEN
+		</text>
+		<text name="layer_type_label">
+			Aufnahme:
+		</text>
+		<combo_box label="Bildebenen" name="layer_types">
+			<combo_box.item label="Farben" name="Colors"/>
+			<combo_box.item label="Tiefe" name="Depth"/>
+		</combo_box>
+		<check_box label="Schnittstelle" name="ui_check"/>
+		<check_box label="HUDs" name="hud_check"/>
+		<check_box label="Standbild (Vollbild)" name="freeze_frame_check"/>
+		<check_box label="Automatisch aktualisieren" name="auto_snapshot_check"/>
+	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/de/floater_toybox.xml b/indra/newview/skins/default/xui/de/floater_toybox.xml
index 23ec9c2e58..90e50804d6 100644
--- a/indra/newview/skins/default/xui/de/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/de/floater_toybox.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Toybox" title="SYMBOLLEISTEN ANPASSEN">
+<floater name="Toybox" title="SYMBOLLEISTENSCHALTFLÄCHEN">
 	<text name="toybox label 1">
 		Sie können Schaltflächen durch Ziehen zu Symbolleisten hinzufügen oder daraus entfernen.
 	</text>
 	<text name="toybox label 2">
 		Je nach Einstellung erscheinen Schaltflächen wie dargestellt oder nur als Symbol.
 	</text>
+	<button label="Alle Symbolleisten leeren" label_selected="Alle Symbolleisten leeren" name="btn_clear_all"/>
 	<button label="Standards wiederherstellen" label_selected="Standards wiederherstellen" name="btn_restore_defaults"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/de/floater_translation_settings.xml b/indra/newview/skins/default/xui/de/floater_translation_settings.xml
new file mode 100644
index 0000000000..3d5d1d46a8
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_translation_settings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_translation_settings" title="ÜBERSETZUNGSEINSTELLUNGEN FÜR CHATS">
+	<string name="bing_api_key_not_verified">
+		Bing-AppID nicht verifiziert. Versuchen Sie es erneut.
+	</string>
+	<string name="google_api_key_not_verified">
+		Google-API-Schlüssel nicht verifiziert. Versuchen Sie es erneut.
+	</string>
+	<string name="bing_api_key_verified">
+		Bing-AppID verifiziert.
+	</string>
+	<string name="google_api_key_verified">
+		Google-API-Schlüssel verifiziert.
+	</string>
+	<check_box label="Maschinenübersetzung beim Chatten aktivieren" name="translate_chat_checkbox"/>
+	<text name="translate_language_label">
+		Chat übersetzen in:
+	</text>
+	<combo_box name="translate_language_combo">
+		<combo_box.item label="Systemstandard" name="System Default Language"/>
+		<combo_box.item label="English (Englisch)" name="English"/>
+		<combo_box.item label="Dansk (Dänisch)" name="Danish"/>
+		<combo_box.item label="Deutsch" name="German"/>
+		<combo_box.item label="Español (Spanisch)" name="Spanish"/>
+		<combo_box.item label="Français (Französisch)" name="French"/>
+		<combo_box.item label="Italiano (Italienisch)" name="Italian"/>
+		<combo_box.item label="Magyar (Ungarisch)" name="Hungarian"/>
+		<combo_box.item label="Nederlands (Holländisch)" name="Dutch"/>
+		<combo_box.item label="Polski (Polnisch)" name="Polish"/>
+		<combo_box.item label="Português (Portugiesisch)" name="Portugese"/>
+		<combo_box.item label="Русский (Russisch)" name="Russian"/>
+		<combo_box.item label="Türkçe (Türkisch)" name="Turkish"/>
+		<combo_box.item label="Українська (Ukrainisch)" name="Ukrainian"/>
+		<combo_box.item label="中文 (正體) (Chinesisch)" name="Chinese"/>
+		<combo_box.item label="日本語 (Japanisch)" name="Japanese"/>
+		<combo_box.item label="한국어 (Koreanisch)" name="Korean"/>
+	</combo_box>
+	<text name="tip">
+		Übersetzungsservice auswählen:
+	</text>
+	<radio_group name="translation_service_rg">
+		<radio_item initial_value="bing" label="Bing Translator" name="bing"/>
+		<radio_item initial_value="google" label="Google Translate" name="google"/>
+	</radio_group>
+	<text name="bing_api_key_label">
+		Bing-[http://www.bing.com/developers/createapp.aspx AppID]:
+	</text>
+	<button label="Verifizieren" name="verify_bing_api_key_btn"/>
+	<text name="google_api_key_label">
+		Google-[http://code.google.com/apis/language/translate/v2/getting_started.html#auth API-Schlüssel]:
+	</text>
+	<button label="Verifizieren" name="verify_google_api_key_btn"/>
+	<text name="google_links_text">
+		[http://code.google.com/apis/language/translate/v2/pricing.html Pricing] | [https://code.google.com/apis/console Statistik]
+	</text>
+	<button label="OK" name="ok_btn"/>
+	<button label="Abbrechen" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_voice_controls.xml b/indra/newview/skins/default/xui/de/floater_voice_controls.xml
index 18d53841b8..5efda4136e 100644
--- a/indra/newview/skins/default/xui/de/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/de/floater_voice_controls.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="floater_voice_controls" title="SPRACHSTEUERUNGEN">
 	<string name="title_nearby">
-		Stimme in der Nähe
+		VOICE-EINSTELLUNGEN
 	</string>
 	<string name="title_group">
-		Gruppengespräch mit [GROUP]
+		GRUPPENGESPRÄCH MIT [GROUP]
 	</string>
 	<string name="title_adhoc">
-		Konferenzgespräch
+		KONFERENZGESPRÄCH
 	</string>
 	<string name="title_peer_2_peer">
-		Gespräch mit [NAME]
+		GESPRÄCH MIT [NAME]
 	</string>
 	<string name="no_one_near">
 		Es ist niemand in der Nähe, der Voice aktiviert hat.
diff --git a/indra/newview/skins/default/xui/de/menu_toolbars.xml b/indra/newview/skins/default/xui/de/menu_toolbars.xml
index cfeae3deca..3fb48e26b2 100644
--- a/indra/newview/skins/default/xui/de/menu_toolbars.xml
+++ b/indra/newview/skins/default/xui/de/menu_toolbars.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <context_menu name="Toolbars Popup">
-	<menu_item_call label="Schaltflächen auswählen..." name="Chose Buttons"/>
+	<menu_item_call label="Diese Schaltfläche entfernen" name="Remove button"/>
+	<menu_item_call label="Symbolleistenschaltflächen..." name="Choose Buttons"/>
 	<menu_item_check label="Symbole und Beschriftungen" name="icons_with_text"/>
 	<menu_item_check label="Nur Symbole" name="icons_only"/>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml
index 90b2cfbc41..a81874bee9 100644
--- a/indra/newview/skins/default/xui/de/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/de/menu_viewer.xml
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <menu_bar name="Main Menu">
 	<menu label="Ich" name="Me">
-		<menu_item_call label="Dashboard..." name="Manage My Account">
-			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=de"/>
-		</menu_item_call>
 		<menu_item_call label="Profil..." name="Profile"/>
 		<menu_item_call label="Aussehen..." name="ChangeOutfit"/>
+		<menu_item_call label="Avatar auswählen..." name="Avatar Picker"/>
 		<menu_item_check label="Inventar..." name="Inventory"/>
-		<menu_item_check label="Gesten..." name="Gestures"/>
-		<menu_item_check label="Stimme..." name="ShowVoice"/>
+		<menu_item_call label="Neues Inventarfenster" name="NewInventoryWindow"/>
+		<menu_item_call label="Orte..." name="Places"/>
+		<menu_item_call label="Auswahlen..." name="Picks"/>
+		<menu_item_call label="Kamerasteuerungen..." name="Camera Controls"/>
 		<menu label="Bewegung" name="Movement">
 			<menu_item_call label="Hinsetzen" name="Sit Down Here"/>
 			<menu_item_check label="Fliegen" name="Fly"/>
@@ -22,34 +22,39 @@
 		<menu_item_call label="Admin-Status anfordern" name="Request Admin Options"/>
 		<menu_item_call label="Admin-Status verlassen" name="Leave Admin Options"/>
 		<menu_item_call label="L$ kaufen" name="Buy and Sell L$"/>
+		<menu_item_call label="Kontoübersicht..." name="Manage My Account">
+			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=de"/>
+		</menu_item_call>
 		<menu_item_call label="Einstellungen..." name="Preferences"/>
-		<menu_item_call label="Symbolleisten..." name="Toolbars"/>
+		<menu_item_call label="Symbolleistenschaltflächen..." name="Toolbars"/>
 		<menu_item_call label="Alle Steuerelemente ausblenden" name="Hide UI"/>
 		<menu_item_call label="[APP_NAME] schließen" name="Quit"/>
 	</menu>
 	<menu label="Unterhalten" name="Communicate">
-		<menu_item_call label="Meine Freunde" name="My Friends"/>
-		<menu_item_call label="Meine Gruppen" name="My Groups"/>
-		<menu_item_check label="Chat in der Nähe" name="Nearby Chat"/>
+		<menu_item_check label="Chat..." name="Nearby Chat"/>
+		<menu_item_check label="Sprechen" name="Speak"/>
+		<menu_item_check label="Voice-Einstellungen..." name="Nearby Voice"/>
+		<menu_item_check label="Voice-Morphing..." name="ShowVoice"/>
+		<menu_item_check label="Gesten..." name="Gestures"/>
+		<menu_item_call label="Freunde" name="My Friends"/>
+		<menu_item_call label="Gruppen" name="My Groups"/>
 		<menu_item_call label="Leute in der Nähe" name="Active Speakers"/>
-		<menu_item_check label="Stimme in der Nähe" name="Nearby Voice"/>
 	</menu>
 	<menu label="Welt" name="World">
-		<menu_item_check label="Minikarte" name="Mini-Map"/>
+		<menu_item_call label="Landmarke für diesen Ort setzen" name="Create Landmark Here"/>
+		<menu_item_call label="Ziele..." name="Destinations"/>
 		<menu_item_check label="Karte" name="World Map"/>
+		<menu_item_check label="Minikarte" name="Mini-Map"/>
 		<menu_item_check label="Suchen" name="Search"/>
+		<menu_item_call label="Nach Hause teleportieren" name="Teleport Home"/>
+		<menu_item_call label="Hier als Zuhause wählen" name="Set Home to Here"/>
 		<menu_item_call label="Foto" name="Take Snapshot"/>
-		<menu_item_call label="Landmarke für diesen Ort setzen" name="Create Landmark Here"/>
-		<menu label="Ortsprofil" name="Land">
-			<menu_item_call label="Ortsprofil" name="Place Profile"/>
-			<menu_item_call label="Land-Info" name="About Land"/>
-			<menu_item_call label="Region/Grundbesitz" name="Region/Estate"/>
-		</menu>
+		<menu_item_call label="Ortsprofil" name="Place Profile"/>
+		<menu_item_call label="Landinformationen" name="About Land"/>
+		<menu_item_call label="Region/Grundbesitz" name="Region/Estate"/>
+		<menu_item_call label="Mein Landbesitz..." name="My Land"/>
 		<menu_item_call label="Dieses Land kaufen" name="Buy Land"/>
-		<menu_item_call label="Mein Land" name="My Land"/>
 		<menu label="Anzeigen" name="LandShow">
-			<menu_item_check label="Bewegungssteuerung" name="Movement Controls"/>
-			<menu_item_check label="Ansichtsteuerung" name="Camera Controls"/>
 			<menu_item_check label="Bannlinien" name="Ban Lines"/>
 			<menu_item_check label="Strahlen" name="beacons"/>
 			<menu_item_check label="Grundstücksgrenzen" name="Property Lines"/>
@@ -58,16 +63,15 @@
 			<menu_item_check label="Parzelleneigenschaften" name="Parcel Properties"/>
 			<menu_item_check label="Menü „Erweitert“" name="Show Advanced Menu"/>
 		</menu>
-		<menu_item_call label="Teleport nach Hause" name="Teleport Home"/>
-		<menu_item_call label="Hier als Zuhause wählen" name="Set Home to Here"/>
 		<menu label="Sonne" name="Environment Settings">
 			<menu_item_call label="Sonnenaufgang" name="Sunrise"/>
 			<menu_item_call label="Mittag" name="Noon"/>
 			<menu_item_call label="Sonnenuntergang" name="Sunset"/>
 			<menu_item_call label="Mitternacht" name="Midnight"/>
+			<menu_item_call label="Regionseinstellungen verwenden" name="Use Region Settings"/>
 		</menu>
-		<menu label="Umgebungs-Editor" name="Enviroment Editor">
-			<menu_item_call label="Umgebungseinstellungen..." name="Enviroment Settings"/>
+		<menu label="Umwelt-Editor" name="Environment Editor">
+			<menu_item_call label="Umwelt-Einstellungen..." name="Environment Settings"/>
 			<menu label="Wasser-Voreinstellungen" name="Water Presets">
 				<menu_item_call label="Neue Voreinstellung..." name="new_water_preset"/>
 				<menu_item_call label="Voreinstellung bearbeiten..." name="edit_water_preset"/>
@@ -146,6 +150,7 @@
 		<menu_item_call label="Wiederholen" name="Redo"/>
 	</menu>
 	<menu label="Hilfe" name="Help">
+		<menu_item_call label="Anweisungen..." name="How To"/>
 		<menu_item_call label="[SECOND_LIFE]-Hilfe" name="Second Life Help"/>
 		<menu_item_call label="Missbrauch melden" name="Report Abuse"/>
 		<menu_item_call label="Fehler melden" name="Report Bug"/>
@@ -200,11 +205,10 @@
 		<menu_item_check label="Plugin Read Thread verwenden" name="Use Plugin Read Thread"/>
 		<menu_item_call label="Gruppen-Cache löschen" name="ClearGroupCache"/>
 		<menu_item_check label="Weiche Mausbewegung" name="Mouse Smoothing"/>
+		<menu_item_call label="Tasten freigeben" name="Release Keys"/>
 		<menu label="Tastaturkürzel" name="Shortcuts">
 			<menu_item_call label="Bild ([COST] L$)..." name="Upload Image"/>
 			<menu_item_check label="Suchen" name="Search"/>
-			<menu_item_call label="Tasten freigeben" name="Release Keys"/>
-			<menu_item_call label="UI-Größe auf Standard setzen" name="Set UI Size to Default"/>
 			<menu_item_check label="Erweitert-Menü anzeigen - veraltetet" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Fenster schließen" name="Close Window"/>
 			<menu_item_call label="Alle Fenster schließen" name="Close All Windows"/>
@@ -290,6 +294,7 @@
 			<menu_item_check label="Lichter" name="Lights"/>
 			<menu_item_check label="Gelenkpunkte" name="Collision Skeleton"/>
 			<menu_item_check label="Raycast" name="Raycast"/>
+			<menu_item_check label="Windvektoren" name="Wind Vectors"/>
 			<menu_item_check label="Komplexität beim Rendern" name="rendercomplexity"/>
 			<menu_item_check label="Formen" name="Sculpt"/>
 		</menu>
@@ -302,7 +307,6 @@
 			<menu_item_check label="Licht und Schatten" name="Lighting and Shadows"/>
 			<menu_item_check label="Schatten von Sonne-/Mond-Projektoren" name="Shadows from Sun/Moon/Projectors"/>
 			<menu_item_check label="SSAO und Schattenglättung" name="SSAO and Shadow Smoothing"/>
-			<menu_item_check label="Globale Beleuchtung (experimentell)" name="Global Illumination"/>
 			<menu_item_check label="Fehler in GL beseitigen" name="Debug GL"/>
 			<menu_item_check label="Fehler in Pipeline beseitigen" name="Debug Pipeline"/>
 			<menu_item_check label="Automatische Alpha-Masken (aufgeschoben)" name="Automatic Alpha Masks (deferred)"/>
diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index a5fcd3e0b4..a34b938a7a 100644
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -1124,8 +1124,13 @@ Der Gruppe „[GROUP_NAME]“ [AREA] m² an Land schenken?
 	<notification name="DisplaySetToSafe">
 		Es wurden sichere Anzeige-Einstellungen gewählt, da die Option -safe verwendet wurde.
 	</notification>
-	<notification name="DisplaySetToRecommended">
-		Es wurden die für Ihre Systemkonfiguration empfohlenen Anzeige-Einstellungen gewählt.
+	<notification name="DisplaySetToRecommendedGPUChange">
+		Die Anzeigeeinstellungen wurden auf die empfohlenen Werte gesetzt, da Ihre Grafikkarte geändert wurde
+von „[LAST_GPU]“
+in „[THIS_GPU]“
+	</notification>
+	<notification name="DisplaySetToRecommendedFeatureChange">
+		Aufgrund einer Änderung des Rendersubsystems wurden die Anzeigeeinstellungen auf die empfohlenen Werte gesetzt.
 	</notification>
 	<notification name="ErrorMessage">
 		[ERROR_MESSAGE]
@@ -1926,7 +1931,13 @@ Inventarobjekt(e) verschieben?
 		<usetemplate ignoretext="Bestätigen, bevor Sitzung beendet wird" name="okcancelignore" notext="Nicht beenden" yestext="Beenden"/>
 	</notification>
 	<notification name="ConfirmRestoreToybox">
-		Möchten Sie wirklich Ihre Standardschaltflächen und -symbolleisten wiederherstellen? 
+		Durch diese Aktion werden Ihre Standardschaltflächen und -symbolleisten wiederhergestellt.
+
+Diese Aktion kann nicht rückgängig gemacht werden.
+		<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
+	</notification>
+	<notification name="ConfirmClearAllToybox">
+		Durch diese Aktion werden alle Schaltflächen zurück in die Toolbox gestellt; die Symbolleisten sind leer.
     
 Diese Aktion kann nicht rückgängig gemacht werden.
 		<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
@@ -2250,14 +2261,16 @@ Wählen Sie ein einzelnes Objekt aus.
 		Ihre Visitenkarte wurde abgelehnt.
 	</notification>
 	<notification name="TeleportToLandmark">
-		Sie können an Positionen wie „[NAME]“ teleportieren, wenn Sie rechts in Ihrem Bildschirm die Tafel „Orte“ öffnen und dann die Registerkarte „Meine Landmarken“ auswählen.
-Klicken Sie auf eine Landmarke, um diese auszuwählen. Klicken Sie anschließend auf unten in der Registerkarte auf „Teleportieren“.
-(Sie können auch auf die Landmarke doppelt klicken oder mit rechts auf die Landmarke klicken und dann „Teleportieren“ auswählen).
+		Um zu Orten wie „[NAME]“ zu teleportieren, klicken Sie zuerst auf die Schaltfläche „Orte“
+    und dann im eingeblendeten Fenster auf die Registerkarte „Landmarken“. Klicken Sie auf
+    die gewünschte Landmarke und dann unten im Fenster auf „Teleportieren“.
+    (Sie können auch auf die Landmarke doppelklicken bzw. sie mit der rechten Maustaste ankklicken und dann
+    „Teleportieren“ wählen.)
 	</notification>
 	<notification name="TeleportToPerson">
-		Sie können Einwohner wie „[NAME]“ kontaktieren, wenn Sie die Tafel „Leute“ auf der rechten Seite Ihres Bildschirms öffnen.
-Wählen Sie den Einwohner aus der Liste aus und klicken Sie unten auf „IM“.
-(Sie können auch auf den Namen doppelt klicken oder mit rechts auf den Namen klicken und dann „IM“ auswählen).
+		Um Einwohner wie „[NAME]“ zu kontaktieren, klicken Sie auf die Schaltfläche „Leute“, wählen Sie eingeblendeten Fenster einen Einwohner aus
+    und klicken Sie unten im Fenster auf „IM“.
+    (Sie können auch auf den Namen doppelklicken bzw. ihn mit der rechten Maustaste anklicken und dann „IM“ wählen.)
 	</notification>
 	<notification name="CantSelectLandFromMultipleRegions">
 		Land kann nicht über Servergrenzen hinweg ausgewählt werden.
@@ -2278,6 +2291,9 @@ Wählen Sie eine kleinere Landfläche.
 	<notification name="PaymentSent">
 		[MESSAGE]
 	</notification>
+	<notification name="PaymentFailure">
+		[MESSAGE]
+	</notification>
 	<notification name="EventNotification">
 		Event-Benachrichtigung:
 
diff --git a/indra/newview/skins/default/xui/de/panel_edit_skin.xml b/indra/newview/skins/default/xui/de/panel_edit_skin.xml
index f167f45e98..60f6919485 100644
--- a/indra/newview/skins/default/xui/de/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/de/panel_edit_skin.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_skin_panel">
 	<panel name="avatar_skin_color_panel">
-		<texture_picker label="Kopftattoo" name="Head Tattoos" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
-		<texture_picker label="Obere Tattoos" name="Upper Tattoos" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
-		<texture_picker label="Untere Tattoos" name="Lower Tattoos" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+		<texture_picker label="Kopf" name="Head" tool_tip="Klicken, um ein Bild zu wählen"/>
+		<texture_picker label="Oberkörper" name="Upper Body" tool_tip="Klicken, um ein Bild zu wählen"/>
+		<texture_picker label="Unterkörper" name="Lower Body" tool_tip="Klicken, um ein Bild zu wählen"/>
 	</panel>
 	<panel name="accordion_panel">
 		<accordion name="wearable_accordion">
diff --git a/indra/newview/skins/default/xui/de/panel_postcard_message.xml b/indra/newview/skins/default/xui/de/panel_postcard_message.xml
new file mode 100644
index 0000000000..6eeef8af71
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_postcard_message.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_message">
+	<text name="to_label">
+		An:
+	</text>
+	<text name="name_label">
+		Von:
+	</text>
+	<text name="subject_label">
+		Betreff:
+	</text>
+	<line_editor label="Betreff hier eingeben." name="subject_form"/>
+	<text name="msg_label">
+		Nachricht:
+	</text>
+	<text_editor name="msg_form">
+		Nachricht hier eingeben.
+	</text_editor>
+	<button label="Abbrechen" name="cancel_btn"/>
+	<button label="Senden" name="send_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_postcard_settings.xml b/indra/newview/skins/default/xui/de/panel_postcard_settings.xml
new file mode 100644
index 0000000000..c1a1c0cc46
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_postcard_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_settings">
+	<combo_box label="Auflösung" name="postcard_size_combo">
+		<combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Benutzerdefiniert" name="Custom"/>
+	</combo_box>
+	<layout_stack name="postcard_image_params_ls">
+		<layout_panel name="postcard_image_size_lp">
+			<spinner label="Breite" name="postcard_snapshot_width"/>
+			<spinner label="Höhe" name="postcard_snapshot_height"/>
+			<check_box label="Seitenverhältnis beibehalten" name="postcard_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="postcard_image_format_quality_lp">
+			<slider label="Bildqualität" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
index 04f6c27330..746a561e6c 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
@@ -29,30 +29,5 @@
 	<check_box label="IM-Chats" name="EnableIMChatPopups" tool_tip="Markieren, um Popups zu sehen, wenn Instant Message eintrifft"/>
 	<spinner label="Lebenszeit von Toasts für Chat in der Nähe:" name="nearby_toasts_lifetime"/>
 	<spinner label="Ein-/Ausblenddauer von Toasts für Chat in der Nähe:" name="nearby_toasts_fadingtime"/>
-	<check_box name="translate_chat_checkbox"/>
-	<text name="translate_chb_label">
-		Beim Chatten Maschinenübersetzung verwenden
-	</text>
-	<text name="translate_language_text">
-		Chat übersetzen in:
-	</text>
-	<combo_box name="translate_language_combobox" width="200">
-		<combo_box.item label="Systemstandard" name="System Default Language"/>
-		<combo_box.item label="English (Englisch)" name="English"/>
-		<combo_box.item label="Dansk (Dänisch)" name="Danish"/>
-		<combo_box.item label="Deutsch" name="German"/>
-		<combo_box.item label="Español (Spanisch)" name="Spanish"/>
-		<combo_box.item label="Français (Französisch)" name="French"/>
-		<combo_box.item label="Italiano (Italienisch)" name="Italian"/>
-		<combo_box.item label="Magyar (Ungarisch)" name="Hungarian"/>
-		<combo_box.item label="Nederlands (Holländisch)" name="Dutch"/>
-		<combo_box.item label="Polski (Polnisch)" name="Polish"/>
-		<combo_box.item label="Português (Portugiesisch)" name="Portugese"/>
-		<combo_box.item label="Русский (Russisch)" name="Russian"/>
-		<combo_box.item label="Türkçe (Türkisch)" name="Turkish"/>
-		<combo_box.item label="Українська (Ukrainisch)" name="Ukrainian"/>
-		<combo_box.item label="中文 (正體) (Chinesisch)" name="Chinese"/>
-		<combo_box.item label="日本語 (Japanisch)" name="Japanese"/>
-		<combo_box.item label="한국어 (Koreanisch)" name="Korean"/>
-	</combo_box>
+	<button label="Übersetzungseinstellungen für Chats" name="ok_btn"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_setup.xml b/indra/newview/skins/default/xui/de/panel_preferences_setup.xml
index 8b18bf8659..8c7ea688d7 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_setup.xml
@@ -15,7 +15,7 @@
 		Web:
 	</text>
 	<radio_group name="use_external_browser">
-		<radio_item label="Meinen Browser verwenden (IE, Firefox, Safari)" name="external" tool_tip="Standard Webbrowser des Systems verwenden, um die Hilfe, Weblinks usw. anzuzeigen. Bei Vollbildmodus nicht empfohlen." value="1"/>
+		<radio_item label="Meinen Browser verwenden (IE, Firefox, Safari)" name="external" tool_tip="Standard Webbrowser des Systems verwenden, um die Hilfe, Weblinks usw. anzuzeigen. Bei Vollbildmodus nicht empfohlen." value="true"/>
 		<radio_item label="Integrierten Browser verwenden" name="internal" tool_tip="Integrierten Webbrowser verwenden, um die Hilfe, Weblinks usw. anzuzeigen. Dieser Browser öffnet als neues Fenster innerhalb von [APP_NAME]." value=""/>
 	</radio_group>
 	<check_box initial_value="true" label="Plugins aktivieren" name="browser_plugins_enabled"/>
diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml
new file mode 100644
index 0000000000..10827ce6f2
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_inventory">
+	<text name="title">
+		In meinem Inventar speichern
+	</text>
+	<text name="hint_lbl">
+		Das Speichern eines Bilds in Ihrem Inventar kostet [UPLOAD_COST] L$. Um das Bild als Textur zu speichern, wählen Sie eines der quadratischen Formate aus.
+	</text>
+	<combo_box label="Auflösung" name="texture_size_combo">
+		<combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
+		<combo_box.item label="Klein (128x128)" name="Small(128x128)"/>
+		<combo_box.item label="Mittel (256x256)" name="Medium(256x256)"/>
+		<combo_box.item label="Groß (512x512)" name="Large(512x512)"/>
+		<combo_box.item label="Benutzerdefiniert" name="Custom"/>
+	</combo_box>
+	<spinner label="Breite" name="inventory_snapshot_width"/>
+	<spinner label="Höhe" name="inventory_snapshot_height"/>
+	<check_box label="Seitenverhältnis beibehalten" name="inventory_keep_aspect_check"/>
+	<button label="Abbrechen" name="cancel_btn"/>
+	<button label="Speichern" name="save_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_local.xml b/indra/newview/skins/default/xui/de/panel_snapshot_local.xml
new file mode 100644
index 0000000000..3aeae80388
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_snapshot_local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_local">
+	<text name="title">
+		Auf meinem Computer speichern
+	</text>
+	<combo_box label="Auflösung" name="local_size_combo">
+		<combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
+		<combo_box.item label="320x240" name="320x240"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="1280x1024" name="1280x1024"/>
+		<combo_box.item label="1600x1200" name="1600x1200"/>
+		<combo_box.item label="Benutzerdefiniert" name="Custom"/>
+	</combo_box>
+	<layout_stack name="local_image_params_ls">
+		<layout_panel name="local_image_size_lp">
+			<spinner label="Breite" name="local_snapshot_width"/>
+			<spinner label="Höhe" name="local_snapshot_height"/>
+			<check_box label="Seitenverhältnis beibehalten" name="local_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="local_image_format_quality_lp">
+			<combo_box label="Format" name="local_format_combo">
+				<combo_box.item label="PNG (verlustfrei)" name="PNG"/>
+				<combo_box.item label="JPEG" name="JPEG"/>
+				<combo_box.item label="BMP (verlustfrei)" name="BMP"/>
+			</combo_box>
+			<slider label="Bildqualität" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+	<button label="Abbrechen" name="cancel_btn"/>
+	<flyout_button label="Speichern" name="save_btn" tool_tip="Bild als Datei speichern">
+		<flyout_button.item label="Speichern" name="save_item"/>
+		<flyout_button.item label="Speichern unter..." name="saveas_item"/>
+	</flyout_button>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_options.xml b/indra/newview/skins/default/xui/de/panel_snapshot_options.xml
new file mode 100644
index 0000000000..e1d8a5dc6d
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_snapshot_options.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_options">
+	<button label="In meinem Profil posten" name="save_to_profile_btn"/>
+	<button label="E-Mail" name="save_to_email_btn"/>
+	<button label="In meinem Inventar speichern ([AMOUNT] L$)" name="save_to_inventory_btn"/>
+	<button label="Auf meinem Computer speichern" name="save_to_computer_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml
new file mode 100644
index 0000000000..c9afe86d7f
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+	<string name="default_subject">
+		Postkarte aus [SECOND_LIFE].
+	</string>
+	<string name="default_message">
+		Sehen Sie mal!
+	</string>
+	<string name="upload_message">
+		Senden...
+	</string>
+	<text name="title">
+		E-Mail
+	</text>
+	<button label="Nachricht" name="message_btn"/>
+	<button label="Einstellungen" name="settings_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/de/panel_snapshot_profile.xml
new file mode 100644
index 0000000000..8d1c52dea8
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_snapshot_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_profile">
+	<text name="title">
+		In meinem Profil posten
+	</text>
+	<combo_box label="Auflösung" name="profile_size_combo">
+		<combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Benutzerdefiniert" name="Custom"/>
+	</combo_box>
+	<layout_stack name="profile_image_params_ls">
+		<layout_panel name="profile_image_size_lp">
+			<spinner label="Breite" name="profile_snapshot_width"/>
+			<spinner label="Höhe" name="profile_snapshot_height"/>
+			<check_box label="Seitenverhältnis beibehalten" name="profile_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="profile_image_metadata_lp">
+			<text name="caption_label">
+				Bildunterschrift:
+			</text>
+			<check_box initial_value="true" label="Ort einschließen" name="add_location_cb"/>
+		</layout_panel>
+	</layout_stack>
+	<button label="Abbrechen" name="cancel_btn"/>
+	<button label="Posten" name="post_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index 2929556d43..14e9fcdb7f 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -1214,7 +1214,7 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.
 		Sie haben keine Kopie dieser Textur in Ihrem Inventar.
 	</string>
 	<string name="InventoryInboxNoItems">
-		Objekte, die auf dem Marktplatz gekauft wurden, werden hierher geliefert.
+		Wenn Sie einen Artikel kaufen oder anderweitig erhalten, erscheint er hier, damit Sie ihn in einen Ordner in Ihrem Inventar ziehen bzw. löschen können, wenn Sie ihn nicht behalten möchten.
 	</string>
 	<string name="MarketplaceURL">
 		http://marketplace.[DOMAIN_NAME]
@@ -1412,6 +1412,9 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.
 	<string name="no_attachments">
 		Keine Anhänge getragen
 	</string>
+	<string name="Attachments remain">
+		Anhänge (noch [COUNT] Positionen frei)
+	</string>
 	<string name="Buy">
 		Kaufen
 	</string>
@@ -1538,6 +1541,12 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.
 	<string name="Right Pec">
 		Rechts
 	</string>
+	<string name="Neck">
+		Hals
+	</string>
+	<string name="Avatar Center">
+		Avatar-Mitte
+	</string>
 	<string name="Invalid Attachment">
 		Ungültige Stelle für Anhang
 	</string>
@@ -4030,6 +4039,18 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_
 	<string name="you_paid_ldollars_no_name">
 		Sie haben [REASON] [AMOUNT] L$ bezahlt.
 	</string>
+	<string name="you_paid_failure_ldollars">
+		Sie haben [NAME] [AMOUNT] L$ [REASON] nicht bezahlt.
+	</string>
+	<string name="you_paid_failure_ldollars_no_info">
+		Sie haben [AMOUNT] L$ nicht bezahlt.
+	</string>
+	<string name="you_paid_failure_ldollars_no_reason">
+		Sie haben [NAME] [AMOUNT] L$ nicht bezahlt.
+	</string>
+	<string name="you_paid_failure_ldollars_no_name">
+		Sie haben [AMOUNT] L$ [REASON] nicht bezahlt.
+	</string>
 	<string name="for item">
 		für [ITEM]
 	</string>
@@ -4440,6 +4461,12 @@ Setzen Sie den Editorpfad in Anführungszeichen
 	<string name="ExternalEditorFailedToRun">
 		Externer Editor konnte nicht ausgeführt werden.
 	</string>
+	<string name="TranslationFailed">
+		Übersetzung fehlgeschlagen: [REASON]
+	</string>
+	<string name="TranslationResponseParseError">
+		Fehler beim Parsen der Übersetzungsantwort.
+	</string>
 	<string name="Esc">
 		Esc
 	</string>
@@ -4810,7 +4837,7 @@ Setzen Sie den Editorpfad in Anführungszeichen
 		Minikarte
 	</string>
 	<string name="Command_Move_Label">
-		Bewegen
+		Gehen / Rennen / Fliegen
 	</string>
 	<string name="Command_People_Label">
 		Leute
@@ -4837,10 +4864,10 @@ Setzen Sie den Editorpfad in Anführungszeichen
 		Sprechen
 	</string>
 	<string name="Command_View_Label">
-		Ansicht
+		Kamerasteuerungen
 	</string>
 	<string name="Command_Voice_Label">
-		Stimme in der Nähe
+		Voice-Einstellungen
 	</string>
 	<string name="Command_AboutLand_Tooltip">
 		Informationen zu dem von Ihnen besuchten Land
@@ -4912,7 +4939,16 @@ Setzen Sie den Editorpfad in Anführungszeichen
 		Kamerawinkel ändern
 	</string>
 	<string name="Command_Voice_Tooltip">
-		Leute in der Nähe mit Sprechfähigkeit
+		Lautstärkeregler für Anrufe und Leute in Ihrer Nähe in SL
+	</string>
+	<string name="Toolbar_Bottom_Tooltip">
+		gegenwärtig in der unteren Symbolleiste
+	</string>
+	<string name="Toolbar_Left_Tooltip">
+		gegenwärtig in der linken Symbolleiste
+	</string>
+	<string name="Toolbar_Right_Tooltip">
+		gegenwärtig in der rechten Symbolleiste
 	</string>
 	<string name="Retain%">
 		% zurückbehalten
@@ -4938,4 +4974,19 @@ Setzen Sie den Editorpfad in Anführungszeichen
 	<string name="Normal">
 		Normal
 	</string>
+	<string name="snapshot_quality_very_low">
+		Sehr niedrig
+	</string>
+	<string name="snapshot_quality_low">
+		Niedrig
+	</string>
+	<string name="snapshot_quality_medium">
+		Mittel
+	</string>
+	<string name="snapshot_quality_high">
+		Hoch
+	</string>
+	<string name="snapshot_quality_very_high">
+		Sehr hoch
+	</string>
 </strings>
diff --git a/indra/newview/skins/default/xui/de/teleport_strings.xml b/indra/newview/skins/default/xui/de/teleport_strings.xml
index bbfc830688..9cf381bacc 100644
--- a/indra/newview/skins/default/xui/de/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/de/teleport_strings.xml
@@ -21,8 +21,8 @@ Wenn der Teleport dann immer noch nicht funktioniert, melden Sie sich bitte ab u
 Versuchen Sie es später noch einmal.
 		</message>
 		<message name="NoHelpIslandTP">
-		Sie können nicht zurück nach Welcome Island teleportieren. 
-Gehen Sie zu „Welcome Island Public“ und wiederholen sie das Tutorial.
+			Sie können nicht zurück nach Welcome Island teleportieren.
+Gehen Sie zu „Welcome Island Public“, um das Tutorial zu wiederholen.
 		</message>
 		<message name="noaccess_tport">
 			Sie haben leider keinen Zugang zu diesem Teleport-Ziel.
diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml
index b7c9cc27ac..307b61133f 100644
--- a/indra/newview/skins/default/xui/es/floater_about.xml
+++ b/indra/newview/skins/default/xui/es/floater_about.xml
@@ -67,32 +67,34 @@ Versión del servidor de voz: [VOICE_VERSION]
 		<panel label="Licencias" name="licenses_panel">
 			<text_editor name="credits_editor">
 				3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
-APR Copyright (C) 2000-2004 The Apache Software Foundation
-Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
-cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
-DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
-expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
-FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
-GL Copyright (C) 1999-2004 Brian Paul.
-GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University y David Luebke, Brenden Schubert, University of Virginia.
-google-perftools Copyright (c) 2005, Google Inc.
-Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
-jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
-jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
-ogg/vorbis Copyright (C) 2001, Xiphophorus
-OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
-PCRE Copyright (c) 1997-2008 University of Cambridge
-SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
-SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
-xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
-zlib Copyright (C) 1995-2002 Jean-loup Gailly y Mark Adler.
-google-perftools Copyright (c) 2005, Google Inc.
+        APR Copyright (C) 2000-2004 The Apache Software Foundation
+        Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
+        cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
+        DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
+        expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
+        FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
+        GL Copyright (C) 1999-2004 Brian Paul.
+        GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
+        google-perftools Copyright (c) 2005, Google Inc.
+        Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
+        jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
+        jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
+        ogg/vorbis Copyright (C) 2001, Xiphophorus
+        OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
+        PCRE Copyright (c) 1997-2008 University of Cambridge
+        SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+        SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+        xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
+        zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler.
+        google-perftools Copyright (c) 2005, Google Inc.
 
-El visor de Second Life utiliza Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (y los propietarios de las licencias). Reservados todos los derechos. Consulta www.havok.com si deseas obtener más información.
+        El visor de Second Life usa Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (y sus licenciadores). Reservados todos los derechos. Vea los detalles en www.havok.com.
 
-Reservados todos los derechos.  Consulta las licencias en .txt si deseas obtener más información.
+        Este software contiene código fuente suministrado por NVIDIA Corporation.
 
-Codificación de sonido del chat de voz: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
+        Reservados todos los derechos.  Consulte los detalles en licenses.txt.
+
+        Codificación del audio del chat de voz: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
 			</text_editor>
 		</panel>
 	</tab_container>
diff --git a/indra/newview/skins/default/xui/es/floater_about_land.xml b/indra/newview/skins/default/xui/es/floater_about_land.xml
index b6391e28a0..6b8a1ff906 100644
--- a/indra/newview/skins/default/xui/es/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/es/floater_about_land.xml
@@ -130,7 +130,7 @@ Vaya al menú Mundo &gt; Acerca del terreno o seleccione otra parcela para ver s
 				Tráfico:
 			</text>
 			<text name="DwellText">
-				0
+				Cargando...
 			</text>
 			<button label="Comprar terreno" left="130" name="Buy Land..." width="125"/>
 			<button label="Venta Linden" name="Linden Sale..." tool_tip="El terreno debe estar en propiedad, con contenido, y no estar en subasta."/>
@@ -309,13 +309,15 @@ Sólo las parcelas más grandes pueden listarse en la búsqueda.
 				Sin &apos;empujones&apos; (prevalece lo marcado en la región)
 			</panel.string>
 			<panel.string name="see_avs_text">
-				Ver a los residentes de esta parcela y chatear con ellos
+				Los avatares de otras parcelas pueden ver
 			</panel.string>
 			<text name="allow_label">
 				Permitir a otros Residentes:
 			</text>
-			<check_box label="Editar el terreno" name="edit land check" tool_tip="Si se marca, cualquiera podrá modificar su terreno. Mejor dejarlo desmarcado, pues usted siempre puede modificar su terreno."/>
-			<check_box label="Volar" name="check fly" tool_tip="Si se marca, los residentes podrán volar en su terreno. Si no, sólo podrán volar al cruzarlo o hasta que aterricen en él."/>
+			<text name="allow_label0">
+				Volar:
+			</text>
+			<check_box label="Todos" name="check fly" tool_tip="Si se marca, los residentes podrán volar en su terreno. Si no, sólo podrán volar al cruzarlo o hasta que aterricen en él."/>
 			<text name="allow_label2">
 				Crear objetos:
 			</text>
@@ -331,9 +333,6 @@ Sólo las parcelas más grandes pueden listarse en la búsqueda.
 			</text>
 			<check_box label="Todos los residentes" name="check other scripts"/>
 			<check_box label="El grupo" name="check group scripts"/>
-			<text name="land_options_label">
-				Opciones del terreno:
-			</text>
 			<check_box label="Seguro (sin daño)" name="check safe" tool_tip="Si se marca, convierte el terreno en &apos;seguro&apos;, desactivando el daño en combate. Si no, se activa el daño en combate."/>
 			<check_box label="Sin &apos;empujones&apos;" name="PushRestrictCheck" tool_tip="Previene scripts que empujen. Marcando esta opción prevendrá que en su terreno haya comportamientos destructivos."/>
 			<check_box label="Mostrar el sitio en la búsqueda (30 L$/semana)" name="ShowDirectoryCheck" tool_tip="Let people see this parcel in search results"/>
@@ -374,9 +373,9 @@ Sólo las parcelas más grandes pueden listarse en la búsqueda.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Pulse para elegir una imagen"/>
 			<text name="allow_label5">
-				Permitir a los residentes de otras parcelas:
+				a los avatares de esta parcela y chatear con ellos
 			</text>
-			<check_box label="Ver los avatares" name="SeeAvatarsCheck" tool_tip="Permite que los residentes de otras parcelas vean a los residentes de ésta y chateen con ellos, y también que tú puedas verles y chatear con ellos."/>
+			<check_box label="Ver los avatares" name="SeeAvatarsCheck" tool_tip="Permite que los avatares de otras parcelas vean a los avatares de ésta y chateen con ellos, y también que tú puedas verles y chatear con ellos."/>
 			<text name="landing_point">
 				Punto de llegada: [LANDING]
 			</text>
diff --git a/indra/newview/skins/default/xui/es/floater_avatar.xml b/indra/newview/skins/default/xui/es/floater_avatar.xml
index 7c87fbe01c..21d202309f 100644
--- a/indra/newview/skins/default/xui/es/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/es/floater_avatar.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Avatar" title="SELECTOR DE AVATAR"/>
+<floater name="Avatar" title="ELIGE UN AVATAR"/>
diff --git a/indra/newview/skins/default/xui/es/floater_camera.xml b/indra/newview/skins/default/xui/es/floater_camera.xml
index f8911f3a4a..b0704ab788 100644
--- a/indra/newview/skins/default/xui/es/floater_camera.xml
+++ b/indra/newview/skins/default/xui/es/floater_camera.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="camera_floater" title="VER">
+<floater name="camera_floater" title="CONTROLES DE LA CÁMARA">
 	<floater.string name="rotate_tooltip">
 		Girar la cámara alrededor de lo enfocado
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/es/floater_hardware_settings.xml b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml
index 0150241d9a..b96076836b 100644
--- a/indra/newview/skins/default/xui/es/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml
@@ -4,7 +4,7 @@
 		Filtrado:
 	</text>
 	<check_box label="Filtrado anisotrópico (más lento si se activa)" name="ani"/>
-	<text name="Antialiasing:">
+	<text name="antialiasing label">
 		Antialiasing:
 	</text>
 	<combo_box label="Antialiasing" name="fsaa" width="94">
diff --git a/indra/newview/skins/default/xui/es/floater_model_preview.xml b/indra/newview/skins/default/xui/es/floater_model_preview.xml
index 3e77453612..ab3ba5aed7 100644
--- a/indra/newview/skins/default/xui/es/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/es/floater_model_preview.xml
@@ -4,6 +4,9 @@
 	<string name="status_parse_error">
 		Error: Problema de análisis de DAE - consulta los datos en el registro.
 	</string>
+	<string name="status_material_mismatch">
+		Error: el material del modelo no es un subconjunto del modelo de referencia.
+	</string>
 	<string name="status_reading_file">
 		Cargando...
 	</string>
diff --git a/indra/newview/skins/default/xui/es/floater_model_wizard.xml b/indra/newview/skins/default/xui/es/floater_model_wizard.xml
index c4eb5e955a..e27db5a1c4 100644
--- a/indra/newview/skins/default/xui/es/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/es/floater_model_wizard.xml
@@ -20,6 +20,9 @@
 				Elige el archivo de modelo que deseas subir
 			</text>
 			<button label="Buscar..." label_selected="Buscar..." name="browse"/>
+			<text name="Model types">
+				‎Second Life admite los archivos COLLADA (.dae)
+			</text>
 			<text name="dimensions">
 				X         Y         Z
 			</text>
diff --git a/indra/newview/skins/default/xui/es/floater_moveview.xml b/indra/newview/skins/default/xui/es/floater_moveview.xml
index b29fe04848..0e7b950bd3 100644
--- a/indra/newview/skins/default/xui/es/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/es/floater_moveview.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move_floater" title="MOVERME">
+<floater name="move_floater" title="CAMINAR / CORRER / VOLAR">
 	<string name="walk_forward_tooltip">
 		Caminar hacia adelante (cursor arriba o W)
 	</string>
diff --git a/indra/newview/skins/default/xui/es/floater_snapshot.xml b/indra/newview/skins/default/xui/es/floater_snapshot.xml
index eafc623ea9..23078b3a55 100644
--- a/indra/newview/skins/default/xui/es/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/es/floater_snapshot.xml
@@ -3,73 +3,63 @@
 	<floater.string name="unknown">
 		desconocido
 	</floater.string>
-	<radio_group label="Tipo de foto" name="snapshot_type_radio">
-		<radio_item label="Correo-e" name="postcard"/>
-		<radio_item label="Mi inventario ([AMOUNT] L$)" name="texture"/>
-		<radio_item label="Guardar en mi ordenador" name="local"/>
-	</radio_group>
+	<string name="postcard_progress_str">
+		Enviando el correo electrónico
+	</string>
+	<string name="profile_progress_str">
+		Publicando
+	</string>
+	<string name="inventory_progress_str">
+		Guardando en el inventario
+	</string>
+	<string name="local_progress_str">
+		Guardando en el equipo
+	</string>
+	<string name="profile_succeeded_str">
+		Imagen subida
+	</string>
+	<string name="postcard_succeeded_str">
+		Correo electrónico enviado
+	</string>
+	<string name="inventory_succeeded_str">
+		¡Guardado en el inventario!
+	</string>
+	<string name="local_succeeded_str">
+		¡Guardado en el equipo!
+	</string>
+	<string name="profile_failed_str">
+		Error al subir la imagen a los comentarios de tu perfil.
+	</string>
+	<string name="postcard_failed_str">
+		Error al enviar el correo electrónico.
+	</string>
+	<string name="inventory_failed_str">
+		Error al guardar en el inventario.
+	</string>
+	<string name="local_failed_str">
+		Error al guardar en el equipo.
+	</string>
+	<button name="advanced_options_btn" tool_tip="Opciones avanzadas"/>
+	<text name="image_res_text">
+		[WIDTH] x [HEIGHT] px
+	</text>
 	<text name="file_size_label">
 		[SIZE] kB
 	</text>
-	<button label="Actualizar la foto" name="new_snapshot_btn"/>
-	<button label="Enviar" name="send_btn"/>
-	<button label="Ahorro ([AMOUNT] L$)" name="upload_btn"/>
-	<flyout_button label="Guardar" name="save_btn" tool_tip="Guardar la imagen en un archivo">
-		<flyout_button.item label="Guardar" name="save_item"/>
-		<flyout_button.item label="Guardar como..." name="saveas_item"/>
-	</flyout_button>
-	<button label="Más" name="more_btn" tool_tip="Opciones avanzadas"/>
-	<button label="Menos" name="less_btn" tool_tip="Opciones avanzadas"/>
-	<button label="Cancelar" name="discard_btn"/>
-	<text name="type_label2">
-		Tamaño
-	</text>
-	<text name="format_label">
-		Formato
-	</text>
-	<combo_box label="Resolución" name="postcard_size_combo">
-		<combo_box.item label="Ventana actual" name="CurrentWindow"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="Personalizado" name="Custom"/>
-	</combo_box>
-	<combo_box label="Resolución" name="texture_size_combo">
-		<combo_box.item label="Ventana actual" name="CurrentWindow"/>
-		<combo_box.item label="Pequeña (128x128)" name="Small(128x128)"/>
-		<combo_box.item label="Mediana (256x256)" name="Medium(256x256)"/>
-		<combo_box.item label="Grande (512x512)" name="Large(512x512)"/>
-		<combo_box.item label="Personalizado" name="Custom"/>
-	</combo_box>
-	<combo_box label="Resolución" name="local_size_combo">
-		<combo_box.item label="Ventana actual" name="CurrentWindow"/>
-		<combo_box.item label="320x240" name="320x240"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="1280x1024" name="1280x1024"/>
-		<combo_box.item label="1600x1200" name="1600x1200"/>
-		<combo_box.item label="Personalizado" name="Custom"/>
-	</combo_box>
-	<combo_box label="Formato" name="local_format_combo">
-		<combo_box.item label="PNG" name="PNG"/>
-		<combo_box.item label="JPEG" name="JPEG"/>
-		<combo_box.item label="BMP" name="BMP"/>
-	</combo_box>
-	<spinner label="Ancho" name="snapshot_width"/>
-	<spinner label="Altura" name="snapshot_height"/>
-	<check_box label="Mantener las proporciones" name="keep_aspect_check"/>
-	<slider label="Calidad de la imagen" name="image_quality_slider"/>
-	<text name="layer_type_label">
-		Captura:
-	</text>
-	<combo_box label="Capas de imagen" name="layer_types">
-		<combo_box.item label="Colores" name="Colors"/>
-		<combo_box.item label="Profundidad" name="Depth"/>
-	</combo_box>
-	<check_box label="Interfaz" name="ui_check"/>
-	<check_box label="HUDs" name="hud_check"/>
-	<check_box label="Mantener abierto después de guardar" name="keep_open_check"/>
-	<check_box label="Congelar la toma (pantalla completa)" name="freeze_frame_check"/>
-	<check_box label="Actualizar automáticamente" name="auto_snapshot_check"/>
+	<panel name="advanced_options_panel">
+		<text name="advanced_options_label">
+			OPCIONES AVANZADAS
+		</text>
+		<text name="layer_type_label">
+			Captura:
+		</text>
+		<combo_box label="Capas de imagen" name="layer_types">
+			<combo_box.item label="Colores" name="Colors"/>
+			<combo_box.item label="Profundidad" name="Depth"/>
+		</combo_box>
+		<check_box label="Interfaz" name="ui_check"/>
+		<check_box label="HUDs" name="hud_check"/>
+		<check_box label="Congelar la toma (pantalla completa)" name="freeze_frame_check"/>
+		<check_box label="Actualizar automáticamente" name="auto_snapshot_check"/>
+	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/es/floater_toybox.xml b/indra/newview/skins/default/xui/es/floater_toybox.xml
index b36a05a6e4..7275b0546b 100644
--- a/indra/newview/skins/default/xui/es/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/es/floater_toybox.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Toybox" title="PERSONALIZAR BARRAS DE HERRAMIENTAS">
+<floater name="Toybox" title="BOTONES DE LA BARRA DE HERRAMIENTAS">
 	<text name="toybox label 1">
 		Puedes agregar o quitar botones arrastrándolos a las barras de herramientas o desde ellas.
 	</text>
 	<text name="toybox label 2">
 		Los botones aparecerán como se muestra o solo como iconos, según la configuración de cada barra de herramientas.
 	</text>
+	<button label="Quitar todas las barras de herramientas" label_selected="Quitar todas las barras de herramientas" name="btn_clear_all"/>
 	<button label="Restaurar valores predeterminados" label_selected="Restaurar valores predeterminados" name="btn_restore_defaults"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/es/floater_translation_settings.xml b/indra/newview/skins/default/xui/es/floater_translation_settings.xml
new file mode 100644
index 0000000000..765c9a05a2
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/floater_translation_settings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_translation_settings" title="CONFIGURACIÓN DE LA TRADUCCIÓN DEL CHAT">
+	<string name="bing_api_key_not_verified">
+		appID de Bing no se ha confirmado. Vuelve a intentarlo.
+	</string>
+	<string name="google_api_key_not_verified">
+		La clave de API de Google no se ha confirmado. Vuelve a intentarlo.
+	</string>
+	<string name="bing_api_key_verified">
+		appID de Bing se ha confirmado.
+	</string>
+	<string name="google_api_key_verified">
+		La clave de API de Google se ha confirmado.
+	</string>
+	<check_box label="Activar la traducción automática durante el chat" name="translate_chat_checkbox"/>
+	<text name="translate_language_label">
+		Traducir el chat al:
+	</text>
+	<combo_box name="translate_language_combo">
+		<combo_box.item label="Predeterminado del sistema" name="System Default Language"/>
+		<combo_box.item label="Inglés" name="English"/>
+		<combo_box.item label="Dansk (danés)" name="Danish"/>
+		<combo_box.item label="Deutsch (alemán)" name="German"/>
+		<combo_box.item label="Español (español)" name="Spanish"/>
+		<combo_box.item label="Français (francés)" name="French"/>
+		<combo_box.item label="Italiano (italiano)" name="Italian"/>
+		<combo_box.item label="Magyar (húngaro)" name="Hungarian"/>
+		<combo_box.item label="Nederlands (neerlandés)" name="Dutch"/>
+		<combo_box.item label="Polski (polaco)" name="Polish"/>
+		<combo_box.item label="Português (portugués)" name="Portugese"/>
+		<combo_box.item label="Русский (ruso)" name="Russian"/>
+		<combo_box.item label="Türkçe (turco)" name="Turkish"/>
+		<combo_box.item label="Українська (ucraniano)" name="Ukrainian"/>
+		<combo_box.item label="中文 (正體) (Chino)" name="Chinese"/>
+		<combo_box.item label="日本語 (japonés)" name="Japanese"/>
+		<combo_box.item label="한국어 (coreano)" name="Korean"/>
+	</combo_box>
+	<text name="tip">
+		Elige el servicio de traducción:
+	</text>
+	<radio_group name="translation_service_rg">
+		<radio_item initial_value="bing" label="Bing Translator" name="bing"/>
+		<radio_item initial_value="google" label="Traductor de Google" name="google"/>
+	</radio_group>
+	<text name="bing_api_key_label">
+		[http://www.bing.com/developers/createapp.aspx AppID] de Bing:
+	</text>
+	<button label="Verificar" name="verify_bing_api_key_btn"/>
+	<text name="google_api_key_label">
+		[http://code.google.com/apis/language/translate/v2/getting_started.html#auth Clave de API] de Google:
+	</text>
+	<button label="Verificar" name="verify_google_api_key_btn"/>
+	<text name="google_links_text">
+		[http://code.google.com/apis/language/translate/v2/pricing.html Precios] | [https://code.google.com/apis/console Estadísticas]
+	</text>
+	<button label="OK" name="ok_btn"/>
+	<button label="Cancelar" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_voice_controls.xml b/indra/newview/skins/default/xui/es/floater_voice_controls.xml
index cefec2a7a1..eff21239be 100644
--- a/indra/newview/skins/default/xui/es/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/es/floater_voice_controls.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="floater_voice_controls" title="CONTROLES DE LA VOZ">
 	<string name="title_nearby">
-		Chat de voz
+		CONFIGURACIÓN DE VOZ
 	</string>
 	<string name="title_group">
-		Multiconferencia de voz con [GROUP]
+		MULTICONFERENCIA DE VOZ CON [GROUP]
 	</string>
 	<string name="title_adhoc">
-		Multiconferencia de voz
+		MULTICONFERENCIA DE VOZ
 	</string>
 	<string name="title_peer_2_peer">
-		Llamada: [NAME]
+		LLAMADA A [NAME]
 	</string>
 	<string name="no_one_near">
 		Nadie cercano tiene activada la voz
diff --git a/indra/newview/skins/default/xui/es/menu_toolbars.xml b/indra/newview/skins/default/xui/es/menu_toolbars.xml
index f8ed1c54ca..63f3dc43bd 100644
--- a/indra/newview/skins/default/xui/es/menu_toolbars.xml
+++ b/indra/newview/skins/default/xui/es/menu_toolbars.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <context_menu name="Toolbars Popup">
-	<menu_item_call label="Elegir botones..." name="Chose Buttons"/>
+	<menu_item_call label="Quitar este botón" name="Remove button"/>
+	<menu_item_call label="Botones de la barra de herramientas..." name="Choose Buttons"/>
 	<menu_item_check label="Iconos y etiquetas" name="icons_with_text"/>
 	<menu_item_check label="Solo iconos" name="icons_only"/>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml
index f5cc2b9389..4762e3f4a4 100644
--- a/indra/newview/skins/default/xui/es/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/es/menu_viewer.xml
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <menu_bar name="Main Menu">
 	<menu label="Yo" name="Me">
-		<menu_item_call label="Panel de control..." name="Manage My Account">
-			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=es"/>
-		</menu_item_call>
 		<menu_item_call label="Perfil..." name="Profile"/>
 		<menu_item_call label="Apariencia" name="ChangeOutfit"/>
+		<menu_item_call label="Elige un avatar..." name="Avatar Picker"/>
 		<menu_item_check label="Inventario..." name="Inventory"/>
-		<menu_item_check label="Gestos..." name="Gestures"/>
-		<menu_item_check label="Voz..." name="ShowVoice"/>
+		<menu_item_call label="Nueva ventana del inventario" name="NewInventoryWindow"/>
+		<menu_item_call label="Lugares..." name="Places"/>
+		<menu_item_call label="Destacados..." name="Picks"/>
+		<menu_item_call label="Controles de la cámara..." name="Camera Controls"/>
 		<menu label="Movimiento" name="Movement">
 			<menu_item_call label="Sentarte" name="Sit Down Here"/>
 			<menu_item_check label="Volar" name="Fly"/>
@@ -22,34 +22,39 @@
 		<menu_item_call label="Solicitar estatus de Administrador" name="Request Admin Options"/>
 		<menu_item_call label="Dejar el estatus de Administrador" name="Leave Admin Options"/>
 		<menu_item_call label="Comprar L$" name="Buy and Sell L$"/>
+		<menu_item_call label="Panel de control de la cuenta..." name="Manage My Account">
+			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=es"/>
+		</menu_item_call>
 		<menu_item_call label="Preferencias..." name="Preferences"/>
-		<menu_item_call label="Barras de herramientas..." name="Toolbars"/>
+		<menu_item_call label="Botones de la barra de herramientas..." name="Toolbars"/>
 		<menu_item_call label="Ocultar todos los controles" name="Hide UI"/>
 		<menu_item_call label="Salir de [APP_NAME]" name="Quit"/>
 	</menu>
 	<menu label="Comunicarme" name="Communicate">
-		<menu_item_call label="Mis amigos" name="My Friends"/>
-		<menu_item_call label="Mis grupos" name="My Groups"/>
-		<menu_item_check label="Chat" name="Nearby Chat"/>
+		<menu_item_check label="Chat..." name="Nearby Chat"/>
+		<menu_item_check label="Hablar" name="Speak"/>
+		<menu_item_check label="Configuración de voz..." name="Nearby Voice"/>
+		<menu_item_check label="Transformación de voz..." name="ShowVoice"/>
+		<menu_item_check label="Gestos..." name="Gestures"/>
+		<menu_item_call label="Amigos" name="My Friends"/>
+		<menu_item_call label="Grupos" name="My Groups"/>
 		<menu_item_call label="Gente cerca" name="Active Speakers"/>
-		<menu_item_check label="Chat de voz" name="Nearby Voice"/>
 	</menu>
 	<menu label="Mundo" name="World">
-		<menu_item_check label="Minimapa" name="Mini-Map"/>
+		<menu_item_call label="Crear un hito de este sitio" name="Create Landmark Here"/>
+		<menu_item_call label="Destinos..." name="Destinations"/>
 		<menu_item_check label="Mapa del mundo" name="World Map"/>
+		<menu_item_check label="Minimapa" name="Mini-Map"/>
 		<menu_item_check label="Buscar" name="Search"/>
+		<menu_item_call label="Teleportar a la Base" name="Teleport Home"/>
+		<menu_item_call label="Fijar mi Base aquí" name="Set Home to Here"/>
 		<menu_item_call label="Foto" name="Take Snapshot"/>
-		<menu_item_call label="Crear un hito de este sitio" name="Create Landmark Here"/>
-		<menu label="Perfil del lugar" name="Land">
-			<menu_item_call label="Perfil del lugar" name="Place Profile"/>
-			<menu_item_call label="Acerca del terreno" name="About Land"/>
-			<menu_item_call label="Región/Estado" name="Region/Estate"/>
-		</menu>
+		<menu_item_call label="Perfil del lugar" name="Place Profile"/>
+		<menu_item_call label="Acerca del terreno" name="About Land"/>
+		<menu_item_call label="Región/Estado" name="Region/Estate"/>
+		<menu_item_call label="Mis terrenos..." name="My Land"/>
 		<menu_item_call label="Comprar este terreno" name="Buy Land"/>
-		<menu_item_call label="Mi terreno" name="My Land"/>
 		<menu label="Mostrar" name="LandShow">
-			<menu_item_check label="Controles del movimiento" name="Movement Controls"/>
-			<menu_item_check label="Controles de la cámara" name="Camera Controls"/>
 			<menu_item_check label="Líneas de prohibición" name="Ban Lines"/>
 			<menu_item_check label="Balizas" name="beacons"/>
 			<menu_item_check label="Límites de las parcelas" name="Property Lines"/>
@@ -58,16 +63,15 @@
 			<menu_item_check label="Propiedades de la parcela" name="Parcel Properties"/>
 			<menu_item_check label="Menú Avanzado" name="Show Advanced Menu"/>
 		</menu>
-		<menu_item_call label="Teleportar a la Base" name="Teleport Home"/>
-		<menu_item_call label="Fijar mi Base aquí" name="Set Home to Here"/>
 		<menu label="Sol" name="Environment Settings">
 			<menu_item_call label="Amanecer" name="Sunrise"/>
 			<menu_item_call label="Mediodía" name="Noon"/>
 			<menu_item_call label="Atardecer" name="Sunset"/>
 			<menu_item_call label="Medianoche" name="Midnight"/>
+			<menu_item_call label="Usar configuración de región" name="Use Region Settings"/>
 		</menu>
-		<menu label="Editor de entorno" name="Enviroment Editor">
-			<menu_item_call label="Configuración de entorno..." name="Enviroment Settings"/>
+		<menu label="Editor de entorno" name="Environment Editor">
+			<menu_item_call label="Configuración del entorno..." name="Environment Settings"/>
 			<menu label="Agua predefinida" name="Water Presets">
 				<menu_item_call label="Nuevo predefinido..." name="new_water_preset"/>
 				<menu_item_call label="Editar predefinido..." name="edit_water_preset"/>
@@ -146,6 +150,7 @@
 		<menu_item_call label="Rehacer" name="Redo"/>
 	</menu>
 	<menu label="Ayuda" name="Help">
+		<menu_item_call label="Cómo..." name="How To"/>
 		<menu_item_call label="Ayuda de [SECOND_LIFE]" name="Second Life Help"/>
 		<menu_item_call label="Denunciar una infracción" name="Report Abuse"/>
 		<menu_item_call label="Informar de un fallo" name="Report Bug"/>
@@ -199,11 +204,10 @@
 		<menu_item_check label="Usar Plugin Read Thread" name="Use Plugin Read Thread"/>
 		<menu_item_call label="Vaciar la caché de grupo" name="ClearGroupCache"/>
 		<menu_item_check label="Vista subjetiva suavizada" name="Mouse Smoothing"/>
+		<menu_item_call label="Recuperar las teclas" name="Release Keys"/>
 		<menu label="Atajos de teclado" name="Shortcuts">
 			<menu_item_call label="Imagen ([COST] L$)..." name="Upload Image"/>
 			<menu_item_check label="Buscar" name="Search"/>
-			<menu_item_call label="Recuperar las teclas" name="Release Keys"/>
-			<menu_item_call label="Interfaz en el tamaño predeterminado" name="Set UI Size to Default"/>
 			<menu_item_check label="Mostrar el menú Avanzado - acceso directo antiguo" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Cerrar la ventana" name="Close Window"/>
 			<menu_item_call label="Cerrar todas las ventanas" name="Close All Windows"/>
@@ -272,6 +276,7 @@
 			<menu_item_check label="Actualizar el tipo" name="Update Type"/>
 			<menu_item_check label="Información sobre el nivel de detalle" name="LOD Info"/>
 			<menu_item_check label="Crear cola" name="Build Queue"/>
+			<menu_item_check label="Vectores de viento" name="Wind Vectors"/>
 			<menu_item_check label="Complejidad del renderizado" name="rendercomplexity"/>
 			<menu_item_check label="Esculpir" name="Sculpt"/>
 		</menu>
@@ -281,7 +286,6 @@
 			<menu_item_check label="Luces y sombras" name="Lighting and Shadows"/>
 			<menu_item_check label="Sombras del sol/la luna/proyectores" name="Shadows from Sun/Moon/Projectors"/>
 			<menu_item_check label="SSAO y sombras suavizadas" name="SSAO and Shadow Smoothing"/>
-			<menu_item_check label="Iluminación global (experimental)" name="Global Illumination"/>
 			<menu_item_check label="Capas alfa automáticas (deferidas)" name="Automatic Alpha Masks (deferred)"/>
 			<menu_item_check label="Capas alfa automáticas (no deferidas)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Animation Textures" name="Animation Textures"/>
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 0de56f9b6d..e0a20683c5 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -1114,8 +1114,13 @@ El precio de compra del terreno no se le devolverá al propietario. Si se vende
 	<notification name="DisplaySetToSafe">
 		Las configuraciones que se muestran se han fijado en los niveles guardados, pues especificaste la opción de guardarlos.
 	</notification>
-	<notification name="DisplaySetToRecommended">
-		Las configuraciones que se muestran se han fijado en los niveles recomendados para la configuración de tu sistema.
+	<notification name="DisplaySetToRecommendedGPUChange">
+		La configuración de pantalla se ha establecido en los niveles recomendados porque tu tarjeta de gráficos ha cambiado
+de &apos;[LAST_GPU]&apos;
+a &apos;[THIS_GPU]&apos;
+	</notification>
+	<notification name="DisplaySetToRecommendedFeatureChange">
+		La configuración de pantalla se ha establecido en los niveles recomendados a causa de un cambio en el subsistema de renderizado.
 	</notification>
 	<notification name="ErrorMessage">
 		[ERROR_MESSAGE]
@@ -1920,7 +1925,13 @@ Dado que estos objetos tienen scripts, moverlos a tu inventario puede provocar u
 		<usetemplate ignoretext="Confirmar antes de salir" name="okcancelignore" notext="No salir" yestext="Salir"/>
 	</notification>
 	<notification name="ConfirmRestoreToybox">
-		¿Estás seguro de que quieres restaurar los botones y barras de herramientas predeterminados? 
+		Esta acción restaurará los botones y barras de herramientas predeterminados.
+
+Esta acción no se puede deshacer.
+		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
+	</notification>
+	<notification name="ConfirmClearAllToybox">
+		Esta acción volverá a colocar todos los botones a la caja de herramientas y las barras de herramientas aparecerán vacías.
     
 Esta acción no se puede deshacer.
 		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
@@ -2244,14 +2255,16 @@ Por favor, selecciona un sólo objeto.
 		Se ha rehusado tu tarjeta de visita.
 	</notification>
 	<notification name="TeleportToLandmark">
-		Puedes teleportarte a lugares como &apos;[NAME]&apos; abriendo el panel Lugares -a la derecha de tu pantalla- y seleccionando la sección Hitos.
-Pulsa en un hito para seleccionarlo, y, luego, pulsa &apos;Teleportar&apos; en la parte inferior del panel.
-(También puedes pulsar dos veces en el hito o pulsarlo con el botón derecho del ratón y elegir &apos;Teleportar&apos;.)
+		Para teleportarte a lugares como &apos;[NAME]&apos;, pulsa el botón &quot;Lugares&quot;,
+    y selecciona la pestaña Hitos en la ventana que se abre. Pulsa en un
+    hito para seleccionarlo y luego pulsa &apos;Teleportar&apos; en la parte inferior de la ventana.
+    (También puedes pulsar dos veces en el hito o pulsarlo con el botón derecho del ratón y
+    elegir &apos;Teleportar&apos;.)
 	</notification>
 	<notification name="TeleportToPerson">
-		Puedes contactar con un Residente como &apos;[NAME]&apos; abriendo el panel Gente en el lado derecho de tu pantalla.
-Elige al Residente de la lista y pulsa &apos;MI&apos; en la parte inferior del panel.
-(También puedes pulsar dos veces en su nombre o pulsarlo con el botón derecho y elegir &apos;MI&apos;).
+		Para ponerte en contacto con Residentes como &apos;[NAME]&apos;, pulsa el botón &quot;Gente&quot;, selecciona un Residente en la ventana que se abre y después pulsa en &apos;MI&apos; en
+    la parte inferior de la ventana.
+    (También puedes pulsar dos veces en su nombre o pulsarlo con el botón derecho y elegir &apos;MI&apos;).
 	</notification>
 	<notification name="CantSelectLandFromMultipleRegions">
 		No puedes seleccionar un terreno que cruce las fronteras entre servidores.
@@ -2272,6 +2285,9 @@ Inténtalo seleccionando un trozo más pequeño de terreno.
 	<notification name="PaymentSent">
 		[MESSAGE]
 	</notification>
+	<notification name="PaymentFailure">
+		[MESSAGE]
+	</notification>
 	<notification name="EventNotification">
 		Notificación de un evento:
 
@@ -2526,10 +2542,10 @@ Por favor, vuelve a intentarlo en unos momentos.
 		</form>
 	</notification>
 	<notification name="FriendshipAccepted">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; ha aceptado tu oferta de amistad.
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; ha aceptado tu ofrecimiento de amistad.
 	</notification>
 	<notification name="FriendshipDeclined">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; ha rehusado tu oferta de amistad.
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; ha rechazado tu ofrecimiento de amistad.
 	</notification>
 	<notification name="FriendshipAcceptedByMe">
 		Aceptado el ofrecimiento de amistad.
diff --git a/indra/newview/skins/default/xui/es/panel_edit_skin.xml b/indra/newview/skins/default/xui/es/panel_edit_skin.xml
index 501ecfb4de..8d895a6152 100644
--- a/indra/newview/skins/default/xui/es/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/es/panel_edit_skin.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_skin_panel">
 	<panel name="avatar_skin_color_panel">
-		<texture_picker label="Tatuajes de la cabeza" name="Head Tattoos" tool_tip="Pulsa para elegir una imagen"/>
-		<texture_picker label="Tatuajes superiores" name="Upper Tattoos" tool_tip="Pulsa para elegir una imagen"/>
-		<texture_picker label="Tatuajes inferiores" name="Lower Tattoos" tool_tip="Pulsa para elegir una imagen"/>
+		<texture_picker label="Cabeza" name="Head" tool_tip="Pulsa para elegir una imagen"/>
+		<texture_picker label="Parte superior del cuerpo" name="Upper Body" tool_tip="Pulsa para elegir una imagen"/>
+		<texture_picker label="Parte inferior del cuerpo" name="Lower Body" tool_tip="Pulsa para elegir una imagen"/>
 	</panel>
 	<panel name="accordion_panel">
 		<accordion name="wearable_accordion">
diff --git a/indra/newview/skins/default/xui/es/panel_nearby_chat.xml b/indra/newview/skins/default/xui/es/panel_nearby_chat.xml
index 5a852a6711..4220ab3c9f 100644
--- a/indra/newview/skins/default/xui/es/panel_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/es/panel_nearby_chat.xml
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="nearby_chat">
-	<check_box label="Traducir chat" name="translate_chat_checkbox"/>
+	<check_box label="Traducir el chat" name="translate_chat_checkbox"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/es/panel_postcard_message.xml b/indra/newview/skins/default/xui/es/panel_postcard_message.xml
new file mode 100644
index 0000000000..7316d91f5c
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_postcard_message.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_message">
+	<text name="to_label">
+		Hasta:
+	</text>
+	<text name="name_label">
+		Desde:
+	</text>
+	<text name="subject_label">
+		Asunto:
+	</text>
+	<line_editor label="Escribe aquí el asunto." name="subject_form"/>
+	<text name="msg_label">
+		Mensaje:
+	</text>
+	<text_editor name="msg_form">
+		Escribe aquí tu mensaje.
+	</text_editor>
+	<button label="Cancelar" name="cancel_btn"/>
+	<button label="Enviar" name="send_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_postcard_settings.xml b/indra/newview/skins/default/xui/es/panel_postcard_settings.xml
new file mode 100644
index 0000000000..3931319447
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_postcard_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_settings">
+	<combo_box label="Resolución" name="postcard_size_combo">
+		<combo_box.item label="Ventana actual" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Personalizado" name="Custom"/>
+	</combo_box>
+	<layout_stack name="postcard_image_params_ls">
+		<layout_panel name="postcard_image_size_lp">
+			<spinner label="Ancho" name="postcard_snapshot_width"/>
+			<spinner label="Altura" name="postcard_snapshot_height"/>
+			<check_box label="Mantener las proporciones" name="postcard_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="postcard_image_format_quality_lp">
+			<slider label="Calidad de la imagen" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
index e822585566..aea9b9ce4a 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
@@ -29,30 +29,5 @@
 	<check_box label="Chats de MI" name="EnableIMChatPopups" tool_tip="Activa esta casilla para ver una ventana emergente cada vez que recibas un mensaje instantáneo"/>
 	<spinner label="Duración de los interlocutores favoritos:" name="nearby_toasts_lifetime"/>
 	<spinner label="Tiempo de los otros interlocutores:" name="nearby_toasts_fadingtime"/>
-	<check_box name="translate_chat_checkbox"/>
-	<text name="translate_chb_label">
-		Usar en el chat el traductor automático
-	</text>
-	<text name="translate_language_text">
-		Traducir el chat al:
-	</text>
-	<combo_box name="translate_language_combobox">
-		<combo_box.item label="Predeterminado del sistema" name="System Default Language"/>
-		<combo_box.item label="English (inglés)" name="English"/>
-		<combo_box.item label="Dansk (danés)" name="Danish"/>
-		<combo_box.item label="Deutsch (alemán)" name="German"/>
-		<combo_box.item label="Español" name="Spanish"/>
-		<combo_box.item label="Français (francés)" name="French"/>
-		<combo_box.item label="Italiano (italiano)" name="Italian"/>
-		<combo_box.item label="Magyar (húngaro)" name="Hungarian"/>
-		<combo_box.item label="Nederlands (neerlandés)" name="Dutch"/>
-		<combo_box.item label="Polski (polaco)" name="Polish"/>
-		<combo_box.item label="Português (portugués)" name="Portugese"/>
-		<combo_box.item label="Русский (ruso)" name="Russian"/>
-		<combo_box.item label="Türkçe (turco)" name="Turkish"/>
-		<combo_box.item label="Українська (ucraniano)" name="Ukrainian"/>
-		<combo_box.item label="中文 (正體) (Chino)" name="Chinese"/>
-		<combo_box.item label="日本語 (japonés)" name="Japanese"/>
-		<combo_box.item label="한국어 (coreano)" name="Korean"/>
-	</combo_box>
+	<button label="Configuración de la traducción del chat" name="ok_btn"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
index 3de18654b5..81a29dae5a 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
@@ -15,7 +15,7 @@
 		Web:
 	</text>
 	<radio_group name="use_external_browser">
-		<radio_item label="Usar mi navegador (IE, Firefox, Safari)" name="external" tool_tip="Usa tu navegador por defecto para ayuda, enlaces web, etc. No es aconsejable si estás a pantalla completa." value="1"/>
+		<radio_item label="Usar mi navegador (IE, Firefox, Safari)" name="external" tool_tip="Usa tu navegador por defecto para ayuda, enlaces web, etc. No es aconsejable si estás a pantalla completa." value="true"/>
 		<radio_item label="Usar el navegador incorporado" name="internal" tool_tip="Usa el navegador incorporado para ayuda, enlaces web, etc. Este navegador se abre en una nueva ventana dentro de [APP_NAME]." value=""/>
 	</radio_group>
 	<check_box initial_value="true" label="Activar plugins" name="browser_plugins_enabled"/>
diff --git a/indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml
new file mode 100644
index 0000000000..12c74b5cd1
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_inventory">
+	<text name="title">
+		Guardar en mi inventario
+	</text>
+	<text name="hint_lbl">
+		Guardar una imagen en el inventario cuesta [UPLOAD_COST] L$. Para guardar una imagen como una textura, selecciona uno de los formatos cuadrados.
+	</text>
+	<combo_box label="Resolución" name="texture_size_combo">
+		<combo_box.item label="Ventana actual" name="CurrentWindow"/>
+		<combo_box.item label="Pequeña (128x128)" name="Small(128x128)"/>
+		<combo_box.item label="Mediana (256x256)" name="Medium(256x256)"/>
+		<combo_box.item label="Grande (512x512)" name="Large(512x512)"/>
+		<combo_box.item label="Personalizado" name="Custom"/>
+	</combo_box>
+	<spinner label="Ancho" name="inventory_snapshot_width"/>
+	<spinner label="Altura" name="inventory_snapshot_height"/>
+	<check_box label="Mantener las proporciones" name="inventory_keep_aspect_check"/>
+	<button label="Cancelar" name="cancel_btn"/>
+	<button label="Guardar" name="save_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_snapshot_local.xml b/indra/newview/skins/default/xui/es/panel_snapshot_local.xml
new file mode 100644
index 0000000000..08c45d2e76
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_snapshot_local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_local">
+	<text name="title">
+		Guardar en mi ordenador
+	</text>
+	<combo_box label="Resolución" name="local_size_combo">
+		<combo_box.item label="Ventana actual" name="CurrentWindow"/>
+		<combo_box.item label="320x240" name="320x240"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="1280x1024" name="1280x1024"/>
+		<combo_box.item label="1600x1200" name="1600x1200"/>
+		<combo_box.item label="Personalizado" name="Custom"/>
+	</combo_box>
+	<layout_stack name="local_image_params_ls">
+		<layout_panel name="local_image_size_lp">
+			<spinner label="Ancho" name="local_snapshot_width"/>
+			<spinner label="Altura" name="local_snapshot_height"/>
+			<check_box label="Mantener las proporciones" name="local_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="local_image_format_quality_lp">
+			<combo_box label="Formato" name="local_format_combo">
+				<combo_box.item label="PNG (sin pérdida)" name="PNG"/>
+				<combo_box.item label="JPEG" name="JPEG"/>
+				<combo_box.item label="BMP (sin pérdida)" name="BMP"/>
+			</combo_box>
+			<slider label="Calidad de la imagen" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+	<button label="Cancelar" name="cancel_btn"/>
+	<flyout_button label="Guardar" name="save_btn" tool_tip="Guardar la imagen en un archivo">
+		<flyout_button.item label="Guardar" name="save_item"/>
+		<flyout_button.item label="Guardar como..." name="saveas_item"/>
+	</flyout_button>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_snapshot_options.xml b/indra/newview/skins/default/xui/es/panel_snapshot_options.xml
new file mode 100644
index 0000000000..2b2584f66c
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_snapshot_options.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_options">
+	<button label="Publicar en los comentarios de Mi perfil" name="save_to_profile_btn"/>
+	<button label="Correo-e" name="save_to_email_btn"/>
+	<button label="Guardar en Mi inventario ([AMOUNT] L$)" name="save_to_inventory_btn"/>
+	<button label="Guardar en mi ordenador" name="save_to_computer_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml
new file mode 100644
index 0000000000..649d547ba0
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+	<string name="default_subject">
+		Postal desde [SECOND_LIFE].
+	</string>
+	<string name="default_message">
+		¡Mira esto!
+	</string>
+	<string name="upload_message">
+		Enviando...
+	</string>
+	<text name="title">
+		Correo-e
+	</text>
+	<button label="Mensaje" name="message_btn"/>
+	<button label="Ajustes" name="settings_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/es/panel_snapshot_profile.xml
new file mode 100644
index 0000000000..6a0bc22d68
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_snapshot_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_profile">
+	<text name="title">
+		Publicar en los comentarios de Mi perfil
+	</text>
+	<combo_box label="Resolución" name="profile_size_combo">
+		<combo_box.item label="Ventana actual" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Personalizado" name="Custom"/>
+	</combo_box>
+	<layout_stack name="profile_image_params_ls">
+		<layout_panel name="profile_image_size_lp">
+			<spinner label="Ancho" name="profile_snapshot_width"/>
+			<spinner label="Altura" name="profile_snapshot_height"/>
+			<check_box label="Mantener las proporciones" name="profile_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="profile_image_metadata_lp">
+			<text name="caption_label">
+				Título:
+			</text>
+			<check_box initial_value="true" label="Incluir ubicación" name="add_location_cb"/>
+		</layout_panel>
+	</layout_stack>
+	<button label="Cancelar" name="cancel_btn"/>
+	<button label="Publicar" name="post_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index e3ea4baa6c..2a6f32f84f 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -1199,7 +1199,7 @@ Intenta iniciar sesión de nuevo en unos instantes.
 		No tienes en tu inventario una copia de esta textura
 	</string>
 	<string name="InventoryInboxNoItems">
-		Aquí se entregarán los objetos comprados en el mercado.
+		Cuando compres un objeto o lo recibas por otra vía, aparecerá aquí, para que puedas arrastrarlo a una carpeta de tu inventario o eliminarlo si no deseas conservarlo.
 	</string>
 	<string name="MarketplaceURL">
 		http://marketplace.[DOMAIN_NAME]
@@ -1391,6 +1391,9 @@ Intenta iniciar sesión de nuevo en unos instantes.
 	<string name="no_attachments">
 		No tienes puestos anexos
 	</string>
+	<string name="Attachments remain">
+		Anexos (quedan [COUNT] ranuras)
+	</string>
 	<string name="Buy">
 		Comprar
 	</string>
@@ -1517,6 +1520,12 @@ Intenta iniciar sesión de nuevo en unos instantes.
 	<string name="Right Pec">
 		Pecho derecho
 	</string>
+	<string name="Neck">
+		Cuello
+	</string>
+	<string name="Avatar Center">
+		Centro del avatar
+	</string>
 	<string name="Invalid Attachment">
 		Punto de colocación no válido
 	</string>
@@ -3943,6 +3952,18 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE].
 	<string name="you_paid_ldollars_no_name">
 		Has pagado [AMOUNT] L$ por [REASON].
 	</string>
+	<string name="you_paid_failure_ldollars">
+		No has pagado a [NAME] [AMOUNT] L$ [REASON].
+	</string>
+	<string name="you_paid_failure_ldollars_no_info">
+		No has pagado [AMOUNT] L$.
+	</string>
+	<string name="you_paid_failure_ldollars_no_reason">
+		No has pagado a [NAME] [AMOUNT] L$.
+	</string>
+	<string name="you_paid_failure_ldollars_no_name">
+		No has pagado [AMOUNT] L$ [REASON].
+	</string>
 	<string name="for item">
 		para [ITEM]
 	</string>
@@ -4353,6 +4374,12 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 	<string name="ExternalEditorFailedToRun">
 		Error al ejecutar el editor externo.
 	</string>
+	<string name="TranslationFailed">
+		Error al traducir: [REASON]
+	</string>
+	<string name="TranslationResponseParseError">
+		Error al analizar la respuesta de la traducción.
+	</string>
 	<string name="Esc">
 		Esc
 	</string>
@@ -4723,7 +4750,7 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 		Minimapa
 	</string>
 	<string name="Command_Move_Label">
-		Moverme
+		Caminar / Correr / Volar
 	</string>
 	<string name="Command_People_Label">
 		Gente
@@ -4750,10 +4777,10 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 		Hablar
 	</string>
 	<string name="Command_View_Label">
-		Visión
+		Controles de la cámara
 	</string>
 	<string name="Command_Voice_Label">
-		Chat de voz
+		Configuración de voz
 	</string>
 	<string name="Command_AboutLand_Tooltip">
 		Información sobre el terreno que vas a visitar
@@ -4825,7 +4852,16 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 		Cambiando el ángulo de la cámara
 	</string>
 	<string name="Command_Voice_Tooltip">
-		Personas próximas con capacidad de voz
+		Controles de volumen para las llamadas y la gente que se encuentre cerca de ti en el mundo virtual
+	</string>
+	<string name="Toolbar_Bottom_Tooltip">
+		actualmente en tu barra de herramientas inferior
+	</string>
+	<string name="Toolbar_Left_Tooltip">
+		actualmente en tu barra de herramientas izquierda
+	</string>
+	<string name="Toolbar_Right_Tooltip">
+		actualmente en tu barra de herramientas derecha
 	</string>
 	<string name="Retain%">
 		% retención
@@ -4851,4 +4887,19 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 	<string name="Normal">
 		Normal
 	</string>
+	<string name="snapshot_quality_very_low">
+		Muy bajo
+	</string>
+	<string name="snapshot_quality_low">
+		Bajo
+	</string>
+	<string name="snapshot_quality_medium">
+		Medio
+	</string>
+	<string name="snapshot_quality_high">
+		Alto
+	</string>
+	<string name="snapshot_quality_very_high">
+		Muy alto
+	</string>
 </strings>
diff --git a/indra/newview/skins/default/xui/es/teleport_strings.xml b/indra/newview/skins/default/xui/es/teleport_strings.xml
index e785a7ac40..a23d9c43d0 100644
--- a/indra/newview/skins/default/xui/es/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/es/teleport_strings.xml
@@ -20,8 +20,8 @@ Si sigues recibiendo este mensaje, por favor, acude al [SUPPORT_SITE].
 Vuelva a intentarlo en un momento.
 		</message>
 		<message name="NoHelpIslandTP">
-		No puede teleportarse de vuelta a la Welcome Island (&apos;Isla de Ayuda&apos;).
-Vaya a la &apos;Welcome Island Public&apos; (&apos;Isla Pública de Ayuda&apos;) para repetir el tutorial.
+			No te puedes volver a teleportar a la isla de bienvenida.
+Para repetir el tutorial, visita la isla de bienvenida pública.
 		</message>
 		<message name="noaccess_tport">
 			Lo sentimos, pero no tienes acceso al destino de este teleporte.
diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml
index 4d02513a53..4409949584 100644
--- a/indra/newview/skins/default/xui/fr/floater_about.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about.xml
@@ -67,32 +67,34 @@ Version serveur vocal : [VOICE_VERSION]
 		<panel label="Licences" name="licenses_panel">
 			<text_editor name="credits_editor">
 				3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
-APR Copyright (C) 2000-2004 The Apache Software Foundation
-Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
-cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
-DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
-expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
-FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
-GL Copyright (C) 1999-2004 Brian Paul.
-GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University et David Luebke, Brenden Schubert, University of Virginia.
-google-perftools Copyright (c) 2005, Google Inc.
-Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
-jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
-jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
-ogg/vorbis Copyright (C) 2001, Xiphophorus
-OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
-PCRE Copyright (c) 1997-2008 University of Cambridge
-SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
-SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
-xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
-zlib Copyright (C) 1995-2002 Jean-loup Gailly et Mark Adler.
-google-perftools Copyright (c) 2005, Google Inc.
+        APR Copyright (C) 2000-2004 The Apache Software Foundation
+        Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
+        cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
+        DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
+        expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
+        FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
+        GL Copyright (C) 1999-2004 Brian Paul.
+        GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University et David Luebke, Brenden Schubert, University of Virginia.
+        google-perftools Copyright (c) 2005, Google Inc.
+        Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
+        jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
+        jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
+        ogg/vorbis Copyright (C) 2001, Xiphophorus
+        OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
+        PCRE Copyright (c) 1997-2008 University of Cambridge
+        SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+        SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+        xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
+        zlib Copyright (C) 1995-2002 Jean-loup Gailly et Mark Adler.
+        google-perftools Copyright (c) 2005, Google Inc.
 
-Le client Second Life utilise Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (et ses concédants de licence). Tous droits réservés. Pour plus de détails, consultez le site Web www.havok.com.
+        Le client Second Life utilise Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (et ses concédants de licence). Tous droits réservés. Pour plus de détails, consultez le site Web www.havok.com.
 
-Tous droits réservés. Voir licenses.txt pour plus d&apos;informations.
+        Ce logiciel contient du code source fourni par NVIDIA Corporation.
 
-Codage audio du chat vocal : Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
+        Tous droits réservés.  Voir licenses.txt pour plus d&apos;informations.
+
+        Codage audio du chat vocal : Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
 			</text_editor>
 		</panel>
 	</tab_container>
diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml
index 9771c3f7fd..b554a0a892 100644
--- a/indra/newview/skins/default/xui/fr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml
@@ -132,7 +132,7 @@
 				Trafic :
 			</text>
 			<text name="DwellText">
-				0
+				Chargement...
 			</text>
 			<button label="Acheter du terrain" label_selected="Acheter le terrain..." left_delta="60" name="Buy Land..." width="125"/>
 			<button label="Vente Linden" label_selected="Vente Linden..." name="Linden Sale..." tool_tip="Le terrain doit être la propriété d&apos;un résident, avoir un contenu défini et ne pas être aux enchères."/>
@@ -313,13 +313,15 @@ Seules les parcelles de grande taille peuvent apparaître dans la recherche.
 				Pas de bousculades (les règles de la région priment)
 			</panel.string>
 			<panel.string name="see_avs_text">
-				Voir et chatter avec les résidents sur cette parcelle
+				Les avatars sur les autres parcelles peuvent voir
 			</panel.string>
 			<text name="allow_label">
 				Autoriser les autres résidents à :
 			</text>
-			<check_box label="Modifier le terrain" name="edit land check" tool_tip="Si cette option est cochée, n&apos;importe qui peut terraformer votre terrain. Il vaut mieux ne pas cocher cette option pour toujours pouvoir modifer votre propre terrain."/>
-			<check_box label="Voler" name="check fly" tool_tip="Si cette option est cochée, les résidents peuvent voler sur votre terrain. Si elle n&apos;est pas cochée, ils ne pourront voler que lorsqu&apos;ils arrivent et passent au dessus de votre terrain."/>
+			<text name="allow_label0">
+				Voler :
+			</text>
+			<check_box label="Tous" name="check fly" tool_tip="Si cette option est cochée, les résidents peuvent voler sur votre terrain. Si elle n&apos;est pas cochée, ils ne pourront voler que lorsqu&apos;ils arrivent et passent au dessus de votre terrain."/>
 			<text name="allow_label2">
 				Construire :
 			</text>
@@ -335,9 +337,6 @@ Seules les parcelles de grande taille peuvent apparaître dans la recherche.
 			</text>
 			<check_box label="Tous" name="check other scripts"/>
 			<check_box label="Groupe" name="check group scripts"/>
-			<text name="land_options_label">
-				Options du terrain :
-			</text>
 			<check_box label="Sécurisé (pas de dégâts)" name="check safe" tool_tip="Si cette option est cochée, le terrain est sécurisé et il n&apos;y pas de risques de dommages causés par des combats. Si elle est décochée, des dommages causés par les combats peuvent avoir lieu."/>
 			<check_box label="Pas de bousculades" name="PushRestrictCheck" tool_tip="Empêche l&apos;utilisation de scripts causant des bousculades. Cette option est utile pour empêcher les comportements abusifs sur votre terrain."/>
 			<check_box label="Afficher le lieu dans la recherche (30 L$/semaine)" name="ShowDirectoryCheck" tool_tip="Afficher la parcelle dans les résultats de recherche"/>
@@ -378,9 +377,9 @@ Seules les parcelles de grande taille peuvent apparaître dans la recherche.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Cliquez pour sélectionner une image"/>
 			<text name="allow_label5">
-				Autoriser les résidents sur les autres parcelles à :
+				et chatter avec les avatars sur cette parcelle
 			</text>
-			<check_box label="Voir les avatars" name="SeeAvatarsCheck" tool_tip="Permettre aux résidents présents sur d&apos;autres parcelles de voir et chatter avec les résidents présents sur cette parcelle et vous permettre de les voir et de chatter avec eux."/>
+			<check_box label="Voir les avatars" name="SeeAvatarsCheck" tool_tip="Permettre aux avatars présents sur d&apos;autres parcelles de voir et chatter avec les avatars présents sur cette parcelle et à vous de les voir et de chatter avec eux."/>
 			<text name="landing_point">
 				Lieu d&apos;arrivée : [LANDING]
 			</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_avatar.xml b/indra/newview/skins/default/xui/fr/floater_avatar.xml
index cfbac66c0e..7cbb50a3d6 100644
--- a/indra/newview/skins/default/xui/fr/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/fr/floater_avatar.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Avatar" title="CHOIX D&apos;AVATAR"/>
+<floater name="Avatar" title="CHOISIR UN AVATAR"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index d9e8e8821d..148a5a35d2 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -22,10 +22,10 @@ le Lindex...
 	<text name="currency_action">
 		Je veux acheter
 	</text>
-	<text name="currency_label" left="308">
+	<text left="308" name="currency_label">
 		L$
 	</text>
-	<line_editor label="L$" name="currency_amt" width="65" left_pad="-85">
+	<line_editor label="L$" left_pad="-85" name="currency_amt" width="65">
 		1234
 	</line_editor>
 	<text name="buying_label">
@@ -47,13 +47,13 @@ le Lindex...
 		[AMT] L$
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php?lang=fr-FR mode de paiement] | [http://www.secondlife.com/my/account/currency.php?lang=fr-FR devise]
+		[http://www.secondlife.com/my/account/payment_method_management.php mode de paiement] | [http://www.secondlife.com/my/account/currency.php devise]
 	</text>
 	<text name="exchange_rate_note">
 		Saisissez à nouveau le montant pour voir le taux de change actuel.
 	</text>
 	<text name="purchase_warning_repurchase">
-		Confirmer cet achat n'achète que des L$, pas l'objet.
+		Confirmer cet achat n&apos;achète que des L$, pas l&apos;objet.
 	</text>
 	<text bottom_delta="16" name="purchase_warning_notenough">
 		Vous n&apos;achetez pas assez de L$. Veuillez augmenter le montant.
diff --git a/indra/newview/skins/default/xui/fr/floater_camera.xml b/indra/newview/skins/default/xui/fr/floater_camera.xml
index 77d3c2cfe4..f2b0ee8af3 100644
--- a/indra/newview/skins/default/xui/fr/floater_camera.xml
+++ b/indra/newview/skins/default/xui/fr/floater_camera.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="camera_floater" title="AFFICHER">
+<floater name="camera_floater" title="PARAMÈTRES DE LA CAMÉRA">
 	<floater.string name="rotate_tooltip">
 		Faire tourner la caméra autour du point central
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml
index 8ad301823b..2bc76e0c63 100644
--- a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml
@@ -4,7 +4,7 @@
 		Filtres :
 	</text>
 	<check_box label="Filtre anisotrope (plus lent si activé)" name="ani"/>
-	<text name="Antialiasing:">
+	<text name="antialiasing label">
 		Anti-aliasing :
 	</text>
 	<combo_box label="Anti-aliasing" name="fsaa" width="84">
diff --git a/indra/newview/skins/default/xui/fr/floater_model_preview.xml b/indra/newview/skins/default/xui/fr/floater_model_preview.xml
index a26deb1aef..a3b50351ae 100644
--- a/indra/newview/skins/default/xui/fr/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/fr/floater_model_preview.xml
@@ -4,6 +4,9 @@
 	<string name="status_parse_error">
 		Erreur : Problème d&apos;analyse de fichier .dae ; reportez-vous au journal pour plus de détails.
 	</string>
+	<string name="status_material_mismatch">
+		Erreur : le matériau du modèle ne correspond pas à un sous-ensemble du modèle de référence.
+	</string>
 	<string name="status_reading_file">
 		Chargement...
 	</string>
@@ -137,7 +140,7 @@
 				</panel>
 				<panel name="physics analysis">
 					<text name="method_label">
-						Étape 2 : Analyse
+						Étape 2 : Analyser
 					</text>
 					<text name="analysis_method_label">
 						Moyen :
diff --git a/indra/newview/skins/default/xui/fr/floater_model_wizard.xml b/indra/newview/skins/default/xui/fr/floater_model_wizard.xml
index cd2eb761ec..63feb1d403 100644
--- a/indra/newview/skins/default/xui/fr/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/fr/floater_model_wizard.xml
@@ -20,6 +20,9 @@
 				Choisir un fichier de modèle à charger
 			</text>
 			<button label="Parcourir..." label_selected="Parcourir..." name="browse"/>
+			<text name="Model types">
+				Second Life prend en charge les fichiers COLLADA (.dae).
+			</text>
 			<text name="dimensions">
 				X         Y         Z
 			</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_moveview.xml b/indra/newview/skins/default/xui/fr/floater_moveview.xml
index 0b0ec51846..853af2afdf 100644
--- a/indra/newview/skins/default/xui/fr/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/fr/floater_moveview.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move_floater" title="BOUGER">
+<floater name="move_floater" title="MARCHER / COURIR / VOLER">
 	<string name="walk_forward_tooltip">
 		Marcher en avant (appuyer sur la flèche vers le haut ou W)
 	</string>
diff --git a/indra/newview/skins/default/xui/fr/floater_snapshot.xml b/indra/newview/skins/default/xui/fr/floater_snapshot.xml
index 365ff77ff9..9244051edc 100644
--- a/indra/newview/skins/default/xui/fr/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/fr/floater_snapshot.xml
@@ -3,73 +3,63 @@
 	<floater.string name="unknown">
 		inconnu
 	</floater.string>
-	<radio_group label="Type de photo" name="snapshot_type_radio">
-		<radio_item label="E-mail" name="postcard"/>
-		<radio_item label="Mon inventaire ([AMOUNT] L$)" name="texture"/>
-		<radio_item label="Enregistrer sur mon ordinateur" name="local"/>
-	</radio_group>
+	<string name="postcard_progress_str">
+		Envoi par e-mail
+	</string>
+	<string name="profile_progress_str">
+		Publication
+	</string>
+	<string name="inventory_progress_str">
+		Enregistrement dans l&apos;inventaire
+	</string>
+	<string name="local_progress_str">
+		Enregistrement sur l&apos;ordinateur
+	</string>
+	<string name="profile_succeeded_str">
+		Image chargée
+	</string>
+	<string name="postcard_succeeded_str">
+		Envoi par e-mail effectué !
+	</string>
+	<string name="inventory_succeeded_str">
+		Enregistrement dans l&apos;inventaire effectué !
+	</string>
+	<string name="local_succeeded_str">
+		Enregistrement sur l&apos;ordinateur effectué !
+	</string>
+	<string name="profile_failed_str">
+		Échec de chargement de l&apos;image sur le flux de votre profil.
+	</string>
+	<string name="postcard_failed_str">
+		Échec d&apos;envoi par e-mail.
+	</string>
+	<string name="inventory_failed_str">
+		Échec d&apos;enregistrement dans l&apos;inventaire.
+	</string>
+	<string name="local_failed_str">
+		Échec d&apos;enregistrement sur l&apos;ordinateur.
+	</string>
+	<button name="advanced_options_btn" tool_tip="Options avancées"/>
+	<text name="image_res_text">
+		[WIDTH] x [HEIGHT] px
+	</text>
 	<text name="file_size_label">
 		[SIZE] Ko
 	</text>
-	<button label="Rafraîchir" name="new_snapshot_btn"/>
-	<button label="Envoyer" name="send_btn"/>
-	<button label="Enreg. ([AMOUNT] L$)" name="upload_btn"/>
-	<flyout_button label="Enregistrer" name="save_btn" tool_tip="Enregistrer l&apos;image sous forme de fichier">
-		<flyout_button.item label="Enregistrer" name="save_item"/>
-		<flyout_button.item label="Enregistrer sous..." name="saveas_item"/>
-	</flyout_button>
-	<button label="Plus" name="more_btn" tool_tip="Options avancées"/>
-	<button label="Moins" name="less_btn" tool_tip="Options avancées"/>
-	<button label="Annuler" name="discard_btn"/>
-	<text name="type_label2">
-		Taille
-	</text>
-	<text name="format_label">
-		Format
-	</text>
-	<combo_box label="Résolution" name="postcard_size_combo">
-		<combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
-		<combo_box.item label="640 x 480" name="640x480"/>
-		<combo_box.item label="800 x 600" name="800x600"/>
-		<combo_box.item label="1 024 x 768" name="1024x768"/>
-		<combo_box.item label="Personnalisée" name="Custom"/>
-	</combo_box>
-	<combo_box label="Résolution" name="texture_size_combo">
-		<combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
-		<combo_box.item label="Petite (128 x 128)" name="Small(128x128)"/>
-		<combo_box.item label="Moyenne (256 x 256)" name="Medium(256x256)"/>
-		<combo_box.item label="Grande (512 x 512)" name="Large(512x512)"/>
-		<combo_box.item label="Personnalisée" name="Custom"/>
-	</combo_box>
-	<combo_box label="Résolution" name="local_size_combo">
-		<combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
-		<combo_box.item label="320 x 240" name="320x240"/>
-		<combo_box.item label="640 x 480" name="640x480"/>
-		<combo_box.item label="800 x 600" name="800x600"/>
-		<combo_box.item label="1 024 x 768" name="1024x768"/>
-		<combo_box.item label="1 280 x 1 024" name="1280x1024"/>
-		<combo_box.item label="1 600 x 1 200" name="1600x1200"/>
-		<combo_box.item label="Personnalisée" name="Custom"/>
-	</combo_box>
-	<combo_box label="Format" name="local_format_combo">
-		<combo_box.item label="PNG" name="PNG"/>
-		<combo_box.item label="JPEG" name="JPEG"/>
-		<combo_box.item label="BMP" name="BMP"/>
-	</combo_box>
-	<spinner label="Larg." name="snapshot_width"/>
-	<spinner label="Haut." name="snapshot_height"/>
-	<check_box label="Contraindre les proportions" name="keep_aspect_check"/>
-	<slider label="Qualité de l&apos;image" name="image_quality_slider"/>
-	<text name="layer_type_label">
-		Capturer :
-	</text>
-	<combo_box label="Couches d&apos;images" name="layer_types">
-		<combo_box.item label="Couleurs" name="Colors"/>
-		<combo_box.item label="Profondeur" name="Depth"/>
-	</combo_box>
-	<check_box label="Interface" name="ui_check"/>
-	<check_box label="HUD" name="hud_check"/>
-	<check_box label="Garder ouvert après enregistrement" name="keep_open_check"/>
-	<check_box label="Arrêt sur image (plein écran)" name="freeze_frame_check"/>
-	<check_box label="Actualisation automatique" name="auto_snapshot_check"/>
+	<panel name="advanced_options_panel">
+		<text name="advanced_options_label">
+			OPTIONS AVANCÉES
+		</text>
+		<text name="layer_type_label">
+			Capturer :
+		</text>
+		<combo_box label="Couches d&apos;images" name="layer_types">
+			<combo_box.item label="Couleurs" name="Colors"/>
+			<combo_box.item label="Profondeur" name="Depth"/>
+		</combo_box>
+		<check_box label="Interface" name="ui_check"/>
+		<check_box label="HUD" name="hud_check"/>
+		<check_box label="Arrêt sur image (plein écran)" name="freeze_frame_check"/>
+		<check_box label="Actualisation automatique" name="auto_snapshot_check"/>
+	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_toybox.xml b/indra/newview/skins/default/xui/fr/floater_toybox.xml
index 33aea6bb2d..f99d3d30b5 100644
--- a/indra/newview/skins/default/xui/fr/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/fr/floater_toybox.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Toybox" title="PERSONNALISER LES BARRES D&apos;OUTILS">
+<floater name="Toybox" title="BOUTONS DES BARRES D&apos;OUTILS">
 	<text name="toybox label 1">
 		Ajouter ou supprimer des boutons : les faire glisser vers ou depuis les barres d&apos;outils.
 	</text>
 	<text name="toybox label 2">
 		Ils s&apos;afficheront comme indiqué ou comme des icônes, selon les paramètres de barre d&apos;outils.
 	</text>
+	<button label="Effacer tout" label_selected="Effacer tout" name="btn_clear_all"/>
 	<button label="Valeurs par défaut" label_selected="Valeurs par défaut" name="btn_restore_defaults"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_translation_settings.xml b/indra/newview/skins/default/xui/fr/floater_translation_settings.xml
new file mode 100644
index 0000000000..c7582f110f
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_translation_settings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_translation_settings" title="TRADUCTION AUTOMATIQUE">
+	<string name="bing_api_key_not_verified">
+		ID d&apos;application Bing non vérifié. Veuillez réessayer.
+	</string>
+	<string name="google_api_key_not_verified">
+		Clé d&apos;API Google non vérifiée. Veuillez réessayer.
+	</string>
+	<string name="bing_api_key_verified">
+		ID d&apos;application Bing vérifié.
+	</string>
+	<string name="google_api_key_verified">
+		Clé d&apos;API Google vérifiée.
+	</string>
+	<check_box label="Activer la traduction automatique lors des chats" name="translate_chat_checkbox"/>
+	<text name="translate_language_label">
+		Traduire les chats en :
+	</text>
+	<combo_box name="translate_language_combo">
+		<combo_box.item label="Langue système par défaut" name="System Default Language"/>
+		<combo_box.item label="English (Anglais)" name="English"/>
+		<combo_box.item label="Dansk (Danois)" name="Danish"/>
+		<combo_box.item label="Deutsch (Allemand)" name="German"/>
+		<combo_box.item label="Español (Espagnol)" name="Spanish"/>
+		<combo_box.item label="Français" name="French"/>
+		<combo_box.item label="Italiano (Italien)" name="Italian"/>
+		<combo_box.item label="Magyar (Hongrois)" name="Hungarian"/>
+		<combo_box.item label="Nederlands (Néerlandais)" name="Dutch"/>
+		<combo_box.item label="Polski (Polonais)" name="Polish"/>
+		<combo_box.item label="Português (Portugais)" name="Portugese"/>
+		<combo_box.item label="Русский (Russe)" name="Russian"/>
+		<combo_box.item label="Türkçe (Turc)" name="Turkish"/>
+		<combo_box.item label="Українська (Ukrainien)" name="Ukrainian"/>
+		<combo_box.item label="中文 (正體) (Chinois)" name="Chinese"/>
+		<combo_box.item label="日本語 (Japonais)" name="Japanese"/>
+		<combo_box.item label="한국어 (Coréen)" name="Korean"/>
+	</combo_box>
+	<text name="tip">
+		Choisir le service à utiliser :
+	</text>
+	<radio_group name="translation_service_rg">
+		<radio_item initial_value="bing" label="Bing Translator" name="bing"/>
+		<radio_item initial_value="google" label="Google Translate" name="google"/>
+	</radio_group>
+	<text name="bing_api_key_label">
+		[http://www.bing.com/developers/createapp.aspx ID d&apos;application] Bing :
+	</text>
+	<button label="Vérifier" name="verify_bing_api_key_btn"/>
+	<text name="google_api_key_label">
+		[http://code.google.com/apis/language/translate/v2/getting_started.html#auth Clé d&apos;API] Google :
+	</text>
+	<button label="Vérifier" name="verify_google_api_key_btn"/>
+	<text name="google_links_text">
+		[http://code.google.com/apis/language/translate/v2/pricing.html Tarification] | [https://code.google.com/apis/console Statistiques]
+	</text>
+	<button label="OK" name="ok_btn"/>
+	<button label="Annuler" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_voice_controls.xml b/indra/newview/skins/default/xui/fr/floater_voice_controls.xml
index 2b2bb8bbe3..fc4de4a5a6 100644
--- a/indra/newview/skins/default/xui/fr/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/fr/floater_voice_controls.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="floater_voice_controls" title="CONTROLES DE LA VOIX">
 	<string name="title_nearby">
-		Chat près de vous
+		PARAMÈTRES VOCAUX
 	</string>
 	<string name="title_group">
-		Appel de groupe avec [GROUP]
+		APPEL DE GROUPE AVEC [GROUP]
 	</string>
 	<string name="title_adhoc">
-		Téléconférence
+		CONFÉRENCE
 	</string>
 	<string name="title_peer_2_peer">
-		Appel avec [NAME]
+		APPEL AVEC [NAME]
 	</string>
 	<string name="no_one_near">
 		Il n&apos;y a personne près de vous avec le chat vocal activé
diff --git a/indra/newview/skins/default/xui/fr/menu_toolbars.xml b/indra/newview/skins/default/xui/fr/menu_toolbars.xml
index d3e9f92770..f74d206d56 100644
--- a/indra/newview/skins/default/xui/fr/menu_toolbars.xml
+++ b/indra/newview/skins/default/xui/fr/menu_toolbars.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <context_menu name="Toolbars Popup">
-	<menu_item_call label="Choisir les boutons..." name="Chose Buttons"/>
+	<menu_item_call label="Supprimer ce bouton" name="Remove button"/>
+	<menu_item_call label="Boutons des barres d&apos;outils..." name="Choose Buttons"/>
 	<menu_item_check label="Icônes et libellés" name="icons_with_text"/>
 	<menu_item_check label="Icônes uniquement" name="icons_only"/>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml
index d3b48639e0..9303815c30 100644
--- a/indra/newview/skins/default/xui/fr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <menu_bar name="Main Menu">
 	<menu label="Moi" name="Me">
-		<menu_item_call label="Page d&apos;accueil..." name="Manage My Account">
-			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=fr"/>
-		</menu_item_call>
 		<menu_item_call label="Profil..." name="Profile"/>
 		<menu_item_call label="Apparence..." name="ChangeOutfit"/>
+		<menu_item_call label="Choisir un avatar..." name="Avatar Picker"/>
 		<menu_item_check label="Inventaire..." name="Inventory"/>
-		<menu_item_check label="Gestes..." name="Gestures"/>
-		<menu_item_check label="Chat vocal..." name="ShowVoice"/>
+		<menu_item_call label="Nouvelle fenêtre d&apos;inventaire" name="NewInventoryWindow"/>
+		<menu_item_call label="Endroits..." name="Places"/>
+		<menu_item_call label="Favoris..." name="Picks"/>
+		<menu_item_call label="Paramètres de la caméra..." name="Camera Controls"/>
 		<menu label="Déplacement" name="Movement">
 			<menu_item_call label="M&apos;asseoir" name="Sit Down Here"/>
 			<menu_item_check label="Voler" name="Fly"/>
@@ -22,34 +22,39 @@
 		<menu_item_call label="Demander le statut Admin" name="Request Admin Options"/>
 		<menu_item_call label="Quitter le statut Admin" name="Leave Admin Options"/>
 		<menu_item_call label="Acheter des L$" name="Buy and Sell L$"/>
+		<menu_item_call label="Page d&apos;accueil du compte..." name="Manage My Account">
+			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=fr"/>
+		</menu_item_call>
 		<menu_item_call label="Préférences..." name="Preferences"/>
-		<menu_item_call label="Barres d&apos;outils..." name="Toolbars"/>
+		<menu_item_call label="Boutons des barres d&apos;outils..." name="Toolbars"/>
 		<menu_item_call label="Masquer tous les contrôles" name="Hide UI"/>
 		<menu_item_call label="Quitter [APP_NAME]" name="Quit"/>
 	</menu>
 	<menu label="Communiquer" name="Communicate">
-		<menu_item_call label="Mes amis" name="My Friends"/>
-		<menu_item_call label="Mes groupes" name="My Groups"/>
-		<menu_item_check label="Chat près de moi" name="Nearby Chat"/>
-		<menu_item_call label="Personnes près de moi" name="Active Speakers"/>
-		<menu_item_check label="Chat vocal près de vous" name="Nearby Voice"/>
+		<menu_item_check label="Chat..." name="Nearby Chat"/>
+		<menu_item_check label="Parler" name="Speak"/>
+		<menu_item_check label="Paramètres vocaux..." name="Nearby Voice"/>
+		<menu_item_check label="Effet de voix..." name="ShowVoice"/>
+		<menu_item_check label="Gestes..." name="Gestures"/>
+		<menu_item_call label="Amis" name="My Friends"/>
+		<menu_item_call label="Groupes" name="My Groups"/>
+		<menu_item_call label="Personnes près de vous" name="Active Speakers"/>
 	</menu>
 	<menu label="Monde" name="World">
-		<menu_item_check label="Mini-carte" name="Mini-Map"/>
+		<menu_item_call label="Créer un repère pour ce lieu" name="Create Landmark Here"/>
+		<menu_item_call label="Destinations..." name="Destinations"/>
 		<menu_item_check label="Carte du monde" name="World Map"/>
+		<menu_item_check label="Mini-carte" name="Mini-Map"/>
 		<menu_item_check label="Rechercher" name="Search"/>
+		<menu_item_call label="Me téléporter chez moi" name="Teleport Home"/>
+		<menu_item_call label="Définir le domicile ici" name="Set Home to Here"/>
 		<menu_item_call label="Photo" name="Take Snapshot"/>
-		<menu_item_call label="Créer un repère pour ce lieu" name="Create Landmark Here"/>
-		<menu label="Profil du lieu" name="Land">
-			<menu_item_call label="Profil du lieu" name="Place Profile"/>
-			<menu_item_call label="À propos du terrain" name="About Land"/>
-			<menu_item_call label="Région/Domaine" name="Region/Estate"/>
-		</menu>
+		<menu_item_call label="Profil du lieu" name="Place Profile"/>
+		<menu_item_call label="À propos du terrain" name="About Land"/>
+		<menu_item_call label="Région/Domaine" name="Region/Estate"/>
+		<menu_item_call label="Mes terrains..." name="My Land"/>
 		<menu_item_call label="Acheter ce terrain" name="Buy Land"/>
-		<menu_item_call label="Mes terrains" name="My Land"/>
 		<menu label="Afficher" name="LandShow">
-			<menu_item_check label="Contrôles de mouvement" name="Movement Controls"/>
-			<menu_item_check label="Contrôles d’affichage" name="Camera Controls"/>
 			<menu_item_check label="Lignes d&apos;interdiction" name="Ban Lines"/>
 			<menu_item_check label="Balises" name="beacons"/>
 			<menu_item_check label="Limites du terrain" name="Property Lines"/>
@@ -58,16 +63,15 @@
 			<menu_item_check label="Propriétés de la parcelle" name="Parcel Properties"/>
 			<menu_item_check label="Menu Avancé" name="Show Advanced Menu"/>
 		</menu>
-		<menu_item_call label="Me téléporter chez moi" name="Teleport Home"/>
-		<menu_item_call label="Définir le domicile ici" name="Set Home to Here"/>
 		<menu label="Luminosité" name="Environment Settings">
 			<menu_item_call label="Aube" name="Sunrise"/>
 			<menu_item_call label="Milieu de journée" name="Noon"/>
 			<menu_item_call label="Coucher de soleil" name="Sunset"/>
 			<menu_item_call label="Minuit" name="Midnight"/>
+			<menu_item_call label="Utiliser les réglages de la région" name="Use Region Settings"/>
 		</menu>
-		<menu label="Éditeur d&apos;environnement" name="Enviroment Editor">
-			<menu_item_call label="Paramètres d&apos;environnement..." name="Enviroment Settings"/>
+		<menu label="Éditeur d&apos;environnement" name="Environment Editor">
+			<menu_item_call label="Paramètres d&apos;environnement..." name="Environment Settings"/>
 			<menu label="Préréglages de l&apos;eau" name="Water Presets">
 				<menu_item_call label="Nouveau préréglage..." name="new_water_preset"/>
 				<menu_item_call label="Modifier un préréglage..." name="edit_water_preset"/>
@@ -146,6 +150,7 @@
 		<menu_item_call label="Refaire" name="Redo"/>
 	</menu>
 	<menu label="Aide" name="Help">
+		<menu_item_call label="Aide rapide..." name="How To"/>
 		<menu_item_call label="Aide de [SECOND_LIFE]" name="Second Life Help"/>
 		<menu_item_call label="Signaler une infraction" name="Report Abuse"/>
 		<menu_item_call label="Signaler un bug" name="Report Bug"/>
@@ -200,11 +205,10 @@
 		<menu_item_check label="Utiliser le thread de lecture de plug-in" name="Use Plugin Read Thread"/>
 		<menu_item_call label="Effacer le cache du groupe" name="ClearGroupCache"/>
 		<menu_item_check label="Effet de lissage de la souris" name="Mouse Smoothing"/>
+		<menu_item_call label="Libérer les touches" name="Release Keys"/>
 		<menu label="Raccourcis" name="Shortcuts">
 			<menu_item_call label="Image ([COST] L$)..." name="Upload Image"/>
 			<menu_item_check label="Rechercher" name="Search"/>
-			<menu_item_call label="Relâcher les touches" name="Release Keys"/>
-			<menu_item_call label="Taille de l&apos;interface par défaut" name="Set UI Size to Default"/>
 			<menu_item_check label="Afficher le menu Avancé - raccourci existant" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Fermer la fenêtre" name="Close Window"/>
 			<menu_item_call label="Fermer toutes les fenêtres" name="Close All Windows"/>
@@ -290,6 +294,7 @@
 			<menu_item_check label="Lumières" name="Lights"/>
 			<menu_item_check label="Squelette de collision" name="Collision Skeleton"/>
 			<menu_item_check label="Rayons" name="Raycast"/>
+			<menu_item_check label="Vecteurs de vent" name="Wind Vectors"/>
 			<menu_item_check label="Complexité du rendu" name="rendercomplexity"/>
 			<menu_item_check label="Sculpture" name="Sculpt"/>
 		</menu>
@@ -302,7 +307,6 @@
 			<menu_item_check label="Éclairage et ombres" name="Lighting and Shadows"/>
 			<menu_item_check label="Ombres du soleil/de la lune/des projecteurs" name="Shadows from Sun/Moon/Projectors"/>
 			<menu_item_check label="SSAO et lissage des ombres" name="SSAO and Shadow Smoothing"/>
-			<menu_item_check label="Illumination globale (expérimental)" name="Global Illumination"/>
 			<menu_item_check label="Débogage GL" name="Debug GL"/>
 			<menu_item_check label="Débogage pipeline" name="Debug Pipeline"/>
 			<menu_item_check label="Masques alpha automatiques (différés)" name="Automatic Alpha Masks (deferred)"/>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index be6f1f8c31..2f9bf23bc4 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -980,7 +980,7 @@ Proposer à [NAME] de devenir votre ami(e) ?
 		</form>
 	</notification>
 	<notification name="RemoveFromFriends">
-		Voulez-vous supprimer &lt;nolink&gt;[NAME]&lt;/nolink&gt; de votre liste d&apos;amis ?
+		Voulez-vous supprimer &lt;nolink&gt;[NAME]&lt;/nolink&gt; de votre liste d&apos;amis ?
 		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
 	</notification>
 	<notification name="RemoveMultipleFromFriends">
@@ -1105,8 +1105,13 @@ Céder ces [AREA] m² de terrain au groupe [GROUP_NAME] ?
 	<notification name="DisplaySetToSafe">
 		Les paramètres d&apos;affichage sont au niveau le plus sûr, comme vous l&apos;aviez indiqué.
 	</notification>
-	<notification name="DisplaySetToRecommended">
-		Vos paramètres d&apos;affichage ont été réglés avec une marge de sécurité en fonction de votre configuration système.
+	<notification name="DisplaySetToRecommendedGPUChange">
+		Les paramètres d&apos;affichage ont été modifiés selon les niveaux recommandés car votre carte graphique
+[LAST_GPU] a été remplacée
+par une carte [THIS_GPU].
+	</notification>
+	<notification name="DisplaySetToRecommendedFeatureChange">
+		Les paramètres d&apos;affichage ont été modifiés selon les niveaux recommandés en raison d&apos;un changement relatif au sous-système de rendu.
 	</notification>
 	<notification name="ErrorMessage">
 		[ERROR_MESSAGE]
@@ -1910,9 +1915,15 @@ Déplacer les objets de l&apos;inventaire ?
 		<usetemplate ignoretext="Confirmer avant de quitter" name="okcancelignore" notext="Ne pas quitter" yestext="Quitter"/>
 	</notification>
 	<notification name="ConfirmRestoreToybox">
-		Etes-vous certain de vouloir restaurer vos boutons et barres d&apos;outils par défaut ? 
+		Cette action rétablira vos boutons et barres d&apos;outils par défaut.
+
+Vous ne pouvez pas l&apos;annuler.
+		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
+	</notification>
+	<notification name="ConfirmClearAllToybox">
+		Cette action replacera tous les boutons dans la boîte à outils de sorte que vos barres d&apos;outils seront vides.
     
-Vous ne pouvez pas annuler cette action.
+Vous ne pouvez pas l&apos;annuler.
 		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
 	</notification>
 	<notification name="DeleteItems">
@@ -2236,14 +2247,16 @@ Veuillez sélectionner un seul objet.
 		Votre carte de visite a été refusée.
 	</notification>
 	<notification name="TeleportToLandmark">
-		Vous pouvez vous téléporter vers des endroits comme [NAME] en ouvrant le panneau Lieux sur le côté droit de votre écran, puis en sélectionnant l&apos;onglet Repères.
-Cliquez sur le repère de votre choix pour le sélectionner, puis sur Téléporter en bas du panneau.
-(Vous pouvez aussi double-cliquer sur le repère ou cliquer dessus avec le bouton droit de la souris et sélectionner Téléporter.)
+		Pour vous téléporter vers un lieu tel que [NAME], cliquez sur le bouton Endroits,
+    puis sélectionnez l&apos;onglet Repères dans la fenêtre qui s&apos;ouvre. Cliquez sur n&apos;importe quel
+    repère pour le sélectionner, puis sur Téléportation en bas de la fenêtre.
+    (Vous pouvez aussi double-cliquer sur le repère ou cliquer-droit dessus et
+    choisir Téléportation).
 	</notification>
 	<notification name="TeleportToPerson">
-		Vous pouvez contacter des résidents comme [NAME] en ouvrant le panneau Résidents sur le côté droit de votre écran.
-Sélectionnez le résident de votre choix dans la liste, puis cliquez sur IM en bas du panneau.
-(Vous pouvez aussi double-cliquer sur le nom du résident dans la liste ou cliquer dessus avec le bouton droit de la souris et sélectionner IM.)
+		Pour contacter un résident tel que [NAME], cliquez sur le bouton Personnes, sélectionnez le résident dans la fenêtre qui s&apos;ouvre, puis cliquez sur IM en
+    bas de la fenêtre.
+    (Vous pouvez aussi double-cliquer sur le nom du résident dans la liste ou cliquer-droit dessus et choisir IM.)
 	</notification>
 	<notification name="CantSelectLandFromMultipleRegions">
 		Vous ne pouvez pas sélectionner de terrain en dehors des limites du serveur.
@@ -2264,6 +2277,9 @@ Veuillez sélectionner un terrain plus petit.
 	<notification name="PaymentSent">
 		[MESSAGE]
 	</notification>
+	<notification name="PaymentFailure">
+		[MESSAGE]
+	</notification>
 	<notification name="EventNotification">
 		Avis d&apos;événement :
 
@@ -2798,7 +2814,7 @@ Voir le fichier journal pour plus de détails.
 avec les résidents suivants :
 
 [RESIDENTS] ?
-		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="Ok"/>
+		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
 	</notification>
 	<notification name="ItemsShared">
 		Articles partagés.
@@ -2888,7 +2904,7 @@ Les résidents rejoignant l&apos;appel ultérieurement seront également
 ignorés, même si vous quittez l&apos;appel.
 
 Ignorer les autres ?
-		<usetemplate ignoretext="Confirmer avant d&apos;ignorer les autres lors d&apos;un appel de groupe" name="okcancelignore" notext="Annuler" yestext="Ok"/>
+		<usetemplate ignoretext="Confirmer avant d&apos;ignorer les autres lors d&apos;un appel de groupe" name="okcancelignore" notext="Annuler" yestext="OK"/>
 	</notification>
 	<notification label="Chat" name="HintChat">
 		Pour participer à la conversation, saisissez du texte dans le champ de chat situé en dessous.
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_skin.xml b/indra/newview/skins/default/xui/fr/panel_edit_skin.xml
index 9640adcdf8..f5f2738319 100644
--- a/indra/newview/skins/default/xui/fr/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/fr/panel_edit_skin.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_skin_panel">
 	<panel name="avatar_skin_color_panel">
-		<texture_picker label="Tatouage tête" name="Head Tattoos" tool_tip="Cliquez pour sélectionner une image" width="76"/>
-		<texture_picker label="Tatouage haut" name="Upper Tattoos" tool_tip="Cliquez pour sélectionner une image" width="80"/>
-		<texture_picker label="Tatouage bas" name="Lower Tattoos" tool_tip="Cliquez pour sélectionner une image"/>
+		<texture_picker label="Tête" name="Head" tool_tip="Cliquer pour sélectionner une image."/>
+		<texture_picker label="Haut du corps" name="Upper Body" tool_tip="Cliquer pour sélectionner une image."/>
+		<texture_picker label="Bas du corps" name="Lower Body" tool_tip="Cliquer pour sélectionner une image."/>
 	</panel>
 	<panel name="accordion_panel">
 		<accordion name="wearable_accordion">
diff --git a/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml b/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml
index 31cb3308e3..00bd6e81ae 100644
--- a/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="nearby_chat">
-	<check_box label="Traduction du chat" name="translate_chat_checkbox"/>
+	<check_box label="Traduire le chat" name="translate_chat_checkbox"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_postcard_message.xml b/indra/newview/skins/default/xui/fr/panel_postcard_message.xml
new file mode 100644
index 0000000000..0f8397cfb4
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_postcard_message.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_message">
+	<text name="to_label">
+		À :
+	</text>
+	<text name="name_label">
+		De :
+	</text>
+	<text name="subject_label">
+		Objet :
+	</text>
+	<line_editor label="Saisir ici votre objet" name="subject_form"/>
+	<text name="msg_label">
+		Message :
+	</text>
+	<text_editor name="msg_form">
+		Saisir ici votre message
+	</text_editor>
+	<button label="Annuler" name="cancel_btn"/>
+	<button label="Envoyer" name="send_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_postcard_settings.xml b/indra/newview/skins/default/xui/fr/panel_postcard_settings.xml
new file mode 100644
index 0000000000..6f4e9c23f9
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_postcard_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_settings">
+	<combo_box label="Résolution" name="postcard_size_combo">
+		<combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
+		<combo_box.item label="640 x 480" name="640x480"/>
+		<combo_box.item label="800 x 600" name="800x600"/>
+		<combo_box.item label="1 024 x 768" name="1024x768"/>
+		<combo_box.item label="Personnalisée" name="Custom"/>
+	</combo_box>
+	<layout_stack name="postcard_image_params_ls">
+		<layout_panel name="postcard_image_size_lp">
+			<spinner label="Largeur" name="postcard_snapshot_width"/>
+			<spinner label="Hauteur" name="postcard_snapshot_height"/>
+			<check_box label="Conserver les proportions" name="postcard_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="postcard_image_format_quality_lp">
+			<slider label="Qualité de l&apos;image" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
index fa026d8106..76ed237451 100644
--- a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
@@ -29,30 +29,5 @@
 	<check_box label="Chats IM" name="EnableIMChatPopups" tool_tip="Cocher cette case pour qu&apos;un popup s&apos;affiche à réception d&apos;un message instantané."/>
 	<spinner label="Durée de vie du popup Chat près de moi :" name="nearby_toasts_lifetime"/>
 	<spinner label="Disparition progressive du popup Chat près de moi :" name="nearby_toasts_fadingtime"/>
-	<check_box name="translate_chat_checkbox"/>
-	<text name="translate_chb_label">
-		Utiliser la traduction automatique lors des chats
-	</text>
-	<text name="translate_language_text">
-		Traduire le chat en :
-	</text>
-	<combo_box name="translate_language_combobox">
-		<combo_box.item label="Choix par défaut" name="System Default Language"/>
-		<combo_box.item label="English (Anglais)" name="English"/>
-		<combo_box.item label="Dansk (Danois)" name="Danish"/>
-		<combo_box.item label="Deutsch (Allemand)" name="German"/>
-		<combo_box.item label="Español (Espagnol)" name="Spanish"/>
-		<combo_box.item label="Français" name="French"/>
-		<combo_box.item label="Italiano (Italien)" name="Italian"/>
-		<combo_box.item label="Magyar (Hongrois)" name="Hungarian"/>
-		<combo_box.item label="Nederlands (Néerlandais)" name="Dutch"/>
-		<combo_box.item label="Polski (Polonais)" name="Polish"/>
-		<combo_box.item label="Português (Portugais)" name="Portugese"/>
-		<combo_box.item label="Русский (Russe)" name="Russian"/>
-		<combo_box.item label="Türkçe (Turc)" name="Turkish"/>
-		<combo_box.item label="Українська (Ukrainien)" name="Ukrainian"/>
-		<combo_box.item label="中文 (正體) (Chinois)" name="Chinese"/>
-		<combo_box.item label="日本語 (Japonais)" name="Japanese"/>
-		<combo_box.item label="한국어 (Coréen)" name="Korean"/>
-	</combo_box>
+	<button label="Traduction automatique" name="ok_btn"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_setup.xml b/indra/newview/skins/default/xui/fr/panel_preferences_setup.xml
index 82780c27c5..83303950dc 100644
--- a/indra/newview/skins/default/xui/fr/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_setup.xml
@@ -15,7 +15,7 @@
 		Web :
 	</text>
 	<radio_group name="use_external_browser">
-		<radio_item label="Utiliser mon navigateur (IE, Firefox, Safari)" name="external" tool_tip="Utiliser le navigateur web système par défaut pour l&apos;aide, les liens etc. Non recommandé en mode plein écran." value="1"/>
+		<radio_item label="Utiliser mon navigateur (IE, Firefox, Safari)" name="external" tool_tip="Utiliser le navigateur web système par défaut pour l&apos;aide, les liens etc. Non recommandé en mode plein écran." value="true"/>
 		<radio_item label="Utiliser le navigateur intégré" name="internal" tool_tip="Utilisez le navigateur intégré pour obtenir de l&apos;aide, ouvrir des liens, etc. Ce navigateur s&apos;ouvre dans [APP_NAME]." value=""/>
 	</radio_group>
 	<check_box initial_value="true" label="Activer les plugins" name="browser_plugins_enabled"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml
new file mode 100644
index 0000000000..4454d2475e
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_inventory">
+	<text name="title">
+		Enregistrer dans mon inventaire
+	</text>
+	<text name="hint_lbl">
+		L&apos;enregistrement d&apos;une image dans votre inventaire coûte [UPLOAD_COST] L$. Pour enregistrer votre image sous forme de texture, sélectionnez l&apos;un des formats carrés.
+	</text>
+	<combo_box label="Résolution" name="texture_size_combo">
+		<combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
+		<combo_box.item label="Petite (128 x 128)" name="Small(128x128)"/>
+		<combo_box.item label="Moyenne (256 x 256)" name="Medium(256x256)"/>
+		<combo_box.item label="Grande (512 x 512)" name="Large(512x512)"/>
+		<combo_box.item label="Personnalisée" name="Custom"/>
+	</combo_box>
+	<spinner label="Largeur" name="inventory_snapshot_width"/>
+	<spinner label="Hauteur" name="inventory_snapshot_height"/>
+	<check_box label="Conserver les proportions" name="inventory_keep_aspect_check"/>
+	<button label="Annuler" name="cancel_btn"/>
+	<button label="Enregistrer" name="save_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_local.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_local.xml
new file mode 100644
index 0000000000..41264521fd
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_snapshot_local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_local">
+	<text name="title">
+		Enregistrer sur mon ordinateur
+	</text>
+	<combo_box label="Résolution" name="local_size_combo">
+		<combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
+		<combo_box.item label="320 x 240" name="320x240"/>
+		<combo_box.item label="640 x 480" name="640x480"/>
+		<combo_box.item label="800 x 600" name="800x600"/>
+		<combo_box.item label="1 024 x 768" name="1024x768"/>
+		<combo_box.item label="1 280 x 1 024" name="1280x1024"/>
+		<combo_box.item label="1 600 x 1 200" name="1600x1200"/>
+		<combo_box.item label="Personnalisée" name="Custom"/>
+	</combo_box>
+	<layout_stack name="local_image_params_ls">
+		<layout_panel name="local_image_size_lp">
+			<spinner label="Largeur" name="local_snapshot_width"/>
+			<spinner label="Hauteur" name="local_snapshot_height"/>
+			<check_box label="Conserver les proportions" name="local_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="local_image_format_quality_lp">
+			<combo_box label="Format" name="local_format_combo">
+				<combo_box.item label="PNG (sans perte)" name="PNG"/>
+				<combo_box.item label="JPEG" name="JPEG"/>
+				<combo_box.item label="BMP (sans perte)" name="BMP"/>
+			</combo_box>
+			<slider label="Qualité de l&apos;image" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+	<button label="Annuler" name="cancel_btn"/>
+	<flyout_button label="Enregistrer" name="save_btn" tool_tip="Enregistrer l&apos;image dans un fichier.">
+		<flyout_button.item label="Enregistrer" name="save_item"/>
+		<flyout_button.item label="Enregistrer sous..." name="saveas_item"/>
+	</flyout_button>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml
new file mode 100644
index 0000000000..db3fcbeac9
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_options">
+	<button label="Publier sur le flux de mon profil" name="save_to_profile_btn"/>
+	<button label="Envoyer par e-mail" name="save_to_email_btn"/>
+	<button label="Enregistrer dans mon inventaire ([AMOUNT] L$)" name="save_to_inventory_btn"/>
+	<button label="Enregistrer sur mon ordinateur" name="save_to_computer_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml
new file mode 100644
index 0000000000..bb23b52850
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+	<string name="default_subject">
+		Carte postale de [SECOND_LIFE].
+	</string>
+	<string name="default_message">
+		Ouvrez-moi !
+	</string>
+	<string name="upload_message">
+		Envoi en cours...
+	</string>
+	<text name="title">
+		Envoyer par e-mail
+	</text>
+	<button label="Message" name="message_btn"/>
+	<button label="Paramètres" name="settings_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_profile.xml
new file mode 100644
index 0000000000..427ffe2113
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_snapshot_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_profile">
+	<text name="title">
+		Publier sur le flux de mon profil
+	</text>
+	<combo_box label="Résolution" name="profile_size_combo">
+		<combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
+		<combo_box.item label="640 x 480" name="640x480"/>
+		<combo_box.item label="800 x 600" name="800x600"/>
+		<combo_box.item label="1 024 x 768" name="1024x768"/>
+		<combo_box.item label="Personnalisée" name="Custom"/>
+	</combo_box>
+	<layout_stack name="profile_image_params_ls">
+		<layout_panel name="profile_image_size_lp">
+			<spinner label="Largeur" name="profile_snapshot_width"/>
+			<spinner label="Hauteur" name="profile_snapshot_height"/>
+			<check_box label="Conserver les proportions" name="profile_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="profile_image_metadata_lp">
+			<text name="caption_label">
+				Légende :
+			</text>
+			<check_box initial_value="true" label="Inclure l&apos;endroit" name="add_location_cb"/>
+		</layout_panel>
+	</layout_stack>
+	<button label="Annuler" name="cancel_btn"/>
+	<button label="Publier" name="post_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index f9f3366f63..d959a96565 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -1214,7 +1214,7 @@ Veuillez réessayer de vous connecter dans une minute.
 		Vous n&apos;avez pas de copie de cette texture dans votre inventaire
 	</string>
 	<string name="InventoryInboxNoItems">
-		Ici seront livrés les articles achetés sur la Place du marché.
+		Lorsque vous achetez ou recevez un article, il s&apos;affiche ici. Vous pouvez alors le faire glisser vers un dossier de votre inventaire ou le supprimer si vous ne souhaitez pas le conserver.
 	</string>
 	<string name="MarketplaceURL">
 		http://marketplace.[DOMAIN_NAME]
@@ -1412,6 +1412,9 @@ Veuillez réessayer de vous connecter dans une minute.
 	<string name="no_attachments">
 		Aucun élément attaché porté
 	</string>
+	<string name="Attachments remain">
+		Éléments attachés ([COUNT] emplacements restants)
+	</string>
 	<string name="Buy">
 		Acheter
 	</string>
@@ -1538,6 +1541,12 @@ Veuillez réessayer de vous connecter dans une minute.
 	<string name="Right Pec">
 		Pectoral droit
 	</string>
+	<string name="Neck">
+		Cou
+	</string>
+	<string name="Avatar Center">
+		Centre de l&apos;avatar
+	</string>
 	<string name="Invalid Attachment">
 		Point d&apos;attache non valide
 	</string>
@@ -4030,6 +4039,18 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].
 	<string name="you_paid_ldollars_no_name">
 		Vous avez payé à [AMOUNT] L$ [REASON].
 	</string>
+	<string name="you_paid_failure_ldollars">
+		Votre paiement de [AMOUNT] L$ à [NAME] [REASON] a échoué.
+	</string>
+	<string name="you_paid_failure_ldollars_no_info">
+		Votre paiement de [AMOUNT] L$ a échoué.
+	</string>
+	<string name="you_paid_failure_ldollars_no_reason">
+		Votre paiement de [AMOUNT] L$ à [NAME] a échoué.
+	</string>
+	<string name="you_paid_failure_ldollars_no_name">
+		Votre paiement de [AMOUNT] L$ [REASON] a échoué.
+	</string>
 	<string name="for item">
 		pour l&apos;article suivant : [ITEM]
 	</string>
@@ -4440,6 +4461,12 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 	<string name="ExternalEditorFailedToRun">
 		Échec d&apos;exécution de l&apos;éditeur externe.
 	</string>
+	<string name="TranslationFailed">
+		Échec de traduction : [REASON]
+	</string>
+	<string name="TranslationResponseParseError">
+		Erreur lors de l&apos;analyse de la réponse relative à la traduction.
+	</string>
 	<string name="Esc">
 		Échap
 	</string>
@@ -4810,7 +4837,7 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 		Mini-carte
 	</string>
 	<string name="Command_Move_Label">
-		Bouger
+		Marcher / Courir / Voler
 	</string>
 	<string name="Command_People_Label">
 		Personnes
@@ -4837,10 +4864,10 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 		Parler
 	</string>
 	<string name="Command_View_Label">
-		Affichage
+		Paramètres de la caméra
 	</string>
 	<string name="Command_Voice_Label">
-		Chat près de vous
+		Paramètres vocaux
 	</string>
 	<string name="Command_AboutLand_Tooltip">
 		Information sur le terrain que vous visitez
@@ -4912,7 +4939,16 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 		Changer l&apos;angle de la caméra
 	</string>
 	<string name="Command_Voice_Tooltip">
-		Personnes près de vous avec le chat vocal
+		Commandes de réglage du volume des appels et des personnes près de vous dans Second Life.
+	</string>
+	<string name="Toolbar_Bottom_Tooltip">
+		actuellement dans la barre d&apos;outils du bas
+	</string>
+	<string name="Toolbar_Left_Tooltip">
+		actuellement dans la barre d&apos;outils de gauche
+	</string>
+	<string name="Toolbar_Right_Tooltip">
+		actuellement dans la barre d&apos;outils de droite
 	</string>
 	<string name="Retain%">
 		Garder%
@@ -4938,4 +4974,19 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 	<string name="Normal">
 		Normal
 	</string>
+	<string name="snapshot_quality_very_low">
+		Très faible
+	</string>
+	<string name="snapshot_quality_low">
+		Faible
+	</string>
+	<string name="snapshot_quality_medium">
+		Moyenne
+	</string>
+	<string name="snapshot_quality_high">
+		Élevée
+	</string>
+	<string name="snapshot_quality_very_high">
+		Très élevée
+	</string>
 </strings>
diff --git a/indra/newview/skins/default/xui/fr/teleport_strings.xml b/indra/newview/skins/default/xui/fr/teleport_strings.xml
index 401b272c81..d0c74ff353 100644
--- a/indra/newview/skins/default/xui/fr/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/fr/teleport_strings.xml
@@ -21,8 +21,8 @@ Si vous ne parvenez toujours pas à être téléporté, déconnectez-vous puis r
 Veuillez réessayer dans un moment.
 		</message>
 		<message name="NoHelpIslandTP">
-		Vous ne pouvez pas retourner sur Welcome Island.
-Pour répéter le didacticiel, veuillez aller sur Welcome Island Public.
+			Vous ne pouvez pas vous téléporter à nouveau vers Welcome Island.
+Pour recommencer le didacticiel, accédez à Welcome Island Public.
 		</message>
 		<message name="noaccess_tport">
 			Désolé, vous n&apos;avez pas accès à cette destination.
diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml
index 68d073a766..39114b7bf7 100644
--- a/indra/newview/skins/default/xui/it/floater_about.xml
+++ b/indra/newview/skins/default/xui/it/floater_about.xml
@@ -67,32 +67,34 @@ Versione Server voice: [VOICE_VERSION]
 		<panel label="Licenze" name="licenses_panel">
 			<text_editor name="credits_editor">
 				3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
-APR Copyright (C) 2000-2004 The Apache Software Foundation
-Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
-cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
-DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
-expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
-FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
-GL Copyright (C) 1999-2004 Brian Paul.
-GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
-google-perftools Copyright (c) 2005, Google Inc.
-Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
-jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
-jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
-ogg/vorbis Copyright (C) 2001, Xiphophorus
-OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
-PCRE Copyright (c) 1997-2008 University of Cambridge
-SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
-SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
-xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
-zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler.
-google-perftools Copyright (c) 2005, Google Inc.
+        APR Copyright (C) 2000-2004 The Apache Software Foundation
+        Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
+        cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
+        DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
+        expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
+        FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
+        GL Copyright (C) 1999-2004 Brian Paul.
+        GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
+        google-perftools Copyright (c) 2005, Google Inc.
+        Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
+        jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
+        jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
+        ogg/vorbis Copyright (C) 2001, Xiphophorus
+        OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
+        PCRE Copyright (c) 1997-2008 University of Cambridge
+        SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+        SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+        xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
+        zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler.
+        google-perftools Copyright (c) 2005, Google Inc.
 
-Il Viewer Second Life utilizza Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (e licenziatari). Tutti i diritti riservati. Per informazioni dettagliate, vedere www.havok.com.
+        Il Viewer Second Life utilizza Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (e licenziatari). Tutti i diritti riservati. Per informazioni dettagliate, vedere www.havok.com.
 
-Tutti i diritti riservati.  Per informazioni dettagliate, vedere licenses.txt.
+        Questo software contiene codice sorgente fornito da NVIDIA Corporation.
 
-Codifica audio chat vocale: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
+        Tutti i diritti riservati.  Per informazioni dettagliate, vedere licenses.txt.
+
+        Codifica audio chat vocale: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
 			</text_editor>
 		</panel>
 	</tab_container>
diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml
index b6bfb4aadf..528cf185fc 100644
--- a/indra/newview/skins/default/xui/it/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/it/floater_about_land.xml
@@ -133,7 +133,7 @@ Vai al menu Mondo &gt; Informazioni sul terreno oppure seleziona un altro appezz
 				Traffico:
 			</text>
 			<text name="DwellText" width="140">
-				0
+				Caricamento in corso...
 			</text>
 			<button label="Acquista il terreno..." label_selected="Acquista il terreno..." left="130" name="Buy Land..." width="125"/>
 			<button label="Vendita Linden" name="Linden Sale..." tool_tip="La terra deve essere di proprietà, con contenuto impostato, e non già messa all&apos;asta."/>
@@ -314,13 +314,15 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
 				Nessuna spinta (Impostazione regionale)
 			</panel.string>
 			<panel.string name="see_avs_text">
-				Vedi i residenti in questo lotto e chatta con loro
+				Gli avatar in altri lotti possono vedere
 			</panel.string>
 			<text name="allow_label">
 				Permetti ad altri residenti di:
 			</text>
-			<check_box label="Modificare il terreno" name="edit land check" tool_tip="Se spuntata, chiunque può terraformare il tuo terreno. È preferibile lasciare questa opzione non spuntata, dato che sarai comunque in grado di modificare il tuo terreno."/>
-			<check_box label="Permetti il volo" name="check fly" tool_tip="Se spuntato, gli altri residenti potranno volare sul tuo terreno. Se non spuntato, potranno solamente arrivare in volo o sorvolare il terreno."/>
+			<text name="allow_label0">
+				Vola:
+			</text>
+			<check_box label="Tutti" name="check fly" tool_tip="Se spuntato, gli altri residenti potranno volare sul tuo terreno. Se non spuntato, potranno solamente arrivare in volo o sorvolare il terreno."/>
 			<text name="allow_label2">
 				Creare oggetti:
 			</text>
@@ -336,9 +338,6 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
 			</text>
 			<check_box label="Tutti i residenti" name="check other scripts"/>
 			<check_box label="Gruppo" name="check group scripts"/>
-			<text name="land_options_label">
-				Opzioni per il terreno:
-			</text>
 			<check_box label="Sicuro (senza danno)" name="check safe" tool_tip="Se spuntato, imposta il terreno su &apos;sicuro&apos;, disabilitando i danni da combattimento. Se non spuntato, viene abilitato il combattimento con danni."/>
 			<check_box label="Nessuna spinta" name="PushRestrictCheck" tool_tip="Previeni i colpi. Selezionare questa opzione può essere utile per prevenire comportamenti dannosi sul tuo terreno."/>
 			<check_box label="Mostra luogo nella ricerca (30 L$/settimana)" name="ShowDirectoryCheck" tool_tip="Consenti che il lotto sia visto nei risultati di ricerca"/>
@@ -379,9 +378,9 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Clicca per scegliere una immagine"/>
 			<text name="allow_label5">
-				Permetti ai residenti in altri lotti di:
+				e chattare con avatar in questo lotto
 			</text>
-			<check_box label="Vedi avatar" name="SeeAvatarsCheck" tool_tip="Consente ai residenti in altri lotti di vedere i residenti in questo lotto e chattare con loro, e ti consente di vederli e chattare con loro."/>
+			<check_box label="Vedi avatar" name="SeeAvatarsCheck" tool_tip="Consente ad avatar in altri lotti di vedere e chattare con avatar in questo lotto e viceversa."/>
 			<text name="landing_point">
 				Punto di atterraggio: [LANDING]
 			</text>
diff --git a/indra/newview/skins/default/xui/it/floater_avatar.xml b/indra/newview/skins/default/xui/it/floater_avatar.xml
index 1587c347a5..d7445cfb2b 100644
--- a/indra/newview/skins/default/xui/it/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/it/floater_avatar.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Avatar" title="SCELTA AVATAR"/>
+<floater name="Avatar" title="SELEZIONA UN AVATAR"/>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index d985ad2b3c..743969f557 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		[AMT]L$
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
+		[http://www.secondlife.com/my/account/payment_method_management.php metodo di pagamento] | [http://www.secondlife.com/my/account/currency.php valuta]
 	</text>
 	<text name="exchange_rate_note">
 		Riscrivi l&apos;importo per vedere l&apos;ultimo tasso al cambio.
diff --git a/indra/newview/skins/default/xui/it/floater_camera.xml b/indra/newview/skins/default/xui/it/floater_camera.xml
index 7e6ca4307e..be03857bc9 100644
--- a/indra/newview/skins/default/xui/it/floater_camera.xml
+++ b/indra/newview/skins/default/xui/it/floater_camera.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="camera_floater" title="VISTA">
+<floater name="camera_floater" title="CONTROLLI FOTOCAMERA">
 	<floater.string name="rotate_tooltip">
 		Ruota la telecamera Intorno all&apos;Inquadratura
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/it/floater_hardware_settings.xml b/indra/newview/skins/default/xui/it/floater_hardware_settings.xml
index 561f8dbf34..5d3ae04a4d 100644
--- a/indra/newview/skins/default/xui/it/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/it/floater_hardware_settings.xml
@@ -4,7 +4,7 @@
 		Filtraggio:
 	</text>
 	<check_box label="Filtraggio Anisotropico (rallenta se attivato)" name="ani"/>
-	<text name="Antialiasing:">
+	<text name="antialiasing label">
 		Antialiasing:
 	</text>
 	<combo_box label="Antialiasing" name="fsaa" width="94">
diff --git a/indra/newview/skins/default/xui/it/floater_model_preview.xml b/indra/newview/skins/default/xui/it/floater_model_preview.xml
index 03102f5f81..ca36fd2def 100644
--- a/indra/newview/skins/default/xui/it/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/it/floater_model_preview.xml
@@ -4,6 +4,9 @@
 	<string name="status_parse_error">
 		Errore: Errore elaborazione Dae - vedere il registro per informazioni dettagliate.
 	</string>
+	<string name="status_material_mismatch">
+		Errore: il materiale del modello non è un sottoinsieme del modello di riferimento.
+	</string>
 	<string name="status_reading_file">
 		Caricamento in corso...
 	</string>
diff --git a/indra/newview/skins/default/xui/it/floater_model_wizard.xml b/indra/newview/skins/default/xui/it/floater_model_wizard.xml
index e6d0a7c4bc..7c1b13c18f 100644
--- a/indra/newview/skins/default/xui/it/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/it/floater_model_wizard.xml
@@ -20,6 +20,9 @@
 				Scegli il file del modello da caricare
 			</text>
 			<button label="Sfoglia..." label_selected="Sfoglia..." name="browse"/>
+			<text name="Model types">
+				Second Life supporta file COLLADA (.dae)
+			</text>
 			<text name="dimensions">
 				X         Y         Z
 			</text>
diff --git a/indra/newview/skins/default/xui/it/floater_moveview.xml b/indra/newview/skins/default/xui/it/floater_moveview.xml
index 6e820a335c..1237bd06a9 100644
--- a/indra/newview/skins/default/xui/it/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/it/floater_moveview.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move_floater" title="SPOSTA">
+<floater name="move_floater" title="CAMMINA / CORRI / VOLA">
 	<string name="walk_forward_tooltip">
 		Cammina in avanti (premi freccia su o W)
 	</string>
diff --git a/indra/newview/skins/default/xui/it/floater_snapshot.xml b/indra/newview/skins/default/xui/it/floater_snapshot.xml
index f1c5cc4caf..bff6081bdf 100644
--- a/indra/newview/skins/default/xui/it/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/it/floater_snapshot.xml
@@ -3,73 +3,63 @@
 	<floater.string name="unknown">
 		sconosciuto
 	</floater.string>
-	<radio_group label="Tipo di fotografia" name="snapshot_type_radio">
-		<radio_item label="E-mail" name="postcard"/>
-		<radio_item label="Il mio inventario (L$[AMOUNT])" name="texture"/>
-		<radio_item label="Salva sul mio computer" name="local"/>
-	</radio_group>
+	<string name="postcard_progress_str">
+		Invio e-mail in corso
+	</string>
+	<string name="profile_progress_str">
+		Caricamento post
+	</string>
+	<string name="inventory_progress_str">
+		Salva nell&apos;inventario
+	</string>
+	<string name="local_progress_str">
+		Salvataggio sul computer in corso
+	</string>
+	<string name="profile_succeeded_str">
+		Immagine caricata
+	</string>
+	<string name="postcard_succeeded_str">
+		E-mail inviata.
+	</string>
+	<string name="inventory_succeeded_str">
+		Salvato nell&apos;inventario.
+	</string>
+	<string name="local_succeeded_str">
+		Salvato sul computer.
+	</string>
+	<string name="profile_failed_str">
+		Caricamento immagine sul feed del profilo non riuscito.
+	</string>
+	<string name="postcard_failed_str">
+		Invio e-mail non riuscito.
+	</string>
+	<string name="inventory_failed_str">
+		Non salvato nell&apos;inventario.
+	</string>
+	<string name="local_failed_str">
+		Non salvato sul computer.
+	</string>
+	<button name="advanced_options_btn" tool_tip="Opzioni Avanzate"/>
+	<text name="image_res_text">
+		[WIDTH] x [HEIGHT] px
+	</text>
 	<text name="file_size_label">
 		[SIZE] KB
 	</text>
-	<button label="Aggiorna la fotografia" name="new_snapshot_btn"/>
-	<button label="Invia" name="send_btn"/>
-	<button label="Salva ([AMOUNT] L$)" name="upload_btn"/>
-	<flyout_button label="Salva" name="save_btn" tool_tip="Salva immagine come file">
-		<flyout_button.item label="Salva" name="save_item"/>
-		<flyout_button.item label="Salva con nome..." name="saveas_item"/>
-	</flyout_button>
-	<button label="Altro" name="more_btn" tool_tip="Opzioni Avanzate"/>
-	<button label="Meno" name="less_btn" tool_tip="Opzioni Avanzate"/>
-	<button label="Annulla" name="discard_btn"/>
-	<text name="type_label2">
-		Dimensioni
-	</text>
-	<text name="format_label">
-		Formato
-	</text>
-	<combo_box label="Risoluzione" name="postcard_size_combo">
-		<combo_box.item label="Finestra attuale" name="CurrentWindow"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="Personalizza" name="Custom"/>
-	</combo_box>
-	<combo_box label="Risoluzione" name="texture_size_combo">
-		<combo_box.item label="Finestra attuale" name="CurrentWindow"/>
-		<combo_box.item label="Piccola (128x128)" name="Small(128x128)"/>
-		<combo_box.item label="Media (256x256)" name="Medium(256x256)"/>
-		<combo_box.item label="Grande (512x512)" name="Large(512x512)"/>
-		<combo_box.item label="Personalizza" name="Custom"/>
-	</combo_box>
-	<combo_box label="Risoluzione" name="local_size_combo">
-		<combo_box.item label="Finestra attuale" name="CurrentWindow"/>
-		<combo_box.item label="320x240" name="320x240"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="1280x1024" name="1280x1024"/>
-		<combo_box.item label="1600x1200" name="1600x1200"/>
-		<combo_box.item label="Personalizza" name="Custom"/>
-	</combo_box>
-	<combo_box label="Formato" name="local_format_combo">
-		<combo_box.item label="PNG" name="PNG"/>
-		<combo_box.item label="JPEG" name="JPEG"/>
-		<combo_box.item label="BMP" name="BMP"/>
-	</combo_box>
-	<spinner label="Larghezza" name="snapshot_width"/>
-	<spinner label="Altezza" name="snapshot_height"/>
-	<check_box label="Mantieni le proporzioni" name="keep_aspect_check"/>
-	<slider label="Qualità dell&apos;immagine" name="image_quality_slider"/>
-	<text name="layer_type_label">
-		Cattura:
-	</text>
-	<combo_box label="Layer dell&apos;immagine" name="layer_types">
-		<combo_box.item label="Colori" name="Colors"/>
-		<combo_box.item label="Profondità" name="Depth"/>
-	</combo_box>
-	<check_box label="Interfaccia" name="ui_check"/>
-	<check_box label="HUD" name="hud_check"/>
-	<check_box label="Tieni aperta dopo il salvataggio" name="keep_open_check"/>
-	<check_box label="Congela il frame (tutto schermo)" name="freeze_frame_check"/>
-	<check_box label="Aggiornamento automatico" name="auto_snapshot_check"/>
+	<panel name="advanced_options_panel">
+		<text name="advanced_options_label">
+			OPZIONI AVANZATE
+		</text>
+		<text name="layer_type_label">
+			Cattura:
+		</text>
+		<combo_box label="Layer dell&apos;immagine" name="layer_types">
+			<combo_box.item label="Colori" name="Colors"/>
+			<combo_box.item label="Profondità" name="Depth"/>
+		</combo_box>
+		<check_box label="Interfaccia" name="ui_check"/>
+		<check_box label="HUD" name="hud_check"/>
+		<check_box label="Congela il frame (tutto schermo)" name="freeze_frame_check"/>
+		<check_box label="Aggiornamento automatico" name="auto_snapshot_check"/>
+	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/it/floater_toybox.xml b/indra/newview/skins/default/xui/it/floater_toybox.xml
index c8d5f1ed7c..269e2831d0 100644
--- a/indra/newview/skins/default/xui/it/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/it/floater_toybox.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Toybox" title="PERSONALIZZA BARRE STRUMENTI">
+<floater name="Toybox" title="PULSANTI BARRA STRUMENTI">
 	<text name="toybox label 1">
 		Aggiungere o rimuovere pulsanti trascinandoli dentro o fuori dalle barre strumenti.
 	</text>
 	<text name="toybox label 2">
 		I pulsanti verranno visualizzati come mostrato o solo come icone, a seconda delle impostazioni della singola barra degli strumenti.
 	</text>
+	<button label="Cancella tutte le barre strumenti" label_selected="Cancella tutte le barre strumenti" name="btn_clear_all"/>
 	<button label="Ripristina predefiniti" label_selected="Ripristina predefiniti" name="btn_restore_defaults"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/it/floater_translation_settings.xml b/indra/newview/skins/default/xui/it/floater_translation_settings.xml
new file mode 100644
index 0000000000..a0a34da723
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/floater_translation_settings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_translation_settings" title="IMPOSTAZIONI TRADUZIONE CHAT">
+	<string name="bing_api_key_not_verified">
+		appID Bing non verificato. Riprova.
+	</string>
+	<string name="google_api_key_not_verified">
+		Chiave API Google non verificata. Riprova.
+	</string>
+	<string name="bing_api_key_verified">
+		appID Bing verificato.
+	</string>
+	<string name="google_api_key_verified">
+		Chiave API Google verificata.
+	</string>
+	<check_box label="Usa la traduzione meccanica durante le chat" name="translate_chat_checkbox"/>
+	<text name="translate_language_label">
+		Traduci chat in:
+	</text>
+	<combo_box name="translate_language_combo">
+		<combo_box.item label="Predefinito di sistema" name="System Default Language"/>
+		<combo_box.item label="English (Inglese)" name="English"/>
+		<combo_box.item label="Dansk (Danese)" name="Danish"/>
+		<combo_box.item label="Deutsch (Tedesco)" name="German"/>
+		<combo_box.item label="Español (Spagnolo)" name="Spanish"/>
+		<combo_box.item label="Français (Francese)" name="French"/>
+		<combo_box.item label="Italiano" name="Italian"/>
+		<combo_box.item label="Magyar (Ungherese)" name="Hungarian"/>
+		<combo_box.item label="Nederlands (Olandese)" name="Dutch"/>
+		<combo_box.item label="Polski (Polacco)" name="Polish"/>
+		<combo_box.item label="Português (Portoghese)" name="Portugese"/>
+		<combo_box.item label="Русский (Russo)" name="Russian"/>
+		<combo_box.item label="Türkçe (Turco)" name="Turkish"/>
+		<combo_box.item label="Українська (Ucraino)" name="Ukrainian"/>
+		<combo_box.item label="中文 (正體) (Cinese)" name="Chinese"/>
+		<combo_box.item label="日本語 (Giapponese)" name="Japanese"/>
+		<combo_box.item label="한국어 (Coreano)" name="Korean"/>
+	</combo_box>
+	<text name="tip">
+		Seleziona il servizio di traduzione:
+	</text>
+	<radio_group name="translation_service_rg">
+		<radio_item initial_value="bing" label="Bing Translator" name="bing"/>
+		<radio_item initial_value="google" label="Google Translate" name="google"/>
+	</radio_group>
+	<text name="bing_api_key_label">
+		Bing [http://www.bing.com/developers/createapp.aspx AppID]:
+	</text>
+	<button label="Verifica" name="verify_bing_api_key_btn"/>
+	<text name="google_api_key_label">
+		Google [http://code.google.com/apis/language/translate/v2/getting_started.html#auth API key]:
+	</text>
+	<button label="Verifica" name="verify_google_api_key_btn"/>
+	<text name="google_links_text">
+		[http://code.google.com/apis/language/translate/v2/pricing.html Prezzi] | [https://code.google.com/apis/console Statistiche]
+	</text>
+	<button label="OK" name="ok_btn"/>
+	<button label="Annulla" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_voice_controls.xml b/indra/newview/skins/default/xui/it/floater_voice_controls.xml
index d0ac815b8b..77973eef1e 100644
--- a/indra/newview/skins/default/xui/it/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/it/floater_voice_controls.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="floater_voice_controls" title="CONTROLLI VOCE">
 	<string name="title_nearby">
-		Voce vicina
+		IMPOSTAZIONI VOCE
 	</string>
 	<string name="title_group">
-		Chiamata di gruppo con [GROUP]
+		CHIAMATA DI GRUPPO CON [GROUP]
 	</string>
 	<string name="title_adhoc">
-		Chiamata in conferenza
+		CHIAMATA IN CONFERENZA
 	</string>
 	<string name="title_peer_2_peer">
-		Chiamata con [NAME]
+		CHIAMATA CON [NAME]
 	</string>
 	<string name="no_one_near">
 		Nessuno nei dintorni ha attivato la funzione voce
diff --git a/indra/newview/skins/default/xui/it/menu_toolbars.xml b/indra/newview/skins/default/xui/it/menu_toolbars.xml
index 784ecd262c..604ca763d1 100644
--- a/indra/newview/skins/default/xui/it/menu_toolbars.xml
+++ b/indra/newview/skins/default/xui/it/menu_toolbars.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <context_menu name="Toolbars Popup">
-	<menu_item_call label="Seleziona pulsanti..." name="Chose Buttons"/>
+	<menu_item_call label="Rimuovi questo pulsante" name="Remove button"/>
+	<menu_item_call label="Pulsanti barra strumenti..." name="Choose Buttons"/>
 	<menu_item_check label="Icone ed etichette" name="icons_with_text"/>
 	<menu_item_check label="Solo icone" name="icons_only"/>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml
index 8792a0fc19..5140d2b1ec 100644
--- a/indra/newview/skins/default/xui/it/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/it/menu_viewer.xml
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <menu_bar name="Main Menu">
 	<menu label="Io" name="Me">
-		<menu_item_call label="Dashboard..." name="Manage My Account">
-			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=it"/>
-		</menu_item_call>
 		<menu_item_call label="Profilo..." name="Profile"/>
 		<menu_item_call label="Aspetto fisico..." name="ChangeOutfit"/>
+		<menu_item_call label="Scegli un avatar..." name="Avatar Picker"/>
 		<menu_item_check label="Inventario..." name="Inventory"/>
-		<menu_item_check label="Gesture..." name="Gestures"/>
-		<menu_item_check label="Voce..." name="ShowVoice"/>
+		<menu_item_call label="Nuova finestra inventario" name="NewInventoryWindow"/>
+		<menu_item_call label="Luoghi..." name="Places"/>
+		<menu_item_call label="Preferiti..." name="Picks"/>
+		<menu_item_call label="Controlli fotocamera..." name="Camera Controls"/>
 		<menu label="Spostamento" name="Movement">
 			<menu_item_call label="Siedi" name="Sit Down Here"/>
 			<menu_item_check label="Vola" name="Fly"/>
@@ -22,34 +22,39 @@
 		<menu_item_call label="Richiedi diritti Admin" name="Request Admin Options"/>
 		<menu_item_call label="Lascia stato Admin" name="Leave Admin Options"/>
 		<menu_item_call label="Compra L$" name="Buy and Sell L$"/>
+		<menu_item_call label="Dashboard dell&apos;account..." name="Manage My Account">
+			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=it"/>
+		</menu_item_call>
 		<menu_item_call label="Preferenze..." name="Preferences"/>
-		<menu_item_call label="Barre strumenti..." name="Toolbars"/>
+		<menu_item_call label="Pulsanti barra strumenti..." name="Toolbars"/>
 		<menu_item_call label="Nascondi tutti i controlli" name="Hide UI"/>
 		<menu_item_call label="Esci da [APP_NAME]" name="Quit"/>
 	</menu>
 	<menu label="Comunica" name="Communicate">
-		<menu_item_call label="I miei amici..." name="My Friends"/>
-		<menu_item_call label="I miei gruppi" name="My Groups"/>
-		<menu_item_check label="Chat nei dintorni" name="Nearby Chat"/>
+		<menu_item_check label="Chat..." name="Nearby Chat"/>
+		<menu_item_check label="Parla" name="Speak"/>
+		<menu_item_check label="Impostazioni voce..." name="Nearby Voice"/>
+		<menu_item_check label="Manipolazione voce..." name="ShowVoice"/>
+		<menu_item_check label="Gesture..." name="Gestures"/>
+		<menu_item_call label="Amici" name="My Friends"/>
+		<menu_item_call label="Gruppi" name="My Groups"/>
 		<menu_item_call label="Persone vicine" name="Active Speakers"/>
-		<menu_item_check label="Voce nei dintorni" name="Nearby Voice"/>
 	</menu>
 	<menu label="Mondo" name="World">
+		<menu_item_call label="Crea punto di riferimento per questo luogo" name="Create Landmark Here"/>
+		<menu_item_call label="Destinazioni..." name="Destinations"/>
+		<menu_item_check label="Mappamondo" name="World Map"/>
 		<menu_item_check label="Mini mappa" name="Mini-Map"/>
-		<menu_item_check label="Mappa del mondo" name="World Map"/>
 		<menu_item_check label="Cerca" name="Search"/>
+		<menu_item_call label="Teleport a Casa" name="Teleport Home"/>
+		<menu_item_call label="Imposta come Casa mia" name="Set Home to Here"/>
 		<menu_item_call label="Istantanea" name="Take Snapshot"/>
-		<menu_item_call label="Crea punto di riferimento per questo luogo" name="Create Landmark Here"/>
-		<menu label="Profilo del luogo" name="Land">
-			<menu_item_call label="Profilo del luogo" name="Place Profile"/>
-			<menu_item_call label="Informazioni sui terreni" name="About Land"/>
-			<menu_item_call label="Regione/proprietà immobiliare" name="Region/Estate"/>
-		</menu>
+		<menu_item_call label="Profilo del luogo" name="Place Profile"/>
+		<menu_item_call label="Informazioni sul terreno" name="About Land"/>
+		<menu_item_call label="Regione/proprietà immobiliare" name="Region/Estate"/>
+		<menu_item_call label="Terreni posseduti..." name="My Land"/>
 		<menu_item_call label="Acquista questo terreno" name="Buy Land"/>
-		<menu_item_call label="Il mio terreno" name="My Land"/>
 		<menu label="Mostra" name="LandShow">
-			<menu_item_check label="Comandi del movimento" name="Movement Controls"/>
-			<menu_item_check label="Comandi visualizzazione" name="Camera Controls"/>
 			<menu_item_check label="Linee di divieto" name="Ban Lines"/>
 			<menu_item_check label="Marcatori" name="beacons"/>
 			<menu_item_check label="Linee di confine" name="Property Lines"/>
@@ -58,29 +63,28 @@
 			<menu_item_check label="Proprietà del lotto" name="Parcel Properties"/>
 			<menu_item_check label="Menu Avanzato" name="Show Advanced Menu"/>
 		</menu>
-		<menu_item_call label="Teleport a Casa" name="Teleport Home"/>
-		<menu_item_call label="Imposta come Casa mia" name="Set Home to Here"/>
 		<menu label="Sole" name="Environment Settings">
 			<menu_item_call label="Alba" name="Sunrise"/>
 			<menu_item_call label="Mezzogiorno" name="Noon"/>
 			<menu_item_call label="Tramonto" name="Sunset"/>
 			<menu_item_call label="Mezzanotte" name="Midnight"/>
+			<menu_item_call label="Usa impostazioni regione" name="Use Region Settings"/>
 		</menu>
-		<menu label="Editor ambiente" name="Enviroment Editor">
-			<menu_item_call label="Impostazioni ambiente..." name="Enviroment Settings"/>
+		<menu label="Editor ambiente" name="Environment Editor">
+			<menu_item_call label="Impostazioni ambiente..." name="Environment Settings"/>
 			<menu label="Valori predefiniti acqua" name="Water Presets">
 				<menu_item_call label="Nuovo valore predefinito..." name="new_water_preset"/>
-				<menu_item_call label="Modifica valori predefiniti..." name="edit_water_preset"/>
+				<menu_item_call label="Modifica valore predefinito..." name="edit_water_preset"/>
 				<menu_item_call label="Cancella valore predefinito..." name="delete_water_preset"/>
 			</menu>
 			<menu label="Valori predefiniti cielo" name="Sky Presets">
 				<menu_item_call label="Nuovo valore predefinito..." name="new_sky_preset"/>
-				<menu_item_call label="Modifica valori predefiniti..." name="edit_sky_preset"/>
+				<menu_item_call label="Modifica valore predefinito..." name="edit_sky_preset"/>
 				<menu_item_call label="Cancella valore predefinito..." name="delete_sky_preset"/>
 			</menu>
-			<menu label="Valori predefiniti giornata" name="Day Presets">
+			<menu label="Valori predefiniti giorno" name="Day Presets">
 				<menu_item_call label="Nuovo valore predefinito..." name="new_day_preset"/>
-				<menu_item_call label="Modifica valori predefiniti..." name="edit_day_preset"/>
+				<menu_item_call label="Modifica valore predefinito..." name="edit_day_preset"/>
 				<menu_item_call label="Cancella valore predefinito..." name="delete_day_preset"/>
 			</menu>
 		</menu>
@@ -146,6 +150,7 @@
 		<menu_item_call label="Ripeti" name="Redo"/>
 	</menu>
 	<menu label="Aiuto" name="Help">
+		<menu_item_call label="Istruzioni..." name="How To"/>
 		<menu_item_call label="Aiuto di [SECOND_LIFE]" name="Second Life Help"/>
 		<menu_item_call label="Segnala abuso" name="Report Abuse"/>
 		<menu_item_call label="Segnala bug" name="Report Bug"/>
@@ -199,11 +204,10 @@
 		<menu_item_check label="Usa thread lettura plugin" name="Use Plugin Read Thread"/>
 		<menu_item_call label="Pulisci cache di gruppo" name="ClearGroupCache"/>
 		<menu_item_check label="Fluidità mouse" name="Mouse Smoothing"/>
+		<menu_item_call label="Rilascia tasti" name="Release Keys"/>
 		<menu label="Scorciatoie" name="Shortcuts">
 			<menu_item_call label="Immagine ([COST]L$)..." name="Upload Image"/>
 			<menu_item_check label="Cerca" name="Search"/>
-			<menu_item_call label="Rilascia tasti" name="Release Keys"/>
-			<menu_item_call label="Imposta dimensioni dell&apos;interfaccia sui valori predefiniti" name="Set UI Size to Default"/>
 			<menu_item_check label="Mostra menu Avanzato - tasti di scelta rapida esistenti" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Chiudi finestra" name="Close Window"/>
 			<menu_item_call label="Chiudi tutte le finestre" name="Close All Windows"/>
@@ -272,6 +276,7 @@
 			<menu_item_check label="Aggiorna tipo" name="Update Type"/>
 			<menu_item_check label="Info livello dettaglio" name="LOD Info"/>
 			<menu_item_check label="Crea coda" name="Build Queue"/>
+			<menu_item_check label="Vettori vento" name="Wind Vectors"/>
 			<menu_item_check label="Complessità rendering" name="rendercomplexity"/>
 			<menu_item_check label="Scolpisci" name="Sculpt"/>
 		</menu>
@@ -281,7 +286,6 @@
 			<menu_item_check label="Luci e ombre" name="Lighting and Shadows"/>
 			<menu_item_check label="Ombra dal sole, dalla luna e dai proiettori" name="Shadows from Sun/Moon/Projectors"/>
 			<menu_item_check label="SSAO e ombre fluide" name="SSAO and Shadow Smoothing"/>
-			<menu_item_check label="Illuminazione globale (sperimentale)" name="Global Illumination"/>
 			<menu_item_check label="Maschera alfa automatica (differita)" name="Automatic Alpha Masks (deferred)"/>
 			<menu_item_check label="Maschera alfa automatica (non differita)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Texture delle animazioni" name="Animation Textures"/>
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index fce027da0c..fcc515186d 100644
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -1110,8 +1110,13 @@ Cedere questi [AREA] m² di terreno al gruppo &apos;[GROUP_NAME]&apos;?
 	<notification name="DisplaySetToSafe">
 		Le impostazioni dello schermo sono state impostate a valori di sicurezza perchè hai specificato l&apos;opzione -safe.
 	</notification>
-	<notification name="DisplaySetToRecommended">
-		Le impostazioni dello schermo sono state impostate a valori ottimali basati sulla tua configurazione di sistema.
+	<notification name="DisplaySetToRecommendedGPUChange">
+		Le impostazioni di visualizzazione sono ai livelli consigliati a causa di un cambiamento nella scheda grafica
+da &apos;[LAST_GPU]&apos;
+a &apos;[THIS_GPU]&apos;
+	</notification>
+	<notification name="DisplaySetToRecommendedFeatureChange">
+		Le impostazioni di visualizzazione sono ai livelli consigliati a causa di un cambiamento nel sottosistema di rendering.
 	</notification>
 	<notification name="ErrorMessage">
 		[ERROR_MESSAGE]
@@ -1916,7 +1921,13 @@ Trasferisci gli elementi nell&apos;inventario?
 		<usetemplate ignoretext="Conferma prima di uscire" name="okcancelignore" notext="Non uscire" yestext="Esci"/>
 	</notification>
 	<notification name="ConfirmRestoreToybox">
-		Passare ai pulsanti e alle barre strumenti predefinite? 
+		Questa azione ripristina pulsanti e barre degli strumenti predefinite.
+
+Questa azione non può essere ripristinata
+		<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
+	</notification>
+	<notification name="ConfirmClearAllToybox">
+		Questa azione riporterà tutti i pulsanti nella casella strumenti. Le barre degli strumenti saranno vuote.
     
 Questa azione non può essere ripristinata
 		<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
@@ -2125,10 +2136,10 @@ Verrà avviato il browser Web.
 		Oggetto: [SUBJECT], Messaggio: [MESSAGE]
 	</notification>
 	<notification name="FriendOnline">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; è Online
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; è online
 	</notification>
 	<notification name="FriendOffline">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; è Offline
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; è offline
 	</notification>
 	<notification name="AddSelfFriend">
 		Anche se sei molto simpatico, non puoi aggiungere te stesso all&apos;elenco degli amici.
@@ -2241,14 +2252,16 @@ Seleziona solo un oggetto.
 		Il tuo biglietto da visita non è stato accettato.
 	</notification>
 	<notification name="TeleportToLandmark">
-		Puoi teleportarti alle ubicazioni come &apos;[NAME]&apos; aprendo il pannello Luoghi sul lato destro dello schermo, quindi selezionare la scheda Punti di riferimento.
-Clicca su un punto di riferimento per selezionarlo, quindi clicca su Teleport sul lato inferiore del pannello.
-(Puoi anche fare doppio clic sul punto di riferimento oppure cliccare su di esso con il tasto destro del mouse e scegliere Teleport.)
+		Per teleportarti a luoghi come &apos;[NAME]&apos;, clicca sul pulsante &quot;Luoghi&quot;,
+    quindi seleziona la scheda Punti di riferimento nel pannello che viene aperto. Clicca su qualsiasi
+    unto di riferimento per selezionarlo, quindi clicca su Teleport sul lato inferiore del pannello.
+    (Puoi anche fare doppio clic sul punto di riferimento oppure cliccare su di esso con il tasto destro del mouse e 
+    scegliere Teleport.)
 	</notification>
 	<notification name="TeleportToPerson">
-		Puoi contattare il residente &apos;[NAME]&apos; aprendo il pannello Persone nel lato destro del tuo schermo.
-Seleziona il residente dall&apos;elenco, clicca su &apos;IM&apos; in basso nel pannello.
-(Puoi anche fare doppio clic sul nome nell&apos;elenco oppure fare clic con il pulsante destro del mouse e selezionare &apos;IM&apos;).
+		Per contattare Residenti come &apos;[NAME]&apos;, clicca sul pulsante &quot;Persone&quot;, seleziona un Residente nel pannello che viene aperto, quindi clicca su &apos;IM&apos; in
+    basso nel pannello.
+    (Puoi anche fare doppio clic sul nome nell&apos;elenco oppure fare clic con il pulsante destro del mouse e selezionare &apos;IM&apos;).
 	</notification>
 	<notification name="CantSelectLandFromMultipleRegions">
 		Non è possibile selezionare il terreno attraverso i confini del server.
@@ -2269,6 +2282,9 @@ Prova a selezionare una parte di terreno più piccola.
 	<notification name="PaymentSent">
 		[MESSAGE]
 	</notification>
+	<notification name="PaymentFailure">
+		[MESSAGE]
+	</notification>
 	<notification name="EventNotification">
 		Notifica eventi:
 
@@ -2520,10 +2536,10 @@ Riprova tra qualche istante.
 		</form>
 	</notification>
 	<notification name="FriendshipAccepted">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; ha accettato la tua offerta di amicizia.
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; ha accettato la tua richiesta di amicizia.
 	</notification>
 	<notification name="FriendshipDeclined">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; ha rifiutato la tua offerta di amicizia.
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; ha rifiutato la tua richiesta di amicizia.
 	</notification>
 	<notification name="FriendshipAcceptedByMe">
 		Offerta di amicizia accettata.
@@ -2800,7 +2816,7 @@ Per informazioni dettagliate, vedi il file del registro.
 Con i seguenti residenti?
 
 [RESIDENTS]
-		<usetemplate name="okcancelbuttons" notext="Annulla" yestext="Ok"/>
+		<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
 	</notification>
 	<notification name="ItemsShared">
 		Gli oggetti sono stati condivisi.
@@ -2890,7 +2906,7 @@ In questo modo verrà disattivato l&apos;audio anche di tutti i residenti che si
 uniscono alla chiamata in un secondo momento, anche dopo che tu ti fossi scollegato.
 
 Disattiva audio di tutti?
-		<usetemplate ignoretext="Conferma prima di disattivare l&apos;audio di tutti i partecipanti alla chiamata di gruppo" name="okcancelignore" notext="Annulla" yestext="Ok"/>
+		<usetemplate ignoretext="Conferma prima di disattivare l&apos;audio di tutti i partecipanti alla chiamata di gruppo" name="okcancelignore" notext="Annulla" yestext="OK"/>
 	</notification>
 	<notification label="Chat" name="HintChat">
 		Per partecipare alla conversazione, digita nel campo chat in basso.
diff --git a/indra/newview/skins/default/xui/it/panel_edit_skin.xml b/indra/newview/skins/default/xui/it/panel_edit_skin.xml
index a15489b333..466eff2708 100644
--- a/indra/newview/skins/default/xui/it/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/it/panel_edit_skin.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_skin_panel">
 	<panel name="avatar_skin_color_panel">
-		<texture_picker label="Tatuaggi testa" name="Head Tattoos" tool_tip="Clicca per scegliere una fotografia"/>
-		<texture_picker label="Tatuaggi superiori" name="Upper Tattoos" tool_tip="Clicca per scegliere una fotografia"/>
-		<texture_picker label="Tatuaggi inferiori" name="Lower Tattoos" tool_tip="Clicca per scegliere una fotografia"/>
+		<texture_picker label="Testa" name="Head" tool_tip="Clicca per scegliere una fotografia"/>
+		<texture_picker label="Parte superiore del corpo" name="Upper Body" tool_tip="Clicca per scegliere una fotografia"/>
+		<texture_picker label="Parte inferiore del corpo" name="Lower Body" tool_tip="Clicca per scegliere una fotografia"/>
 	</panel>
 	<panel name="accordion_panel">
 		<accordion name="wearable_accordion">
diff --git a/indra/newview/skins/default/xui/it/panel_postcard_message.xml b/indra/newview/skins/default/xui/it/panel_postcard_message.xml
new file mode 100644
index 0000000000..c720f4822d
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_postcard_message.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_message">
+	<text name="to_label">
+		A:
+	</text>
+	<text name="name_label">
+		Da:
+	</text>
+	<text name="subject_label">
+		Oggetto:
+	</text>
+	<line_editor label="Digita qui l&apos;oggetto." name="subject_form"/>
+	<text name="msg_label">
+		Messaggio:
+	</text>
+	<text_editor name="msg_form">
+		Digita qui il messaggio.
+	</text_editor>
+	<button label="Annulla" name="cancel_btn"/>
+	<button label="Invia" name="send_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_postcard_settings.xml b/indra/newview/skins/default/xui/it/panel_postcard_settings.xml
new file mode 100644
index 0000000000..6a586c4415
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_postcard_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_settings">
+	<combo_box label="Risoluzione" name="postcard_size_combo">
+		<combo_box.item label="Finestra attuale" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Personalizza" name="Custom"/>
+	</combo_box>
+	<layout_stack name="postcard_image_params_ls">
+		<layout_panel name="postcard_image_size_lp">
+			<spinner label="Larghezza" name="postcard_snapshot_width"/>
+			<spinner label="Altezza" name="postcard_snapshot_height"/>
+			<check_box label="Mantieni le proporzioni" name="postcard_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="postcard_image_format_quality_lp">
+			<slider label="Qualità dell&apos;immagine" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml
index 1a0a1d8434..7f5992b584 100644
--- a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml
@@ -29,30 +29,5 @@
 	<check_box label="Chat IM" name="EnableIMChatPopups" tool_tip="Seleziona per vedere una finestra popup quando arriva un messaggio IM"/>
 	<spinner label="Durata chat vicine:" name="nearby_toasts_lifetime"/>
 	<spinner label="Durata dissolvenza chat vicine:" name="nearby_toasts_fadingtime"/>
-	<check_box label="Use machine translation while chatting" name="translate_chat_checkbox"/>
-	<text name="translate_chb_label">
-		Usa la traduzione meccanica durante le chat
-	</text>
-	<text name="translate_language_text" width="110">
-		Traduci chat in:
-	</text>
-	<combo_box name="translate_language_combobox" width="146">
-		<combo_box.item label="Default di sistema" name="System Default Language"/>
-		<combo_box.item label="English (Inglese)" name="English"/>
-		<combo_box.item label="Dansk (Danese)" name="Danish"/>
-		<combo_box.item label="Deutsch (Tedesco)" name="German"/>
-		<combo_box.item label="Español (Spagnolo)" name="Spanish"/>
-		<combo_box.item label="Français (Francese)" name="French"/>
-		<combo_box.item label="Italiano" name="Italian"/>
-		<combo_box.item label="Magyar (Ungherese)" name="Hungarian"/>
-		<combo_box.item label="Nederlands (Olandese)" name="Dutch"/>
-		<combo_box.item label="Polski (Polacco)" name="Polish"/>
-		<combo_box.item label="Português (Portoghese)" name="Portugese"/>
-		<combo_box.item label="Русский (Russo)" name="Russian"/>
-		<combo_box.item label="Türkçe (Turco)" name="Turkish"/>
-		<combo_box.item label="Українська (Ucraino)" name="Ukrainian"/>
-		<combo_box.item label="中文 (正體) (Cinese)" name="Chinese"/>
-		<combo_box.item label="日本語 (Giapponese)" name="Japanese"/>
-		<combo_box.item label="한국어 (Coreano)" name="Korean"/>
-	</combo_box>
+	<button label="Impostazioni traduzione chat" name="ok_btn"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_setup.xml b/indra/newview/skins/default/xui/it/panel_preferences_setup.xml
index bf78432110..0189d47f45 100644
--- a/indra/newview/skins/default/xui/it/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/it/panel_preferences_setup.xml
@@ -15,7 +15,7 @@
 		Web:
 	</text>
 	<radio_group name="use_external_browser">
-		<radio_item label="Usa il mio browser (IE, Firefox, Safari)" name="external" tool_tip="Utilizza il browser Web predefinito di sistema per l&apos;aiuto, per i link Web e così via. Sconsigliato durante l&apos;esecuzione a tutto schermo." value="1"/>
+		<radio_item label="Usa il mio browser (IE, Firefox, Safari)" name="external" tool_tip="Utilizza il browser Web predefinito di sistema per l&apos;aiuto, per i link Web e così via. Sconsigliato durante l&apos;esecuzione a tutto schermo." value="true"/>
 		<radio_item label="Utilizza il browser Web integrato" name="internal" tool_tip="Utilizza il browser Web integrato per l&apos;aiuto, per i link Web e così via. Questo browser si apre in una nuova finestra in [APP_NAME]." value=""/>
 	</radio_group>
 	<check_box initial_value="true" label="Abilita plugin" name="browser_plugins_enabled"/>
diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml
new file mode 100644
index 0000000000..c9245029b7
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_inventory">
+	<text name="title">
+		Salva nell&apos;inventario
+	</text>
+	<text name="hint_lbl">
+		Salvare un&apos;immagine nell&apos;inventario costa L$[UPLOAD_COST]. Per salvare l&apos;immagine come texture, selezionare uno dei formati quadrati.
+	</text>
+	<combo_box label="Risoluzione" name="texture_size_combo">
+		<combo_box.item label="Finestra attuale" name="CurrentWindow"/>
+		<combo_box.item label="Piccola (128x128)" name="Small(128x128)"/>
+		<combo_box.item label="Media (256x256)" name="Medium(256x256)"/>
+		<combo_box.item label="Grande (512x512)" name="Large(512x512)"/>
+		<combo_box.item label="Personalizza" name="Custom"/>
+	</combo_box>
+	<spinner label="Larghezza" name="inventory_snapshot_width"/>
+	<spinner label="Altezza" name="inventory_snapshot_height"/>
+	<check_box label="Mantieni le proporzioni" name="inventory_keep_aspect_check"/>
+	<button label="Annulla" name="cancel_btn"/>
+	<button label="Salva" name="save_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_local.xml b/indra/newview/skins/default/xui/it/panel_snapshot_local.xml
new file mode 100644
index 0000000000..4b725b68f9
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_snapshot_local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_local">
+	<text name="title">
+		Salva sul mio computer
+	</text>
+	<combo_box label="Risoluzione" name="local_size_combo">
+		<combo_box.item label="Finestra attuale" name="CurrentWindow"/>
+		<combo_box.item label="320x240" name="320x240"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="1280x1024" name="1280x1024"/>
+		<combo_box.item label="1600x1200" name="1600x1200"/>
+		<combo_box.item label="Personalizza" name="Custom"/>
+	</combo_box>
+	<layout_stack name="local_image_params_ls">
+		<layout_panel name="local_image_size_lp">
+			<spinner label="Larghezza" name="local_snapshot_width"/>
+			<spinner label="Altezza" name="local_snapshot_height"/>
+			<check_box label="Mantieni le proporzioni" name="local_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="local_image_format_quality_lp">
+			<combo_box label="Formato" name="local_format_combo">
+				<combo_box.item label="PNG (senza perdite)" name="PNG"/>
+				<combo_box.item label="JPEG" name="JPEG"/>
+				<combo_box.item label="BMP (senza perdite)" name="BMP"/>
+			</combo_box>
+			<slider label="Qualità dell&apos;immagine" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+	<button label="Annulla" name="cancel_btn"/>
+	<flyout_button label="Salva" name="save_btn" tool_tip="Salva immagine come file">
+		<flyout_button.item label="Salva" name="save_item"/>
+		<flyout_button.item label="Salva con nome..." name="saveas_item"/>
+	</flyout_button>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_options.xml b/indra/newview/skins/default/xui/it/panel_snapshot_options.xml
new file mode 100644
index 0000000000..f2d42c5197
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_snapshot_options.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_options">
+	<button label="Invia post al feed del mio profilo" name="save_to_profile_btn"/>
+	<button label="E-mail" name="save_to_email_btn"/>
+	<button label="Salva nell&apos;inventario (L$[AMOUNT])" name="save_to_inventory_btn"/>
+	<button label="Salva sul mio computer" name="save_to_computer_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml
new file mode 100644
index 0000000000..3703b97e6c
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+	<string name="default_subject">
+		Cartolina da [SECOND_LIFE].
+	</string>
+	<string name="default_message">
+		Dai un&apos;occhiata!
+	</string>
+	<string name="upload_message">
+		Invio...
+	</string>
+	<text name="title">
+		E-mail
+	</text>
+	<button label="Messaggio" name="message_btn"/>
+	<button label="Impostazioni" name="settings_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/it/panel_snapshot_profile.xml
new file mode 100644
index 0000000000..2cdbf97049
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_snapshot_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_profile">
+	<text name="title">
+		Invia post al feed del mio profilo
+	</text>
+	<combo_box label="Risoluzione" name="profile_size_combo">
+		<combo_box.item label="Finestra attuale" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Personalizza" name="Custom"/>
+	</combo_box>
+	<layout_stack name="profile_image_params_ls">
+		<layout_panel name="profile_image_size_lp">
+			<spinner label="Larghezza" name="profile_snapshot_width"/>
+			<spinner label="Altezza" name="profile_snapshot_height"/>
+			<check_box label="Mantieni le proporzioni" name="profile_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="profile_image_metadata_lp">
+			<text name="caption_label">
+				Didascalia:
+			</text>
+			<check_box initial_value="true" label="Includi luogo" name="add_location_cb"/>
+		</layout_panel>
+	</layout_stack>
+	<button label="Annulla" name="cancel_btn"/>
+	<button label="Post" name="post_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index 8f29233825..c81dd0f55d 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -1205,7 +1205,7 @@ Prova ad accedere nuovamente tra un minuto.
 		Non hai una copia di questa texture nel tuo inventario
 	</string>
 	<string name="InventoryInboxNoItems">
-		Gli elementi acquistati attraverso il mercato verranno consegnati qui
+		Quando acquisti o ricevi un oggetto, verrà visualizzato qui per permetterti di trascinarlo in una cartella dell&apos;inventario o di cancellarlo se non desideri mantenerlo.
 	</string>
 	<string name="MarketplaceURL">
 		http://marketplace.[DOMAIN_NAME]/learn_more
@@ -1397,6 +1397,9 @@ Prova ad accedere nuovamente tra un minuto.
 	<string name="no_attachments">
 		Nessun allegato indossato
 	</string>
+	<string name="Attachments remain">
+		Allegati ([COUNT] spazi restanti)
+	</string>
 	<string name="Buy">
 		Acquista
 	</string>
@@ -1523,6 +1526,12 @@ Prova ad accedere nuovamente tra un minuto.
 	<string name="Right Pec">
 		Petto destro
 	</string>
+	<string name="Neck">
+		Collo
+	</string>
+	<string name="Avatar Center">
+		Centro avatar
+	</string>
 	<string name="Invalid Attachment">
 		Punto di collegamento non valido
 	</string>
@@ -3940,6 +3949,18 @@ Se il messaggio persiste, contatta [SUPPORT_SITE].
 	<string name="you_paid_ldollars_no_name">
 		Hai pagato L$ [AMOUNT] [REASON].
 	</string>
+	<string name="you_paid_failure_ldollars">
+		Non hai pagato [NAME] L$[AMOUNT] [REASON].
+	</string>
+	<string name="you_paid_failure_ldollars_no_info">
+		Non hai pagato L$ [AMOUNT].
+	</string>
+	<string name="you_paid_failure_ldollars_no_reason">
+		Non hai pagato [NAME] L$[AMOUNT].
+	</string>
+	<string name="you_paid_failure_ldollars_no_name">
+		Non hai pagato L$ [AMOUNT] [REASON].
+	</string>
 	<string name="for item">
 		per [ITEM]
 	</string>
@@ -4350,6 +4371,12 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 	<string name="ExternalEditorFailedToRun">
 		L&apos;editor esterno non è stato avviato.
 	</string>
+	<string name="TranslationFailed">
+		Traduzione non riuscita: [REASON]
+	</string>
+	<string name="TranslationResponseParseError">
+		Errore di elaborazione della risposta della traduzione.
+	</string>
 	<string name="Esc">
 		Esc
 	</string>
@@ -4720,7 +4747,7 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 		Mini mappa
 	</string>
 	<string name="Command_Move_Label">
-		Movimento
+		Cammina / corri / vola
 	</string>
 	<string name="Command_People_Label">
 		Persone
@@ -4747,10 +4774,10 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 		Parla
 	</string>
 	<string name="Command_View_Label">
-		Visuale
+		Controlli fotocamera
 	</string>
 	<string name="Command_Voice_Label">
-		Voce vicina
+		Impostazioni voce
 	</string>
 	<string name="Command_AboutLand_Tooltip">
 		Informazioni sul terreno che visiti
@@ -4822,7 +4849,16 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 		Modifica angolo fotocamera
 	</string>
 	<string name="Command_Voice_Tooltip">
-		Persona vicine con funzioni voce
+		I controlli per il volume per le chiamate e per le persone nelle vicinanze nel mondo virtuale
+	</string>
+	<string name="Toolbar_Bottom_Tooltip">
+		attualmente nella barra degli strumenti in basso
+	</string>
+	<string name="Toolbar_Left_Tooltip">
+		attualmente nella barra degli strumenti a sinistra
+	</string>
+	<string name="Toolbar_Right_Tooltip">
+		attualmente nella barra degli strumenti a destra
 	</string>
 	<string name="Retain%">
 		Mantieni%
@@ -4848,4 +4884,19 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 	<string name="Normal">
 		Normale
 	</string>
+	<string name="snapshot_quality_very_low">
+		Molto basso
+	</string>
+	<string name="snapshot_quality_low">
+		Basso
+	</string>
+	<string name="snapshot_quality_medium">
+		Medio
+	</string>
+	<string name="snapshot_quality_high">
+		Alto
+	</string>
+	<string name="snapshot_quality_very_high">
+		Molto alto
+	</string>
 </strings>
diff --git a/indra/newview/skins/default/xui/it/teleport_strings.xml b/indra/newview/skins/default/xui/it/teleport_strings.xml
index a0b324d8fb..f485212290 100644
--- a/indra/newview/skins/default/xui/it/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/it/teleport_strings.xml
@@ -19,8 +19,8 @@ Se si continua a visualizzare questo messaggio, consulta la pagina [SUPPORT_SITE
 			Spiacenti, il sistema non riesce a completare il teletrasporto. Riprova tra un attimo.
 		</message>
 		<message name="NoHelpIslandTP">
-		Non è possibile per te ritornare all&apos;Welcome Island.
-Vai alla &apos;Welcome Island Public&apos; per ripetere il tutorial.
+			Non puoi teleportarti nuovamente a Welcome Island.
+Per ripetere l&apos;esercitazione, visita &apos;Welcome Island Public&apos;.
 		</message>
 		<message name="noaccess_tport">
 			Spiacenti, ma non hai accesso nel luogo di destinazione richiesto.
diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml
index c628ade43e..3c7a210a22 100644
--- a/indra/newview/skins/default/xui/ja/floater_about.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about.xml
@@ -90,6 +90,8 @@ google-perftools Copyright (c) 2005, Google Inc.
 
 Second Life ビューワでは Havok (TM) Physics が使用されています。(c)Copyright 1999-2010 Havok.com Inc. (and its Licensors).無断複写・複製・転載を禁じます。詳細については www.havok.com をご参照ください。
 
+このソフトウェアには、NVIDIA Corporation によるソースコードが含まれます。
+
 無断複写・複製・転載を禁じます。詳細については licenses.txt をご参照ください。
 
 ボイスチャットのオーディオコーディング:Polycom(R) Siren14(TM) (ITU-T Rec.G.722.1 Annex C)
diff --git a/indra/newview/skins/default/xui/ja/floater_about_land.xml b/indra/newview/skins/default/xui/ja/floater_about_land.xml
index 3c88c902f8..816a6ff203 100644
--- a/indra/newview/skins/default/xui/ja/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about_land.xml
@@ -130,7 +130,7 @@
 				交通量:
 			</text>
 			<text name="DwellText">
-				誤
+				ローディング...
 			</text>
 			<button label="土地の購入" label_selected="土地を購入..." left="130" name="Buy Land..." width="100"/>
 			<button label="リンデンセール" label_selected="Linden セール..." name="Linden Sale..." tool_tip="土地が所有されており、コンテンツが設定されている必要があります。オークションの対象になっていないことも必要条件です。"/>
@@ -311,13 +311,15 @@
 				プッシュ禁止 (地域設定優先)
 			</panel.string>
 			<panel.string name="see_avs_text">
-				この区画にいる住人と会ってチャットする
+				他の区画にいるアバターは、
 			</panel.string>
 			<text name="allow_label">
 				他の住人への許可:
 			</text>
-			<check_box label="地形を編集" name="edit land check" tool_tip="チェックを入れると、他人があなたの土地の地形編集を行うことが可能となります。このオプションのチェックを外しておくことをおすすめします。外した状態であなたの土地の地形編集が可能です。"/>
-			<check_box label="飛行" name="check fly" tool_tip="チェックを入れるとこの土地での飛行が可能となります。チェックを外すと土地に入る際と通り過ぎるときのみ飛行可能となります。"/>
+			<text name="allow_label0">
+				飛行:
+			</text>
+			<check_box label="全員" name="check fly" tool_tip="チェックを入れるとこの土地での飛行が可能となります。チェックを外すと土地に入る際と通り過ぎるときのみ飛行可能となります。"/>
 			<text name="allow_label2">
 				制作:
 			</text>
@@ -333,9 +335,6 @@
 			</text>
 			<check_box label="全員" name="check other scripts"/>
 			<check_box label="グループ" name="check group scripts"/>
-			<text name="land_options_label">
-				土地オプション:
-			</text>
 			<check_box label="安全(ダメージなし)" name="check safe" tool_tip="チェックを入れるとこの土地でのダメージコンバットが無効になり、「安全」に設定されます。 チェックを外すとダメージコンバットが有効になります。"/>
 			<check_box label="プッシュ禁止" name="PushRestrictCheck" tool_tip="スクリプトによるプッシュを禁止します。 このオプションを選択することにより、あなたの土地での破壊的行動を防ぐことができます。"/>
 			<check_box label="検索に区画を表示(週 L$ 30)" name="ShowDirectoryCheck" tool_tip="この区画を検索結果に表示します"/>
@@ -376,9 +375,9 @@
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="写真をクリックして選択"/>
 			<text name="allow_label5">
-				他の区画にいる住人への許可:
+				この区画にいるアバターに会ってチャットできます
 			</text>
-			<check_box label="アバターを表示" name="SeeAvatarsCheck" tool_tip="他の区画の住人が、この区画にいる住人に会ってチャットすることを許可し、あなたもそれら住人に会ってチャットできるようにします。"/>
+			<check_box label="アバターを表示" name="SeeAvatarsCheck" tool_tip="他の区画のアバターが、この区画にいるアバターに会ってチャットすることを許可し、あなたもそれらアバターに会ってチャットできるようにします。"/>
 			<text name="landing_point">
 				着地点: [LANDING]
 			</text>
diff --git a/indra/newview/skins/default/xui/ja/floater_avatar.xml b/indra/newview/skins/default/xui/ja/floater_avatar.xml
index c4455282d2..d289580506 100644
--- a/indra/newview/skins/default/xui/ja/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/ja/floater_avatar.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Avatar" title="アバターピッカー"/>
+<floater name="Avatar" title="アバターを選択"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
index e447eefe0e..a472f163e3 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php?lang=ja-JP 支払方法] | [http://www.secondlife.com/my/account/currency.php?lang=ja-JP 通貨]
+		[http://www.secondlife.com/my/account/payment_method_management.php 支払方法] | [http://www.secondlife.com/my/account/currency.php 通貨]
 	</text>
 	<text name="exchange_rate_note">
 		金額を再入力して最新換算レートを確認します。
diff --git a/indra/newview/skins/default/xui/ja/floater_camera.xml b/indra/newview/skins/default/xui/ja/floater_camera.xml
index 0661e17309..982e5ce42b 100644
--- a/indra/newview/skins/default/xui/ja/floater_camera.xml
+++ b/indra/newview/skins/default/xui/ja/floater_camera.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="camera_floater" title="表示">
+<floater name="camera_floater" title="カメラのコントロール">
 	<floater.string name="rotate_tooltip">
 		フォーカスを中心にカメラを回転
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml b/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml
index ffafbaf3b6..1b6558a9eb 100644
--- a/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml
@@ -4,8 +4,8 @@
 		フィルタリング:
 	</text>
 	<check_box label="異方的フィルタリング(有効にすると速度が低下します)" name="ani"/>
-	<text name="Antialiasing:">
-		アンチエイリアシング:
+	<text name="antialiasing label">
+		アンチエイリアシング:
 	</text>
 	<combo_box label="アンチエイリアシング" name="fsaa">
 		<combo_box.item label="無効" name="FSAADisabled"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_model_preview.xml b/indra/newview/skins/default/xui/ja/floater_model_preview.xml
index 157c68a570..c9ff0e29cb 100644
--- a/indra/newview/skins/default/xui/ja/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/ja/floater_model_preview.xml
@@ -4,6 +4,9 @@
 	<string name="status_parse_error">
 		エラー:Dae に問題が見つかりました - 詳細についてはログをご参照ください。
 	</string>
+	<string name="status_material_mismatch">
+		エラー:モデルの材料は参考モデルのサブセットではありません。
+	</string>
 	<string name="status_reading_file">
 		ローディング...
 	</string>
diff --git a/indra/newview/skins/default/xui/ja/floater_model_wizard.xml b/indra/newview/skins/default/xui/ja/floater_model_wizard.xml
index 915b37557f..6aaa9a42a5 100644
--- a/indra/newview/skins/default/xui/ja/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/ja/floater_model_wizard.xml
@@ -20,6 +20,9 @@
 				アップロードするモデルファイルの選択
 			</text>
 			<button label="参照" label_selected="参照" name="browse"/>
+			<text name="Model types">
+				Second Life は COLLADA (.dae) ファイルをサポートします。
+			</text>
 			<text name="dimensions">
 				X         Y         Z
 			</text>
diff --git a/indra/newview/skins/default/xui/ja/floater_moveview.xml b/indra/newview/skins/default/xui/ja/floater_moveview.xml
index 88c1905b8a..aed3b78a14 100644
--- a/indra/newview/skins/default/xui/ja/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/ja/floater_moveview.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move_floater" title="移動">
+<floater name="move_floater" title="歩行 / 走行 / 飛行">
 	<string name="walk_forward_tooltip">
 		前に進む(上矢印か W を押す)
 	</string>
diff --git a/indra/newview/skins/default/xui/ja/floater_snapshot.xml b/indra/newview/skins/default/xui/ja/floater_snapshot.xml
index 05a10f9f6d..cf4732a68e 100644
--- a/indra/newview/skins/default/xui/ja/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/ja/floater_snapshot.xml
@@ -3,73 +3,63 @@
 	<floater.string name="unknown">
 		不明
 	</floater.string>
-	<radio_group label="スナップショットの種類" name="snapshot_type_radio">
-		<radio_item label="メール" name="postcard"/>
-		<radio_item label="持ち物(L$[AMOUNT])" name="texture"/>
-		<radio_item label="コンピューターに保存" name="local"/>
-	</radio_group>
+	<string name="postcard_progress_str">
+		メールの送信
+	</string>
+	<string name="profile_progress_str">
+		投稿
+	</string>
+	<string name="inventory_progress_str">
+		持ち物に保存
+	</string>
+	<string name="local_progress_str">
+		コンピュータに保存
+	</string>
+	<string name="profile_succeeded_str">
+		画像がアップロードされました
+	</string>
+	<string name="postcard_succeeded_str">
+		メールが送信されました
+	</string>
+	<string name="inventory_succeeded_str">
+		持ち物に保存されました
+	</string>
+	<string name="local_succeeded_str">
+		コンピュータに保存されました
+	</string>
+	<string name="profile_failed_str">
+		プロフィールフィードに画像をアップロードできませんでした。
+	</string>
+	<string name="postcard_failed_str">
+		メールを送信できませんでした。
+	</string>
+	<string name="inventory_failed_str">
+		持ち物に保存できませんでした。
+	</string>
+	<string name="local_failed_str">
+		コンピュータに保存できませんでした。
+	</string>
+	<button name="advanced_options_btn" tool_tip="詳しい設定"/>
+	<text name="image_res_text">
+		[WIDTH] x [HEIGHT] px
+	</text>
 	<text name="file_size_label">
 		[SIZE] キロバイト
 	</text>
-	<button label="スナップショットを更新" name="new_snapshot_btn"/>
-	<button label="送信" name="send_btn"/>
-	<button label="保存(L$[AMOUNT])" name="upload_btn"/>
-	<flyout_button label="保存" name="save_btn" tool_tip="画像をファイルに保存">
-		<flyout_button.item label="保存" name="save_item"/>
-		<flyout_button.item label="別名で保存..." name="saveas_item"/>
-	</flyout_button>
-	<button label="詳細" name="more_btn" tool_tip="詳しい設定"/>
-	<button label="簡易" name="less_btn" tool_tip="詳しい設定"/>
-	<button label="取り消し" name="discard_btn"/>
-	<text name="type_label2">
-		サイズ
-	</text>
-	<text name="format_label">
-		書式
-	</text>
-	<combo_box label="解像度" name="postcard_size_combo">
-		<combo_box.item label="現在のウィンドウ" name="CurrentWindow"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="カスタム" name="Custom"/>
-	</combo_box>
-	<combo_box label="解像度" name="texture_size_combo">
-		<combo_box.item label="現在のウィンドウ" name="CurrentWindow"/>
-		<combo_box.item label="小(128x128)" name="Small(128x128)"/>
-		<combo_box.item label="中(256x256)" name="Medium(256x256)"/>
-		<combo_box.item label="大(512x512)" name="Large(512x512)"/>
-		<combo_box.item label="カスタム" name="Custom"/>
-	</combo_box>
-	<combo_box label="解像度" name="local_size_combo">
-		<combo_box.item label="現在のウィンドウ" name="CurrentWindow"/>
-		<combo_box.item label="320x240" name="320x240"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="1280x1024" name="1280x1024"/>
-		<combo_box.item label="1600x1200" name="1600x1200"/>
-		<combo_box.item label="カスタム" name="Custom"/>
-	</combo_box>
-	<combo_box label="書式" name="local_format_combo">
-		<combo_box.item label="PNG" name="PNG"/>
-		<combo_box.item label="JPEG" name="JPEG"/>
-		<combo_box.item label="BMP" name="BMP"/>
-	</combo_box>
-	<spinner label="幅" name="snapshot_width"/>
-	<spinner label="高さ" name="snapshot_height"/>
-	<check_box label="縦横比の固定" name="keep_aspect_check"/>
-	<slider label="画質" name="image_quality_slider"/>
-	<text name="layer_type_label">
-		キャプチャ:
-	</text>
-	<combo_box label="画像レイヤー" name="layer_types">
-		<combo_box.item label="色" name="Colors"/>
-		<combo_box.item label="深度" name="Depth"/>
-	</combo_box>
-	<check_box label="インターフェース" name="ui_check"/>
-	<check_box label="HUD" name="hud_check"/>
-	<check_box label="保存後もこのまま" name="keep_open_check"/>
-	<check_box label="画面全体を静止" name="freeze_frame_check"/>
-	<check_box label="自動更新" name="auto_snapshot_check"/>
+	<panel name="advanced_options_panel">
+		<text name="advanced_options_label">
+			詳しい設定
+		</text>
+		<text name="layer_type_label">
+			キャプチャ:
+		</text>
+		<combo_box label="画像レイヤー" name="layer_types">
+			<combo_box.item label="色" name="Colors"/>
+			<combo_box.item label="深度" name="Depth"/>
+		</combo_box>
+		<check_box label="インターフェース" name="ui_check"/>
+		<check_box label="HUD" name="hud_check"/>
+		<check_box label="画面全体を静止" name="freeze_frame_check"/>
+		<check_box label="自動更新" name="auto_snapshot_check"/>
+	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_toybox.xml b/indra/newview/skins/default/xui/ja/floater_toybox.xml
index d7056f806c..682352ec82 100644
--- a/indra/newview/skins/default/xui/ja/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/ja/floater_toybox.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Toybox" title="ツールバーをカスタマイズ">
+<floater name="Toybox" title="ツールバーのボタン">
 	<text name="toybox label 1">
 		ボタンをツールバーに追加または削除するにはボタンをドラッグします。
 	</text>
 	<text name="toybox label 2">
 		各ツールバーの設定に応じて、ボタンは以下のように表示されたり、アイコンのみで表示されます。
 	</text>
+	<button label="ツールバーを全てクリア" label_selected="ツールバーを全てクリア" name="btn_clear_all"/>
 	<button label="デフォルト設定を復元" label_selected="デフォルト設定を復元" name="btn_restore_defaults"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_translation_settings.xml b/indra/newview/skins/default/xui/ja/floater_translation_settings.xml
new file mode 100644
index 0000000000..27143086ac
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_translation_settings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_translation_settings" title="チャットの翻訳設定">
+	<string name="bing_api_key_not_verified">
+		Bing appID を認証できませんでした。もう一度お試しください。
+	</string>
+	<string name="google_api_key_not_verified">
+		Google API キーを認証できませんでした。もう一度お試しください。
+	</string>
+	<string name="bing_api_key_verified">
+		Bing appID が認証されました。
+	</string>
+	<string name="google_api_key_verified">
+		Google API キーが認証されました。
+	</string>
+	<check_box label="チャット中の機械翻訳機能を有効にする" name="translate_chat_checkbox"/>
+	<text name="translate_language_label">
+		翻訳する言語:
+	</text>
+	<combo_box name="translate_language_combo">
+		<combo_box.item label="システム標準" name="System Default Language"/>
+		<combo_box.item label="英語" name="English"/>
+		<combo_box.item label="Dansk(デンマーク語)" name="Danish"/>
+		<combo_box.item label="Deutsch(ドイツ語)" name="German"/>
+		<combo_box.item label="Español(スペイン語)" name="Spanish"/>
+		<combo_box.item label="Français(フランス語)" name="French"/>
+		<combo_box.item label="Italiano(イタリア語)" name="Italian"/>
+		<combo_box.item label="Magyar(ハンガリー語)" name="Hungarian"/>
+		<combo_box.item label="Nederlands(オランダ語)" name="Dutch"/>
+		<combo_box.item label="Polski(ポーランド語)" name="Polish"/>
+		<combo_box.item label="Português(ポルトガル語)" name="Portugese"/>
+		<combo_box.item label="Русский(ロシア語)" name="Russian"/>
+		<combo_box.item label="Türkçe(トルコ語)" name="Turkish"/>
+		<combo_box.item label="Українська (ウクライナ語)" name="Ukrainian"/>
+		<combo_box.item label="中文 (正體) (中国語)" name="Chinese"/>
+		<combo_box.item label="日本語(日本語)" name="Japanese"/>
+		<combo_box.item label="한국어(韓国語)" name="Korean"/>
+	</combo_box>
+	<text name="tip">
+		翻訳サービスを選択してください:
+	</text>
+	<radio_group name="translation_service_rg">
+		<radio_item initial_value="bing" label="Bing Translator" name="bing"/>
+		<radio_item initial_value="google" label="Google Translate" name="google"/>
+	</radio_group>
+	<text name="bing_api_key_label">
+		Bing AppID [http://www.bing.com/developers/createapp.aspx AppID]:
+	</text>
+	<button label="認証" name="verify_bing_api_key_btn"/>
+	<text name="google_api_key_label">
+		Google API key [http://code.google.com/apis/language/translate/v2/getting_started.html#auth API key]:
+	</text>
+	<button label="認証" name="verify_google_api_key_btn"/>
+	<text name="google_links_text">
+		[http://code.google.com/apis/language/translate/v2/pricing.html 価格] | [https://code.google.com/apis/console 統計]
+	</text>
+	<button label="OK" name="ok_btn"/>
+	<button label="取り消し" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_voice_controls.xml b/indra/newview/skins/default/xui/ja/floater_voice_controls.xml
index f12648f208..f7d3fd11e0 100644
--- a/indra/newview/skins/default/xui/ja/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/ja/floater_voice_controls.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="floater_voice_controls" title="ボイスコントロール">
 	<string name="title_nearby">
-		近くのボイス
+		ボイス設定
 	</string>
 	<string name="title_group">
 		[GROUP] とグループコール
@@ -10,7 +10,7 @@
 		コンファレンスコール
 	</string>
 	<string name="title_peer_2_peer">
-		[NAME] でコール
+		[NAME] とコール
 	</string>
 	<string name="no_one_near">
 		近くにボイスを有効にしている人はいません。
diff --git a/indra/newview/skins/default/xui/ja/menu_toolbars.xml b/indra/newview/skins/default/xui/ja/menu_toolbars.xml
index e911ca4a13..d5363a5131 100644
--- a/indra/newview/skins/default/xui/ja/menu_toolbars.xml
+++ b/indra/newview/skins/default/xui/ja/menu_toolbars.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <context_menu name="Toolbars Popup">
-	<menu_item_call label="ボタンを選択..." name="Chose Buttons"/>
+	<menu_item_call label="このボタンを削除" name="Remove button"/>
+	<menu_item_call label="ツールバーのボタン..." name="Choose Buttons"/>
 	<menu_item_check label="アイコンとラベル" name="icons_with_text"/>
 	<menu_item_check label="アイコンのみ" name="icons_only"/>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml
index 125e9bb226..ef3261f1d4 100644
--- a/indra/newview/skins/default/xui/ja/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <menu_bar name="Main Menu">
 	<menu label="ミー" name="Me">
-		<menu_item_call label="マイアカウント..." name="Manage My Account">
-			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=ja"/>
-		</menu_item_call>
 		<menu_item_call label="プロフィール..." name="Profile"/>
 		<menu_item_call label="容姿..." name="ChangeOutfit"/>
+		<menu_item_call label="アバターを選択..." name="Avatar Picker"/>
 		<menu_item_check label="持ち物..." name="Inventory"/>
-		<menu_item_check label="ジェスチャー..." name="Gestures"/>
-		<menu_item_check label="ボイス..." name="ShowVoice"/>
+		<menu_item_call label="新しい持ち物ウィンドウ" name="NewInventoryWindow"/>
+		<menu_item_call label="場所..." name="Places"/>
+		<menu_item_call label="ピック..." name="Picks"/>
+		<menu_item_call label="カメラコントロール..." name="Camera Controls"/>
 		<menu label="ムーブメント" name="Movement">
 			<menu_item_call label="座る" name="Sit Down Here"/>
 			<menu_item_check label="飛ぶ" name="Fly"/>
@@ -22,34 +22,39 @@
 		<menu_item_call label="管理者権限のリクエスト" name="Request Admin Options"/>
 		<menu_item_call label="管理者ステータス解除" name="Leave Admin Options"/>
 		<menu_item_call label="L$ の購入" name="Buy and Sell L$"/>
+		<menu_item_call label="マイアカウント..." name="Manage My Account">
+			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=ja"/>
+		</menu_item_call>
 		<menu_item_call label="環境設定..." name="Preferences"/>
-		<menu_item_call label="ツールバー..." name="Toolbars"/>
+		<menu_item_call label="ツールバーのボタン..." name="Toolbars"/>
 		<menu_item_call label="全てのコントロールを非表示にする" name="Hide UI"/>
 		<menu_item_call label="[APP_NAME] を終了" name="Quit"/>
 	</menu>
 	<menu label="コミュニケーション" name="Communicate">
+		<menu_item_check label="チャット..." name="Nearby Chat"/>
+		<menu_item_check label="話す" name="Speak"/>
+		<menu_item_check label="ボイス設定..." name="Nearby Voice"/>
+		<menu_item_check label="ボイスモーフィング..." name="ShowVoice"/>
+		<menu_item_check label="ジェスチャー..." name="Gestures"/>
 		<menu_item_call label="フレンド" name="My Friends"/>
-		<menu_item_call label="所属グループ" name="My Groups"/>
-		<menu_item_check label="近くのチャット" name="Nearby Chat"/>
+		<menu_item_call label="グループ" name="My Groups"/>
 		<menu_item_call label="近くにいる人" name="Active Speakers"/>
-		<menu_item_check label="近くのボイス" name="Nearby Voice"/>
 	</menu>
 	<menu label="世界" name="World">
-		<menu_item_check label="ミニマップ" name="Mini-Map"/>
+		<menu_item_call label="現在地をランドマーク" name="Create Landmark Here"/>
+		<menu_item_call label="行き先..." name="Destinations"/>
 		<menu_item_check label="世界地図" name="World Map"/>
+		<menu_item_check label="ミニマップ" name="Mini-Map"/>
 		<menu_item_check label="検索" name="Search"/>
+		<menu_item_call label="ホームにテレポート" name="Teleport Home"/>
+		<menu_item_call label="現在地をホームに設定" name="Set Home to Here"/>
 		<menu_item_call label="スナップショット" name="Take Snapshot"/>
-		<menu_item_call label="現在地をランドマーク" name="Create Landmark Here"/>
-		<menu label="場所のプロフィール" name="Land">
-			<menu_item_call label="場所のプロフィール" name="Place Profile"/>
-			<menu_item_call label="土地情報" name="About Land"/>
-			<menu_item_call label="地域 / 不動産" name="Region/Estate"/>
-		</menu>
+		<menu_item_call label="場所のプロフィール" name="Place Profile"/>
+		<menu_item_call label="土地情報" name="About Land"/>
+		<menu_item_call label="地域 / 不動産" name="Region/Estate"/>
+		<menu_item_call label="保有地..." name="My Land"/>
 		<menu_item_call label="この土地を購入" name="Buy Land"/>
-		<menu_item_call label="自分の土地" name="My Land"/>
 		<menu label="表示" name="LandShow">
-			<menu_item_check label="移動コントロール" name="Movement Controls"/>
-			<menu_item_check label="カメラコントロール" name="Camera Controls"/>
 			<menu_item_check label="立入禁止ライン" name="Ban Lines"/>
 			<menu_item_check label="ビーコン(標識)" name="beacons"/>
 			<menu_item_check label="プロパティ境界線" name="Property Lines"/>
@@ -58,16 +63,15 @@
 			<menu_item_check label="区画プロパティ" name="Parcel Properties"/>
 			<menu_item_check label="アドバンスメニュー" name="Show Advanced Menu"/>
 		</menu>
-		<menu_item_call label="ホームにテレポート" name="Teleport Home"/>
-		<menu_item_call label="現在地をホームに設定" name="Set Home to Here"/>
 		<menu label="太陽" name="Environment Settings">
 			<menu_item_call label="日の出" name="Sunrise"/>
 			<menu_item_call label="正午" name="Noon"/>
 			<menu_item_call label="日没" name="Sunset"/>
 			<menu_item_call label="深夜" name="Midnight"/>
+			<menu_item_call label="リージョンの設定を使用" name="Use Region Settings"/>
 		</menu>
-		<menu label="自然環境エディター" name="Enviroment Editor">
-			<menu_item_call label="環境の設定..." name="Enviroment Settings"/>
+		<menu label="自然環境エディター" name="Environment Editor">
+			<menu_item_call label="自然環境の設定..." name="Environment Settings"/>
 			<menu label="水の事前設定" name="Water Presets">
 				<menu_item_call label="新しい事前設定..." name="new_water_preset"/>
 				<menu_item_call label="事前設定を編集..." name="edit_water_preset"/>
@@ -146,6 +150,7 @@
 		<menu_item_call label="やり直し" name="Redo"/>
 	</menu>
 	<menu label="ヘルプ" name="Help">
+		<menu_item_call label="ハウツー..." name="How To"/>
 		<menu_item_call label="[SECOND_LIFE] ヘルプ" name="Second Life Help"/>
 		<menu_item_call label="嫌がらせを報告する" name="Report Abuse"/>
 		<menu_item_call label="バグを報告する" name="Report Bug"/>
@@ -200,11 +205,10 @@
 		<menu_item_check label="Use Plugin Read Thread" name="Use Plugin Read Thread"/>
 		<menu_item_call label="グループキャッシュのクリア" name="ClearGroupCache"/>
 		<menu_item_check label="マウスの平滑化" name="Mouse Smoothing"/>
+		<menu_item_call label="リリースキー" name="Release Keys"/>
 		<menu label="ショートカット" name="Shortcuts">
 			<menu_item_call label="画像 (L$ [COST] )..." name="Upload Image"/>
 			<menu_item_check label="検索" name="Search"/>
-			<menu_item_call label="キーをリリース" name="Release Keys"/>
-			<menu_item_call label="UI のサイズをデフォルトに設定する" name="Set UI Size to Default"/>
 			<menu_item_check label="アドバンスメニューを表示 - レガシーのショートカット" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="ウィンドウを閉じる" name="Close Window"/>
 			<menu_item_call label="全てのウィンドウを閉じる" name="Close All Windows"/>
@@ -290,6 +294,7 @@
 			<menu_item_check label="光" name="Lights"/>
 			<menu_item_check label="骨組みの衝突判定" name="Collision Skeleton"/>
 			<menu_item_check label="レイキャスト" name="Raycast"/>
+			<menu_item_check label="風のベクトル" name="Wind Vectors"/>
 			<menu_item_check label="描画の詳細度" name="rendercomplexity"/>
 			<menu_item_check label="スカルプト" name="Sculpt"/>
 		</menu>
@@ -302,7 +307,6 @@
 			<menu_item_check label="光と影" name="Lighting and Shadows"/>
 			<menu_item_check label="太陽・月・プロジェクタからの影" name="Shadows from Sun/Moon/Projectors"/>
 			<menu_item_check label="SSAO と影の平滑化" name="SSAO and Shadow Smoothing"/>
-			<menu_item_check label="グローバルイルミネーション(試験段階)" name="Global Illumination"/>
 			<menu_item_check label="GL デバッグ" name="Debug GL"/>
 			<menu_item_check label="経路をデバッグ" name="Debug Pipeline"/>
 			<menu_item_check label="自動アルファマスク(遅延)" name="Automatic Alpha Masks (deferred)"/>
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index 141f2c8071..20468c8c2a 100644
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -1144,8 +1144,13 @@ L$ は返金されません。
 		-safe オプションを指定したので、
 表示設定はセーフレベルに設定されています。
 	</notification>
-	<notification name="DisplaySetToRecommended">
-		表示設定は、あなたのシステム構成に基づいて推奨されたレベルに設定されています。
+	<notification name="DisplaySetToRecommendedGPUChange">
+		グラフィックの変更により、画面設定は推奨レベルに設定されました。
+&apos;[LAST_GPU]&apos; から
+&apos;[THIS_GPU]&apos; まで
+	</notification>
+	<notification name="DisplaySetToRecommendedFeatureChange">
+		レンダリングサブシステムの変更により、画面設定は推奨レベルに設定されました。
 	</notification>
 	<notification name="ErrorMessage">
 		[ERROR_MESSAGE]
@@ -1954,7 +1959,13 @@ Adult 専用リージョンに入るには、住人のアカウントが年齢
 		<usetemplate ignoretext="終了時の確認" name="okcancelignore" notext="終了しない" yestext="終了"/>
 	</notification>
 	<notification name="ConfirmRestoreToybox">
-		デフォルトのボタンとツールバーを復元しますか? 
+		この操作を実行すると、デフォルト設定のボタンとツールバーが復元されます。
+
+この操作は元に戻せません。
+		<usetemplate name="okcancelbuttons" notext="取り消し" yestext="OK"/>
+	</notification>
+	<notification name="ConfirmClearAllToybox">
+		この操作により、全てのボタンはツールボックスに戻り、ツールバーは空になります。
     
 この操作は元に戻せません。
 		<usetemplate name="okcancelbuttons" notext="取り消し" yestext="OK"/>
@@ -2167,10 +2178,10 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 		件名: [SUBJECT]、メッセージ: [MESSAGE]
 	</notification>
 	<notification name="FriendOnline">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; はオンライン中です
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; はオンラインです
 	</notification>
 	<notification name="FriendOffline">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; はオフライン中です
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; はオフラインです
 	</notification>
 	<notification name="AddSelfFriend">
 		残念ながら自分自身をフレンド登録することはできません。
@@ -2284,13 +2295,15 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 		コーリングカードが拒否されました。
 	</notification>
 	<notification name="TeleportToLandmark">
-		画面右の「場所」パネルを開いて、「ランドマーク」タブを選ぶと、[NAME] といった場所にテレポートできます。 
-好きなランドマークをクリックして選び、次にパネル下の「テレポート」をクリックします。
-(ランドマークをダブルクリック、または右クリックして「テレポート」を選んでも同じです。)
+		[NAME] などの場所にテレポートするには、「場所」ボタンをクリックしてから、
+表示されたウィンドウで「ランドマーク」タブを選択します。ランドマークを
+いずれか 1 つ選択してから、ウィンドウ下部にある「テレポート」をクリックします。
+(この操作は、ランドマークをダブルクリックするか、右クリックして
+「テレポート」を選択して実行することもできます。)
 	</notification>
 	<notification name="TeleportToPerson">
-		画面右の「人」パネルを開いて、[NAME] といった住人に連絡を取ることができます。
-リストから住人を選択して、パネル下の「IM」をクリックします。
+		[NAME] のような住人に連絡をとるには、「人」ボタンをクリックし、表示されるウィンドウで「住人」を選択してから、
+ウィンドウ下部にある「IM」をクリックします。
 (リストの名前をダブルクリック、または右クリックして「IM」を選んでも同じです。)
 	</notification>
 	<notification name="CantSelectLandFromMultipleRegions">
@@ -2312,6 +2325,9 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 	<notification name="PaymentSent">
 		[MESSAGE]
 	</notification>
+	<notification name="PaymentFailure">
+		[MESSAGE]
+	</notification>
 	<notification name="EventNotification">
 		イベント通知:
 
@@ -2567,10 +2583,10 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 		</form>
 	</notification>
 	<notification name="FriendshipAccepted">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt;は、フレンド登録を受け入れました。
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; はあなたからの友人登録リクエストを受諾しました。
 	</notification>
 	<notification name="FriendshipDeclined">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt;は、フレンド登録を断りました。
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; はあなたからの友人登録リクエストを拒否しました。
 	</notification>
 	<notification name="FriendshipAcceptedByMe">
 		フレンドの登録依頼が承認されました。
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_skin.xml b/indra/newview/skins/default/xui/ja/panel_edit_skin.xml
index 2c554dad94..7573132576 100644
--- a/indra/newview/skins/default/xui/ja/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/ja/panel_edit_skin.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_skin_panel">
 	<panel name="avatar_skin_color_panel">
-		<texture_picker label="頭部のタトゥー" name="Head Tattoos" tool_tip="クリックして写真を選択"/>
-		<texture_picker label="上部のタトゥー" name="Upper Tattoos" tool_tip="クリックして写真を選択"/>
-		<texture_picker label="下部のタトゥー" name="Lower Tattoos" tool_tip="クリックして写真を選択"/>
+		<texture_picker label="頭" name="Head" tool_tip="クリックして写真を選択します"/>
+		<texture_picker label="上半身" name="Upper Body" tool_tip="クリックして写真を選択します"/>
+		<texture_picker label="下半身" name="Lower Body" tool_tip="クリックして写真を選択します"/>
 	</panel>
 	<panel name="accordion_panel">
 		<accordion name="wearable_accordion">
diff --git a/indra/newview/skins/default/xui/ja/panel_postcard_message.xml b/indra/newview/skins/default/xui/ja/panel_postcard_message.xml
new file mode 100644
index 0000000000..b7c3f48557
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_postcard_message.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_message">
+	<text name="to_label">
+		終:
+	</text>
+	<text name="name_label">
+		始:
+	</text>
+	<text name="subject_label">
+		件名:
+	</text>
+	<line_editor label="件名をここに入力してください。" name="subject_form"/>
+	<text name="msg_label">
+		メッセージ:
+	</text>
+	<text_editor name="msg_form">
+		メッセージをここに入力してください。
+	</text_editor>
+	<button label="取り消し" name="cancel_btn"/>
+	<button label="送信" name="send_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_postcard_settings.xml b/indra/newview/skins/default/xui/ja/panel_postcard_settings.xml
new file mode 100644
index 0000000000..314aaef7fd
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_postcard_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_settings">
+	<combo_box label="解像度" name="postcard_size_combo">
+		<combo_box.item label="現在のウィンドウ" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="カスタム" name="Custom"/>
+	</combo_box>
+	<layout_stack name="postcard_image_params_ls">
+		<layout_panel name="postcard_image_size_lp">
+			<spinner label="幅" name="postcard_snapshot_width"/>
+			<spinner label="高さ" name="postcard_snapshot_height"/>
+			<check_box label="縦横比の固定" name="postcard_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="postcard_image_format_quality_lp">
+			<slider label="画質" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml b/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml
index 1502442a06..75bf28a3c8 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml
@@ -29,30 +29,5 @@
 	<check_box label="IM チャット" name="EnableIMChatPopups" tool_tip="これを選択すると、インスタントメッセージを受信した際にポップアップが表示されます"/>
 	<spinner label="近くのチャットメッセージが表示される長さ:" name="nearby_toasts_lifetime"/>
 	<spinner label="近くのチャットメッセージが消えるまでの長さ:" name="nearby_toasts_fadingtime"/>
-	<check_box label="Use machine translation while chatting" name="translate_chat_checkbox"/>
-	<text name="translate_chb_label">
-		チャット中に内容を機械翻訳する
-	</text>
-	<text name="translate_language_text">
-		翻訳する言語:
-	</text>
-	<combo_box name="translate_language_combobox">
-		<combo_box.item label="システム標準" name="System Default Language"/>
-		<combo_box.item label="English(英語)" name="English"/>
-		<combo_box.item label="Dansk(デンマーク語)" name="Danish"/>
-		<combo_box.item label="Deutsch(ドイツ語)" name="German"/>
-		<combo_box.item label="Español(スペイン語)" name="Spanish"/>
-		<combo_box.item label="Français(フランス語)" name="French"/>
-		<combo_box.item label="Italiano(イタリア語)" name="Italian"/>
-		<combo_box.item label="Magyar(ハンガリー語)" name="Hungarian"/>
-		<combo_box.item label="Nederlands(オランダ語)" name="Dutch"/>
-		<combo_box.item label="Polski(ポーランド語)" name="Polish"/>
-		<combo_box.item label="Português(ポルトガル語)" name="Portugese"/>
-		<combo_box.item label="Русский(ロシア語)" name="Russian"/>
-		<combo_box.item label="Türkçe(トルコ語)" name="Turkish"/>
-		<combo_box.item label="Українська(ウクライナ語)" name="Ukrainian"/>
-		<combo_box.item label="中文 (正體) (Chinese)" name="Chinese"/>
-		<combo_box.item label="日本語" name="Japanese"/>
-		<combo_box.item label="한국어(韓国語)" name="Korean"/>
-	</combo_box>
+	<button label="チャットの翻訳設定" name="ok_btn"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_general.xml b/indra/newview/skins/default/xui/ja/panel_preferences_general.xml
index 1bafa52fbe..91e1514e49 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_general.xml
@@ -16,7 +16,7 @@
 		<combo_box.item label="Русский (ロシア語) - ベータ" name="Russian"/>
 		<combo_box.item label="Türkçe (トルコ語) - ベータ" name="Turkish"/>
 		<combo_box.item label="日本語 – ベータ" name="(Japanese)"/>
-		<combo_box.item label="正體中文 (中国語 - 繁体字) - ベータ" name="Traditional Chinese"/>
+		<combo_box.item label="正體中文(簡体字中国語)- ベータ版" name="Traditional Chinese"/>
 	</combo_box>
 	<text name="language_textbox2">
 		(再起動後に反映)
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_setup.xml b/indra/newview/skins/default/xui/ja/panel_preferences_setup.xml
index 7877c0495f..d90a1632ab 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_setup.xml
@@ -15,7 +15,7 @@
 		Web:
 	</text>
 	<radio_group name="use_external_browser">
-		<radio_item label="指定のブラウザ(IE や Firefox)を使用" name="external" tool_tip="デフォルトのシステム Web ブラウザでヘルプや Web リンク先などを見ます。全画面で起動中にはおすすめしません。" value="1"/>
+		<radio_item label="指定のブラウザ(IE や Firefox)を使用" name="external" tool_tip="デフォルトのシステム Web ブラウザでヘルプや Web リンク先などを見ます。全画面で起動中にはおすすめしません。" value="true"/>
 		<radio_item label="内蔵ブラウザを使用" name="internal" tool_tip="内蔵ブラウザでヘルプや Web リンクなどを見ます。[APP_NAME] 内に新しいウィンドウでこのブラウザが開きます。" value=""/>
 	</radio_group>
 	<check_box initial_value="true" label="プラグインを有効にする" name="browser_plugins_enabled"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml
new file mode 100644
index 0000000000..46f2b0a3f9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_inventory">
+	<text name="title">
+		「持ち物」に保存
+	</text>
+	<text name="hint_lbl">
+		画像を持ち物に保存するには L$[UPLOAD_COST] の費用がかかります。画像をテクスチャとして保存するには平方形式の 1 つを選択してください。
+	</text>
+	<combo_box label="解像度" name="texture_size_combo">
+		<combo_box.item label="現在のウィンドウ" name="CurrentWindow"/>
+		<combo_box.item label="小(128x128)" name="Small(128x128)"/>
+		<combo_box.item label="中(256x256)" name="Medium(256x256)"/>
+		<combo_box.item label="大(512x512)" name="Large(512x512)"/>
+		<combo_box.item label="カスタム" name="Custom"/>
+	</combo_box>
+	<spinner label="幅" name="inventory_snapshot_width"/>
+	<spinner label="高さ" name="inventory_snapshot_height"/>
+	<check_box label="縦横比の固定" name="inventory_keep_aspect_check"/>
+	<button label="取り消し" name="cancel_btn"/>
+	<button label="保存" name="save_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_local.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_local.xml
new file mode 100644
index 0000000000..cb658fb6c9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_snapshot_local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_local">
+	<text name="title">
+		コンピューターに保存
+	</text>
+	<combo_box label="解像度" name="local_size_combo">
+		<combo_box.item label="現在のウィンドウ" name="CurrentWindow"/>
+		<combo_box.item label="320x240" name="320x240"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="1280x1024" name="1280x1024"/>
+		<combo_box.item label="1600x1200" name="1600x1200"/>
+		<combo_box.item label="カスタム" name="Custom"/>
+	</combo_box>
+	<layout_stack name="local_image_params_ls">
+		<layout_panel name="local_image_size_lp">
+			<spinner label="幅" name="local_snapshot_width"/>
+			<spinner label="高さ" name="local_snapshot_height"/>
+			<check_box label="縦横比の固定" name="local_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="local_image_format_quality_lp">
+			<combo_box label="書式" name="local_format_combo">
+				<combo_box.item label="PNG(可逆圧縮)" name="PNG"/>
+				<combo_box.item label="JPEG" name="JPEG"/>
+				<combo_box.item label="BMP(可逆圧縮)" name="BMP"/>
+			</combo_box>
+			<slider label="画質" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+	<button label="取り消し" name="cancel_btn"/>
+	<flyout_button label="保存" name="save_btn" tool_tip="画像をファイルに保存">
+		<flyout_button.item label="保存" name="save_item"/>
+		<flyout_button.item label="別名で保存..." name="saveas_item"/>
+	</flyout_button>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml
new file mode 100644
index 0000000000..cd5b7590ad
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_options">
+	<button label="プロフィールフィードに投稿する" name="save_to_profile_btn"/>
+	<button label="メール" name="save_to_email_btn"/>
+	<button label="持ち物に保存(L$[Amount])" name="save_to_inventory_btn"/>
+	<button label="コンピューターに保存" name="save_to_computer_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml
new file mode 100644
index 0000000000..1ddd723840
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+	<string name="default_subject">
+		[SECOND_LIFE] からのポストカードです。
+	</string>
+	<string name="default_message">
+		ぜひご覧ください!
+	</string>
+	<string name="upload_message">
+		送信中...
+	</string>
+	<text name="title">
+		メール
+	</text>
+	<button label="メッセージ" name="message_btn"/>
+	<button label="設定" name="settings_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_profile.xml
new file mode 100644
index 0000000000..b860a6afe9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_snapshot_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_profile">
+	<text name="title">
+		プロフィールフィードに投稿する
+	</text>
+	<combo_box label="解像度" name="profile_size_combo">
+		<combo_box.item label="現在のウィンドウ" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="カスタム" name="Custom"/>
+	</combo_box>
+	<layout_stack name="profile_image_params_ls">
+		<layout_panel name="profile_image_size_lp">
+			<spinner label="幅" name="profile_snapshot_width"/>
+			<spinner label="高さ" name="profile_snapshot_height"/>
+			<check_box label="縦横比の固定" name="profile_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="profile_image_metadata_lp">
+			<text name="caption_label">
+				キャプション:
+			</text>
+			<check_box initial_value="true" label="場所を含む" name="add_location_cb"/>
+		</layout_panel>
+	</layout_stack>
+	<button label="取り消し" name="cancel_btn"/>
+	<button label="投稿" name="post_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index f611b96502..c6b033ed95 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -1214,7 +1214,7 @@ support@secondlife.com にお問い合わせください。
 		「持ち物」内にこのテクスチャのコピーがありません
 	</string>
 	<string name="InventoryInboxNoItems">
-		マーケットプレイスで購入した商品はここに配達されます。
+		購入するなどして取得したアイテムや商品はここに表示され、持ち物のフォルダにドラッグして移動することもできれば、要らなくなった場合には削除することができます。
 	</string>
 	<string name="MarketplaceURL">
 		http://marketplace.[DOMAIN_NAME]
@@ -1412,6 +1412,9 @@ support@secondlife.com にお問い合わせください。
 	<string name="no_attachments">
 		着用しているアタッチメントはありません
 	</string>
+	<string name="Attachments remain">
+		アタッチメント(残りのスロット数:[COUNT])
+	</string>
 	<string name="Buy">
 		買う
 	</string>
@@ -1538,6 +1541,12 @@ support@secondlife.com にお問い合わせください。
 	<string name="Right Pec">
 		右胸筋
 	</string>
+	<string name="Neck">
+		首
+	</string>
+	<string name="Avatar Center">
+		アバターの中央
+	</string>
 	<string name="Invalid Attachment">
 		装着先が正しくありません
 	</string>
@@ -4030,6 +4039,18 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="you_paid_ldollars_no_name">
 		L$ [AMOUNT] を支払いました:[REASON]
 	</string>
+	<string name="you_paid_failure_ldollars">
+		[NAME] に [REASON] の代金 L$ [AMOUNT] を支払えませんでした。
+	</string>
+	<string name="you_paid_failure_ldollars_no_info">
+		L$ [AMOUNT] を支払えませんでした。
+	</string>
+	<string name="you_paid_failure_ldollars_no_reason">
+		[NAME] に L$ [AMOUNT] を支払えませんでした。
+	</string>
+	<string name="you_paid_failure_ldollars_no_name">
+		[REASON] の 代金 L$ [AMOUNT] を支払えませんでした。
+	</string>
 	<string name="for item">
 		[ITEM] 向け
 	</string>
@@ -4440,6 +4461,12 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="ExternalEditorFailedToRun">
 		外部エディターを実行できませんでした。
 	</string>
+	<string name="TranslationFailed">
+		翻訳できませんでした:[REASON]
+	</string>
+	<string name="TranslationResponseParseError">
+		翻訳の応答にエラーが発生しました。
+	</string>
 	<string name="Esc">
 		Esc
 	</string>
@@ -4810,7 +4837,7 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 		ミニマップ
 	</string>
 	<string name="Command_Move_Label">
-		移動
+		歩行 / 走行 / 飛行
 	</string>
 	<string name="Command_People_Label">
 		人
@@ -4837,10 +4864,10 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 		話す
 	</string>
 	<string name="Command_View_Label">
-		視界
+		カメラコントロール
 	</string>
 	<string name="Command_Voice_Label">
-		近くのボイス
+		ボイス設定
 	</string>
 	<string name="Command_AboutLand_Tooltip">
 		訪問先に関する情報
@@ -4912,7 +4939,16 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 		カメラの角度を変更
 	</string>
 	<string name="Command_Voice_Tooltip">
-		ボイスチャット機能を持つ近くの人
+		インワールドでのコールや近くにいる人の音量調整
+	</string>
+	<string name="Toolbar_Bottom_Tooltip">
+		現在、下のツールバーにあります
+	</string>
+	<string name="Toolbar_Left_Tooltip">
+		現在、左のツールバーにあります
+	</string>
+	<string name="Toolbar_Right_Tooltip">
+		現在、右のツールバーにあります
 	</string>
 	<string name="Retain%">
 		維持率
@@ -4938,4 +4974,19 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="Normal">
 		普通
 	</string>
+	<string name="snapshot_quality_very_low">
+		非常に低い
+	</string>
+	<string name="snapshot_quality_low">
+		低
+	</string>
+	<string name="snapshot_quality_medium">
+		中
+	</string>
+	<string name="snapshot_quality_high">
+		高
+	</string>
+	<string name="snapshot_quality_very_high">
+		非常に高い
+	</string>
 </strings>
diff --git a/indra/newview/skins/default/xui/ja/teleport_strings.xml b/indra/newview/skins/default/xui/ja/teleport_strings.xml
index 04ea1c2438..6c69c7a231 100644
--- a/indra/newview/skins/default/xui/ja/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/ja/teleport_strings.xml
@@ -21,8 +21,8 @@
 もう少し後でやり直してください。
 		</message>
 		<message name="NoHelpIslandTP">
-		Welcome Islandには戻ることができません。
-「Welcome Island Public」に行き、
+			ウェルカムアイランドにテレポートで戻ることはできません。
+「Welcome Island Public」に行き再度チュートリアルを行ってください。
 		</message>
 		<message name="noaccess_tport">
 			残念ながら、そのテレポート目的地へのアクセスがありません。
diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml
index c374264c4a..e843e56090 100644
--- a/indra/newview/skins/default/xui/pt/floater_about.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about.xml
@@ -65,13 +65,35 @@ Versão do servidor de voz: [VOICE_VERSION]
 		</panel>
 		<panel label="Licenças" name="licenses_panel">
 			<text_editor name="credits_editor">
-				3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation Collada DOM Copyright 2005 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org). GL Copyright (C) 1999-2004 Brian Paul. GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) jpeglib Copyright (C) 1991-1998, Thomas G. Lane. ogg/vorbis Copyright (C) 2001, Xiphophorus OpenSSL Copyright (C) 1998-2002 The OpenSSL Project. PCRE Copyright (c) 1997-2008 University of Cambridge SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler. google-perftools Copyright (c) 2005, Google Inc.
+				3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
+        APR Copyright (C) 2000-2004 The Apache Software Foundation
+        Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
+        cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
+        DBus/dbus-glib Copyright (C) 2002, 2003  CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
+        expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
+        FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
+        GL Copyright (C) 1999-2004 Brian Paul.
+        GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University e David Luebke, Brenden Schubert, University of Virginia.
+        google-perftools Copyright (c) 2005, Google Inc.
+        Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
+        jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
+        jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
+        ogg/vorbis Copyright (C) 2001, Xiphophorus
+        OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
+        PCRE Copyright (c) 1997-2008 University of Cambridge
+        SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+        SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+        xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
+        zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler.
+        google-perftools Copyright (c) 2005, Google Inc.
 
-O Second Life Viewer usa Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (e licenciadores). Todos os direitos reservados. Mais detalhes em www.havok.com
+        O Visualizador do Second Life usa Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (e seus Licenciantes). Todos os direitos reservados. Consulte www.havok.com para obter detalhes.
 
-Todos os direitos reservados.  Mais detalhes em licenses.txt.
+        Este software contém código fonte fornecido pela NVIDIA Corporation.
 
-Codificação do áudio de bate-papo de voz: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
+        Todos os direitos reservados.  Consulte licenses.txt para obter detalhes.
+
+        Codificação de áudio da conversa com voz: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
 			</text_editor>
 		</panel>
 	</tab_container>
diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml
index cc09888994..30d4b0290c 100644
--- a/indra/newview/skins/default/xui/pt/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml
@@ -130,7 +130,7 @@ Vá para o menu Mundo &gt; Sobre o terreno ou selecione outro lote para mostrar
 				Tráfego:
 			</text>
 			<text name="DwellText">
-				0
+				Carregando...
 			</text>
 			<button label="Comprar terreno..." label_selected="Comprar terreno..." left="130" name="Buy Land..." width="125"/>
 			<button label="Venda Linden" name="Linden Sale..." tool_tip="O terreno precisa ser possuído, estar com o conteúdo configurado e não estar pronto para leilão."/>
@@ -309,13 +309,15 @@ Apenas lotes maiores podem ser listados na busca.
 				Proibido empurrar (regulamento da região)
 			</panel.string>
 			<panel.string name="see_avs_text">
-				Veja e bata papo com os residentes deste terreno
+				Avatares em outros lotes podem ver
 			</panel.string>
 			<text name="allow_label">
 				Autorizar outros residentes a:
 			</text>
-			<check_box label="Editar terreno" name="edit land check" tool_tip="Se ativado, qualquer um pode modificar o terreno. É melhor deixar esta opção desativada, uma vez que você sempre pode editar seu próprio terreno."/>
-			<check_box label="Voar" name="check fly" tool_tip="Se ativado,  residentes podem voar sobre seu terreno. Se desativado, eles podem voar apenas até chegar ou sobrevoar o seu terreno."/>
+			<text name="allow_label0">
+				Voar:
+			</text>
+			<check_box label="Todos" name="check fly" tool_tip="Se ativado,  residentes podem voar sobre seu terreno. Se desativado, eles podem voar apenas até chegar ou sobrevoar o seu terreno."/>
 			<text name="allow_label2">
 				Criar objetos:
 			</text>
@@ -331,9 +333,6 @@ Apenas lotes maiores podem ser listados na busca.
 			</text>
 			<check_box label="Residentes" name="check other scripts"/>
 			<check_box label="Grupo" name="check group scripts"/>
-			<text name="land_options_label">
-				Opções do terreno:
-			</text>
 			<check_box label="Seguro (sem danos)" name="check safe" tool_tip="Se ativado, ajusta o terreno para Seguro, impedindo lutas com danos. Se não ativado, lutas com danos é habilitado."/>
 			<check_box label="Proibido empurrar" name="PushRestrictCheck" tool_tip="Evita scripts que empurram. Ativar essa opção ajuda a prevenir comportamentos desordeiros no seu terreno."/>
 			<check_box label="Mostrar terreno nos resultados de busca (L$30/semana)" name="ShowDirectoryCheck" tool_tip="Permitir que as pessoas vejam este terreno nos resultados de busca"/>
@@ -374,9 +373,9 @@ Apenas lotes maiores podem ser listados na busca.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Clique para escolher uma imagem"/>
 			<text name="allow_label5">
-				Permitir que residentes de outros terrenos:
+				e bater papo com avatares neste lote
 			</text>
-			<check_box label="Ver avatares" name="SeeAvatarsCheck" tool_tip="Permite que residentes de outros terrenos vejam e conversem com os residentes deste terreno e vice-versa."/>
+			<check_box label="Ver avatares" name="SeeAvatarsCheck" tool_tip="Permite que os avatares em outros lotes vejam e batam papo com avatares neste lote. Você poderá vê-los e conversar com eles."/>
 			<text name="landing_point">
 				Ponto de Aterrissagem: [LANDING]
 			</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_avatar.xml b/indra/newview/skins/default/xui/pt/floater_avatar.xml
index f51b765105..168cdacae1 100644
--- a/indra/newview/skins/default/xui/pt/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/pt/floater_avatar.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Avatar" title="SELETOR DE AVATAR"/>
+<floater name="Avatar" title="ESCOLHA UM AVATAR"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
index b5ba477fe5..2845a29e1d 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
+		[http://www.secondlife.com/my/account/payment_method_management.php método de pagamento] | [http://www.secondlife.com/my/account/currency.php moeda]
 	</text>
 	<text name="exchange_rate_note">
 		Digite o valor novamente para ver o câmbio atual.
diff --git a/indra/newview/skins/default/xui/pt/floater_camera.xml b/indra/newview/skins/default/xui/pt/floater_camera.xml
index 6b66d01781..9cda01c187 100644
--- a/indra/newview/skins/default/xui/pt/floater_camera.xml
+++ b/indra/newview/skins/default/xui/pt/floater_camera.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="camera_floater" title="EXIBIR">
+<floater name="camera_floater" title="CONTROLES DA CÂMERA">
 	<floater.string name="rotate_tooltip">
 		Girar a Câmera ao redor do Foco
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml b/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml
index 8c95a3b548..1bc2bce768 100644
--- a/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml
@@ -4,7 +4,7 @@
 		Filtragem:
 	</text>
 	<check_box label="Filtragem Anisotrópica (mais lento quando habilitada)" name="ani"/>
-	<text name="Antialiasing:">
+	<text name="antialiasing label">
 		Suavização:
 	</text>
 	<combo_box label="Suavização" name="fsaa" width="94">
diff --git a/indra/newview/skins/default/xui/pt/floater_model_preview.xml b/indra/newview/skins/default/xui/pt/floater_model_preview.xml
index 17abe72173..8960500831 100644
--- a/indra/newview/skins/default/xui/pt/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/pt/floater_model_preview.xml
@@ -4,6 +4,9 @@
 	<string name="status_parse_error">
 		Erro: Problema ao analisar .dae - consulte log para obter detalhes.
 	</string>
+	<string name="status_material_mismatch">
+		Erro: o material do modelo não é um subconjunto do modelo de referência.
+	</string>
 	<string name="status_reading_file">
 		Carregando...
 	</string>
diff --git a/indra/newview/skins/default/xui/pt/floater_model_wizard.xml b/indra/newview/skins/default/xui/pt/floater_model_wizard.xml
index d9195adbf9..498058f933 100644
--- a/indra/newview/skins/default/xui/pt/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/pt/floater_model_wizard.xml
@@ -20,6 +20,9 @@
 				Escolha o arquivo de modelo para upload
 			</text>
 			<button label="Procurar..." label_selected="Procurar..." name="browse"/>
+			<text name="Model types">
+				O Second Life oferece suporte a arquivos COLLADA (.dae)
+			</text>
 			<text name="dimensions">
 				X         Y         Z
 			</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_moveview.xml b/indra/newview/skins/default/xui/pt/floater_moveview.xml
index 0cb6f9a98e..728357a400 100644
--- a/indra/newview/skins/default/xui/pt/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/pt/floater_moveview.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move_floater" title="MOVER">
+<floater name="move_floater" title="ANDAR/CORRER/VOAR">
 	<string name="walk_forward_tooltip">
 		Andar para frente (flecha para cima ou W)
 	</string>
diff --git a/indra/newview/skins/default/xui/pt/floater_snapshot.xml b/indra/newview/skins/default/xui/pt/floater_snapshot.xml
index d62fe3dd20..4110e69068 100644
--- a/indra/newview/skins/default/xui/pt/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/pt/floater_snapshot.xml
@@ -3,73 +3,63 @@
 	<floater.string name="unknown">
 		desconhecido
 	</floater.string>
-	<radio_group label="Tipo de foto" name="snapshot_type_radio">
-		<radio_item label="Email" name="postcard"/>
-		<radio_item label="Meu inventário (L$[AMOUNT])" name="texture"/>
-		<radio_item label="Salvar no meu PC" name="local"/>
-	</radio_group>
+	<string name="postcard_progress_str">
+		Enviando e-mail
+	</string>
+	<string name="profile_progress_str">
+		Postando
+	</string>
+	<string name="inventory_progress_str">
+		Salvando no inventário
+	</string>
+	<string name="local_progress_str">
+		Salvo no computador
+	</string>
+	<string name="profile_succeeded_str">
+		Imagem carregada
+	</string>
+	<string name="postcard_succeeded_str">
+		E-mail enviado!
+	</string>
+	<string name="inventory_succeeded_str">
+		Salvo no inventário!
+	</string>
+	<string name="local_succeeded_str">
+		Salvo no computador!
+	</string>
+	<string name="profile_failed_str">
+		Falha ao carregar a imagem no feed do seu perfil.
+	</string>
+	<string name="postcard_failed_str">
+		Falha ao enviar e-mail.
+	</string>
+	<string name="inventory_failed_str">
+		Falha ao salvar no inventário.
+	</string>
+	<string name="local_failed_str">
+		Falha ao salvar no computador.
+	</string>
+	<button name="advanced_options_btn" tool_tip="Opções avançadas"/>
+	<text name="image_res_text">
+		[WIDTH] x [HEIGHT] px
+	</text>
 	<text name="file_size_label">
 		[TAMANHO] KB
 	</text>
-	<button label="Atualizar a foto" name="new_snapshot_btn"/>
-	<button label="Enviar" name="send_btn"/>
-	<button label="Economize (L$[AMOUNT])" name="upload_btn"/>
-	<flyout_button label="Salvar" name="save_btn" tool_tip="Salvar imagem em um arquivo">
-		<flyout_button.item label="Salvar" name="save_item"/>
-		<flyout_button.item label="Salvar como..." name="saveas_item"/>
-	</flyout_button>
-	<button label="Mais" name="more_btn" tool_tip="Opções avançadas"/>
-	<button label="Menos" name="less_btn" tool_tip="Opções avançadas"/>
-	<button label="Cancelar" name="discard_btn"/>
-	<text name="type_label2">
-		Tamanho
-	</text>
-	<text name="format_label">
-		Formato
-	</text>
-	<combo_box label="Resolução" name="postcard_size_combo">
-		<combo_box.item label="Janela atual" name="CurrentWindow"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="Customizado" name="Custom"/>
-	</combo_box>
-	<combo_box label="Resolução" name="texture_size_combo">
-		<combo_box.item label="Janela atual" name="CurrentWindow"/>
-		<combo_box.item label="Pequeno (128x128)" name="Small(128x128)"/>
-		<combo_box.item label="Médio (256x256)" name="Medium(256x256)"/>
-		<combo_box.item label="Grande (512x512)" name="Large(512x512)"/>
-		<combo_box.item label="Customizado" name="Custom"/>
-	</combo_box>
-	<combo_box label="Resolução" name="local_size_combo">
-		<combo_box.item label="Janela atual" name="CurrentWindow"/>
-		<combo_box.item label="320x240" name="320x240"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="1280x1024" name="1280x1024"/>
-		<combo_box.item label="1600x1200" name="1600x1200"/>
-		<combo_box.item label="Customizado" name="Custom"/>
-	</combo_box>
-	<combo_box label="Formato" name="local_format_combo">
-		<combo_box.item label="PNG" name="PNG"/>
-		<combo_box.item label="JPEG" name="JPEG"/>
-		<combo_box.item label="BMP" name="BMP"/>
-	</combo_box>
-	<spinner label="Largura" name="snapshot_width"/>
-	<spinner label="Altura" name="snapshot_height"/>
-	<check_box label="Limitar proproções" name="keep_aspect_check"/>
-	<slider label="Qualidade da imagem" name="image_quality_slider"/>
-	<text name="layer_type_label">
-		Capturar:
-	</text>
-	<combo_box label="Camadas da imagem" name="layer_types">
-		<combo_box.item label="Cores" name="Colors"/>
-		<combo_box.item label="Profundidade" name="Depth"/>
-	</combo_box>
-	<check_box label="Interface" name="ui_check"/>
-	<check_box label="HUDs" name="hud_check"/>
-	<check_box label="Deixar aberto depois de salvo" name="keep_open_check"/>
-	<check_box label="Gerar quadro (tela inteira)" name="freeze_frame_check"/>
-	<check_box label="Atualizar" name="auto_snapshot_check"/>
+	<panel name="advanced_options_panel">
+		<text name="advanced_options_label">
+			OPÇÕES AVANÇADAS
+		</text>
+		<text name="layer_type_label">
+			Capturar:
+		</text>
+		<combo_box label="Camadas da imagem" name="layer_types">
+			<combo_box.item label="Cores" name="Colors"/>
+			<combo_box.item label="Profundidade" name="Depth"/>
+		</combo_box>
+		<check_box label="Interface" name="ui_check"/>
+		<check_box label="HUDs" name="hud_check"/>
+		<check_box label="Gerar quadro (tela inteira)" name="freeze_frame_check"/>
+		<check_box label="Atualização automática" name="auto_snapshot_check"/>
+	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_toybox.xml b/indra/newview/skins/default/xui/pt/floater_toybox.xml
index 67076beb0f..3677c3b1f5 100644
--- a/indra/newview/skins/default/xui/pt/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/pt/floater_toybox.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Toybox" title="PERSONALIZAR BARRAS DE FERRAMENTA">
+<floater name="Toybox" title="BOTÕES DA BARRA DE FERRAMENTAS">
 	<text name="toybox label 1">
 		Adicione ou remova botões arrastando-os para dentro ou para fora das barras de ferramentas.
 	</text>
 	<text name="toybox label 2">
 		Os botões aparecerão como mostrado ou somente como ícone, dependendo das configurações de cada barra de ferramentas.
 	</text>
+	<button label="Limpar todas as barras de ferramentas" label_selected="Limpar todas as barras de ferramentas" name="btn_clear_all"/>
 	<button label="Restaurar padrão" label_selected="Restaurar padrão" name="btn_restore_defaults"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_translation_settings.xml b/indra/newview/skins/default/xui/pt/floater_translation_settings.xml
new file mode 100644
index 0000000000..1955599a81
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/floater_translation_settings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_translation_settings" title="CONFIGURAÇÕES DE TRADUÇÃO DE BATE-PAPO">
+	<string name="bing_api_key_not_verified">
+		appID do Bing não verificada. Tente novamente.
+	</string>
+	<string name="google_api_key_not_verified">
+		Chave do API do Google não verificada. Tente novamente.
+	</string>
+	<string name="bing_api_key_verified">
+		appID do Bing verificada.
+	</string>
+	<string name="google_api_key_verified">
+		Chave do API do Google verificada.
+	</string>
+	<check_box label="Permitir a tradução de máquina durante o bate-papo" name="translate_chat_checkbox"/>
+	<text name="translate_language_label">
+		Traduzir bate-papo para:
+	</text>
+	<combo_box name="translate_language_combo">
+		<combo_box.item label="Padrão" name="System Default Language"/>
+		<combo_box.item label="Inglês" name="English"/>
+		<combo_box.item label="Dansk (Dinamarquês)" name="Danish"/>
+		<combo_box.item label="Deutsch (Alemão)" name="German"/>
+		<combo_box.item label="Español (Espanhol)" name="Spanish"/>
+		<combo_box.item label="Français (Francês)" name="French"/>
+		<combo_box.item label="Italiano (Italiano)" name="Italian"/>
+		<combo_box.item label="Magyar (Húngaro)" name="Hungarian"/>
+		<combo_box.item label="Nederlands (Holandês)" name="Dutch"/>
+		<combo_box.item label="Polski (Polonês)" name="Polish"/>
+		<combo_box.item label="Português (Português)" name="Portugese"/>
+		<combo_box.item label="Русский (Russo)" name="Russian"/>
+		<combo_box.item label="Türkçe (Turco)" name="Turkish"/>
+		<combo_box.item label="Українська (Ucraniano)" name="Ukrainian"/>
+		<combo_box.item label="中文 (简体) (Chinês)" name="Chinese"/>
+		<combo_box.item label="日本語 (Japonês)" name="Japanese"/>
+		<combo_box.item label="한국어 (Coreano)" name="Korean"/>
+	</combo_box>
+	<text name="tip">
+		Escolha o serviço de tradução:
+	</text>
+	<radio_group name="translation_service_rg">
+		<radio_item initial_value="bing" label="Bing Translator" name="bing"/>
+		<radio_item initial_value="google" label="Google Translate" name="google"/>
+	</radio_group>
+	<text name="bing_api_key_label">
+		[http://www.bing.com/developers/createapp.aspx AppID] do Bing:
+	</text>
+	<button label="Verificar" name="verify_bing_api_key_btn"/>
+	<text name="google_api_key_label">
+		[http://code.google.com/apis/language/translate/v2/getting_started.html#auth Chave API] do Google:
+	</text>
+	<button label="Verificar" name="verify_google_api_key_btn"/>
+	<text name="google_links_text">
+		[http://code.google.com/apis/language/translate/v2/pricing.html Preços] | [https://code.google.com/apis/console Estatísticas]
+	</text>
+	<button label="OK" name="ok_btn"/>
+	<button label="Cancelar" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_voice_controls.xml b/indra/newview/skins/default/xui/pt/floater_voice_controls.xml
index 6132479041..745a7d0e00 100644
--- a/indra/newview/skins/default/xui/pt/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/pt/floater_voice_controls.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="floater_voice_controls" title="CONTROLES DE VOZ">
 	<string name="title_nearby">
-		Voz próxima
+		CONFIGURAÇÕES DE VOZ
 	</string>
 	<string name="title_group">
-		Ligação de grupo com [GROUP]
+		LIGAÇÃO DE GRUPO COM [GROUP]
 	</string>
 	<string name="title_adhoc">
-		Teleconferência
+		TELECONFERÊNCIA
 	</string>
 	<string name="title_peer_2_peer">
-		Ligação para [NAME]
+		LIGAÇÃO PARA [NAME]
 	</string>
 	<string name="no_one_near">
 		Ninguém por perto ativou a voz
diff --git a/indra/newview/skins/default/xui/pt/menu_toolbars.xml b/indra/newview/skins/default/xui/pt/menu_toolbars.xml
index f1e41aaea9..b58a1a6e4f 100644
--- a/indra/newview/skins/default/xui/pt/menu_toolbars.xml
+++ b/indra/newview/skins/default/xui/pt/menu_toolbars.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <context_menu name="Toolbars Popup">
-	<menu_item_call label="Escolher botões..." name="Chose Buttons"/>
+	<menu_item_call label="Remover este botão" name="Remove button"/>
+	<menu_item_call label="Botões da barra de ferramentas..." name="Choose Buttons"/>
 	<menu_item_check label="Ícones e rótulos" name="icons_with_text"/>
 	<menu_item_check label="Somente ícones" name="icons_only"/>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml
index 5ff2d49ac1..119a3bdcfe 100644
--- a/indra/newview/skins/default/xui/pt/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <menu_bar name="Main Menu">
 	<menu label="Eu" name="Me">
-		<menu_item_call label="Painel..." name="Manage My Account">
-			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=pt"/>
-		</menu_item_call>
 		<menu_item_call label="Perfil..." name="Profile"/>
 		<menu_item_call label="Aparência..." name="ChangeOutfit"/>
+		<menu_item_call label="Selecione um avatar..." name="Avatar Picker"/>
 		<menu_item_check label="Inventário..." name="Inventory"/>
-		<menu_item_check label="Gestos..." name="Gestures"/>
-		<menu_item_check label="Voz..." name="ShowVoice"/>
+		<menu_item_call label="Nova janela de inventário" name="NewInventoryWindow"/>
+		<menu_item_call label="Lugares..." name="Places"/>
+		<menu_item_call label="Destaques..." name="Picks"/>
+		<menu_item_call label="Controles da câmera..." name="Camera Controls"/>
 		<menu label="Movimentos" name="Movement">
 			<menu_item_call label="Sentar" name="Sit Down Here"/>
 			<menu_item_check label="Voar" name="Fly"/>
@@ -22,34 +22,39 @@
 		<menu_item_call label="Request Admin Status" name="Request Admin Options"/>
 		<menu_item_call label="Sair do modo admin" name="Leave Admin Options"/>
 		<menu_item_call label="Comprar L$" name="Buy and Sell L$"/>
+		<menu_item_call label="Painel da conta..." name="Manage My Account">
+			<menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=pt"/>
+		</menu_item_call>
 		<menu_item_call label="Preferências..." name="Preferences"/>
-		<menu_item_call label="Barras de ferramentas..." name="Toolbars"/>
+		<menu_item_call label="Botões da barra de ferramentas..." name="Toolbars"/>
 		<menu_item_call label="Ocultar todos os controles" name="Hide UI"/>
 		<menu_item_call label="Sair do [APP_NAME]" name="Quit"/>
 	</menu>
 	<menu label="Comunicar" name="Communicate">
-		<menu_item_call label="Meus amigos" name="My Friends"/>
-		<menu_item_call label="Meus grupos" name="My Groups"/>
-		<menu_item_check label="Bate-papo local" name="Nearby Chat"/>
-		<menu_item_call label="Pessoas por perto" name="Active Speakers"/>
-		<menu_item_check label="Voz por perto" name="Nearby Voice"/>
+		<menu_item_check label="Bate-papo..." name="Nearby Chat"/>
+		<menu_item_check label="Falar" name="Speak"/>
+		<menu_item_check label="Configurações de voz..." name="Nearby Voice"/>
+		<menu_item_check label="Distorção de voz..." name="ShowVoice"/>
+		<menu_item_check label="Gestos..." name="Gestures"/>
+		<menu_item_call label="Amigos" name="My Friends"/>
+		<menu_item_call label="Grupos" name="My Groups"/>
+		<menu_item_call label="Pessoas próximas" name="Active Speakers"/>
 	</menu>
 	<menu label="Mundo" name="World">
-		<menu_item_check label="Mini Mapa" name="Mini-Map"/>
+		<menu_item_call label="Criar marco deste lugar" name="Create Landmark Here"/>
+		<menu_item_call label="Destinos..." name="Destinations"/>
 		<menu_item_check label="Mapa-múndi" name="World Map"/>
+		<menu_item_check label="Mini Mapa" name="Mini-Map"/>
 		<menu_item_check label="Busca" name="Search"/>
+		<menu_item_call label="Teletransportar para início" name="Teleport Home"/>
+		<menu_item_call label="Definir como casa" name="Set Home to Here"/>
 		<menu_item_call label="Foto" name="Take Snapshot"/>
-		<menu_item_call label="Criar marco deste lugar" name="Create Landmark Here"/>
-		<menu label="Perfil da região" name="Land">
-			<menu_item_call label="Perfil da região" name="Place Profile"/>
-			<menu_item_call label="Sobre terrenos" name="About Land"/>
-			<menu_item_call label="Região/Propriedade" name="Region/Estate"/>
-		</menu>
+		<menu_item_call label="Perfil da região" name="Place Profile"/>
+		<menu_item_call label="Sobre terrenos" name="About Land"/>
+		<menu_item_call label="Região/Propriedade" name="Region/Estate"/>
+		<menu_item_call label="Meus terrenos..." name="My Land"/>
 		<menu_item_call label="Comprar este terreno" name="Buy Land"/>
-		<menu_item_call label="Meus terrenos" name="My Land"/>
 		<menu label="Mostrar" name="LandShow">
-			<menu_item_check label="Controles de movimento" name="Movement Controls"/>
-			<menu_item_check label="Ver controles" name="Camera Controls"/>
 			<menu_item_check label="Limites" name="Ban Lines"/>
 			<menu_item_check label="Balizas" name="beacons"/>
 			<menu_item_check label="Limites do imóvel" name="Property Lines"/>
@@ -58,30 +63,29 @@
 			<menu_item_check label="Propriedades do lote" name="Parcel Properties"/>
 			<menu_item_check label="Menu avançado" name="Show Advanced Menu"/>
 		</menu>
-		<menu_item_call label="Teletransportar para meu início" name="Teleport Home"/>
-		<menu_item_call label="Definir como Início" name="Set Home to Here"/>
 		<menu label="Sol" name="Environment Settings">
 			<menu_item_call label="Amanhecer" name="Sunrise"/>
 			<menu_item_call label="Meio-dia" name="Noon"/>
 			<menu_item_call label="Pôr-do-Sol" name="Sunset"/>
 			<menu_item_call label="Meia-noite" name="Midnight"/>
-		</menu>
-		<menu label="Editor de ambientes" name="Enviroment Editor">
-			<menu_item_call label="Configurações de ambiente..." name="Enviroment Settings"/>
-			<menu label="Pré-configurações de água" name="Water Presets">
-				<menu_item_call label="Nova pré-configuração..." name="new_water_preset"/>
-				<menu_item_call label="Editar pré-configuração..." name="edit_water_preset"/>
-				<menu_item_call label="Excluir pré-configuração..." name="delete_water_preset"/>
+			<menu_item_call label="Usar configurações da região" name="Use Region Settings"/>
+		</menu>
+		<menu label="Editor de ambientes" name="Environment Editor">
+			<menu_item_call label="Configurações do ambiente..." name="Environment Settings"/>
+			<menu label="Predefinições da água" name="Water Presets">
+				<menu_item_call label="Nova predefinição..." name="new_water_preset"/>
+				<menu_item_call label="Editar predefinição..." name="edit_water_preset"/>
+				<menu_item_call label="Excluir predefinição..." name="delete_water_preset"/>
 			</menu>
-			<menu label="Pré-configurações de céu" name="Sky Presets">
-				<menu_item_call label="Nova pré-configuração..." name="new_sky_preset"/>
-				<menu_item_call label="Editar pré-configuração..." name="edit_sky_preset"/>
-				<menu_item_call label="Excluir pré-configuração..." name="delete_sky_preset"/>
+			<menu label="Predefinições de céu" name="Sky Presets">
+				<menu_item_call label="Nova predefinição..." name="new_sky_preset"/>
+				<menu_item_call label="Editar predefinição..." name="edit_sky_preset"/>
+				<menu_item_call label="Excluir predefinição..." name="delete_sky_preset"/>
 			</menu>
-			<menu label="Pré-configurações de dias" name="Day Presets">
-				<menu_item_call label="Nova pré-configuração..." name="new_day_preset"/>
-				<menu_item_call label="Editar pré-configuração..." name="edit_day_preset"/>
-				<menu_item_call label="Excluir pré-configuração..." name="delete_day_preset"/>
+			<menu label="Predefinições do dia" name="Day Presets">
+				<menu_item_call label="Nova predefinição..." name="new_day_preset"/>
+				<menu_item_call label="Editar predefinição..." name="edit_day_preset"/>
+				<menu_item_call label="Excluir predefinição..." name="delete_day_preset"/>
 			</menu>
 		</menu>
 	</menu>
@@ -146,6 +150,7 @@
 		<menu_item_call label="Repetir" name="Redo"/>
 	</menu>
 	<menu label="Ajuda" name="Help">
+		<menu_item_call label="Como..." name="How To"/>
 		<menu_item_call label="[SECOND_LIFE] Ajuda" name="Second Life Help"/>
 		<menu_item_call label="Denunciar abuso" name="Report Abuse"/>
 		<menu_item_call label="Relatar bug" name="Report Bug"/>
@@ -199,11 +204,10 @@
 		<menu_item_check label="Usar plugin de leitura de threads" name="Use Plugin Read Thread"/>
 		<menu_item_call label="Limpar cache de grupo" name="ClearGroupCache"/>
 		<menu_item_check label="Smoothing de mouse" name="Mouse Smoothing"/>
+		<menu_item_call label="Liberar teclas" name="Release Keys"/>
 		<menu label="Atalhos" name="Shortcuts">
 			<menu_item_call label="Imagem (L$[COST])..." name="Upload Image"/>
 			<menu_item_check label="Busca" name="Search"/>
-			<menu_item_call label="Soltar objeto" name="Release Keys"/>
-			<menu_item_call label="Interface tamanho padrão" name="Set UI Size to Default"/>
 			<menu_item_check label="Mostrar menu avançado - atalho antigo" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Fechar janela" name="Close Window"/>
 			<menu_item_call label="Fechar todas as janelas" name="Close All Windows"/>
@@ -272,6 +276,7 @@
 			<menu_item_check label="Tipo de atualização" name="Update Type"/>
 			<menu_item_check label="Dados LOD" name="LOD Info"/>
 			<menu_item_check label="Fila de construção" name="Build Queue"/>
+			<menu_item_check label="Vetores de vento" name="Wind Vectors"/>
 			<menu_item_check label="Renderizar complexidade" name="rendercomplexity"/>
 			<menu_item_check label="Esculpir" name="Sculpt"/>
 		</menu>
@@ -281,7 +286,6 @@
 			<menu_item_check label="Iluminação e sombras" name="Lighting and Shadows"/>
 			<menu_item_check label="Sombras da projeção do sol/lua" name="Shadows from Sun/Moon/Projectors"/>
 			<menu_item_check label="SSAO e sombra suave" name="SSAO and Shadow Smoothing"/>
-			<menu_item_check label="Iluminação global (fase experimental)" name="Global Illumination"/>
 			<menu_item_check label="Máscaras alpha automáticas (adiadas)" name="Automatic Alpha Masks (deferred)"/>
 			<menu_item_check label="Máscaras alpha automáticas (sem adiar)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Texturas de animação" name="Animation Textures"/>
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index b53ebeb136..2c5ccd6e19 100644
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -973,7 +973,7 @@ Oferecer amizade para [NAME]?
 		</form>
 	</notification>
 	<notification name="RemoveFromFriends">
-		Remover &lt;nolink&gt;[NAME]&lt;/nolink&gt; da sua lista de amigos?
+		Deseja remover &lt;nolink&gt;[NAME]&lt;/nolink&gt; da sua lista de amigos?
 		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Remover"/>
 	</notification>
 	<notification name="RemoveMultipleFromFriends">
@@ -1099,8 +1099,13 @@ Doar este terreno de [AREA] m² para o grupo &apos;[GROUP_NAME]&apos;?
 	<notification name="DisplaySetToSafe">
 		Configurações de display foram ajustadas para níveis de segurança porque você especificou -- opção de segurança.
 	</notification>
-	<notification name="DisplaySetToRecommended">
-		Configurações de display foram ajustadas para nível recomendado baseado na configuração do seu sistema.
+	<notification name="DisplaySetToRecommendedGPUChange">
+		As configurações de tela foram definidas nos níveis recomendados porque sua placa de vídeo foi alterada
+de &apos;[LAST_GPU]&apos;
+para &apos;[THIS_GPU]&apos;
+	</notification>
+	<notification name="DisplaySetToRecommendedFeatureChange">
+		As configurações de tela foram definidas nos níveis recomendados por causa de uma alteração no subsistema de renderização.
 	</notification>
 	<notification name="ErrorMessage">
 		[ERROR_MESSAGE]
@@ -1900,7 +1905,13 @@ Mover para o inventário o(s) item(s)?
 		<usetemplate ignoretext="Confirmar antes de sair" name="okcancelignore" notext="Não sair" yestext="Sair"/>
 	</notification>
 	<notification name="ConfirmRestoreToybox">
-		Tem certeza que deseja restaurar seus botões e barras de ferramenta padrão? 
+		Essa ação irá restaurar os botões e barras de ferramenta padrão.
+
+Não é possível desfazer essa ação.
+		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
+	</notification>
+	<notification name="ConfirmClearAllToybox">
+		Essa ação fará com que todos os botões voltem para a caixa de ferramentas e suas barras de ferramentas ficarão vazias.
     
 Não é possível desfazer essa ação.
 		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
@@ -2225,14 +2236,16 @@ Selecione só um objeto.
 		Seu cartão de visita foi negado.
 	</notification>
 	<notification name="TeleportToLandmark">
-		Para se teletransportar para lugares como &apos;[NAME]&apos;, abra o painel &apos;Lugares&apos; à direita da tela e selecione a guia Marcos.  
-Basta clicar em qualquer marco e depois clicar em &apos;Teletransportar&apos; na parte inferior da tela. 
-(Também é possível clicar duas vezes no marco, ou clicar no marco com o botão direito e selecionar &apos;Teletransportar&apos;.)
+		Para se teletransportar para locais como &apos;[NAME]&apos;, clique no botão &quot;Lugares&quot;,
+    e selecione a guia Marcos na janela que é exibida. Clique em qualquer
+    marco para selecioná-lo e em seguida em &apos;Teletransportar&apos; na parte inferior da tela.
+    (Também é possível clicar duas vezes sobre o marco ou clicar com o botão direito do mouse sobre ele
+    e selecionar &apos;Teletransportar&apos;.)
 	</notification>
 	<notification name="TeleportToPerson">
-		Para entrar em contato com residentes como &apos;&apos;[NAME]&apos;,  abra o painel &apos;Pessoas&apos; à direita da tela.
-Selecione o residente da lista e clique em &apos;MI&apos; na parte de baixo do painel.
-(Também é possível clicar duas vezes no nome, ou clicar no nome com o botão direito e selecionar &apos;MI&apos;.)
+		Para entrar em contato com residentes como &apos;[NAME]&apos;, clique no botão &quot;Pessoas&quot;, selecione um residente na janela que é exibida e clique em &apos;MI&apos; na
+    parte inferior da janela.
+    (Também é possível clicar duas vezes no nome, ou clicar no nome com o botão direito e selecionar &apos;MI&apos;.)
 	</notification>
 	<notification name="CantSelectLandFromMultipleRegions">
 		Impossível selecionar terra nas fronteiras do servidor. Tente selecionar um pedaço menor de terra.
@@ -2252,6 +2265,9 @@ Selecione o residente da lista e clique em &apos;MI&apos; na parte de baixo do p
 	<notification name="PaymentSent">
 		[MESSAGE]
 	</notification>
+	<notification name="PaymentFailure">
+		[MESSAGE]
+	</notification>
 	<notification name="EventNotification">
 		Notificação de evento:
 
@@ -2501,10 +2517,10 @@ Cada um pode ver o status do outro (definição padrão).
 		</form>
 	</notification>
 	<notification name="FriendshipAccepted">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; aceitou seu convite de amizade.
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; aceitou sua oferta de amizade.
 	</notification>
 	<notification name="FriendshipDeclined">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; recusou seu convite de amizade
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; rejeitou sua oferta de amizade.
 	</notification>
 	<notification name="FriendshipAcceptedByMe">
 		Oferta de amizada aceita.
diff --git a/indra/newview/skins/default/xui/pt/panel_edit_skin.xml b/indra/newview/skins/default/xui/pt/panel_edit_skin.xml
index f3d88123f2..d00aa2dc66 100644
--- a/indra/newview/skins/default/xui/pt/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/pt/panel_edit_skin.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_skin_panel">
 	<panel name="avatar_skin_color_panel">
-		<texture_picker label="Tatuagens na cabeça" name="Head Tattoos" tool_tip="Selecionar imagem"/>
-		<texture_picker label="Tatuagem parte de cima" name="Upper Tattoos" tool_tip="Selecionar imagem"/>
-		<texture_picker label="Tatuagem de baixo" name="Lower Tattoos" tool_tip="Selecionar imagem"/>
+		<texture_picker label="Cabeça" name="Head" tool_tip="Selecionar imagem"/>
+		<texture_picker label="Cintura acima" name="Upper Body" tool_tip="Selecionar imagem"/>
+		<texture_picker label="Cintura para baixo" name="Lower Body" tool_tip="Selecionar imagem"/>
 	</panel>
 	<panel name="accordion_panel">
 		<accordion name="wearable_accordion">
diff --git a/indra/newview/skins/default/xui/pt/panel_postcard_message.xml b/indra/newview/skins/default/xui/pt/panel_postcard_message.xml
new file mode 100644
index 0000000000..9cde810430
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_postcard_message.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_message">
+	<text name="to_label">
+		Para:
+	</text>
+	<text name="name_label">
+		De:
+	</text>
+	<text name="subject_label">
+		Assunto:
+	</text>
+	<line_editor label="Digite aqui o assunto." name="subject_form"/>
+	<text name="msg_label">
+		Mensagem:
+	</text>
+	<text_editor name="msg_form">
+		Digite aqui a mensagem.
+	</text_editor>
+	<button label="Cancelar" name="cancel_btn"/>
+	<button label="Enviar" name="send_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_postcard_settings.xml b/indra/newview/skins/default/xui/pt/panel_postcard_settings.xml
new file mode 100644
index 0000000000..3088b9a996
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_postcard_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_settings">
+	<combo_box label="Resolução" name="postcard_size_combo">
+		<combo_box.item label="Janela atual" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Customizado" name="Custom"/>
+	</combo_box>
+	<layout_stack name="postcard_image_params_ls">
+		<layout_panel name="postcard_image_size_lp">
+			<spinner label="Largura" name="postcard_snapshot_width"/>
+			<spinner label="Altura" name="postcard_snapshot_height"/>
+			<check_box label="Limitar proporções" name="postcard_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="postcard_image_format_quality_lp">
+			<slider label="Qualidade da imagem" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml
index f98659aa73..c5a4febb0e 100644
--- a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml
@@ -29,30 +29,5 @@
 	<check_box label="Bate-papos de MI" name="EnableIMChatPopups" tool_tip="Exibir pop-up de mensagens instantâneas novas"/>
 	<spinner label="Transição de avisos de bate-papos por perto:" name="nearby_toasts_lifetime"/>
 	<spinner label="Transição de avisos de bate-papos por perto:" name="nearby_toasts_fadingtime"/>
-	<check_box name="translate_chat_checkbox"/>
-	<text name="translate_chb_label">
-		Traduzir bate-papo automaticamente
-	</text>
-	<text name="translate_language_text">
-		Traduzir bate-papo para:
-	</text>
-	<combo_box name="translate_language_combobox">
-		<combo_box.item label="Padrão" name="System Default Language"/>
-		<combo_box.item label="English (Inglês)" name="English"/>
-		<combo_box.item label="Dansk (Dinamarquês)" name="Danish"/>
-		<combo_box.item label="Deutsch (Alemão)" name="German"/>
-		<combo_box.item label="Español (Espanhol)" name="Spanish"/>
-		<combo_box.item label="Français (Francês)" name="French"/>
-		<combo_box.item label="Italiano (Italiano)" name="Italian"/>
-		<combo_box.item label="Magyar (Húngaro)" name="Hungarian"/>
-		<combo_box.item label="Nederlands (Holandês)" name="Dutch"/>
-		<combo_box.item label="Polski (Polonês)" name="Polish"/>
-		<combo_box.item label="Português (Português)" name="Portugese"/>
-		<combo_box.item label="Русский (Russo)" name="Russian"/>
-		<combo_box.item label="Türkçe (Turco)" name="Turkish"/>
-		<combo_box.item label="Українська (Ucraniano)" name="Ukrainian"/>
-		<combo_box.item label="中文 (简体) (Chinês)" name="Chinese"/>
-		<combo_box.item label="日本語 (Japonês)" name="Japanese"/>
-		<combo_box.item label="한국어 (Coreano)" name="Korean"/>
-	</combo_box>
+	<button label="Configurações de tradução de bate-papo" name="ok_btn"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml b/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml
index 9259c0ed56..ebbd63138a 100644
--- a/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml
@@ -15,7 +15,7 @@
 		Web:
 	</text>
 	<radio_group name="use_external_browser">
-		<radio_item label="Usar meu navegador (IE, Firefox, Safari)" name="external" tool_tip="Use o navegador incluso para consultar a ajuda, abrir links da web, etc. Uso em tela inteira não recomendado." value="1"/>
+		<radio_item label="Usar meu navegador (IE, Firefox, Safari)" name="external" tool_tip="Use o navegador incluso para consultar a ajuda, abrir links da web, etc. Uso em tela inteira não recomendado." value="true"/>
 		<radio_item label="Usar navegador incluso" name="internal" tool_tip="Use este navegador para consultar a ajuda, abrir links da web, etc. As janelas abrem dentro do [APP_NAME]." value=""/>
 	</radio_group>
 	<check_box initial_value="true" label="Habilitar plugins" name="browser_plugins_enabled"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml
new file mode 100644
index 0000000000..3c4bb18687
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_inventory">
+	<text name="title">
+		Salvar no meu inventário
+	</text>
+	<text name="hint_lbl">
+		Salvar uma imagem em seu inventário custa L$[UPLOAD_COST]. Para salvar sua imagem como uma textura, selecione um dos formatos quadrados.
+	</text>
+	<combo_box label="Resolução" name="texture_size_combo">
+		<combo_box.item label="Janela atual" name="CurrentWindow"/>
+		<combo_box.item label="Pequeno (128x128)" name="Small(128x128)"/>
+		<combo_box.item label="Médio (256x256)" name="Medium(256x256)"/>
+		<combo_box.item label="Grande (512x512)" name="Large(512x512)"/>
+		<combo_box.item label="Customizado" name="Custom"/>
+	</combo_box>
+	<spinner label="Largura" name="inventory_snapshot_width"/>
+	<spinner label="Altura" name="inventory_snapshot_height"/>
+	<check_box label="Limitar proporções" name="inventory_keep_aspect_check"/>
+	<button label="Cancelar" name="cancel_btn"/>
+	<button label="Salvar" name="save_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_local.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_local.xml
new file mode 100644
index 0000000000..36b5b0cbe6
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_snapshot_local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_local">
+	<text name="title">
+		Salvar no meu PC
+	</text>
+	<combo_box label="Resolução" name="local_size_combo">
+		<combo_box.item label="Janela atual" name="CurrentWindow"/>
+		<combo_box.item label="320x240" name="320x240"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="1280x1024" name="1280x1024"/>
+		<combo_box.item label="1600x1200" name="1600x1200"/>
+		<combo_box.item label="Customizado" name="Custom"/>
+	</combo_box>
+	<layout_stack name="local_image_params_ls">
+		<layout_panel name="local_image_size_lp">
+			<spinner label="Largura" name="local_snapshot_width"/>
+			<spinner label="Altura" name="local_snapshot_height"/>
+			<check_box label="Limitar proporções" name="local_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="local_image_format_quality_lp">
+			<combo_box label="Formato" name="local_format_combo">
+				<combo_box.item label="PNG (sem perda)" name="PNG"/>
+				<combo_box.item label="JPEG" name="JPEG"/>
+				<combo_box.item label="BMP (sem perda)" name="BMP"/>
+			</combo_box>
+			<slider label="Qualidade da imagem" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+	<button label="Cancelar" name="cancel_btn"/>
+	<flyout_button label="Salvar" name="save_btn" tool_tip="Salvar imagem em um arquivo">
+		<flyout_button.item label="Salvar" name="save_item"/>
+		<flyout_button.item label="Salvar como..." name="saveas_item"/>
+	</flyout_button>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_options.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_options.xml
new file mode 100644
index 0000000000..7f1452e992
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_snapshot_options.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_options">
+	<button label="Postar no feed do meu perfil" name="save_to_profile_btn"/>
+	<button label="E-mail" name="save_to_email_btn"/>
+	<button label="Salvar em Meu inventário (L$[AMOUNT])" name="save_to_inventory_btn"/>
+	<button label="Salvar no meu PC" name="save_to_computer_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml
new file mode 100644
index 0000000000..12a648f600
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+	<string name="default_subject">
+		Postal do [SECOND_LIFE].
+	</string>
+	<string name="default_message">
+		Confira!
+	</string>
+	<string name="upload_message">
+		Enviando...
+	</string>
+	<text name="title">
+		E-mail
+	</text>
+	<button label="Mensagem" name="message_btn"/>
+	<button label="Configurações" name="settings_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_profile.xml
new file mode 100644
index 0000000000..095b8fc75d
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_snapshot_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_profile">
+	<text name="title">
+		Postar no feed do meu perfil
+	</text>
+	<combo_box label="Resolução" name="profile_size_combo">
+		<combo_box.item label="Janela atual" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Customizado" name="Custom"/>
+	</combo_box>
+	<layout_stack name="profile_image_params_ls">
+		<layout_panel name="profile_image_size_lp">
+			<spinner label="Largura" name="profile_snapshot_width"/>
+			<spinner label="Altura" name="profile_snapshot_height"/>
+			<check_box label="Limitar proporções" name="profile_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="profile_image_metadata_lp">
+			<text name="caption_label">
+				Legenda:
+			</text>
+			<check_box initial_value="true" label="Incluir local" name="add_location_cb"/>
+		</layout_panel>
+	</layout_stack>
+	<button label="Cancelar" name="cancel_btn"/>
+	<button label="Postar" name="post_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 6b4835e819..4babd9cc43 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -1160,7 +1160,7 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar
 		Você não possui uma cópia desta textura no seu inventário
 	</string>
 	<string name="InventoryInboxNoItems">
-		Compras do marketplace serão entregues aqui.
+		Quando você comprar ou receber um item, ele aparecerá aqui para que você possa arrastá-lo para uma pasta em seu inventário ou excluí-lo caso não queira mantê-lo.
 	</string>
 	<string name="MarketplaceURL">
 		http://marketplace.[DOMAIN_NAME]
@@ -1352,6 +1352,9 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar
 	<string name="no_attachments">
 		Nenhum anexo vestido
 	</string>
+	<string name="Attachments remain">
+		Anexos ([COUNT] slots permanecem)
+	</string>
 	<string name="Buy">
 		Comprar
 	</string>
@@ -1478,6 +1481,12 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar
 	<string name="Right Pec">
 		Peitoral D
 	</string>
+	<string name="Neck">
+		Pescoço
+	</string>
+	<string name="Avatar Center">
+		Centro do avatar
+	</string>
 	<string name="Invalid Attachment">
 		Ponto de encaixe inválido
 	</string>
@@ -3897,6 +3906,18 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 	<string name="you_paid_ldollars_no_name">
 		Você pagou L$[AMOUNT] por [REASON].
 	</string>
+	<string name="you_paid_failure_ldollars">
+		Você não pagou L$[AMOUNT] a [NAME] referentes a [REASON].
+	</string>
+	<string name="you_paid_failure_ldollars_no_info">
+		Você não pagou L$[AMOUNT].
+	</string>
+	<string name="you_paid_failure_ldollars_no_reason">
+		Você não pagou L$[AMOUNT] a [NAME].
+	</string>
+	<string name="you_paid_failure_ldollars_no_name">
+		Você não pagou L$[AMOUNT] referentes a [REASON].
+	</string>
 	<string name="for item">
 		por [ITEM]
 	</string>
@@ -4307,6 +4328,12 @@ Tente colocar o caminho do editor entre aspas.
 	<string name="ExternalEditorFailedToRun">
 		Falha de execução do editor externo.
 	</string>
+	<string name="TranslationFailed">
+		Falha na tradução: [REASON]
+	</string>
+	<string name="TranslationResponseParseError">
+		Erro ao analisar resposta de tradução.
+	</string>
 	<string name="Esc">
 		Esc
 	</string>
@@ -4677,7 +4704,7 @@ Tente colocar o caminho do editor entre aspas.
 		Mini Mapa
 	</string>
 	<string name="Command_Move_Label">
-		Mover
+		Andar/correr/voar
 	</string>
 	<string name="Command_People_Label">
 		Pessoas
@@ -4704,10 +4731,10 @@ Tente colocar o caminho do editor entre aspas.
 		Falar
 	</string>
 	<string name="Command_View_Label">
-		Exibir
+		Controles da câmera
 	</string>
 	<string name="Command_Voice_Label">
-		Voz próxima
+		Configurações de voz
 	</string>
 	<string name="Command_AboutLand_Tooltip">
 		Informações sobre o terreno que você está visitando
@@ -4779,7 +4806,16 @@ Tente colocar o caminho do editor entre aspas.
 		Alterar o ângulo da câmera
 	</string>
 	<string name="Command_Voice_Tooltip">
-		Pessoas próximas com recursos de voz
+		Controles de volume das chamadas e pessoas próximas a você no mundo virtual
+	</string>
+	<string name="Toolbar_Bottom_Tooltip">
+		atualmente na sua barra de ferramentas inferior
+	</string>
+	<string name="Toolbar_Left_Tooltip">
+		atualmente na sua barra de ferramentas esquerda
+	</string>
+	<string name="Toolbar_Right_Tooltip">
+		atualmente na sua barra de ferramentas direita
 	</string>
 	<string name="Retain%">
 		Reter%
@@ -4805,4 +4841,19 @@ Tente colocar o caminho do editor entre aspas.
 	<string name="Normal">
 		Normal
 	</string>
+	<string name="snapshot_quality_very_low">
+		Muito baixo
+	</string>
+	<string name="snapshot_quality_low">
+		Baixo
+	</string>
+	<string name="snapshot_quality_medium">
+		Médio
+	</string>
+	<string name="snapshot_quality_high">
+		Alto
+	</string>
+	<string name="snapshot_quality_very_high">
+		Muito alto
+	</string>
 </strings>
diff --git a/indra/newview/skins/default/xui/pt/teleport_strings.xml b/indra/newview/skins/default/xui/pt/teleport_strings.xml
index f8ded1ce69..3fb77a02d2 100644
--- a/indra/newview/skins/default/xui/pt/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/pt/teleport_strings.xml
@@ -19,8 +19,8 @@ Se você continuar a receber esta mensagem, por favor consulte o [SUPPORT_SITE].
 			Desculpe, não foi possível para o sistema executar o teletransporte. Tente novamente dentro de alguns instantes.
 		</message>
 		<message name="NoHelpIslandTP">
-		Você não pode se tele-transportar de volta à Ilha de Welcome.
-Vá para a Ilha de Welcome Pública para repetir este tutorial.
+			Não é possível se teletransportar de volta à Ilha Welcome.
+Vá para a &apos;Ilha Welcome Pública&apos; para repetir o tutorial.
 		</message>
 		<message name="noaccess_tport">
 			Desculpe, você não tem acesso ao destino deste teletransporte.
diff --git a/indra/newview/skins/default/xui/ru/floater_about.xml b/indra/newview/skins/default/xui/ru/floater_about.xml
index deb6be319c..119f104906 100644
--- a/indra/newview/skins/default/xui/ru/floater_about.xml
+++ b/indra/newview/skins/default/xui/ru/floater_about.xml
@@ -63,32 +63,34 @@
 		<panel label="Лицензии" name="licenses_panel">
 			<text_editor name="credits_editor">
 				3Dconnexion SDK (C) 1992-2007 3Dconnexion
-APR (C) 2000-2004 The Apache Software Foundation
-Collada DOM (C) 2005 Sony Computer Entertainment Inc.cURL (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
+        APR (C) 2000-2004 The Apache Software Foundation
+        Collada DOM (C) 2005 Sony Computer Entertainment Inc.
+        cURL (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
+        DBus/dbus-glib (C) 2002, 2003  CodeFactory AB / (C) 2003, 2004 Red Hat, Inc.
+        expat (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
+        FreeType (C) 1996-2002, The FreeType Project (www.freetype.org).
+        GL (C) 1999-2004 Brian Paul.
+        GLOD (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Университет Джона Гопкинса и David Luebke, Brenden Schubert, Университет Вирджинии.
+        google-perftools (c) 2005, Google Inc.
+        Havok.com(TM) (C) 1999-2001, Telekinesys Research Limited.
+        jpeg2000 (C) 2001, David Taubman, Университет Нового Южного Уэльса (UNSW)
+        jpeglib (C) 1991-1998, Thomas G. Lane.
+        ogg/vorbis (C) 2001, Xiphophorus
+        OpenSSL (C) 1998-2002 The OpenSSL Project.
+        PCRE (c) 1997-2008, Кембриджский университет
+        SDL (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+        SSLeay (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+        xmlrpc-epi (C) 2000 Epinions, Inc.
+        zlib (C) 1995-2002 Jean-loup Gailly и Mark Adler.
+        google-perftools (c) 2005, Google Inc.
 
-DBus/dbus-glib (C) 2002, 2003  CodeFactory AB / (C) 2003, 2004 Red Hat, Inc.
-expat (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
-FreeType (C) 1996-2002, The FreeType Project (www.freetype.org).
-GL (C) 1999-2004 Brian Paul.
-GLOD (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University и David Luebke, Brenden Schubert, Университет Вирджиинии.
-google-perftools (c) 2005, Google Inc.
-Havok.com(TM) (C) 1999-2001, Telekinesys Research Limited.
-jpeg2000 (C) 2001, David Taubman, Университет Нового Южного Уэльса (UNSW)
-jpeglib (C) 1991-1998, Thomas G. Lane.
-ogg/vorbis (C) 2001, Xiphophorus
-OpenSSL (C) 1998-2002 The OpenSSL Project.
-PCRE (c) 1997-2008, Кембриджский университет
-SDL (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
-SSLeay (C) 1995-1998 Eric Young (eay@cryptsoft.com)
-xmlrpc-epi (C) 2000 Epinions, Inc.
-zlib (C) 1995-2002 Jean-loup Gailly и Mark Adler.
-google-perftools (c) 2005, Google Inc.
+        В клиенте Second Life используется технология Havok (TM) Physics. (C) 1999-2010 Havok.com Inc. (и лицензиары компании). Все права защищены. Подробнее см. веб-сайт www.havok.com.
 
-В клиенте Second Life используется технология Havok (TM) Physics. (C) 1999-2010 Havok.com Inc. (и лицензиары компании). Все права защищены. Подробнее см. веб-сайт www.havok.com.
+        Это программное обеспечение содержит исходный код, предоставленный корпорацией NVIDIA.
 
-Все права защищены.  Подробные сведения см. в файле licenses.txt.
+        Все права защищены.  Подробные сведения см. в файле licenses.txt.
 
-Кодирование звука для голосового чата: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1, Приложение C)
+        Кодирование звука для голосового чата: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
 			</text_editor>
 		</panel>
 	</tab_container>
diff --git a/indra/newview/skins/default/xui/ru/floater_about_land.xml b/indra/newview/skins/default/xui/ru/floater_about_land.xml
index 3c278fce52..46414a530a 100644
--- a/indra/newview/skins/default/xui/ru/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ru/floater_about_land.xml
@@ -129,7 +129,7 @@
 				Посещаемость:
 			</text>
 			<text name="DwellText">
-				0
+				Загрузка...
 			</text>
 			<button label="Купить землю" name="Buy Land..."/>
 			<button label="Продать для Linden" name="Linden Sale..." tool_tip="Земля должна быть в собственности, иметь заданное содержимое и не быть выставленной на аукцион,"/>
@@ -307,13 +307,15 @@
 				Не толкать (настройки региона)
 			</panel.string>
 			<panel.string name="see_avs_text">
-				Видеть жителей этого участка и общаться с ними в чате
+				Аватары с других участков могут видеть
 			</panel.string>
 			<text name="allow_label">
 				Позволить другим жителям:
 			</text>
-			<check_box label="Изменить ландшафт" name="edit land check" tool_tip="Если отмечено, вашу землю сможет терраформировать кто угодно. Лучше не отмечать, так как вы всегда можете изменить вашу землю."/>
-			<check_box label="Полет" name="check fly" tool_tip="Если отмечено, жители смогут летать над вашей землей. Если не отметить, они смогут только прилетать и пролетать мимо земли."/>
+			<text name="allow_label0">
+				Полет:
+			</text>
+			<check_box label="Все" name="check fly" tool_tip="Если отмечено, жители смогут летать над вашей землей. Если не отметить, они смогут только прилетать и пролетать мимо земли."/>
 			<text name="allow_label2">
 				Строительство:
 			</text>
@@ -329,9 +331,6 @@
 			</text>
 			<check_box label="Все" name="check other scripts"/>
 			<check_box label="Группа" name="check group scripts"/>
-			<text name="land_options_label">
-				Параметры земли:
-			</text>
 			<check_box label="Безопасно (нет повреждений)" name="check safe" tool_tip="Если отмечено, то земля считается безопасной, отключены боевые повреждения. Если не отмечено, то боевые повреждения включены."/>
 			<check_box label="Не толкать" name="PushRestrictCheck" tool_tip="Запрещает скриптам функцию толкания. Этот параметр может оказаться полезным для предотвращения нежелательного поведения на вашей земле."/>
 			<check_box label="Показать место в поиске (L$30/неделя)" name="ShowDirectoryCheck" tool_tip="Позволить людям видеть участок в результатах поиска"/>
@@ -372,9 +371,9 @@
 			</text>
 			<texture_picker name="snapshot_ctrl" tool_tip="Щелкните для выбора изображения"/>
 			<text name="allow_label5">
-				Позволить жителям с других участков:
+				аватары на этом участке и общаться с ними
 			</text>
-			<check_box label="Видны аватары" name="SeeAvatarsCheck" tool_tip="Жители с других участков могут видеть жителей этого участка и общаться с ними в чате (вы также сможете видеть жителей с других участков и общаться с ними)."/>
+			<check_box label="Видны аватары" name="SeeAvatarsCheck" tool_tip="Аватары с других участков смогут видеть аватары на этом участке и общаться с ними в чате, а вы также сможете видеть их и общаться с ними."/>
 			<text name="landing_point">
 				В точку телепортации: [LANDING]
 			</text>
diff --git a/indra/newview/skins/default/xui/ru/floater_avatar.xml b/indra/newview/skins/default/xui/ru/floater_avatar.xml
index 6bdf819880..b480af9345 100644
--- a/indra/newview/skins/default/xui/ru/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/ru/floater_avatar.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Avatar" title="ВЫБОР АВАТАРА"/>
+<floater name="Avatar" title="ВЫБЕРИТЕ АВАТАР"/>
diff --git a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
index 7d34ca3274..87e8bd524e 100644
--- a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php способ оплаты] | [http://www.secondlife.com/my/account/currency.php валюта]
+		[http://www.secondlife.com/my/account/payment_method_management.php способ оплаты] | [http://www.secondlife.com/my/account/currency.php деньги]
 	</text>
 	<text name="exchange_rate_note">
 		Повторно введите сумму, чтобы увидеть новый обменный курс.
diff --git a/indra/newview/skins/default/xui/ru/floater_camera.xml b/indra/newview/skins/default/xui/ru/floater_camera.xml
index 945a63c0eb..52e7c62e06 100644
--- a/indra/newview/skins/default/xui/ru/floater_camera.xml
+++ b/indra/newview/skins/default/xui/ru/floater_camera.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="camera_floater" title="КАМЕРА">
+<floater name="camera_floater" title="УПРАВЛЕНИЕ КАМЕРОЙ">
 	<floater.string name="rotate_tooltip">
 		Повернуть камеру вокруг точки фокусировки
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml b/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml
index 0fefb76ea5..7400f1df3b 100644
--- a/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml
@@ -4,7 +4,7 @@
 		Фильтрация:
 	</text>
 	<check_box label="Анизотропная фильтрация (медленнее, если включено)" name="ani"/>
-	<text name="Antialiasing:">
+	<text name="antialiasing label">
 		Сглаживание:
 	</text>
 	<combo_box label="Сглаживание" name="fsaa">
diff --git a/indra/newview/skins/default/xui/ru/floater_model_preview.xml b/indra/newview/skins/default/xui/ru/floater_model_preview.xml
index 31517e722d..5bb96b8de4 100644
--- a/indra/newview/skins/default/xui/ru/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/ru/floater_model_preview.xml
@@ -4,6 +4,9 @@
 	<string name="status_parse_error">
 		Ошибка. Проблема при анализе файла DAE – см. подробности в журнале.
 	</string>
+	<string name="status_material_mismatch">
+		Ошибка. Материал модели не входит в эталонную модель.
+	</string>
 	<string name="status_reading_file">
 		Загрузка...
 	</string>
@@ -137,7 +140,7 @@
 				</panel>
 				<panel name="physics analysis">
 					<text name="method_label">
-						Шаг 2. Анализ
+						2 этап. Анализ
 					</text>
 					<text name="analysis_method_label">
 						Метод:
diff --git a/indra/newview/skins/default/xui/ru/floater_model_wizard.xml b/indra/newview/skins/default/xui/ru/floater_model_wizard.xml
index ef2fe8e5a5..5b03dd2c73 100644
--- a/indra/newview/skins/default/xui/ru/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/ru/floater_model_wizard.xml
@@ -20,6 +20,9 @@
 				Выберите файл модели для передачи
 			</text>
 			<button label="Обзор..." label_selected="Обзор..." name="browse"/>
+			<text name="Model types">
+				В Second Life поддерживаются файлы COLLADA (.dae)
+			</text>
 			<text name="dimensions">
 				X         Y         Z
 			</text>
diff --git a/indra/newview/skins/default/xui/ru/floater_moveview.xml b/indra/newview/skins/default/xui/ru/floater_moveview.xml
index 6e01f997e1..cb1fda1a1f 100644
--- a/indra/newview/skins/default/xui/ru/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/ru/floater_moveview.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move_floater" title="ПЕРЕМЕЩЕНИЕ">
+<floater name="move_floater" title="ХОДЬБА / БЕГ / ПОЛЕТ">
 	<string name="walk_forward_tooltip">
 		Идти вперед (нажмите стрелку вверх или клавишу W)
 	</string>
diff --git a/indra/newview/skins/default/xui/ru/floater_snapshot.xml b/indra/newview/skins/default/xui/ru/floater_snapshot.xml
index f85d602be7..7e88630b32 100644
--- a/indra/newview/skins/default/xui/ru/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/ru/floater_snapshot.xml
@@ -3,72 +3,63 @@
 	<floater.string name="unknown">
 		неизвестно
 	</floater.string>
-	<radio_group label="Тип снимка" name="snapshot_type_radio">
-		<radio_item label="Электронная почта" name="postcard"/>
-		<radio_item label="Мой инвентарь (L$[AMOUNT])" name="texture"/>
-		<radio_item label="Сохранить на моем компьютере" name="local"/>
-	</radio_group>
+	<string name="postcard_progress_str">
+		Отправка письма
+	</string>
+	<string name="profile_progress_str">
+		Публикация
+	</string>
+	<string name="inventory_progress_str">
+		Сохранение в -инвентарь
+	</string>
+	<string name="local_progress_str">
+		Сохранение на компьютере
+	</string>
+	<string name="profile_succeeded_str">
+		Изображение отправлено
+	</string>
+	<string name="postcard_succeeded_str">
+		Письмо отправлено!
+	</string>
+	<string name="inventory_succeeded_str">
+		Сохранено в инвентаре!
+	</string>
+	<string name="local_succeeded_str">
+		Сохранено на компьютере!
+	</string>
+	<string name="profile_failed_str">
+		Не удалось передать изображение в ваш профиль.
+	</string>
+	<string name="postcard_failed_str">
+		Не удалось отправить письмо.
+	</string>
+	<string name="inventory_failed_str">
+		Не удалось сохранить в инвентаре.
+	</string>
+	<string name="local_failed_str">
+		Не удалось сохранить на компьютере.
+	</string>
+	<button name="advanced_options_btn" tool_tip="Дополнительные параметры"/>
+	<text name="image_res_text">
+		[WIDTH] x [HEIGHT] пикс.
+	</text>
 	<text name="file_size_label">
 		[SIZE] КБ
 	</text>
-	<button label="Послать" name="send_btn"/>
-	<button label="Сохранить (L$[AMOUNT])" name="upload_btn"/>
-	<flyout_button label="Сохранить" name="save_btn" tool_tip="Сохранить изображение в файл">
-		<flyout_button.item label="Сохранить" name="save_item"/>
-		<flyout_button.item label="Сохранить как..." name="saveas_item"/>
-	</flyout_button>
-	<button label="Больше" name="more_btn" tool_tip="Дополнительные параметры"/>
-	<button label="Меньше" name="less_btn" tool_tip="Дополнительные параметры"/>
-	<button label="Отмена" name="discard_btn"/>
-	<text name="type_label2">
-		Размер
-	</text>
-	<text name="format_label">
-		Формат
-	</text>
-	<combo_box label="Разрешение" name="postcard_size_combo">
-		<combo_box.item label="Текущее окно" name="CurrentWindow"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="Задать" name="Custom"/>
-	</combo_box>
-	<combo_box label="Разрешение" name="texture_size_combo">
-		<combo_box.item label="Текущее окно" name="CurrentWindow"/>
-		<combo_box.item label="Маленький (128x128)" name="Small(128x128)"/>
-		<combo_box.item label="Средний (256x256)" name="Medium(256x256)"/>
-		<combo_box.item label="Большой (512x512)" name="Large(512x512)"/>
-		<combo_box.item label="Задать" name="Custom"/>
-	</combo_box>
-	<combo_box label="Разрешение" name="local_size_combo">
-		<combo_box.item label="Текущее окно" name="CurrentWindow"/>
-		<combo_box.item label="320x240" name="320x240"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="1280x1024" name="1280x1024"/>
-		<combo_box.item label="1600x1200" name="1600x1200"/>
-		<combo_box.item label="Задать" name="Custom"/>
-	</combo_box>
-	<combo_box label="Формат" name="local_format_combo">
-		<combo_box.item label="PNG" name="PNG"/>
-		<combo_box.item label="JPEG" name="JPEG"/>
-		<combo_box.item label="BMP" name="BMP"/>
-	</combo_box>
-	<spinner label="Ширина" name="snapshot_width"/>
-	<spinner label="Высота" name="snapshot_height"/>
-	<check_box label="Сохранять пропорции" name="keep_aspect_check"/>
-	<slider label="Качество изображения" name="image_quality_slider"/>
-	<text name="layer_type_label">
-		Захват:
-	</text>
-	<combo_box label="Слои изображения" name="layer_types">
-		<combo_box.item label="Цвета" name="Colors"/>
-		<combo_box.item label="Глубина" name="Depth"/>
-	</combo_box>
-	<check_box label="Интерфейс" name="ui_check"/>
-	<check_box label="HUD" name="hud_check"/>
-	<check_box label="Оставить окно открытым" name="keep_open_check"/>
-	<check_box label="Стоп-кадр (полноэкранный)" name="freeze_frame_check"/>
-	<check_box label="Автообновление" name="auto_snapshot_check"/>
+	<panel name="advanced_options_panel">
+		<text name="advanced_options_label">
+			ДОПОЛНИТЕЛЬНЫЕ ПАРАМЕТРЫ
+		</text>
+		<text name="layer_type_label">
+			Захват:
+		</text>
+		<combo_box label="Слои изображения" name="layer_types">
+			<combo_box.item label="Цвета" name="Colors"/>
+			<combo_box.item label="Глубина" name="Depth"/>
+		</combo_box>
+		<check_box label="Интерфейс" name="ui_check"/>
+		<check_box label="Данные в игре" name="hud_check"/>
+		<check_box label="Стоп-кадр (полноэкранный)" name="freeze_frame_check"/>
+		<check_box label="Автообновление" name="auto_snapshot_check"/>
+	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_toybox.xml b/indra/newview/skins/default/xui/ru/floater_toybox.xml
index 8d7431d393..a4754ad7ab 100644
--- a/indra/newview/skins/default/xui/ru/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/ru/floater_toybox.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Toybox" title="НАСТРОИТЬ ПАНЕЛИ ИНСТРУМЕНТОВ">
+<floater name="Toybox" title="КНОПКИ ПАНЕЛИ ИНСТРУМЕНТОВ">
 	<text name="toybox label 1">
 		Добавьте или удалите кнопки, перетягивая их на панели инструментов или с них.
 	</text>
 	<text name="toybox label 2">
 		Кнопки будут отображены в исходном виде или в виде значков, в зависимости от настроек каждой панели инструментов.
 	</text>
+	<button label="Очистить все панели" label_selected="Очистить все панели" name="btn_clear_all"/>
 	<button label="Вернуть стандартные" label_selected="Вернуть стандартные" name="btn_restore_defaults"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_translation_settings.xml b/indra/newview/skins/default/xui/ru/floater_translation_settings.xml
new file mode 100644
index 0000000000..ad280a50dd
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/floater_translation_settings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_translation_settings" title="НАСТРОЙКИ ПЕРЕВОДА ЧАТА">
+	<string name="bing_api_key_not_verified">
+		Bing appID не подтвержден. Повторите попытку.
+	</string>
+	<string name="google_api_key_not_verified">
+		Ключ Google API не подтвержден. Повторите попытку.
+	</string>
+	<string name="bing_api_key_verified">
+		Bing appID подтвержден.
+	</string>
+	<string name="google_api_key_verified">
+		Ключ Google API подтвержден.
+	</string>
+	<check_box label="Включить машинный перевод при чате" name="translate_chat_checkbox"/>
+	<text name="translate_language_label">
+		Переводить чат на:
+	</text>
+	<combo_box name="translate_language_combo">
+		<combo_box.item label="язык системы" name="System Default Language"/>
+		<combo_box.item label="английский" name="English"/>
+		<combo_box.item label="датский" name="Danish"/>
+		<combo_box.item label="немецкий" name="German"/>
+		<combo_box.item label="испанский" name="Spanish"/>
+		<combo_box.item label="французский" name="French"/>
+		<combo_box.item label="итальянский" name="Italian"/>
+		<combo_box.item label="венгерский" name="Hungarian"/>
+		<combo_box.item label="нидерландский" name="Dutch"/>
+		<combo_box.item label="польский" name="Polish"/>
+		<combo_box.item label="португальский" name="Portugese"/>
+		<combo_box.item label="русский" name="Russian"/>
+		<combo_box.item label="турецкий" name="Turkish"/>
+		<combo_box.item label="украинский" name="Ukrainian"/>
+		<combo_box.item label="китайский" name="Chinese"/>
+		<combo_box.item label="японский" name="Japanese"/>
+		<combo_box.item label="корейский" name="Korean"/>
+	</combo_box>
+	<text name="tip">
+		Выберите сервис перевода:
+	</text>
+	<radio_group name="translation_service_rg">
+		<radio_item initial_value="bing" label="Bing Translator" name="bing"/>
+		<radio_item initial_value="google" label="Google Translate" name="google"/>
+	</radio_group>
+	<text name="bing_api_key_label">
+		Bing [http://www.bing.com/developers/createapp.aspx AppID]:
+	</text>
+	<button label="Подтвердить" name="verify_bing_api_key_btn"/>
+	<text name="google_api_key_label">
+		Google [http://code.google.com/apis/language/translate/v2/getting_started.html#auth Ключ API]:
+	</text>
+	<button label="Подтвердить" name="verify_google_api_key_btn"/>
+	<text name="google_links_text">
+		[http://code.google.com/apis/language/translate/v2/pricing.html Цены] | [https://code.google.com/apis/console Статистика]
+	</text>
+	<button label="OK" name="ok_btn"/>
+	<button label="Отмена" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_voice_controls.xml b/indra/newview/skins/default/xui/ru/floater_voice_controls.xml
index c1fb858d48..2b23086062 100644
--- a/indra/newview/skins/default/xui/ru/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/ru/floater_voice_controls.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="floater_voice_controls" title="УПРАВЛЕНИЕ ГОЛОСОМ">
 	<string name="title_nearby">
-		Настройки голоса
+		НАСТРОЙКИ ГОЛОСА
 	</string>
 	<string name="title_group">
-		Звонок группе [GROUP]
+		ЗВОНОК ГРУППЕ [GROUP]
 	</string>
 	<string name="title_adhoc">
-		Конференция
+		КОНФЕРЕНЦИЯ
 	</string>
 	<string name="title_peer_2_peer">
-		Звонок пользователю [NAME]
+		ЗВОНОК ПОЛЬЗОВАТЕЛЮ [NAME]
 	</string>
 	<string name="no_one_near">
 		Нет никого с включенным голосом
diff --git a/indra/newview/skins/default/xui/ru/menu_toolbars.xml b/indra/newview/skins/default/xui/ru/menu_toolbars.xml
index e04a9ee57d..aa05dbc390 100644
--- a/indra/newview/skins/default/xui/ru/menu_toolbars.xml
+++ b/indra/newview/skins/default/xui/ru/menu_toolbars.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <context_menu name="Toolbars Popup">
-	<menu_item_call label="Выбор кнопок..." name="Chose Buttons"/>
+	<menu_item_call label="Удалить эту кнопку" name="Remove button"/>
+	<menu_item_call label="Кнопки панели инструментов..." name="Choose Buttons"/>
 	<menu_item_check label="Значки и подписи" name="icons_with_text"/>
 	<menu_item_check label="Только значки" name="icons_only"/>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/ru/menu_viewer.xml b/indra/newview/skins/default/xui/ru/menu_viewer.xml
index b9f403c04b..93d0166568 100644
--- a/indra/newview/skins/default/xui/ru/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ru/menu_viewer.xml
@@ -1,12 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <menu_bar name="Main Menu">
 	<menu label="Я" name="Me">
-		<menu_item_call label="Информационная панель..." name="Manage My Account"/>
 		<menu_item_call label="Профиль…" name="Profile"/>
 		<menu_item_call label="Внешность..." name="ChangeOutfit"/>
+		<menu_item_call label="Выберите аватар..." name="Avatar Picker"/>
 		<menu_item_check label="Инвентарь..." name="Inventory"/>
-		<menu_item_check label="Жесты..." name="Gestures"/>
-		<menu_item_check label="Голос..." name="ShowVoice"/>
+		<menu_item_call label="Новое окно инвентаря" name="NewInventoryWindow"/>
+		<menu_item_call label="Места..." name="Places"/>
+		<menu_item_call label="Подборка..." name="Picks"/>
+		<menu_item_call label="Управление камерой..." name="Camera Controls"/>
 		<menu label="Движение" name="Movement">
 			<menu_item_call label="Сесть" name="Sit Down Here"/>
 			<menu_item_check label="Полет" name="Fly"/>
@@ -20,34 +22,37 @@
 		<menu_item_call label="Запрос статуса администратора" name="Request Admin Options"/>
 		<menu_item_call label="Выход из статуса администратора" name="Leave Admin Options"/>
 		<menu_item_call label="Купить L$" name="Buy and Sell L$"/>
+		<menu_item_call label="Информационная панель аккаунта..." name="Manage My Account"/>
 		<menu_item_call label="Настройки..." name="Preferences"/>
-		<menu_item_call label="Панели инструментов..." name="Toolbars"/>
+		<menu_item_call label="Кнопки панели инструментов..." name="Toolbars"/>
 		<menu_item_call label="Скрыть все элементы управления" name="Hide UI"/>
 		<menu_item_call label="Выход из [APP_NAME]" name="Quit"/>
 	</menu>
 	<menu label="Общение" name="Communicate">
-		<menu_item_call label="Мои друзья" name="My Friends"/>
-		<menu_item_call label="Мои группы" name="My Groups"/>
-		<menu_item_check label="Локальный чат" name="Nearby Chat"/>
+		<menu_item_check label="Чат..." name="Nearby Chat"/>
+		<menu_item_check label="Говорить" name="Speak"/>
+		<menu_item_check label="Настройки голоса..." name="Nearby Voice"/>
+		<menu_item_check label="Изменение голоса..." name="ShowVoice"/>
+		<menu_item_check label="Жесты..." name="Gestures"/>
+		<menu_item_call label="Друзья" name="My Friends"/>
+		<menu_item_call label="Группы" name="My Groups"/>
 		<menu_item_call label="Люди неподалеку" name="Active Speakers"/>
-		<menu_item_check label="Голоса собеседников" name="Nearby Voice"/>
 	</menu>
 	<menu label="Мир" name="World">
-		<menu_item_check label="Миникарта" name="Mini-Map"/>
+		<menu_item_call label="Добавить закладку на это место" name="Create Landmark Here"/>
+		<menu_item_call label="Пункты..." name="Destinations"/>
 		<menu_item_check label="Карта мира" name="World Map"/>
+		<menu_item_check label="Миникарта" name="Mini-Map"/>
 		<menu_item_check label="Поиск" name="Search"/>
+		<menu_item_call label="Телепортация домой" name="Teleport Home"/>
+		<menu_item_call label="Установить дом здесь" name="Set Home to Here"/>
 		<menu_item_call label="Снимок" name="Take Snapshot"/>
-		<menu_item_call label="Добавить закладку на это место" name="Create Landmark Here"/>
-		<menu label="Профиль места" name="Land">
-			<menu_item_call label="Профиль места" name="Place Profile"/>
-			<menu_item_call label="О земле" name="About Land"/>
-			<menu_item_call label="Регион/землевладение" name="Region/Estate"/>
-		</menu>
+		<menu_item_call label="Профиль места" name="Place Profile"/>
+		<menu_item_call label="О земле" name="About Land"/>
+		<menu_item_call label="Регион/землевладение" name="Region/Estate"/>
+		<menu_item_call label="Мои владения..." name="My Land"/>
 		<menu_item_call label="Купить эту землю" name="Buy Land"/>
-		<menu_item_call label="Моя земля" name="My Land"/>
 		<menu label="Показать" name="LandShow">
-			<menu_item_check label="Панель движения" name="Movement Controls"/>
-			<menu_item_check label="Панель камеры" name="Camera Controls"/>
 			<menu_item_check label="Линии запрета" name="Ban Lines"/>
 			<menu_item_check label="Метки" name="beacons"/>
 			<menu_item_check label="Границы собственности" name="Property Lines"/>
@@ -56,16 +61,15 @@
 			<menu_item_check label="Свойства участка" name="Parcel Properties"/>
 			<menu_item_check label="Меню «Дополнительно»" name="Show Advanced Menu"/>
 		</menu>
-		<menu_item_call label="Телепортироваться домой" name="Teleport Home"/>
-		<menu_item_call label="Установить дом здесь" name="Set Home to Here"/>
 		<menu label="Солнце" name="Environment Settings">
 			<menu_item_call label="Восход" name="Sunrise"/>
 			<menu_item_call label="Полдень" name="Noon"/>
 			<menu_item_call label="Закат" name="Sunset"/>
 			<menu_item_call label="Полночь" name="Midnight"/>
+			<menu_item_call label="Использовать настройки региона" name="Use Region Settings"/>
 		</menu>
-		<menu label="Редактор среды" name="Enviroment Editor">
-			<menu_item_call label="Настройки среды..." name="Enviroment Settings"/>
+		<menu label="Редактор среды" name="Environment Editor">
+			<menu_item_call label="Настройки среды..." name="Environment Settings"/>
 			<menu label="Настройки воды" name="Water Presets">
 				<menu_item_call label="Создать настройку..." name="new_water_preset"/>
 				<menu_item_call label="Изменить настройку..." name="edit_water_preset"/>
@@ -144,6 +148,7 @@
 		<menu_item_call label="Вернуть" name="Redo"/>
 	</menu>
 	<menu label="Справка" name="Help">
+		<menu_item_call label="Инструкции..." name="How To"/>
 		<menu_item_call label="Справка по [SECOND_LIFE]" name="Second Life Help"/>
 		<menu_item_call label="Жалоба" name="Report Abuse"/>
 		<menu_item_call label="Сообщить об ошибке" name="Report Bug"/>
@@ -198,11 +203,10 @@
 		<menu_item_check label="Использовать поток для чтения подключаемых модулей" name="Use Plugin Read Thread"/>
 		<menu_item_call label="Очистить кэш группы" name="ClearGroupCache"/>
 		<menu_item_check label="Сглаживание мышью" name="Mouse Smoothing"/>
+		<menu_item_call label="Освободить клавиши" name="Release Keys"/>
 		<menu label="Горячие клавиши" name="Shortcuts">
 			<menu_item_call label="Изображение (L$[COST])..." name="Upload Image"/>
 			<menu_item_check label="Поиск" name="Search"/>
-			<menu_item_call label="Освободить клавиши" name="Release Keys"/>
-			<menu_item_call label="Сбросить размер интерфейса" name="Set UI Size to Default"/>
 			<menu_item_check label="Показать меню «Дополнительно» - старое сочетание клавиш" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Закрыть окно" name="Close Window"/>
 			<menu_item_call label="Закрыть все окна" name="Close All Windows"/>
@@ -288,6 +292,7 @@
 			<menu_item_check label="Освещение" name="Lights"/>
 			<menu_item_check label="Каркас столкновений" name="Collision Skeleton"/>
 			<menu_item_check label="Лучи" name="Raycast"/>
+			<menu_item_check label="Направления ветра" name="Wind Vectors"/>
 			<menu_item_check label="Сложность визуализации" name="rendercomplexity"/>
 			<menu_item_check label="Лепка" name="Sculpt"/>
 		</menu>
@@ -300,7 +305,6 @@
 			<menu_item_check label="Освещение и тени" name="Lighting and Shadows"/>
 			<menu_item_check label="Тени от солнца, луны и прожекторов" name="Shadows from Sun/Moon/Projectors"/>
 			<menu_item_check label="SSAO и сглаживание теней" name="SSAO and Shadow Smoothing"/>
-			<menu_item_check label="Повсеместное освещение (экспериментальное)" name="Global Illumination"/>
 			<menu_item_check label="Отладка GL" name="Debug GL"/>
 			<menu_item_check label="Отладка конвейера" name="Debug Pipeline"/>
 			<menu_item_check label="Автоматические альфа-маски (отложенные)" name="Automatic Alpha Masks (deferred)"/>
diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml
index f121743fe9..04f2f6b486 100644
--- a/indra/newview/skins/default/xui/ru/notifications.xml
+++ b/indra/newview/skins/default/xui/ru/notifications.xml
@@ -1110,8 +1110,13 @@
 	<notification name="DisplaySetToSafe">
 		Установлен безопасный уровень настроек отображения, так как указан параметр -safe.
 	</notification>
-	<notification name="DisplaySetToRecommended">
-		Установлен рекомендуемый уровень настроек отображения в соответствии с вашей системной конфигурацией.
+	<notification name="DisplaySetToRecommendedGPUChange">
+		Установлен рекомендуемый уровень настроек отображения, так как графическая карта изменена:
+с «[LAST_GPU]»
+на «[THIS_GPU]»
+	</notification>
+	<notification name="DisplaySetToRecommendedFeatureChange">
+		Установлен рекомендуемый уровень настроек отображения, так как подсистема визуализации изменена.
 	</notification>
 	<notification name="ErrorMessage">
 		[ERROR_MESSAGE]
@@ -1910,7 +1915,13 @@ http://secondlife.com/download.
 		<usetemplate ignoretext="Подтверждать перед выходом" name="okcancelignore" notext="Не выходить" yestext="Выйти"/>
 	</notification>
 	<notification name="ConfirmRestoreToybox">
-		Вы действительно хотите восстановить принятые по умолчанию кнопки и панели инструментов? 
+		Это действие приведет к восстановлению стандартных кнопок и панелей инструментов.
+
+Это действие нельзя отменить.
+		<usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/>
+	</notification>
+	<notification name="ConfirmClearAllToybox">
+		Это действие возвращает все кнопки в инструментарий, а панели инструментов становятся пустыми.
     
 Это действие нельзя отменить.
 		<usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/>
@@ -2236,14 +2247,16 @@ http://secondlife.com/download.
 		Ваша визитка отклонена.
 	</notification>
 	<notification name="TeleportToLandmark">
-		Вы можете телепортироваться в такие места, как «[NAME]», открыв панель «Места» в правой части экрана и выбрав вкладку «Закладки».
-Щелкните любую закладку, чтобы выбрать ее, а затем нажмите кнопку «Телепортация» внизу панели.
-(Также можно дважды щелкнуть закладку или щелкнуть ее правой кнопкой мыши и выбрать команду «Телепортация».)
+		Для телепортации в другое место, например «[NAME]», нажмите кнопку «Места»,
+    затем в открывшемся окне выберите вкладку «Закладки». Щелкните любую
+    закладку, чтобы выбрать ее, а затем нажмите кнопку «Телепортация» внизу окна.
+    (Также можно дважды щелкнуть закладку или щелкнуть ее правой кнопкой мыши и
+    выбрать команду «Телепортация».)
 	</notification>
 	<notification name="TeleportToPerson">
-		Вы можете общаться с такими жителями, как «[NAME]», открыв панель «Люди» в правой части экрана.
-Выберите в списке нужного жителя, а затем нажмите кнопку «IM» внизу панели.
-(Также можно дважды щелкнуть имя жителя в списке или щелкнуть ее правой кнопкой мыши и выбрать команду «IM».)
+		Чтобы обратиться к жителю, например «[NAME]», нажмите кнопку «Люди», выберите жителя в появившемся окне и нажмите кнопку
+    «IM» внизу окна.
+    (Также можно дважды щелкнуть имя жителя в списке или щелкнуть его правой кнопкой мыши и выбрать команду «IM».)
 	</notification>
 	<notification name="CantSelectLandFromMultipleRegions">
 		Нельзя выбрать землю с обеих сторон границы между серверами.
@@ -2264,6 +2277,9 @@ http://secondlife.com/download.
 	<notification name="PaymentSent">
 		[MESSAGE]
 	</notification>
+	<notification name="PaymentFailure">
+		[MESSAGE]
+	</notification>
 	<notification name="EventNotification">
 		Уведомление о событии:
 
@@ -2798,7 +2814,7 @@ http://secondlife.com/download.
 Со следующими жителями:
 
 [RESIDENTS]
-		<usetemplate name="okcancelbuttons" notext="Отмена" yestext="ОК"/>
+		<usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/>
 	</notification>
 	<notification name="ItemsShared">
 		Предметы успешно розданы.
@@ -2888,7 +2904,7 @@ http://secondlife.com/download.
 позже, даже после того, как вы покинули разговор.
 
 Заглушить всех?
-		<usetemplate ignoretext="Подтверждать перед заглушением всех участников группового разговора" name="okcancelignore" notext="Отмена" yestext="ОК"/>
+		<usetemplate ignoretext="Подтверждать перед заглушением всех участников группового разговора" name="okcancelignore" notext="Отмена" yestext="OK"/>
 	</notification>
 	<notification label="Чат" name="HintChat">
 		Чтобы присоединиться к чату, введите слова в поле чата ниже.
diff --git a/indra/newview/skins/default/xui/ru/panel_edit_skin.xml b/indra/newview/skins/default/xui/ru/panel_edit_skin.xml
index ac7e74316e..f5a5339afe 100644
--- a/indra/newview/skins/default/xui/ru/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/ru/panel_edit_skin.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_skin_panel">
 	<panel name="avatar_skin_color_panel">
-		<texture_picker label="Тату на голове" name="Head Tattoos" tool_tip="Щелкните для выбора изображения"/>
-		<texture_picker label="Тату на верхних частях тела" name="Upper Tattoos" tool_tip="Щелкните для выбора изображения"/>
-		<texture_picker label="Тату на нижних частях тела" name="Lower Tattoos" tool_tip="Щелкните для выбора изображения"/>
+		<texture_picker label="Голова" name="Head" tool_tip="Щелкните для выбора изображения"/>
+		<texture_picker label="Верхняя часть тела" name="Upper Body" tool_tip="Щелкните для выбора изображения"/>
+		<texture_picker label="Нижняя часть тела" name="Lower Body" tool_tip="Щелкните для выбора изображения"/>
 	</panel>
 	<panel name="accordion_panel">
 		<accordion name="wearable_accordion">
diff --git a/indra/newview/skins/default/xui/ru/panel_nearby_chat.xml b/indra/newview/skins/default/xui/ru/panel_nearby_chat.xml
index 1d26eecf87..8e3aac38d2 100644
--- a/indra/newview/skins/default/xui/ru/panel_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/ru/panel_nearby_chat.xml
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="nearby_chat">
-	<check_box label="Перевод чата" name="translate_chat_checkbox"/>
+	<check_box label="Переводить чат" name="translate_chat_checkbox"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_postcard_message.xml b/indra/newview/skins/default/xui/ru/panel_postcard_message.xml
new file mode 100644
index 0000000000..70587d8090
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_postcard_message.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_message">
+	<text name="to_label">
+		Кому:
+	</text>
+	<text name="name_label">
+		От:
+	</text>
+	<text name="subject_label">
+		Тема:
+	</text>
+	<line_editor label="Введите тему письма." name="subject_form"/>
+	<text name="msg_label">
+		Сообщение:
+	</text>
+	<text_editor name="msg_form">
+		Введите текст письма.
+	</text_editor>
+	<button label="Отмена" name="cancel_btn"/>
+	<button label="Послать" name="send_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_postcard_settings.xml b/indra/newview/skins/default/xui/ru/panel_postcard_settings.xml
new file mode 100644
index 0000000000..dc9d59008f
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_postcard_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_settings">
+	<combo_box label="Размер" name="postcard_size_combo">
+		<combo_box.item label="Текущее окно" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Задать" name="Custom"/>
+	</combo_box>
+	<layout_stack name="postcard_image_params_ls">
+		<layout_panel name="postcard_image_size_lp">
+			<spinner label="Ширина" name="postcard_snapshot_width"/>
+			<spinner label="Высота" name="postcard_snapshot_height"/>
+			<check_box label="Сохранять пропорции" name="postcard_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="postcard_image_format_quality_lp">
+			<slider label="Качество изображения" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml b/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml
index a3ee5b7815..a9d5569c7f 100644
--- a/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml
@@ -29,29 +29,5 @@
 	<check_box label="Текстовые чаты" name="EnableIMChatPopups" tool_tip="Отображать всплывающие уведомления при получении IM-сообщений"/>
 	<spinner label="Время отображения всплывающих реплик:" name="nearby_toasts_lifetime"/>
 	<spinner label="Время затухания всплывающих реплик:" name="nearby_toasts_fadingtime"/>
-	<text name="translate_chb_label">
-		Использовать машинный перевод при общении
-	</text>
-	<text name="translate_language_text">
-		Переводить чат на:
-	</text>
-	<combo_box name="translate_language_combobox">
-		<combo_box.item label="Язык системы" name="System Default Language"/>
-		<combo_box.item label="English" name="English"/>
-		<combo_box.item label="Dansk" name="Danish"/>
-		<combo_box.item label="Deutsch" name="German"/>
-		<combo_box.item label="Español" name="Spanish"/>
-		<combo_box.item label="Français" name="French"/>
-		<combo_box.item label="Italiano" name="Italian"/>
-		<combo_box.item label="Magyar" name="Hungarian"/>
-		<combo_box.item label="Nederlands" name="Dutch"/>
-		<combo_box.item label="Polski" name="Polish"/>
-		<combo_box.item label="Português" name="Portugese"/>
-		<combo_box.item label="Русский" name="Russian"/>
-		<combo_box.item label="Türkçe" name="Turkish"/>
-		<combo_box.item label="Українська" name="Ukrainian"/>
-		<combo_box.item label="中文 (简体) (китайский)" name="Chinese"/>
-		<combo_box.item label="日本語 (Japanese)" name="Japanese"/>
-		<combo_box.item label="한국어 (Korean)" name="Korean"/>
-	</combo_box>
+	<button label="Настройки перевода чата" name="ok_btn"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_general.xml b/indra/newview/skins/default/xui/ru/panel_preferences_general.xml
index 49f743a6ba..d1bfedf2d8 100644
--- a/indra/newview/skins/default/xui/ru/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_general.xml
@@ -16,7 +16,7 @@
 		<combo_box.item label="Русский (бета-версия)" name="Russian"/>
 		<combo_box.item label="Türkçe - турецкий (бета-версия)" name="Turkish"/>
 		<combo_box.item label="日本語 – японский (бета-версия)" name="(Japanese)"/>
-		<combo_box.item label="正體中文 - китайский, традиционное письмо (бета-версия)" name="Traditional Chinese"/>
+		<combo_box.item label="китайский, традиционное письмо - бета-версия" name="Traditional Chinese"/>
 	</combo_box>
 	<text name="language_textbox2">
 		(Требуется перезапуск)
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml b/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml
index db88189169..8e7fc71f0d 100644
--- a/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml
@@ -15,7 +15,7 @@
 		Браузер:
 	</text>
 	<radio_group name="use_external_browser">
-		<radio_item label="Использовать мой браузер (IE, Firefox, Safari)" name="external" tool_tip="Будет использоваться браузер, заданный в системе по умолчанию. Не рекомендуется, если [APP_NAME] работает в полноэкранном режиме." value="1"/>
+		<radio_item label="Использовать мой браузер (IE, Firefox, Safari)" name="external" tool_tip="Будет использоваться браузер, заданный в системе по умолчанию. Не рекомендуется, если [APP_NAME] работает в полноэкранном режиме." value="true"/>
 		<radio_item label="Использовать встроенный браузер" name="internal" tool_tip="Для просмотра справки, ссылок на веб-страницы и т. д. будет использоваться встроенный браузер. Этот браузер открывается как новое окно в [APP_NAME]." value=""/>
 	</radio_group>
 	<check_box initial_value="истина" label="Разрешить плагины" name="browser_plugins_enabled"/>
diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml
new file mode 100644
index 0000000000..53a150c9f9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_inventory">
+	<text name="title">
+		Сохранить в моем инвентаре
+	</text>
+	<text name="hint_lbl">
+		Сохранение изображения в инвентаре стоит L$[UPLOAD_COST]. Чтобы сохранить его как текстуру, выберите один из квадратных форматов.
+	</text>
+	<combo_box label="Размер" name="texture_size_combo">
+		<combo_box.item label="Текущее окно" name="CurrentWindow"/>
+		<combo_box.item label="Маленький (128x128)" name="Small(128x128)"/>
+		<combo_box.item label="Средний (256x256)" name="Medium(256x256)"/>
+		<combo_box.item label="Большой (512x512)" name="Large(512x512)"/>
+		<combo_box.item label="Задать" name="Custom"/>
+	</combo_box>
+	<spinner label="Ширина" name="inventory_snapshot_width"/>
+	<spinner label="Высота" name="inventory_snapshot_height"/>
+	<check_box label="Сохранять пропорции" name="inventory_keep_aspect_check"/>
+	<button label="Отмена" name="cancel_btn"/>
+	<button label="Сохранить" name="save_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_local.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_local.xml
new file mode 100644
index 0000000000..446b9bb2fd
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_snapshot_local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_local">
+	<text name="title">
+		Сохранить на моем компьютере
+	</text>
+	<combo_box label="Размер" name="local_size_combo">
+		<combo_box.item label="Текущее окно" name="CurrentWindow"/>
+		<combo_box.item label="320x240" name="320x240"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="1280x1024" name="1280x1024"/>
+		<combo_box.item label="1600x1200" name="1600x1200"/>
+		<combo_box.item label="Задать" name="Custom"/>
+	</combo_box>
+	<layout_stack name="local_image_params_ls">
+		<layout_panel name="local_image_size_lp">
+			<spinner label="Ширина" name="local_snapshot_width"/>
+			<spinner label="Высота" name="local_snapshot_height"/>
+			<check_box label="Сохранять пропорции" name="local_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="local_image_format_quality_lp">
+			<combo_box label="Формат" name="local_format_combo">
+				<combo_box.item label="PNG (без потерь)" name="PNG"/>
+				<combo_box.item label="JPEG" name="JPEG"/>
+				<combo_box.item label="BMP (без потерь)" name="BMP"/>
+			</combo_box>
+			<slider label="Качество изображения" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+	<button label="Отмена" name="cancel_btn"/>
+	<flyout_button label="Сохранить" name="save_btn" tool_tip="Сохранить изображение в файл">
+		<flyout_button.item label="Сохранить" name="save_item"/>
+		<flyout_button.item label="Сохранить как..." name="saveas_item"/>
+	</flyout_button>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_options.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_options.xml
new file mode 100644
index 0000000000..250a76cd21
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_snapshot_options.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_options">
+	<button label="Поместить в мой профиль" name="save_to_profile_btn"/>
+	<button label="Отправить по почте" name="save_to_email_btn"/>
+	<button label="Сохранить в моем инвентаре (L$[AMOUNT])" name="save_to_inventory_btn"/>
+	<button label="Сохранить на моем компьютере" name="save_to_computer_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml
new file mode 100644
index 0000000000..47f4caf8e3
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+	<string name="default_subject">
+		Открытка из [SECOND_LIFE].
+	</string>
+	<string name="default_message">
+		Побывай здесь!
+	</string>
+	<string name="upload_message">
+		Отправка...
+	</string>
+	<text name="title">
+		Электронное письмо
+	</text>
+	<button label="Сообщение" name="message_btn"/>
+	<button label="Настройки" name="settings_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_profile.xml
new file mode 100644
index 0000000000..79a9ef58d0
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_snapshot_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_profile">
+	<text name="title">
+		Поместить в мой профиль
+	</text>
+	<combo_box label="Размер" name="profile_size_combo">
+		<combo_box.item label="Текущее окно" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Задать" name="Custom"/>
+	</combo_box>
+	<layout_stack name="profile_image_params_ls">
+		<layout_panel name="profile_image_size_lp">
+			<spinner label="Ширина" name="profile_snapshot_width"/>
+			<spinner label="Высота" name="profile_snapshot_height"/>
+			<check_box label="Сохранять пропорции" name="profile_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="profile_image_metadata_lp">
+			<text name="caption_label">
+				Подпись:
+			</text>
+			<check_box initial_value="true" label="Включить расположение" name="add_location_cb"/>
+		</layout_panel>
+	</layout_stack>
+	<button label="Отмена" name="cancel_btn"/>
+	<button label="Опубликовать" name="post_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml
index 7fef5797a9..6d954139ff 100644
--- a/indra/newview/skins/default/xui/ru/strings.xml
+++ b/indra/newview/skins/default/xui/ru/strings.xml
@@ -1211,7 +1211,7 @@ support@secondlife.com.
 		В вашем инвентаре нет копии этой текстуры
 	</string>
 	<string name="InventoryInboxNoItems">
-		Покупки из торгового центра будут доставлены сюда.
+		Если вы купите или как-то иначе получите предмет, он появится здесь. Его можно будет перетащить в папку вашего инвентаря или удалить, если он больше не нужен.
 	</string>
 	<string name="MarketplaceURL">
 		http://marketplace.[DOMAIN_NAME]
@@ -1409,6 +1409,9 @@ support@secondlife.com.
 	<string name="no_attachments">
 		Нет прикрепленных объектов
 	</string>
+	<string name="Attachments remain">
+		Присоединения (осталось гнезд: [COUNT])
+	</string>
 	<string name="Buy">
 		Купить
 	</string>
@@ -1535,6 +1538,12 @@ support@secondlife.com.
 	<string name="Right Pec">
 		Правая грудь
 	</string>
+	<string name="Neck">
+		Шея
+	</string>
+	<string name="Avatar Center">
+		Центр аватара
+	</string>
 	<string name="Invalid Attachment">
 		Неверная точка присоединения
 	</string>
@@ -4024,6 +4033,18 @@ support@secondlife.com.
 	<string name="you_paid_ldollars_no_name">
 		Вы заплатили L$[AMOUNT] за [REASON].
 	</string>
+	<string name="you_paid_failure_ldollars">
+		Вы не смогли заплатить пользователю [NAME] L$[AMOUNT]: [REASON].
+	</string>
+	<string name="you_paid_failure_ldollars_no_info">
+		Вы не смогли заплатить L$[AMOUNT]
+	</string>
+	<string name="you_paid_failure_ldollars_no_reason">
+		Вы не смогли заплатить пользователю [NAME] L$[AMOUNT]
+	</string>
+	<string name="you_paid_failure_ldollars_no_name">
+		Вы не смогли заплатить L$[AMOUNT]: [REASON].
+	</string>
 	<string name="for item">
 		за [ITEM]
 	</string>
@@ -4433,6 +4454,12 @@ support@secondlife.com.
 	<string name="ExternalEditorFailedToRun">
 		Не удалось запустить внешний редактор.
 	</string>
+	<string name="TranslationFailed">
+		Ошибка телепортации: [REASON]
+	</string>
+	<string name="TranslationResponseParseError">
+		Ошибка при анализе ответа переводчика.
+	</string>
 	<string name="Esc">
 		ESC
 	</string>
@@ -4815,7 +4842,7 @@ support@secondlife.com.
 		Миникарта
 	</string>
 	<string name="Command_Move_Label">
-		Переместить
+		Ходьба / бег / полет
 	</string>
 	<string name="Command_People_Label">
 		Люди
@@ -4842,7 +4869,7 @@ support@secondlife.com.
 		Говорить
 	</string>
 	<string name="Command_View_Label">
-		Вид
+		Управление камерой
 	</string>
 	<string name="Command_Voice_Label">
 		Настройки голоса
@@ -4917,7 +4944,16 @@ support@secondlife.com.
 		Изменение угла камеры
 	</string>
 	<string name="Command_Voice_Tooltip">
-		Громкость звонков и голосов окружающих вас людей
+		Регулировка громкости вызовов и разговоров с людьми около вас
+	</string>
+	<string name="Toolbar_Bottom_Tooltip">
+		сейчас на нижней панели инструментов
+	</string>
+	<string name="Toolbar_Left_Tooltip">
+		сейчас на левой панели инструментов
+	</string>
+	<string name="Toolbar_Right_Tooltip">
+		сейчас на правой панели инструментов
 	</string>
 	<string name="Retain%">
 		Остаток%
@@ -4943,4 +4979,19 @@ support@secondlife.com.
 	<string name="Normal">
 		Нормальный
 	</string>
+	<string name="snapshot_quality_very_low">
+		Очень низкий
+	</string>
+	<string name="snapshot_quality_low">
+		Низкий
+	</string>
+	<string name="snapshot_quality_medium">
+		Средний
+	</string>
+	<string name="snapshot_quality_high">
+		Высокий
+	</string>
+	<string name="snapshot_quality_very_high">
+		Очень высокий
+	</string>
 </strings>
diff --git a/indra/newview/skins/default/xui/ru/teleport_strings.xml b/indra/newview/skins/default/xui/ru/teleport_strings.xml
index 296562e6f1..feff286111 100644
--- a/indra/newview/skins/default/xui/ru/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/ru/teleport_strings.xml
@@ -21,8 +21,8 @@
 Повторите попытку позже.
 		</message>
 		<message name="NoHelpIslandTP">
-		Вы не можете телепортироваться обратно на Остров Помощи.
-Телепортируйтесь на Общественный Остров Помощи, чтобы повторить обучение
+			Телепортироваться назад на Остров прибытия нельзя.
+Для повторения учебника перейдите на «Остров прибытия - общий».
 		</message>
 		<message name="noaccess_tport">
 			У вас нет доступа к точке назначения этого телепорта.
diff --git a/indra/newview/skins/default/xui/tr/floater_about.xml b/indra/newview/skins/default/xui/tr/floater_about.xml
index 993ec42958..8fa12ea759 100644
--- a/indra/newview/skins/default/xui/tr/floater_about.xml
+++ b/indra/newview/skins/default/xui/tr/floater_about.xml
@@ -64,32 +64,34 @@ Ses Sunucusu Sürümü: [VOICE_VERSION]
 		<panel label="Lisanslar" name="licenses_panel">
 			<text_editor name="credits_editor">
 				3Dconnexion SDK Telif Hakkı (C) 1992-2007 3Dconnexion
-APR Telif Hakkı (C) 2000-2004 The Apache Software Foundation
-Collada DOM Telif Hakkı 2005 Sony Computer Entertainment Inc.
-cURL Telif Hakkı (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
-DBus/dbus-glib Telif Hakkı (C) 2002, 2003  CodeFactory AB / Telif Hakkı (C) 2003, 2004 Red Hat, Inc.
-expat Telif Hakkı (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
-FreeType Telif Hakkı (C) 1996-2002, The FreeType Project (www.freetype.org).
-GL Telif Hakkı (C) 1999-2004 Brian Paul.
-GLOD Telif Hakkı (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University ve David Luebke, Brenden Schubert, University of Virginia.
-google-perftools Telif Hakkı (c) 2005, Google Inc.
-Havok.com(TM) Telif Hakkı (C) 1999-2001, Telekinesys Research Limited.
-jpeg2000 Telif Hakkı (C) 2001, David Taubman, The University of New South Wales (UNSW)
-jpeglib Telif Hakkı (C) 1991-1998, Thomas G. Lane.
-ogg/vorbis Telif Hakkı (C) 2001, Xiphophorus
-OpenSSL Telif Hakkı (C) 1998-2002 The OpenSSL Project.
-PCRE Telif Hakkı (c) 1997-2008 University of Cambridge
-SDL Telif Hakkı (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
-SSLeay Telif Hakkı (C) 1995-1998 Eric Young (eay@cryptsoft.com)
-xmlrpc-epi Telif Hakkı (C) 2000 Epinions, Inc.
-zlib Telif Hakkı (C) 1995-2002 Jean-loup Gailly ve Mark Adler.
-google-perftools Telif Hakkı (c) 2005, Google Inc.
+        APR Telif Hakkı (C) 2000-2004 The Apache Software Foundation
+        Collada DOM Telif Hakkı 2005 Sony Computer Entertainment Inc.
+        cURL Telif Hakkı (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
+        DBus/dbus-glib Telif Hakkı (C) 2002, 2003  CodeFactory AB / Telif Hakkı (C) 2003, 2004 Red Hat, Inc.
+        expat Telif Hakkı (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
+        FreeType Telif Hakkı (C) 1996-2002, The FreeType Project (www.freetype.org).
+        GL Telif Hakkı (C) 1999-2004 Brian Paul.
+        GLOD Telif Hakkı (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University ve David Luebke, Brenden Schubert, University of Virginia.
+        google-perftools Telif Hakkı (c) 2005, Google Inc.
+        Havok.com(TM) Telif Hakkı (C) 1999-2001, Telekinesys Research Limited.
+        jpeg2000 Telif Hakkı (C) 2001, David Taubman, The University of New South Wales (UNSW)
+        jpeglib Telif Hakkı (C) 1991-1998, Thomas G. Lane.
+        ogg/vorbis Telif Hakkı (C) 2001, Xiphophorus
+        OpenSSL Telif Hakkı (C) 1998-2002 The OpenSSL Project.
+        PCRE Telif Hakkı (c) 1997-2008 University of Cambridge
+        SDL Telif Hakkı (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+        SSLeay Telif Hakkı (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+        xmlrpc-epi Telif Hakkı (C) 2000 Epinions, Inc.
+        zlib Telif Hakkı (C) 1995-2002 Jean-loup Gailly ve Mark Adler.
+        google-perftools Telif Hakkı (c) 2005, Google Inc.
 
-Second Life Görüntüleyicisi Havok (TM) Fizik motorunu kullanmaktadır. (c)Telif Hakkı 1999-2010 Havok.com Inc. (ve Lisans Verenleri). Tüm Hakları Saklıdır. Ayrıntılı bilgi için bkz. www.havok.com
+        Second Life Görüntüleyicisi Havok (TM) Fizik motorunu kullanmaktadır. (c)Telif Hakkı 1999-2010 Havok.com Inc. (ve Lisans Verenleri). Tüm Hakları Saklıdır. Ayrıntılı bilgi için bkz. www.havok.com
 
-Tüm hakları saklıdır.  Ayrıntılı bilgi için bkz. licenses.txt
+        Bu yazılımda NVIDIA Corporation tarafından sağlanan kaynak kod yer almaktadır.
 
-Sesli sohbet için Ses kodlaması: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
+        Tüm hakları saklıdır.  Ayrıntılı bilgi için bkz. licenses.txt
+
+        Sesli sohbet için Ses kodlaması: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
 			</text_editor>
 		</panel>
 	</tab_container>
diff --git a/indra/newview/skins/default/xui/tr/floater_about_land.xml b/indra/newview/skins/default/xui/tr/floater_about_land.xml
index e0350964b5..dde658d64d 100644
--- a/indra/newview/skins/default/xui/tr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/tr/floater_about_land.xml
@@ -129,7 +129,7 @@
 				Trafik:
 			</text>
 			<text name="DwellText">
-				0
+				Yükleniyor...
 			</text>
 			<button label="Arazi Satın Al" name="Buy Land..."/>
 			<button label="Linden Satışı" name="Linden Sale..." tool_tip="Arazinin sahip olunması, içeriğinin ayarlanması ve ihaleye çıkmamış olması gerekir"/>
@@ -307,13 +307,15 @@ Sadece büyük parseller aramada görünür.
 				İtme Yok (Bölge Geçersiz Kılma)
 			</panel.string>
 			<panel.string name="see_avs_text">
-				Parseldeki sakinleri gör ve onlarla sohbet et
+				Diğer parsellerdeki avatarlar bu
 			</panel.string>
 			<text name="allow_label">
 				Sakinlere şunun için izin ver:
 			</text>
-			<check_box label="Yüzeyi Düzenle" name="edit land check" tool_tip="İşaretliyse herkes arazinizi şekillendirebilir. en iyisi bunu işaretlememektir, çünkü kendi arazinizi her zaman düzenleyebilirsiniz."/>
-			<check_box label="Uç" name="check fly" tool_tip="İşaretliyse Sakinler arazinizden uçabilir. İşaretli değilse, sadece arazinize ve arazinizin üzerinde uçabilir."/>
+			<text name="allow_label0">
+				Uçma:
+			</text>
+			<check_box label="Herkes" name="check fly" tool_tip="İşaretliyse Sakinler arazinizden uçabilir. İşaretli değilse, sadece arazinize ve arazinizin üzerinde uçabilir."/>
 			<text name="allow_label2">
 				İnşa Et:
 			</text>
@@ -329,9 +331,6 @@ Sadece büyük parseller aramada görünür.
 			</text>
 			<check_box label="Herkes" name="check other scripts"/>
 			<check_box label="Grup" name="check group scripts"/>
-			<text name="land_options_label">
-				Arazi Seçenekleri:
-			</text>
 			<check_box label="Güvenli (hasar yok)" name="check safe" tool_tip="İşaretliyse, araziyi Güvenli moda getirerek hasar çarpışmasını etkinsizleştirir İşaretli değilse hasar çarpışması etkinleşir."/>
 			<check_box label="İtme Yok" name="PushRestrictCheck" tool_tip="Komut dosyalarının itmesini önler Bu seçeneğin işaretlenmesi arazinizdeki bozucu davranışları önlemeye yardımcı olabilir."/>
 			<check_box label="Konumu Arama sonuçlarında göster (L$30/hafta)" name="ShowDirectoryCheck" tool_tip="Arama sonuçlarında bu parsel görünsün"/>
@@ -372,9 +371,9 @@ Sadece büyük parseller aramada görünür.
 			</text>
 			<texture_picker name="snapshot_ctrl" tool_tip="Bir resim seçmek için tıklayın"/>
 			<text name="allow_label5">
-				Diğer parsel Sakinlerine şunun için izin verin:
+				bu parseldeki avatarları görebilir ve onlarla sohbet edebilir
 			</text>
-			<check_box label="Avatarları Gör" name="SeeAvatarsCheck" tool_tip="Diğer parsellerdeki sakinlerin bu parseldeki sakinleri görmesine ve onlarla sohbet etmesine, sizin de onları görüp, onlarla sohbet etmenize imkan tanır."/>
+			<check_box label="Avatarları Gör" name="SeeAvatarsCheck" tool_tip="Diğer parsellerdeki avatarların bu parseldeki avatarları görmesine ve onlarla sohbet etmesine, sizin de onları görüp, onlarla sohbet etmenize imkan tanır."/>
 			<text name="landing_point">
 				İniş Noktası: [LANDING]
 			</text>
diff --git a/indra/newview/skins/default/xui/tr/floater_avatar.xml b/indra/newview/skins/default/xui/tr/floater_avatar.xml
index fc9e3c8a9b..c6b14ba710 100644
--- a/indra/newview/skins/default/xui/tr/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/tr/floater_avatar.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Avatar" title="AVATAR SEÇİCİ"/>
+<floater name="Avatar" title="BİR AVATAR SEÇİN"/>
diff --git a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
index 6608fd72e1..d90985dcff 100644
--- a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php ödeme yöntemi] | [http://www.secondlife.com/my/account/currency.php para birimi
+		[http://www.secondlife.com/my/account/payment_method_management.php ödeme yöntemi] | [http://www.secondlife.com/my/account/currency.php para birimi]
 	</text>
 	<text name="exchange_rate_note">
 		En son döviz kurunu görmek için miktarı yeniden girin.
diff --git a/indra/newview/skins/default/xui/tr/floater_camera.xml b/indra/newview/skins/default/xui/tr/floater_camera.xml
index c92d4e9db4..22e2aa52c6 100644
--- a/indra/newview/skins/default/xui/tr/floater_camera.xml
+++ b/indra/newview/skins/default/xui/tr/floater_camera.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="camera_floater" title="GÖSTER">
+<floater name="camera_floater" title="KAMERA DENETİMLERİ">
 	<floater.string name="rotate_tooltip">
 		Odak Etrafında Kamerayı Döndür
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/tr/floater_hardware_settings.xml b/indra/newview/skins/default/xui/tr/floater_hardware_settings.xml
index 12927dcaeb..8e056b9b0d 100644
--- a/indra/newview/skins/default/xui/tr/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/tr/floater_hardware_settings.xml
@@ -4,8 +4,8 @@
 		Filtreleme:
 	</text>
 	<check_box label="Anisotropik Filtreleme (etkinken daha yavaş)" name="ani"/>
-	<text name="Antialiasing:">
-		Antialiasing:
+	<text name="antialiasing label">
+		Düzgünleştirme:
 	</text>
 	<combo_box label="Antialiasing" name="fsaa">
 		<combo_box.item label="Devre dışı" name="FSAADisabled"/>
diff --git a/indra/newview/skins/default/xui/tr/floater_model_preview.xml b/indra/newview/skins/default/xui/tr/floater_model_preview.xml
index 339545f96e..0c7cabc6ea 100644
--- a/indra/newview/skins/default/xui/tr/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/tr/floater_model_preview.xml
@@ -4,6 +4,9 @@
 	<string name="status_parse_error">
 		Hata: Tarih ayrıştırma sorunu - ayrıntılar için günlüğe bakın.
 	</string>
+	<string name="status_material_mismatch">
+		Hata: Modelin malzemesi, referans modelin bir alt kümesi değil.
+	</string>
 	<string name="status_reading_file">
 		Yükleniyor...
 	</string>
diff --git a/indra/newview/skins/default/xui/tr/floater_model_wizard.xml b/indra/newview/skins/default/xui/tr/floater_model_wizard.xml
index 108d20cfac..b3c72ba2da 100644
--- a/indra/newview/skins/default/xui/tr/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/tr/floater_model_wizard.xml
@@ -20,6 +20,9 @@
 				Karşıya yüklenecek model dosyasını seçin
 			</text>
 			<button label="Gözat..." label_selected="Gözat..." name="browse"/>
+			<text name="Model types">
+				Second Life, COLLADA (.dae) dosyalarını destekler
+			</text>
 			<text name="dimensions">
 				X         Y         Z
 			</text>
diff --git a/indra/newview/skins/default/xui/tr/floater_moveview.xml b/indra/newview/skins/default/xui/tr/floater_moveview.xml
index 74ed613a62..9226218a24 100644
--- a/indra/newview/skins/default/xui/tr/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/tr/floater_moveview.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move_floater" title="HAREKET ET">
+<floater name="move_floater" title="YÜRÜ / KOŞ / UÇ">
 	<string name="walk_forward_tooltip">
 		İleri Yürü (Yukarı Okuna veya W&apos;ye basın)
 	</string>
diff --git a/indra/newview/skins/default/xui/tr/floater_snapshot.xml b/indra/newview/skins/default/xui/tr/floater_snapshot.xml
index 492ec4b588..fa51f15d16 100644
--- a/indra/newview/skins/default/xui/tr/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/tr/floater_snapshot.xml
@@ -3,72 +3,63 @@
 	<floater.string name="unknown">
 		bilinmiyor
 	</floater.string>
-	<radio_group label="Anlık görüntü türü" name="snapshot_type_radio">
-		<radio_item label="E-posta" name="postcard"/>
-		<radio_item label="Envanterim (L$[AMOUNT])" name="texture"/>
-		<radio_item label="Bilgisayarıma kaydet" name="local"/>
-	</radio_group>
+	<string name="postcard_progress_str">
+		E-posta Gönderiliyor
+	</string>
+	<string name="profile_progress_str">
+		Yayınlanıyor
+	</string>
+	<string name="inventory_progress_str">
+		Envantere Kaydediliyor
+	</string>
+	<string name="local_progress_str">
+		Bilgisayara Kaydediliyor
+	</string>
+	<string name="profile_succeeded_str">
+		Görüntü yüklendi
+	</string>
+	<string name="postcard_succeeded_str">
+		E-posta Gönderildi!
+	</string>
+	<string name="inventory_succeeded_str">
+		Envantere Kaydedildi!
+	</string>
+	<string name="local_succeeded_str">
+		Bilgisayara Kaydedildi!
+	</string>
+	<string name="profile_failed_str">
+		Görüntü Profil Akışınıza yüklenemedi.
+	</string>
+	<string name="postcard_failed_str">
+		E-posta gönderilemedi.
+	</string>
+	<string name="inventory_failed_str">
+		Envantere kaydedilemedi.
+	</string>
+	<string name="local_failed_str">
+		Bilgisayara kaydedilemedi.
+	</string>
+	<button name="advanced_options_btn" tool_tip="Gelişmiş seçenekler"/>
+	<text name="image_res_text">
+		[WIDTH] x [HEIGHT] px
+	</text>
 	<text name="file_size_label">
 		[SIZE] KB
 	</text>
-	<button label="Gönder" name="send_btn"/>
-	<button label="Kaydet (L$[AMOUNT])" name="upload_btn"/>
-	<flyout_button label="Kaydet" name="save_btn" tool_tip="Görüntüyü bir dosyaya kaydet">
-		<flyout_button.item label="Kaydet" name="save_item"/>
-		<flyout_button.item label="Farklı Kaydet..." name="saveas_item"/>
-	</flyout_button>
-	<button label="Daha Fazla" name="more_btn" tool_tip="Gelişmiş seçenekler"/>
-	<button label="Daha Az" name="less_btn" tool_tip="Gelişmiş seçenekler"/>
-	<button label="İptal" name="discard_btn"/>
-	<text name="type_label2">
-		Büyüklük
-	</text>
-	<text name="format_label">
-		Format
-	</text>
-	<combo_box label="Çözünürlük" name="postcard_size_combo">
-		<combo_box.item label="Mevcut Pencere" name="CurrentWindow"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="Özel" name="Custom"/>
-	</combo_box>
-	<combo_box label="Çözünürlük" name="texture_size_combo">
-		<combo_box.item label="Mevcut Pencere" name="CurrentWindow"/>
-		<combo_box.item label="Küçük (128x128)" name="Small(128x128)"/>
-		<combo_box.item label="Orta (256x256)" name="Medium(256x256)"/>
-		<combo_box.item label="Büyük (512x512)" name="Large(512x512)"/>
-		<combo_box.item label="Özel" name="Custom"/>
-	</combo_box>
-	<combo_box label="Çözünürlük" name="local_size_combo">
-		<combo_box.item label="Mevcut Pencere" name="CurrentWindow"/>
-		<combo_box.item label="320x240" name="320x240"/>
-		<combo_box.item label="640x480" name="640x480"/>
-		<combo_box.item label="800x600" name="800x600"/>
-		<combo_box.item label="1024x768" name="1024x768"/>
-		<combo_box.item label="1280x1024" name="1280x1024"/>
-		<combo_box.item label="1600x1200" name="1600x1200"/>
-		<combo_box.item label="Özel" name="Custom"/>
-	</combo_box>
-	<combo_box label="Format" name="local_format_combo">
-		<combo_box.item label="PNG" name="PNG"/>
-		<combo_box.item label="JPEG" name="JPEG"/>
-		<combo_box.item label="BMP" name="BMP"/>
-	</combo_box>
-	<spinner label="Genişlik" name="snapshot_width"/>
-	<spinner label="Yükseklik" name="snapshot_height"/>
-	<check_box label="Oranları Koru" name="keep_aspect_check"/>
-	<slider label="Görüntü kalitesi" name="image_quality_slider"/>
-	<text name="layer_type_label">
-		Yakala:
-	</text>
-	<combo_box label="Görüntü Katmanları" name="layer_types">
-		<combo_box.item label="Renkler" name="Colors"/>
-		<combo_box.item label="Derinlik" name="Depth"/>
-	</combo_box>
-	<check_box label="Arayüz" name="ui_check"/>
-	<check_box label="BÜG&apos;ler" name="hud_check"/>
-	<check_box label="Kaydettikten sonra açık tut" name="keep_open_check"/>
-	<check_box label="Kare dondur (tam ekran)" name="freeze_frame_check"/>
-	<check_box label="Otomatik yenile" name="auto_snapshot_check"/>
+	<panel name="advanced_options_panel">
+		<text name="advanced_options_label">
+			GELİŞMİŞ SEÇENEKLER
+		</text>
+		<text name="layer_type_label">
+			Yakala:
+		</text>
+		<combo_box label="Görüntü Katmanları" name="layer_types">
+			<combo_box.item label="Renkler" name="Colors"/>
+			<combo_box.item label="Derinlik" name="Depth"/>
+		</combo_box>
+		<check_box label="Arayüz" name="ui_check"/>
+		<check_box label="BÜG&apos;ler" name="hud_check"/>
+		<check_box label="Kare dondur (tam ekran)" name="freeze_frame_check"/>
+		<check_box label="Otomatik yenile" name="auto_snapshot_check"/>
+	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_toybox.xml b/indra/newview/skins/default/xui/tr/floater_toybox.xml
index 05d3633df0..e60e176643 100644
--- a/indra/newview/skins/default/xui/tr/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/tr/floater_toybox.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Toybox" title="ARAÇ ÇUBUKLARINI ÖZELLEŞTİR">
+<floater name="Toybox" title="ARAÇ ÇUBUĞU DÜĞMELERİ">
 	<text name="toybox label 1">
 		Düğmeleri araç çubuklarına veya araç çubuklarından sürükleyerek ekleyin ya da kaldırın.
 	</text>
 	<text name="toybox label 2">
 		Her bir araç çubuğunun ayarına göre düğmeler gösterilir veya sadece simgeleri yer alır.
 	</text>
+	<button label="Tüm araç çubuklarını temizle" label_selected="Tüm araç çubuklarını temizle" name="btn_clear_all"/>
 	<button label="Varsayılanları geri yükle" label_selected="Varsayılanları geri yükle" name="btn_restore_defaults"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_translation_settings.xml b/indra/newview/skins/default/xui/tr/floater_translation_settings.xml
new file mode 100644
index 0000000000..33ce76bd9a
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/floater_translation_settings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_translation_settings" title="SOHBET ÇEVİRİSİ AYARLARI">
+	<string name="bing_api_key_not_verified">
+		Bing uygulama kimliği doğrulanmadı. Lütfen tekrar deneyin.
+	</string>
+	<string name="google_api_key_not_verified">
+		Google API anahtarı doğrulanmadı. Lütfen tekrar deneyin.
+	</string>
+	<string name="bing_api_key_verified">
+		Bing uygulama kimliği doğrulandı.
+	</string>
+	<string name="google_api_key_verified">
+		Google API anahtarı doğrulandı.
+	</string>
+	<check_box label="Sohbet ederken makine çevirisini etkinleştirin" name="translate_chat_checkbox"/>
+	<text name="translate_language_label">
+		Sohbeti şu dile çevir:
+	</text>
+	<combo_box name="translate_language_combo">
+		<combo_box.item label="Sistem Varsayılanı" name="System Default Language"/>
+		<combo_box.item label="İngilizce" name="English"/>
+		<combo_box.item label="Dansk (Danca)" name="Danish"/>
+		<combo_box.item label="Deutsch (Almanca)" name="German"/>
+		<combo_box.item label="Español (İspanyolca)" name="Spanish"/>
+		<combo_box.item label="Français (Fransızca)" name="French"/>
+		<combo_box.item label="Italiano (İtalyanca)" name="Italian"/>
+		<combo_box.item label="Magyar (Macarca)" name="Hungarian"/>
+		<combo_box.item label="Nederlands (Flemenkçe)" name="Dutch"/>
+		<combo_box.item label="Polski (Lehçe)" name="Polish"/>
+		<combo_box.item label="Português (Portekizce)" name="Portugese"/>
+		<combo_box.item label="Русский (Rusça)" name="Russian"/>
+		<combo_box.item label="Türkçe (Türkçe)" name="Turkish"/>
+		<combo_box.item label="Українська (Ukraynaca)" name="Ukrainian"/>
+		<combo_box.item label="中文 (正體) (Çince)" name="Chinese"/>
+		<combo_box.item label="日本語 (Japonca)" name="Japanese"/>
+		<combo_box.item label="한국어 (Korece)" name="Korean"/>
+	</combo_box>
+	<text name="tip">
+		Çeviri hizmetini seçin:
+	</text>
+	<radio_group name="translation_service_rg">
+		<radio_item initial_value="bing" label="Bing Çevirmeni" name="bing"/>
+		<radio_item initial_value="google" label="Google Translate" name="google"/>
+	</radio_group>
+	<text name="bing_api_key_label">
+		Bing [http://www.bing.com/developers/createapp.aspx Uygulama Kimliği]:
+	</text>
+	<button label="Doğrula" name="verify_bing_api_key_btn"/>
+	<text name="google_api_key_label">
+		Google [http://code.google.com/apis/language/translate/v2/getting_started.html#auth API anahtarı]:
+	</text>
+	<button label="Doğrula" name="verify_google_api_key_btn"/>
+	<text name="google_links_text">
+		[http://code.google.com/apis/language/translate/v2/pricing.html Fiyatlandırma] | [https://code.google.com/apis/console İstatistikler]
+	</text>
+	<button label="Tamam" name="ok_btn"/>
+	<button label="İptal" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_voice_controls.xml b/indra/newview/skins/default/xui/tr/floater_voice_controls.xml
index dac05d8327..5ff0804f17 100644
--- a/indra/newview/skins/default/xui/tr/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/tr/floater_voice_controls.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="floater_voice_controls" title="SES DENETİMLERİ">
 	<string name="title_nearby">
-		Yakındaki ses
+		SES AYARLARI
 	</string>
 	<string name="title_group">
-		[GROUP] ile grup araması
+		[GROUP] İLE GRUP ARAMASI
 	</string>
 	<string name="title_adhoc">
-		Konferans araması
+		KONFERANS ARAMASI
 	</string>
 	<string name="title_peer_2_peer">
-		[NAME] ile arama
+		[NAME] İLE ARAMA
 	</string>
 	<string name="no_one_near">
 		Yakındaki kimsede ses etkin değil
diff --git a/indra/newview/skins/default/xui/tr/menu_toolbars.xml b/indra/newview/skins/default/xui/tr/menu_toolbars.xml
index 7cb3192ec4..c8523a6ec9 100644
--- a/indra/newview/skins/default/xui/tr/menu_toolbars.xml
+++ b/indra/newview/skins/default/xui/tr/menu_toolbars.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <context_menu name="Toolbars Popup">
-	<menu_item_call label="Düğmeleri seç..." name="Chose Buttons"/>
+	<menu_item_call label="Bu düğmeyi kaldır" name="Remove button"/>
+	<menu_item_call label="Araç çubuğu düğmeleri..." name="Choose Buttons"/>
 	<menu_item_check label="Simgeler ve etiketler" name="icons_with_text"/>
 	<menu_item_check label="Sadece simgeler" name="icons_only"/>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/tr/menu_viewer.xml b/indra/newview/skins/default/xui/tr/menu_viewer.xml
index 75294e38d5..ef10d639d7 100644
--- a/indra/newview/skins/default/xui/tr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/tr/menu_viewer.xml
@@ -1,12 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <menu_bar name="Main Menu">
 	<menu label="Ben" name="Me">
-		<menu_item_call label="Kontrol Paneli..." name="Manage My Account"/>
 		<menu_item_call label="Profil..." name="Profile"/>
 		<menu_item_call label="Görünüm..." name="ChangeOutfit"/>
+		<menu_item_call label="Bir avatar seçin..." name="Avatar Picker"/>
 		<menu_item_check label="Envanter..." name="Inventory"/>
-		<menu_item_check label="Mimikler..." name="Gestures"/>
-		<menu_item_check label="Ses..." name="ShowVoice"/>
+		<menu_item_call label="Yeni Envanter Penceresi" name="NewInventoryWindow"/>
+		<menu_item_call label="Yerler..." name="Places"/>
+		<menu_item_call label="Favoriler..." name="Picks"/>
+		<menu_item_call label="Kamera Denetimleri..." name="Camera Controls"/>
 		<menu label="Hareket" name="Movement">
 			<menu_item_call label="Otur" name="Sit Down Here"/>
 			<menu_item_check label="Uç" name="Fly"/>
@@ -20,34 +22,37 @@
 		<menu_item_call label="Yönetici Durumu Talep Et" name="Request Admin Options"/>
 		<menu_item_call label="Yönetici Durumundan Ayrıl" name="Leave Admin Options"/>
 		<menu_item_call label="L$ Satın Al" name="Buy and Sell L$"/>
+		<menu_item_call label="Hesap kontrol paneli..." name="Manage My Account"/>
 		<menu_item_call label="Tercihler..." name="Preferences"/>
-		<menu_item_call label="Araç çubukları..." name="Toolbars"/>
+		<menu_item_call label="Araç çubuğu düğmeleri..." name="Toolbars"/>
 		<menu_item_call label="Tüm denetimleri sakla" name="Hide UI"/>
 		<menu_item_call label="[APP_NAME]&apos;den Çık" name="Quit"/>
 	</menu>
 	<menu label="İletişim Kur" name="Communicate">
-		<menu_item_call label="Arkadaşlarım" name="My Friends"/>
-		<menu_item_call label="Gruplarım" name="My Groups"/>
-		<menu_item_check label="Yakındaki Sohbet" name="Nearby Chat"/>
-		<menu_item_call label="Yakındaki Kişiler" name="Active Speakers"/>
-		<menu_item_check label="Yakındaki Ses" name="Nearby Voice"/>
+		<menu_item_check label="Sohbet..." name="Nearby Chat"/>
+		<menu_item_check label="Konuş" name="Speak"/>
+		<menu_item_check label="Ses ayarları..." name="Nearby Voice"/>
+		<menu_item_check label="Ses şekillendirme..." name="ShowVoice"/>
+		<menu_item_check label="Mimikler..." name="Gestures"/>
+		<menu_item_call label="Arkadaşlar" name="My Friends"/>
+		<menu_item_call label="Gruplar" name="My Groups"/>
+		<menu_item_call label="Yakındaki kişiler" name="Active Speakers"/>
 	</menu>
 	<menu label="Dünya" name="World">
+		<menu_item_call label="Bu Yeri Yer İmlerine Ekle" name="Create Landmark Here"/>
+		<menu_item_call label="Hedef Konumlar..." name="Destinations"/>
+		<menu_item_check label="Dünya haritası" name="World Map"/>
 		<menu_item_check label="Mini-harita" name="Mini-Map"/>
-		<menu_item_check label="Dünya Haritası" name="World Map"/>
 		<menu_item_check label="Ara" name="Search"/>
+		<menu_item_call label="Ana konuma ışınlan" name="Teleport Home"/>
+		<menu_item_call label="Ana konumu burası olarak seç" name="Set Home to Here"/>
 		<menu_item_call label="Anlık Görüntü" name="Take Snapshot"/>
-		<menu_item_call label="Bu Yeri Yer İmlerine Ekle" name="Create Landmark Here"/>
-		<menu label="Profili Yerleştir" name="Land">
-			<menu_item_call label="Profili Yerleştir" name="Place Profile"/>
-			<menu_item_call label="Arazi Hakkında" name="About Land"/>
-			<menu_item_call label="Bölge/Gayrimenkul" name="Region/Estate"/>
-		</menu>
-		<menu_item_call label="Bu Araziyi Satın Al" name="Buy Land"/>
-		<menu_item_call label="Arazim" name="My Land"/>
+		<menu_item_call label="Profili yerleştir" name="Place Profile"/>
+		<menu_item_call label="Arazi hakkında" name="About Land"/>
+		<menu_item_call label="Bölge / Gayrimenkul" name="Region/Estate"/>
+		<menu_item_call label="Sahip olduğum arazi parçaları..." name="My Land"/>
+		<menu_item_call label="Bu araziyi satın al" name="Buy Land"/>
 		<menu label="Göster" name="LandShow">
-			<menu_item_check label="Denetimleri Hareket Ettir" name="Movement Controls"/>
-			<menu_item_check label="Denetimleri Göster" name="Camera Controls"/>
 			<menu_item_check label="Yasaklama Çizgileri" name="Ban Lines"/>
 			<menu_item_check label="İşaretler" name="beacons"/>
 			<menu_item_check label="Mülkiyet Çizgileri" name="Property Lines"/>
@@ -56,16 +61,15 @@
 			<menu_item_check label="Parsel Özellikleri" name="Parcel Properties"/>
 			<menu_item_check label="Gelişmiş Menü" name="Show Advanced Menu"/>
 		</menu>
-		<menu_item_call label="Ana Konuma Işınla" name="Teleport Home"/>
-		<menu_item_call label="Ana Konumu Burası Olarak Seç" name="Set Home to Here"/>
 		<menu label="Güneş" name="Environment Settings">
 			<menu_item_call label="Gün Doğumu" name="Sunrise"/>
 			<menu_item_call label="Gün Ortası" name="Noon"/>
 			<menu_item_call label="Gün Batımı" name="Sunset"/>
 			<menu_item_call label="Gece Yarısı" name="Midnight"/>
+			<menu_item_call label="Bölge Ayarlarını Kullanın" name="Use Region Settings"/>
 		</menu>
-		<menu label="Ortam Düzenleyici" name="Enviroment Editor">
-			<menu_item_call label="Ortam Ayarları..." name="Enviroment Settings"/>
+		<menu label="Ortam Düzenleyici" name="Environment Editor">
+			<menu_item_call label="Ortam Ayarları..." name="Environment Settings"/>
 			<menu label="Su Ön Ayarları" name="Water Presets">
 				<menu_item_call label="Yeni ön ayar..." name="new_water_preset"/>
 				<menu_item_call label="Ön ayarı düzenle..." name="edit_water_preset"/>
@@ -144,6 +148,7 @@
 		<menu_item_call label="Yinele" name="Redo"/>
 	</menu>
 	<menu label="Yardım" name="Help">
+		<menu_item_call label="Nasıl yapılır..." name="How To"/>
 		<menu_item_call label="[SECOND_LIFE] Yardımı" name="Second Life Help"/>
 		<menu_item_call label="Kötüye Kullanımı Bildir" name="Report Abuse"/>
 		<menu_item_call label="Hata Bildir" name="Report Bug"/>
@@ -198,11 +203,10 @@
 		<menu_item_check label="İş Parçacığı Okuma Eklentisini Kullan" name="Use Plugin Read Thread"/>
 		<menu_item_call label="Grup Ön Belleğini Temizle" name="ClearGroupCache"/>
 		<menu_item_check label="Fare Düzleştirme" name="Mouse Smoothing"/>
+		<menu_item_call label="Bırakma Anahtarları" name="Release Keys"/>
 		<menu label="Kısa Yollar" name="Shortcuts">
 			<menu_item_call label="Görüntü (L$[COST])..." name="Upload Image"/>
 			<menu_item_check label="Ara" name="Search"/>
-			<menu_item_call label="Bırakma Anahtarları" name="Release Keys"/>
-			<menu_item_call label="KA Büyüklüğünü Varsayılana Ayarla" name="Set UI Size to Default"/>
 			<menu_item_check label="Gelişmiş Menüyü Göster - eski kısayol" name="Show Advanced Menu - legacy shortcut"/>
 			<menu_item_call label="Pencereyi Kapat" name="Close Window"/>
 			<menu_item_call label="Tüm Pencereleri Kapat" name="Close All Windows"/>
@@ -288,6 +292,7 @@
 			<menu_item_check label="Işıklar" name="Lights"/>
 			<menu_item_check label="Çarpışma İskeleti" name="Collision Skeleton"/>
 			<menu_item_check label="Işın Yayını" name="Raycast"/>
+			<menu_item_check label="Rüzgar Vektörleri" name="Wind Vectors"/>
 			<menu_item_check label="İşleme Karmaşıklığı" name="rendercomplexity"/>
 			<menu_item_check label="Şekillendir" name="Sculpt"/>
 		</menu>
@@ -300,7 +305,6 @@
 			<menu_item_check label="Işıklandırma ve Gölgeler" name="Lighting and Shadows"/>
 			<menu_item_check label="Güneş/Ay/Projektörlerden Gelen Gölgeler" name="Shadows from Sun/Moon/Projectors"/>
 			<menu_item_check label="SSAO ve Gölge Yumuşatma" name="SSAO and Shadow Smoothing"/>
-			<menu_item_check label="Küresel Aydınlatma (Deneysel)" name="Global Illumination"/>
 			<menu_item_check label="GL Hata Ayıklama" name="Debug GL"/>
 			<menu_item_check label="Ardışık Hata Ayıklama" name="Debug Pipeline"/>
 			<menu_item_check label="Otomatik Alfa Maskeleri (ertelenmiş)" name="Automatic Alpha Masks (deferred)"/>
diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml
index c0dc67ed34..631634aa7d 100644
--- a/indra/newview/skins/default/xui/tr/notifications.xml
+++ b/indra/newview/skins/default/xui/tr/notifications.xml
@@ -1110,8 +1110,13 @@ Arazinin satış bedeli sahibine geri ödenmez. Devredilen bir parsel satılırs
 	<notification name="DisplaySetToSafe">
 		Güvenli seçeneği seçtiğiniz için görüntüleme ayarları güvenli düzeye ayarlandı.
 	</notification>
-	<notification name="DisplaySetToRecommended">
-		Görüntüleme ayarları sistem yapılandırmanız için önerilen düzeye ayarlandı.
+	<notification name="DisplaySetToRecommendedGPUChange">
+		Grafik kartınız değiştiği için görüntü ayarları tavsiye edilen seviyelere ayarlandı
+önceki: &apos;[LAST_GPU]&apos;
+sonraki: &apos;[THIS_GPU]&apos;
+	</notification>
+	<notification name="DisplaySetToRecommendedFeatureChange">
+		İşleme alt sistemindeki bir değişiklik nedeniyle görüntü ayarları tavsiye edilen seviyelere ayarlandı.
 	</notification>
 	<notification name="ErrorMessage">
 		[ERROR_MESSAGE]
@@ -1910,7 +1915,13 @@ Envanter öğesi/öğeleri taşınsın mı?
 		<usetemplate ignoretext="Çıkmadan önce doğrulama iste" name="okcancelignore" notext="Çıkma" yestext="Çık"/>
 	</notification>
 	<notification name="ConfirmRestoreToybox">
-		Varsayılan düğmelerinizi ve araç çubuklarınızı geri yüklemek istediğinize emin misiniz? 
+		Bu eylem, varsayılan düğmelerinizi ve araç çubuklarınızı geri yükleyecek.
+
+Bu eylemi geri alamazsınız.
+		<usetemplate name="okcancelbuttons" notext="İptal" yestext="Tamam"/>
+	</notification>
+	<notification name="ConfirmClearAllToybox">
+		Bu eylem ile tüm düğmeler araç kutusuna döner ve araç çubuklarınız boş olur.
     
 Bu eylemi geri alamazsınız.
 		<usetemplate name="okcancelbuttons" notext="İptal" yestext="Tamam"/>
@@ -2119,10 +2130,10 @@ Bu adımda web tarayıcınızın başlatılacağına dikkat edin.
 		Konu: [SUBJECT], İleti: [MESSAGE]
 	</notification>
 	<notification name="FriendOnline">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; Çevrimiçi
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; çevrimiçi
 	</notification>
 	<notification name="FriendOffline">
-		&lt;nolink&gt;[NAME]&lt;/nolink&gt; Çevrimdışı
+		&lt;nolink&gt;[NAME]&lt;/nolink&gt; çevrimdışı
 	</notification>
 	<notification name="AddSelfFriend">
 		Çok iyi biri olduğunuza eminiz fakat kendinizi arkadaş olarak ekleyemezsiniz.
@@ -2236,14 +2247,16 @@ Lütfen tek bir nesne seçin.
 		Arama kartınız reddedildi.
 	</notification>
 	<notification name="TeleportToLandmark">
-		Ekranınızın sağ tarafındaki Yerler panelini açıp Yer İmleri sekmesini seçerek &apos;[NAME]&apos; gibi konumlara ışınlanabilirsiniz.
-Seçmek için herhangi bir yer iminin üzerini tıklatın ve ardından panelin en altındaki &apos;Işınla&apos; düğmesini tıklatın.
-(Yer iminin üzerini çift tıklatabilir veya sağ tıklayıp &apos;Işınla&apos;yı seçebilirsiniz.)
+		&apos;[NAME]&apos; gibi konumlara ışınlanmak için &quot;Yerler&quot; düğmesine tıklayın,
+    sonra açılan pencerede Yer İmleri sekmesini seçin. Herhangi bir
+    yer iminin üzerine tıklayarak bunu seçin ve ardından pencerenin en altındaki &apos;Işınla&apos; düğmesine tıklayın.
+    (Ayrıca yer imine çift tıklayabilir veya sağ tıklayarak
+    &apos;Işınla&apos; seçimini yapabilirsiniz.)
 	</notification>
 	<notification name="TeleportToPerson">
-		Ekranınızın sağ tarafındaki İnsanlar panelini açarak  &apos;[NAME]&apos; gibi Sakinler ile iletişim kurabilirsiniz.
-Sakini listeden seçin ve  panelin altındaki &apos;Aİ&quot; düğmesini tıklatın.
-(Listede adlarını çift tıklatarak veya sağ tıklatıp &quot;Aİ&quot;yi seçerek de bunu yapabilirsiniz.)
+		&apos;[NAME]&apos; gibi sakinlerle bağlantıya geçmek için &quot;Kişiler&quot; düğmesine tıklayın, açılan pencereden bir Sakin seçin ve sonra
+    pencerenin altında &apos;Anlık İleti&quot; üzerine tıklayın.
+    (Listede adlarına çift tıklayarak veya sağ tıklayıp &quot;Anlık İleti&quot;yi seçerek de bunu yapabilirsiniz.)
 	</notification>
 	<notification name="CantSelectLandFromMultipleRegions">
 		Sunucunun sınırları dışındaki arazi seçilemez.
@@ -2264,6 +2277,9 @@ Daha küçük bir arazi parçası seçmeyi deneyin.
 	<notification name="PaymentSent">
 		[MESSAGE]
 	</notification>
+	<notification name="PaymentFailure">
+		[MESSAGE]
+	</notification>
 	<notification name="EventNotification">
 		Etkinlik Bildirimi
 
diff --git a/indra/newview/skins/default/xui/tr/panel_edit_skin.xml b/indra/newview/skins/default/xui/tr/panel_edit_skin.xml
index 33fb787e08..fdf75100ed 100644
--- a/indra/newview/skins/default/xui/tr/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/tr/panel_edit_skin.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_skin_panel">
 	<panel name="avatar_skin_color_panel">
-		<texture_picker label="Baş Dövmeleri" name="Head Tattoos" tool_tip="Bir resim seçmek için tıklayın"/>
-		<texture_picker label="Üst Gövde Dövmeleri" name="Upper Tattoos" tool_tip="Bir resim seçmek için tıklayın"/>
-		<texture_picker label="Alt Gövde Dövmeleri" name="Lower Tattoos" tool_tip="Bir resim seçmek için tıklayın"/>
+		<texture_picker label="Baş" name="Head" tool_tip="Bir resim seçmek için tıklayın"/>
+		<texture_picker label="Üst gövde" name="Upper Body" tool_tip="Bir resim seçmek için tıklayın"/>
+		<texture_picker label="Alt gövde" name="Lower Body" tool_tip="Bir resim seçmek için tıklayın"/>
 	</panel>
 	<panel name="accordion_panel">
 		<accordion name="wearable_accordion">
diff --git a/indra/newview/skins/default/xui/tr/panel_postcard_message.xml b/indra/newview/skins/default/xui/tr/panel_postcard_message.xml
new file mode 100644
index 0000000000..2361f4c1c3
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_postcard_message.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_message">
+	<text name="to_label">
+		Kime:
+	</text>
+	<text name="name_label">
+		Kimden:
+	</text>
+	<text name="subject_label">
+		Konu:
+	</text>
+	<line_editor label="Konunuzu buraya yazın." name="subject_form"/>
+	<text name="msg_label">
+		İleti:
+	</text>
+	<text_editor name="msg_form">
+		İletinizi buraya yazın.
+	</text_editor>
+	<button label="İptal" name="cancel_btn"/>
+	<button label="Gönder" name="send_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_postcard_settings.xml b/indra/newview/skins/default/xui/tr/panel_postcard_settings.xml
new file mode 100644
index 0000000000..bce0b21b9a
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_postcard_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_postcard_settings">
+	<combo_box label="Çözünürlük" name="postcard_size_combo">
+		<combo_box.item label="Mevcut Pencere" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Özel" name="Custom"/>
+	</combo_box>
+	<layout_stack name="postcard_image_params_ls">
+		<layout_panel name="postcard_image_size_lp">
+			<spinner label="Genişlik" name="postcard_snapshot_width"/>
+			<spinner label="Yükseklik" name="postcard_snapshot_height"/>
+			<check_box label="Oranları koru" name="postcard_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="postcard_image_format_quality_lp">
+			<slider label="Görüntü kalitesi" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_preferences_chat.xml b/indra/newview/skins/default/xui/tr/panel_preferences_chat.xml
index f7f0698a31..9caf95a122 100644
--- a/indra/newview/skins/default/xui/tr/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/tr/panel_preferences_chat.xml
@@ -29,29 +29,5 @@
 	<check_box label="Aİ Sohbetleri" name="EnableIMChatPopups" tool_tip="Bir anlık ileti geldiğinde açılır pencereleri görmek için işaretle"/>
 	<spinner label="Yakındaki sohbet iletilerinin vurgulanma süresi:" name="nearby_toasts_lifetime"/>
 	<spinner label="Yakındaki sohbet iletilerinin sönme süresi:" name="nearby_toasts_fadingtime"/>
-	<text name="translate_chb_label">
-		Sohbet ederken makine çevirisi kullanılsın
-	</text>
-	<text name="translate_language_text">
-		Sohbeti şu dile çevir:
-	</text>
-	<combo_box name="translate_language_combobox">
-		<combo_box.item label="Sistem Varsayılanı" name="System Default Language"/>
-		<combo_box.item label="İngilizce" name="English"/>
-		<combo_box.item label="Dansk (Danca)" name="Danish"/>
-		<combo_box.item label="Deutsch (Almanca)" name="German"/>
-		<combo_box.item label="Español (İspanyolca)" name="Spanish"/>
-		<combo_box.item label="Français (Fransızca)" name="French"/>
-		<combo_box.item label="Italiano (İtalyanca)" name="Italian"/>
-		<combo_box.item label="Magyar (Macarca)" name="Hungarian"/>
-		<combo_box.item label="Nederlands (Flemenkçe)" name="Dutch"/>
-		<combo_box.item label="Polski (Lehçe)" name="Polish"/>
-		<combo_box.item label="Português (Portekizce)" name="Portugese"/>
-		<combo_box.item label="Русский (Rusça)" name="Russian"/>
-		<combo_box.item label="Türkçe (Türkçe)" name="Turkish"/>
-		<combo_box.item label="Українська (Ukraynaca)" name="Ukrainian"/>
-		<combo_box.item label="中文 (正體) (Çince)" name="Chinese"/>
-		<combo_box.item label="日本語 (Japonca)" name="Japanese"/>
-		<combo_box.item label="한국어 (Korece)" name="Korean"/>
-	</combo_box>
+	<button label="Sohbet Çevirisi Ayarları" name="ok_btn"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_preferences_setup.xml b/indra/newview/skins/default/xui/tr/panel_preferences_setup.xml
index 12c175b8f5..9d03d9b01d 100644
--- a/indra/newview/skins/default/xui/tr/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/tr/panel_preferences_setup.xml
@@ -15,7 +15,7 @@
 		Web:
 	</text>
 	<radio_group name="use_external_browser">
-		<radio_item label="Tarayıcımı kullan (IE, Firefox, Safari)" name="external" tool_tip="Yardım, web bağlantıları vs. için sistemin varsayılan web tarayıcısını kullanın. Tam ekran çalıştırılıyorsa tavsiye edilmez." value="1"/>
+		<radio_item label="Tarayıcımı kullan (IE, Firefox, Safari)" name="external" tool_tip="Yardım, web bağlantıları vs. için sistemin varsayılan web tarayıcısını kullanın. Tam ekran çalıştırılıyorsa tavsiye edilmez." value="true"/>
 		<radio_item label="Yerleşik tarayıcıyı kullan" name="internal" tool_tip="Yardım, web bağlantıları vs. için dahili web tarayıcısını kullanın. Bu tarayıcı [APP_NAME] içerisinde yeni bir pencere olarak açılır." value=""/>
 	</radio_group>
 	<check_box initial_value="true" label="Eklentileri etkinleştir" name="browser_plugins_enabled"/>
diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml
new file mode 100644
index 0000000000..e3b22c639a
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_inventory">
+	<text name="title">
+		Envanterime Kaydet
+	</text>
+	<text name="hint_lbl">
+		Bir görüntüyü envanterinize kaydetmenin maliyeti L$[UPLOAD_COST] olur. Görüntünüzü bir doku olarak kaydetmek için kare formatlardan birini seçin.
+	</text>
+	<combo_box label="Çözünürlük" name="texture_size_combo">
+		<combo_box.item label="Mevcut Pencere" name="CurrentWindow"/>
+		<combo_box.item label="Küçük (128x128)" name="Small(128x128)"/>
+		<combo_box.item label="Orta (256x256)" name="Medium(256x256)"/>
+		<combo_box.item label="Büyük (512x512)" name="Large(512x512)"/>
+		<combo_box.item label="Özel" name="Custom"/>
+	</combo_box>
+	<spinner label="Genişlik" name="inventory_snapshot_width"/>
+	<spinner label="Yükseklik" name="inventory_snapshot_height"/>
+	<check_box label="Oranları koru" name="inventory_keep_aspect_check"/>
+	<button label="İptal" name="cancel_btn"/>
+	<button label="Kaydet" name="save_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_local.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_local.xml
new file mode 100644
index 0000000000..87d7677d73
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_snapshot_local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_local">
+	<text name="title">
+		Bilgisayarıma Kaydet
+	</text>
+	<combo_box label="Çözünürlük" name="local_size_combo">
+		<combo_box.item label="Mevcut Pencere" name="CurrentWindow"/>
+		<combo_box.item label="320x240" name="320x240"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="1280x1024" name="1280x1024"/>
+		<combo_box.item label="1600x1200" name="1600x1200"/>
+		<combo_box.item label="Özel" name="Custom"/>
+	</combo_box>
+	<layout_stack name="local_image_params_ls">
+		<layout_panel name="local_image_size_lp">
+			<spinner label="Genişlik" name="local_snapshot_width"/>
+			<spinner label="Yükseklik" name="local_snapshot_height"/>
+			<check_box label="Oranları koru" name="local_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="local_image_format_quality_lp">
+			<combo_box label="Format" name="local_format_combo">
+				<combo_box.item label="PNG (Kayıpsız)" name="PNG"/>
+				<combo_box.item label="JPEG" name="JPEG"/>
+				<combo_box.item label="BMP (Kayıpsız)" name="BMP"/>
+			</combo_box>
+			<slider label="Görüntü kalitesi" name="image_quality_slider"/>
+			<text name="image_quality_level">
+				([QLVL])
+			</text>
+		</layout_panel>
+	</layout_stack>
+	<button label="İptal" name="cancel_btn"/>
+	<flyout_button label="Kaydet" name="save_btn" tool_tip="Görüntüyü bir dosyaya kaydet">
+		<flyout_button.item label="Kaydet" name="save_item"/>
+		<flyout_button.item label="Farklı Kaydet..." name="saveas_item"/>
+	</flyout_button>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_options.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_options.xml
new file mode 100644
index 0000000000..fd2e85fce5
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_snapshot_options.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_options">
+	<button label="Profil Akışımda Yayınla" name="save_to_profile_btn"/>
+	<button label="E-posta" name="save_to_email_btn"/>
+	<button label="Envanterime Kaydet (L$[AMOUNT])" name="save_to_inventory_btn"/>
+	<button label="Bilgisayarıma Kaydet" name="save_to_computer_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml
new file mode 100644
index 0000000000..e999678a0d
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+	<string name="default_subject">
+		SECOND_LIFE]&apos;dan posta kartı.
+	</string>
+	<string name="default_message">
+		Buna bakın!
+	</string>
+	<string name="upload_message">
+		Gönderiyor...
+	</string>
+	<text name="title">
+		E-posta
+	</text>
+	<button label="İleti" name="message_btn"/>
+	<button label="Ayarlar" name="settings_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_profile.xml
new file mode 100644
index 0000000000..334fd52a48
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_snapshot_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_profile">
+	<text name="title">
+		Profil Akışımda Yayınla
+	</text>
+	<combo_box label="Çözünürlük" name="profile_size_combo">
+		<combo_box.item label="Mevcut Pencere" name="CurrentWindow"/>
+		<combo_box.item label="640x480" name="640x480"/>
+		<combo_box.item label="800x600" name="800x600"/>
+		<combo_box.item label="1024x768" name="1024x768"/>
+		<combo_box.item label="Özel" name="Custom"/>
+	</combo_box>
+	<layout_stack name="profile_image_params_ls">
+		<layout_panel name="profile_image_size_lp">
+			<spinner label="Genişlik" name="profile_snapshot_width"/>
+			<spinner label="Yükseklik" name="profile_snapshot_height"/>
+			<check_box label="Oranları koru" name="profile_keep_aspect_check"/>
+		</layout_panel>
+		<layout_panel name="profile_image_metadata_lp">
+			<text name="caption_label">
+				Resim yazısı:
+			</text>
+			<check_box initial_value="true" label="Konumu dahil et" name="add_location_cb"/>
+		</layout_panel>
+	</layout_stack>
+	<button label="İptal" name="cancel_btn"/>
+	<button label="Yayınla" name="post_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml
index bf331dc3cf..0dbc9b0a0e 100644
--- a/indra/newview/skins/default/xui/tr/strings.xml
+++ b/indra/newview/skins/default/xui/tr/strings.xml
@@ -1211,7 +1211,7 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin.
 		Envanterinizde bu dokunun kopyası yok
 	</string>
 	<string name="InventoryInboxNoItems">
-		Pazaryeri üzerinden satın alınan öğeler buraya teslim edilir.
+		Bir öğeyi satın aldığınızda veya başka bir şekilde edindiğinizde burada görünür; bunu envanterinizdeki bir klasöre sürükleyebilir veya tutmak istemiyorsanız silebilirsiniz.
 	</string>
 	<string name="MarketplaceURL">
 		http://marketplace.[DOMAIN_NAME]
@@ -1409,6 +1409,9 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin.
 	<string name="no_attachments">
 		Giyilen aksesuar yok
 	</string>
+	<string name="Attachments remain">
+		Aksesuarlar ([COUNT] yuva mevcut)
+	</string>
 	<string name="Buy">
 		Satın Al
 	</string>
@@ -1535,6 +1538,12 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin.
 	<string name="Right Pec">
 		Sağ Göğüs
 	</string>
+	<string name="Neck">
+		Boyun
+	</string>
+	<string name="Avatar Center">
+		Avatar Merkezi
+	</string>
 	<string name="Invalid Attachment">
 		Geçersiz Aksesuar Noktası
 	</string>
@@ -4027,6 +4036,18 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne başvurun.
 	<string name="you_paid_ldollars_no_name">
 		[REASON] L$[AMOUNT] ödediniz.
 	</string>
+	<string name="you_paid_failure_ldollars">
+		[REASON] [NAME]&apos;e L$[AMOUNT] ödeyemediniz.
+	</string>
+	<string name="you_paid_failure_ldollars_no_info">
+		L$[AMOUNT] ödeyemediniz.
+	</string>
+	<string name="you_paid_failure_ldollars_no_reason">
+		[NAME]&apos;e L$[AMOUNT] ödeyemediniz.
+	</string>
+	<string name="you_paid_failure_ldollars_no_name">
+		[REASON] L$[AMOUNT] ödeyemediniz.
+	</string>
 	<string name="for item">
 		[ITEM] için.
 	</string>
@@ -4437,6 +4458,12 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 	<string name="ExternalEditorFailedToRun">
 		Harici düzenleyici çalışmadı.
 	</string>
+	<string name="TranslationFailed">
+		Çeviri başarılamadı: [REASON]
+	</string>
+	<string name="TranslationResponseParseError">
+		Çeviri yanıtı ayrıştırılırken hata meydana geldi.
+	</string>
 	<string name="Esc">
 		Esc
 	</string>
@@ -4819,7 +4846,7 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 		Mini-harita
 	</string>
 	<string name="Command_Move_Label">
-		Hareket Et
+		Yürü / koş / uç
 	</string>
 	<string name="Command_People_Label">
 		Kişiler
@@ -4846,10 +4873,10 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 		Konuş
 	</string>
 	<string name="Command_View_Label">
-		Görünüm
+		Kamera denetimleri
 	</string>
 	<string name="Command_Voice_Label">
-		Yakındaki ses
+		Ses ayarları
 	</string>
 	<string name="Command_AboutLand_Tooltip">
 		Ziyaret ettiğiniz araziyle ilgili bilgi
@@ -4921,7 +4948,16 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 		Kamera açısını değiştirmek
 	</string>
 	<string name="Command_Voice_Tooltip">
-		Ses imkanına sahip yakındaki kişiler
+		Aramalar ve 	SL dünyası içinde size yakın kişiler için ses denetimleri
+	</string>
+	<string name="Toolbar_Bottom_Tooltip">
+		şu anda alt araç çubuğunuzda
+	</string>
+	<string name="Toolbar_Left_Tooltip">
+		şu anda sol araç çubuğunuzda
+	</string>
+	<string name="Toolbar_Right_Tooltip">
+		şu anda sağ araç çubuğunuzda
 	</string>
 	<string name="Retain%">
 		Koru %
@@ -4947,4 +4983,19 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 	<string name="Normal">
 		Normal
 	</string>
+	<string name="snapshot_quality_very_low">
+		Çok Düşük
+	</string>
+	<string name="snapshot_quality_low">
+		Düşük
+	</string>
+	<string name="snapshot_quality_medium">
+		Orta
+	</string>
+	<string name="snapshot_quality_high">
+		Yüksek
+	</string>
+	<string name="snapshot_quality_very_high">
+		Çok Yüksek
+	</string>
 </strings>
diff --git a/indra/newview/skins/default/xui/tr/teleport_strings.xml b/indra/newview/skins/default/xui/tr/teleport_strings.xml
index c506bb8a58..62aaaf671f 100644
--- a/indra/newview/skins/default/xui/tr/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/tr/teleport_strings.xml
@@ -21,8 +21,8 @@ Hala ışınlanamıyorsanız, sorunu çözmek için lütfen çıkış yapıp otu
 Bir dakika sonra tekrar deneyin.
 		</message>
 		<message name="NoHelpIslandTP">
-You cannot teleport back to Welcome Island.
-Go to &apos;Welcome Island Public&apos; to repeat the tutorial.
+			Karşılama Ada&apos;sına geri ışınlanamazsınız.
+Öğreticiyi tekrarlamak için &apos;Karşılama Ada&apos;sı Kamusal Alanı&apos;na gidin.
 		</message>
 		<message name="noaccess_tport">
 			Üzgünüz, bu ışınlanma hedef konumuna erişim hakkına sahip değilsiniz.
-- 
cgit v1.2.3


From 00b767e5a91d9e3379119c867164f9be40f888cc Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 11 Jan 2012 10:05:15 -0800
Subject: EXP-1791 - Handle case where initialization with SLM fails in the
 Merchant Outbox floater in the viewer

* Added code to clear and re-initialize the SLM cookie when authentication errors are encountered.
* Re-organized logic for outbox import a bit to hopefully be more robust when errors are encountered.
---
 indra/newview/llfloateroutbox.cpp                  |  38 +++--
 indra/newview/llfloateroutbox.h                    |   1 +
 indra/newview/llmarketplacefunctions.cpp           | 175 +++++++++++++--------
 indra/newview/llmarketplacefunctions.h             |   4 +
 .../newview/skins/default/xui/en/notifications.xml |  14 ++
 5 files changed, 157 insertions(+), 75 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 6ecf715588..28589f5e9a 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -250,12 +250,12 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
 	// Initialize the marketplace import API
 	//
 	
-	mImportBusy = true;
-	setStatusString(getString("OutboxInitializing"));
-
-	LLMarketplaceInventoryImporter::getInstance()->initialize();
-	LLMarketplaceInventoryImporter::getInstance()->setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
-	LLMarketplaceInventoryImporter::getInstance()->setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
+	LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance();
+	
+	importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2));
+	importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
+	importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
+	importer.initialize();
 }
 
 void LLFloaterOutbox::setStatusString(const std::string& statusString)
@@ -403,7 +403,7 @@ void LLFloaterOutbox::onImportButtonClicked()
 {
 	mOutboxInventoryPanel->clearSelection();
 
-	LLMarketplaceInventoryImporter::instance().triggerImport();
+	mImportBusy = LLMarketplaceInventoryImporter::instance().triggerImport();
 }
 
 void LLFloaterOutbox::onOutboxChanged()
@@ -449,10 +449,14 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress)
 {
 	if (inProgress)
 	{
-		if (!mImportBusy)
+		if (mImportBusy)
 		{
 			setStatusString(getString("OutboxImporting"));
 		}
+		else
+		{
+			setStatusString(getString("OutboxInitializing"));
+		}
 		
 		mImportBusy = true;
 		mImportButton->setEnabled(false);
@@ -463,9 +467,25 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress)
 		mImportBusy = false;
 		mImportButton->setEnabled(mOutboxItemCount > 0);
 		mInventoryImportInProgress->setVisible(false);
+	}
+	
+	updateView();
+}
 
-		updateView();
+void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content)
+{
+	if (status != MarketplaceErrorCodes::IMPORT_DONE)
+	{
+		char status_string[16];
+		sprintf(status_string, "%d", status);
+		
+		LLSD subs;
+		subs["[ERROR_CODE]"] = status_string;
+		
+		LLNotificationsUtil::add("OutboxInitFailed", subs);
 	}
+	
+	updateView();
 }
 
 void LLFloaterOutbox::showNotification(const LLSD& notify)
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index 6b4021807c..58b7d6ec98 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -71,6 +71,7 @@ protected:
 
 	void importReportResults(U32 status, const LLSD& content);
 	void importStatusChanged(bool inProgress);
+	void initializationReportError(U32 status, const LLSD& content);
 	
 	void onClose(bool app_quitting);
 	void onOpen(const LLSD& key);
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 9a83c5fcb7..ea6634a39e 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -97,14 +97,15 @@ namespace LLMarketplaceImport
 {
 	// Basic interface for this namespace
 
+	bool hasSessionCookie();
 	bool inProgress();
 	bool resultPending();
 	U32 getResultStatus();
 	const LLSD& getResults();
 
-	void establishMarketplaceSessionCookie();
-	void pollStatus();
-	void triggerImport();
+	bool establishMarketplaceSessionCookie();
+	bool pollStatus();
+	bool triggerImport();
 	
 	// Internal state variables
 
@@ -116,7 +117,6 @@ namespace LLMarketplaceImport
 	static U32 sImportResultStatus = 0;
 	static LLSD sImportResults = LLSD::emptyMap();
 
-	
 	// Responders
 	
 	class LLImportPostResponder : public LLHTTPClient::Responder
@@ -147,7 +147,12 @@ namespace LLMarketplaceImport
 		
 		void completedHeader(U32 status, const std::string& reason, const LLSD& content)
 		{
-			sMarketplaceCookie = content["set-cookie"].asString();
+			const std::string& set_cookie_string = content["set-cookie"].asString();
+			
+			if (!set_cookie_string.empty())
+			{
+				sMarketplaceCookie = set_cookie_string;
+			}
 		}
 		
 		void completed(U32 status, const std::string& reason, const LLSD& content)
@@ -158,6 +163,16 @@ namespace LLMarketplaceImport
 				llinfos << " SLM GET reason: " << reason << llendl;
 				llinfos << " SLM GET content: " << content.asString() << llendl;
 			}
+			
+			if (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR)
+			{
+				if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
+				{
+					llinfos << " SLM GET clearing marketplace cookie due to authentication failure" << llendl;
+				}
+
+				sMarketplaceCookie.clear();
+			}
 
 			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
 			sImportGetPending = false;
@@ -165,56 +180,14 @@ namespace LLMarketplaceImport
 			sImportResults = content;
 		}
 	};
-	
-	// Coroutine testing
-/*
-	std::string gTimeDelayDebugFunc = "";
-	
-	void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
-	{
-		waitForEventOn(self, "mainloop");
-		
-		LLTimer delayTimer;
-		delayTimer.reset();
-		delayTimer.setTimerExpirySec(5.0f);
-		
-		while (!delayTimer.hasExpired())
-		{
-			waitForEventOn(self, "mainloop");
-		}
-		
-		outboxPanel->onImportPostComplete(MarketplaceErrorCodes::IMPORT_DONE, LLSD::emptyMap());
-		
-		gTimeDelayDebugFunc = "";
-	}
-	
-	std::string gImportPollingFunc = "";
-	
-	void importPoll(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
+
+	// Basic API
+
+	bool hasSessionCookie()
 	{
-		waitForEventOn(self, "mainloop");
-		
-		while (outboxPanel->isImportInProgress())
-		{
-			LLTimer delayTimer;
-			delayTimer.reset();
-			delayTimer.setTimerExpirySec(5.0f);
-			
-			while (!delayTimer.hasExpired())
-			{
-				waitForEventOn(self, "mainloop");
-			}
-			
-			//outboxPanel->
-		}
-		
-		gImportPollingFunc = "";
+		return !sMarketplaceCookie.empty();
 	}
 	
-*/	
-	
-	// Basic API
-
 	bool inProgress()
 	{
 		return sImportInProgress;
@@ -246,8 +219,13 @@ namespace LLMarketplaceImport
 		return url;
 	}
 	
-	void establishMarketplaceSessionCookie()
+	bool establishMarketplaceSessionCookie()
 	{
+		if (hasSessionCookie())
+		{
+			return false;
+		}
+
 		sImportInProgress = true;
 		sImportGetPending = true;
 		
@@ -259,10 +237,17 @@ namespace LLMarketplaceImport
 		}
 
 		LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders());
+		
+		return true;
 	}
 	
-	void pollStatus()
+	bool pollStatus()
 	{
+		if (!hasSessionCookie())
+		{
+			return false;
+		}
+		
 		sImportGetPending = true;
 
 		std::string url = getInventoryImportURL();
@@ -282,10 +267,17 @@ namespace LLMarketplaceImport
 		}
 
 		LLHTTPClient::get(url, new LLImportGetResponder(), headers);
+		
+		return true;
 	}
 	
-	void triggerImport()
+	bool triggerImport()
 	{
+		if (!hasSessionCookie())
+		{
+			return false;
+		}
+
 		sImportId = LLSD::emptyMap();
 		sImportInProgress = true;
 		sImportPostPending = true;
@@ -309,8 +301,7 @@ namespace LLMarketplaceImport
 
 		LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers);
 		
-		// Set a timer (for testing only)
-		//gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this));
+		return true;
 	}
 }
 
@@ -330,8 +321,10 @@ void LLMarketplaceInventoryImporter::update()
 }
 
 LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter()
-	: mImportInProgress(false)
+	: mAutoTriggerImport(false)
+	, mImportInProgress(false)
 	, mInitialized(false)
+	, mErrorInitSignal(NULL)
 	, mStatusChangedSignal(NULL)
 	, mStatusReportSignal(NULL)
 {
@@ -339,12 +332,24 @@ LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter()
 
 void LLMarketplaceInventoryImporter::initialize()
 {
-	if (!mInitialized)
+	llassert(!mInitialized);
+	
+	if (!LLMarketplaceImport::hasSessionCookie())
 	{
 		LLMarketplaceImport::establishMarketplaceSessionCookie();
 	}
 }
 
+boost::signals2::connection LLMarketplaceInventoryImporter::setInitializationErrorCallback(const status_report_signal_t::slot_type& cb)
+{
+	if (mErrorInitSignal == NULL)
+	{
+		mErrorInitSignal = new status_report_signal_t();
+	}
+	
+	return mErrorInitSignal->connect(cb);
+}
+
 boost::signals2::connection LLMarketplaceInventoryImporter::setStatusChangedCallback(const status_changed_signal_t::slot_type& cb)
 {
 	if (mStatusChangedSignal == NULL)
@@ -367,9 +372,18 @@ boost::signals2::connection LLMarketplaceInventoryImporter::setStatusReportCallb
 
 bool LLMarketplaceInventoryImporter::triggerImport()
 {
-	LLMarketplaceImport::triggerImport();
+	const bool import_triggered = LLMarketplaceImport::triggerImport();
 	
-	return LLMarketplaceImport::inProgress();
+	if (!import_triggered)
+	{
+		mInitialized = false;
+
+		initialize();
+		
+		mAutoTriggerImport = true;
+	}
+	
+	return import_triggered;
 }
 
 void LLMarketplaceInventoryImporter::updateImport()
@@ -378,7 +392,16 @@ void LLMarketplaceInventoryImporter::updateImport()
 	
 	if (in_progress && !LLMarketplaceImport::resultPending())
 	{
-		LLMarketplaceImport::pollStatus();
+		const bool polling_status = LLMarketplaceImport::pollStatus();
+		
+		if (!polling_status)
+		{
+			mInitialized = false;
+			
+			initialize();
+			
+			mAutoTriggerImport = true;
+		}
 	}	
 	
 	if (mImportInProgress != in_progress)
@@ -390,16 +413,36 @@ void LLMarketplaceInventoryImporter::updateImport()
 			(*mStatusChangedSignal)(mImportInProgress);
 		}
 		
-		// If we are no longer in progress, report results
-		if (!mImportInProgress && mStatusReportSignal)
+		// If we are no longer in progress
+		if (!mImportInProgress)
 		{
 			if (mInitialized)
 			{
-				(*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults());
+				// Report results
+				if (mStatusReportSignal)
+				{
+					(*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults());
+				}
 			}
 			else
 			{
-				mInitialized = true;
+				// Look for results success
+				mInitialized = LLMarketplaceImport::hasSessionCookie();
+				
+				if (mInitialized)
+				{
+					// Follow up with auto trigger of import
+					if (mAutoTriggerImport)
+					{
+						mAutoTriggerImport = false;
+
+						triggerImport();
+					}
+				}
+				else if (mErrorInitSignal)
+				{
+					(*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults());
+				}
 			}
 		}
 	}
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index f501f1ee8b..b2f6cb7521 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -46,6 +46,7 @@ namespace MarketplaceErrorCodes
 	{
 		IMPORT_DONE = 200,
 		IMPORT_PROCESSING = 202,
+		IMPORT_AUTHENTICATION_ERROR = 401,
 		IMPORT_DONE_WITH_ERRORS = 409,
 		IMPORT_JOB_FAILED = 410,
 	};
@@ -65,6 +66,7 @@ public:
 	typedef boost::signals2::signal<void (bool)> status_changed_signal_t;
 	typedef boost::signals2::signal<void (U32, const LLSD&)> status_report_signal_t;
 
+	boost::signals2::connection setInitializationErrorCallback(const status_report_signal_t::slot_type& cb);
 	boost::signals2::connection setStatusChangedCallback(const status_changed_signal_t::slot_type& cb);
 	boost::signals2::connection setStatusReportCallback(const status_report_signal_t::slot_type& cb);
 	
@@ -75,9 +77,11 @@ protected:
 	void updateImport();
 	
 private:
+	bool mAutoTriggerImport;
 	bool mImportInProgress;
 	bool mInitialized;
 	
+	status_report_signal_t *	mErrorInitSignal;
 	status_changed_signal_t *	mStatusChangedSignal;
 	status_report_signal_t *	mStatusReportSignal;
 };
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index bcb3a105ea..2269703cb6 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -252,6 +252,20 @@ Error [ERROR_CODE]
          yestext="OK"/>
   </notification>
 
+  <notification
+   icon="OutboxStatus_Error"
+   name="OutboxInitFailed"
+   type="outbox">
+Marketplace initialization failed
+
+Initialization with the Marketplace failed because of a system or network error.  Try again later.
+
+Error [ERROR_CODE]
+
+        <usetemplate
+         name="okbutton"
+         yestext="OK"/>
+  </notification>
     
 
     <notification
-- 
cgit v1.2.3


From 3169f4a96fd4c62d1390cd53ff2aaa4cb28fb047 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 11 Jan 2012 10:19:11 -0800
Subject: assert for updating views while drawing was too aggressive made
 assert match actual error condition for list iterators

reviewed by Leslie
---
 indra/llui/llview.cpp | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 542f57ee5f..004681325f 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -282,9 +282,6 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child)
 // virtual
 bool LLView::addChild(LLView* child, S32 tab_group)
 {
-	// NOTE: Changed this to not crash in release mode
-	llassert(mInDraw == false);
-
 	if (!child)
 	{
 		return false;
@@ -334,10 +331,11 @@ bool LLView::addChildInBack(LLView* child, S32 tab_group)
 // remove the specified child from the view, and set it's parent to NULL.
 void LLView::removeChild(LLView* child)
 {
-	llassert_always(mInDraw == false);
 	//llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs
 	if (child->mParentView == this) 
 	{
+		// if we are removing an item we are currently iterating over, that would be bad
+		llassert(child->mInDraw == false);
 		mChildList.remove( child );
 		child->mParentView = NULL;
 		if (child->isCtrl())
@@ -1086,7 +1084,6 @@ void LLView::draw()
 
 void LLView::drawChildren()
 {
-	mInDraw = true;
 	if (!mChildList.empty())
 	{
 		LLView* rootp = LLUI::getRootView();		
@@ -1105,7 +1102,10 @@ void LLView::drawChildren()
 					LLUI::pushMatrix();
 					{
 						LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
+						// flag the fact we are in draw here, in case overridden draw() method attempts to remove this widget
+						viewp->mInDraw = true;
 						viewp->draw();
+						viewp->mInDraw = false;
 
 						if (sDebugRects)
 						{
@@ -1125,7 +1125,6 @@ void LLView::drawChildren()
 		}
 		--sDepth;
 	}
-	mInDraw = false;
 }
 
 void LLView::dirtyRect()
-- 
cgit v1.2.3


From 0a1cb4f03ee1aeb0cfc9d9bdb837043d0f46f292 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 11 Jan 2012 11:26:56 -0800
Subject: EXP-1791 FIX -- Handle case where initialization with SLM fails in
 the Merchant Outbox floater in the viewer

* Updated marketplace import to properly handle failed cases of authentications
  and invalid cookies.  The import will reset to an uninitialized state and then
  trigger and initialization followed immediately by an import when appropriate.
---
 indra/newview/llfloateroutbox.cpp                  |  1 -
 indra/newview/llmarketplacefunctions.cpp           | 67 +++++++++++++---------
 indra/newview/llmarketplacefunctions.h             |  5 +-
 .../newview/skins/default/xui/en/notifications.xml |  7 +--
 4 files changed, 45 insertions(+), 35 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 28589f5e9a..130c26acdc 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -438,7 +438,6 @@ void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
 		LLSD subs;
 		subs["[ERROR_CODE]"] = status_string;
 		
-		//llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED);
 		LLNotificationsUtil::add("OutboxImportFailed", subs);
 	}
 	
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index ea6634a39e..84cbe3cac2 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -133,6 +133,17 @@ namespace LLMarketplaceImport
 				llinfos << " SLM POST content: " << content.asString() << llendl;
 			}
 
+			if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) ||
+				(status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR))
+			{
+				if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
+				{
+					llinfos << " SLM POST clearing marketplace cookie due to authentication failure" << llendl;
+				}
+
+				sMarketplaceCookie.clear();
+			}
+
 			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
 			sImportPostPending = false;
 			sImportResultStatus = status;
@@ -330,16 +341,6 @@ LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter()
 {
 }
 
-void LLMarketplaceInventoryImporter::initialize()
-{
-	llassert(!mInitialized);
-	
-	if (!LLMarketplaceImport::hasSessionCookie())
-	{
-		LLMarketplaceImport::establishMarketplaceSessionCookie();
-	}
-}
-
 boost::signals2::connection LLMarketplaceInventoryImporter::setInitializationErrorCallback(const status_report_signal_t::slot_type& cb)
 {
 	if (mErrorInitSignal == NULL)
@@ -370,17 +371,32 @@ boost::signals2::connection LLMarketplaceInventoryImporter::setStatusReportCallb
 	return mStatusReportSignal->connect(cb);
 }
 
+void LLMarketplaceInventoryImporter::initialize()
+{
+	llassert(!mInitialized);
+
+	if (!LLMarketplaceImport::hasSessionCookie())
+	{
+		LLMarketplaceImport::establishMarketplaceSessionCookie();
+	}
+}
+
+void LLMarketplaceInventoryImporter::reinitializeAndTriggerImport()
+{
+	mInitialized = false;
+
+	initialize();
+
+	mAutoTriggerImport = true;
+}
+
 bool LLMarketplaceInventoryImporter::triggerImport()
 {
 	const bool import_triggered = LLMarketplaceImport::triggerImport();
 	
 	if (!import_triggered)
 	{
-		mInitialized = false;
-
-		initialize();
-		
-		mAutoTriggerImport = true;
+		reinitializeAndTriggerImport();
 	}
 	
 	return import_triggered;
@@ -396,23 +412,14 @@ void LLMarketplaceInventoryImporter::updateImport()
 		
 		if (!polling_status)
 		{
-			mInitialized = false;
-			
-			initialize();
-			
-			mAutoTriggerImport = true;
+			reinitializeAndTriggerImport();
 		}
 	}	
 	
 	if (mImportInProgress != in_progress)
 	{
 		mImportInProgress = in_progress;
-		
-		if (mStatusChangedSignal)
-		{
-			(*mStatusChangedSignal)(mImportInProgress);
-		}
-		
+
 		// If we are no longer in progress
 		if (!mImportInProgress)
 		{
@@ -436,7 +443,7 @@ void LLMarketplaceInventoryImporter::updateImport()
 					{
 						mAutoTriggerImport = false;
 
-						triggerImport();
+						mImportInProgress = triggerImport();
 					}
 				}
 				else if (mErrorInitSignal)
@@ -445,6 +452,12 @@ void LLMarketplaceInventoryImporter::updateImport()
 				}
 			}
 		}
+
+		// Make sure we trigger the status change with the final state (in case of auto trigger after initialize)
+		if (mStatusChangedSignal)
+		{
+			(*mStatusChangedSignal)(mImportInProgress);
+		}
 	}
 }
 
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index b2f6cb7521..78df86ef3e 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -46,6 +46,7 @@ namespace MarketplaceErrorCodes
 	{
 		IMPORT_DONE = 200,
 		IMPORT_PROCESSING = 202,
+		IMPORT_REDIRECT = 302,
 		IMPORT_AUTHENTICATION_ERROR = 401,
 		IMPORT_DONE_WITH_ERRORS = 409,
 		IMPORT_JOB_FAILED = 410,
@@ -61,8 +62,6 @@ public:
 	
 	LLMarketplaceInventoryImporter();
 	
-	void initialize();
-
 	typedef boost::signals2::signal<void (bool)> status_changed_signal_t;
 	typedef boost::signals2::signal<void (U32, const LLSD&)> status_report_signal_t;
 
@@ -70,10 +69,12 @@ public:
 	boost::signals2::connection setStatusChangedCallback(const status_changed_signal_t::slot_type& cb);
 	boost::signals2::connection setStatusReportCallback(const status_report_signal_t::slot_type& cb);
 	
+	void initialize();
 	bool triggerImport();
 	bool isImportInProgress() const { return mImportInProgress; }
 	
 protected:
+	void reinitializeAndTriggerImport();
 	void updateImport();
 	
 private:
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 2269703cb6..61346bf3d6 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -230,8 +230,9 @@ All folders were successfully sent to the Marketplace.
    type="outbox">
 Some folders did not transfer
 
-Errors occurred when some folders were sent to the Marketplace.  Those folders are still in your Merchant Outbox.  See the error log for more information.
+Errors occurred when some folders were sent to the Marketplace.  Those folders are still in your Merchant Outbox.
 
+See the error log for more information.
         <usetemplate
          name="okbutton"
          yestext="OK"/>
@@ -245,8 +246,6 @@ Transfer failed
 
 No folders were sent to the Marketplace because of a system or network error.  Try again later.
 
-Error [ERROR_CODE]
-
         <usetemplate
          name="okbutton"
          yestext="OK"/>
@@ -260,8 +259,6 @@ Marketplace initialization failed
 
 Initialization with the Marketplace failed because of a system or network error.  Try again later.
 
-Error [ERROR_CODE]
-
         <usetemplate
          name="okbutton"
          yestext="OK"/>
-- 
cgit v1.2.3


From 98f071aa6fc2961d9a86fa1d174c1f988a6ef8dc Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 11 Jan 2012 11:59:34 -0800
Subject: EXP-1790 FIX -- Hitting return on item in Merchant Outbox wears the
 object

* Disabled the "openItem" function on outbox items to prevent default behavior
  when the return button is pressed.
---
 indra/newview/llpanelmarketplaceoutboxinventory.cpp | 5 +++++
 indra/newview/llpanelmarketplaceoutboxinventory.h   | 1 +
 2 files changed, 6 insertions(+)

diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp
index c14a0c8379..ff62cb23db 100644
--- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp
+++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp
@@ -148,4 +148,9 @@ BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask)
 	return TRUE;
 }
 
+void LLOutboxFolderViewItem::openItem()
+{
+	// Intentionally do nothing to block attaching items from the outbox
+}
+
 // eof
diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.h b/indra/newview/llpanelmarketplaceoutboxinventory.h
index 167f371f0e..a6c522b7c2 100644
--- a/indra/newview/llpanelmarketplaceoutboxinventory.h
+++ b/indra/newview/llpanelmarketplaceoutboxinventory.h
@@ -71,6 +71,7 @@ public:
 
 	// virtual
 	BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+	void openItem();
 };
 
 
-- 
cgit v1.2.3


From 542c31d547a7a42cd81c2a535805d30b164e31e4 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 11 Jan 2012 13:37:43 -0800
Subject: EXP-1788 FIX -- Outbox drag and drop restrictions can be bypassed if
 inventory not fully loaded

* The "Copy to Outbox" option is now disabled when the item is in the loading state.
---
 indra/newview/llfolderviewitem.h    |   2 +
 indra/newview/llinventorybridge.cpp | 118 ++++++++++++++++++++++--------------
 indra/newview/llinventorybridge.h   |   6 +-
 3 files changed, 76 insertions(+), 50 deletions(-)

diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 0f8c3edef8..5a0e58ea0e 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -122,6 +122,8 @@ public:
 
 	// Mostly for debugging printout purposes.
 	const std::string& getSearchableLabel() { return mSearchableLabel; }
+	
+	BOOL isLoading() const { return mIsLoading; }
 
 private:
 	BOOL						mIsSelected;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 8abb6d66ad..e75ef20c6a 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1088,108 +1088,132 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
 	}
 }
 
-BOOL LLInvFVBridge::canShare() const
+bool LLInvFVBridge::canShare() const
 {
-	if (!isAgentInventory()) return FALSE;
+	bool can_share = false;
 
-	const LLInventoryModel* model = getInventoryModel();
-	if (!model) return FALSE;
-
-	const LLViewerInventoryItem *item = model->getItem(mUUID);
-	if (item)
+	if (isAgentInventory())
 	{
-		if (!LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item)) 
-			return FALSE;
-		return (BOOL)LLGiveInventory::isInventoryGiveAcceptable(item);
+		const LLInventoryModel* model = getInventoryModel();
+		if (model)
+		{
+			const LLViewerInventoryItem *item = model->getItem(mUUID);
+			if (item)
+			{
+				if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item)) 
+				{
+					can_share = LLGiveInventory::isInventoryGiveAcceptable(item);
+				}
+			}
+			else
+			{
+				// Categories can be given.
+				can_share = (model->getCategory(mUUID) != NULL);
+			}
+		}
 	}
 
-	// Categories can be given.
-	if (model->getCategory(mUUID)) return TRUE;
-
-	return FALSE;
+	return can_share;
 }
 
-BOOL LLInvFVBridge::canListOnMarketplace() const
+bool LLInvFVBridge::canListOnMarketplace() const
 {
 #if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+
 	LLInventoryModel * model = getInventoryModel();
+
 	const LLViewerInventoryCategory * cat = model->getCategory(mUUID);
 	if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
 	{
-		return FALSE;
+		return false;
 	}
 
 	if (!isAgentInventory())
 	{
-		return FALSE;
+		return false;
 	}
 	
 	if (getOutboxFolder().isNull())
 	{
-		return FALSE;
+		return false;
 	}
 
 	if (isInboxFolder() || isOutboxFolder())
 	{
-		return FALSE;
+		return false;
 	}
 	
 	const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
 	if (outbox_id.isNull())
 	{
-		return FALSE;
+		return false;
 	}
 
 	LLViewerInventoryItem * item = model->getItem(mUUID);
 	if (item && !item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
 	{
-		return FALSE;
+		return false;
 	}
 
-	return TRUE;
+	return true;
+
 #else
-	return FALSE;
+	return false;
 #endif
 }
 
-BOOL LLInvFVBridge::canListOnMarketplaceNow() const
+bool LLInvFVBridge::canListOnMarketplaceNow() const
 {
-	BOOL can_list = FALSE;
-	
 #if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+	
+	bool can_list = true;
 
+	// Do not allow listing while import is in progress
+	if (LLMarketplaceInventoryImporter::instanceExists())
+	{
+		can_list = !LLMarketplaceInventoryImporter::instance().isImportInProgress();
+	}
+	
 	const LLInventoryObject* obj = getInventoryObject();
 
-	if (obj)
+	if (obj && can_list)
 	{
-		// Get outbox id
-		const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
-		LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id);
+		const LLUUID& object_id = obj->getLinkedUUID();
+		can_list = object_id.notNull();
 
-		if (outbox_itemp)
+		if (can_list)
 		{
-			MASK mask = 0x0;
-			BOOL drop = FALSE;
-			EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
-			void * cargo_data = (void *) obj;
-			std::string tooltip_msg;
-			
-			can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
+			LLFolderViewFolder * object_folderp = mRoot->getFolderByID(object_id);
+			if (object_folderp)
+			{
+				can_list = !object_folderp->isLoading();
+			}
 		}
-	}
-
-	// Do not allow listing while import is in progress
-	if (LLMarketplaceInventoryImporter::instanceExists())
-	{
-		if (LLMarketplaceInventoryImporter::instance().isImportInProgress())
+		
+		if (can_list)
 		{
-			can_list = FALSE;
+			// Get outbox id
+			const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+			LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id);
+
+			if (outbox_itemp)
+			{
+				MASK mask = 0x0;
+				BOOL drop = FALSE;
+				EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
+				void * cargo_data = (void *) obj;
+				std::string tooltip_msg;
+				
+				can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
+			}
 		}
 	}
+	
+	return can_list;
 
+#else
+	return false;
 #endif
-
-	return can_list;
 }
 
 
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 2ab339b918..cb378b7d7a 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -69,9 +69,9 @@ public:
 									   U32 flags = 0x00);
 	virtual ~LLInvFVBridge() {}
 
-	BOOL canShare() const;
-	BOOL canListOnMarketplace() const;
-	BOOL canListOnMarketplaceNow() const;
+	bool canShare() const;
+	bool canListOnMarketplace() const;
+	bool canListOnMarketplaceNow() const;
 
 	//--------------------------------------------------------------------
 	// LLInvFVBridge functionality
-- 
cgit v1.2.3


From 59950f6178699b96e86bfd2c0bc701271b3f1a6b Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 11 Jan 2012 16:49:32 -0800
Subject: EXP-1778 FIX -- Link to Marketplace Error log in transfer failed
 viewer notification

* Added a link to the "imports" log from the "done with errors" notification when
  sending folders to the marketplace.
---
 indra/newview/llfloateroutbox.cpp                    |  6 ++++--
 indra/newview/llmarketplacefunctions.cpp             | 12 +++++-------
 indra/newview/llmarketplacefunctions.h               |  2 +-
 indra/newview/skins/default/xui/en/notifications.xml |  3 ++-
 indra/newview/skins/default/xui/en/strings.xml       |  1 +
 5 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 130c26acdc..597602d5ab 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -332,7 +332,7 @@ void LLFloaterOutbox::updateView()
 		std::string outbox_title;
 		std::string outbox_tooltip;
 		
-		LLStringUtil::format_map_t subs = getMarketplaceStringSubstitutions();
+		const LLSD& subs = getMarketplaceStringSubstitutions();
 		
 		if (mOutboxId.notNull())
 		{
@@ -428,7 +428,9 @@ void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
 	}
 	else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
 	{
-		LLNotificationsUtil::add("OutboxImportHadErrors");
+		const LLSD& subs = getMarketplaceStringSubstitutions();
+
+		LLNotificationsUtil::add("OutboxImportHadErrors", subs);
 	}
 	else
 	{
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 84cbe3cac2..ee7505c4f4 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -72,23 +72,21 @@ static std::string getMarketplaceURL(const std::string& urlStringName)
 	return marketplace_url;
 }
 
-LLStringUtil::format_map_t getMarketplaceStringSubstitutions()
+LLSD getMarketplaceStringSubstitutions()
 {
 	std::string marketplace_url = getMarketplaceURL("MarketplaceURL");
 	std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore");
 	std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard");
+	std::string marketplace_url_imports = getMarketplaceURL("MarketplaceURL_Imports");
 	std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore");
 	
-	LLStringUtil::format_map_t agent_map;
-	agent_map["[AGENT_ID]"] = gAgent.getID().getString();
-	
-	LLStringUtil::format(marketplace_url_dashboard, agent_map);
-	
-	LLStringUtil::format_map_t marketplace_sub_map;
+	LLSD marketplace_sub_map;
+
 	marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url;
 	marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create;
 	marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info;
 	marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard;
+	marketplace_sub_map["[MARKETPLACE_IMPORTS_URL]"] = marketplace_url_imports;
 	
 	return marketplace_sub_map;
 }
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index 78df86ef3e..4731566366 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -37,7 +37,7 @@
 #include "llstring.h"
 
 
-LLStringUtil::format_map_t getMarketplaceStringSubstitutions();
+LLSD getMarketplaceStringSubstitutions();
 
 
 namespace MarketplaceErrorCodes
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 61346bf3d6..657d9fe91a 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -232,7 +232,8 @@ Some folders did not transfer
 
 Errors occurred when some folders were sent to the Marketplace.  Those folders are still in your Merchant Outbox.
 
-See the error log for more information.
+See the [[MARKETPLACE_IMPORTS_URL] error log] for more information.
+
         <usetemplate
          name="okbutton"
          yestext="OK"/>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index a78f3df5b6..84fce6630b 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2040,6 +2040,7 @@ Returns a string with the requested data about the region
 	<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string>
 	<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string>
 	<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string>
+	<string name="MarketplaceURL_Imports">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports</string>
 	<string name="MarketplaceURL_LearnMore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more</string>
 	<string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace.</string>
 	<string name="InventoryOutboxNotMerchantTooltip"></string>
-- 
cgit v1.2.3


From 6452154b19c6592efaf27e07bbee3bc6bcd3a415 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 11 Jan 2012 16:53:08 -0800
Subject: Correcting logic back to way it was, to make sure invalid objects can
 not be copied to the outbox

---
 indra/newview/llinventorybridge.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index e75ef20c6a..1d7406883c 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1175,8 +1175,9 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const
 	}
 	
 	const LLInventoryObject* obj = getInventoryObject();
+	can_list &= (obj != NULL);
 
-	if (obj && can_list)
+	if (can_list)
 	{
 		const LLUUID& object_id = obj->getLinkedUUID();
 		can_list = object_id.notNull();
-- 
cgit v1.2.3


From b41e66c1cb7d48ef600588fa2b57e43f80860c71 Mon Sep 17 00:00:00 2001
From: callum <none@none>
Date: Wed, 11 Jan 2012 17:15:06 -0800
Subject: EXP-1511 REFIX Preview image overlays ui elements in Upload image
 floater Tweaked offset and missed a corner case

---
 indra/newview/llfloaterimagepreview.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index cc279049ca..92ee8ddac6 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -63,7 +63,7 @@
 const S32 PREVIEW_BORDER_WIDTH = 2;
 const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
 const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
-const S32 PREVIEW_VPAD = 32;	// yuk, hard coded
+const S32 PREVIEW_VPAD = -24;	// yuk, hard coded
 const S32 PREF_BUTTON_HEIGHT = 16 + 7 + 16;
 const S32 PREVIEW_TEXTURE_HEIGHT = 320;
 
@@ -304,13 +304,13 @@ void LLFloaterImagePreview::draw()
 				gGL.begin( LLRender::QUADS );
 				{
 					gGL.texCoord2f(0.f, 1.f);
-					gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
+					gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
 					gGL.texCoord2f(0.f, 0.f);
 					gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
 					gGL.texCoord2f(1.f, 0.f);
 					gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
 					gGL.texCoord2f(1.f, 1.f);
-					gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
+					gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
 				}
 				gGL.end();
 
-- 
cgit v1.2.3


From 1307fad7c9f7a1130242a4de7e0144ba4dea6297 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 11 Jan 2012 17:32:22 -0800
Subject: EXP-1752 FIX -- Merchant outbox import completion success modal
 dialog needs checkbox to disable EXP-1795 PROGRESS -- Update warning dialog
 for dragging and dropping no-copy items to Merchant Outbox

* The text associated with EXP-1795 has been updated but the "apply to all"
  checkbox has not been implemented yet.
* Updated the "0 folders" text to be an empty string instead.
---
 .../newview/skins/default/xui/en/floater_merchant_outbox.xml |  2 +-
 indra/newview/skins/default/xui/en/notifications.xml         | 12 +++++++-----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index 741515d56c..c0f26413cb 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -13,7 +13,7 @@
  reuse_instance="true"
  title="MERCHANT OUTBOX"
  width="333" >
- <string name="OutboxFolderCount0">0 folders</string>
+ <string name="OutboxFolderCount0"></string>
  <string name="OutboxFolderCount1">1 folder</string>
  <string name="OutboxFolderCountN">[NUM] folders</string>
  <string name="OutboxImporting">Sending folders...</string>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 657d9fe91a..387cee3cee 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -203,12 +203,13 @@ Save changes to current clothing/body part?
    icon="alertmodal.tga"
      name="ConfirmNoCopyToOutbox"
      type="alertmodal">
-You don't have permission to copy this item to the Marketplace Outbox. Are you sure you want to move the following item?
+You don't have permission to copy this item to the Merchant Outbox. You can move it or leave it behind.
+
 [ITEM_NAME]
         <usetemplate
-         name="okcancelbuttons"
-         notext="No"
-         yestext="Yes"/>
+         name="yesnocancelbuttons"
+         notext="Don't move item"
+         yestext="Move item"/>
     </notification>
 
   <notification
@@ -220,7 +221,8 @@ Success
 All folders were successfully sent to the Marketplace.
 
         <usetemplate
-         name="okbutton"
+         ignoretext="All folders sent to the Marketplace"
+         name="okignore"
          yestext="OK"/>
   </notification>
 
-- 
cgit v1.2.3


From 33a17d8a83b3810e344e663395219d3130cb34c3 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 11 Jan 2012 17:43:17 -0800
Subject: EXP-1549 : Disable the Remove button menu item in the toolbar
 contextual menu if no button clicked

---
 indra/llui/lltoolbar.cpp | 9 ++++++++-
 indra/llui/lltoolbar.h   | 1 +
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index 7f96c1373c..9b31a6449d 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -151,14 +151,20 @@ void LLToolBar::createContextMenu()
 		if (menu)
 		{
 			menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
-
 			mPopupMenuHandle = menu->getHandle();
+			mRemoveButtonHandle = menu->getChild<LLView>("Remove button")->getHandle();
 		}
 		else
 		{
 			llwarns << "Unable to load toolbars context menu." << llendl;
 		}
 	}
+	
+	if (mRemoveButtonHandle.get())
+	{
+		// Disable/Enable the "Remove button" menu item depending on whether or not a button was clicked
+		mRemoveButtonHandle.get()->setEnabled(mRightMouseTargetButton != NULL);
+	}
 }
 
 void LLToolBar::initFromParams(const LLToolBar::Params& p)
@@ -401,6 +407,7 @@ BOOL LLToolBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
 	{
 		// Determine which button the mouse was over during the click in case the context menu action
 		// is intended to affect the button.
+		mRightMouseTargetButton = NULL;
 		BOOST_FOREACH(LLToolBarButton* button, mButtons)
 		{
 			LLRect button_rect;
diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h
index 51fe23ddd1..a50c60282c 100644
--- a/indra/llui/lltoolbar.h
+++ b/indra/llui/lltoolbar.h
@@ -271,6 +271,7 @@ private:
 	LLLayoutStack*					mCenteringStack;
 	LLPanel*						mButtonPanel;
 	LLHandle<class LLContextMenu>	mPopupMenuHandle;
+	LLHandle<class LLView>			mRemoveButtonHandle;
 
 	LLToolBarButton*				mRightMouseTargetButton;
 
-- 
cgit v1.2.3


From 37c68057c92f5a21a3d21b4ac01690a1cf4cf8e4 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 11 Jan 2012 18:59:35 -0800
Subject: EXP-876 : Avoid ui elements using the same name reference.

---
 .../skins/default/xui/en/floater_model_wizard.xml  | 32 +++++++++++-----------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/floater_model_wizard.xml b/indra/newview/skins/default/xui/en/floater_model_wizard.xml
index 9c0af7d9ba..62b8c5f96e 100644
--- a/indra/newview/skins/default/xui/en/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_wizard.xml
@@ -108,7 +108,7 @@
 		 height="22"
 		 top_pad="15"
 		 width="505"
-		 name="header_panel"
+		 name="choose_file_header_panel"
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
 		 background_opaque="true"
@@ -117,7 +117,7 @@
 			 width="200"
 			 left="10"
 			 top="3"
-			 name="header_text"
+			 name="choose_file_header_text"
 			 text_color="White"
 			 height="10"
 			 font="SansSerifBig"
@@ -130,7 +130,7 @@
 		 left="15"
 		 height="310"
 		 width="505"
-		 name="content"
+		 name="choose_file_content"
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
 		 background_opaque="true">
@@ -287,7 +287,7 @@
 		<panel
 		 height="22"
 		 top_pad="15"
-		 name="header_panel"
+		 name="optimize_header_panel"
 		 width="505"
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
@@ -296,7 +296,7 @@
 			<text
 			 width="200"
 			 left="10"
-			 name="header_text"
+			 name="optimize_header_text"
 			 top="3"
 			 text_color="White"
 			 height="10"
@@ -311,7 +311,7 @@
 		 height="20"
 		 font="SansSerifSmall"
 		 layout="topleft"
-		 name="description"
+		 name="optimize_description"
 		 word_wrap="true"
 		 left_delta="5">
 			We have optimized the model for performance. Adjust it further if you wish.
@@ -322,7 +322,7 @@
 		 left="15"
 		 height="270"
 		 width="505"
-		 name="content"
+		 name="optimize_content"
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
 		 background_opaque="true">
@@ -497,7 +497,7 @@ Higher prim weight</text>
 		<panel
 		 height="22"
 		 top_pad="15"
-		 name="header_panel"
+		 name="physics_header_panel"
 		 width="505"
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
@@ -506,7 +506,7 @@ Higher prim weight</text>
 			<text
 			 width="200"
 			 left="10"
-			 name="header_text"
+			 name="physics_header_text"
 			 top="3"
 			 height="10"
 			 font="SansSerifBig"
@@ -521,7 +521,7 @@ Higher prim weight</text>
 		 height="50"
 		 font="SansSerifSmall"
 		 layout="topleft"
-		 name="description"
+		 name="physics_description"
 		 word_wrap="true"
 		 left_delta="5">
 			We will create a shape for the outer hull of the model. Adjust the shape's detail level as needed for the intended purpose of your model.
@@ -531,7 +531,7 @@ Higher prim weight</text>
 		 left="15"
 		 height="270"
 		 width="505"
-		 name="content"
+		 name="physics_content"
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
 		 background_opaque="true">
@@ -635,7 +635,7 @@ Buildings</text>
 		<panel
 		 height="22"
 		 top_pad="15"
-		 name="header_panel"
+		 name="review_header_panel"
 		 width="505"
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
@@ -644,7 +644,7 @@ Buildings</text>
 			<text
 			 width="200"
 			 left="10"
-			 name="header_text"
+			 name="review_header_text"
 			 text_color="White" 
 			 top="3"
 			 height="10"
@@ -658,7 +658,7 @@ Buildings</text>
 		 left="15"
 		 height="310"
 		 width="505"
-		 name="content"
+		 name="review_content"
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
 		 background_opaque="true">
@@ -706,7 +706,7 @@ Buildings</text>
 		<panel
 		 height="22"
 		 top_pad="15"
-		 name="header_panel"
+		 name="upload_header_panel"
 		 width="505"
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
@@ -715,7 +715,7 @@ Buildings</text>
 			<text
 			 width="200"
 			 left="10"
-			 name="header_text"
+			 name="upload_header_text"
 			 top="3"
 			 text_color="White" 
 			 height="10"
-- 
cgit v1.2.3


From 39a86eda8d6d810bd7f4dd6b96f022548a496ba1 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 12 Jan 2012 12:19:27 -0500
Subject: Add LLStreamQueue::size() and tests to exercise it.

---
 indra/llcommon/llstreamqueue.h              | 11 +++++++++++
 indra/llcommon/tests/llstreamqueue_test.cpp | 30 ++++++++++++++++++++++++-----
 2 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/indra/llcommon/llstreamqueue.h b/indra/llcommon/llstreamqueue.h
index 2fbc2067d2..0726bad175 100644
--- a/indra/llcommon/llstreamqueue.h
+++ b/indra/llcommon/llstreamqueue.h
@@ -53,6 +53,7 @@ class LLGenericStreamQueue
 {
 public:
     LLGenericStreamQueue():
+        mSize(0),
         mClosed(false)
     {}
 
@@ -134,6 +135,7 @@ public:
         // we want this to scale to large data volumes, better to allocate
         // individual pieces.
         mBuffer.push_back(string(s, n));
+        mSize += n;
         return n;
     }
 
@@ -167,10 +169,17 @@ public:
     /// at EOF we simply skip 0 characters.
     std::streamsize skip(std::streamsize n);
 
+    /// How many characters do we currently have buffered?
+    std::streamsize size() const
+    {
+        return mSize;
+    }
+
 private:
     typedef std::basic_string<Ch> string;
     typedef std::list<string> BufferList;
     BufferList mBuffer;
+    std::streamsize mSize;
     bool mClosed;
 };
 
@@ -212,12 +221,14 @@ std::streamsize LLGenericStreamQueue<Ch>::skip(std::streamsize n)
         std::streamsize chunk(bli->length());
         typename BufferList::iterator zap(bli++);
         mBuffer.erase(zap);
+        mSize   -= chunk;
         toskip  -= chunk;
         skipped += chunk;
     }
     if (bli != blend && toskip)
     {
         bli->erase(bli->begin(), bli->begin() + toskip);
+        mSize   -= toskip;
         skipped += toskip;
     }
     return skipped;
diff --git a/indra/llcommon/tests/llstreamqueue_test.cpp b/indra/llcommon/tests/llstreamqueue_test.cpp
index e88c37d5be..050ad5c5bf 100644
--- a/indra/llcommon/tests/llstreamqueue_test.cpp
+++ b/indra/llcommon/tests/llstreamqueue_test.cpp
@@ -50,6 +50,8 @@ namespace tut
     {
         set_test_name("empty LLStreamQueue");
         ensure_equals("brand-new LLStreamQueue isn't empty",
+                      strq.size(), 0);
+        ensure_equals("brand-new LLStreamQueue returns data",
                       strq.asSource().read(&buffer[0], buffer.size()), 0);
         strq.asSink().close();
         ensure_equals("closed empty LLStreamQueue not at EOF",
@@ -62,18 +64,22 @@ namespace tut
         set_test_name("one internal block, one buffer");
         LLStreamQueue::Sink sink(strq.asSink());
         ensure_equals("write(\"\")", sink.write("", 0), 0);
-        ensure_equals("0 write should leave LLStreamQueue empty",
+        ensure_equals("0 write should leave LLStreamQueue empty (size())",
+                      strq.size(), 0);
+        ensure_equals("0 write should leave LLStreamQueue empty (peek())",
                       strq.peek(&buffer[0], buffer.size()), 0);
         // The meaning of "atomic" is that it must be smaller than our buffer.
         std::string atomic("atomic");
         ensure("test data exceeds buffer", atomic.length() < buffer.size());
         ensure_equals(STRINGIZE("write(\"" << atomic << "\")"),
                       sink.write(&atomic[0], atomic.length()), atomic.length());
+        ensure_equals("size() after write()", strq.size(), atomic.length());
         size_t peeklen(strq.peek(&buffer[0], buffer.size()));
         ensure_equals(STRINGIZE("peek(\"" << atomic << "\")"),
                       peeklen, atomic.length());
         ensure_equals(STRINGIZE("peek(\"" << atomic << "\") result"),
                       std::string(buffer.begin(), buffer.begin() + peeklen), atomic);
+        ensure_equals("size() after peek()", strq.size(), atomic.length());
         // peek() should not consume. Use a different buffer to prove it isn't
         // just leftover data from the first peek().
         std::vector<char> again(buffer.size());
@@ -90,6 +96,7 @@ namespace tut
         ensure_equals(STRINGIZE("read(\"" << atomic << "\") result"),
                       std::string(third.begin(), third.begin() + readlen), atomic);
         ensure_equals("peek() after read()", strq.peek(&buffer[0], buffer.size()), 0);
+        ensure_equals("size() after read()", strq.size(), 0);
     }
 
     template<> template<>
@@ -107,6 +114,7 @@ namespace tut
                       std::string(buffer.begin(), buffer.begin() + peeklen), lovecraft);
         std::streamsize skip1(4);
         ensure_equals(STRINGIZE("skip(" << skip1 << ")"), strq.skip(skip1), skip1);
+        ensure_equals("size() after skip()", strq.size(), lovecraft.length() - skip1);
         size_t readlen(strq.read(&buffer[0], buffer.size()));
         ensure_equals(STRINGIZE("read(\"" << lovecraft.substr(skip1) << "\")"),
                       readlen, lovecraft.length() - skip1);
@@ -121,15 +129,20 @@ namespace tut
     {
         set_test_name("skip() multiple blocks");
         std::string blocks[] = { "books of ", "H.P. ", "Lovecraft" };
-        std::streamsize skip(blocks[0].length() + blocks[1].length() + 4);
+        std::streamsize total(blocks[0].length() + blocks[1].length() + blocks[2].length());
+        std::streamsize leave(5);   // len("craft") above
+        std::streamsize skip(total - leave);
+        std::streamsize written(0);
         BOOST_FOREACH(const std::string& block, blocks)
         {
-            strq.write(&block[0], block.length());
+            written += strq.write(&block[0], block.length());
+            ensure_equals("size() after write()", strq.size(), written);
         }
         std::streamsize skiplen(strq.skip(skip));
         ensure_equals(STRINGIZE("skip(" << skip << ")"), skiplen, skip);
+        ensure_equals("size() after skip()", strq.size(), leave);
         size_t readlen(strq.read(&buffer[0], buffer.size()));
-        ensure_equals("read(\"craft\")", readlen, 5);
+        ensure_equals("read(\"craft\")", readlen, leave);
         ensure_equals("read(\"craft\") result",
                       std::string(buffer.begin(), buffer.begin() + readlen), "craft");
     }
@@ -162,14 +175,21 @@ namespace tut
             strq.write(&block[0], block.length());
         }
         strq.close();
+        // We've already verified what strq.size() should be at this point;
+        // see above test named "skip() multiple blocks"
+        std::streamsize chksize(strq.size());
         std::streamsize readlen(strq.read(&buffer[0], buffer.size()));
         ensure_equals("read() 0", readlen, buffer.size());
         ensure_equals("read() 0 result", std::string(buffer.begin(), buffer.end()), "abcdefghij");
+        chksize -= readlen;
+        ensure_equals("size() after read() 0", strq.size(), chksize);
         readlen = strq.read(&buffer[0], buffer.size());
         ensure_equals("read() 1", readlen, buffer.size());
         ensure_equals("read() 1 result", std::string(buffer.begin(), buffer.end()), "klmnopqrst");
+        chksize -= readlen;
+        ensure_equals("size() after read() 1", strq.size(), chksize);
         readlen = strq.read(&buffer[0], buffer.size());
-        ensure_equals("read() 2", readlen, 6);
+        ensure_equals("read() 2", readlen, chksize);
         ensure_equals("read() 2 result",
                       std::string(buffer.begin(), buffer.begin() + readlen), "uvwxyz");
         ensure_equals("read() 3", strq.read(&buffer[0], buffer.size()), -1);
-- 
cgit v1.2.3


From 2ae55b2be6bea2b95a3fa4cc1ca2c4fe14609a4e Mon Sep 17 00:00:00 2001
From: Jonathan Yap <none@none>
Date: Thu, 12 Jan 2012 15:42:31 -0500
Subject: STORM-1798 'Block' menuitem title isn't changed after blocking item
 in object inspector

---
 indra/newview/llviewermenu.cpp                     | 28 ++++++++++++++++++++--
 .../default/xui/en/menu_inspect_object_gear.xml    |  9 +++++++
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 3a1b8d7623..4d6f6a444e 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2762,8 +2762,31 @@ bool enable_object_mute()
 	else
 	{
 		// Just a regular object
-		return LLSelectMgr::getInstance()->getSelection()->
-			contains( object, SELECT_ALL_TES );
+		return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) &&
+			   !LLMuteList::getInstance()->isMuted(object->getID());
+	}
+}
+
+bool enable_object_unmute()
+{
+	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+	if (!object) return false;
+
+	LLVOAvatar* avatar = find_avatar_from_object(object); 
+	if (avatar)
+	{
+		// It's an avatar
+		LLNameValue *lastname = avatar->getNVPair("LastName");
+		bool is_linden =
+			lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
+		bool is_self = avatar->isSelf();
+		return !is_linden && !is_self;
+	}
+	else
+	{
+		// Just a regular object
+		return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) &&
+			   LLMuteList::getInstance()->isMuted(object->getID());;
 	}
 }
 
@@ -8281,6 +8304,7 @@ void initialize_menus()
 
 	enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute));
 	enable.add("Object.EnableMute", boost::bind(&enable_object_mute));
+	enable.add("Object.EnableUnmute", boost::bind(&enable_object_unmute));
 	enable.add("Object.EnableBuy", boost::bind(&enable_buy_object));
 	commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom"));
 
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
index f818ebe2d7..63e154697b 100644
--- a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
@@ -113,6 +113,15 @@
     <menu_item_call.on_visible
      function="Object.EnableMute" />
   </menu_item_call>
+  <menu_item_call
+   label="Unblock"
+   layout="topleft"
+   name="unblock">
+    <menu_item_call.on_click
+     function="Object.Mute" />
+    <menu_item_call.on_visible
+     function="Object.EnableUnmute" />
+  </menu_item_call>
   <menu_item_call
     label="Zoom In"
     layout="topleft"
-- 
cgit v1.2.3


From ec2b0e3af34bee7870283e5af2d16f879ad68f1b Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 12 Jan 2012 14:17:47 -0800
Subject: Fixing up 'cancel' button text on no-copy item transfer to outbox
 message

---
 indra/newview/skins/default/xui/en/notifications.xml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 387cee3cee..a7e7436256 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -207,6 +207,7 @@ You don't have permission to copy this item to the Merchant Outbox. You can move
 
 [ITEM_NAME]
         <usetemplate
+         canceltext="Cancel"
          name="yesnocancelbuttons"
          notext="Don't move item"
          yestext="Move item"/>
-- 
cgit v1.2.3


From f082de03ff24ae8cc6a2de103bc643c392135742 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 12 Jan 2012 16:36:56 -0700
Subject: fix for SH-2845, SH-2846, SH-2847, SH-2851: curl crashes and
 out-of-memory crashes.

---
 indra/llmessage/llcurl.cpp                         | 293 +++++++++++++++++----
 indra/llmessage/llcurl.h                           |  22 +-
 indra/llmessage/llhttpassetstorage.cpp             |  10 +-
 indra/llmessage/llhttpclient.cpp                   |  12 +-
 indra/llmessage/lliopipe.cpp                       |   6 +
 indra/llmessage/lliopipe.h                         |   2 +
 indra/llmessage/llpumpio.cpp                       |  50 +++-
 indra/llmessage/llpumpio.h                         |  12 +-
 indra/llmessage/llsdrpcclient.h                    |   3 +
 indra/llmessage/llurlrequest.cpp                   |  18 ++
 indra/llmessage/llurlrequest.h                     |   2 +
 indra/newview/llmeshrepository.cpp                 | 131 +++++----
 indra/newview/llmeshrepository.h                   |   4 +-
 indra/newview/llxmlrpctransaction.cpp              |  19 ++
 .../updater/llupdatedownloader.cpp                 |  23 +-
 15 files changed, 475 insertions(+), 132 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index e17380fdf5..eab2874596 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -72,10 +72,12 @@
 
 static const U32 EASY_HANDLE_POOL_SIZE		= 5;
 static const S32 MULTI_PERFORM_CALL_REPEAT	= 5;
-static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds
+static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation
 static const S32 MAX_ACTIVE_REQUEST_COUNT = 100;
 
-static 
+static const F32 DEFAULT_MULTI_IDLE_TIME = 120.0f ; //seconds
+static const S32 MAX_NUM_OF_HANDLES = 256 ; //max number of handles, (multi handles and easy handles combined).
+
 // DEBUG //
 S32 gCurlEasyCount = 0;
 S32 gCurlMultiCount = 0;
@@ -87,6 +89,8 @@ std::vector<LLMutex*> LLCurl::sSSLMutex;
 std::string LLCurl::sCAPath;
 std::string LLCurl::sCAFile;
 LLCurlThread* LLCurl::sCurlThread = NULL ;
+LLMutex* LLCurl::sHandleMutexp = NULL ;
+S32      LLCurl::sTotalHandles = 0 ;
 
 void check_curl_code(CURLcode code)
 {
@@ -230,7 +234,7 @@ CURL* LLCurl::Easy::allocEasyHandle()
 
 	if (sFreeHandles.empty())
 	{
-		ret = curl_easy_init();
+		ret = LLCurl::newEasyHandle();
 	}
 	else
 	{
@@ -250,16 +254,27 @@ CURL* LLCurl::Easy::allocEasyHandle()
 //static
 void LLCurl::Easy::releaseEasyHandle(CURL* handle)
 {
+	static const S32 MAX_NUM_FREE_HANDLES = 32 ;
+
 	if (!handle)
 	{
-		llerrs << "handle cannot be NULL!" << llendl;
+		return ; //handle allocation failed.
+		//llerrs << "handle cannot be NULL!" << llendl;
 	}
 
 	LLMutexLock lock(sHandleMutexp) ;
 	if (sActiveHandles.find(handle) != sActiveHandles.end())
 	{
 		sActiveHandles.erase(handle);
-		sFreeHandles.insert(handle);
+
+		if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES)
+		{
+			sFreeHandles.insert(handle);
+		}
+		else
+		{
+			LLCurl::deleteEasyHandle(handle) ;
+		}
 	}
 	else
 	{
@@ -517,8 +532,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 }
 
 ////////////////////////////////////////////////////////////////////////////
-LLMutex* LLCurl::Multi::sMultiInitMutexp = NULL ;
-LLCurl::Multi::Multi()
+LLCurl::Multi::Multi(F32 idle_time_out)
 	: mQueued(0),
 	  mErrorCount(0),
 	  mState(STATE_READY),
@@ -527,28 +541,47 @@ LLCurl::Multi::Multi()
 	  mDeletionMutexp(NULL),
 	  mEasyMutexp(NULL)
 {
-	mCurlMultiHandle = initMulti();
+	mCurlMultiHandle = LLCurl::newMultiHandle();
 	if (!mCurlMultiHandle)
 	{
 		llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
-		mCurlMultiHandle = initMulti();
+		mCurlMultiHandle = LLCurl::newMultiHandle();
 	}
 	
-	llassert_always(mCurlMultiHandle);	
-
-	if(LLCurl::getCurlThread()->getThreaded())
+	//llassert_always(mCurlMultiHandle);	
+	
+	if(mCurlMultiHandle)
 	{
-		mMutexp = new LLMutex(NULL) ;
-		mDeletionMutexp = new LLMutex(NULL) ;
-		mEasyMutexp = new LLMutex(NULL) ;
-	}
-	LLCurl::getCurlThread()->addMulti(this) ;
+		if(LLCurl::getCurlThread()->getThreaded())
+		{
+			mMutexp = new LLMutex(NULL) ;
+			mDeletionMutexp = new LLMutex(NULL) ;
+			mEasyMutexp = new LLMutex(NULL) ;
+		}
+		LLCurl::getCurlThread()->addMulti(this) ;
+
+		mIdleTimeOut = idle_time_out ;
+		if(mIdleTimeOut < DEFAULT_MULTI_IDLE_TIME)
+		{
+			mIdleTimeOut = DEFAULT_MULTI_IDLE_TIME ;
+		}
 
-	++gCurlMultiCount;
+		++gCurlMultiCount;
+	}
 }
 
 LLCurl::Multi::~Multi()
 {
+	cleanup() ;	
+}
+
+void LLCurl::Multi::cleanup()
+{
+	if(!mCurlMultiHandle)
+	{
+		return ; //nothing to clean.
+	}
+
 	// Clean up active
 	for(easy_active_list_t::iterator iter = mEasyActiveList.begin();
 		iter != mEasyActiveList.end(); ++iter)
@@ -564,7 +597,8 @@ LLCurl::Multi::~Multi()
 	for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer());	
 	mEasyFreeList.clear();
 
-	check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle));
+	check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle));
+	mCurlMultiHandle = NULL ;
 
 	delete mMutexp ;
 	mMutexp = NULL ;
@@ -572,15 +606,13 @@ LLCurl::Multi::~Multi()
 	mDeletionMutexp = NULL ;
 	delete mEasyMutexp ;
 	mEasyMutexp = NULL ;
-
+	
+	mQueued = 0 ;
+	mState = STATE_COMPLETED;
+	
 	--gCurlMultiCount;
-}
-
-CURLM* LLCurl::Multi::initMulti()
-{
-	LLMutexLock lock(sMultiInitMutexp) ;
 
-	return curl_multi_init() ;
+	return ;
 }
 
 void LLCurl::Multi::lock()
@@ -604,6 +636,7 @@ void LLCurl::Multi::markDead()
 	LLMutexLock lock(mDeletionMutexp) ;
 	
 	mDead = TRUE ;
+	LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; 
 }
 
 void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
@@ -630,6 +663,11 @@ bool LLCurl::Multi::isCompleted()
 
 bool LLCurl::Multi::waitToComplete()
 {
+	if(!isValid())
+	{
+		return true ;
+	}
+
 	if(!mMutexp) //not threaded
 	{
 		doPerform() ;
@@ -639,7 +677,7 @@ bool LLCurl::Multi::waitToComplete()
 	bool completed = (STATE_COMPLETED == mState) ;
 	if(!completed)
 	{
-		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;
+		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_HIGH) ;
 	}
 	
 	return completed;
@@ -689,7 +727,12 @@ bool LLCurl::Multi::doPerform()
 		}
 
 		mQueued = q;	
-		setState(STATE_COMPLETED) ;
+		setState(STATE_COMPLETED) ;		
+		mIdleTimer.reset() ;
+	}
+	else if(mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it.
+	{
+		dead = true ;
 	}
 
 	return dead ;
@@ -697,6 +740,11 @@ bool LLCurl::Multi::doPerform()
 
 S32 LLCurl::Multi::process()
 {
+	if(!isValid())
+	{
+		return 0 ;
+	}
+
 	waitToComplete() ;
 
 	if (getState() != STATE_COMPLETED)
@@ -849,7 +897,11 @@ bool LLCurlThread::CurlRequest::processRequest()
 	if(mMulti)
 	{
 		completed = mCurlThread->doMultiPerform(mMulti) ;
-		setPriority(LLQueuedThread::PRIORITY_LOW) ;
+
+		if(!completed)
+		{
+			setPriority(LLQueuedThread::PRIORITY_LOW) ;
+		}
 	}
 
 	return completed ;
@@ -857,24 +909,26 @@ bool LLCurlThread::CurlRequest::processRequest()
 
 void LLCurlThread::CurlRequest::finishRequest(bool completed)
 {
-	mCurlThread->deleteMulti(mMulti) ;
+	if(mMulti->isDead())
+	{
+		mCurlThread->deleteMulti(mMulti) ;
+	}
+	else
+	{
+		mMulti->cleanup() ; //being idle too long, remove the request.
+	}
+
 	mMulti = NULL ;
 }
 	
 LLCurlThread::LLCurlThread(bool threaded) :
 	LLQueuedThread("curlthread", threaded)
 {
-	if(!LLCurl::Multi::sMultiInitMutexp)
-	{
-		LLCurl::Multi::sMultiInitMutexp = new LLMutex(NULL) ;
-	}
 }
 	
 //virtual 
 LLCurlThread::~LLCurlThread() 
 {
-	delete LLCurl::Multi::sMultiInitMutexp ;
-	LLCurl::Multi::sMultiInitMutexp = NULL ;
 }
 
 S32 LLCurlThread::update(F32 max_time_ms)
@@ -896,7 +950,19 @@ void LLCurlThread::addMulti(LLCurl::Multi* multi)
 	
 void LLCurlThread::killMulti(LLCurl::Multi* multi)
 {
-	multi->markDead() ;
+	if(!multi)
+	{
+		return ;
+	}
+
+	if(multi->isValid())
+	{
+		multi->markDead() ;
+	}
+	else
+	{
+		deleteMulti(multi) ;
+	}
 }
 
 //private
@@ -942,7 +1008,14 @@ LLCurlRequest::~LLCurlRequest()
 void LLCurlRequest::addMulti()
 {
 	LLCurl::Multi* multi = new LLCurl::Multi();
-	
+	if(!multi->isValid())
+	{
+		LLCurl::getCurlThread()->killMulti(multi) ;
+		mActiveMulti = NULL ;
+		mActiveRequestCount = 0 ;
+		return;
+	}
+
 	mMultiSet.insert(multi);
 	mActiveMulti = multi;
 	mActiveRequestCount = 0;
@@ -1066,6 +1139,19 @@ S32 LLCurlRequest::process()
 	{
 		curlmulti_set_t::iterator curiter = iter++;
 		LLCurl::Multi* multi = *curiter;
+
+		if(!multi->isValid())
+		{
+			if(multi == mActiveMulti)
+			{				
+				mActiveMulti = NULL ;
+				mActiveRequestCount = 0 ;
+			}
+			mMultiSet.erase(curiter) ;
+			LLCurl::getCurlThread()->killMulti(multi) ;
+			continue ;
+		}
+
 		S32 tres = multi->process();
 		res += tres;
 		if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0)
@@ -1086,6 +1172,19 @@ S32 LLCurlRequest::getQueued()
 	{
 		curlmulti_set_t::iterator curiter = iter++;
 		LLCurl::Multi* multi = *curiter;
+		
+		if(!multi->isValid())
+		{
+			if(multi == mActiveMulti)
+			{				
+				mActiveMulti = NULL ;
+				mActiveRequestCount = 0 ;
+			}
+			LLCurl::getCurlThread()->killMulti(multi);
+			mMultiSet.erase(curiter) ;
+			continue ;
+		}
+
 		queued += multi->mQueued;
 		if (multi->getState() != LLCurl::Multi::STATE_READY)
 		{
@@ -1105,13 +1204,22 @@ LLCurlEasyRequest::LLCurlEasyRequest()
 {
 	mMulti = new LLCurl::Multi();
 	
-	mEasy = mMulti->allocEasy();
-	if (mEasy)
+	if(mMulti->isValid())
 	{
-		mEasy->setErrorBuffer();
-		mEasy->setCA();
-		// Set proxy settings if configured to do so.
-		LLProxy::getInstance()->applyProxySettings(mEasy);
+		mEasy = mMulti->allocEasy();
+		if (mEasy)
+		{
+			mEasy->setErrorBuffer();
+			mEasy->setCA();
+			// Set proxy settings if configured to do so.
+			LLProxy::getInstance()->applyProxySettings(mEasy);
+		}
+	}
+	else
+	{
+		LLCurl::getCurlThread()->killMulti(mMulti) ;
+		mEasy = NULL ;
+		mMulti = NULL ;
 	}
 }
 
@@ -1122,7 +1230,7 @@ LLCurlEasyRequest::~LLCurlEasyRequest()
 	
 void LLCurlEasyRequest::setopt(CURLoption option, S32 value)
 {
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mEasy->setopt(option, value);
 	}
@@ -1130,7 +1238,7 @@ void LLCurlEasyRequest::setopt(CURLoption option, S32 value)
 
 void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value)
 {
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mEasy->setoptString(option, value);
 	}
@@ -1138,7 +1246,7 @@ void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value
 
 void LLCurlEasyRequest::setPost(char* postdata, S32 size)
 {
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mEasy->setopt(CURLOPT_POST, 1);
 		mEasy->setopt(CURLOPT_POSTFIELDS, postdata);
@@ -1148,7 +1256,7 @@ void LLCurlEasyRequest::setPost(char* postdata, S32 size)
 
 void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* userdata)
 {
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mEasy->setopt(CURLOPT_HEADERFUNCTION, (void*)callback);
 		mEasy->setopt(CURLOPT_HEADERDATA, userdata); // aka CURLOPT_WRITEHEADER
@@ -1157,7 +1265,7 @@ void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* u
 
 void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* userdata)
 {
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mEasy->setopt(CURLOPT_WRITEFUNCTION, (void*)callback);
 		mEasy->setopt(CURLOPT_WRITEDATA, userdata);
@@ -1166,7 +1274,7 @@ void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* use
 
 void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userdata)
 {
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mEasy->setopt(CURLOPT_READFUNCTION, (void*)callback);
 		mEasy->setopt(CURLOPT_READDATA, userdata);
@@ -1175,7 +1283,7 @@ void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userd
 
 void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata)
 {
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback);
 		mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata);
@@ -1184,7 +1292,7 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void*
 
 void LLCurlEasyRequest::slist_append(const char* str)
 {
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mEasy->slist_append(str);
 	}
@@ -1195,7 +1303,7 @@ void LLCurlEasyRequest::sendRequest(const std::string& url)
 	llassert_always(!mRequestSent);
 	mRequestSent = true;
 	lldebugs << url << llendl;
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mEasy->setHeaders();
 		mEasy->setoptString(CURLOPT_URL, url);
@@ -1207,7 +1315,7 @@ void LLCurlEasyRequest::requestComplete()
 {
 	llassert_always(mRequestSent);
 	mRequestSent = false;
-	if (mEasy)
+	if (isValid() && mEasy)
 	{
 		mMulti->removeEasy(mEasy);
 	}
@@ -1216,6 +1324,10 @@ void LLCurlEasyRequest::requestComplete()
 // Usage: Call getRestult until it returns false (no more messages)
 bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info)
 {
+	if(!isValid())
+	{
+		return false ;
+	}
 	if (!mMulti->isCompleted())
 	{ //we're busy, try again later
 		return false;
@@ -1280,7 +1392,7 @@ CURLMsg* LLCurlEasyRequest::info_read(S32* q, LLCurl::TransferInfo* info)
 
 std::string LLCurlEasyRequest::getErrorString()
 {
-	return mEasy ? std::string(mEasy->getErrorBuffer()) : std::string();
+	return isValid() &&  mEasy ? std::string(mEasy->getErrorBuffer()) : std::string();
 }
 
 ////////////////////////////////////////////////////////////////////////////
@@ -1328,6 +1440,7 @@ void LLCurl::initClass(bool multi_threaded)
 	sCurlThread = new LLCurlThread(multi_threaded) ;
 	if(multi_threaded)
 	{
+		sHandleMutexp = new LLMutex(NULL) ;
 		Easy::sHandleMutexp = new LLMutex(NULL) ;
 	}
 }
@@ -1354,7 +1467,7 @@ void LLCurl::cleanupClass()
 	for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)
 	{
 		CURL* curl = *iter;
-		curl_easy_cleanup(curl);
+		LLCurl::deleteEasyHandle(curl);
 	}
 
 	Easy::sFreeHandles.clear();
@@ -1362,9 +1475,77 @@ void LLCurl::cleanupClass()
 	delete Easy::sHandleMutexp ;
 	Easy::sHandleMutexp = NULL ;
 
+	delete sHandleMutexp ;
+	sHandleMutexp = NULL ;
+
 	llassert(Easy::sActiveHandles.empty());
 }
 
+//static 
+CURLM* LLCurl::newMultiHandle()
+{
+	LLMutexLock lock(sHandleMutexp) ;
+
+	if(sTotalHandles + 1 > MAX_NUM_OF_HANDLES)
+	{
+		llwarns << "no more handles available." << llendl ;
+		return NULL ; //failed
+	}
+	sTotalHandles++;
+
+	CURLM* ret = curl_multi_init() ;
+	if(!ret)
+	{
+		llwarns << "curl_multi_init failed." << llendl ;
+	}
+
+	return ret ;
+}
+
+//static 
+CURLMcode  LLCurl::deleteMultiHandle(CURLM* handle)
+{
+	if(handle)
+	{
+		LLMutexLock lock(sHandleMutexp) ;		
+		sTotalHandles-- ;
+		return curl_multi_cleanup(handle) ;
+	}
+	return CURLM_OK ;
+}
+
+//static 
+CURL*  LLCurl::newEasyHandle()
+{
+	LLMutexLock lock(sHandleMutexp) ;
+
+	if(sTotalHandles + 1 > MAX_NUM_OF_HANDLES)
+	{
+		llwarns << "no more handles available." << llendl ;
+		return NULL ; //failed
+	}
+	sTotalHandles++;
+
+	CURL* ret = curl_easy_init() ;
+	if(!ret)
+	{
+		llwarns << "curl_easy_init failed." << llendl ;
+	}
+
+	return ret ;
+}
+
+//static 
+void  LLCurl::deleteEasyHandle(CURL* handle)
+{
+	if(handle)
+	{
+		LLMutexLock lock(sHandleMutexp) ;
+		curl_easy_cleanup(handle) ;
+		sTotalHandles-- ;
+	}
+}
+
 const unsigned int LLCurl::MAX_REDIRECTS = 5;
 
 // Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace.
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 9c2c215c7a..32da911cbf 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -43,6 +43,7 @@
 #include "llsd.h"
 #include "llthread.h"
 #include "llqueuedthread.h"
+#include "llframetimer.h"
 
 class LLMutex;
 class LLCurlThread;
@@ -182,11 +183,20 @@ public:
 	static unsigned long ssl_thread_id(void);
 
 	static LLCurlThread* getCurlThread() { return sCurlThread ;}
+
+	static CURLM* newMultiHandle() ;
+	static CURLMcode deleteMultiHandle(CURLM* handle) ;
+	static CURL*  newEasyHandle() ;
+	static void   deleteEasyHandle(CURL* handle) ;
+
 private:
 	static std::string sCAPath;
 	static std::string sCAFile;
 	static const unsigned int MAX_REDIRECTS;
 	static LLCurlThread* sCurlThread;
+
+	static LLMutex* sHandleMutexp ;
+	static S32      sTotalHandles ;
 };
 
 class LLCurl::Easy
@@ -277,7 +287,7 @@ public:
 		STATE_COMPLETED=2
 	} ePerformState;
 
-	Multi();	
+	Multi(F32 idle_time_out = 0.f);	
 
 	LLCurl::Easy* allocEasy();
 	bool addEasy(LLCurl::Easy* easy);	
@@ -288,7 +298,10 @@ public:
 
 	void setState(ePerformState state) ;
 	ePerformState getState() ;
+	
 	bool isCompleted() ;
+	bool isValid() {return mCurlMultiHandle != NULL ;}
+	bool isDead() {return mDead;}
 
 	bool waitToComplete() ;
 
@@ -299,9 +312,9 @@ public:
 	S32 mQueued;
 	S32 mErrorCount;
 	
-	static CURLM* initMulti() ;
 private:
 	void easyFree(LLCurl::Easy*);
+	void cleanup() ;
 	
 	CURLM* mCurlMultiHandle;
 
@@ -319,8 +332,8 @@ private:
 	LLMutex* mMutexp ;
 	LLMutex* mDeletionMutexp ;
 	LLMutex* mEasyMutexp ;
-
-	static LLMutex* sMultiInitMutexp ;
+	LLFrameTimer mIdleTimer ;
+	F32 mIdleTimeOut;
 };
 
 class LLCurlThread : public LLQueuedThread
@@ -414,6 +427,7 @@ public:
 	std::string getErrorString();
 	bool isCompleted() {return mMulti->isCompleted() ;}
 	bool wait() { return mMulti->waitToComplete(); }
+	bool isValid() {return mMulti && mMulti->isValid(); }
 
 	LLCurl::Easy* getEasy() const { return mEasy; }
 
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
index 2bca517e97..612d765969 100644
--- a/indra/llmessage/llhttpassetstorage.cpp
+++ b/indra/llmessage/llhttpassetstorage.cpp
@@ -232,7 +232,8 @@ LLSD LLHTTPAssetRequest::getFullDetails() const
 void LLHTTPAssetRequest::setupCurlHandle()
 {
 	// *NOTE: Similar code exists in mapserver/llcurlutil.cpp  JC
-	mCurlHandle = curl_easy_init();
+	mCurlHandle = LLCurl::newEasyHandle();
+	llassert_always(mCurlHandle != NULL) ;
 
 	// Apply proxy settings if configured to do so
 	LLProxy::getInstance()->applyProxySettings(mCurlHandle);
@@ -278,7 +279,7 @@ void LLHTTPAssetRequest::setupCurlHandle()
 
 void LLHTTPAssetRequest::cleanupCurlHandle()
 {
-	curl_easy_cleanup(mCurlHandle);
+	LLCurl::deleteEasyHandle(mCurlHandle);
 	if (mAssetStoragep)
 	{
 		// Terminating a request.  Thus upload or download is no longer pending.
@@ -429,12 +430,13 @@ void LLHTTPAssetStorage::_init(const std::string& web_host, const std::string& l
 
 	// curl_global_init moved to LLCurl::initClass()
 	
-	mCurlMultiHandle = curl_multi_init();
+	mCurlMultiHandle = LLCurl::newMultiHandle() ;
+	llassert_always(mCurlMultiHandle != NULL) ;
 }
 
 LLHTTPAssetStorage::~LLHTTPAssetStorage()
 {
-	curl_multi_cleanup(mCurlMultiHandle);
+	LLCurl::deleteMultiHandle(mCurlMultiHandle);
 	mCurlMultiHandle = NULL;
 	
 	// curl_global_cleanup moved to LLCurl::initClass()
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index dd4e3a6300..231cb7ca8f 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -228,6 +228,12 @@ static void request(
 	LLPumpIO::chain_t chain;
 
 	LLURLRequest* req = new LLURLRequest(method, url);
+	if(!req->isValid())//failed
+	{
+		delete req ;
+		return ;
+	}
+
 	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);
 
 	
@@ -423,7 +429,9 @@ static LLSD blocking_request(
 {
 	lldebugs << "blockingRequest of " << url << llendl;
 	char curl_error_buffer[CURL_ERROR_SIZE] = "\0";
-	CURL* curlp = curl_easy_init();
+	CURL* curlp = LLCurl::newEasyHandle();
+	llassert_always(curlp != NULL) ;
+
 	LLHTTPBuffer http_buffer;
 	std::string body_str;
 	
@@ -517,7 +525,7 @@ static LLSD blocking_request(
 	}
 
 	// * Cleanup
-	curl_easy_cleanup(curlp);
+	LLCurl::deleteEasyHandle(curlp);
 	return response;
 }
 
diff --git a/indra/llmessage/lliopipe.cpp b/indra/llmessage/lliopipe.cpp
index 6e4eec74a6..8f827f7a30 100644
--- a/indra/llmessage/lliopipe.cpp
+++ b/indra/llmessage/lliopipe.cpp
@@ -75,6 +75,12 @@ LLIOPipe::~LLIOPipe()
 	//lldebugs << "destroying LLIOPipe" << llendl;
 }
 
+//virtual 
+bool LLIOPipe::isValid() 
+{
+	return true ;
+}
+
 // static
 std::string LLIOPipe::lookupStatusString(EStatus status)
 {
diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h
index 8e656b6da1..cbd17b5a3d 100644
--- a/indra/llmessage/lliopipe.h
+++ b/indra/llmessage/lliopipe.h
@@ -231,6 +231,8 @@ public:
 	 */
 	virtual ~LLIOPipe();
 
+	virtual bool isValid() ;
+
 protected:
 	/**
 	 * @brief Base Constructor.
diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index a8d2a0a224..0ff300efd0 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -195,7 +195,7 @@ bool LLPumpIO::prime(apr_pool_t* pool)
 	return ((pool == NULL) ? false : true);
 }
 
-bool LLPumpIO::addChain(const chain_t& chain, F32 timeout)
+bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_PUMP);
 	if(chain.empty()) return false;
@@ -204,6 +204,7 @@ bool LLPumpIO::addChain(const chain_t& chain, F32 timeout)
 	LLScopedLock lock(mChainsMutex);
 #endif
 	LLChainInfo info;
+	info.mHasCurlRequest = has_curl_request;
 	info.setTimeoutSeconds(timeout);
 	info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray);
 	LLLinkInfo link;
@@ -440,6 +441,15 @@ void LLPumpIO::pump()
 
 static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO");
 
+LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain) 
+{
+	std::for_each(
+				(*run_chain).mDescriptors.begin(),
+				(*run_chain).mDescriptors.end(),
+				ll_delete_apr_pollset_fd_client_data());
+	return mRunningChains.erase(run_chain);
+}
+
 //timeout is in microseconds
 void LLPumpIO::pump(const S32& poll_timeout)
 {
@@ -585,10 +595,16 @@ void LLPumpIO::pump(const S32& poll_timeout)
 //						<< (*run_chain).mChainLinks[0].mPipe
 //						<< " because we reached the end." << llendl;
 #endif
-				run_chain = mRunningChains.erase(run_chain);
+				run_chain = removeRunningChain(run_chain);
 				continue;
 			}
 		}
+		else if(isChainExpired(*run_chain))
+		{
+			run_chain = removeRunningChain(run_chain);
+			continue;
+		}
+
 		PUMP_DEBUG;
 		if((*run_chain).mLock)
 		{
@@ -696,11 +712,7 @@ void LLPumpIO::pump(const S32& poll_timeout)
 			PUMP_DEBUG;
 			// This chain is done. Clean up any allocated memory and
 			// erase the chain info.
-			std::for_each(
-				(*run_chain).mDescriptors.begin(),
-				(*run_chain).mDescriptors.end(),
-				ll_delete_apr_pollset_fd_client_data());
-			run_chain = mRunningChains.erase(run_chain);
+			run_chain = removeRunningChain(run_chain);
 
 			// *NOTE: may not always need to rebuild the pollset.
 			mRebuildPollset = true;
@@ -1095,6 +1107,24 @@ void LLPumpIO::processChain(LLChainInfo& chain)
 	PUMP_DEBUG;
 }
 
+bool LLPumpIO::isChainExpired(LLChainInfo& chain)
+{
+	if(!chain.mHasCurlRequest)
+	{
+		return false ;
+	}
+
+	for(links_t::iterator iter = chain.mChainLinks.begin(); iter != chain.mChainLinks.end(); ++iter)
+	{
+		if(!(*iter).mPipe->isValid())
+		{
+			return true ;
+		}
+	}
+
+	return false ;
+}
+
 bool LLPumpIO::handleChainError(
 	LLChainInfo& chain,
 	LLIOPipe::EStatus error)
@@ -1136,6 +1166,9 @@ bool LLPumpIO::handleChainError(
 #endif
 			keep_going = false;
 			break;
+		case LLIOPipe::STATUS_EXPIRED:
+			keep_going = false;
+			break ;
 		default:
 			if(LLIOPipe::isSuccess(error))
 			{
@@ -1157,7 +1190,8 @@ bool LLPumpIO::handleChainError(
 LLPumpIO::LLChainInfo::LLChainInfo() :
 	mInit(false),
 	mLock(0),
-	mEOS(false)
+	mEOS(false),
+	mHasCurlRequest(false)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_PUMP);
 	mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS);
diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h
index 9303c9d7fc..e405124403 100644
--- a/indra/llmessage/llpumpio.h
+++ b/indra/llmessage/llpumpio.h
@@ -113,7 +113,7 @@ public:
 	 * expire. Pass in 0.0f to never expire.
 	 * @return Returns true if anything was added to the pump.
 	 */
-	bool addChain(const chain_t& chain, F32 timeout);
+	bool addChain(const chain_t& chain, F32 timeout, bool has_curl_request = false);
 	
 	/** 
 	 * @brief Struct to associate a pipe with it's buffer io indexes.
@@ -356,12 +356,13 @@ protected:
 
 		// basic member data
 		bool mInit;
+		bool mEOS;
+		bool mHasCurlRequest;
 		S32 mLock;
 		LLFrameTimer mTimer;
 		links_t::iterator mHead;
 		links_t mChainLinks;
-		LLIOPipe::buffer_ptr_t mData;
-		bool mEOS;
+		LLIOPipe::buffer_ptr_t mData;		
 		LLSD mContext;
 
 		// tracking inside the pump
@@ -402,7 +403,7 @@ protected:
 protected:
 	void initialize(apr_pool_t* pool);
 	void cleanup();
-
+	current_chain_t removeRunningChain(current_chain_t& chain) ;
 	/** 
 	 * @brief Given the internal state of the chains, rebuild the pollset
 	 * @see setConditional()
@@ -429,6 +430,9 @@ protected:
 	 */
 	bool handleChainError(LLChainInfo& chain, LLIOPipe::EStatus error);
 
+	//if the chain is expired, remove it
+	bool isChainExpired(LLChainInfo& chain) ;
+
 public:
 	/** 
 	 * @brief Return number of running chains.
diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h
index 9fb49a5c33..235077179e 100644
--- a/indra/llmessage/llsdrpcclient.h
+++ b/indra/llmessage/llsdrpcclient.h
@@ -239,6 +239,8 @@ public:
 	LLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
 	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
 	{
+		llerrs << "Can not call this." << llendl ;
+
 		lldebugs << "LLSDRPCClientFactory::build" << llendl;
 		LLIOPipe::ptr_t service(new Client);
 		chain.push_back(service);
@@ -282,6 +284,7 @@ public:
 	LLXMLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
 	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
 	{
+		llerrs << "who calls this?" << llendl ;
 		lldebugs << "LLXMLSDRPCClientFactory::build" << llendl;
 		LLIOPipe::ptr_t service(new Client);
 		chain.push_back(service);
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 261e57e79e..f02c636838 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -83,6 +83,12 @@ LLURLRequestDetail::LLURLRequestDetail() :
 {
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	mCurlRequest = new LLCurlEasyRequest();
+	
+	if(!mCurlRequest->isValid()) //failed.
+	{
+		delete mCurlRequest ;
+		mCurlRequest = NULL ;
+	}
 }
 
 LLURLRequestDetail::~LLURLRequestDetail()
@@ -250,12 +256,24 @@ void LLURLRequest::allowCookies()
 	mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, "");
 }
 
+//virtual 
+bool LLURLRequest::isValid() 
+{
+	return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid(); 
+}
+
 // virtual
 LLIOPipe::EStatus LLURLRequest::handleError(
 	LLIOPipe::EStatus status,
 	LLPumpIO* pump)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
+	
+	if(!isValid())
+	{
+		return STATUS_EXPIRED ;
+	}
+
 	if(mCompletionCallback && pump)
 	{
 		LLURLRequestComplete* complete = NULL;
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index ec5c2c1941..44d358d906 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -188,6 +188,8 @@ public:
 	 */
 	void allowCookies();
 
+	/*virtual*/ bool isValid() ;
+
 public:
 	/** 
 	 * @brief Give this pipe a chance to handle a generated error
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index a97e256c89..c64479f589 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -498,9 +498,11 @@ void LLMeshRepoThread::run()
 					LODRequest req = mLODReqQ.front();
 					mLODReqQ.pop();
 					mMutex->unlock();
-					if (fetchMeshLOD(req.mMeshParams, req.mLOD))
+					if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit
 					{
-						count++;
+						mMutex->lock();
+						mLODReqQ.push(req) ; 
+						mMutex->unlock();
 					}
 				}
 			}
@@ -512,9 +514,11 @@ void LLMeshRepoThread::run()
 					HeaderRequest req = mHeaderReqQ.front();
 					mHeaderReqQ.pop();
 					mMutex->unlock();
-					if (fetchMeshHeader(req.mMeshParams))
+					if (!fetchMeshHeader(req.mMeshParams, count))//failed, resubmit
 					{
-						count++;
+						mMutex->lock();
+						mHeaderReqQ.push(req) ;
+						mMutex->unlock();
 					}
 				}
 			}
@@ -658,6 +662,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 		return false;
 	}
 
+	bool ret = true ;
 	U32 header_size = mMeshHeaderSize[mesh_id];
 	
 	if (header_size > 0)
@@ -673,7 +678,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 			//check VFS for mesh skin info
 			LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);
 			if (file.getSize() >= offset+size)
-			{
+			{				
 				LLMeshRepository::sCacheBytesRead += size;
 				file.seek(offset);
 				U8* buffer = new U8[size];
@@ -689,7 +694,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 				if (!zero)
 				{ //attempt to parse
 					if (skinInfoReceived(mesh_id, buffer, size))
-					{
+					{						
 						delete[] buffer;
 						return true;
 					}
@@ -704,11 +709,14 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
-			{
-				++sActiveLODRequests;
-				LLMeshRepository::sHTTPRequestCount++;
-				mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
+			{				
+				ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
 										   new LLMeshSkinInfoResponder(mesh_id, offset, size));
+				if(ret)
+				{
+					++sActiveLODRequests;
+					LLMeshRepository::sHTTPRequestCount++;
+				}
 			}
 		}
 	}
@@ -718,7 +726,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 	}
 
 	//early out was not hit, effectively fetched
-	return true;
+	return ret;
 }
 
 bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
@@ -732,7 +740,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 	}
 
 	U32 header_size = mMeshHeaderSize[mesh_id];
-
+	bool ret = true ;
+	
 	if (header_size > 0)
 	{
 		S32 version = mMeshHeader[mesh_id]["version"].asInteger();
@@ -748,6 +757,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 			if (file.getSize() >= offset+size)
 			{
 				LLMeshRepository::sCacheBytesRead += size;
+
 				file.seek(offset);
 				U8* buffer = new U8[size];
 				file.read(buffer, size);
@@ -777,11 +787,14 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
-			{
-				++sActiveLODRequests;
-				LLMeshRepository::sHTTPRequestCount++;
-				mCurlRequest->getByteRange(http_url, headers, offset, size,
+			{				
+				ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
 										   new LLMeshDecompositionResponder(mesh_id, offset, size));
+				if(ret)
+				{
+					++sActiveLODRequests;
+					LLMeshRepository::sHTTPRequestCount++;
+				}
 			}
 		}
 	}
@@ -791,7 +804,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 	}
 
 	//early out was not hit, effectively fetched
-	return true;
+	return ret;
 }
 
 bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
@@ -805,6 +818,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 	}
 
 	U32 header_size = mMeshHeaderSize[mesh_id];
+	bool ret = true ;
 
 	if (header_size > 0)
 	{
@@ -850,11 +864,15 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
-			{
-				++sActiveLODRequests;
-				LLMeshRepository::sHTTPRequestCount++;
-				mCurlRequest->getByteRange(http_url, headers, offset, size,
+			{				
+				ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
 										   new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
+
+				if(ret)
+				{
+					++sActiveLODRequests;
+					LLMeshRepository::sHTTPRequestCount++;
+				}
 			}
 		}
 		else
@@ -868,13 +886,12 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 	}
 
 	//early out was not hit, effectively fetched
-	return true;
+	return ret;
 }
 
-bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
+//return false if failed to get header
+bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count)
 {
-	bool retval = false;
-
 	{
 		//look for mesh in asset in vfs
 		LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH);
@@ -889,36 +906,40 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
 			file.read(buffer, bytes);
 			if (headerReceived(mesh_params, buffer, bytes))
 			{ //did not do an HTTP request, return false
-				return false;
+				return true;
 			}
 		}
 	}
 
-	//either cache entry doesn't exist or is corrupt, request header from simulator
-
+	//either cache entry doesn't exist or is corrupt, request header from simulator	
+	bool retval = true ;
 	std::vector<std::string> headers;
 	headers.push_back("Accept: application/octet-stream");
 
 	std::string http_url = constructUrl(mesh_params.getSculptID());
 	if (!http_url.empty())
 	{
-		++sActiveHeaderRequests;
-		retval = true;
 		//grab first 4KB if we're going to bother with a fetch.  Cache will prevent future fetches if a full mesh fits
 		//within the first 4KB
-		//NOTE -- this will break of headers ever exceed 4KB
-		LLMeshRepository::sHTTPRequestCount++;
-		mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params));
+		//NOTE -- this will break of headers ever exceed 4KB		
+		retval = mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params));
+		if(retval)
+		{
+			++sActiveHeaderRequests;
+			LLMeshRepository::sHTTPRequestCount++;
+		}
+		count++;
 	}
 
 	return retval;
 }
 
-bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
+//return false if failed to get mesh lod.
+bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count)
 { //protected by mMutex
 	mHeaderMutex->lock();
 
-	bool retval = false;
+	bool retval = true;
 
 	LLUUID mesh_id = mesh_params.getSculptID();
 	
@@ -955,7 +976,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 					if (lodReceived(mesh_params, lod, buffer, size))
 					{
 						delete[] buffer;
-						return false;
+						return true;
 					}
 				}
 
@@ -968,12 +989,16 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
-			{
-				++sActiveLODRequests;
-				retval = true;
-				LLMeshRepository::sHTTPRequestCount++;
-				mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
+			{				
+				retval = mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
 										   new LLMeshLODResponder(mesh_params, lod, offset, size));
+
+				if(retval)
+				{
+					++sActiveLODRequests;				
+					LLMeshRepository::sHTTPRequestCount++;
+				}
+				count++;
 			}
 			else
 			{
@@ -1540,8 +1565,17 @@ void LLMeshUploadThread::doWholeModelUpload()
 		LLSD body = full_model_data["asset_resources"];
 		dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num));
 		LLCurlRequest::headers_t headers;
-		mCurlRequest->post(mWholeModelUploadURL, headers, body,
-						   new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle), mMeshUploadTimeOut);
+
+		{
+			LLCurl::ResponderPtr responder = new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle) ;
+
+			while(!mCurlRequest->post(mWholeModelUploadURL, headers, body, responder, mMeshUploadTimeOut))
+			{
+				//sleep for 10ms to prevent eating a whole core
+				apr_sleep(10000);
+			}
+		}
+
 		do
 		{
 			mCurlRequest->process();
@@ -1571,8 +1605,15 @@ void LLMeshUploadThread::requestWholeModelFee()
 
 	mPendingUploads++;
 	LLCurlRequest::headers_t headers;
-	mCurlRequest->post(mWholeModelFeeCapability, headers, model_data,
-					   new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle), mMeshUploadTimeOut);
+
+	{
+		LLCurl::ResponderPtr responder = new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle) ;
+		while(!mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, responder, mMeshUploadTimeOut))
+		{
+			//sleep for 10ms to prevent eating a whole core
+			apr_sleep(10000);
+		}
+	}
 
 	do
 	{
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 31b84ea0d9..2efe810438 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -323,8 +323,8 @@ public:
 	virtual void run();
 
 	void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
-	bool fetchMeshHeader(const LLVolumeParams& mesh_params);
-	bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+	bool fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count);
+	bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count);
 	bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
 	bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);
 	bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 920a9a3752..0da70d398b 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -305,6 +305,15 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
 	{
 		mCurlRequest = new LLCurlEasyRequest();
 	}
+	if(!mCurlRequest->isValid())
+	{
+		llwarns << "mCurlRequest is invalid." << llendl ;
+
+		delete mCurlRequest ;
+		mCurlRequest = NULL ;
+		return ;
+	}
+
 	mErrorCert = NULL;
 
 //	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging
@@ -357,10 +366,20 @@ LLXMLRPCTransaction::Impl::~Impl()
 	}
 	
 	delete mCurlRequest;
+	mCurlRequest = NULL ;
 }
 
 bool LLXMLRPCTransaction::Impl::process()
 {
+	if(!mCurlRequest || !mCurlRequest->isValid())
+	{
+		llwarns << "transaction failed." << llendl ;
+
+		delete mCurlRequest ;
+		mCurlRequest = NULL ;
+		return true ; //failed, quit.
+	}
+
 	switch(mStatus)
 	{
 		case LLXMLRPCTransaction::StatusComplete:
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
index e88d1bf811..19ac418e9e 100644
--- a/indra/viewer_components/updater/llupdatedownloader.cpp
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -39,7 +39,7 @@
 #include "llsdserialize.h"
 #include "llthread.h"
 #include "llupdaterservice.h"
-
+#include "llcurl.h"
 
 class LLUpdateDownloader::Implementation:
 	public LLThread
@@ -198,13 +198,19 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client &
 
 LLUpdateDownloader::Implementation::~Implementation()
 {
-	if(isDownloading()) {
+	if(isDownloading()) 
+	{
 		cancel();
 		shutdown();
-	} else {
+	} 
+	else 
+	{
 		; // No op.
 	}
-	if(mCurl) curl_easy_cleanup(mCurl);
+	if(mCurl)
+	{
+		LLCurl::deleteEasyHandle(mCurl);
+	}
 }
 
 
@@ -406,9 +412,12 @@ void LLUpdateDownloader::Implementation::run(void)
 
 void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader)
 {
-	if(mCurl == 0) {
-		mCurl = curl_easy_init();
-	} else {
+	if(mCurl == 0) 
+	{
+		mCurl = LLCurl::newEasyHandle();
+	} 
+	else 
+	{
 		curl_easy_reset(mCurl);
 	}
 	
-- 
cgit v1.2.3


From ba41aea4b2813ac96cad2bae7c82da6e5eefd63a Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 12 Jan 2012 17:01:23 -0800
Subject: EXP-1795 FIX -- Update warning dialog for dragging and dropping
 no-copy items to Merchant Outbox

* Any drag and drop or copy operation to the merchant outbox that contains one
  or more no-copy items now brings up a single modal dialog prompting the user
  to move the no-copy items to the outbox or to leave them all behind.
---
 indra/newview/llinventorybridge.cpp                |  8 +--
 indra/newview/llinventoryfunctions.cpp             | 60 ++++++++++++++++------
 indra/newview/llinventoryfunctions.h               |  4 +-
 indra/newview/lltooldraganddrop.cpp                |  8 +++
 indra/newview/lltooldraganddrop.h                  |  3 ++
 .../newview/skins/default/xui/en/notifications.xml | 11 ++--
 6 files changed, 66 insertions(+), 28 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 1d7406883c..11e22d5226 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1323,7 +1323,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
 		if (!itemp) return;
 
 		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false);
-		copy_item_to_outbox(itemp, outbox_id, LLUUID::null);
+		copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId());
 	}
 }
 
@@ -2221,7 +2221,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 			}
 			else if (move_is_into_outbox && !move_is_from_outbox)
 			{
-				copy_folder_to_outbox(inv_cat, mUUID, cat_id);
+				copy_folder_to_outbox(inv_cat, mUUID, cat_id, LLToolDragAndDrop::getOperationId());
 			}
 			else
 			{
@@ -2655,7 +2655,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
 		if (!cat) return;
 
 		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false);
-		copy_folder_to_outbox(cat, outbox_id, cat->getUUID());
+		copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId());
 	}
 #if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
 	else if (isMarketplaceSendAction(action))
@@ -3694,7 +3694,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 				}
 				else
 				{
-					copy_item_to_outbox(inv_item, mUUID, LLUUID::null);
+					copy_item_to_outbox(inv_item, mUUID, LLUUID::null, LLToolDragAndDrop::getOperationId());
 				}
 			}
 			// NORMAL or TRASH folder
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index e8efac1ebf..7672f7e674 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -82,6 +82,8 @@
 #include "llvoavatarself.h"
 #include "llwearablelist.h"
 
+#include <boost/foreach.hpp>
+
 BOOL LLInventoryState::sWearNewClothing = FALSE;
 LLUUID LLInventoryState::sWearNewClothingTransactionID;
 
@@ -535,13 +537,10 @@ void open_outbox()
 	LLFloaterReg::showInstance("outbox");
 }
 
-void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
+void move_to_outbox_cb_action(const LLSD& payload)
 {
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (option != 0) return; // canceled
-
-	LLViewerInventoryItem * viitem = gInventory.getItem(notification["payload"]["item_id"].asUUID());
-	LLUUID dest_folder_id = notification["payload"]["dest_folder_id"].asUUID();
+	LLViewerInventoryItem * viitem = gInventory.getItem(payload["item_id"].asUUID());
+	LLUUID dest_folder_id = payload["dest_folder_id"].asUUID();
 
 	if (viitem)
 	{	
@@ -560,12 +559,12 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
 			dest_folder_id,
 			false);
 
-		LLUUID top_level_folder = notification["payload"]["top_level_folder"].asUUID();
+		LLUUID top_level_folder = payload["top_level_folder"].asUUID();
 
 		if (top_level_folder != LLUUID::null)
 		{
 			LLViewerInventoryCategory* category;
-			
+
 			while (parent.notNull())
 			{
 				LLInventoryModel::cat_array_t* cat_array;
@@ -593,20 +592,41 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
 				parent = next_parent;
 			}
 		}
-		
+
 		open_outbox();
 	}
 }
 
+static S32 move_to_outbox_operation_id = -1;
+static std::list<LLSD> move_to_outbox_payloads;
+
+void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
+{
+	const S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+	if (option == 0)
+	{
+		llassert(move_to_outbox_payloads.size() > 0);
+
+		BOOST_FOREACH(const LLSD& payload, move_to_outbox_payloads)
+		{
+			move_to_outbox_cb_action(payload);
+		}
+	}
+
+	move_to_outbox_operation_id = -1;
+	move_to_outbox_payloads.clear();
+}
+
 
-void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder)
+void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id)
 {
 	// Collapse links directly to items/folders
 	LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
 	LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
 	if (linked_category != NULL)
 	{
-		copy_folder_to_outbox(linked_category, dest_folder, top_level_folder);
+		copy_folder_to_outbox(linked_category, dest_folder, top_level_folder, operation_id);
 	}
 	else
 	{
@@ -639,11 +659,21 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
 		{	
 			LLSD args;
 			args["ITEM_NAME"] = inv_item->getName();
+
 			LLSD payload;
 			payload["item_id"] = inv_item->getUUID();
 			payload["dest_folder_id"] = dest_folder;
 			payload["top_level_folder"] = top_level_folder;
-			LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2));
+
+			if (move_to_outbox_operation_id != operation_id)
+			{
+				LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2));
+				
+				move_to_outbox_operation_id = operation_id;
+				move_to_outbox_payloads.clear();
+			}
+
+			move_to_outbox_payloads.push_back(payload);
 		}
 	}
 }
@@ -665,7 +695,7 @@ void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder)
 					   false);
 }
 
-void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder)
+void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id)
 {
 	LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName());
 	gInventory.notifyObservers();
@@ -680,7 +710,7 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold
 	for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
 	{
 		LLInventoryItem* item = *iter;
-		copy_item_to_outbox(item, new_folder_id, top_level_folder);
+		copy_item_to_outbox(item, new_folder_id, top_level_folder, operation_id);
 	}
 
 	LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
@@ -688,7 +718,7 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold
 	for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
 	{
 		LLViewerInventoryCategory* category = *iter;
-		copy_folder_to_outbox(category, new_folder_id, top_level_folder);
+		copy_folder_to_outbox(category, new_folder_id, top_level_folder, operation_id);
 	}
 
 	open_outbox();
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 9f0ee0571a..a93446000d 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -74,10 +74,10 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
 // Generates a string containing the path to the item specified by item_id.
 void append_path(const LLUUID& id, std::string& path);
 
-void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder);
+void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id);
 void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder);
 
-void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder);
+void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id);
 
 /**                    Miscellaneous global functions
  **                                                                            **
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 5a4d177709..8c32dfcb4d 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -282,6 +282,8 @@ void LLCategoryDropDescendentsObserver::done()
 }
 */
 
+S32 LLToolDragAndDrop::sOperationId = 0;
+
 LLToolDragAndDrop::DragAndDropEntry::DragAndDropEntry(dragOrDrop3dImpl f_none,
 													  dragOrDrop3dImpl f_self,
 													  dragOrDrop3dImpl f_avatar,
@@ -644,6 +646,12 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
 
 	mToolTipMsg.clear();
 
+	// Increment the operation id for every drop
+	if (drop)
+	{
+		sOperationId++;
+	}
+
 	if (top_view)
 	{
 		handled = TRUE;
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 273d23d1a0..188d36cd1b 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -88,6 +88,7 @@ public:
 	boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); }
 	
 	uuid_vec_t::size_type getCargoIDsCount() const { return mCargoIDs.size(); }
+	static S32 getOperationId() { return sOperationId; }
 
 protected:
 	enum EDropTarget
@@ -127,6 +128,8 @@ protected:
 	LLUUID mSourceID;
 	LLUUID mObjectID;
 
+	static S32		sOperationId;
+
 	LLVector3d		mLastCameraPos;
 	LLVector3d		mLastHitPos;
 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index a7e7436256..1a4dab2ac5 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -203,14 +203,11 @@ Save changes to current clothing/body part?
    icon="alertmodal.tga"
      name="ConfirmNoCopyToOutbox"
      type="alertmodal">
-You don't have permission to copy this item to the Merchant Outbox. You can move it or leave it behind.
-
-[ITEM_NAME]
+You don't have permission to copy one or more of these items to the Merchant Outbox.  You can move them or leave them behind.
         <usetemplate
-         canceltext="Cancel"
-         name="yesnocancelbuttons"
-         notext="Don't move item"
-         yestext="Move item"/>
+         name="okcancelbuttons"
+         notext="Don't move item(s)"
+         yestext="Move item(s)"/>
     </notification>
 
   <notification
-- 
cgit v1.2.3


From 11bd5cb86025376a198e45330116de4757b5c89e Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 12 Jan 2012 20:32:32 -0700
Subject: trivial: fix a mac build error.

---
 indra/llmessage/llcurl.cpp | 9 ++++++++-
 indra/llmessage/llcurl.h   | 1 +
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index eab2874596..277c274f52 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -915,7 +915,7 @@ void LLCurlThread::CurlRequest::finishRequest(bool completed)
 	}
 	else
 	{
-		mMulti->cleanup() ; //being idle too long, remove the request.
+		mCurlThread->cleanupMulti(mMulti) ; //being idle too long, remove the request.
 	}
 
 	mMulti = NULL ;
@@ -976,6 +976,13 @@ void LLCurlThread::deleteMulti(LLCurl::Multi* multi)
 {
 	delete multi ;
 }
+
+//private
+void LLCurlThread::cleanupMulti(LLCurl::Multi* multi) 
+{
+	multi->cleanup() ;
+}
+
 //------------------------------------------------------------
 
 //static
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 32da911cbf..2b23ac9763 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -370,6 +370,7 @@ public:
 private:
 	bool doMultiPerform(LLCurl::Multi* multi) ;
 	void deleteMulti(LLCurl::Multi* multi) ;
+	void cleanupMulti(LLCurl::Multi* multi) ;
 } ;
 
 namespace boost
-- 
cgit v1.2.3


From b6a08ad007deb855ce4d428654279206853a3b99 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 13 Jan 2012 12:41:54 -0500
Subject: Extract APR and temp-fixture-file helper code to indra/test.
 Specifically: Introduce ManageAPR class in indra/test/manageapr.h. This is
 useful for a simple test program without lots of static constructors. Extract
 NamedTempFile from llsdserialize_test.cpp to indra/test/ namedtempfile.h.
 Refactor to use APR file operations rather than platform- dependent APIs. Use
 NamedTempFile for llprocesslauncher_test.cpp.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp |  73 ++-----
 indra/llcommon/tests/llsdserialize_test.cpp     | 261 +-----------------------
 indra/test/manageapr.h                          |  45 ++++
 indra/test/namedtempfile.h                      | 113 ++++++++++
 4 files changed, 184 insertions(+), 308 deletions(-)
 create mode 100644 indra/test/manageapr.h
 create mode 100644 indra/test/namedtempfile.h

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 4d8f850d92..3935c64a94 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -18,14 +18,14 @@
 #include <vector>
 #include <list>
 // std headers
-#include <errno.h>
 // external library headers
 #include "llapr.h"
 #include "apr_thread_proc.h"
-#include "apr_file_io.h"
 #include <boost/foreach.hpp>
 // other Linden headers
 #include "../test/lltut.h"
+#include "../test/manageapr.h"
+#include "../test/namedtempfile.h"
 #include "stringize.h"
 
 #if defined(LL_WINDOWS)
@@ -36,30 +36,8 @@
 #include <sys/wait.h>
 #endif
 
-class APR
-{
-public:
-    APR():
-        pool(NULL)
-    {
-        apr_initialize();
-        apr_pool_create(&pool, NULL);
-    }
-
-    ~APR()
-    {
-        apr_terminate();
-    }
-
-    std::string strerror(apr_status_t rv)
-    {
-        char errbuf[256];
-        apr_strerror(rv, errbuf, sizeof(errbuf));
-        return errbuf;
-    }
-
-    apr_pool_t *pool;
-};
+// static instance of this manages APR init/cleanup
+static ManageAPR manager;
 
 #define ensure_equals_(left, right) \
         ensure_equals(STRINGIZE(#left << " != " << #right), (left), (right))
@@ -74,11 +52,11 @@ namespace tut
     {
         void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
         {
-            ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr.strerror(rv)),
+            ensure_equals(STRINGIZE(call << " => " << rv << ": " << manager.strerror(rv)),
                           rv, expected);
         }
 
-        APR apr;
+        LLAPRPool pool;
     };
     typedef test_group<llprocesslauncher_data> llprocesslauncher_group;
     typedef llprocesslauncher_group::object object;
@@ -186,19 +164,7 @@ namespace tut
         set_test_name("raw APR nonblocking I/O");
 
         // Create a script file in a temporary place.
-        const char* tempdir = NULL;
-        aprchk(apr_temp_dir_get(&tempdir, apr.pool));
-
-        // Construct a temp filename template in that directory.
-        char *tempname = NULL;
-        aprchk(apr_filepath_merge(&tempname, tempdir, "testXXXXXX", 0, apr.pool));
-
-        // Create a temp file from that template.
-        apr_file_t* fp = NULL;
-        aprchk(apr_file_mktemp(&fp, tempname, APR_CREATE | APR_WRITE | APR_EXCL, apr.pool));
-
-        // Write it.
-        const char script[] =
+        NamedTempFile script("py",
             "import sys" EOL
             "import time" EOL
             EOL
@@ -208,10 +174,7 @@ namespace tut
             "time.sleep(2)" EOL
             "print >>sys.stderr, 'stderr after wait'" EOL
             "sys.stderr.flush()" EOL
-            ;
-        apr_size_t len(sizeof(script)-1);
-        aprchk(apr_file_write(fp, script, &len));
-        aprchk(apr_file_close(fp));
+            );
 
         // Arrange to track the history of our interaction with child: what we
         // fetched, which pipe it came from, how many tries it took before we
@@ -221,30 +184,33 @@ namespace tut
 
         // Run the child process.
         apr_procattr_t *procattr = NULL;
-        aprchk(apr_procattr_create(&procattr, apr.pool));
+        aprchk(apr_procattr_create(&procattr, pool.getAPRPool()));
         aprchk(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK));
         aprchk(apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH));
 
         std::vector<const char*> argv;
         apr_proc_t child;
         argv.push_back("python");
-        argv.push_back(tempname);
+        // Have to have a named copy of this std::string so its c_str() value
+        // will persist.
+        std::string scriptname(script.getName());
+        argv.push_back(scriptname.c_str());
         argv.push_back(NULL);
 
         aprchk(apr_proc_create(&child, argv[0],
                                &argv[0],
                                NULL, // if we wanted to pass explicit environment
                                procattr,
-                               apr.pool));
+                               pool.getAPRPool()));
 
         // We do not want this child process to outlive our APR pool. On
         // destruction of the pool, forcibly kill the process. Tell APR to try
         // SIGTERM and wait 3 seconds. If that didn't work, use SIGKILL.
-        apr_pool_note_subprocess(apr.pool, &child, APR_KILL_AFTER_TIMEOUT);
+        apr_pool_note_subprocess(pool.getAPRPool(), &child, APR_KILL_AFTER_TIMEOUT);
 
         // arrange to call child_status_callback()
         WaitInfo wi(&child);
-        apr_proc_other_child_register(&child, child_status_callback, &wi, child.in, apr.pool);
+        apr_proc_other_child_register(&child, child_status_callback, &wi, child.in, pool.getAPRPool());
 
         // TODO:
         // Stuff child.in until it (would) block to verify EWOULDBLOCK/EAGAIN.
@@ -289,7 +255,7 @@ namespace tut
                 }
                 if (rv == EWOULDBLOCK || rv == EAGAIN)
                 {
-//                  std::cout << "(waiting; apr_file_gets(" << dfli->first << ") => " << rv << ": " << apr.strerror(rv) << ")\n";
+//                  std::cout << "(waiting; apr_file_gets(" << dfli->first << ") => " << rv << ": " << manager.strerror(rv) << ")\n";
                     ++history.back().tries;
                     continue;
                 }
@@ -334,14 +300,11 @@ namespace tut
             std::cout << "child_status_callback(APR_OC_REASON_DEATH) wasn't called" << std::endl;
             wi.rv = apr_proc_wait(wi.child, &wi.rc, &wi.why, APR_NOWAIT);
         }
-//      std::cout << "child done: rv = " << rv << " (" << apr.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
+//      std::cout << "child done: rv = " << rv << " (" << manager.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
         aprchk_("apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT)", wi.rv, APR_CHILD_DONE);
         ensure_equals_(wi.why, APR_PROC_EXIT);
         ensure_equals_(wi.rc, 0);
 
-        // Remove temp script file
-        aprchk(apr_file_remove(tempname, apr.pool));
-
         // Beyond merely executing all the above successfully, verify that we
         // obtained expected output -- and that we duly got control while
         // waiting, proving the non-blocking nature of these pipes.
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 72322c3b72..4359e9afb9 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -43,38 +43,12 @@ typedef U32 uint32_t;
 #include "llprocesslauncher.h"
 #endif
 
-#include <sstream>
-
-/*==========================================================================*|
-// Whoops, seems Linden's Boost package and the viewer are built with
-// different settings of VC's /Zc:wchar_t switch! Using Boost.Filesystem
-// pathname operations produces Windows link errors:
-// unresolved external symbol "private: static class std::codecvt<unsigned short,
-// char,int> const * & __cdecl boost::filesystem3::path::wchar_t_codecvt_facet()"
-// unresolved external symbol "void __cdecl boost::filesystem3::path_traits::convert()"
-// See:
-// http://boost.2283326.n4.nabble.com/filesystem-v3-unicode-and-std-codecvt-linker-error-td3455549.html
-// which points to:
-// http://msdn.microsoft.com/en-us/library/dh8che7s%28v=VS.100%29.aspx
-
-// As we're not trying to preserve compatibility with old Boost.Filesystem
-// code, but rather writing brand-new code, use the newest available
-// Filesystem API.
-#define BOOST_FILESYSTEM_VERSION 3
-#include "boost/filesystem.hpp"
-#include "boost/filesystem/v3/fstream.hpp"
-|*==========================================================================*/
 #include "boost/range.hpp"
 #include "boost/foreach.hpp"
 #include "boost/function.hpp"
 #include "boost/lambda/lambda.hpp"
 #include "boost/lambda/bind.hpp"
 namespace lambda = boost::lambda;
-/*==========================================================================*|
-// Aaaarrgh, Linden's Boost package doesn't even include Boost.Iostreams!
-#include "boost/iostreams/stream.hpp"
-#include "boost/iostreams/device/file_descriptor.hpp"
-|*==========================================================================*/
 
 #include "../llsd.h"
 #include "../llsdserialize.h"
@@ -82,236 +56,17 @@ namespace lambda = boost::lambda;
 #include "../llformat.h"
 
 #include "../test/lltut.h"
+#include "../test/manageapr.h"
+#include "../test/namedtempfile.h"
 #include "stringize.h"
 
+static ManageAPR manager;
+
 std::vector<U8> string_to_vector(const std::string& str)
 {
 	return std::vector<U8>(str.begin(), str.end());
 }
 
-#if ! LL_WINDOWS
-// We want to call strerror_r(), but alarmingly, there are two different
-// variants. The one that returns int always populates the passed buffer
-// (except in case of error), whereas the other one always returns a valid
-// char* but might or might not populate the passed buffer. How do we know
-// which one we're getting? Define adapters for each and let the compiler
-// select the applicable adapter.
-
-// strerror_r() returns char*
-std::string message_from(int /*orig_errno*/, const char* /*buffer*/, const char* strerror_ret)
-{
-    return strerror_ret;
-}
-
-// strerror_r() returns int
-std::string message_from(int orig_errno, const char* buffer, int strerror_ret)
-{
-    if (strerror_ret == 0)
-    {
-        return buffer;
-    }
-    // Here strerror_r() has set errno. Since strerror_r() has already failed,
-    // seems like a poor bet to call it again to diagnose its own error...
-    int stre_errno = errno;
-    if (stre_errno == ERANGE)
-    {
-        return STRINGIZE("strerror_r() can't explain errno " << orig_errno
-                         << " (buffer too small)");
-    }
-    if (stre_errno == EINVAL)
-    {
-        return STRINGIZE("unknown errno " << orig_errno);
-    }
-    // Here we don't even understand the errno from strerror_r()!
-    return STRINGIZE("strerror_r() can't explain errno " << orig_errno
-                     << " (error " << stre_errno << ')');
-}
-#endif  // ! LL_WINDOWS
-
-// boost::filesystem::temp_directory_path() isn't yet in Boost 1.45! :-(
-std::string temp_directory_path()
-{
-#if LL_WINDOWS
-    char buffer[4096];
-    GetTempPathA(sizeof(buffer), buffer);
-    return buffer;
-
-#else  // LL_DARWIN, LL_LINUX
-    static const char* vars[] = { "TMPDIR", "TMP", "TEMP", "TEMPDIR" };
-    BOOST_FOREACH(const char* var, vars)
-    {
-        const char* found = getenv(var);
-        if (found)
-            return found;
-    }
-    return "/tmp";
-#endif // LL_DARWIN, LL_LINUX
-}
-
-// Windows presents a kinda sorta compatibility layer. Code to the yucky
-// Windows names because they're less likely than the Posix names to collide
-// with any other names in this source.
-#if LL_WINDOWS
-#define _remove   DeleteFileA
-#else  // ! LL_WINDOWS
-#define _open     open
-#define _write    write
-#define _close    close
-#define _remove   remove
-#endif  // ! LL_WINDOWS
-
-// Create a text file with specified content "somewhere in the
-// filesystem," cleaning up when it goes out of scope.
-class NamedTempFile
-{
-public:
-    // Function that accepts an ostream ref and (presumably) writes stuff to
-    // it, e.g.:
-    // (lambda::_1 << "the value is " << 17 << '\n')
-    typedef boost::function<void(std::ostream&)> Streamer;
-
-    NamedTempFile(const std::string& ext, const std::string& content):
-        mPath(temp_directory_path())
-    {
-        createFile(ext, lambda::_1 << content);
-    }
-
-    // Disambiguate when passing string literal
-    NamedTempFile(const std::string& ext, const char* content):
-        mPath(temp_directory_path())
-    {
-        createFile(ext, lambda::_1 << content);
-    }
-
-    NamedTempFile(const std::string& ext, const Streamer& func):
-        mPath(temp_directory_path())
-    {
-        createFile(ext, func);
-    }
-
-    ~NamedTempFile()
-    {
-        _remove(mPath.c_str());
-    }
-
-    std::string getName() const { return mPath; }
-
-private:
-    void createFile(const std::string& ext, const Streamer& func)
-    {
-        // Silly maybe, but use 'ext' as the name prefix. Strip off a leading
-        // '.' if present.
-        int pfx_offset = ((! ext.empty()) && ext[0] == '.')? 1 : 0;
-
-#if ! LL_WINDOWS
-        // Make sure mPath ends with a directory separator, if it doesn't already.
-        if (mPath.empty() ||
-            ! (mPath[mPath.length() - 1] == '\\' || mPath[mPath.length() - 1] == '/'))
-        {
-            mPath.append("/");
-        }
-
-        // mkstemp() accepts and modifies a char* template string. Generate
-        // the template string, then copy to modifiable storage.
-        // mkstemp() requires its template string to end in six X's.
-        mPath += ext.substr(pfx_offset) + "XXXXXX";
-        // Copy to vector<char>
-        std::vector<char> pathtemplate(mPath.begin(), mPath.end());
-        // append a nul byte for classic-C semantics
-        pathtemplate.push_back('\0');
-        // std::vector promises that a pointer to the 0th element is the same
-        // as a pointer to a contiguous classic-C array
-        int fd(mkstemp(&pathtemplate[0]));
-        if (fd == -1)
-        {
-            // The documented errno values (http://linux.die.net/man/3/mkstemp)
-            // are used in a somewhat unusual way, so provide context-specific
-            // errors.
-            if (errno == EEXIST)
-            {
-                LL_ERRS("NamedTempFile") << "mkstemp(\"" << mPath
-                                         << "\") could not create unique file " << LL_ENDL;
-            }
-            if (errno == EINVAL)
-            {
-                LL_ERRS("NamedTempFile") << "bad mkstemp() file path template '"
-                                         << mPath << "'" << LL_ENDL;
-            }
-            // Shrug, something else
-            int mkst_errno = errno;
-            char buffer[256];
-            LL_ERRS("NamedTempFile") << "mkstemp(\"" << mPath << "\") failed: "
-                                     << message_from(mkst_errno, buffer,
-                                                     strerror_r(mkst_errno, buffer, sizeof(buffer)))
-                                     << LL_ENDL;
-        }
-        // mkstemp() seems to have worked! Capture the modified filename.
-        // Avoid the nul byte we appended.
-        mPath.assign(pathtemplate.begin(), (pathtemplate.end()-1));
-
-/*==========================================================================*|
-        // Define an ostream on the open fd. Tell it to close fd on destruction.
-        boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
-            out(fd, boost::iostreams::close_handle);
-|*==========================================================================*/
-
-        // Write desired content.
-        std::ostringstream out;
-        // Stream stuff to it.
-        func(out);
-
-        std::string data(out.str());
-        int written(_write(fd, data.c_str(), data.length()));
-        int closed(_close(fd));
-        llassert_always(written == data.length() && closed == 0);
-
-#else // LL_WINDOWS
-        // GetTempFileName() is documented to require a MAX_PATH buffer.
-        char tempname[MAX_PATH];
-        // Use 'ext' as filename prefix, but skip leading '.' if any.
-        // The 0 param is very important: requests iterating until we get a
-        // unique name.
-        if (0 == GetTempFileNameA(mPath.c_str(), ext.c_str() + pfx_offset, 0, tempname))
-        {
-            // I always have to look up this call...  :-P
-            LPSTR msgptr;
-            FormatMessageA(
-                FORMAT_MESSAGE_ALLOCATE_BUFFER | 
-                FORMAT_MESSAGE_FROM_SYSTEM |
-                FORMAT_MESSAGE_IGNORE_INSERTS,
-                NULL,
-                GetLastError(),
-                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                LPSTR(&msgptr),     // have to cast (char**) to (char*)
-                0, NULL );
-            LL_ERRS("NamedTempFile") << "GetTempFileName(\"" << mPath << "\", \""
-                                     << (ext.c_str() + pfx_offset) << "\") failed: "
-                                     << msgptr << LL_ENDL;
-            LocalFree(msgptr);
-        }
-        // GetTempFileName() appears to have worked! Capture the actual
-        // filename.
-        mPath = tempname;
-        // Open the file and stream content to it. Destructor will close.
-        std::ofstream out(tempname);
-        func(out);
-
-#endif  // LL_WINDOWS
-    }
-
-    void peep()
-    {
-        std::cout << "File '" << mPath << "' contains:\n";
-        std::ifstream reader(mPath.c_str());
-        std::string line;
-        while (std::getline(reader, line))
-            std::cout << line << '\n';
-        std::cout << "---\n";
-    }
-
-    std::string mPath;
-};
-
 namespace tut
 {
 	struct sd_xml_data
@@ -1783,7 +1538,7 @@ namespace tut
             const char* PYTHON(getenv("PYTHON"));
             ensure("Set $PYTHON to the Python interpreter", PYTHON);
 
-            NamedTempFile scriptfile(".py", script);
+            NamedTempFile scriptfile("py", script);
 
 #if LL_WINDOWS
             std::string q("\"");
@@ -1888,12 +1643,12 @@ namespace tut
             "    else:\n"
             "        assert False, 'Too many data items'\n";
 
-        // Create a something.llsd file containing 'data' serialized to
+        // Create an llsdXXXXXX file containing 'data' serialized to
         // notation. It's important to separate with newlines because Python's
         // llsd module doesn't support parsing from a file stream, only from a
         // string, so we have to know how much of the file to read into a
         // string.
-        NamedTempFile file(".llsd",
+        NamedTempFile file("llsd",
                            // NamedTempFile's boost::function constructor
                            // takes a callable. To this callable it passes the
                            // std::ostream with which it's writing the
@@ -1926,7 +1681,7 @@ namespace tut
         // Create an empty data file. This is just a placeholder for our
         // script to write into. Create it to establish a unique name that
         // we know.
-        NamedTempFile file(".llsd", "");
+        NamedTempFile file("llsd", "");
 
         python("write Python notation",
                lambda::_1 <<
diff --git a/indra/test/manageapr.h b/indra/test/manageapr.h
new file mode 100644
index 0000000000..0c1ca7b7be
--- /dev/null
+++ b/indra/test/manageapr.h
@@ -0,0 +1,45 @@
+/**
+ * @file   manageapr.h
+ * @author Nat Goodspeed
+ * @date   2012-01-13
+ * @brief  ManageAPR class for simple test programs
+ * 
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Copyright (c) 2012, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_MANAGEAPR_H)
+#define LL_MANAGEAPR_H
+
+#include "llapr.h"
+
+/**
+ * Declare a static instance of this class for dead-simple ll_init_apr() at
+ * program startup, ll_cleanup_apr() at termination. This is recommended for
+ * use only with simple test programs. Once you start introducing static
+ * instances of other classes that depend on APR already being initialized,
+ * the indeterminate static-constructor-order problem rears its ugly head.
+ */
+class ManageAPR
+{
+public:
+    ManageAPR()
+    {
+        ll_init_apr();
+    }
+
+    ~ManageAPR()
+    {
+        ll_cleanup_apr();
+    }
+
+    static std::string strerror(apr_status_t rv)
+    {
+        char errbuf[256];
+        apr_strerror(rv, errbuf, sizeof(errbuf));
+        return errbuf;
+    }
+};
+
+#endif /* ! defined(LL_MANAGEAPR_H) */
diff --git a/indra/test/namedtempfile.h b/indra/test/namedtempfile.h
new file mode 100644
index 0000000000..9670d4db53
--- /dev/null
+++ b/indra/test/namedtempfile.h
@@ -0,0 +1,113 @@
+/**
+ * @file   namedtempfile.h
+ * @author Nat Goodspeed
+ * @date   2012-01-13
+ * @brief  NamedTempFile class for tests that need disk files as fixtures.
+ * 
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Copyright (c) 2012, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_NAMEDTEMPFILE_H)
+#define LL_NAMEDTEMPFILE_H
+
+#include "llapr.h"
+#include "apr_file_io.h"
+#include <string>
+#include <boost/function.hpp>
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/bind.hpp"
+#include <iostream>
+#include <sstream>
+
+/**
+ * Create a text file with specified content "somewhere in the
+ * filesystem," cleaning up when it goes out of scope.
+ */
+class NamedTempFile
+{
+public:
+    NamedTempFile(const std::string& pfx, const std::string& content, apr_pool_t* pool=gAPRPoolp):
+        mPool(pool)
+    {
+        createFile(pfx, boost::lambda::_1 << content);
+    }
+
+    // Disambiguate when passing string literal
+    NamedTempFile(const std::string& pfx, const char* content, apr_pool_t* pool=gAPRPoolp):
+        mPool(pool)
+    {
+        createFile(pfx, boost::lambda::_1 << content);
+    }
+
+    // Function that accepts an ostream ref and (presumably) writes stuff to
+    // it, e.g.:
+    // (boost::lambda::_1 << "the value is " << 17 << '\n')
+    typedef boost::function<void(std::ostream&)> Streamer;
+
+    NamedTempFile(const std::string& pfx, const Streamer& func, apr_pool_t* pool=gAPRPoolp):
+        mPool(pool)
+    {
+        createFile(pfx, func);
+    }
+
+    ~NamedTempFile()
+    {
+        ll_apr_assert_status(apr_file_remove(mPath.c_str(), mPool));
+    }
+
+    std::string getName() const { return mPath; }
+
+private:
+    void createFile(const std::string& pfx, const Streamer& func)
+    {
+        // Create file in a temporary place.
+        const char* tempdir = NULL;
+        ll_apr_assert_status(apr_temp_dir_get(&tempdir, mPool));
+
+        // Construct a temp filename template in that directory.
+        char *tempname = NULL;
+        ll_apr_assert_status(apr_filepath_merge(&tempname,
+                                                tempdir,
+                                                (pfx + "XXXXXX").c_str(),
+                                                0,
+                                                mPool));
+
+        // Create a temp file from that template.
+        apr_file_t* fp = NULL;
+        ll_apr_assert_status(apr_file_mktemp(&fp,
+                                             tempname,
+                                             APR_CREATE | APR_WRITE | APR_EXCL,
+                                             mPool));
+        // apr_file_mktemp() alters tempname with the actual name. Not until
+        // now is it valid to capture as our mPath.
+        mPath = tempname;
+
+        // Write desired content.
+        std::ostringstream out;
+        // Stream stuff to it.
+        func(out);
+
+        std::string data(out.str());
+        apr_size_t writelen(data.length());
+        ll_apr_assert_status(apr_file_write(fp, data.c_str(), &writelen));
+        ll_apr_assert_status(apr_file_close(fp));
+        llassert_always(writelen == data.length());
+    }
+
+    void peep()
+    {
+        std::cout << "File '" << mPath << "' contains:\n";
+        std::ifstream reader(mPath.c_str());
+        std::string line;
+        while (std::getline(reader, line))
+            std::cout << line << '\n';
+        std::cout << "---\n";
+    }
+
+    std::string mPath;
+    apr_pool_t* mPool;
+};
+
+#endif /* ! defined(LL_NAMEDTEMPFILE_H) */
-- 
cgit v1.2.3


From 86ef722e7cb2e4c791e8223f5c09a0552b52b574 Mon Sep 17 00:00:00 2001
From: merov <none@none>
Date: Fri, 13 Jan 2012 15:11:37 -0800
Subject: EXP-1775 : cleanup a bit PeekMessage() usage, avoid eating one event
 when reaching MAX_MESSAGE_PER_UPDATE.

---
 indra/llwindow/llwindowwin32.cpp | 2 +-
 indra/newview/llstartup.cpp      | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 954b9f2b15..228fbefd19 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1747,7 +1747,7 @@ void LLWindowWin32::gatherInput()
 
 	LLMemType m1(LLMemType::MTYPE_GATHER_INPUT);
 
-	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE)
+	while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
 	{
 		mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput");
 		TranslateMessage(&msg);
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 7e02a41e7e..3923b4510a 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -804,9 +804,8 @@ bool idle_startup()
 #ifdef _WIN32
 		MSG msg;
 		while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) )
-		{
-			display_startup();
-		}
+		{ }
+		display_startup();
 #endif
 		timeout.reset();
 		return FALSE;
-- 
cgit v1.2.3


From d6add298d7c793eda1fee2c03b2ccf91df7f6102 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 13 Jan 2012 16:06:58 -0800
Subject: EXP-1802 FIX -- Create labeled drop target region at bottom of
 merchant outbox floater for easy top level drop access

* Added generic drop zone that highlights green when its functionality will be used.
---
 indra/newview/llfloateroutbox.cpp                  |  34 ++-
 indra/newview/llfloateroutbox.h                    |   3 +
 .../default/xui/en/floater_merchant_outbox.xml     | 241 +++++++++++----------
 3 files changed, 167 insertions(+), 111 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 597602d5ab..297736f3bd 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -111,6 +111,7 @@ LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
 	, mOutboxId(LLUUID::null)
 	, mOutboxInventoryPanel(NULL)
 	, mOutboxItemCount(0)
+	, mOutboxTopLevelDropZone(NULL)
 	, mWindowShade(NULL)
 {
 }
@@ -140,7 +141,9 @@ BOOL LLFloaterOutbox::postBuild()
 	
 	mImportButton = getChild<LLButton>("outbox_import_btn");
 	mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this));
-	
+
+	mOutboxTopLevelDropZone = getChild<LLPanel>("outbox_generic_drag_target");
+
 	LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this));
 
 	return TRUE;
@@ -353,6 +356,11 @@ void LLFloaterOutbox::updateView()
 	}
 }
 
+bool isAccepted(EAcceptance accept)
+{
+	return (accept >= ACCEPT_YES_COPY_SINGLE);
+}
+
 BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 										EDragAndDropType cargo_type,
 										void* cargo_data,
@@ -370,7 +378,7 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 	BOOL handled = (handled_view != NULL);
 	
 	// Pass all drag and drop for this floater to the outbox inventory control
-	if (!handled || (*accept == ACCEPT_NO))
+	if (!handled || !isAccepted(*accept))
 	{
 		// Always assume we are going to move the drag and drop operation to the outbox root folder
 		bool move_to_root = true;
@@ -394,11 +402,33 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 			
 			handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
 		}
+
+		if (mOutboxTopLevelDropZone)
+		{
+			mOutboxTopLevelDropZone->setBackgroundVisible(handled && !drop && isAccepted(*accept));
+		}
+	}
+	else
+	{
+		if (mOutboxTopLevelDropZone)
+		{
+			mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
+		}
 	}
 	
 	return handled;
 }
 
+void LLFloaterOutbox::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+	if (mOutboxTopLevelDropZone)
+	{
+		mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
+	}
+
+	LLFloater::onMouseLeave(x, y, mask);
+}
+
 void LLFloaterOutbox::onImportButtonClicked()
 {
 	mOutboxInventoryPanel->clearSelection();
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index 58b7d6ec98..796c533059 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -66,6 +66,8 @@ public:
 	
 	void showNotification(const LLSD& notify);
 
+	void onMouseLeave(S32 x, S32 y, MASK mask);
+
 protected:
 	void fetchOutboxContents();
 
@@ -103,6 +105,7 @@ private:
 	LLUUID				mOutboxId;
 	LLInventoryPanel *	mOutboxInventoryPanel;
 	U32					mOutboxItemCount;
+	LLPanel *			mOutboxTopLevelDropZone;
 	
 	LLWindowShade *	mWindowShade;
 };
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index c0f26413cb..498a9b6ce0 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -1,24 +1,24 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <floater
- open_positioning="cascading"
- can_close="true"
- can_resize="true"
- height="440"
- help_topic="floater_merchant_outbox"
- min_width="300"
- min_height="200"
- name="floater_merchant_outbox"
- save_rect="true"
- save_visibility="false"
- reuse_instance="true"
- title="MERCHANT OUTBOX"
- width="333" >
- <string name="OutboxFolderCount0"></string>
- <string name="OutboxFolderCount1">1 folder</string>
- <string name="OutboxFolderCountN">[NUM] folders</string>
- <string name="OutboxImporting">Sending folders...</string>
- <string name="OutboxInitializing">Initializing...</string>
- <panel
+    open_positioning="cascading"
+    can_close="true"
+    can_resize="true"
+    height="440"
+    help_topic="floater_merchant_outbox"
+    min_width="300"
+    min_height="200"
+    name="floater_merchant_outbox"
+    save_rect="true"
+    save_visibility="false"
+    reuse_instance="true"
+    title="MERCHANT OUTBOX"
+    width="333">
+  <string name="OutboxFolderCount0"></string>
+  <string name="OutboxFolderCount1">1 folder</string>
+  <string name="OutboxFolderCountN">[NUM] folders</string>
+  <string name="OutboxImporting">Sending folders...</string>
+  <string name="OutboxInitializing">Initializing...</string>
+  <panel
       follows="all"
       layout="topleft"
       left="0"
@@ -26,104 +26,127 @@
       label=""
       height="440"
       width="333">
-     <panel
+    <panel
         follows="all"
         left="10"
-        bottom="400"
+        bottom="370"
         width="313"
         top="0"
-        bg_opaque_color="InventoryBackgroundColor"
-        >
-		<panel
-			name="outbox_inventory_placeholder_panel"
-			follows="all"
-			layout="topleft"
-			top="0"
-			left="0"
-			width="308"
-			height="400"
-			bg_opaque_color="InventoryBackgroundColor"
-			>
-			<text
-				name="outbox_inventory_placeholder_title"
-				type="string"
-				follows="top|left|right"
-				layout="topleft"
-				top="10"
-				left="0"
-				width="308"
-				height="25"
-				wrap="true"
-				halign="center"
-				font="SansSerifBold">
-				Loading...
-			</text>
-			<text
-				name="outbox_inventory_placeholder_text"
-				type="string"
-				follows="top|left|right"
-				layout="topleft"
-				top="35"
-				left="0"
-				width="308"
-				height="130"
-				wrap="true"
-				halign="left" />
-		</panel>
+        bg_opaque_color="InventoryBackgroundColor">
+      <panel
+          name="outbox_inventory_placeholder_panel"
+          follows="all"
+          layout="topleft"
+          top="0"
+          left="0"
+          width="308"
+          height="370"
+          bg_opaque_color="InventoryBackgroundColor">
+        <text
+            name="outbox_inventory_placeholder_title"
+            type="string"
+            follows="top|left|right"
+            layout="topleft"
+            top="10"
+            left="0"
+            width="308"
+            height="25"
+            wrap="true"
+            halign="center"
+            font="SansSerifBold">
+          Loading...
+        </text>
+        <text
+            name="outbox_inventory_placeholder_text"
+            type="string"
+            follows="top|left|right"
+            layout="topleft"
+            top="35"
+            left="0"
+            width="308"
+            height="130"
+            wrap="true"
+            halign="left" />
+      </panel>
     </panel>
-	<panel
+    <panel
         follows="bottom|left|right"
         left="10"
         bottom="435"
         width="313"
-        top="405"
-        bg_opaque_color="InventoryBackgroundColor"
-        >
-		<text
-			name="outbox_folder_count"
-			type="string"
-			follows="all"
-			layout="topleft"
-			top="10"
-			left="5"
-			width="150"
-			height="20"
-			wrap="true"
-			halign="left"
-			valign="bottom"
-			font="SansSerif" />
-		<button
-			 label="Send to Marketplace"
-			 tool_tip="Push to my Marketplace Storefront"
-			 is_toggle="false"
-			 name="outbox_import_btn"
-			 follows="bottom|right"
-			 tab_stop="false"
-			 halign="center"
-			 top="3"
-			 left="160"
-			 height="25"
-			 width="150"
-			 enabled="false" />
+        top="370">
+      <panel
+          name="outbox_generic_drag_target"
+          mouse_opaque="false"
+          follows="all"
+          top="5"
+          left="5"
+          width="303"
+          height="25"
+          background_visible="false"
+          bg_alpha_color="EmphasisColor_35"
+          border="true"
+          bevel_style="in"
+          visible="true">
+        <text
+            type="string"
+            follows="all"
+            layout="topleft"
+            top="6"
+            height="20"
+            left="5"
+            width="293"
+            halign="center"
+            font="SansSerifMedium"
+            font_shadow="hard"
+            valign="bottom">
+          Drag items here to create folders
+        </text>
+      </panel>
+      <text
+          name="outbox_folder_count"
+          type="string"
+          follows="all"
+          layout="topleft"
+          top="40"
+          left="5"
+          width="150"
+          height="20"
+          wrap="true"
+          halign="left"
+          valign="bottom"
+          font="SansSerif" />
+      <button
+          label="Send to Marketplace"
+          tool_tip="Push to my Marketplace Storefront"
+          is_toggle="false"
+          name="outbox_import_btn"
+          follows="bottom|right"
+          tab_stop="false"
+          halign="center"
+          top="37"
+          left="160"
+          height="25"
+          width="150"
+          enabled="false" />
     </panel>
-	<layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false">
-		<layout_panel />
-		<layout_panel height="45" auto_resize="false">
-			<layout_stack orientation="horizontal" left="0" height="45" top="0" width="333" follows="all">
-				<layout_panel width="0" />
-				<layout_panel width="45" auto_resize="false">
-					<loading_indicator
-						 height="45"
-						 layout="topleft"
-						 left="0"
-						 top="0"
-						 width="45"
-						 />
-				</layout_panel>
-				<layout_panel width="0" />
-			</layout_stack>
-		 </layout_panel>
-		 <layout_panel />
-	</layout_stack>
- </panel>
+    <layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false">
+      <layout_panel />
+      <layout_panel height="45" auto_resize="false">
+        <layout_stack orientation="horizontal" left="0" height="45" top="0" width="333" follows="all">
+          <layout_panel width="0" />
+          <layout_panel width="45" auto_resize="false">
+            <loading_indicator
+                height="45"
+                layout="topleft"
+                left="0"
+                top="0"
+                width="45" />
+          </layout_panel>
+          <layout_panel width="0" />
+        </layout_stack>
+      </layout_panel>
+      <layout_panel />
+    </layout_stack>
+  </panel>
 </floater>
-- 
cgit v1.2.3


From 6b919e324e55ebcac0e2d33ca44a05fae9ac1d42 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 13 Jan 2012 16:36:57 -0800
Subject: EXP-1803 FIX -- Notify the user when a folder is automatically
 created for them in the outbox

* New confirmation dialog lets them know when a folder was automatically created to contain an item dragged/copied to the outbox.
---
 indra/newview/llinventorybridge.cpp                |  2 +-
 indra/newview/llinventoryfunctions.cpp             | 45 ++++++++++++++++------
 indra/newview/llinventoryfunctions.h               |  2 +-
 .../newview/skins/default/xui/en/notifications.xml | 22 ++++++++---
 4 files changed, 53 insertions(+), 18 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 11e22d5226..270ef4fddc 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3690,7 +3690,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			{
 				if (move_is_from_outbox)
 				{
-					move_item_within_outbox(inv_item, mUUID);
+					move_item_within_outbox(inv_item, mUUID, LLToolDragAndDrop::getOperationId());
 				}
 				else
 				{
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 7672f7e674..f5be271a68 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -532,11 +532,39 @@ void show_item_original(const LLUUID& item_uuid)
 	}
 }
 
+
+static S32 create_folder_in_outbox_operation_id = -1;
+static S32 move_to_outbox_operation_id = -1;
+static std::list<LLSD> move_to_outbox_payloads;
+
 void open_outbox()
 {
 	LLFloaterReg::showInstance("outbox");
 }
 
+void folder_created_in_outbox_cb(const LLSD& notification, const LLSD& response)
+{
+	create_folder_in_outbox_operation_id = -1;
+}
+
+LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& destFolderId, S32 operation_id)
+{
+	llassert(item);
+	llassert(destFolderId.notNull());
+
+	LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName());
+	gInventory.notifyObservers();
+
+	if (create_folder_in_outbox_operation_id != operation_id)
+	{
+		LLNotificationsUtil::add("OutboxFolderCreated", LLSD(), LLSD(), boost::bind(&folder_created_in_outbox_cb, _1, _2));
+
+		create_folder_in_outbox_operation_id = operation_id;
+	}
+
+	return created_folder_id;
+}
+
 void move_to_outbox_cb_action(const LLSD& payload)
 {
 	LLViewerInventoryItem * viitem = gInventory.getItem(payload["item_id"].asUUID());
@@ -547,8 +575,8 @@ void move_to_outbox_cb_action(const LLSD& payload)
 		// when moving item directly into outbox create folder with that name
 		if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
 		{
-			dest_folder_id = gInventory.createNewCategory(dest_folder_id,  LLFolderType::FT_NONE, viitem->getName());
-			gInventory.notifyObservers();
+			S32 operation_id = payload["operation_id"].asInteger();
+			dest_folder_id = create_folder_in_outbox_for_item(viitem, dest_folder_id, operation_id);
 		}
 
 		LLUUID parent = viitem->getParentUUID();
@@ -597,9 +625,6 @@ void move_to_outbox_cb_action(const LLSD& payload)
 	}
 }
 
-static S32 move_to_outbox_operation_id = -1;
-static std::list<LLSD> move_to_outbox_payloads;
-
 void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
 {
 	const S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -618,7 +643,6 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
 	move_to_outbox_payloads.clear();
 }
 
-
 void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id)
 {
 	// Collapse links directly to items/folders
@@ -642,8 +666,7 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
 			// when moving item directly into outbox create folder with that name
 			if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
 			{
-				dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName());
-				gInventory.notifyObservers();
+				dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id);
 			}
 			
 			copy_inventory_item(gAgent.getID(),
@@ -664,6 +687,7 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
 			payload["item_id"] = inv_item->getUUID();
 			payload["dest_folder_id"] = dest_folder;
 			payload["top_level_folder"] = top_level_folder;
+			payload["operation_id"] = operation_id;
 
 			if (move_to_outbox_operation_id != operation_id)
 			{
@@ -678,13 +702,12 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
 	}
 }
 
-void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder)
+void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id)
 {
 	// when moving item directly into outbox create folder with that name
 	if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
 	{
-		dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName());
-		gInventory.notifyObservers();
+		dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id);
 	}
 	
 	LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index a93446000d..ce2b89b22e 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -75,7 +75,7 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
 void append_path(const LLUUID& id, std::string& path);
 
 void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id);
-void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder);
+void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id);
 
 void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id);
 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 1a4dab2ac5..e44fb3bf28 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -204,11 +204,23 @@ Save changes to current clothing/body part?
      name="ConfirmNoCopyToOutbox"
      type="alertmodal">
 You don't have permission to copy one or more of these items to the Merchant Outbox.  You can move them or leave them behind.
-        <usetemplate
-         name="okcancelbuttons"
-         notext="Don't move item(s)"
-         yestext="Move item(s)"/>
-    </notification>
+    <usetemplate
+     name="okcancelbuttons"
+     notext="Don't move item(s)"
+     yestext="Move item(s)"/>
+  </notification>
+
+  <notification
+   icon="OutboxStatus_Success"
+   name="OutboxFolderCreated"
+   type="outbox">
+A new folder has been created for each item you have transferred into the top level of your Merchant Outbox.
+
+    <usetemplate
+     ignoretext="A new folder was created in the Merchant Outbox"
+     name="okignore"
+     yestext="OK"/>
+  </notification>
 
   <notification
    icon="OutboxStatus_Success"
-- 
cgit v1.2.3


From 637409950512ac84a7c94c446ac60875757a92ef Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 13 Jan 2012 16:41:54 -0800
Subject: EXP-1770 WIP Drag and drop visual selection can be off across
 hierarchies made shift-selection work consistently across folder boundaries

---
 indra/newview/llfolderview.cpp     |  24 ---
 indra/newview/llfolderview.h       |   5 +-
 indra/newview/llfolderviewitem.cpp | 364 ++++++++++++++++++++++---------------
 indra/newview/llfolderviewitem.h   |  18 +-
 4 files changed, 223 insertions(+), 188 deletions(-)

diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index ecd4c2c3de..3167c51970 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -349,10 +349,6 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)
 	{
 		mFolders.insert(mFolders.begin(), folder);
 	}
-	if (folder->numSelected())
-	{
-		recursiveIncrementNumDescendantsSelected(folder->numSelected());
-	}
 	folder->setShowLoadStatus(mShowLoadStatus);
 	folder->setOrigin(0, 0);
 	folder->reshape(getRect().getWidth(), 0);
@@ -694,26 +690,6 @@ BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected)
 	return rv;
 }
 
-void LLFolderView::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items)
-{
-	// now store resulting selection
-	if (mAllowMultiSelect)
-	{
-		LLFolderViewItem *cur_selection = getCurSelectedItem();
-		LLFolderViewFolder::extendSelection(selection, cur_selection, items);
-		for (S32 i = 0; i < items.count(); i++)
-		{
-			addToSelectionList(items[i]);
-		}
-	}
-	else
-	{
-		setSelection(selection, FALSE, FALSE);
-	}
-
-	mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS;
-}
-
 static LLFastTimer::DeclareTimer FTM_SANITIZE_SELECTION("Sanitize Selection");
 void LLFolderView::sanitizeSelection()
 {
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 8af01e9102..d4305a2fe2 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -106,6 +106,8 @@ public:
 	U32 getSortOrder() const;
 	BOOL isFilterModified();
 
+	bool getAllowMultiSelect() { return mAllowMultiSelect; }
+
 	// Close all folders in the view
 	void closeAllFolders();
 	void openTopLevelFolders();
@@ -141,8 +143,6 @@ public:
 	// children, and keeps track of selected objects.
 	virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected);
 
-	virtual void extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items);
-
 	virtual std::set<LLUUID> getSelectionList() const;
 
 	// make sure if ancestor is selected, descendents are not
@@ -156,7 +156,6 @@ public:
 	void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; }
 	LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; }
 
-
 	// deletion functionality
  	void removeSelectedItems();
 
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index f27fd035db..ca7e4bc1d0 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -386,13 +386,6 @@ void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL
 	getRoot()->changeSelection(selection, selected);
 }
 
-void LLFolderViewItem::extendSelectionFromRoot(LLFolderViewItem* selection)
-{
-	LLDynamicArray<LLFolderViewItem*> selected_items;
-
-	getRoot()->extendSelection(selection, NULL, selected_items);
-}
-
 std::set<LLUUID> LLFolderViewItem::getSelectionList() const
 {
 	std::set<LLUUID> selection;
@@ -496,10 +489,6 @@ BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem,
 	if (selection == this && !mIsSelected)
 	{
 		selectItem();
-		if (mListener)
-		{
-			mListener->selectItem();
-		}
 	}
 	else if (mIsSelected)	// Deselect everything else.
 	{
@@ -520,10 +509,6 @@ BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selecte
 		{
 			selectItem();
 		}
-		if (mListener)
-		{
-			mListener->selectItem();
-		}
 		return TRUE;
 	}
 	return FALSE;
@@ -531,30 +516,16 @@ BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selecte
 
 void LLFolderViewItem::deselectItem(void)
 {
-	llassert(mIsSelected);
-
 	mIsSelected = FALSE;
-
-	// Update ancestors' count of selected descendents.
-	LLFolderViewFolder* parent_folder = getParentFolder();
-	if (parent_folder)
-	{
-		parent_folder->recursiveIncrementNumDescendantsSelected(-1);
-	}
 }
 
 void LLFolderViewItem::selectItem(void)
 {
-	llassert(!mIsSelected);
-
-	mIsSelected = TRUE;
-
-	// Update ancestors' count of selected descendents.
-	LLFolderViewFolder* parent_folder = getParentFolder();
-	if (parent_folder)
+	if (mListener)
 	{
-		parent_folder->recursiveIncrementNumDescendantsSelected(1);
+		mListener->selectItem();
 	}
+	mIsSelected = TRUE;
 }
 
 BOOL LLFolderViewItem::isMovable()
@@ -697,7 +668,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )
 		}
 		else if (mask & MASK_SHIFT)
 		{
-			extendSelectionFromRoot(this);
+			getParentFolder()->extendSelectionTo(this);
 		}
 		else
 		{
@@ -812,7 +783,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )
 		}
 		else if (mask & MASK_SHIFT)
 		{
-			extendSelectionFromRoot(this);
+			getParentFolder()->extendSelectionTo(this);
 		}
 		else
 		{
@@ -1125,7 +1096,6 @@ void LLFolderViewItem::draw()
 
 LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): 
 	LLFolderViewItem( p ),	// 0 = no create time
-	mNumDescendantsSelected(0),
 	mIsOpen(FALSE),
 	mExpanderHighlighted(FALSE),
 	mCurHeight(0.f),
@@ -1572,21 +1542,6 @@ BOOL LLFolderViewFolder::hasFilteredDescendants()
 	return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration();
 }
 
-void LLFolderViewFolder::recursiveIncrementNumDescendantsSelected(S32 increment)
-{
-	LLFolderViewFolder* parent_folder = this;
-	do
-	{
-		parent_folder->mNumDescendantsSelected += increment;
-
-		// Make sure we don't have negative values.
-		llassert(parent_folder->mNumDescendantsSelected >= 0);
-
-		parent_folder = parent_folder->getParentFolder();
-	}
-	while(parent_folder);
-}
-
 // Passes selection information on to children and record selection
 // information if necessary.
 BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem,
@@ -1599,10 +1554,6 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem
 		{
 			selectItem();
 		}
-		if (mListener)
-		{
-			mListener->selectItem();
-		}
 		rv = TRUE;
 	}
 	else
@@ -1663,10 +1614,6 @@ BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selec
 				deselectItem();
 			}
 		}
-		if (mListener && selected)
-		{
-			mListener->selectItem();
-		}
 	}
 
 	for (folders_t::iterator iter = mFolders.begin();
@@ -1690,119 +1637,261 @@ BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selec
 	return rv;
 }
 
-void LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& selected_items)
+LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse)
 {
-	// pass on to child folders first
-	for (folders_t::iterator iter = mFolders.begin();
-		iter != mFolders.end();)
+	if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL;
+
+	std::deque<LLFolderViewFolder*> item_a_ancestors;
+
+	LLFolderViewFolder* parent = item_a->getParentFolder();
+	while(parent)
 	{
-		folders_t::iterator fit = iter++;
-		(*fit)->extendSelection(selection, last_selected, selected_items);
+		item_a_ancestors.push_back(parent);
+		parent = parent->getParentFolder();
 	}
 
-	// handle selection of our immediate children...
-	BOOL reverse_select = FALSE;
-	BOOL found_last_selected = FALSE;
-	BOOL found_selection = FALSE;
-	LLDynamicArray<LLFolderViewItem*> items_to_select;
-	LLFolderViewItem* item;
+	std::deque<LLFolderViewFolder*> item_b_ancestors;
+	
+	parent = item_b->getParentFolder();
+	while(parent)
+	{
+		item_b_ancestors.push_back(parent);
+		parent = parent->getParentFolder();
+	}
 
-	//...folders first...
-	for (folders_t::iterator iter = mFolders.begin();
-		iter != mFolders.end();)
+	LLFolderViewFolder* common_ancestor = item_a->getRoot();
+
+	while(item_a_ancestors.size() > item_b_ancestors.size())
 	{
-		folders_t::iterator fit = iter++;
-		item = (*fit);
-		if(item == selection)
-		{
-			found_selection = TRUE;
-		}
-		else if (item == last_selected)
+		item_a = item_a_ancestors.front();
+		item_a_ancestors.pop_front();
+	}
+
+	while(item_b_ancestors.size() > item_a_ancestors.size())
+	{
+		item_b = item_b_ancestors.front();
+		item_b_ancestors.pop_front();
+	}
+
+	while(item_a_ancestors.size())
+	{
+		common_ancestor = item_a_ancestors.front();
+
+		if (item_a_ancestors.front() == item_b_ancestors.front())
 		{
-			found_last_selected = TRUE;
-			if (found_selection)
+			// which came first, sibling a or sibling b?
+			for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end();
+				it != end_it;
+				++it)
 			{
-				reverse_select = TRUE;
+				LLFolderViewItem* item = *it;
+
+				if (item == item_a)
+				{
+					reverse = false;
+					return common_ancestor;
+				}
+				if (item == item_b)
+				{
+					reverse = true;
+					return common_ancestor;
+				}
 			}
-		}
 
-		if (found_selection || found_last_selected)
-		{
-			// deselect currently selected items so they can be pushed back on queue
-			if (item->isSelected())
+			for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end();
+				it != end_it;
+				++it)
 			{
-				item->changeSelection(item, FALSE);
+				LLFolderViewItem* item = *it;
+
+				if (item == item_a)
+				{
+					reverse = false;
+					return common_ancestor;
+				}
+				if (item == item_b)
+				{
+					reverse = true;
+					return common_ancestor;
+				}
 			}
-			items_to_select.put(item);
+			break;
 		}
 
-		if (found_selection && found_last_selected)
-		{
-			break;
-		}		
+		item_a = item_a_ancestors.front();
+		item_a_ancestors.pop_front();
+		item_b = item_b_ancestors.front();
+		item_b_ancestors.pop_front();
 	}
 
-	if (!(found_selection && found_last_selected))
+	return NULL;
+}
+
+void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items)
+{
+	bool selecting = start == NULL;
+	if (reverse)
 	{
-		//,,,then items
-		for (items_t::iterator iter = mItems.begin();
-			iter != mItems.end();)
+		for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend();
+			it != end_it;
+			++it)
 		{
-			items_t::iterator iit = iter++;
-			item = (*iit);
-			if(item == selection)
+			if (*it == end)
 			{
-				found_selection = TRUE;
+				return;
 			}
-			else if (item == last_selected)
+			if (selecting)
 			{
-				found_last_selected = TRUE;
-				if (found_selection)
-				{
-					reverse_select = TRUE;
-				}
+				items.push_back(*it);
 			}
 
-			if (found_selection || found_last_selected)
+			if (*it == start)
 			{
-				// deselect currently selected items so they can be pushed back on queue
-				if (item->isSelected())
-				{
-					item->changeSelection(item, FALSE);
-				}
-				items_to_select.put(item);
+				selecting = true;
+			}
+		}
+		for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend();
+			it != end_it;
+			++it)
+		{
+			if (*it == end)
+			{
+				return;
 			}
 
-			if (found_selection && found_last_selected)
+			if (selecting)
 			{
-				break;
+				items.push_back(*it);
+			}
+
+			if (*it == start)
+			{
+				selecting = true;
 			}
 		}
 	}
-
-	if (found_last_selected && found_selection)
+	else
 	{
-		// we have a complete selection inside this folder
-		for (S32 index = reverse_select ? items_to_select.getLength() - 1 : 0; 
-			reverse_select ? index >= 0 : index < items_to_select.getLength(); reverse_select ? index-- : index++)
+		for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end();
+			it != end_it;
+			++it)
+		{
+			if (*it == end)
+			{
+				return;
+			}
+
+			if (selecting)
+			{
+				items.push_back(*it);
+			}
+
+			if (*it == start)
+			{
+				selecting = true;
+			}
+		}
+		for (items_t::iterator it = mItems.begin(), end_it = mItems.end();
+			it != end_it;
+			++it)
 		{
-			LLFolderViewItem* item = items_to_select[index];
-			if (item->changeSelection(item, TRUE))
+			if (*it == end)
+			{
+				return;
+			}
+
+			if (selecting)
+			{
+				items.push_back(*it);
+			}
+
+			if (*it == start)
 			{
-				selected_items.put(item);
+				selecting = true;
 			}
 		}
 	}
-	else if (found_selection)
+}
+
+void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection)
+{
+	if (getRoot()->getAllowMultiSelect() == FALSE) return;
+
+	LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem();
+	if (cur_selected_item == NULL)
+	{
+		cur_selected_item = new_selection;
+	}
+
+
+	bool reverse = false;
+	LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse);
+	if (!common_ancestor) return;
+
+	LLFolderViewItem* last_selected_item_from_cur = cur_selected_item;
+	LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder();
+
+	std::vector<LLFolderViewItem*> items_to_select_forward;
+
+	while(cur_folder != common_ancestor)
+	{
+		cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward);
+			
+		last_selected_item_from_cur = cur_folder;
+		cur_folder = cur_folder->getParentFolder();
+	}
+
+	std::vector<LLFolderViewItem*> items_to_select_reverse;
+
+	LLFolderViewItem* last_selected_item_from_new = new_selection;
+	cur_folder = new_selection->getParentFolder();
+	while(cur_folder != common_ancestor)
+	{
+		cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse);
+
+		last_selected_item_from_new = cur_folder;
+		cur_folder = cur_folder->getParentFolder();
+	}
+
+	common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward);
+
+	for (std::vector<LLFolderViewItem*>::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend();
+		it != end_it;
+		++it)
 	{
-		// last selection was not in this folder....go ahead and select just the new item
-		if (selection->changeSelection(selection, TRUE))
+		items_to_select_forward.push_back(*it);
+	}
+
+	LLFolderView* root = getRoot();
+
+	for (std::vector<LLFolderViewItem*>::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end();
+		it != end_it;
+		++it)
+	{
+		LLFolderViewItem* item = *it;
+		if (item->isSelected())
+		{
+			root->removeFromSelectionList(item);
+		}
+		else
 		{
-			selected_items.put(selection);
+			item->selectItem();
 		}
+		root->addToSelectionList(item);
 	}
+
+	if (new_selection->isSelected())
+	{
+		root->removeFromSelectionList(new_selection);
+	}
+	else
+	{
+		new_selection->selectItem();
+	}
+	root->addToSelectionList(new_selection);
 }
 
+
 void LLFolderViewFolder::destroyView()
 {
 	for (items_t::iterator iter = mItems.begin();
@@ -1874,19 +1963,11 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
 		ft = std::find(mFolders.begin(), mFolders.end(), f);
 		if (ft != mFolders.end())
 		{
-			if ((*ft)->numSelected())
-			{
-				recursiveIncrementNumDescendantsSelected(-(*ft)->numSelected());
-			}
 			mFolders.erase(ft);
 		}
 	}
 	else
 	{
-		if ((*it)->isSelected())
-		{
-			recursiveIncrementNumDescendantsSelected(-1);
-		}
 		mItems.erase(it);
 	}
 	//item has been removed, need to update filter
@@ -2055,11 +2136,6 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
 {
 	mItems.push_back(item);
 	
-	if (item->isSelected())
-	{
-		recursiveIncrementNumDescendantsSelected(1);
-	}
-	
 	item->setRect(LLRect(0, 0, getRect().getWidth(), 0));
 	item->setVisible(FALSE);
 	
@@ -2097,10 +2173,6 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
 BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
 {
 	mFolders.push_back(folder);
-	if (folder->numSelected())
-	{
-		recursiveIncrementNumDescendantsSelected(folder->numSelected());
-	}
 	folder->setOrigin(0, 0);
 	folder->reshape(getRect().getWidth(), 0);
 	folder->setVisible(FALSE);
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 3433e3f7f3..29c5b2246d 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -164,9 +164,6 @@ protected:
 	// helper function to change the selection from the root.
 	void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
 
-	// helper function to change the selection from the root.
-	void extendSelectionFromRoot(LLFolderViewItem* selection);
-
 	// this is an internal method used for adding items to folders. A
 	// no-op at this level, but reimplemented in derived classes.
 	virtual BOOL addItem(LLFolderViewItem*) { return FALSE; }
@@ -224,9 +221,6 @@ public:
 	// Returns TRUE if the selection state of this item was changed.
 	virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected);
 
-	// this method is used to group select items
-	virtual void extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items) { }
-
 	// this method is used to deselect this element
 	void deselectItem();
 
@@ -373,13 +367,6 @@ public:
 	typedef std::list<LLFolderViewItem*> items_t;
 	typedef std::list<LLFolderViewFolder*> folders_t;
 
-private:
-	S32		mNumDescendantsSelected;
-
-public:		// Accessed needed by LLFolderViewItem
-	void recursiveIncrementNumDescendantsSelected(S32 increment);
-	S32 numSelected(void) const { return mNumDescendantsSelected + (isSelected() ? 1 : 0); }
-
 protected:
 	items_t mItems;
 	folders_t mFolders;
@@ -461,7 +448,7 @@ public:
 	virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected);
 
 	// this method is used to group select items
-	virtual void extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items);
+	void extendSelectionTo(LLFolderViewItem* selection);
 
 	// Returns true is this object and all of its children can be removed.
 	virtual BOOL isRemovable();
@@ -551,7 +538,6 @@ public:
 
 	time_t getCreationDate() const;
 	bool isTrash() const;
-	S32 getNumSelectedDescendants(void) const { return mNumDescendantsSelected; }
 
 	folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); }
 	folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); }
@@ -560,6 +546,8 @@ public:
 	items_t::const_iterator getItemsBegin() const { return mItems.begin(); }
 	items_t::const_iterator getItemsEnd() const { return mItems.end(); }
 	items_t::size_type getItemsCount() const { return mItems.size(); }
+	LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse);
+	void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse,  std::vector<LLFolderViewItem*>& items);
 };
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- 
cgit v1.2.3


From 5e5105bd223f5180bbca634ba2c393be2ef3d13d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 13 Jan 2012 18:37:50 -0800
Subject: EXP-1770 WIP Drag and drop visual selection can be off across
 hierarchies added throttling to fetchInventoryItem queries

---
 indra/newview/llfolderviewitem.cpp                |  11 +-
 indra/newview/llinventorybridge.cpp               |   2 +-
 indra/newview/llinventorymodelbackgroundfetch.cpp | 328 +++++++++++++++-------
 indra/newview/llinventorymodelbackgroundfetch.h   |  16 +-
 4 files changed, 237 insertions(+), 120 deletions(-)

diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index ca7e4bc1d0..50d62b29d3 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -499,7 +499,7 @@ BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem,
 
 BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected)
 {
-	if (selection == this && mIsSelected != selected)
+	if (selection == this)
 	{
 		if (mIsSelected)
 		{
@@ -521,11 +521,14 @@ void LLFolderViewItem::deselectItem(void)
 
 void LLFolderViewItem::selectItem(void)
 {
-	if (mListener)
+	if (mIsSelected == FALSE)
 	{
-		mListener->selectItem();
+		if (mListener)
+		{
+			mListener->selectItem();
+		}
+		mIsSelected = TRUE;
 	}
-	mIsSelected = TRUE;
 }
 
 BOOL LLFolderViewItem::isMovable()
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index eaf9b53eb9..5916ed60a4 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1234,7 +1234,7 @@ void LLItemBridge::selectItem()
 	LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
 	if(item && !item->isFinished())
 	{
-		item->fetchFromServer();
+		LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
 	}
 }
 
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 91fdd67806..5f0c744192 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -50,7 +50,7 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :
 	mMinTimeBetweenFetches(0.3f),
 	mMaxTimeBetweenFetches(10.f),
 	mTimelyFetchPending(FALSE),
-	mBulkFetchCount(0)
+	mFetchCount(0)
 {
 }
 
@@ -60,7 +60,7 @@ LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()
 
 bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const
 {
-	return mFetchQueue.empty() && mBulkFetchCount<=0;
+	return mFetchQueue.empty() && mFetchCount<=0;
 }
 
 bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const
@@ -103,44 +103,60 @@ BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() const
 	return mBackgroundFetchActive;
 }
 
-void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive)
+void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)
 {
-	if (!mAllFoldersFetched || cat_id.notNull())
-	{
-		LL_DEBUGS("InventoryFetch") << "Start fetching category: " << cat_id << ", recursive: " << recursive << LL_ENDL;
+	if (id.isNull()) return;
 
-		mBackgroundFetchActive = TRUE;
-		if (cat_id.isNull())
+	LLViewerInventoryCategory* cat = gInventory.getCategory(id);
+	if (cat)
+	{	// it's a folder, do a bulk fetch
+		if (!mAllFoldersFetched)
 		{
-			if (!mRecursiveInventoryFetchStarted)
+			LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL;
+
+			mBackgroundFetchActive = TRUE;
+			if (id.isNull())
 			{
-				mRecursiveInventoryFetchStarted |= recursive;
-				mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive));
-				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
+				if (!mRecursiveInventoryFetchStarted)
+				{
+					mRecursiveInventoryFetchStarted |= recursive;
+					mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive));
+					gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
+				}
+				if (!mRecursiveLibraryFetchStarted)
+				{
+					mRecursiveLibraryFetchStarted |= recursive;
+					mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive));
+					gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
+				}
 			}
-			if (!mRecursiveLibraryFetchStarted)
+			else
 			{
-				mRecursiveLibraryFetchStarted |= recursive;
-				mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive));
-				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
+				// Specific folder requests go to front of queue.
+				if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)
+				{
+					mFetchQueue.push_front(FetchQueueInfo(id, recursive));
+					gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
+				}
+				if (id == gInventory.getLibraryRootFolderID())
+				{
+					mRecursiveLibraryFetchStarted |= recursive;
+				}
+				if (id == gInventory.getRootFolderID())
+				{
+					mRecursiveInventoryFetchStarted |= recursive;
+				}
 			}
 		}
-		else
+	}
+	else if (LLViewerInventoryItem* itemp = gInventory.getItem(id))
+	{
+		if (!itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id))
 		{
-			// Specific folder requests go to front of queue.
-			if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id)
-			{
-				mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive));
-				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
-			}
-			if (cat_id == gInventory.getLibraryRootFolderID())
-			{
-				mRecursiveLibraryFetchStarted |= recursive;
-			}
-			if (cat_id == gInventory.getRootFolderID())
-			{
-				mRecursiveInventoryFetchStarted |= recursive;
-			}
+			mBackgroundFetchActive = TRUE;
+
+			mFetchQueue.push_front(FetchQueueInfo(id, false, false));
+			gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
 		}
 	}
 }
@@ -158,7 +174,7 @@ void LLInventoryModelBackgroundFetch::stopBackgroundFetch()
 	{
 		mBackgroundFetchActive = FALSE;
 		gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
-		mBulkFetchCount=0;
+		mFetchCount=0;
 		mMinTimeBetweenFetches=0.0f;
 	}
 }
@@ -183,10 +199,9 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
 	if (mBackgroundFetchActive && gAgent.getRegion())
 	{
 		// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
-		std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");   
-		if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty()) 
+		if (gSavedSettings.getBOOL("UseHTTPInventory")) 
 		{
-			bulkFetch(url);
+			bulkFetch();
 			return;
 		}
 		
@@ -230,7 +245,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
 			}
 
 			const FetchQueueInfo info = mFetchQueue.front();
-			LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID);
+			LLViewerInventoryCategory* cat = gInventory.getCategory(info.mUUID);
 
 			// Category has been deleted, remove from queue.
 			if (!cat)
@@ -258,7 +273,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
 				}
 			}
 			// Do I have all my children?
-			else if (gInventory.isCategoryComplete(info.mCatUUID))
+			else if (gInventory.isCategoryComplete(info.mUUID))
 			{
 				// Finished with this category, remove from queue.
 				mFetchQueue.pop_front();
@@ -313,15 +328,35 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
 	}
 }
 
-void LLInventoryModelBackgroundFetch::incrBulkFetch(S16 fetching) 
+void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching) 
 {  
-	mBulkFetchCount += fetching; 
-	if (mBulkFetchCount < 0)
+	mFetchCount += fetching; 
+	if (mFetchCount < 0)
 	{
-		mBulkFetchCount = 0; 
+		mFetchCount = 0; 
 	}
 }
 
+class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder
+{
+public:
+	LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {};
+	void result(const LLSD& content);			
+	void error(U32 status, const std::string& reason);
+};
+
+void LLInventoryModelFetchItemResponder::result( const LLSD& content )
+{
+	LLInventoryModel::fetchInventoryResponder::result(content);
+	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
+}
+
+void LLInventoryModelFetchItemResponder::error( U32 status, const std::string& reason )
+{
+	LLInventoryModel::fetchInventoryResponder::error(status, reason);
+	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
+}
+
 
 class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
 {
@@ -458,7 +493,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
 		}
 	}
 
-	fetcher->incrBulkFetch(-1);
+	fetcher->incrFetchCount(-1);
 	
 	if (fetcher->isBulkFetchProcessingComplete())
 	{
@@ -477,7 +512,7 @@ void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::str
 	llinfos << "LLInventoryModelFetchDescendentsResponder::error "
 		<< status << ": " << reason << llendl;
 						
-	fetcher->incrBulkFetch(-1);
+	fetcher->incrFetchCount(-1);
 
 	if (status==499) // timed out
 	{
@@ -508,12 +543,14 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat
 
 // Bundle up a bunch of requests to send all at once.
 // static   
-void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
+void LLInventoryModelBackgroundFetch::bulkFetch()
 {
 	//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped.
 	//If there are items in mFetchQueue, we want to check the time since the last bulkFetch was 
 	//sent.  If it exceeds our retry time, go ahead and fire off another batch.  
 	//Stopbackgroundfetch will be run from the Responder instead of here.  
+	LLViewerRegion* region = gAgent.getRegion();
+	if (!region) return;
 
 	S16 max_concurrent_fetches=8;
 	F32 new_min_time = 0.5f;			//HACK!  Clean this up when old code goes away entirely.
@@ -523,12 +560,13 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
 	}
 	
 	if (gDisconnected ||
-		(mBulkFetchCount > max_concurrent_fetches) ||
+		(mFetchCount > max_concurrent_fetches) ||
 		(mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches))
 	{
 		return; // just bail if we are disconnected
 	}	
 
+	U32 item_count=0;
 	U32 folder_count=0;
 	U32 max_batch_size=5;
 
@@ -536,83 +574,159 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
 
 	uuid_vec_t recursive_cats;
 
-	LLSD body;
-	LLSD body_lib;
+	LLSD folder_request_body;
+	LLSD folder_request_body_lib;
+	LLSD item_request_body;
+	LLSD item_request_body_lib;
 
-	while (!(mFetchQueue.empty()) && (folder_count < max_batch_size))
+	while (!(mFetchQueue.empty()) && ((item_count + folder_count) < max_batch_size))
 	{
 		const FetchQueueInfo& fetch_info = mFetchQueue.front();
-		const LLUUID &cat_id = fetch_info.mCatUUID;
-        if (cat_id.isNull()) //DEV-17797
-        {
-			LLSD folder_sd;
-			folder_sd["folder_id"]		= LLUUID::null.asString();
-			folder_sd["owner_id"]		= gAgent.getID();
-			folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
-			folder_sd["fetch_folders"]	= (LLSD::Boolean)FALSE;
-			folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
-			body["folders"].append(folder_sd);
-            folder_count++;
-        }
-        else
-        {
-		    const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
+		if (fetch_info.mIsCategory)
+		{
+
+			const LLUUID &cat_id = fetch_info.mUUID;
+			if (cat_id.isNull()) //DEV-17797
+			{
+				LLSD folder_sd;
+				folder_sd["folder_id"]		= LLUUID::null.asString();
+				folder_sd["owner_id"]		= gAgent.getID();
+				folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
+				folder_sd["fetch_folders"]	= (LLSD::Boolean)FALSE;
+				folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
+				folder_request_body["folders"].append(folder_sd);
+				folder_count++;
+			}
+			else
+			{
+				const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
 		
-		    if (cat)
-		    {
-			    if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
-			    {
-				    LLSD folder_sd;
-				    folder_sd["folder_id"]		= cat->getUUID();
-				    folder_sd["owner_id"]		= cat->getOwnerID();
-				    folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
-				    folder_sd["fetch_folders"]	= TRUE; //(LLSD::Boolean)sFullFetchStarted;
-				    folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
-				    
-				    if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
-					    body_lib["folders"].append(folder_sd);
-				    else
-					    body["folders"].append(folder_sd);
-				    folder_count++;
-			    }
-				// May already have this folder, but append child folders to list.
-			    if (fetch_info.mRecursive)
-			    {	
-					LLInventoryModel::cat_array_t* categories;
-					LLInventoryModel::item_array_t* items;
-					gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
-					for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
-						 it != categories->end();
-						 ++it)
+				if (cat)
+				{
+					if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
 					{
-						mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
-				    }
-			    }
-		    }
-        }
-		if (fetch_info.mRecursive)
-			recursive_cats.push_back(cat_id);
+						LLSD folder_sd;
+						folder_sd["folder_id"]		= cat->getUUID();
+						folder_sd["owner_id"]		= cat->getOwnerID();
+						folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
+						folder_sd["fetch_folders"]	= TRUE; //(LLSD::Boolean)sFullFetchStarted;
+						folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
+				    
+						if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
+							folder_request_body_lib["folders"].append(folder_sd);
+						else
+							folder_request_body["folders"].append(folder_sd);
+						folder_count++;
+					}
+					// May already have this folder, but append child folders to list.
+					if (fetch_info.mRecursive)
+					{	
+						LLInventoryModel::cat_array_t* categories;
+						LLInventoryModel::item_array_t* items;
+						gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
+						for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
+							 it != categories->end();
+							 ++it)
+						{
+							mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
+						}
+					}
+				}
+			}
+			if (fetch_info.mRecursive)
+				recursive_cats.push_back(cat_id);
+		}
+		else
+		{
+			LLViewerInventoryItem* itemp = gInventory.getItem(fetch_info.mUUID);
+			if (itemp)
+			{
+				LLSD item_sd;
+				item_sd["owner_id"] = itemp->getPermissions().getOwner();
+				item_sd["item_id"] = itemp->getUUID();
+				if (itemp->getPermissions().getOwner() == gAgent.getID())
+				{
+					item_request_body.append(item_sd);
+				}
+				else
+				{
+					item_request_body_lib.append(item_sd);
+				}
+				//itemp->fetchFromServer();
+				item_count++;
+			}
+		}
 
 		mFetchQueue.pop_front();
 	}
 		
-	if (folder_count > 0)
+	if (item_count + folder_count > 0)
 	{
-		mBulkFetchCount++;
-		if (body["folders"].size())
+		if (folder_count)
 		{
-			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body, recursive_cats);
-			LLHTTPClient::post(url, body, fetcher, 300.0);
+			std::string url = region->getCapability("FetchInventoryDescendents2");   
+			mFetchCount++;
+			if (folder_request_body["folders"].size())
+			{
+				LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
+				LLHTTPClient::post(url, folder_request_body, fetcher, 300.0);
+			}
+			if (folder_request_body_lib["folders"].size())
+			{
+				std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
+
+				LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
+				LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0);
+			}
 		}
-		if (body_lib["folders"].size())
+		if (item_count)
 		{
-			std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
-			
-			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats);
-			LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0);
+			std::string url;
+
+			if (item_request_body.size())
+			{
+				mFetchCount++;
+				url = region->getCapability("FetchInventory2");
+				if (!url.empty())
+				{
+					LLSD body;
+					body["agent_id"]	= gAgent.getID();
+					body["items"] = item_request_body;
+
+					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
+				}
+				//else
+				//{
+				//	LLMessageSystem* msg = gMessageSystem;
+				//	msg->newMessage("FetchInventory");
+				//	msg->nextBlock("AgentData");
+				//	msg->addUUID("AgentID", gAgent.getID());
+				//	msg->addUUID("SessionID", gAgent.getSessionID());
+				//	msg->nextBlock("InventoryData");
+				//	msg->addUUID("OwnerID", mPermissions.getOwner());
+				//	msg->addUUID("ItemID", mUUID);
+				//	gAgent.sendReliableMessage();
+				//}
+			}
+
+			if (item_request_body_lib.size())
+			{
+				mFetchCount++;
+
+				url = region->getCapability("FetchLib2");
+				if (!url.empty())
+				{
+					LLSD body;
+					body["agent_id"]	= gAgent.getID();
+					body["items"] = item_request_body_lib;
+
+					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
+				}
+			}
 		}
 		mFetchTimer.reset();
 	}
+
 	else if (isBulkFetchProcessingComplete())
 	{
 		setAllFoldersFetched();
@@ -624,7 +738,7 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL
 	for (fetch_queue_t::const_iterator it = mFetchQueue.begin();
 		 it != mFetchQueue.end(); ++it)
 	{
-		const LLUUID& fetch_id = (*it).mCatUUID;
+		const LLUUID& fetch_id = (*it).mUUID;
 		if (gInventory.isObjectDescendentOf(fetch_id, cat_id))
 			return false;
 	}
diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h
index c35c785ceb..0745407a8c 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.h
+++ b/indra/newview/llinventorymodelbackgroundfetch.h
@@ -60,10 +60,10 @@ public:
 	bool inventoryFetchInProgress() const;
 
     void findLostItems();	
+	void incrFetchCount(S16 fetching);
 protected:
-	void incrBulkFetch(S16 fetching);
 	bool isBulkFetchProcessingComplete() const;
-	void bulkFetch(std::string url);
+	void bulkFetch();
 
 	void backgroundFetch();
 	static void backgroundFetchCB(void*); // background fetch idle function
@@ -77,7 +77,7 @@ private:
 	BOOL mAllFoldersFetched;
 
 	BOOL mBackgroundFetchActive;
-	S16 mBulkFetchCount;
+	S16 mFetchCount;
 	BOOL mTimelyFetchPending;
 	S32 mNumFetchRetries;
 
@@ -87,11 +87,11 @@ private:
 
 	struct FetchQueueInfo
 	{
-		FetchQueueInfo(const LLUUID& id, BOOL recursive) :
-			mCatUUID(id), mRecursive(recursive)
-		{
-		}
-		LLUUID mCatUUID;
+		FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) :
+			mUUID(id), mRecursive(recursive), mIsCategory(is_category)
+		{}
+		LLUUID mUUID;
+		bool mIsCategory;
 		BOOL mRecursive;
 	};
 	typedef std::deque<FetchQueueInfo> fetch_queue_t;
-- 
cgit v1.2.3


From c0d2d316bef9157fcf80e7ee33aff38b55410f16 Mon Sep 17 00:00:00 2001
From: Jonathan Yap <none@none>
Date: Sun, 15 Jan 2012 10:04:41 -0500
Subject: STORM-1796 Preferences->Privacy->Only friends and groups can call or
 IM me cannot be changed unless Voice Chat is enabled

---
 doc/contributions.txt                                            | 1 +
 indra/newview/skins/default/xui/en/panel_preferences_privacy.xml | 1 -
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 84f399cc89..30cc447bbf 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -607,6 +607,7 @@ Jonathan Yap
 	STORM-1737
 	STORM-1733
 	STORM-1790
+	STORM-1796
 Kadah Coba
 	STORM-1060
 Jondan Lundquist
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
index 47236c1a48..587c461bee 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
@@ -59,7 +59,6 @@
      top_pad="30"
      width="350" />
     <check_box
-     enabled_control="EnableVoiceChat"
      control_name="VoiceCallsFriendsOnly"
      height="16"
      label="Only friends and groups can call or IM me"
-- 
cgit v1.2.3


From 1fc53d33bd6ca6e6cb2f32281e54bd5c78b15610 Mon Sep 17 00:00:00 2001
From: Jonathan Yap <none@none>
Date: Mon, 16 Jan 2012 12:16:17 -0500
Subject: STORM-1799 Object doesn't appear in Block list if trying to block
 from Remote object inspector

---
 doc/contributions.txt                   |  1 +
 indra/newview/llinspectremoteobject.cpp | 24 +++---------------------
 2 files changed, 4 insertions(+), 21 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 84f399cc89..cd782985dd 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -607,6 +607,7 @@ Jonathan Yap
 	STORM-1737
 	STORM-1733
 	STORM-1790
+	STORM-1799
 Kadah Coba
 	STORM-1060
 Jondan Lundquist
diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp
index bf6cf52298..a12ec390af 100644
--- a/indra/newview/llinspectremoteobject.cpp
+++ b/indra/newview/llinspectremoteobject.cpp
@@ -60,12 +60,10 @@ public:
 	
 private:
 	void update();
-	void onNameCache(const LLUUID& id, const std::string& name, bool is_group);
 	
 private:
 	LLUUID		 mObjectID;
 	LLUUID		 mOwnerID;
-	std::string  mOwnerLegacyName;
 	std::string  mSLurl;
 	std::string  mName;
 	bool         mGroupOwned;
@@ -75,7 +73,6 @@ LLInspectRemoteObject::LLInspectRemoteObject(const LLSD& sd) :
 	LLInspect(LLSD()),
 	mObjectID(NULL),
 	mOwnerID(NULL),
-	mOwnerLegacyName(),
 	mSLurl(""),
 	mName(""),
 	mGroupOwned(false)
@@ -111,14 +108,6 @@ void LLInspectRemoteObject::onOpen(const LLSD& data)
 	mGroupOwned = data["group_owned"].asBoolean();
 	mSLurl      = data["slurl"].asString();
 
-	// work out the owner's name
-	mOwnerLegacyName = "";
-	if (gCacheName)
-	{
-		gCacheName->get(mOwnerID, mGroupOwned,  // muting
-			boost::bind(&LLInspectRemoteObject::onNameCache, this, _1, _2, _3));
-	}
-
 	// update the inspector with the current object state
 	update();
 
@@ -144,8 +133,7 @@ void LLInspectRemoteObject::onClickMap()
 
 void LLInspectRemoteObject::onClickBlock()
 {
-	LLMute::EType mute_type = mGroupOwned ? LLMute::GROUP : LLMute::AGENT;
-	LLMute mute(mOwnerID, mOwnerLegacyName, mute_type);
+	LLMute mute(mObjectID, mName, LLMute::OBJECT);
 	LLMuteList::getInstance()->add(mute);
 	LLPanelBlockedList::showPanelAndSelect(mute.mID);
 	closeFloater();
@@ -156,12 +144,6 @@ void LLInspectRemoteObject::onClickClose()
 	closeFloater();
 }
 
-void LLInspectRemoteObject::onNameCache(const LLUUID& id, const std::string& name, bool is_group)
-{
-	mOwnerLegacyName = name;
-	update();
-}
-
 void LLInspectRemoteObject::update()
 {
 	// show the object name as the inspector's title
@@ -198,8 +180,8 @@ void LLInspectRemoteObject::update()
 	// disable the Map button if we don't have a SLurl
 	getChild<LLUICtrl>("map_btn")->setEnabled(! mSLurl.empty());
 
-	// disable the Block button if we don't have the owner ID
-	getChild<LLUICtrl>("block_btn")->setEnabled(! mOwnerID.isNull());
+	// disable the Block button if we don't have the object ID (will this ever happen?)
+	getChild<LLUICtrl>("block_btn")->setEnabled(! mObjectID.isNull());
 }
 
 //////////////////////////////////////////////////////////////////////////////
-- 
cgit v1.2.3


From cd4204b2730350eede126190814621b65308c422 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 16 Jan 2012 11:03:33 -0800
Subject: EXP-1758 WIP Progress spinner not shown during merketplace synch if
 Merchant Outbox floater was previously minimized rewrote layout_stack
 resizing logic to be symmetrical

---
 indra/llui/lllayoutstack.cpp                       | 784 ++++++++++++---------
 indra/llui/lllayoutstack.h                         |  69 +-
 indra/llui/llresizebar.cpp                         |   4 +-
 indra/llui/llresizebar.h                           |   1 +
 indra/llui/llwindowshade.cpp                       |   4 +-
 indra/newview/llchathistory.cpp                    |   1 -
 indra/newview/llchicletbar.cpp                     |  27 -
 indra/newview/llfloaternotificationsconsole.cpp    |   2 +-
 indra/newview/llimfloater.cpp                      |   3 -
 indra/newview/llsidepanelinventory.cpp             |   1 -
 .../skins/default/xui/en/floater_help_browser.xml  |   1 -
 .../skins/default/xui/en/floater_im_session.xml    |   5 +-
 .../skins/default/xui/en/floater_media_browser.xml |   4 -
 .../default/xui/en/floater_test_layout_stacks.xml  | 223 ++++++
 .../skins/default/xui/en/floater_ui_preview.xml    |   2 +
 .../default/xui/en/floater_voice_controls.xml      |   5 +-
 .../skins/default/xui/en/floater_web_content.xml   |   5 +-
 indra/newview/skins/default/xui/en/main_view.xml   |   2 -
 .../skins/default/xui/en/menu_inventory_add.xml    |   1 +
 .../default/xui/en/panel_adhoc_control_panel.xml   |   6 +-
 .../skins/default/xui/en/panel_bottomtray_lite.xml |   8 +-
 .../skins/default/xui/en/panel_chiclet_bar.xml     |   4 -
 .../skins/default/xui/en/panel_classified_info.xml |  12 +-
 .../skins/default/xui/en/panel_edit_classified.xml |   2 -
 .../skins/default/xui/en/panel_edit_pick.xml       |   2 -
 .../skins/default/xui/en/panel_edit_profile.xml    |   2 -
 .../skins/default/xui/en/panel_edit_wearable.xml   |   2 -
 .../default/xui/en/panel_group_control_panel.xml   |  11 +-
 .../default/xui/en/panel_group_info_sidetray.xml   |   5 +-
 .../default/xui/en/panel_im_control_panel.xml      |  23 +-
 .../skins/default/xui/en/panel_landmarks.xml       |   4 -
 indra/newview/skins/default/xui/en/panel_login.xml |   2 -
 .../skins/default/xui/en/panel_main_inventory.xml  |   4 -
 .../skins/default/xui/en/panel_navigation_bar.xml  |   1 -
 .../skins/default/xui/en/panel_nearby_media.xml    |  10 +-
 .../skins/default/xui/en/panel_outfit_edit.xml     |   6 +-
 .../default/xui/en/panel_outfits_inventory.xml     |   2 -
 .../newview/skins/default/xui/en/panel_people.xml  |  12 -
 .../skins/default/xui/en/panel_pick_info.xml       |   3 -
 indra/newview/skins/default/xui/en/panel_picks.xml |   5 -
 .../skins/default/xui/en/panel_place_profile.xml   |   2 -
 .../newview/skins/default/xui/en/panel_places.xml  |  10 -
 .../default/xui/en/panel_postcard_settings.xml     |   2 -
 .../default/xui/en/panel_prim_media_controls.xml   |  35 +-
 .../skins/default/xui/en/panel_progress.xml        |   3 -
 .../skins/default/xui/en/panel_snapshot_local.xml  |   2 -
 .../default/xui/en/panel_snapshot_profile.xml      |   2 -
 .../skins/default/xui/en/panel_toolbar_view.xml    |   5 -
 .../skins/default/xui/en/sidepanel_inventory.xml   |  12 +-
 49 files changed, 755 insertions(+), 588 deletions(-)
 create mode 100644 indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 0e7060e22c..b67030dc34 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -34,10 +34,13 @@
 #include "llpanel.h"
 #include "llresizebar.h"
 #include "llcriticaldamp.h"
+#include "boost/foreach.hpp"
 
 static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack");
 static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel");
 
+static const F32 MAX_FRACTIONAL_VALUE = 0.99999f;
+
 void LLLayoutStack::OrientationNames::declareValues()
 {
 	declare("horizontal", HORIZONTAL);
@@ -49,15 +52,12 @@ void LLLayoutStack::OrientationNames::declareValues()
 //
 LLLayoutPanel::Params::Params()	
 :	expanded_min_dim("expanded_min_dim", 0),
-	min_dim("min_dim", 0),
-	max_dim("max_dim", S32_MAX),
-	user_resize("user_resize", true),
+	min_dim("min_dim", -1),
+	user_resize("user_resize", false),
 	auto_resize("auto_resize", true)
 {
 	addSynonym(min_dim, "min_width");
 	addSynonym(min_dim, "min_height");
-	addSynonym(max_dim, "max_width");
-	addSynonym(max_dim, "max_height");
 }
 
 LLLayoutPanel::LLLayoutPanel(const Params& p)	
@@ -65,7 +65,6 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
 	mExpandedMinDimSpecified(false),
 	mExpandedMinDim(p.min_dim),
  	mMinDim(p.min_dim), 
- 	mMaxDim(p.max_dim), 
  	mAutoResize(p.auto_resize),
  	mUserResize(p.user_resize),
 	mCollapsed(FALSE),
@@ -73,6 +72,8 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
 	mVisibleAmt(1.f), // default to fully visible
 	mResizeBar(NULL),
 	mFractionalSize(0.f),
+	mTargetDim(0),
+	mIgnoreReshape(false),
 	mOrientation(LLLayoutStack::HORIZONTAL)
 {
 	// Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value
@@ -103,33 +104,85 @@ LLLayoutPanel::~LLLayoutPanel()
 	mResizeBar = NULL;
 }
 
-void LLLayoutPanel::reshape(S32 width, S32 height, BOOL called_from_parent)
+F32 LLLayoutPanel::getAutoResizeFactor() const
+{
+	return mVisibleAmt * (1.f - mCollapseAmt);
+}
+ 
+F32 LLLayoutPanel::getVisibleAmount() const
+{
+	return mVisibleAmt;
+}
+
+S32 LLLayoutPanel::getLayoutDim() const
+{
+	return llround((mOrientation == LLLayoutStack::HORIZONTAL)
+					? getRect().getWidth()
+					: getRect().getHeight());
+}
+ 
+S32 LLLayoutPanel::getVisibleDim() const
+{
+	F32 min_dim = getRelevantMinDim();
+	return llround(mVisibleAmt
+					* (min_dim
+						+ (((F32)mTargetDim - min_dim) * (1.f - mCollapseAmt))));
+}
+ 
+void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientation )
 {
-	if (mOrientation == LLLayoutStack::HORIZONTAL)
+	mOrientation = orientation;
+	S32 layout_dim = llround((mOrientation == LLLayoutStack::HORIZONTAL)
+		? getRect().getWidth()
+		: getRect().getHeight());
+
+	if (mMinDim == -1)
 	{
-		mFractionalSize += width - llround(mFractionalSize);
+		if (!mAutoResize)
+		{
+			setMinDim(layout_dim);
+		}
+		else
+		{
+			setMinDim(0);
+		}
 	}
-	else
+
+	mTargetDim = llmax(layout_dim, getMinDim());
+}
+ 
+void LLLayoutPanel::setVisible( BOOL visible )
+{
+	if (visible != getVisible())
 	{
-		mFractionalSize += height - llround(mFractionalSize);
+		LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent());
+		stackp->mNeedsLayout = true;
 	}
-	LLPanel::reshape(width, height, called_from_parent);
+	LLPanel::setVisible(visible);
 }
 
-F32 LLLayoutPanel::getCollapseFactor()
+void LLLayoutPanel::reshape( S32 width, S32 height, BOOL called_from_parent /*= TRUE*/ )
 {
-	if (mOrientation == LLLayoutStack::HORIZONTAL)
+	if (!mIgnoreReshape && !mAutoResize)
 	{
-		F32 collapse_amt = 
-			clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getWidth()));
-		return mVisibleAmt * collapse_amt;
+		mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height;
 	}
-	else
+	LLPanel::reshape(width, height, called_from_parent);
+}
+
+void LLLayoutPanel::handleReshape(const LLRect& new_rect, bool by_user)
+{
+	LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent());
+	if (stackp)
 	{
-		F32 collapse_amt = 
-			clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getHeight())));
-		return mVisibleAmt * collapse_amt;
+		stackp->mNeedsLayout = true;
+		if (by_user)
+		{
+			// tell layout stack to account for new shape
+			stackp->updatePanelRect(this, new_rect);
+		}
 	}
+	LLPanel::handleReshape(new_rect, by_user);
 }
 
 //
@@ -147,12 +200,11 @@ LLLayoutStack::Params::Params()
 
 LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) 
 :	LLView(p),
-	mMinWidth(0),
-	mMinHeight(0),
 	mPanelSpacing(p.border_size),
 	mOrientation(p.orientation),
 	mAnimate(p.animate),
 	mAnimatedThisFrame(false),
+	mNeedsLayout(true),
 	mClip(p.clip),
 	mOpenTimeConstant(p.open_time_constant),
 	mCloseTimeConstant(p.close_time_constant)
@@ -169,26 +221,26 @@ void LLLayoutStack::draw()
 {
 	updateLayout();
 
-	e_panel_list_t::iterator panel_it;
-	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+	// always clip to stack itself
+	LLLocalClipRect clip(getLocalRect());
+	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
 	{
 		// clip to layout rectangle, not bounding rectangle
-		LLRect clip_rect = (*panel_it)->getRect();
+		LLRect clip_rect = panelp->getRect();
 		// scale clipping rectangle by visible amount
 		if (mOrientation == HORIZONTAL)
 		{
-			clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor());
+			clip_rect.mRight = clip_rect.mLeft + panelp->getVisibleDim();
 		}
 		else
 		{
-			clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor());
+			clip_rect.mBottom = clip_rect.mTop - panelp->getVisibleDim();
 		}
 
-		LLPanel* panelp = (*panel_it);
-
-		LLLocalClipRect clip(clip_rect, mClip);
-		// only force drawing invisible children if visible amount is non-zero
-		drawChild(panelp, 0, 0, !clip_rect.isEmpty());
+		{LLLocalClipRect clip(clip_rect, mClip);
+			// only force drawing invisible children if visible amount is non-zero
+			drawChild(panelp, 0, 0, !clip_rect.isEmpty());
+		}
 	}
 	mAnimatedThisFrame = false;
 }
@@ -201,12 +253,10 @@ void LLLayoutStack::removeChild(LLView* view)
 	{
 		mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
 		delete embedded_panelp;
+		updateFractionalSizes();
+		mNeedsLayout = true;
 	}
 
-	// need to update resizebars
-
-	calcMinExtents();
-
 	LLView::removeChild(view);
 }
 
@@ -221,29 +271,15 @@ bool LLLayoutStack::addChild(LLView* child, S32 tab_group)
 	LLLayoutPanel* panelp = dynamic_cast<LLLayoutPanel*>(child);
 	if (panelp)
 	{
-		panelp->mFractionalSize = (mOrientation == HORIZONTAL)
-									? panelp->getRect().getWidth()
-									: panelp->getRect().getHeight();
 		panelp->setOrientation(mOrientation);
 		mPanels.push_back(panelp);
+		createResizeBar(panelp);
+		mNeedsLayout = true;
 	}
-	return LLView::addChild(child, tab_group);
-}
-
-void LLLayoutStack::movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front)
-{
-	LLLayoutPanel* embedded_panel_to_move = findEmbeddedPanel(panel_to_move);
-	LLLayoutPanel* embedded_target_panel = move_to_front ? *mPanels.begin() : findEmbeddedPanel(target_panel);
+	BOOL result = LLView::addChild(child, tab_group);
 
-	if (!embedded_panel_to_move || !embedded_target_panel || embedded_panel_to_move == embedded_target_panel)
-	{
-		llwarns << "One of the panels was not found in stack or NULL was passed instead of valid panel" << llendl;
-		return;
-	}
-	e_panel_list_t::iterator it = std::find(mPanels.begin(), mPanels.end(), embedded_panel_to_move);
-	mPanels.erase(it);
-	it = move_to_front ? mPanels.begin() : std::find(mPanels.begin(), mPanels.end(), embedded_target_panel);
-	mPanels.insert(it, embedded_panel_to_move);
+	updateFractionalSizes();
+	return result;
 }
 
 void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate)
@@ -258,23 +294,19 @@ void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate)
 	}
 }
 
-void LLLayoutStack::removePanel(LLPanel* panel)
-{
-	removeChild(panel);
-}
-
 void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
 {
 	LLLayoutPanel* panel_container = findEmbeddedPanel(panel);
 	if (!panel_container) return;
 
 	panel_container->mCollapsed = collapsed;
+	mNeedsLayout = true;
 }
 
 void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize)
 {
 	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
-
+	
 	if (panel)
 	{
 		panel->mAutoResize = auto_resize;
@@ -291,51 +323,246 @@ void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_
 	}
 }
 
-bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_dimp)
+
+static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks");
+
+void LLLayoutStack::updateLayout()
+{	
+	LLFastTimer ft(FTM_UPDATE_LAYOUT);
+
+	if (!mNeedsLayout) return;
+
+	bool animation_in_progress = animatePanels();
+	F32 total_visible_fraction = 0.f;
+	S32 space_to_distribute = (mOrientation == HORIZONTAL)
+							? getRect().getWidth()
+							: getRect().getHeight();
+
+	// first, assign minimum dimensions
+	LLLayoutPanel* panelp = NULL;
+	BOOST_FOREACH(panelp, mPanels)
+	{
+		if (panelp->mAutoResize)
+		{
+			panelp->mTargetDim = panelp->getRelevantMinDim();
+		}
+		space_to_distribute -= panelp->getVisibleDim() + llround((F32)mPanelSpacing * panelp->getVisibleAmount());
+		total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor();
+	}
+
+	llassert(total_visible_fraction < 1.01f);
+
+	// don't need spacing after last panel
+	space_to_distribute += panelp ? llround((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0;
+
+	// scale up space to distribute, since some of might will go to an invisible fraction of the auto-resize space
+	space_to_distribute = (total_visible_fraction > 0.f)
+						? llround((F32)space_to_distribute / total_visible_fraction)
+						: space_to_distribute;
+
+	if (space_to_distribute > 0)
+	{	// give space proportionally to auto resize panels, even invisible ones
+		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+		{
+			if (panelp->mAutoResize == TRUE)
+			{
+				S32 delta = llround((F32)space_to_distribute * panelp->mFractionalSize/* * panelp->getAutoResizeFactor()*/);
+				panelp->mTargetDim += delta;
+			}
+		}
+	}
+
+	F32 cur_pos = (mOrientation == HORIZONTAL) ? 0.f : (F32)getRect().getHeight();
+
+	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+	{
+		F32 panel_dim = panelp->mTargetDim;
+		F32 panel_visible_dim = panelp->getVisibleDim();
+
+		LLRect panel_rect;
+		if (mOrientation == HORIZONTAL)
+		{
+			panel_rect.setLeftTopAndSize(llround(cur_pos),
+										getRect().getHeight(),
+										llround(panel_dim),
+										getRect().getHeight());
+		}
+		else
+		{
+			panel_rect.setLeftTopAndSize(0,
+				llround(cur_pos),
+				getRect().getWidth(),
+				llround(panel_dim));
+		}
+		panelp->setIgnoreReshape(true);
+		panelp->setShape(panel_rect);
+		panelp->setIgnoreReshape(false);
+
+		static LLUICachedControl<S32> resize_bar_overlap ("UIResizeBarOverlap", 0);
+		LLRect resize_bar_rect(panel_rect);
+
+		F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount();
+		if (mOrientation == HORIZONTAL)
+		{
+			resize_bar_rect.mLeft = panel_rect.mRight - resize_bar_overlap;
+			resize_bar_rect.mRight = panel_rect.mRight + panel_spacing + resize_bar_overlap;
+
+			cur_pos += panel_visible_dim + panel_spacing;
+		}
+		else //VERTICAL
+		{
+			resize_bar_rect.mTop = panel_rect.mBottom + resize_bar_overlap;
+			resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing - resize_bar_overlap;
+
+			cur_pos -= panel_visible_dim + panel_spacing;
+		}
+		panelp->mResizeBar->setShape(resize_bar_rect);
+	}
+
+	updateResizeBarLimits();
+
+	// clear animation flag at end, since panel resizes will set it
+	// and leave it set if there is any animation in progress
+	mNeedsLayout = animation_in_progress;
+} // end LLLayoutStack::updateLayout
+
+LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
+{
+	if (!panelp) return NULL;
+
+	e_panel_list_t::const_iterator panel_it;
+	BOOST_FOREACH(LLLayoutPanel* p, mPanels)
+	{
+		if (p == panelp)
+		{
+			return p;
+		}
+	}
+	return NULL;
+}
+
+LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const
 {
-	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+	LLLayoutPanel* result = NULL;
 
-	if (panel && min_dimp)
+	BOOST_FOREACH(LLLayoutPanel* p, mPanels)
 	{
-		*min_dimp = panel->getRelevantMinDim();
+		if (p->getName() == name)
+		{
+			result = p;
+			break;
+		}
 	}
 
-	return NULL != panel;
+	return result;
 }
 
-bool LLLayoutStack::getPanelMaxSize(const std::string& panel_name, S32* max_dimp)
+void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)
 {
-	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+	BOOST_FOREACH(LLLayoutPanel* lp, mPanels)
+	{
+		if (lp->mResizeBar == NULL)
+		{
+			LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
+			LLRect resize_bar_rect = getRect();
 
-	if (panel)
+			LLResizeBar::Params resize_params;
+			resize_params.name("resize");
+			resize_params.resizing_view(lp);
+			resize_params.min_size(lp->getRelevantMinDim());
+			resize_params.side(side);
+			resize_params.snapping_enabled(false);
+			LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);
+			lp->mResizeBar = resize_bar;
+			LLView::addChild(resize_bar, 0);
+		}
+	}
+	// bring all resize bars to the front so that they are clickable even over the panels
+	// with a bit of overlap
+	for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
 	{
-		if (max_dimp) *max_dimp = panel->mMaxDim;
+		LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
+		sendChildToFront(resize_barp);
 	}
+}
 
-	return NULL != panel;
+// update layout stack animations, etc. once per frame
+// NOTE: we use this to size world view based on animating UI, *before* we draw the UI
+// we might still need to call updateLayout during UI draw phase, in case UI elements
+// are resizing themselves dynamically
+//static 
+void LLLayoutStack::updateClass()
+{
+	for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+	{
+		it->updateLayout();
+	}
 }
 
-static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks");
-void LLLayoutStack::updateLayout(BOOL force_resize)
+void LLLayoutStack::updateFractionalSizes()
 {
-	LLFastTimer ft(FTM_UPDATE_LAYOUT);
-	static LLUICachedControl<S32> resize_bar_overlap ("UIResizeBarOverlap", 0);
-	calcMinExtents();
-	createResizeBars();
+	F32 total_resizable_dim = 0;
+	S32 num_auto_resize_panels = 0;
+
+	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+	{
+		if (panelp->mAutoResize)
+		{
+			total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim());
+			num_auto_resize_panels++;
+		}
+	}
 
-	// calculate current extents
-	F32 total_size = 0.f;
+	F32 total_fractional_size = 0.f;
+	
+	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+	{
+		if (panelp->mAutoResize)
+		{
+			F32 panel_resizable_dim = llmax(0.f, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim()));
+			panelp->mFractionalSize = llmin(MAX_FRACTIONAL_VALUE, (panel_resizable_dim == 0.f)
+																	? (1.f - MAX_FRACTIONAL_VALUE)
+																	: panel_resizable_dim / total_resizable_dim);
+			total_fractional_size += panelp->mFractionalSize;
+			// check for NaNs
+			llassert(panelp->mFractionalSize == panelp->mFractionalSize);
+		}
+	}
 
+	if (total_fractional_size == 0.f)
+	{ // equal distribution
+		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+		{
+			if (panelp->mAutoResize)
+			{
+				panelp->mFractionalSize = 1.f / (F32)num_auto_resize_panels;
+			}
+		}
+	}
+	else
+	{ // renormalize
+		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+		{
+			if (panelp->mAutoResize)
+			{
+				panelp->mFractionalSize /= total_fractional_size;
+			}
+		}
+	}
+}
+
+bool LLLayoutStack::animatePanels()
+{
+	bool animation_in_progress = false;
+	
 	//
 	// animate visibility
 	//
-	e_panel_list_t::iterator panel_it;
-	for (panel_it = mPanels.begin(); panel_it != mPanels.end();	++panel_it)
+	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
 	{
-		LLLayoutPanel* panelp = (*panel_it);
-		if (panelp->getVisible()) 
+		if (panelp->getVisible())
 		{
-			if (mAnimate)
+			if (mAnimate && panelp->mVisibleAmt < 1.f)
 			{
 				if (!mAnimatedThisFrame)
 				{
@@ -345,15 +572,21 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 						panelp->mVisibleAmt = 1.f;
 					}
 				}
+				
+				animation_in_progress = true;
 			}
 			else
 			{
-				panelp->mVisibleAmt = 1.f;
+				if (panelp->mVisibleAmt != 1.f)
+				{
+					panelp->mVisibleAmt = 1.f;
+					animation_in_progress = true;
+				}
 			}
 		}
 		else // not visible
 		{
-			if (mAnimate)
+			if (mAnimate && panelp->mVisibleAmt > 0.f)
 			{
 				if (!mAnimatedThisFrame)
 				{
@@ -363,297 +596,206 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 						panelp->mVisibleAmt = 0.f;
 					}
 				}
+
+				animation_in_progress = true;
 			}
 			else
 			{
-				panelp->mVisibleAmt = 0.f;
+				if (panelp->mVisibleAmt != 0.f)
+				{
+					panelp->mVisibleAmt = 0.f;
+					animation_in_progress = true;
+				}
 			}
 		}
 
 		F32 collapse_state = panelp->mCollapsed ? 1.f : 0.f;
-		panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
-
-        total_size += panelp->mFractionalSize * panelp->getCollapseFactor();
-        // want n-1 panel gaps for n panels
-		if (panel_it != mPanels.begin())
-		{
-			total_size += mPanelSpacing;
-		}
-	}
-
-	S32 num_resizable_panels = 0;
-	F32 shrink_headroom_available = 0.f;
-	F32 shrink_headroom_total = 0.f;
-	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
-	{
-		LLLayoutPanel* panelp = (*panel_it);
-
-		// panels that are not fully visible do not count towards shrink headroom
-		if (panelp->getCollapseFactor() < 1.f) 
-		{
-			continue;
-		}
-
-		F32 cur_size = panelp->mFractionalSize;
-		F32 min_size = (F32)panelp->getRelevantMinDim();
-		
-		// if currently resizing a panel or the panel is flagged as not automatically resizing
-		// only track total available headroom, but don't use it for automatic resize logic
-		if (panelp->mResizeBar->hasMouseCapture() 
-			|| (!panelp->mAutoResize 
-				&& !force_resize))
-		{
-			shrink_headroom_total += cur_size - min_size;
-		}
-		else
-		{
-			num_resizable_panels++;
-			
-			shrink_headroom_available += cur_size - min_size;
-			shrink_headroom_total += cur_size - min_size;
-		}
-	}
-
-	// calculate how many pixels need to be distributed among layout panels
-	// positive means panels need to grow, negative means shrink
-	F32 pixels_to_distribute = (mOrientation == HORIZONTAL)
-							? getRect().getWidth() - total_size
-							: getRect().getHeight() - total_size;
-
-	// now we distribute the pixels...
-	F32 cur_x = 0.f;
-	F32 cur_y = (F32)getRect().getHeight();
-
-	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
-	{
-		LLLayoutPanel* panelp = (*panel_it);
-
-		F32 min_size = panelp->getRelevantMinDim();
-		F32 delta_size = 0.f;
-
-		// if panel can automatically resize (not animating, and resize flag set)...
-		if (panelp->getCollapseFactor() == 1.f 
-			&& (force_resize || panelp->mAutoResize) 
-			&& !panelp->mResizeBar->hasMouseCapture()) 
+		if (panelp->mCollapseAmt != collapse_state)
 		{
-			if (pixels_to_distribute < 0.f)
+			if (!mAnimatedThisFrame)
 			{
-				// shrink proportionally to amount over minimum
-				// so we can do this in one pass
-				delta_size = (shrink_headroom_available > 0.f) 
-					? pixels_to_distribute * ((F32)(panelp->mFractionalSize - min_size) / shrink_headroom_available) 
-					: 0.f;
-				shrink_headroom_available -= (panelp->mFractionalSize - min_size);
+				panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
 			}
-			else
+			animation_in_progress = true;
+			
+			if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f)
 			{
-				// grow all elements equally
-				delta_size = pixels_to_distribute / (F32)num_resizable_panels;
-				num_resizable_panels--;
+				panelp->mCollapseAmt = collapse_state;
 			}
-			
-			panelp->mFractionalSize = llmax(min_size, panelp->mFractionalSize + delta_size);
-			pixels_to_distribute -= delta_size;
 		}
+	}
 
-		// adjust running headroom count based on new sizes
-		shrink_headroom_total += delta_size;
+	mAnimatedThisFrame = true;
 
-		LLRect panel_rect;
-		if (mOrientation == HORIZONTAL)
-		{
-			panel_rect.setLeftTopAndSize(llround(cur_x), 
-										llround(cur_y), 
-										llround(panelp->mFractionalSize), 
-										getRect().getHeight());
-		}
-		else
-		{
-			panel_rect.setLeftTopAndSize(llround(cur_x), 
-										llround(cur_y), 
-										getRect().getWidth(), 
-										llround(panelp->mFractionalSize));
-		}
-		panelp->setShape(panel_rect);
+	return animation_in_progress;
+}
 
-		LLRect resize_bar_rect = panel_rect;
-		if (mOrientation == HORIZONTAL)
-		{
-			resize_bar_rect.mLeft = panel_rect.mRight - resize_bar_overlap;
-			resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + resize_bar_overlap;
-		}
-		else
-		{
-			resize_bar_rect.mTop = panel_rect.mBottom + resize_bar_overlap;
-			resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - resize_bar_overlap;
-		}
-		(*panel_it)->mResizeBar->setRect(resize_bar_rect);
+void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& new_rect )
+{
+	S32 new_dim = (mOrientation == HORIZONTAL)
+					? new_rect.getWidth()
+					: new_rect.getHeight();
+	S32 delta_dim = new_dim - resized_panel->getVisibleDim();
+	if (delta_dim == 0) return;
 
-		F32 size = ((*panel_it)->mFractionalSize * (*panel_it)->getCollapseFactor()) + (F32)mPanelSpacing;
-		if (mOrientation == HORIZONTAL)
-		{
-			cur_x += size;
-		}
-		else //VERTICAL
-		{
-			cur_y -= size;
-		}
-	}
+	F32 total_visible_fraction = 0.f;
+	F32 delta_auto_resize_headroom = 0.f;
+	F32 total_auto_resize_headroom = 0.f;
 
-	// update resize bars with new limits
-	LLLayoutPanel* last_resizeable_panel = NULL;
-	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
-	{
-		LLLayoutPanel* panelp = (*panel_it);
-		S32 relevant_min = panelp->getRelevantMinDim();
+	LLLayoutPanel* other_resize_panel = NULL;
+	LLLayoutPanel* following_panel = NULL;
 
-		if (mOrientation == HORIZONTAL)
+	BOOST_REVERSE_FOREACH(LLLayoutPanel* panelp, mPanels)
+	{
+		if (panelp->mAutoResize)
 		{
-			(*panel_it)->mResizeBar->setResizeLimits(
-				relevant_min, 
-				relevant_min + llround(shrink_headroom_total));
+			total_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim());
+			total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor();
 		}
-		else //VERTICAL
+
+		if (panelp == resized_panel)
 		{
-			(*panel_it)->mResizeBar->setResizeLimits(
-				relevant_min, 
-				relevant_min + llround(shrink_headroom_total));
+			other_resize_panel = following_panel;
 		}
 
-		// toggle resize bars based on panel visibility, resizability, etc
-		BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize;
-		(*panel_it)->mResizeBar->setVisible(resize_bar_enabled);
-
-		if ((*panel_it)->mUserResize || (*panel_it)->mAutoResize)
+		if (panelp->getVisible() && !panelp->mCollapsed)
 		{
-			last_resizeable_panel = (*panel_it);
+			following_panel = panelp;
 		}
 	}
 
-	// hide last resize bar as there is nothing past it
-	// resize bars need to be in between two resizable panels
-	if (last_resizeable_panel)
+	if (resized_panel->mAutoResize == FALSE)
 	{
-		last_resizeable_panel->mResizeBar->setVisible(FALSE);
+		delta_auto_resize_headroom += -delta_dim;
 	}
-
-	// not enough room to fit existing contents
-	if (force_resize == FALSE
-		// layout did not complete by reaching target position
-		&& ((mOrientation == VERTICAL && llround(cur_y) != -mPanelSpacing)
-			|| (mOrientation == HORIZONTAL && llround(cur_x) != getRect().getWidth() + mPanelSpacing)))
+	if (other_resize_panel && other_resize_panel->mAutoResize == FALSE)
 	{
-		// do another layout pass with all stacked elements contributing
-		// even those that don't usually resize
-		llassert_always(force_resize == FALSE);
-		updateLayout(TRUE);
+		delta_auto_resize_headroom += delta_dim;
 	}
 
-	 mAnimatedThisFrame = true;
-} // end LLLayoutStack::updateLayout
 
+	//delta_auto_resize_headroom = (total_visible_fraction > 0.f)
+	//								? delta_auto_resize_headroom / total_visible_fraction
+	//								: 0.f;
 
-LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
-{
-	if (!panelp) return NULL;
+	F32 fraction_given_up = 0.f;
+	F32 fraction_remaining = 1.f;
+	F32 updated_auto_resize_headroom = total_auto_resize_headroom + delta_auto_resize_headroom;
 
-	e_panel_list_t::const_iterator panel_it;
-	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+	enum
 	{
-		if ((*panel_it) == panelp)
-		{
-			return *panel_it;
-		}
-	}
-	return NULL;
-}
-
-LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const
-{
-	LLLayoutPanel* result = NULL;
+		BEFORE_RESIZED_PANEL,
+		RESIZED_PANEL,
+		NEXT_PANEL,
+		AFTER_RESIZED_PANEL
+	} which_panel = BEFORE_RESIZED_PANEL;
 
-	for (e_panel_list_t::const_iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
 	{
-		LLLayoutPanel* p = *panel_it;
+		if (!panelp->getVisible() || panelp->mCollapsed) continue;
 
-		if (p->getName() == name)
+		if (panelp == resized_panel)
 		{
-			result = p;
-			break;
+			which_panel = RESIZED_PANEL;
 		}
-	}
-
-	return result;
-}
 
-// Compute sum of min_width or min_height of children
-void LLLayoutStack::calcMinExtents()
-{
-	mMinWidth = 0;
-	mMinHeight = 0;
-
-	e_panel_list_t::iterator panel_it;
-	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
-	{
-		if (mOrientation == HORIZONTAL)
+		switch(which_panel)
 		{
-            mMinWidth += (*panel_it)->getRelevantMinDim();
-			if (panel_it != mPanels.begin())
+		case BEFORE_RESIZED_PANEL:
+			if (panelp->mAutoResize)
+			{	// freeze current size as fraction of overall auto_resize space
+				F32 fractional_adjustment_factor = total_auto_resize_headroom / updated_auto_resize_headroom;
+				F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor,
+													0.f,
+													MAX_FRACTIONAL_VALUE);
+				F32 fraction_delta = (new_fractional_size - panelp->mFractionalSize);
+				fraction_given_up -= fraction_delta;
+				fraction_remaining -= panelp->mFractionalSize;
+				panelp->mFractionalSize += fraction_delta;
+				llassert(!llisnan(panelp->mFractionalSize));
+			}
+			else
 			{
-				mMinWidth += mPanelSpacing;
+				// leave non auto-resize panels alone
 			}
-		}
-		else //VERTICAL
-		{
-			mMinHeight += (*panel_it)->getRelevantMinDim();
-			if (panel_it != mPanels.begin())
+			break;
+		case RESIZED_PANEL:
+			if (panelp->mAutoResize)
+			{	// freeze new size as fraction
+				F32 new_fractional_size = (updated_auto_resize_headroom == 0.f)
+					? 1.f
+					: llmin(MAX_FRACTIONAL_VALUE, ((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom));
+				fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
+				fraction_remaining -= panelp->mFractionalSize;
+				panelp->mFractionalSize = new_fractional_size;
+				llassert(!llisnan(panelp->mFractionalSize));
+			}
+			else
+			{	// freeze new size as original size
+				panelp->mTargetDim = new_dim;
+				fraction_remaining -= fraction_given_up;
+			}
+			which_panel = NEXT_PANEL;
+			break;
+		case NEXT_PANEL:
+			if (panelp->mAutoResize)
+			{
+				F32 new_fractional_size = (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) 
+												/ updated_auto_resize_headroom;
+				fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
+				fraction_remaining -= panelp->mFractionalSize;
+				panelp->mFractionalSize = new_fractional_size;
+			}
+			else
+			{
+				panelp->mTargetDim -= delta_dim;
+			}
+			which_panel = AFTER_RESIZED_PANEL;
+			break;
+		case AFTER_RESIZED_PANEL:
+			if (panelp->mAutoResize)
 			{
-				mMinHeight += mPanelSpacing;
+				panelp->mFractionalSize += (panelp->mFractionalSize / fraction_remaining) * fraction_given_up;
 			}
+		default:
+			break;
 		}
 	}
 }
 
-void LLLayoutStack::createResizeBars()
+void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
 {
-	for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+	mNeedsLayout = true;
+	LLView::reshape(width, height, called_from_parent);
+}
+
+void LLLayoutStack::updateResizeBarLimits()
+{
+	LLLayoutPanel* previous_visible_panelp = NULL;
+	BOOST_REVERSE_FOREACH(LLLayoutPanel* visible_panelp, mPanels)
 	{
-		LLLayoutPanel* lp = (*panel_it);
-		if (lp->mResizeBar == NULL)
+		if (!visible_panelp->getVisible() || visible_panelp->mCollapsed)
 		{
-			LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
-			LLRect resize_bar_rect = getRect();
-
-			LLResizeBar::Params resize_params;
-			resize_params.name("resize");
-			resize_params.resizing_view(lp);
-			resize_params.min_size(lp->getRelevantMinDim());
-			resize_params.side(side);
-			resize_params.snapping_enabled(false);
-			LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);
-			lp->mResizeBar = resize_bar;
-			LLView::addChild(resize_bar, 0);
+			visible_panelp->mResizeBar->setVisible(FALSE);
+			continue;
+		}
 
-			// bring all resize bars to the front so that they are clickable even over the panels
-			// with a bit of overlap
-			for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
-			{
-				LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
-				sendChildToFront(resize_barp);
-			}
+		// toggle resize bars based on panel visibility, resizability, etc
+		if (visible_panelp->mUserResize 
+			&& previous_visible_panelp 
+			&& previous_visible_panelp->mUserResize)
+		{
+			visible_panelp->mResizeBar->setVisible(TRUE);
+			visible_panelp->mResizeBar->setResizeLimits(visible_panelp->getRelevantMinDim(), 
+														visible_panelp->getVisibleDim() 
+															+ (previous_visible_panelp->getVisibleDim() 
+																- previous_visible_panelp->getRelevantMinDim()));
+		}
+		else
+		{
+			visible_panelp->mResizeBar->setVisible(FALSE);
 		}
-	}
-}
 
-// update layout stack animations, etc. once per frame
-// NOTE: we use this to size world view based on animating UI, *before* we draw the UI
-// we might still need to call updateLayout during UI draw phase, in case UI elements
-// are resizing themselves dynamically
-//static 
-void LLLayoutStack::updateClass()
-{
-	for (instance_iter it = beginInstances(); it != endInstances(); ++it)
-	{
-		it->updateLayout();
+		previous_visible_panelp = visible_panelp;
 	}
 }
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 3b308a359d..a343e11cec 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -5,7 +5,7 @@
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2010, Linden Reshasearch, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -72,12 +72,11 @@ public:
 	/*virtual*/ void removeChild(LLView*);
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ bool addChild(LLView* child, S32 tab_group = 0);
+	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
 
 	static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
 
-	S32 getMinWidth() const { return mMinWidth; }
-	S32 getMinHeight() const { return mMinHeight; }
-	
 	typedef enum e_animate
 	{
 		NO_ANIMATE,
@@ -85,47 +84,27 @@ public:
 	} EAnimate;
 
 	void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE);
-	void removePanel(LLPanel* panel);
 	void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
 	S32 getNumPanels() { return mPanels.size(); }
-	/**
-	 * Moves panel_to_move before target_panel inside layout stack (both panels should already be there).
-	 * If move_to_front is true target_panel is ignored and panel_to_move is moved to the beginning of mPanels
-	 */
-	void movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front = false);
 
 	void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize);
 	void setPanelUserResize(const std::string& panel_name, BOOL user_resize);
 	
-	/**
-	 * Gets minimal dimension along layout_stack axis of the specified by name panel.
-	 *
-	 * @returns true if specified by panel_name internal panel exists, false otherwise.
-	 */
-	bool getPanelMinSize(const std::string& panel_name, S32* min_dimp);
-
-	/**
-	 * Gets maximal dimension along layout_stack axis of the specified by name panel.
-	 *
-	 * @returns true if specified by panel_name internal panel exists, false otherwise.
-	 */
-	bool getPanelMaxSize(const std::string& panel_name, S32* max_dim);
-	
-	void updateLayout(BOOL force_resize = FALSE);
-	
+	void updateLayout();
+
 	S32 getPanelSpacing() const { return mPanelSpacing; }
-	BOOL getAnimate () const { return mAnimate; }
-	void setAnimate (BOOL animate) { mAnimate = animate; }
 	
 	static void updateClass();
 
 protected:
 	LLLayoutStack(const Params&);
 	friend class LLUICtrlFactory;
+	friend class LLLayoutPanel;
 
 private:
-	void createResizeBars();
-	void calcMinExtents();
+	void updateResizeBarLimits();
+	bool animatePanels();
+	void createResizeBar(LLLayoutPanel* panel);
 
 	const ELayoutOrientation mOrientation;
 
@@ -134,9 +113,9 @@ private:
 
 	LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;
 	LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const;
+	void updateFractionalSizes();
+	void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect );
 
-	S32 mMinWidth;  // calculated by calcMinExtents
-	S32 mMinHeight;  // calculated by calcMinExtents
 	S32 mPanelSpacing;
 
 	// true if we already applied animation this frame
@@ -145,6 +124,7 @@ private:
 	bool mClip;
 	F32 mOpenTimeConstant;
 	F32 mCloseTimeConstant;
+	bool mNeedsLayout;
 }; // end class LLLayoutStack
 
 
@@ -156,8 +136,7 @@ public:
 	struct Params : public LLInitParam::Block<Params, LLPanel::Params>
 	{
 		Optional<S32>			expanded_min_dim,
-								min_dim,
-								max_dim;
+								min_dim;
 		Optional<bool>			user_resize,
 								auto_resize;
 
@@ -168,14 +147,17 @@ public:
 
 	void initFromParams(const Params& p);
 
+	void handleReshape(const LLRect& new_rect, bool by_user);
+
 	void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+	
+
+	void setVisible(BOOL visible);
 
+	S32 getLayoutDim() const;
 	S32 getMinDim() const { return mMinDim; }
 	void setMinDim(S32 value) { mMinDim = value; if (!mExpandedMinDimSpecified) mExpandedMinDim = value; }
 
-	S32 getMaxDim() const { return mMaxDim; }
-	void setMaxDim(S32 value) { mMaxDim = value; }
-
 	S32 getExpandedMinDim() const { return mExpandedMinDim; }
 	void setExpandedMinDim(S32 value) { mExpandedMinDim = value; mExpandedMinDimSpecified = true; }
 	
@@ -191,8 +173,14 @@ public:
 		return min_dim;
 	}
 
-	F32 getCollapseFactor();
-	void setOrientation(LLLayoutStack::ELayoutOrientation orientation) { mOrientation = orientation; }
+	F32 getAutoResizeFactor() const;
+	F32 getVisibleAmount() const;
+	S32 getVisibleDim() const;
+
+	void setOrientation(LLLayoutStack::ELayoutOrientation orientation);
+	void storeOriginalDim();
+
+	void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; }
 
 protected:
 	LLLayoutPanel(const Params& p);
@@ -201,13 +189,14 @@ protected:
 	S32		mExpandedMinDim;
 	
 	S32		mMinDim;
-	S32		mMaxDim;
 	bool	mAutoResize;
 	bool	mUserResize;
 	bool	mCollapsed;
 	F32		mVisibleAmt;
 	F32		mCollapseAmt;
 	F32		mFractionalSize;
+	S32		mTargetDim;
+	bool	mIgnoreReshape;
 	LLLayoutStack::ELayoutOrientation mOrientation;
 	class LLResizeBar* mResizeBar;
 };
diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp
index 02f60c76fa..87aeb4d7a7 100644
--- a/indra/llui/llresizebar.cpp
+++ b/indra/llui/llresizebar.cpp
@@ -79,6 +79,8 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
 
 BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask)
 {
+	if (!canResize()) return FALSE;
+
 	// Route future Mouse messages here preemptively.  (Release on mouse up.)
 	// No handler needed for focus lost since this clas has no state that depends on it.
 	gFocusMgr.setMouseCapture( this );
@@ -243,7 +245,7 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
 		handled = TRUE;
 	}
 
-	if( handled )
+	if( handled && canResize() )
 	{
 		switch( mSide )
 		{
diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h
index 0725fbd846..6daf191918 100644
--- a/indra/llui/llresizebar.h
+++ b/indra/llui/llresizebar.h
@@ -70,6 +70,7 @@ public:
 	void			setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; }
 	void			setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; }
 	void			setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; }
+	bool			canResize() { return getEnabled() && mMaxSize > mMinSize; }
 
 private:
 	S32				mDragLastScreenX;
diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp
index ae8b30b1ba..a8bb29374e 100644
--- a/indra/llui/llwindowshade.cpp
+++ b/indra/llui/llwindowshade.cpp
@@ -176,12 +176,12 @@ void LLWindowShade::draw()
 	{
 		hide();
 	}
-	else if (notification_area->getCollapseFactor() < 0.01f)
+	else if (notification_area->getVisibleAmount() < 0.01f)
 	{
 		displayLatestNotification();
 	}
 
-	if (!notification_area->getVisible() && (notification_area->getCollapseFactor() < 0.001f))
+	if (!notification_area->getVisible() && (notification_area->getVisibleAmount() < 0.001f))
 	{
 		getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(false);
 		setMouseOpaque(false);
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 42de47e777..f530d10ddc 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -621,7 +621,6 @@ void LLChatHistory::initFromParams(const LLChatHistory::Params& p)
 	panel_p.has_border = false;
 	panel_p.mouse_opaque = false;
 	panel_p.min_dim = 30;
-	panel_p.max_dim = S32_MAX;
 	panel_p.auto_resize = true;
 	panel_p.user_resize = false;
 
diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp
index a879651060..a32fd307f1 100644
--- a/indra/newview/llchicletbar.cpp
+++ b/indra/newview/llchicletbar.cpp
@@ -42,28 +42,6 @@ namespace
 {
 	const std::string& PANEL_CHICLET_NAME	= "chiclet_list_panel";
 
-	S32 get_panel_min_width(LLLayoutStack* stack, LLView* panel)
-	{
-		S32 minimal_width = 0;
-		llassert(stack);
-		if ( stack && panel && panel->getVisible() )
-		{
-			stack->getPanelMinSize(panel->getName(), &minimal_width);
-		}
-		return minimal_width;
-	}
-
-	S32 get_panel_max_width(LLLayoutStack* stack, LLPanel* panel)
-	{
-		S32 max_width = 0;
-		llassert(stack);
-		if ( stack && panel && panel->getVisible() )
-		{
-			stack->getPanelMaxSize(panel->getName(), &max_width);
-		}
-		return max_width;
-	}
-
 	S32 get_curr_width(LLUICtrl* ctrl)
 	{
 		S32 cur_width = 0;
@@ -234,15 +212,10 @@ void LLChicletBar::reshape(S32 width, S32 height, BOOL called_from_parent)
 	{
 		// Firstly, update layout stack to ensure we deal with correct panel sizes.
 		{
-			BOOL saved_anim = mToolbarStack->getAnimate();
 			// Set chiclet panel to be autoresized by default.
 			mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE);
-			// Disable animation to prevent layout updating in several frames.
-			mToolbarStack->setAnimate(FALSE);
 			// Force the updating of layout to reset panels collapse factor.
 			mToolbarStack->updateLayout();
-			// Restore animate state.
-			mToolbarStack->setAnimate(saved_anim);
 		}
 
 		// chiclet bar is narrowed
diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp
index 29af81d64c..2681d4b34d 100644
--- a/indra/newview/llfloaternotificationsconsole.cpp
+++ b/indra/newview/llfloaternotificationsconsole.cpp
@@ -220,7 +220,7 @@ void LLFloaterNotificationConsole::addChannel(const std::string& name, bool open
 void LLFloaterNotificationConsole::removeChannel(const std::string& name)
 {
 	LLPanel* panelp = getChild<LLPanel>(name);
-	getChildRef<LLLayoutStack>("notification_channels").removePanel(panelp);
+	getChildRef<LLView>("notification_channels").removeChild(panelp);
 	delete panelp;
 
 	updateResizeLimits();
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index f5cda52d44..228260c41a 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -385,9 +385,6 @@ void LLIMFloater::onSlide()
 
 	getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getParent()->getVisible());
 	getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getParent()->getVisible());
-
-	LLLayoutStack* stack = getChild<LLLayoutStack>("im_panels");
-	if (stack) stack->setAnimate(true);
 }
 
 //static
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 9d069c3996..e40cc4662b 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -248,7 +248,6 @@ BOOL LLSidepanelInventory::postBuild()
 
 		// Disable user_resize on main inventory panel by default
 		inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false);
-		inv_stack->setPanelUserResize(INBOX_OUTBOX_LAYOUT_PANEL_NAME, false);
 
 		// Collapse marketplace panel by default
 		inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME), true);
diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml
index d101bca694..cd075abc41 100644
--- a/indra/newview/skins/default/xui/en/floater_help_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml
@@ -34,7 +34,6 @@
          left_delta="0"
          top_delta="0"
          name="external_controls"
-         user_resize="false"
          width="620">
             <web_browser
              trusted_content="true" 
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index a2739a8339..ca73883e53 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -16,7 +16,7 @@
  min_width="250"
  min_height="190">
   <layout_stack
-   animate="false" 
+   animate="true" 
    default_tab_group="2"
   follows="all"
   height="320"
@@ -32,8 +32,7 @@
       min_width="115"
       width="150" 
       height="320" 
-      auto_resize="false"
-      user_resize="false">
+      auto_resize="false">
       <panel
         name="panel_im_control_panel"
         layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml
index c3324a6aa4..ce788654aa 100644
--- a/indra/newview/skins/default/xui/en/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml
@@ -37,7 +37,6 @@
          min_height="20"
          name="nav_controls"
          top="400"
-         user_resize="false"
          width="800">
             <button
              follows="left|top"
@@ -113,7 +112,6 @@
          min_height="20"         
          name="time_controls"
          top_delta="0"
-         user_resize="false"
          width="800">
             <button
              follows="left|top"
@@ -171,7 +169,6 @@
          min_height="20"         
          name="parcel_owner_controls"
          top_delta="0"
-         user_resize="false"
          width="540">
             <button
              enabled="false"
@@ -193,7 +190,6 @@
          left_delta="0"
          name="external_controls"
          top_delta="0"
-         user_resize="false"
          width="540">
           <web_browser
              bottom="-30"
diff --git a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
new file mode 100644
index 0000000000..dbe75f8b53
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_resize="true"
+ can_close="true"
+ bevel_style="in"
+ height="300"
+ layout="topleft"
+ min_height="40"
+ min_width="420"
+ name="Test Floater"
+ title="LAYOUTSTACK TESTS"
+ width="420">
+  <layout_stack name="test_stack"
+              left="0"
+              top="0"
+              width="100"
+              height="250"
+              follows="left|top|bottom"
+              orientation="vertical">
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="11"
+                  min_height="0"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+    <layout_panel name="fixed"
+                auto_resize="false"
+                  user_resize="true"
+                height="50"
+                  min_height="0"
+                bg_alpha_color="green"
+                background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+    </layout_panel>
+    <layout_panel name="fixed"
+                auto_resize="false"
+                  user_resize="true"
+                height="50"
+                  min_height="0"
+                bg_alpha_color="green"
+                background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+    </layout_panel>
+    <layout_panel name="fixed"
+                auto_resize="false"
+                  user_resize="true"
+                height="50"
+                bg_alpha_color="green"
+                background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+    </layout_panel>
+  </layout_stack>
+  <layout_stack name="test_stack"
+              left_pad="5"
+              top="0"
+              width="100"
+              height="250"
+              follows="left|top|bottom"
+              orientation="vertical">
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="100"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  visible="false"
+                  bg_alpha_color="blue"
+                  height="100"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+    <layout_panel name="fixed"
+                  auto_resize="false"
+                  user_resize="true"
+                  height="50"
+                  min_height="10"
+                  bg_alpha_color="green"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+    </layout_panel>
+    <layout_panel name="fixed"
+                auto_resize="false"
+                  user_resize="true"
+                height="50"
+                min_height="10"
+                bg_alpha_color="green"
+                background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+    </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="100"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="100"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="100"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="100"
+                  visible="true"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+  </layout_stack>
+  <layout_stack name="test_stack"
+               left_pad="5"
+               top="0"
+               width="100"
+               height="250"
+               follows="left|top|bottom"
+               orientation="vertical">
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  height="11"
+                  bg_alpha_color="blue"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+    <layout_panel name="fixed"
+                auto_resize="false"
+                  user_resize="true"
+                height="50"
+                bg_alpha_color="green"
+                background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+    </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="11"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+  </layout_stack>
+  <layout_stack name="test_stack"
+               left_pad="5"
+               top="0"
+               width="100"
+               height="250"
+               follows="left|top|bottom"
+               orientation="vertical">
+    <layout_panel name="fixed"
+                auto_resize="false"
+                  user_resize="true"
+                height="50"
+                bg_alpha_color="green"
+                background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+    </layout_panel>
+    <layout_panel name="fixed"
+                auto_resize="false"
+                  user_resize="true"
+                height="50"
+                bg_alpha_color="green"
+                background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+    </layout_panel>
+    <layout_panel name="fixed"
+                auto_resize="false"
+                  user_resize="true"
+                height="50"
+                bg_alpha_color="green"
+                background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+    </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="11"
+                  min_height="0"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="11"
+                  min_height="0"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="11"
+                  min_height="0"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
+  </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_ui_preview.xml b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
index 3921cfcd2c..06d4327293 100644
--- a/indra/newview/skins/default/xui/en/floater_ui_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
@@ -22,6 +22,7 @@ or specifying its path in the "Editor Path" field.</string>
      layout="topleft"
      left="0"
      mouse_opaque="false"
+     default_tab_group="1"
      name="main_panel"
      right="750"
      top="0">
@@ -196,6 +197,7 @@ or specifying its path in the "Editor Path" field.</string>
          left="10"
          name="name_list"
          right="-10"
+         tab_group="1"
          search_column="1"
          top="80">
             <scroll_list.columns
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index 6807b01fa3..cea19ec75c 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -49,7 +49,6 @@
          width="263">
         <layout_panel
          follows="top|left|right"
-         user_resize="false"
          auto_resize="false"
          layout="topleft"
          min_height="20"
@@ -89,7 +88,7 @@
              visible="true"
              width="20" />
         </layout_panel>
-        <layout_panel name="leave_call_panel" height="26" min_height="26" user_resize="false" auto_resize="false">
+        <layout_panel name="leave_call_panel" height="26" min_height="26" auto_resize="false">
         <layout_stack
          clip="true"
          follows="left|top|right"
@@ -110,7 +109,6 @@
           </layout_panel>
           <layout_panel
            auto_resize="false"
-           user_resize="false"
            follows="top|right"
            height="23"
            visible="true"
@@ -133,7 +131,6 @@
           top_pad="0"
           height="132"
           name="callers_panel"
-          user_resize="false" 
           auto_resize="true"
           width="280">
         <avatar_list
diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml
index 57d1c92acb..cea10adca8 100644
--- a/indra/newview/skins/default/xui/en/floater_web_content.xml
+++ b/indra/newview/skins/default/xui/en/floater_web_content.xml
@@ -31,7 +31,6 @@
       min_height="20"
       name="nav_controls"
       top="400"
-      user_resize="false"
       width="770">
       <button
         image_overlay="Arrow_Left_Off"
@@ -160,7 +159,6 @@
       left_delta="0"
       name="external_controls"
       top_delta="0"
-      user_resize="false"
       auto_resize="true"
       width="585">
       <web_browser
@@ -173,8 +171,7 @@
     </layout_panel>
     <layout_panel name="status_bar" 
                   height="23"
-                  auto_resize="false"
-                  user_resize="false">
+                  auto_resize="false">
       <text
         type="string"
         length="200"
diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml
index b4be17e677..a87027a113 100644
--- a/indra/newview/skins/default/xui/en/main_view.xml
+++ b/indra/newview/skins/default/xui/en/main_view.xml
@@ -23,7 +23,6 @@
               left="0"
               top="0"
               width="1024"
-              user_resize="false"
               auto_resize="false"
               visible="true">
       <view mouse_opaque="false"
@@ -40,7 +39,6 @@
                   name="nav_bar_container"
                   tab_stop="false"
                   width="1024"
-                  user_resize="false"
                   visible="false"/>
     <layout_panel auto_resize="true"  
                   follows="all"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
index 0f42000ae7..e91f5af3d5 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -3,6 +3,7 @@
  layout="topleft"
  left="0"
  mouse_opaque="false"
+ can_tear_off="true"
  name="menu_inventory_add"
  visible="false">
             <menu
diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
index 93cafd4a53..d68fa6ca6c 100644
--- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
@@ -27,8 +27,7 @@
          mouse_opaque="false"
          width="147"
          top="0"
-         name="speakers_list_panel"
-         user_resize="false">
+         name="speakers_list_panel">
             <avatar_list
              color="DkGray2"
              follows="all"
@@ -50,7 +49,6 @@
          min_height="25"
          width="130"
          name="call_btn_panel"
-         user_resize="false"
          visible="false">
             <button
              follows="all"
@@ -68,7 +66,6 @@
          min_height="25"
          width="130"
          name="end_call_btn_panel"
-         user_resize="false"
          visible="false">
             <button
              follows="all"
@@ -85,7 +82,6 @@
          min_height="25"
          width="130"
          name="voice_ctrls_btn_panel"
-         user_resize="false"
          visible="false">
             <button
              follows="all"
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml b/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml
index b5e1a5f16d..f4722b05d6 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml
@@ -31,7 +31,6 @@
      width="1000">
         <layout_panel
          auto_resize="false"
-         user_resize="false" 
          min_width="2"
          width="2" />
         <layout_panel
@@ -40,8 +39,7 @@
          height="28"
          layout="topleft"
          width="310"
-         min_width="188"
-         user_resize="false">
+         min_width="188">
           <panel
             left="0"
             filename="panel_nearby_chat_bar.xml"
@@ -61,8 +59,7 @@
          width="82"
          top_delta="0"
          min_width="52"
-         name="gesture_panel"
-         user_resize="false">
+         name="gesture_panel">
             <gesture_combo_list
              follows="left|right"
              height="23"
@@ -80,7 +77,6 @@
         </layout_panel>
         <layout_panel
          auto_resize="false"
-         user_resize="false" 
          min_width="3"
          name="after_gesture_panel"
          width="3"/>
diff --git a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml
index 41d1036a4d..6d4008a4ed 100644
--- a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml
@@ -28,7 +28,6 @@
          mouse_opaque="false"
          name="chiclet_list_panel"
          top="0"
-         user_resize="false"
          width="189">
       <chiclet_panel
              chiclet_padding="4"
@@ -78,7 +77,6 @@
       </chiclet_panel>
     </layout_panel>
     <layout_panel auto_resize="false"
-                      user_resize="false"
                       width="4"
                       min_width="4"/>
     <layout_panel
@@ -90,7 +88,6 @@
          min_width="37"
          name="im_well_panel"
          top="0"
-         user_resize="false"
          width="37">
       <chiclet_im_well
              follows="right"
@@ -139,7 +136,6 @@ image_pressed_selected  "Lit" + "Selected" - there are new messages and the Well
          min_width="37"
          name="notification_well_panel"
          top="0"
-         user_resize="false"
          width="37">
       <chiclet_notification
              follows="right"
diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml
index 6c8d994bc6..d4a2745d1d 100644
--- a/indra/newview/skins/default/xui/en/panel_classified_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml
@@ -289,8 +289,7 @@
           left="0"
           top="0"
           width="290"
-          height="16"
-          user_resize="false">
+          height="16">
         <text
          follows="left|top"
          font.style="BOLD"
@@ -327,8 +326,7 @@
           left="0"
           top="0"
           width="290"
-          height="16"
-          user_resize="false">
+          height="16">
         <text
          follows="left|top"
          font.style="BOLD"
@@ -357,8 +355,7 @@
           left="0"
           top="0"
           width="290"
-          height="215"
-          user_resize="false">
+          height="215">
         <text
          auto_resize="false"
          follows="left|top"
@@ -416,7 +413,6 @@
 			  layout="bottomleft"
 			  left="0"
 			  name="layout_panel1"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="101">
 			  <button
@@ -436,7 +432,6 @@
 			  layout="bottomleft"
 			  left_pad="3"
 			  name="show_on_map_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="100">
 			  <button
@@ -455,7 +450,6 @@
 			  layout="bottomleft"
 			  left_pad="3"
 			  name="edit_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="101">
 			  <button
diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
index e512d63f9e..3509eaa285 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
@@ -319,7 +319,6 @@
 			  layout="bottomleft"
 			  left="0"
 			  name="save_changes_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="156">
 			  <button
@@ -339,7 +338,6 @@
 			  layout="bottomleft"
 			  left_pad="3"
 			  name="show_on_map_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="157">
 			  <button
diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
index 2ec2e03e8c..0faa1598b1 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
@@ -201,7 +201,6 @@
 			  layout="topleft"
 			  left="0"
 			  name="layout_panel1"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="150">
 		        <button
@@ -221,7 +220,6 @@
 			  layout="topleft"
 			  left_pad="4"
 			  name="layout_panel2"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="146">
 		        <button
diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
index 442eb8c28d..2c7c8133d1 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
@@ -435,7 +435,6 @@
 			  layout="bottomleft"
 			  name="save_changes_btn_lp"
 			  top="0"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="153">
         <button
@@ -456,7 +455,6 @@
 			  left_pad="3"
 			  name="show_on_map_btn_lp"
 			  top="0"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="154">
         <button
diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
index c8764a6a84..69a692e2c4 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -454,7 +454,6 @@
              left="0"			
              mouse_opaque="false"
              name="save_as_btn_lp"
-             user_resize="false" 
              auto_resize="true"
              width="154">
                 <button
@@ -474,7 +473,6 @@
              left_pad="3"			
              mouse_opaque="false"
              name="revert_btn_lp"
-             user_resize="false" 
              auto_resize="true"
              width="152">
                 <button
diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
index c1dc2aaaf7..ad10e53a4e 100644
--- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
@@ -26,8 +26,7 @@
          mouse_opaque="false"
          width="145"
          top="0"
-         name="speakers_list_panel"
-         user_resize="false">
+         name="speakers_list_panel">
             <avatar_list
              color="DkGray2"
              follows="all"
@@ -48,8 +47,7 @@
          layout="topleft"
          min_height="28"
          width="130"
-         name="group_info_btn_panel"
-         user_resize="false">
+         name="group_info_btn_panel">
             <button
              follows="left|right|bottom"
              height="23"
@@ -66,8 +64,7 @@
          layout="topleft"
          min_height="28"
          width="130"
-         name="call_btn_panel"
-         user_resize="false">
+         name="call_btn_panel">
             <button
              follows="all"
              height="23"
@@ -84,7 +81,6 @@
          min_height="28"
          width="130"
          name="end_call_btn_panel"
-         user_resize="false"
          visible="false">
             <button
              follows="all"
@@ -101,7 +97,6 @@
          min_height="28"
          width="130"
          name="voice_ctrls_btn_panel"
-         user_resize="false"
          visible="false">
             <button
              follows="all"
diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
index ec3f3b48bc..206496cc0e 100644
--- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
@@ -97,6 +97,7 @@ background_visible="true"
        follows="all"
        layout="topleft"
        auto_resize="true"
+       user_resize="true"
        height="513"
        width="313">
    <accordion
@@ -195,7 +196,6 @@ background_visible="true"
 				layout="bottomleft"
 				left="0"
 				name="btn_refresh_lp"
-			    user_resize="false" 
 			    auto_resize="false"
 				width="24">
 					<button
@@ -215,7 +215,6 @@ background_visible="true"
 				layout="bottomleft"
 				left_pad="3"
 				name="btn_chat_lp"
-			    user_resize="false" 
 			    auto_resize="true"
 				width="91">
 					<button
@@ -234,7 +233,6 @@ background_visible="true"
 				layout="bottomleft"
 				left_pad="3"
 				name="call_btn_lp"
-			    user_resize="false" 
 			    auto_resize="true"
 				width="91">
 					<button
@@ -255,7 +253,6 @@ background_visible="true"
 				layout="bottomleft"
 				left_pad="3"
 				name="btn_apply_lp"
-			    user_resize="false" 
 			    auto_resize="true"
 				width="91">
 					<button
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
index 9f73b7c540..8fcd6ccbaf 100644
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -32,8 +32,7 @@
          min_height="20"
          width="140"
          name="view_profile_btn_panel"
-         top="0" 
-         user_resize="false">
+         top="0" >
             <button
              follows="left|top|right"
              height="23"
@@ -49,8 +48,7 @@
          layout="topleft"
          min_height="25"
          width="140"
-         name="add_friend_btn_panel"
-         user_resize="false">
+         name="add_friend_btn_panel">
             <button
              follows="left|top|right"
              height="23"
@@ -66,8 +64,7 @@
          layout="topleft"
          min_height="25"
          width="140"
-         name="teleport_btn_panel"
-         user_resize="false">
+         name="teleport_btn_panel">
         <button
              auto_resize="false"
              follows="left|top|right"
@@ -84,8 +81,7 @@
          layout="topleft"
          min_height="25"
          width="140"
-         name="share_btn_panel"
-         user_resize="false">
+         name="share_btn_panel">
            <button
              auto_resize="true"
              follows="left|top|right"
@@ -101,8 +97,7 @@
          layout="topleft"
          min_height="25"
          width="140"
-         name="pay_btn_panel"
-         user_resize="false">
+         name="pay_btn_panel">
            <button
              auto_resize="true"
              follows="left|top|right"
@@ -118,8 +113,7 @@
          layout="topleft"
          min_height="25"
          width="140"
-         name="call_btn_panel"
-         user_resize="false">
+         name="call_btn_panel">
             <button
              follows="left|top|right"
              height="23"
@@ -135,7 +129,6 @@
          min_height="25"
          width="140"
          name="end_call_btn_panel"
-         user_resize="false"
          visible="false">
             <button
              follows="left|top|right"
@@ -152,7 +145,6 @@
          min_height="25"
          width="140"
          name="voice_ctrls_btn_panel"
-         user_resize="false"
          visible="false">
             <button
              follows="left|top|right"
@@ -169,7 +161,6 @@
        layout="topleft"
        min_height="0"
        width="140"
-       name="spacer"
-       user_resize="false" />
+       name="spacer"/>
     </layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index 23d8cb11ca..2a5933e3e9 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -114,7 +114,6 @@
 		       height="25"
 		       layout="topleft"
 		       name="options_gear_btn_panel"
-		       user_resize="false"
 		       width="32">
 		          <menu_button
 		           follows="bottom|left"
@@ -135,7 +134,6 @@
 		       height="25"
 		       layout="topleft"
 		       name="add_btn_panel"
-		       user_resize="false"
 		       width="32">
 		          <button
 		           follows="bottom|left"
@@ -156,7 +154,6 @@
 		       height="25"
 		       layout="topleft"
 		       name="dummy_panel"
-		       user_resize="false"
 		       width="212">
 		          <icon
 		           follows="bottom|left|right"
@@ -173,7 +170,6 @@
 		       height="25"
 		       layout="topleft"
 		       name="trash_btn_panel"
-		       user_resize="false"
 		       width="31">
 		          <dnd_button
 		           follows="bottom|left"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 6521bf2a4e..223326dd06 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -48,7 +48,6 @@ name="login"
 layout="topleft"
 width="705"
 min_width="705"
-user_resize="false"
 height="80">
 <text
 follows="left|bottom"
@@ -165,7 +164,6 @@ follows="right|bottom"
 name="links"
 width="205"
 min_width="205"
-user_resize="false"
 height="80">
    <text
 follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index e6c5110999..9f84cdc43e 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -119,7 +119,6 @@
        height="25"
        layout="topleft"
        name="options_gear_btn_panel"
-       user_resize="false"
        width="32">
           <menu_button
            follows="bottom|left"
@@ -140,7 +139,6 @@
        height="25"
        layout="topleft"
        name="add_btn_panel"
-       user_resize="false"
        width="32">
           <button
            follows="bottom|left"
@@ -161,7 +159,6 @@
        height="25"
        layout="topleft"
        name="dummy_panel"
-       user_resize="false"
        width="212">
           <icon
            follows="bottom|left|right"
@@ -178,7 +175,6 @@
        height="25"
        layout="topleft"
        name="trash_btn_panel"
-       user_resize="false"
        width="31">
           <dnd_button
            follows="bottom|left"
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index 7a8e872dc9..9dee68efa7 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -141,7 +141,6 @@
            max_width="5"
            min_width="5"
            name="nav_bar_resize_handle_panel"
-           user_resize="false"
            width="5">
              <icon
                follows="top|right"
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_media.xml b/indra/newview/skins/default/xui/en/panel_nearby_media.xml
index bfc503f05b..d1cb64f7ad 100644
--- a/indra/newview/skins/default/xui/en/panel_nearby_media.xml
+++ b/indra/newview/skins/default/xui/en/panel_nearby_media.xml
@@ -196,7 +196,6 @@
 			name="stop"
 			mouse_opaque="false"
 			auto_resize="false"
-			user_resize="false"
 			layout="topleft"
 			top="0"
 			height="22"
@@ -224,7 +223,6 @@
 			name="play"
 			mouse_opaque="false"
 			auto_resize="false"
-			user_resize="false"
 			layout="topleft"
 			top="0"
 			height="22"
@@ -252,7 +250,6 @@
 			name="pause"
 			mouse_opaque="false"
 			auto_resize="false"
-			user_resize="false"
 			layout="topleft"
 			top="0"
 			min_width="22"
@@ -279,7 +276,6 @@
 			name="volume_slider_ctrl"
 			mouse_opaque="false"
 			auto_resize="true"
-			user_resize="false"
 			follows="left|right"
 			layout="topleft"
 			top="0"
@@ -304,7 +300,6 @@
 			name="mute"
 			mouse_opaque="false"
 			auto_resize="false"
-			user_resize="false"
 			layout="topleft"
 			top="0"
 			height="72"
@@ -333,7 +328,6 @@
 			name="zoom"
 			mouse_opaque="false"
 			auto_resize="false"
-			user_resize="false"
 			layout="topleft"
 			top="0"
 			height="28"
@@ -361,7 +355,6 @@
 			name="unzoom"
 			mouse_opaque="false"
 			auto_resize="false"
-			user_resize="false"
 			layout="topleft"
 			top="0"
 			min_width="21"
@@ -388,8 +381,7 @@
 		<layout_panel
 			name="right_bookend"
 			width="0"
-			mouse_opaque="false"
-			user_resize="false" />
+			mouse_opaque="false"/>
 	  </layout_stack>
 	</panel>
   </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index e1cd78bad8..b61f110e32 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -198,7 +198,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap
                  height="154"
                  name="add_button_and_combobox"
                  width="311"
-                 user_resize="false"
                  visible="true">
 
             <!-- List containing items from the COF and Base outfit -->
@@ -271,8 +270,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap
                  height="30"
                  name="filter_panel"
                  width="311"
-                 visible="false"
-                 user_resize="false">
+                 visible="false">
 
                     <filter_editor
 		             background_image="TextField_Search_Off"
@@ -515,7 +513,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap
                      left="0"			
                      mouse_opaque="false"
                      name="save_btn_lp"
-                     user_resize="false" 
                      auto_resize="true"
                      width="156">
         <button
@@ -550,7 +547,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap
                      left_pad="3"			
                      mouse_opaque="false"
                      name="revert_btn_lp"
-                     user_resize="false" 
                      auto_resize="true"
                      width="147">
         <button
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
index 2ad2416179..405d9513db 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -84,7 +84,6 @@
                      left="0"			
                      mouse_opaque="false"
                      name="save_btn_lp"
-                     user_resize="false" 
                      auto_resize="true"
                      width="156">
                     <button
@@ -118,7 +117,6 @@
                      left_pad="3"			
                      mouse_opaque="false"
                      name="wear_btn_lp"
-                     user_resize="false" 
                      auto_resize="true"
                      width="147">
                     <button
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 0ebfd9c037..98c7c49ff4 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -284,7 +284,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 				       height="25"
 				       layout="topleft"
 				       name="options_gear_btn_panel"
-				       user_resize="false"
 				       width="32">
 				          <menu_button
 				           follows="bottom|left"
@@ -305,7 +304,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 				       height="25"
 				       layout="topleft"
 				       name="add_btn_panel"
-				       user_resize="false"
 				       width="32">
 				          <button
 				           follows="bottom|left"
@@ -326,7 +324,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 				       height="25"
 				       layout="topleft"
 				       name="dummy_panel"
-				       user_resize="false"
 				       width="210">
 				          <icon
 				           follows="bottom|left|right"
@@ -343,7 +340,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 				       height="25"
 				       layout="topleft"
 				       name="trash_btn_panel"
-				       user_resize="false"
 				       width="31">
 				          <dnd_button
 				           follows="bottom|left"
@@ -602,7 +598,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 			layout="bottomleft"
 			left="0"
 			name="view_profile_btn_lp"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="68">
 				<button
@@ -623,7 +618,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 			layout="bottomleft"
 			left_pad="3"
 			name="im_btn_lp"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="41">
 				<button
@@ -644,7 +638,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 			layout="bottomleft"
 			left_pad="3"
 			name="call_btn_lp"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="52">
 				<button
@@ -665,7 +658,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 			layout="bottomleft"
 			left_pad="3"
 			name="share_btn_lp"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="66">
 				<button
@@ -686,7 +678,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 			layout="bottomleft"
 			left_pad="3"
 			name="teleport_btn_lp"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="77">
 				<button
@@ -720,7 +711,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 			left="0"			
 			mouse_opaque="false"
 			name="group_info_btn_lp"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="108">
 				<button
@@ -743,7 +733,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 			left_pad="3"
 			mouse_opaque="false"
 			name="chat_btn_lp"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="101">
 				<button
@@ -766,7 +755,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 			left_pad="3"
 			mouse_opaque="false"
 			name="group_call_btn_lp"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="96">
 				<button
diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml
index 24046d5cca..79d190e1e0 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml
@@ -139,7 +139,6 @@
 			  layout="bottomleft"
 			  left="0"
 			  name="layout_panel1"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="101">
 			  <button
@@ -158,7 +157,6 @@
 			  layout="bottomleft"
 			  left_pad="3"
 			  name="show_on_map_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="100">
 			  <button
@@ -177,7 +175,6 @@
 			  layout="bottomleft"
 			  left_pad="3"
 			  name="edit_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="101">
 			  <button
diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml
index 85f402dfa2..8def96cada 100644
--- a/indra/newview/skins/default/xui/en/panel_picks.xml
+++ b/indra/newview/skins/default/xui/en/panel_picks.xml
@@ -102,7 +102,6 @@ bg_opaque_color="DkGray2"
 			  layout="bottomleft"
 			  left="0"
 			  name="gear_menu_btn"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="51">
 				<button
@@ -124,7 +123,6 @@ bg_opaque_color="DkGray2"
 			  height="18"
 			  layout="bottomleft"
 			  name="trash_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="18">
 				<button
@@ -170,7 +168,6 @@ bg_opaque_color="DkGray2"
 			  layout="topleft"
 			  left="0"
 			  name="info_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true"
 			  top="0"
 			  width="95">
@@ -192,7 +189,6 @@ bg_opaque_color="DkGray2"
 			  layout="bottomleft" 
 			  left_pad="2"
 			  name="teleport_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true"
 			  width="117">
 		        <button
@@ -212,7 +208,6 @@ bg_opaque_color="DkGray2"
 			  height="28"
 			  layout="bottomleft"
 			  name="show_on_map_btn_lp"
-		      user_resize="false" 
 		      auto_resize="true" 
 			  left_pad="2"
 			  width="90">
diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml
index e280115bda..308acf0c0c 100644
--- a/indra/newview/skins/default/xui/en/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -238,7 +238,6 @@
                  mouse_opaque="false"
                  name="here_panel"
                  top="0"
-                 user_resize="false"
                  width="60">
                     <icon
                      follows="top|left"
@@ -259,7 +258,6 @@
                  mouse_opaque="false"
                  name="for_sale_panel"
                  top="0"
-                 user_resize="false"
                  width="60">
                     <icon
                      follows="top|left"
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index 670aa47313..f169dbb702 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -92,7 +92,6 @@ background_visible="true"
 			left="0"			
 			mouse_opaque="false"
 			name="lp1"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="193">
 			
@@ -115,7 +114,6 @@ background_visible="true"
 					left="0"			
 					mouse_opaque="false"
 					name="teleport_btn_lp"
-				    user_resize="false" 
 				    auto_resize="true"
 					width="109">
 						<button
@@ -137,7 +135,6 @@ background_visible="true"
 					left_pad="3"
 					mouse_opaque="false"
 					name="chat_btn_lp"
-				    user_resize="false" 
 				    auto_resize="true"
 					width="86">
 						<button
@@ -161,7 +158,6 @@ background_visible="true"
 			left_pad="0"			
 			mouse_opaque="false"
 			name="lp2"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="116">
 			
@@ -185,7 +181,6 @@ background_visible="true"
 					left_pad="0"
 					mouse_opaque="false"
 					name="edit_btn_lp"
-				    user_resize="false" 
 				    auto_resize="true"
 					width="84">
 						<button
@@ -208,7 +203,6 @@ background_visible="true"
 					left_pad="0"
 					mouse_opaque="false"
 					name="overflow_btn_lp"
-				    user_resize="false" 
 				    auto_resize="true"
 					width="24">
 						<menu_button
@@ -246,7 +240,6 @@ background_visible="true"
 					left_pad="3"			
 					mouse_opaque="false"
 					name="profile_btn_lp"
-				    user_resize="false" 
 				    auto_resize="true"
 					width="102">
 						<button
@@ -283,7 +276,6 @@ background_visible="true"
 					mouse_opaque="false"
 					name="close_btn_lp"
 					top="0"
-				    user_resize="false" 
 				    auto_resize="true"
 					width="51">
 						<button
@@ -324,7 +316,6 @@ background_visible="true"
 			mouse_opaque="false"
 			name="save_btn_lp"
 			top="0"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="153">
 				<button
@@ -347,7 +338,6 @@ background_visible="true"
 			mouse_opaque="false"
 			name="cancel_btn_lp"
 			top="0"
-		    user_resize="false" 
 		    auto_resize="true"
 			width="154">
 				<button
diff --git a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml
index 2e0bb88f53..e9427a2388 100644
--- a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml
+++ b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml
@@ -50,7 +50,6 @@
          layout="topleft"
          left="0"
          name="postcard_image_size_lp"
-         user_resize="false" 
          auto_resize="false"
          top="0"
          right="-1"
@@ -99,7 +98,6 @@
          layout="topleft"
          left="0"
          name="postcard_image_format_quality_lp"
-         user_resize="false" 
          auto_resize="true"
          top="0"
          right="-1"
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
index 273c252474..198ccd6e2f 100644
--- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -31,8 +31,7 @@
 		width="0"
 		name="left_bookend_bottom"
 		mouse_opaque="false"
-		layout="topleft"
-		user_resize="false" />
+		layout="topleft"/>
 	<layout_panel
 		name="media_progress_indicator"
 		mouse_opaque="false"
@@ -41,7 +40,6 @@
 		left="0"
 		top="0"
 		auto_resize="false"
-		user_resize="false"
 		min_width="100"
 		width="200">
 	  <progress_bar
@@ -59,8 +57,7 @@
 		name="right_bookend_bottom"
 		width="0"
 		mouse_opaque="false"
-		layout="topleft"
-		user_resize="false" />
+		layout="topleft"/>
   </layout_stack>
   <layout_stack
 	  name="media_controls"
@@ -79,13 +76,11 @@
 		top="0"
 		width="0"
 		mouse_opaque="false"
-		layout="topleft"
-		user_resize="false" />
+		layout="topleft"/>
 	<layout_panel
 		name="back"
 		top="0"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		mouse_opaque="false"
 		min_width="22"
@@ -114,7 +109,6 @@
 		name="fwd"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		min_width="22"
 		top="0"
@@ -142,7 +136,6 @@
 		name="home"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		height="22"
@@ -170,7 +163,6 @@
 		name="media_stop"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		height="22"
@@ -198,7 +190,6 @@
 		name="reload"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		height="22"
@@ -226,7 +217,6 @@
 		name="stop"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		height="22"
@@ -254,7 +244,6 @@
 		name="play"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		height="22"
@@ -282,7 +271,6 @@
 		name="pause"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		min_width="22"
@@ -310,7 +298,6 @@
 		name="media_address"
 		mouse_opaque="false"
 		auto_resize="true"
-		user_resize="false"
 		height="24"
 		follows="left|right|bottom"
 		layout="topleft"
@@ -343,8 +330,7 @@
 			layout="topleft"
 			width="16"
 			mouse_opaque="false"
-			auto_resize="false"
-			user_resize="false">
+			auto_resize="false">
 		  <icon
 			  name="media_whitelist_flag"
 			  follows="top|right"
@@ -358,8 +344,7 @@
 			layout="topleft"
 			width="16"
 			mouse_opaque="false"
-			auto_resize="false"
-			user_resize="false">
+			auto_resize="false">
 		  <icon
 			  name="media_secure_lock_flag"
 			  height="16"
@@ -374,7 +359,6 @@
 		name="media_play_position"
 		mouse_opaque="false"
 		auto_resize="true"
-		user_resize="false"
 		follows="left|right"
 		layout="topleft"
 		top="0"
@@ -399,7 +383,6 @@
 		name="skip_back"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		min_width="22"
@@ -428,7 +411,6 @@
 		name="skip_forward"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		min_width="22"
@@ -455,7 +437,6 @@
 		name="media_volume"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		height="72"
@@ -511,7 +492,6 @@
 		name="zoom_frame"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		height="28"
@@ -539,7 +519,6 @@
 		name="close"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		min_width="21"
@@ -567,7 +546,6 @@
 		name="new_window"
 		mouse_opaque="false"
 		auto_resize="false"
-		user_resize="false"
 		layout="topleft"
 		top="0"
 		min_width="22"
@@ -596,8 +574,7 @@
 		mouse_opaque="false"
 		top="0"
 		width="0"
-		layout="topleft"
-		user_resize="false" />
+		layout="topleft"/>
   </layout_stack>
   <panel
 	  name="media_region"
diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml
index 4535c56339..7275e8d89b 100644
--- a/indra/newview/skins/default/xui/en/panel_progress.xml
+++ b/indra/newview/skins/default/xui/en/panel_progress.xml
@@ -20,14 +20,12 @@
          layout="topleft"
          min_width="10"
          name="panel1"
-         user_resize="false"
          width="150" />
         <layout_panel
          height="768"
          layout="topleft"
          min_width="640"
          name="panel2"
-         user_resize="false"
          width="640">
             <layout_stack
              follows="left|right|top|bottom"
@@ -121,7 +119,6 @@
          layout="topleft"
          min_width="10"
          name="panel6"
-         user_resize="false"
          width="150" />
     </layout_stack>
     <button
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml
index ae0215a578..b966358f18 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml
@@ -96,7 +96,6 @@
          layout="topleft"
          left="0"
          name="local_image_size_lp"
-         user_resize="false" 
          auto_resize="false"
          top="0"
          right="-1"
@@ -145,7 +144,6 @@
          layout="topleft"
          left="0"
          name="local_image_format_quality_lp"
-         user_resize="false" 
          auto_resize="true"
          top="0"
          right="-1"
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml
index 91ac9ad658..5bd383b81e 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml
@@ -84,7 +84,6 @@
          layout="topleft"
          left="0"
          name="profile_image_size_lp"
-         user_resize="false" 
          auto_resize="false"
          top="0"
          right="-1"
@@ -132,7 +131,6 @@
          layout="topleft"
          left="0"
          name="profile_image_metadata_lp"
-         user_resize="false" 
          auto_resize="true"
          top="0"
          right="-1"
diff --git a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml
index 3c69a0cb6c..58911bed56 100644
--- a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml
@@ -20,7 +20,6 @@
                 mouse_opaque="false">
   <layout_panel name="vertical_toolbar_panel"
                 auto_resize="true"
-                user_resize="false"
                 width="1024"
                 height="500"
                 mouse_opaque="false">
@@ -34,7 +33,6 @@
                   mouse_opaque="false">
       <layout_panel name="left_toolbar_panel"
                     auto_resize="false"
-                    user_resize="false"
                     height="500"
                     width="30"
                     mouse_opaque="false">
@@ -61,7 +59,6 @@
       </layout_panel>
       <layout_panel name="non_toolbar_panel"
                     auto_resize="true"
-                    user_resize="false"
                     mouse_opaque="false"
                     height="100"
                     width="200">
@@ -102,7 +99,6 @@
       </layout_panel>
       <layout_panel name="right_toolbar_panel"
                     auto_resize="false"
-                    user_resize="false"
                     height="500"
                     width="30"
                     mouse_opaque="false">
@@ -132,7 +128,6 @@
   </layout_panel>
   <layout_panel name="bottom_toolbar_panel"
                 auto_resize="false"
-                user_resize="false"
                 height="30"
                 width="1024"
                 mouse_opaque="false">
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index b52784d6bc..d4162f6d9a 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -34,7 +34,6 @@
                  min_dim="150"
                  width="330"
                  follows="bottom|left|right"
-                 user_resize="false"
                  height="300">
                  <panel
                       class="panel_main_inventory"
@@ -52,12 +51,10 @@
                  width="330"
 								 layout="topleft"
                  auto_resize="true"
-                 user_resize="false"
                  follows="bottom|left|right"
                  name="inbox_outbox_layout_panel"
                  visible="false"
                  min_dim="35"
-                 max_dim="235"
                  expanded_min_dim="125"
                  height="235">
 							 <layout_stack
@@ -75,13 +72,11 @@
                  width="330"
 								 layout="topleft"
                  auto_resize="true"
-                 user_resize="false"
                  follows="left|right|top"
                  name="inbox_layout_panel"
                  visible="false"
                  min_dim="35"
-                 max_dim="200"
-                 expanded_min_dim="90"
+
                  height="200">
                  <panel
                       follows="all"
@@ -157,12 +152,10 @@
                  width="330"
                  layout="topleft"
                  auto_resize="true"
-                 user_resize="false"
                  follows="all"
                  name="outbox_layout_panel"
                  visible="false"
                  min_dim="35"
-                 max_dim="200"
                  expanded_min_dim="90"
                  height="200">
                  <panel
@@ -312,7 +305,6 @@
                      left="0"			
                      mouse_opaque="false"
                      name="info_btn_lp"
-                     user_resize="false" 
                      auto_resize="true"
                      width="101">
                     <button
@@ -334,7 +326,6 @@
                      left_pad="1"			
                      mouse_opaque="false"
                      name="share_btn_lp"
-                     user_resize="false" 
                      auto_resize="true"
                      width="100">
                     <button
@@ -356,7 +347,6 @@
                      left_pad="1"			
                      mouse_opaque="false"
                      name="shop_btn_lp"
-                     user_resize="false" 
                      auto_resize="true"
                      width="100">
                     <button
-- 
cgit v1.2.3


From 7092a07045e0bc17c503c0bc81e3f038bd1516e8 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 16 Jan 2012 14:35:00 -0800
Subject: Fix Mac build issue

---
 indra/llui/lllayoutstack.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index b67030dc34..a1e8eebb47 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -116,9 +116,9 @@ F32 LLLayoutPanel::getVisibleAmount() const
 
 S32 LLLayoutPanel::getLayoutDim() const
 {
-	return llround((mOrientation == LLLayoutStack::HORIZONTAL)
+	return llround((F32)((mOrientation == LLLayoutStack::HORIZONTAL)
 					? getRect().getWidth()
-					: getRect().getHeight());
+					: getRect().getHeight()));
 }
  
 S32 LLLayoutPanel::getVisibleDim() const
@@ -132,9 +132,9 @@ S32 LLLayoutPanel::getVisibleDim() const
 void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientation )
 {
 	mOrientation = orientation;
-	S32 layout_dim = llround((mOrientation == LLLayoutStack::HORIZONTAL)
+	S32 layout_dim = llround((F32)((mOrientation == LLLayoutStack::HORIZONTAL)
 		? getRect().getWidth()
-		: getRect().getHeight());
+		: getRect().getHeight()));
 
 	if (mMinDim == -1)
 	{
-- 
cgit v1.2.3


From 83138403ec6bb839d38b1d72c286df1121d08be9 Mon Sep 17 00:00:00 2001
From: Paul ProductEngine <pguslisty@productengine.com>
Date: Tue, 17 Jan 2012 13:40:35 +0200
Subject: EXP-1768 FIXED (incomplete sentence for translation)

The whole sentence was split to two parts:
 First pars was in panel.string and the second one in the text box. I combined them both in "allow_label5" text box and also I deleted unnecessary panel.string with the first part of the sentence.
---
 indra/newview/llfloaterland.cpp                          |  1 -
 .../newview/skins/default/xui/de/floater_about_land.xml  |  5 +----
 .../newview/skins/default/xui/en/floater_about_land.xml  | 16 ++++++----------
 .../newview/skins/default/xui/es/floater_about_land.xml  |  5 +----
 .../newview/skins/default/xui/fr/floater_about_land.xml  |  5 +----
 .../newview/skins/default/xui/it/floater_about_land.xml  |  5 +----
 .../newview/skins/default/xui/ja/floater_about_land.xml  |  5 +----
 .../newview/skins/default/xui/pt/floater_about_land.xml  |  5 +----
 .../newview/skins/default/xui/ru/floater_about_land.xml  |  5 +----
 .../newview/skins/default/xui/tr/floater_about_land.xml  |  5 +----
 10 files changed, 14 insertions(+), 43 deletions(-)

diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index b13a9aab88..d8e4aa03f7 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2025,7 +2025,6 @@ void LLPanelLandOptions::refresh()
 		}
 
 		mSeeAvatarsCtrl->set(parcel->getSeeAVs());
-		mSeeAvatarsCtrl->setLabel(getString("see_avs_text"));
 		mSeeAvatarsCtrl->setEnabled(can_change_options && parcel->getHaveNewParcelLimitData());
 
 		BOOL can_change_landing_point = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, 
diff --git a/indra/newview/skins/default/xui/de/floater_about_land.xml b/indra/newview/skins/default/xui/de/floater_about_land.xml
index 3cf3a16247..f377c74a3f 100644
--- a/indra/newview/skins/default/xui/de/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_about_land.xml
@@ -309,9 +309,6 @@ Nur große Parzellen können in der Suche aufgeführt werden.
 			<panel.string name="push_restrict_region_text">
 				Kein Stoßen (regional)
 			</panel.string>
-			<panel.string name="see_avs_text">
-				Auf dieser Parzelle Einwohner sehen und mit ihnen chatten
-			</panel.string>
 			<text name="allow_label">
 				Anderen Einwohnern gestatten:
 			</text>
@@ -375,7 +372,7 @@ Nur große Parzellen können in der Suche aufgeführt werden.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Klicken Sie hier, um ein Bild auszuwählen"/>
 			<text name="allow_label5">
-				Einwohnern auf anderen Parzellen Folgendes gestatten:
+				Einwohnern auf anderen Parzellen Folgendes gestatten: Auf dieser Parzelle Einwohner sehen und mit ihnen chatten
 			</text>
 			<check_box label="Avatare sehen" name="SeeAvatarsCheck" tool_tip="Gestattet sowohl Einwohnern auf anderen Parzellen, Einwohner auf dieser Parzelle zu sehen und mit ihnen zu chatten, als auch Ihnen, diese Einwohner auf anderen Parzellen zu sehen und mit ihnen zu chatten."/>
 			<text name="landing_point">
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 4772f744ea..d198cd65a8 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -1206,10 +1206,6 @@ Only large parcels can be listed in search.
              name="push_restrict_region_text">
                 No Pushing (Region Override)
             </panel.string>
-            <panel.string
-             name="see_avs_text">
-                    Avatars on other parcels can see
-            </panel.string>
             <text
              type="string"
              length="1"
@@ -1524,24 +1520,24 @@ Only large parcels can be listed in search.
              length="1"
              follows="left|top"
              text_color="LtGray"
-             height="16"
+             height="32"
              layout="topleft"
              left="274"
-             top="166"
+             top="150"
              name="allow_label5"
-             width="278">
-              and chat with avatars on this parcel
+             width="205"
+             wrap="true">
+              Avatars on other parcels can see and chat with avatars on this parcel
             </text>
             <check_box
              height="16"
-             label="See Avatars"
              follows="top"
              layout="topleft"
              left="253"
              top="150"
              name="SeeAvatarsCheck"
              tool_tip="Allows avatars on other parcels to see and chat with avatars on this parcel, and you to see and chat with them."
-             width="120" />
+             width="10" />
             <text
              type="string"
              length="1"
diff --git a/indra/newview/skins/default/xui/es/floater_about_land.xml b/indra/newview/skins/default/xui/es/floater_about_land.xml
index b6391e28a0..e34b57fca3 100644
--- a/indra/newview/skins/default/xui/es/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/es/floater_about_land.xml
@@ -308,9 +308,6 @@ Sólo las parcelas más grandes pueden listarse en la búsqueda.
 			<panel.string name="push_restrict_region_text">
 				Sin &apos;empujones&apos; (prevalece lo marcado en la región)
 			</panel.string>
-			<panel.string name="see_avs_text">
-				Ver a los residentes de esta parcela y chatear con ellos
-			</panel.string>
 			<text name="allow_label">
 				Permitir a otros Residentes:
 			</text>
@@ -374,7 +371,7 @@ Sólo las parcelas más grandes pueden listarse en la búsqueda.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Pulse para elegir una imagen"/>
 			<text name="allow_label5">
-				Permitir a los residentes de otras parcelas:
+				Permitir a los residentes de otras parcelas: Ver a los residentes de esta parcela y chatear con ellos
 			</text>
 			<check_box label="Ver los avatares" name="SeeAvatarsCheck" tool_tip="Permite que los residentes de otras parcelas vean a los residentes de ésta y chateen con ellos, y también que tú puedas verles y chatear con ellos."/>
 			<text name="landing_point">
diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml
index 9771c3f7fd..900a856e7b 100644
--- a/indra/newview/skins/default/xui/fr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml
@@ -312,9 +312,6 @@ Seules les parcelles de grande taille peuvent apparaître dans la recherche.
 			<panel.string name="push_restrict_region_text">
 				Pas de bousculades (les règles de la région priment)
 			</panel.string>
-			<panel.string name="see_avs_text">
-				Voir et chatter avec les résidents sur cette parcelle
-			</panel.string>
 			<text name="allow_label">
 				Autoriser les autres résidents à :
 			</text>
@@ -378,7 +375,7 @@ Seules les parcelles de grande taille peuvent apparaître dans la recherche.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Cliquez pour sélectionner une image"/>
 			<text name="allow_label5">
-				Autoriser les résidents sur les autres parcelles à :
+				Autoriser les résidents sur les autres parcelles à : Voir et chatter avec les résidents sur cette parcelle
 			</text>
 			<check_box label="Voir les avatars" name="SeeAvatarsCheck" tool_tip="Permettre aux résidents présents sur d&apos;autres parcelles de voir et chatter avec les résidents présents sur cette parcelle et vous permettre de les voir et de chatter avec eux."/>
 			<text name="landing_point">
diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml
index b6bfb4aadf..2e30de4214 100644
--- a/indra/newview/skins/default/xui/it/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/it/floater_about_land.xml
@@ -313,9 +313,6 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
 			<panel.string name="push_restrict_region_text">
 				Nessuna spinta (Impostazione regionale)
 			</panel.string>
-			<panel.string name="see_avs_text">
-				Vedi i residenti in questo lotto e chatta con loro
-			</panel.string>
 			<text name="allow_label">
 				Permetti ad altri residenti di:
 			</text>
@@ -379,7 +376,7 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Clicca per scegliere una immagine"/>
 			<text name="allow_label5">
-				Permetti ai residenti in altri lotti di:
+				Permetti ai residenti in altri lotti di: Vedi i residenti in questo lotto e chatta con loro
 			</text>
 			<check_box label="Vedi avatar" name="SeeAvatarsCheck" tool_tip="Consente ai residenti in altri lotti di vedere i residenti in questo lotto e chattare con loro, e ti consente di vederli e chattare con loro."/>
 			<text name="landing_point">
diff --git a/indra/newview/skins/default/xui/ja/floater_about_land.xml b/indra/newview/skins/default/xui/ja/floater_about_land.xml
index 3c88c902f8..61d418b2d8 100644
--- a/indra/newview/skins/default/xui/ja/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about_land.xml
@@ -310,9 +310,6 @@
 			<panel.string name="push_restrict_region_text">
 				プッシュ禁止 (地域設定優先)
 			</panel.string>
-			<panel.string name="see_avs_text">
-				この区画にいる住人と会ってチャットする
-			</panel.string>
 			<text name="allow_label">
 				他の住人への許可:
 			</text>
@@ -376,7 +373,7 @@
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="写真をクリックして選択"/>
 			<text name="allow_label5">
-				他の区画にいる住人への許可:
+				他の区画にいる住人への許可: この区画にいる住人と会ってチャットする
 			</text>
 			<check_box label="アバターを表示" name="SeeAvatarsCheck" tool_tip="他の区画の住人が、この区画にいる住人に会ってチャットすることを許可し、あなたもそれら住人に会ってチャットできるようにします。"/>
 			<text name="landing_point">
diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml
index cc09888994..39d44a9949 100644
--- a/indra/newview/skins/default/xui/pt/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml
@@ -308,9 +308,6 @@ Apenas lotes maiores podem ser listados na busca.
 			<panel.string name="push_restrict_region_text">
 				Proibido empurrar (regulamento da região)
 			</panel.string>
-			<panel.string name="see_avs_text">
-				Veja e bata papo com os residentes deste terreno
-			</panel.string>
 			<text name="allow_label">
 				Autorizar outros residentes a:
 			</text>
@@ -374,7 +371,7 @@ Apenas lotes maiores podem ser listados na busca.
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Clique para escolher uma imagem"/>
 			<text name="allow_label5">
-				Permitir que residentes de outros terrenos:
+				Permitir que residentes de outros terrenos: Veja e bata papo com os residentes deste terreno
 			</text>
 			<check_box label="Ver avatares" name="SeeAvatarsCheck" tool_tip="Permite que residentes de outros terrenos vejam e conversem com os residentes deste terreno e vice-versa."/>
 			<text name="landing_point">
diff --git a/indra/newview/skins/default/xui/ru/floater_about_land.xml b/indra/newview/skins/default/xui/ru/floater_about_land.xml
index 3c278fce52..2f5c64984d 100644
--- a/indra/newview/skins/default/xui/ru/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ru/floater_about_land.xml
@@ -306,9 +306,6 @@
 			<panel.string name="push_restrict_region_text">
 				Не толкать (настройки региона)
 			</panel.string>
-			<panel.string name="see_avs_text">
-				Видеть жителей этого участка и общаться с ними в чате
-			</panel.string>
 			<text name="allow_label">
 				Позволить другим жителям:
 			</text>
@@ -372,7 +369,7 @@
 			</text>
 			<texture_picker name="snapshot_ctrl" tool_tip="Щелкните для выбора изображения"/>
 			<text name="allow_label5">
-				Позволить жителям с других участков:
+				Позволить жителям с других участков: Видеть жителей этого участка и общаться с ними в чате
 			</text>
 			<check_box label="Видны аватары" name="SeeAvatarsCheck" tool_tip="Жители с других участков могут видеть жителей этого участка и общаться с ними в чате (вы также сможете видеть жителей с других участков и общаться с ними)."/>
 			<text name="landing_point">
diff --git a/indra/newview/skins/default/xui/tr/floater_about_land.xml b/indra/newview/skins/default/xui/tr/floater_about_land.xml
index e0350964b5..69abe582e6 100644
--- a/indra/newview/skins/default/xui/tr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/tr/floater_about_land.xml
@@ -306,9 +306,6 @@ Sadece büyük parseller aramada görünür.
 			<panel.string name="push_restrict_region_text">
 				İtme Yok (Bölge Geçersiz Kılma)
 			</panel.string>
-			<panel.string name="see_avs_text">
-				Parseldeki sakinleri gör ve onlarla sohbet et
-			</panel.string>
 			<text name="allow_label">
 				Sakinlere şunun için izin ver:
 			</text>
@@ -372,7 +369,7 @@ Sadece büyük parseller aramada görünür.
 			</text>
 			<texture_picker name="snapshot_ctrl" tool_tip="Bir resim seçmek için tıklayın"/>
 			<text name="allow_label5">
-				Diğer parsel Sakinlerine şunun için izin verin:
+				Diğer parsel Sakinlerine şunun için izin verin: Parseldeki sakinleri gör ve onlarla sohbet et
 			</text>
 			<check_box label="Avatarları Gör" name="SeeAvatarsCheck" tool_tip="Diğer parsellerdeki sakinlerin bu parseldeki sakinleri görmesine ve onlarla sohbet etmesine, sizin de onları görüp, onlarla sohbet etmenize imkan tanır."/>
 			<text name="landing_point">
-- 
cgit v1.2.3


From 6157386b4c96740e406a49eb9e8f42c6d7f252ff Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 17 Jan 2012 10:38:59 -0500
Subject: Added tag 3.2.7-start for changeset 4891c46a56fe

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index f4ffb61aa6..75dc28b262 100644
--- a/.hgtags
+++ b/.hgtags
@@ -245,3 +245,4 @@ bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d DRTVWR-107_3.2.5-beta2
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d 3.2.5-beta2
 2174ed1c7129562428a5cfe8651ed77b8d26ae18 3.2.6-start
+4891c46a56fed7512c783b9cbe7cb7260727bf0c 3.2.7-start
-- 
cgit v1.2.3


From 0e7956a4cbdb0772ff6175307475ee6fc8b620ea Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 17 Jan 2012 07:39:14 -0800
Subject: EXP-1758 : Fix crash on login on Mac (bad pointer reference). Might
 need more work if the intent was to always get that pointer.

---
 indra/llui/lllayoutstack.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index a1e8eebb47..ac10afe594 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -156,7 +156,10 @@ void LLLayoutPanel::setVisible( BOOL visible )
 	if (visible != getVisible())
 	{
 		LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent());
-		stackp->mNeedsLayout = true;
+		if (stackp)
+		{
+			stackp->mNeedsLayout = true;
+		}
 	}
 	LLPanel::setVisible(visible);
 }
-- 
cgit v1.2.3


From 64c45cbd1ace677456db56d1a506f2fe44b6e9c6 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 17 Jan 2012 10:39:14 -0500
Subject: increment viewer version to 3.2.8

---
 indra/llcommon/llversionviewer.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 7bba3d298f..99ab053b25 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
 
 const S32 LL_VERSION_MAJOR = 3;
 const S32 LL_VERSION_MINOR = 2;
-const S32 LL_VERSION_PATCH = 7;
+const S32 LL_VERSION_PATCH = 8;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";
-- 
cgit v1.2.3


From 1f9529c0c2b02c4ceee912f8ecb35181174cc7cc Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 17 Jan 2012 08:55:19 -0800
Subject: EXP-1772 : Suppress a useless and confusing assert in destructor,
 called cleanup in there instead.

---
 indra/newview/llwearablelist.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index ddbcdfc3f7..6f6411ce3c 100644
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -63,7 +63,7 @@ struct LLWearableArrivedData
 
 LLWearableList::~LLWearableList()
 {
-	llassert_always(mList.empty()) ;
+	cleanup();
 }
 
 void LLWearableList::cleanup() 
-- 
cgit v1.2.3


From 577479a3e53ef152da191e3a004aeb34f0815658 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 17 Jan 2012 09:36:14 -0800
Subject: EXP-1803 CLEAN-UP -- Modified code to use the "unique" tag on the
 notification.

---
 indra/newview/llinventorybridge.cpp                  | 10 +++++-----
 indra/newview/llinventoryfunctions.cpp               | 13 +------------
 indra/newview/skins/default/xui/en/notifications.xml |  1 +
 3 files changed, 7 insertions(+), 17 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 270ef4fddc..1a4fd17d61 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2244,7 +2244,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 	{
 		if (move_is_into_outbox)
 		{
-			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+			tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
 		}
 		else
@@ -2256,7 +2256,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 	{
 		if (move_is_into_outbox)
 		{
-			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+			tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
 		}
 		else
@@ -3765,7 +3765,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		}
 		else if (move_is_into_outbox)
 		{
-			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+			tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
 		}
 		
@@ -3796,7 +3796,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 	{
 		if (move_is_into_outbox)
 		{
-			tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+			tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
 		}
 		else
@@ -3823,7 +3823,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 
 			if (move_is_into_outbox)
 			{
-				tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+				tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 				accept = FALSE;
 			}
 			else if (move_is_into_current_outfit || move_is_into_outfit)
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index f5be271a68..40bc3b76c9 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -533,7 +533,6 @@ void show_item_original(const LLUUID& item_uuid)
 }
 
 
-static S32 create_folder_in_outbox_operation_id = -1;
 static S32 move_to_outbox_operation_id = -1;
 static std::list<LLSD> move_to_outbox_payloads;
 
@@ -542,11 +541,6 @@ void open_outbox()
 	LLFloaterReg::showInstance("outbox");
 }
 
-void folder_created_in_outbox_cb(const LLSD& notification, const LLSD& response)
-{
-	create_folder_in_outbox_operation_id = -1;
-}
-
 LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& destFolderId, S32 operation_id)
 {
 	llassert(item);
@@ -555,12 +549,7 @@ LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& des
 	LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName());
 	gInventory.notifyObservers();
 
-	if (create_folder_in_outbox_operation_id != operation_id)
-	{
-		LLNotificationsUtil::add("OutboxFolderCreated", LLSD(), LLSD(), boost::bind(&folder_created_in_outbox_cb, _1, _2));
-
-		create_folder_in_outbox_operation_id = operation_id;
-	}
+	LLNotificationsUtil::add("OutboxFolderCreated");
 
 	return created_folder_id;
 }
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index e44fb3bf28..af75d49353 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -214,6 +214,7 @@ You don't have permission to copy one or more of these items to the Merchant Out
    icon="OutboxStatus_Success"
    name="OutboxFolderCreated"
    type="outbox">
+    <unique/>
 A new folder has been created for each item you have transferred into the top level of your Merchant Outbox.
 
     <usetemplate
-- 
cgit v1.2.3


From 74737fa31988b30d0ebdcb6cc28cf660b7ccf607 Mon Sep 17 00:00:00 2001
From: "Debi King (Dessie)" <dessie@lindenlab.com>
Date: Tue, 17 Jan 2012 13:26:35 -0500
Subject: Added tag DRTVWR-109_3.2.6-beta1, 3.2.6-beta1 for changeset
 286d73ff5c19

---
 .hgtags | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.hgtags b/.hgtags
index f4ffb61aa6..d51435daa5 100644
--- a/.hgtags
+++ b/.hgtags
@@ -245,3 +245,5 @@ bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d DRTVWR-107_3.2.5-beta2
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d 3.2.5-beta2
 2174ed1c7129562428a5cfe8651ed77b8d26ae18 3.2.6-start
+286d73ff5c19f6c00e023dc1b60975ed6bbe2872 DRTVWR-109_3.2.6-beta1
+286d73ff5c19f6c00e023dc1b60975ed6bbe2872 3.2.6-beta1
-- 
cgit v1.2.3


From 2abb1a81c56a27eab02157851cb9e67730231bb6 Mon Sep 17 00:00:00 2001
From: "Debi King (Dessie)" <dessie@lindenlab.com>
Date: Tue, 17 Jan 2012 13:31:00 -0500
Subject: Added tag DRTVWR-105_3.2.5-release, 3.2.5-release for changeset
 c6175c955a19

---
 .hgtags | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.hgtags b/.hgtags
index 3def677a7f..5c2b0843dd 100644
--- a/.hgtags
+++ b/.hgtags
@@ -240,3 +240,5 @@ bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release
 3d2d5d244c6398a4214c666d5dd3965b0918709a 3.2.5-beta1
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d DRTVWR-107_3.2.5-beta2
 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d 3.2.5-beta2
+c6175c955a19e9b9353d242889ec1779b5762522 DRTVWR-105_3.2.5-release
+c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release
-- 
cgit v1.2.3


From 3a313469c9be4e71384314ebecb2de7434752c02 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 17 Jan 2012 11:44:40 -0800
Subject: EXP-1799 FIX -- Replace and Add to Outfit options appear as grayed
 out in Inventory

* Updated context menu code to enable visible items that aren't explicitly disabled.
---
 indra/newview/llinventorybridge.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 1a4fd17d61..c97d756a31 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -529,14 +529,17 @@ void hide_context_entries(LLMenuGL& menu,
 			// so that some other UI element from multi-select doesn't later set this invisible.
 			menu_item->pushVisible(TRUE);
 
+			BOOL enabled = TRUE;
 			for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
 			{
 				if (*itor2 == name)
 				{
-					menu_item->setEnabled(FALSE);
+					enabled = FALSE;
 					break;
 				}
 			}
+
+			menu_item->setEnabled(enabled);
 		}
 	}
 }
-- 
cgit v1.2.3


From 2589a7e135a9e894eb7bbe0cb1e032c105f72bf8 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 17 Jan 2012 12:17:03 -0800
Subject: fix for crash in assert when programmatically toggling user resize

---
 indra/llui/lllayoutstack.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index ac10afe594..000f729e29 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -314,6 +314,8 @@ void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL au
 	{
 		panel->mAutoResize = auto_resize;
 	}
+
+	mNeedsLayout = true;
 }
 
 void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize)
@@ -324,6 +326,8 @@ void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_
 	{
 		panel->mUserResize = user_resize;
 	}
+
+	mNeedsLayout = true;
 }
 
 
-- 
cgit v1.2.3


From accf83394513c82e98fffa15bc0131ee25f63f00 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 17 Jan 2012 13:07:57 -0800
Subject: EXP-1805 FIX -- Block calling cards from being added to Merchant
 Outbox EXP-1810 PROGRESS -- Cannot resize Received items panel in Inventory
 window

* Updated "copy to merchant outbox" context menu and drag and drop code to block calling cards.
* Changed user_resize to true on the "Received Items" panel and the main inventory panel
---
 indra/newview/llinventorybridge.cpp                  | 20 +++++++++++++++++---
 .../skins/default/xui/en/sidepanel_inventory.xml     |  5 ++++-
 indra/newview/skins/default/xui/en/strings.xml       |  1 +
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 2d5e4938c6..3929183be2 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1153,9 +1153,17 @@ bool LLInvFVBridge::canListOnMarketplace() const
 	}
 
 	LLViewerInventoryItem * item = model->getItem(mUUID);
-	if (item && !item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+	if (item)
 	{
-		return false;
+		if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+		{
+			return false;
+		}
+		
+		if (LLAssetType::AT_CALLINGCARD == item->getType())
+		{
+			return false;
+		}
 	}
 
 	return true;
@@ -1897,7 +1905,6 @@ static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_m
 	}
 	
 	bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
-
 	if (!allow_transfer)
 	{
 		tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer");
@@ -1913,6 +1920,13 @@ static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_m
 	}
 #endif
 	
+	bool calling_card = (LLAssetType::AT_CALLINGCARD == inv_item->getType());
+	if (calling_card)
+	{
+		tooltip_msg = LLTrans::getString("TooltipOutboxCallingCard");
+		return false;
+	}
+	
 	return true;
 }
 
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index 5d398a29af..fcba937bdb 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -30,6 +30,8 @@
              <layout_panel
                  name="main_inventory_layout_panel"
                  layout="topleft"
+                 auto_resize="true"
+                 user_resize="true"
                  min_dim="150"
                  width="330"
                  follows="bottom|left|right"
@@ -48,8 +50,9 @@
              </layout_panel>
 			 <layout_panel
                  width="330"
-		 layout="topleft"
+                 layout="topleft"
                  auto_resize="true"
+                 user_resize="true"
                  follows="left|right|top"
                  name="inbox_layout_panel"
                  visible="false"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 84fce6630b..3b00969fd4 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -169,6 +169,7 @@ Please try logging in again in a minute.</string>
 	<string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred.</string>
 	<string name="TooltipOutboxNotInInventory">Your merchant outbox can only accept items directly from your inventory</string>
 	<string name="TooltipOutboxWorn">You can not put items you are wearing into your merchant outbox</string>
+	<string name="TooltipOutboxCallingCard">You can not put calling cards into your merchant outbox</string>
 	<string name="TooltipOutboxFolderLevels">Depth of nested folders exceeds 3</string>
 	<string name="TooltipOutboxTooManyFolders">Subfolder count in top-level folder exceeds 20</string>
 	<string name="TooltipOutboxTooManyObjects">Item count in top-level folder exceeds 200</string>
-- 
cgit v1.2.3


From e4b63c96b83a1ed8c18946ecd64c21d6bd7c26fe Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 17 Jan 2012 14:59:18 -0800
Subject: EXP-1804 FIX -- Drag and drop operations can be blocked by modal
 dialogs

* Added support for marketplace notifications that don't display the dialog
  until the next frame, leaving room for the drag and drop operation to
  properly complete before the notification shows up and interferes.
---
 indra/newview/CMakeLists.txt                 |  2 +
 indra/newview/llappviewer.cpp                |  4 +-
 indra/newview/llinventoryfunctions.cpp       | 39 ++----------
 indra/newview/llmarketplacenotifications.cpp | 89 ++++++++++++++++++++++++++++
 indra/newview/llmarketplacenotifications.h   | 57 ++++++++++++++++++
 5 files changed, 155 insertions(+), 36 deletions(-)
 create mode 100644 indra/newview/llmarketplacenotifications.cpp
 create mode 100644 indra/newview/llmarketplacenotifications.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 78cd33210f..f85b943c70 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -316,6 +316,7 @@ set(viewer_SOURCE_FILES
     llmanipscale.cpp
     llmaniptranslate.cpp
     llmarketplacefunctions.cpp
+    llmarketplacenotifications.cpp
     llmediactrl.cpp
     llmediadataclient.cpp
     llmemoryview.cpp
@@ -871,6 +872,7 @@ set(viewer_HEADER_FILES
     llmanipscale.h
     llmaniptranslate.h
     llmarketplacefunctions.h
+    llmarketplacenotifications.h
     llmediactrl.h
     llmediadataclient.h
     llmemoryview.h
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 5c51f1b11a..a455d359bf 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -46,6 +46,7 @@
 #include "llviewerstats.h"
 #include "llviewerstatsrecorder.h"
 #include "llmarketplacefunctions.h"
+#include "llmarketplacenotifications.h"
 #include "llmd5.h"
 #include "llmeshrepository.h"
 #include "llpumpio.h"
@@ -4406,8 +4407,9 @@ void LLAppViewer::idle()
 	// update media focus
 	LLViewerMediaFocus::getInstance()->update();
 	
-	// Update marketplace importer
+	// Update marketplace
 	LLMarketplaceInventoryImporter::update();
+	LLMarketplaceInventoryNotifications::update();
 
 	// objects and camera should be in sync, do LOD calculations now
 	{
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 40bc3b76c9..dd92188e9d 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -58,6 +58,7 @@
 #include "llinventorymodel.h"
 #include "llinventorypanel.h"
 #include "lllineeditor.h"
+#include "llmarketplacenotifications.h"
 #include "llmenugl.h"
 #include "llnotificationsutil.h"
 #include "llpanelmaininventory.h"
@@ -533,9 +534,6 @@ void show_item_original(const LLUUID& item_uuid)
 }
 
 
-static S32 move_to_outbox_operation_id = -1;
-static std::list<LLSD> move_to_outbox_payloads;
-
 void open_outbox()
 {
 	LLFloaterReg::showInstance("outbox");
@@ -614,24 +612,6 @@ void move_to_outbox_cb_action(const LLSD& payload)
 	}
 }
 
-void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
-{
-	const S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
-	if (option == 0)
-	{
-		llassert(move_to_outbox_payloads.size() > 0);
-
-		BOOST_FOREACH(const LLSD& payload, move_to_outbox_payloads)
-		{
-			move_to_outbox_cb_action(payload);
-		}
-	}
-
-	move_to_outbox_operation_id = -1;
-	move_to_outbox_payloads.clear();
-}
-
 void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id)
 {
 	// Collapse links directly to items/folders
@@ -668,25 +648,14 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
 			open_outbox();
 		}
 		else
-		{	
-			LLSD args;
-			args["ITEM_NAME"] = inv_item->getName();
-
+		{
 			LLSD payload;
 			payload["item_id"] = inv_item->getUUID();
 			payload["dest_folder_id"] = dest_folder;
 			payload["top_level_folder"] = top_level_folder;
 			payload["operation_id"] = operation_id;
-
-			if (move_to_outbox_operation_id != operation_id)
-			{
-				LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2));
-				
-				move_to_outbox_operation_id = operation_id;
-				move_to_outbox_payloads.clear();
-			}
-
-			move_to_outbox_payloads.push_back(payload);
+			
+			LLMarketplaceInventoryNotifications::addNoCopyNotification(payload, move_to_outbox_cb_action);
 		}
 	}
 }
diff --git a/indra/newview/llmarketplacenotifications.cpp b/indra/newview/llmarketplacenotifications.cpp
new file mode 100644
index 0000000000..25faafb8ea
--- /dev/null
+++ b/indra/newview/llmarketplacenotifications.cpp
@@ -0,0 +1,89 @@
+/** 
+ * @file llmarketplacenotifications.cpp
+ * @brief Handler for notifications related to marketplace file I/O
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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 "llmarketplacenotifications.h"
+#include "llnotificationsutil.h"
+
+#include "llerror.h"
+
+#include <boost/foreach.hpp>
+#include <boost/signals2.hpp>
+
+
+namespace LLMarketplaceInventoryNotifications
+{
+	typedef boost::signals2::signal<void (const LLSD& param)>	no_copy_payload_cb_signal_t;
+
+	static no_copy_payload_cb_signal_t*	no_copy_cb_action = NULL;
+	static bool							no_copy_notify_active = false;
+	static std::list<LLSD>				no_copy_payloads;
+
+	void notifyNoCopyCallback(const LLSD& notification, const LLSD& response)
+	{
+		const S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+		
+		if (option == 0)
+		{
+			llassert(!no_copy_payloads.empty());
+			llassert(no_copy_cb_action != NULL);
+			
+			BOOST_FOREACH(const LLSD& payload, no_copy_payloads)
+			{
+				(*no_copy_cb_action)(payload);
+			}
+		}
+		
+		delete no_copy_cb_action;
+		no_copy_cb_action = NULL;
+		
+		no_copy_notify_active = false;
+		no_copy_payloads.clear();
+	}
+
+	void update()
+	{
+		if (!no_copy_notify_active && !no_copy_payloads.empty())
+		{
+			no_copy_notify_active = true;
+			
+			LLNotificationsUtil::add("ConfirmNoCopyToOutbox", LLSD(), LLSD(), boost::bind(&notifyNoCopyCallback, _1, _2));
+		}
+	}
+		
+	void addNoCopyNotification(const LLSD& payload, const NoCopyCallbackFunction& cb)
+	{
+		if (no_copy_cb_action == NULL)
+		{
+			no_copy_cb_action = new no_copy_payload_cb_signal_t;
+			no_copy_cb_action->connect(boost::bind(cb, _1));
+		}
+
+		no_copy_payloads.push_back(payload);
+	}
+}
diff --git a/indra/newview/llmarketplacenotifications.h b/indra/newview/llmarketplacenotifications.h
new file mode 100644
index 0000000000..83a4e163c7
--- /dev/null
+++ b/indra/newview/llmarketplacenotifications.h
@@ -0,0 +1,57 @@
+/** 
+ * @file llmarketplacenotifications.h
+ * @brief Handler for notifications related to marketplace file I/O
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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 LL_LLMARKETPLACENOTIFICATIONS_H
+#define LL_LLMARKETPLACENOTIFICATIONS_H
+
+
+#include <llsd.h>
+#include <boost/function.hpp>
+
+
+//
+// This is a set of helper functions to handle a unique notification with multiple
+// payloads, helpful when dragging and dropping items to the merchant outbox that
+// trigger notifications that can potentially interfere with the current drag and
+// drop operation.
+//
+// Notification payloads are cached locally when initiated, the notification itself
+// is triggered on the following frame during the call to "update" and then the
+// response is triggered once per payload.
+//
+
+namespace LLMarketplaceInventoryNotifications
+{
+	void update();
+
+	typedef boost::function<void (const LLSD&)> NoCopyCallbackFunction;
+	
+	void addNoCopyNotification(const LLSD& payload, const NoCopyCallbackFunction& cb);
+};
+
+
+#endif // LL_LLMARKETPLACENOTIFICATIONS_H
-- 
cgit v1.2.3


From 4b9cca70d7a3db719a9dfcfbf4937cfcb06b3516 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 17 Jan 2012 15:04:47 -0800
Subject: Fix for precompiled header issue on windows

---
 indra/newview/llmarketplacenotifications.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llmarketplacenotifications.cpp b/indra/newview/llmarketplacenotifications.cpp
index 25faafb8ea..0886f9a990 100644
--- a/indra/newview/llmarketplacenotifications.cpp
+++ b/indra/newview/llmarketplacenotifications.cpp
@@ -25,7 +25,8 @@
  * $/LicenseInfo$
  */
 
-#include "linden_common.h"
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
 
 #include "llmarketplacenotifications.h"
 #include "llnotificationsutil.h"
-- 
cgit v1.2.3


From a01dd3549cca620de47fae824198473c51a12f49 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 17 Jan 2012 18:40:05 -0500
Subject: Make NamedTempFile::peep() a public member for debugging unit tests.

---
 indra/test/namedtempfile.h | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/indra/test/namedtempfile.h b/indra/test/namedtempfile.h
index 9670d4db53..7ffb2836cc 100644
--- a/indra/test/namedtempfile.h
+++ b/indra/test/namedtempfile.h
@@ -59,6 +59,16 @@ public:
 
     std::string getName() const { return mPath; }
 
+    void peep()
+    {
+        std::cout << "File '" << mPath << "' contains:\n";
+        std::ifstream reader(mPath.c_str());
+        std::string line;
+        while (std::getline(reader, line))
+            std::cout << line << '\n';
+        std::cout << "---\n";
+    }
+
 private:
     void createFile(const std::string& pfx, const Streamer& func)
     {
@@ -96,16 +106,6 @@ private:
         llassert_always(writelen == data.length());
     }
 
-    void peep()
-    {
-        std::cout << "File '" << mPath << "' contains:\n";
-        std::ifstream reader(mPath.c_str());
-        std::string line;
-        while (std::getline(reader, line))
-            std::cout << line << '\n';
-        std::cout << "---\n";
-    }
-
     std::string mPath;
     apr_pool_t* mPool;
 };
-- 
cgit v1.2.3


From 652ef621543497aa947970d374285d8f851ed682 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 17 Jan 2012 15:51:30 -0800
Subject: EXP-1791 FIX -- Handle case where initialization with SLM fails in
 the Merchant Outbox floater in the viewer

* Timeout now triggers the re-initialization logic in the merchant outbox.
---
 indra/newview/llmarketplacefunctions.cpp | 10 ++++++----
 indra/newview/llmarketplacefunctions.h   |  1 +
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index ee7505c4f4..a3f0a6062c 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -132,11 +132,12 @@ namespace LLMarketplaceImport
 			}
 
 			if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) ||
-				(status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR))
+				(status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
+				(status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
 			{
 				if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 				{
-					llinfos << " SLM POST clearing marketplace cookie due to authentication failure" << llendl;
+					llinfos << " SLM POST clearing marketplace cookie due to authentication failure or timeout" << llendl;
 				}
 
 				sMarketplaceCookie.clear();
@@ -173,11 +174,12 @@ namespace LLMarketplaceImport
 				llinfos << " SLM GET content: " << content.asString() << llendl;
 			}
 			
-			if (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR)
+			if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
+				(status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
 			{
 				if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 				{
-					llinfos << " SLM GET clearing marketplace cookie due to authentication failure" << llendl;
+					llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout" << llendl;
 				}
 
 				sMarketplaceCookie.clear();
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index 4731566366..4b8f7a1ac7 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -50,6 +50,7 @@ namespace MarketplaceErrorCodes
 		IMPORT_AUTHENTICATION_ERROR = 401,
 		IMPORT_DONE_WITH_ERRORS = 409,
 		IMPORT_JOB_FAILED = 410,
+		IMPORT_JOB_TIMEOUT = 499,
 	};
 }
 
-- 
cgit v1.2.3


From c0731c1c05cafe508c91c5f583301234ba3b8403 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 17 Jan 2012 18:55:42 -0500
Subject: Add log message if LLProcessLauncher child fails to execv(). On a
 Posix platform (vfork()/execv() implementation), if for any reason the
 execv() failed (e.g. executable not on PATH), the viewer would never know,
 nor the user: the vfork() child produced no output, and terminated with rc 0!
 Add logging, make child terminate with nonzero rc. Remove pointless
 addArgument(const char*) overload: this does nothing for you that the
 compiler won't do implicitly. In llupdateinstaller.cpp, remove pointless
 c_str() call in addArgument() arg: we were starting with a std::string, then
 extracting its c_str(), only to construct a whole new std::string from it!

---
 indra/llcommon/llprocesslauncher.cpp                 | 20 +++++++++++---------
 indra/llcommon/llprocesslauncher.h                   |  4 +++-
 .../viewer_components/updater/llupdateinstaller.cpp  |  2 +-
 3 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp
index 10950181fd..25d64e9e28 100644
--- a/indra/llcommon/llprocesslauncher.cpp
+++ b/indra/llcommon/llprocesslauncher.cpp
@@ -73,11 +73,6 @@ void LLProcessLauncher::addArgument(const std::string &arg)
 	mLaunchArguments.push_back(arg);
 }
 
-void LLProcessLauncher::addArgument(const char *arg)
-{
-	mLaunchArguments.push_back(std::string(arg));
-}
-
 #if LL_WINDOWS
 
 int LLProcessLauncher::launch(void)
@@ -262,12 +257,19 @@ int LLProcessLauncher::launch(void)
 	if(id == 0)
 	{
 		// child process
-		
 		::execv(mExecutable.c_str(), (char * const *)fake_argv);
-		
+
 		// If we reach this point, the exec failed.
-		// Use _exit() instead of exit() per the vfork man page.
-		_exit(0);
+        LL_WARNS("LLProcessLauncher") << "failed to launch: ";
+        for (const char * const * ai = fake_argv; *ai; ++ai)
+        {
+            LL_CONT << *ai << ' ';
+        }
+        LL_CONT << LL_ENDL;
+		// Use _exit() instead of exit() per the vfork man page. Exit with a
+		// distinctive rc: someday soon we'll be able to retrieve it, and it
+		// would be nice to be able to tell that the child process failed!
+		_exit(249);
 	}
 
 	// parent process
diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h
index 954c249147..1daa980c58 100644
--- a/indra/llcommon/llprocesslauncher.h
+++ b/indra/llcommon/llprocesslauncher.h
@@ -28,6 +28,7 @@
 #define LL_LLPROCESSLAUNCHER_H
 
 #if LL_WINDOWS
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #endif
 
@@ -51,7 +52,6 @@ public:
 
 	void clearArguments();
 	void addArgument(const std::string &arg);
-	void addArgument(const char *arg);
 		
 	int launch(void);
 	bool isRunning(void);
@@ -66,10 +66,12 @@ public:
 	void orphan(void);	
 	
 	// This needs to be called periodically on Mac/Linux to clean up zombie processes.
+	// (However, as of 2012-01-12 there are no such calls in the viewer code base. :-P )
 	static void reap(void);
 	
 	// Accessors for platform-specific process ID
 #if LL_WINDOWS
+	// (Windows flavor unused as of 2012-01-12)
 	HANDLE getProcessHandle() { return mProcessHandle; };
 #else
 	pid_t getProcessID() { return mProcessID; };
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index c7b70c2de8..84f23b3acc 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -81,7 +81,7 @@ int ll_install_update(std::string const & script,
 	LLProcessLauncher launcher;
 	launcher.setExecutable(actualScriptPath);
 	launcher.addArgument(updatePath);
-	launcher.addArgument(ll_install_failed_marker_path().c_str());
+	launcher.addArgument(ll_install_failed_marker_path());
 	launcher.addArgument(boost::lexical_cast<std::string>(required));
 	int result = launcher.launch();
 	launcher.orphan();
-- 
cgit v1.2.3


From 74fbd31813494fe120211fbdad3ed6da9c2d5d8b Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 17 Jan 2012 19:03:17 -0500
Subject: Add first couple of LLProcessLauncher tests. Run
 INTEGRATION_TEST_llprocesslauncher using setpython.py so we can find the
 Python interpreter of interest. Introduce python() function to run a Python
 script specified using NamedTempFile conventions. Introduce a convention by
 which we can read output from a Python script using only the limited
 pre-January-2012 LLProcessLauncher API. Introduce python_out() function to
 leverage that convention. Exercise a couple of LLProcessLauncher methods
 using all the above.

---
 indra/llcommon/CMakeLists.txt                   |   3 +-
 indra/llcommon/tests/llprocesslauncher_test.cpp | 146 ++++++++++++++++++++++++
 2 files changed, 148 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 334f78cbff..2c376bb016 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -328,7 +328,8 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llprocesslauncher "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llprocesslauncher "" "${test_libs}"
+                          "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
   LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
 
   # *TODO - reenable these once tcmalloc libs no longer break the build.
diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 3935c64a94..aebd280c2e 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -18,10 +18,14 @@
 #include <vector>
 #include <list>
 // std headers
+#include <fstream>
 // external library headers
 #include "llapr.h"
 #include "apr_thread_proc.h"
 #include <boost/foreach.hpp>
+#include <boost/function.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
 // other Linden headers
 #include "../test/lltut.h"
 #include "../test/manageapr.h"
@@ -36,6 +40,8 @@
 #include <sys/wait.h>
 #endif
 
+namespace lambda = boost::lambda;
+
 // static instance of this manages APR init/cleanup
 static ManageAPR manager;
 
@@ -56,6 +62,116 @@ namespace tut
                           rv, expected);
         }
 
+        /**
+         * Run a Python script using LLProcessLauncher.
+         * @param desc Arbitrary description for error messages
+         * @param script Python script, any form acceptable to NamedTempFile,
+         * typically either a std::string or an expression of the form
+         * (lambda::_1 << "script content with " << variable_data)
+         * @param arg If specified, will be passed to script as its
+         * sys.argv[1]
+         * @param tweak "Do something" to LLProcessLauncher object before
+         * calling its launch() method. This program is to test
+         * LLProcessLauncher, but many such tests are "just like" this
+         * python() function but for one or two extra method calls before
+         * launch(). This avoids us having to clone & edit this function for
+         * such tests.
+         */
+        template <typename CONTENT>
+        void python(const std::string& desc, const CONTENT& script, const std::string& arg="",
+                    const boost::function<void (LLProcessLauncher&)> tweak=lambda::_1)
+        {
+            const char* PYTHON(getenv("PYTHON"));
+            ensure("Set $PYTHON to the Python interpreter", PYTHON);
+
+            NamedTempFile scriptfile("py", script);
+            LLProcessLauncher py;
+            py.setExecutable(PYTHON);
+            py.addArgument(scriptfile.getName());
+            if (! arg.empty())
+            {
+                py.addArgument(arg);
+            }
+            tweak(py);
+            ensure_equals(STRINGIZE("Couldn't launch " << desc << " script"), py.launch(), 0);
+            // One of the irritating things about LLProcessLauncher is that
+            // there's no API to wait for the child to terminate -- but given
+            // its use in our graphics-intensive interactive viewer, it's
+            // understandable.
+            while (py.isRunning())
+            {
+                sleep(1);
+            }
+        }
+
+        /**
+         * Run a Python script using LLProcessLauncher, expecting that it will
+         * write to the file passed as its sys.argv[1]. Retrieve that output.
+         *
+         * Until January 2012, LLProcessLauncher provided distressingly few
+         * mechanisms for a child process to communicate back to its caller --
+         * not even its return code. We've introduced a convention by which we
+         * create an empty temp file, pass the name of that file to our child
+         * as sys.argv[1] and expect the script to write its output to that
+         * file. This function implements the C++ (parent process) side of
+         * that convention.
+         *
+         * @param desc as for python()
+         * @param script as for python()
+         * @param tweak as for python()
+         */
+        template <typename CONTENT>
+        std::string python_out(const std::string& desc, const CONTENT& script,
+                               const boost::function<void (LLProcessLauncher&)> tweak=lambda::_1)
+        {
+            NamedTempFile out("out", ""); // placeholder
+            // pass name of this temporary file to the script
+            python(desc, script, out.getName(), tweak);
+            // assuming the script wrote a line to that file, read it
+            std::string output;
+            {
+                std::ifstream inf(out.getName().c_str());
+                ensure(STRINGIZE("No output from " << desc << " script"),
+                       std::getline(inf, output));
+                std::string more;
+                while (std::getline(inf, more))
+                {
+                    output += '\n' + more;
+                }
+            } // important to close inf BEFORE removing NamedTempFile
+            return output;
+        }
+
+        class NamedTempDir
+        {
+        public:
+            // Use python() function to create a temp directory: I've found
+            // nothing in either Boost.Filesystem or APR quite like Python's
+            // tempfile.mkdtemp().
+            // Special extra bonus: on Mac, mkdtemp() reports a pathname
+            // starting with /var/folders/something, whereas that's really a
+            // symlink to /private/var/folders/something. Have to use
+            // realpath() to compare properly.
+            NamedTempDir(llprocesslauncher_data* ths):
+                mThis(ths),
+                mPath(ths->python_out("mkdtemp()",
+                                      "import os.path, sys, tempfile\n"
+                                      "with open(sys.argv[1], 'w') as f:\n"
+                                      "    f.write(os.path.realpath(tempfile.mkdtemp()))\n"))
+            {}
+
+            ~NamedTempDir()
+            {
+                mThis->aprchk(apr_dir_remove(mPath.c_str(), gAPRPoolp));
+            }
+
+            std::string getName() const { return mPath; }
+
+        private:
+            llprocesslauncher_data* mThis;
+            std::string mPath;
+        };
+
         LLAPRPool pool;
     };
     typedef test_group<llprocesslauncher_data> llprocesslauncher_group;
@@ -349,4 +465,34 @@ namespace tut
             throw;
         }
     }
+
+    template<> template<>
+    void object::test<2>()
+    {
+        set_test_name("set/getExecutable()");
+        LLProcessLauncher child;
+        child.setExecutable("nonsense string");
+        ensure_equals("setExecutable() 0", child.getExecutable(), "nonsense string");
+        child.setExecutable("python");
+        ensure_equals("setExecutable() 1", child.getExecutable(), "python");
+    }
+
+    template<> template<>
+    void object::test<3>()
+    {
+        set_test_name("setWorkingDirectory()");
+        // We want to test setWorkingDirectory(). But what directory is
+        // guaranteed to exist on every machine, under every OS? Have to
+        // create one.
+        NamedTempDir tempdir(this);
+        std::string cwd(python_out("getcwd()",
+                                   "import os, sys\n"
+                                   "with open(sys.argv[1], 'w') as f:\n"
+                                   "    f.write(os.getcwd())\n",
+                                   // Before LLProcessLauncher::launch(), call setWorkingDirectory()
+                                   lambda::bind(&LLProcessLauncher::setWorkingDirectory,
+                                                lambda::_1,
+                                                tempdir.getName())));
+        ensure_equals("os.getcwd()", cwd, tempdir.getName());
+    }
 } // namespace tut
-- 
cgit v1.2.3


From 1fede65af23248293d4033b8f7557875b499e191 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 17 Jan 2012 16:05:10 -0800
Subject: EXP-1810 FIX Cannot resize Received items panel in Inventory window

---
 indra/llui/lllayoutstack.cpp                       | 34 +++++++++++++---------
 .../default/xui/en/floater_test_layout_stacks.xml  | 29 ++++--------------
 2 files changed, 27 insertions(+), 36 deletions(-)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 000f729e29..f7b34bbb38 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -39,8 +39,6 @@
 static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack");
 static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel");
 
-static const F32 MAX_FRACTIONAL_VALUE = 0.99999f;
-
 void LLLayoutStack::OrientationNames::declareValues()
 {
 	declare("horizontal", HORIZONTAL);
@@ -328,6 +326,7 @@ void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_
 	}
 
 	mNeedsLayout = true;
+	updateFractionalSizes();
 }
 
 
@@ -527,8 +526,8 @@ void LLLayoutStack::updateFractionalSizes()
 		if (panelp->mAutoResize)
 		{
 			F32 panel_resizable_dim = llmax(0.f, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim()));
-			panelp->mFractionalSize = llmin(MAX_FRACTIONAL_VALUE, (panel_resizable_dim == 0.f)
-																	? (1.f - MAX_FRACTIONAL_VALUE)
+			panelp->mFractionalSize = llmin(1.f, (panel_resizable_dim == 0.f)
+																	? 0.f
 																	: panel_resizable_dim / total_resizable_dim);
 			total_fractional_size += panelp->mFractionalSize;
 			// check for NaNs
@@ -714,7 +713,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 				F32 fractional_adjustment_factor = total_auto_resize_headroom / updated_auto_resize_headroom;
 				F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor,
 													0.f,
-													MAX_FRACTIONAL_VALUE);
+													1.f);
 				F32 fraction_delta = (new_fractional_size - panelp->mFractionalSize);
 				fraction_given_up -= fraction_delta;
 				fraction_remaining -= panelp->mFractionalSize;
@@ -731,7 +730,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 			{	// freeze new size as fraction
 				F32 new_fractional_size = (updated_auto_resize_headroom == 0.f)
 					? 1.f
-					: llmin(MAX_FRACTIONAL_VALUE, ((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom));
+					: llmin(1.f, ((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom));
 				fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
 				fraction_remaining -= panelp->mFractionalSize;
 				panelp->mFractionalSize = new_fractional_size;
@@ -747,11 +746,20 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 		case NEXT_PANEL:
 			if (panelp->mAutoResize)
 			{
-				F32 new_fractional_size = (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) 
-												/ updated_auto_resize_headroom;
-				fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
 				fraction_remaining -= panelp->mFractionalSize;
-				panelp->mFractionalSize = new_fractional_size;
+				if (fraction_given_up != 0.f)
+				{
+					panelp->mFractionalSize += fraction_given_up;
+					fraction_given_up = 0.f;
+				}
+				else
+				{
+					F32 new_fractional_size = llmin(1.f, 
+													(F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) 
+														/ updated_auto_resize_headroom);
+					fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
+					panelp->mFractionalSize = new_fractional_size;
+				}
 			}
 			else
 			{
@@ -788,9 +796,9 @@ void LLLayoutStack::updateResizeBarLimits()
 		}
 
 		// toggle resize bars based on panel visibility, resizability, etc
-		if (visible_panelp->mUserResize 
-			&& previous_visible_panelp 
-			&& previous_visible_panelp->mUserResize)
+		if (previous_visible_panelp 
+			&& (visible_panelp->mUserResize 
+				|| previous_visible_panelp->mUserResize))
 		{
 			visible_panelp->mResizeBar->setVisible(TRUE);
 			visible_panelp->mResizeBar->setResizeLimits(visible_panelp->getRelevantMinDim(), 
diff --git a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
index dbe75f8b53..f95f21e63a 100644
--- a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
@@ -26,31 +26,14 @@
                   background_visible="true">
       <text follows="top|left|right" halign="center" text_color="white">flex</text>
     </layout_panel>
-    <layout_panel name="fixed"
-                auto_resize="false"
-                  user_resize="true"
-                height="50"
-                  min_height="0"
-                bg_alpha_color="green"
-                background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
-    </layout_panel>
-    <layout_panel name="fixed"
-                auto_resize="false"
+    <layout_panel name="flex"
+                  auto_resize="true"
                   user_resize="true"
-                height="50"
+                  bg_alpha_color="blue"
+                  height="11"
                   min_height="0"
-                bg_alpha_color="green"
-                background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
-    </layout_panel>
-    <layout_panel name="fixed"
-                auto_resize="false"
-                  user_resize="true"
-                height="50"
-                bg_alpha_color="green"
-                background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
     </layout_panel>
   </layout_stack>
   <layout_stack name="test_stack"
-- 
cgit v1.2.3


From 1eae229cf2470bee506d72ddecbd1305f305670b Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 17 Jan 2012 16:28:12 -0800
Subject: EXP-1809 FIX Buttons in right toolbar clipped and can be out of
 position

---
 indra/llui/lllayoutstack.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index f7b34bbb38..a309e3ff97 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -167,6 +167,11 @@ void LLLayoutPanel::reshape( S32 width, S32 height, BOOL called_from_parent /*=
 	if (!mIgnoreReshape && !mAutoResize)
 	{
 		mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height;
+		LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent());
+		if (stackp)
+		{
+			stackp->mNeedsLayout = true;
+		}
 	}
 	LLPanel::reshape(width, height, called_from_parent);
 }
-- 
cgit v1.2.3


From a6c638d882919b58186a6859644d61cdb5e45a7b Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 17 Jan 2012 17:45:52 -0700
Subject: more exception handlings for llcurl fixes.

---
 indra/llmessage/llpumpio.h      |  1 +
 indra/llmessage/llsdrpcclient.h | 25 ++++++++++++++++++-------
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h
index e405124403..d2c5d37571 100644
--- a/indra/llmessage/llpumpio.h
+++ b/indra/llmessage/llpumpio.h
@@ -111,6 +111,7 @@ public:
 	 * @param chain The pipes for the chain
 	 * @param timeout The number of seconds in the future to
 	 * expire. Pass in 0.0f to never expire.
+	 * @param has_curl_request The chain contains LLURLRequest if true.
 	 * @return Returns true if anything was added to the pump.
 	 */
 	bool addChain(const chain_t& chain, F32 timeout, bool has_curl_request = false);
diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h
index 235077179e..0cecf4f688 100644
--- a/indra/llmessage/llsdrpcclient.h
+++ b/indra/llmessage/llsdrpcclient.h
@@ -239,12 +239,17 @@ public:
 	LLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
 	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
 	{
-		llerrs << "Can not call this." << llendl ;
-
 		lldebugs << "LLSDRPCClientFactory::build" << llendl;
-		LLIOPipe::ptr_t service(new Client);
-		chain.push_back(service);
 		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
+		if(!http->isValid())
+		{
+			llwarns << "Creating LLURLRequest failed." << llendl ;
+			delete http;
+			return false;
+		}
+
+		LLIOPipe::ptr_t service(new Client);
+		chain.push_back(service);		
 		LLIOPipe::ptr_t http_pipe(http);
 		http->addHeader("Content-Type: text/llsd");
 		if(mURL.empty())
@@ -284,11 +289,17 @@ public:
 	LLXMLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
 	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
 	{
-		llerrs << "who calls this?" << llendl ;
 		lldebugs << "LLXMLSDRPCClientFactory::build" << llendl;
-		LLIOPipe::ptr_t service(new Client);
-		chain.push_back(service);
+
 		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
+		if(!http->isValid())
+		{
+			llwarns << "Creating LLURLRequest failed." << llendl ;
+			delete http;
+			return false ;
+		}
+		LLIOPipe::ptr_t service(new Client);
+		chain.push_back(service);		
 		LLIOPipe::ptr_t http_pipe(http);
 		http->addHeader("Content-Type: text/xml");
 		if(mURL.empty())
-- 
cgit v1.2.3


From 51b26cab9ad8dc54277c6158ad40afdf3ed0e6d0 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 17 Jan 2012 20:30:46 -0500
Subject: Any proper RAII class must either handle copying or be noncopyable.
 NamedTempFile makes no attempt to deal with copying, therefore make it
 noncopyable.

---
 indra/test/namedtempfile.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/indra/test/namedtempfile.h b/indra/test/namedtempfile.h
index 7ffb2836cc..aa7058b111 100644
--- a/indra/test/namedtempfile.h
+++ b/indra/test/namedtempfile.h
@@ -16,8 +16,9 @@
 #include "apr_file_io.h"
 #include <string>
 #include <boost/function.hpp>
-#include "boost/lambda/lambda.hpp"
-#include "boost/lambda/bind.hpp"
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+#include <boost/noncopyable.hpp>
 #include <iostream>
 #include <sstream>
 
@@ -25,7 +26,7 @@
  * Create a text file with specified content "somewhere in the
  * filesystem," cleaning up when it goes out of scope.
  */
-class NamedTempFile
+class NamedTempFile: public boost::noncopyable
 {
 public:
     NamedTempFile(const std::string& pfx, const std::string& content, apr_pool_t* pool=gAPRPoolp):
-- 
cgit v1.2.3


From 23773d792d4387a93db6e66bddcfe2035164d7be Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 17 Jan 2012 17:36:59 -0800
Subject: EXP-1811 FIX Login progress floater has smaller than expected size
 made minimum size reflect default size for 1024 width window of old layout
 stack no way to match behavior

---
 indra/newview/llfloateruipreview.cpp               |  6 +++--
 .../skins/default/xui/en/panel_progress.xml        | 30 +++++++++++-----------
 2 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 4c9c4cb154..d741b5b133 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -915,14 +915,16 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
 		{
 			panel->buildFromFile(path);										// build it
 			LLRect new_size = panel->getRect();								// get its rectangle
-			panel->setOrigin(0,0);											// reset its origin point so it's not offset by -left or other XUI attributes
+			panel->setOrigin(2,2);											// reset its origin point so it's not offset by -left or other XUI attributes
 			(*floaterp)->setTitle(path);									// use the file name as its title, since panels have no guaranteed meaningful name attribute
 			panel->setUseBoundingRect(TRUE);								// enable the use of its outer bounding rect (normally disabled because it's O(n) on the number of sub-elements)
 			panel->updateBoundingRect();									// update bounding rect
 			LLRect bounding_rect = panel->getBoundingRect();				// get the bounding rect
 			LLRect new_rect = panel->getRect();								// get the panel's rect
 			new_rect.unionWith(bounding_rect);								// union them to make sure we get the biggest one possible
-			(*floaterp)->reshape(new_rect.getWidth(), new_rect.getHeight() + floater_header_size);	// reshape floater to match the union rect's dimensions
+			LLRect floater_rect = new_rect;
+			floater_rect.stretch(4, 4);
+			(*floaterp)->reshape(floater_rect.getWidth(), floater_rect.getHeight() + floater_header_size);	// reshape floater to match the union rect's dimensions
 			panel->reshape(new_rect.getWidth(), new_rect.getHeight());		// reshape panel to match the union rect's dimensions as well (both are needed)
 			(*floaterp)->addChild(panel);					// add panel as child
 			(*floaterp)->openFloater();						// open floater (needed?)
diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml
index 7275e8d89b..860caf2d21 100644
--- a/indra/newview/skins/default/xui/en/panel_progress.xml
+++ b/indra/newview/skins/default/xui/en/panel_progress.xml
@@ -12,43 +12,43 @@
      height="768"
      layout="topleft"
      left="0"
-     name="stack1"
+     name="horizontal_centering"
      orientation="horizontal"
      top="0"
      width="1024">
         <layout_panel
          layout="topleft"
          min_width="10"
-         name="panel1"
+         name="left"
          width="150" />
         <layout_panel
          height="768"
          layout="topleft"
-         min_width="640"
-         name="panel2"
-         width="640">
+         min_width="670"
+         name="center"
+         width="670">
             <layout_stack
              follows="left|right|top|bottom"
              height="768"
              layout="topleft"
              left="0"
              orientation="vertical" 
-             name="stack2"
+             name="vertical_centering"
              top="0"
-             width="640">
+             width="670">
                 <layout_panel
                  height="200"
                  layout="topleft"
                  min_height="10"
                  name="panel3"
-                 width="640" />
+                 width="670" />
                 <layout_panel
                  auto_resize="false"
                  height="250"
                  layout="topleft"
                  min_height="250"
                  name="panel4"
-                 width="640">
+                 width="670">
                     <icon
                      color="LoginProgressBoxCenterColor"
                      follows="left|right|bottom|top"
@@ -57,7 +57,7 @@
                      layout="topleft"
                      left="0"
                      top="0"
-                     width="640" />
+                     width="670" />
                     <text
                      follows="left|right|top"
                      font="SansSerifHuge"
@@ -69,7 +69,7 @@
                      name="title_text"
                      text_color="LoginProgressBoxTextColor"
                      top_delta="50"
-                     width="593" />
+                     right="-47"/>
                     <text
                      follows="left|right|top"
                      font="SansSerif"
@@ -81,7 +81,7 @@
                      name="progress_text"
                      text_color="LoginProgressBoxTextColor"
                      top_pad="5"
-                     width="593"
+                     right="-47"
                      word_wrap="true"/>
                     <progress_bar
                      bottom="115"
@@ -104,7 +104,7 @@
                      name="message_text"
                      text_color="LoginProgressBoxTextColor"
                      top="145"
-                     width="550"
+                     right="-90"
                      word_wrap="true"/>
                 </layout_panel>
                 <layout_panel
@@ -112,13 +112,13 @@
                  layout="topleft"
                  min_width="10"
                  name="panel5"
-                 width="640" />
+                 width="670" />
             </layout_stack>
         </layout_panel>
         <layout_panel
          layout="topleft"
          min_width="10"
-         name="panel6"
+         name="right"
          width="150" />
     </layout_stack>
     <button
-- 
cgit v1.2.3


From 2ae9f921f2e1d6bd10e4c334a19312761a914046 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 17 Jan 2012 20:44:26 -0500
Subject: Refactor llprocesslauncher_test.cpp for better code reuse. Instead of
 free python() and python_out() functions containing a local temporary
 LLProcessLauncher instance, with a 'tweak' callback param to "do stuff" to
 that inaccessible object, change to a PythonProcessLauncher class that sets
 up a (public) LLProcessLauncher member, then allows you to run() or run() and
 then readfile() the output. Now you can construct an instance and tweak to
 your heart's content -- without funky callback syntax -- before running the
 script. Move all such helpers from TUT fixture struct to namespace scope.
 While fixture-struct methods can freely call one another, introducing a
 nested class gets awkward: constructor must explicitly require and bind a
 fixture-struct pointer or reference. Namespace scope solves this.
 (Truthfully, I only put them in the fixture struct originally because I
 thought it necessary for calling ensure() et al. But ensure() and friends are
 free functions; need only qualify them with tut:: namespace.)

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 282 +++++++++++++-----------
 1 file changed, 155 insertions(+), 127 deletions(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index aebd280c2e..310271e465 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -12,7 +12,6 @@
 // Precompiled header
 #include "linden_common.h"
 // associated header
-#define WIN32_LEAN_AND_MEAN
 #include "llprocesslauncher.h"
 // STL headers
 #include <vector>
@@ -24,8 +23,8 @@
 #include "apr_thread_proc.h"
 #include <boost/foreach.hpp>
 #include <boost/function.hpp>
-#include <boost/lambda/lambda.hpp>
-#include <boost/lambda/bind.hpp>
+//#include <boost/lambda/lambda.hpp>
+//#include <boost/lambda/bind.hpp>
 // other Linden headers
 #include "../test/lltut.h"
 #include "../test/manageapr.h"
@@ -40,138 +39,169 @@
 #include <sys/wait.h>
 #endif
 
-namespace lambda = boost::lambda;
+//namespace lambda = boost::lambda;
 
 // static instance of this manages APR init/cleanup
 static ManageAPR manager;
 
+/*****************************************************************************
+*   Helpers
+*****************************************************************************/
+
 #define ensure_equals_(left, right) \
         ensure_equals(STRINGIZE(#left << " != " << #right), (left), (right))
+
 #define aprchk(expr) aprchk_(#expr, (expr))
+static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
+{
+    tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << manager.strerror(rv)),
+                       rv, expected);
+}
 
-/*****************************************************************************
-*   TUT
-*****************************************************************************/
-namespace tut
+/**
+ * Read specified file using std::getline(). It is assumed to be an error if
+ * the file is empty: don't use this function if that's an acceptable case.
+ * Last line will not end with '\n'; this is to facilitate the usual case of
+ * string compares with a single line of output.
+ * @param pathname The file to read.
+ * @param desc Optional description of the file for error message;
+ * defaults to "in <pathname>"
+ */
+static std::string readfile(const std::string& pathname, const std::string& desc="")
 {
-    struct llprocesslauncher_data
+    std::string use_desc(desc);
+    if (use_desc.empty())
     {
-        void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
-        {
-            ensure_equals(STRINGIZE(call << " => " << rv << ": " << manager.strerror(rv)),
-                          rv, expected);
-        }
+        use_desc = STRINGIZE("in " << pathname);
+    }
+    std::ifstream inf(pathname.c_str());
+    std::string output;
+    tut::ensure(STRINGIZE("No output " << use_desc), std::getline(inf, output));
+    std::string more;
+    while (std::getline(inf, more))
+    {
+        output += '\n' + more;
+    }
+    return output;
+}
 
-        /**
-         * Run a Python script using LLProcessLauncher.
-         * @param desc Arbitrary description for error messages
-         * @param script Python script, any form acceptable to NamedTempFile,
-         * typically either a std::string or an expression of the form
-         * (lambda::_1 << "script content with " << variable_data)
-         * @param arg If specified, will be passed to script as its
-         * sys.argv[1]
-         * @param tweak "Do something" to LLProcessLauncher object before
-         * calling its launch() method. This program is to test
-         * LLProcessLauncher, but many such tests are "just like" this
-         * python() function but for one or two extra method calls before
-         * launch(). This avoids us having to clone & edit this function for
-         * such tests.
-         */
-        template <typename CONTENT>
-        void python(const std::string& desc, const CONTENT& script, const std::string& arg="",
-                    const boost::function<void (LLProcessLauncher&)> tweak=lambda::_1)
-        {
-            const char* PYTHON(getenv("PYTHON"));
-            ensure("Set $PYTHON to the Python interpreter", PYTHON);
-
-            NamedTempFile scriptfile("py", script);
-            LLProcessLauncher py;
-            py.setExecutable(PYTHON);
-            py.addArgument(scriptfile.getName());
-            if (! arg.empty())
-            {
-                py.addArgument(arg);
-            }
-            tweak(py);
-            ensure_equals(STRINGIZE("Couldn't launch " << desc << " script"), py.launch(), 0);
-            // One of the irritating things about LLProcessLauncher is that
-            // there's no API to wait for the child to terminate -- but given
-            // its use in our graphics-intensive interactive viewer, it's
-            // understandable.
-            while (py.isRunning())
-            {
-                sleep(1);
-            }
-        }
+/**
+ * Construct an LLProcessLauncher to run a Python script.
+ */
+struct PythonProcessLauncher
+{
+    /**
+     * @param desc Arbitrary description for error messages
+     * @param script Python script, any form acceptable to NamedTempFile,
+     * typically either a std::string or an expression of the form
+     * (lambda::_1 << "script content with " << variable_data)
+     */
+    template <typename CONTENT>
+    PythonProcessLauncher(const std::string& desc, const CONTENT& script):
+        mDesc(desc),
+        mScript("py", script)
+    {
+        const char* PYTHON(getenv("PYTHON"));
+        tut::ensure("Set $PYTHON to the Python interpreter", PYTHON);
+
+        mPy.setExecutable(PYTHON);
+        mPy.addArgument(mScript.getName());
+    }
 
-        /**
-         * Run a Python script using LLProcessLauncher, expecting that it will
-         * write to the file passed as its sys.argv[1]. Retrieve that output.
-         *
-         * Until January 2012, LLProcessLauncher provided distressingly few
-         * mechanisms for a child process to communicate back to its caller --
-         * not even its return code. We've introduced a convention by which we
-         * create an empty temp file, pass the name of that file to our child
-         * as sys.argv[1] and expect the script to write its output to that
-         * file. This function implements the C++ (parent process) side of
-         * that convention.
-         *
-         * @param desc as for python()
-         * @param script as for python()
-         * @param tweak as for python()
-         */
-        template <typename CONTENT>
-        std::string python_out(const std::string& desc, const CONTENT& script,
-                               const boost::function<void (LLProcessLauncher&)> tweak=lambda::_1)
+    /// Run Python script and wait for it to complete.
+    void run()
+    {
+        tut::ensure_equals(STRINGIZE("Couldn't launch " << mDesc << " script"),
+                           mPy.launch(), 0);
+        // One of the irritating things about LLProcessLauncher is that
+        // there's no API to wait for the child to terminate -- but given
+        // its use in our graphics-intensive interactive viewer, it's
+        // understandable.
+        while (mPy.isRunning())
         {
-            NamedTempFile out("out", ""); // placeholder
-            // pass name of this temporary file to the script
-            python(desc, script, out.getName(), tweak);
-            // assuming the script wrote a line to that file, read it
-            std::string output;
-            {
-                std::ifstream inf(out.getName().c_str());
-                ensure(STRINGIZE("No output from " << desc << " script"),
-                       std::getline(inf, output));
-                std::string more;
-                while (std::getline(inf, more))
-                {
-                    output += '\n' + more;
-                }
-            } // important to close inf BEFORE removing NamedTempFile
-            return output;
+            sleep(1);
         }
+    }
 
-        class NamedTempDir
-        {
-        public:
-            // Use python() function to create a temp directory: I've found
-            // nothing in either Boost.Filesystem or APR quite like Python's
-            // tempfile.mkdtemp().
-            // Special extra bonus: on Mac, mkdtemp() reports a pathname
-            // starting with /var/folders/something, whereas that's really a
-            // symlink to /private/var/folders/something. Have to use
-            // realpath() to compare properly.
-            NamedTempDir(llprocesslauncher_data* ths):
-                mThis(ths),
-                mPath(ths->python_out("mkdtemp()",
-                                      "import os.path, sys, tempfile\n"
-                                      "with open(sys.argv[1], 'w') as f:\n"
-                                      "    f.write(os.path.realpath(tempfile.mkdtemp()))\n"))
-            {}
-
-            ~NamedTempDir()
-            {
-                mThis->aprchk(apr_dir_remove(mPath.c_str(), gAPRPoolp));
-            }
+    /**
+     * Run a Python script using LLProcessLauncher, expecting that it will
+     * write to the file passed as its sys.argv[1]. Retrieve that output.
+     *
+     * Until January 2012, LLProcessLauncher provided distressingly few
+     * mechanisms for a child process to communicate back to its caller --
+     * not even its return code. We've introduced a convention by which we
+     * create an empty temp file, pass the name of that file to our child
+     * as sys.argv[1] and expect the script to write its output to that
+     * file. This function implements the C++ (parent process) side of
+     * that convention.
+     */
+    std::string run_read()
+    {
+        NamedTempFile out("out", ""); // placeholder
+        // pass name of this temporary file to the script
+        mPy.addArgument(out.getName());
+        run();
+        // assuming the script wrote to that file, read it
+        return readfile(out.getName(), STRINGIZE("from " << mDesc << " script"));
+    }
+
+    LLProcessLauncher mPy;
+    std::string mDesc;
+    NamedTempFile mScript;
+};
+
+/// convenience function for PythonProcessLauncher::run()
+template <typename CONTENT>
+static void python(const std::string& desc, const CONTENT& script)
+{
+    PythonProcessLauncher py(desc, script);
+    py.run();
+}
+
+/// convenience function for PythonProcessLauncher::run_read()
+template <typename CONTENT>
+static std::string python_out(const std::string& desc, const CONTENT& script)
+{
+    PythonProcessLauncher py(desc, script);
+    return py.run_read();
+}
+
+/// Create a temporary directory and clean it up later.
+class NamedTempDir: public boost::noncopyable
+{
+public:
+    // Use python() function to create a temp directory: I've found
+    // nothing in either Boost.Filesystem or APR quite like Python's
+    // tempfile.mkdtemp().
+    // Special extra bonus: on Mac, mkdtemp() reports a pathname
+    // starting with /var/folders/something, whereas that's really a
+    // symlink to /private/var/folders/something. Have to use
+    // realpath() to compare properly.
+    NamedTempDir():
+        mPath(python_out("mkdtemp()",
+                         "import os.path, sys, tempfile\n"
+                         "with open(sys.argv[1], 'w') as f:\n"
+                         "    f.write(os.path.realpath(tempfile.mkdtemp()))\n"))
+    {}
+
+    ~NamedTempDir()
+    {
+        aprchk(apr_dir_remove(mPath.c_str(), gAPRPoolp));
+    }
 
-            std::string getName() const { return mPath; }
+    std::string getName() const { return mPath; }
 
-        private:
-            llprocesslauncher_data* mThis;
-            std::string mPath;
-        };
+private:
+    std::string mPath;
+};
 
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct llprocesslauncher_data
+    {
         LLAPRPool pool;
     };
     typedef test_group<llprocesslauncher_data> llprocesslauncher_group;
@@ -484,15 +514,13 @@ namespace tut
         // We want to test setWorkingDirectory(). But what directory is
         // guaranteed to exist on every machine, under every OS? Have to
         // create one.
-        NamedTempDir tempdir(this);
-        std::string cwd(python_out("getcwd()",
-                                   "import os, sys\n"
-                                   "with open(sys.argv[1], 'w') as f:\n"
-                                   "    f.write(os.getcwd())\n",
-                                   // Before LLProcessLauncher::launch(), call setWorkingDirectory()
-                                   lambda::bind(&LLProcessLauncher::setWorkingDirectory,
-                                                lambda::_1,
-                                                tempdir.getName())));
-        ensure_equals("os.getcwd()", cwd, tempdir.getName());
+        NamedTempDir tempdir;
+        PythonProcessLauncher py("getcwd()",
+                                 "import os, sys\n"
+                                 "with open(sys.argv[1], 'w') as f:\n"
+                                 "    f.write(os.getcwd())\n");
+        // Before running, call setWorkingDirectory()
+        py.mPy.setWorkingDirectory(tempdir.getName());
+        ensure_equals("os.getcwd()", py.run_read(), tempdir.getName());
     }
 } // namespace tut
-- 
cgit v1.2.3


From 4bfd84d3be8d33bc6eb0dab22d2b3034de0800c9 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 17 Jan 2012 21:40:41 -0500
Subject: Add tests for child-process args management and for kill() method.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 80 ++++++++++++++++++++++++-
 1 file changed, 79 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 310271e465..4f6a6ed922 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -23,6 +23,8 @@
 #include "apr_thread_proc.h"
 #include <boost/foreach.hpp>
 #include <boost/function.hpp>
+#include <boost/algorithm/string/find_iterator.hpp>
+#include <boost/algorithm/string/finder.hpp>
 //#include <boost/lambda/lambda.hpp>
 //#include <boost/lambda/bind.hpp>
 // other Linden headers
@@ -513,7 +515,7 @@ namespace tut
         set_test_name("setWorkingDirectory()");
         // We want to test setWorkingDirectory(). But what directory is
         // guaranteed to exist on every machine, under every OS? Have to
-        // create one.
+        // create one. Naturally, ensure we clean it up when done.
         NamedTempDir tempdir;
         PythonProcessLauncher py("getcwd()",
                                  "import os, sys\n"
@@ -523,4 +525,80 @@ namespace tut
         py.mPy.setWorkingDirectory(tempdir.getName());
         ensure_equals("os.getcwd()", py.run_read(), tempdir.getName());
     }
+
+    template<> template<>
+    void object::test<4>()
+    {
+        set_test_name("clearArguments()");
+        PythonProcessLauncher py("args",
+                                 "import sys\n"
+                                 // note nonstandard output-file arg!
+                                 "with open(sys.argv[3], 'w') as f:\n"
+                                 "    for arg in sys.argv[1:]:\n"
+                                 "        print >>f, arg\n");
+        // We expect that PythonProcessLauncher has already called
+        // addArgument() with the name of its own NamedTempFile. But let's
+        // change it up.
+        py.mPy.clearArguments();
+        // re-add script pathname
+        py.mPy.addArgument(py.mScript.getName()); // sys.argv[0]
+        py.mPy.addArgument("first arg");          // sys.argv[1]
+        py.mPy.addArgument("second arg");         // sys.argv[2]
+        // run_read() calls addArgument() one more time, hence [3]
+        std::string output(py.run_read());
+        boost::split_iterator<std::string::const_iterator>
+            li(output, boost::first_finder("\n")), lend;
+        ensure("didn't get first arg", li != lend);
+        std::string arg(li->begin(), li->end());
+        ensure_equals(arg, "first arg");
+        ++li;
+        ensure("didn't get second arg", li != lend);
+        arg.assign(li->begin(), li->end());
+        ensure_equals(arg, "second arg");
+        ++li;
+        ensure("didn't get output filename?!", li != lend);
+        arg.assign(li->begin(), li->end());
+        ensure("output filename empty?!", ! arg.empty());
+        ++li;
+        ensure("too many args", li == lend);
+    }
+
+    template<> template<>
+    void object::test<5>()
+    {
+        set_test_name("kill()");
+        PythonProcessLauncher py("kill()",
+                                 "import sys, time\n"
+                                 "with open(sys.argv[1], 'w') as f:\n"
+                                 "    f.write('ok')\n"
+                                 "# now sleep; expect caller to kill\n"
+                                 "time.sleep(120)\n"
+                                 "# if caller hasn't managed to kill by now, bad\n"
+                                 "with open(sys.argv[1], 'w') as f:\n"
+                                 "    f.write('bad')\n");
+        NamedTempFile out("out", "not started");
+        py.mPy.addArgument(out.getName());
+        ensure_equals("couldn't launch kill() script", py.mPy.launch(), 0);
+        // Wait for the script to wake up and do its first write
+        int i = 0, timeout = 60;
+        for ( ; i < timeout; ++i)
+        {
+            sleep(1);
+            if (readfile(out.getName(), "from kill() script") == "ok")
+                break;
+        }
+        // If we broke this loop because of the counter, something's wrong
+        ensure("script never started", i < timeout);
+        // script has performed its first write and should now be sleeping.
+        py.mPy.kill();
+        // wait for the script to terminate... one way or another.
+        while (py.mPy.isRunning())
+        {
+            sleep(1);
+        }
+        // If kill() failed, the script would have woken up on its own and
+        // overwritten the file with 'bad'. But if kill() succeeded, it should
+        // not have had that chance.
+        ensure_equals("kill() script output", readfile(out.getName()), "ok");
+    }
 } // namespace tut
-- 
cgit v1.2.3


From 25c21c3761d871fa7927e2a5656ed18100084454 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 17 Jan 2012 22:56:28 -0700
Subject: add more exception handlings for llcurl fix.

---
 indra/llmessage/llcurl.cpp       | 7 ++++++-
 indra/llmessage/llurlrequest.cpp | 6 ++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 277c274f52..5edf0dc8c0 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -1036,7 +1036,12 @@ LLCurl::Easy* LLCurlRequest::allocEasy()
 	{
 		addMulti();
 	}
-	llassert_always(mActiveMulti);
+	if(!mActiveMulti)
+	{
+		return NULL ;
+	}
+
+	//llassert_always(mActiveMulti);
 	++mActiveRequestCount;
 	LLCurl::Easy* easy = mActiveMulti->allocEasy();
 	return easy;
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index f02c636838..a16f5c7bf0 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -459,6 +459,12 @@ void LLURLRequest::initialize()
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	mState = STATE_INITIALIZED;
 	mDetail = new LLURLRequestDetail;
+
+	if(!isValid())
+	{
+		return ;
+	}
+
 	mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
 	mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
 	mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
-- 
cgit v1.2.3


From 06f9dbd8db9895f81d7bd325d8cf616f68533396 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 18 Jan 2012 01:09:50 -0500
Subject: Introduce static LLProcessLauncher::isRunning(ll_pid_t) method.
 typedef LLProcessLauncher::ll_pid_t to be HANDLE on Windows, pid_t elsewhere.
 Then we can define getProcessID() returning ll_pid_t on all platforms,
 retaining getProcessHandle() for hypothetical existing consumers... of which
 there are none in practice. This lets us define isRunning(ll_pid_t) to
 encapsulate the platform-specific logic to actually check on a running child
 process, turning non-static isRunning() into a fairly trivial wrapper.

---
 indra/llcommon/llprocesslauncher.cpp | 49 +++++++++++++++++++++++-------------
 indra/llcommon/llprocesslauncher.h   | 19 ++++++++++++--
 2 files changed, 48 insertions(+), 20 deletions(-)

diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp
index 25d64e9e28..e1af49c2fb 100644
--- a/indra/llcommon/llprocesslauncher.cpp
+++ b/indra/llcommon/llprocesslauncher.cpp
@@ -143,18 +143,25 @@ int LLProcessLauncher::launch(void)
 
 bool LLProcessLauncher::isRunning(void)
 {
-	if(mProcessHandle != 0)		
+	mProcessHandle = isRunning(mProcessHandle);
+	return (mProcessHandle != 0);
+}
+
+LLProcessLauncher::ll_pid_t LLProcessLauncher::isRunning(ll_pid_t handle)
+{
+	if (! handle)
+		return 0;
+
+	DWORD waitresult = WaitForSingleObject(handle, 0);
+	if(waitresult == WAIT_OBJECT_0)
 	{
-		DWORD waitresult = WaitForSingleObject(mProcessHandle, 0);
-		if(waitresult == WAIT_OBJECT_0)
-		{
-			// the process has completed.
-			mProcessHandle = 0;
-		}			
+		// the process has completed.
+		return 0;
 	}
 
-	return (mProcessHandle != 0);
+	return handle;
 }
+
 bool LLProcessLauncher::kill(void)
 {
 	bool result = true;
@@ -293,19 +300,25 @@ int LLProcessLauncher::launch(void)
 
 bool LLProcessLauncher::isRunning(void)
 {
-	if(mProcessID != 0)
-	{
-		// Check whether the process has exited, and reap it if it has.
-		if(reap_pid(mProcessID))
-		{
-			// the process has exited.
-			mProcessID = 0;
-		}
-	}
-	
+	mProcessID = isRunning(mProcessID);
 	return (mProcessID != 0);
 }
 
+LLProcessLauncher::ll_pid_t LLProcessLauncher::isRunning(ll_pid_t pid)
+{
+    if (! pid)
+        return 0;
+
+    // Check whether the process has exited, and reap it if it has.
+    if(reap_pid(pid))
+    {
+        // the process has exited.
+        return 0;
+    }
+
+    return pid;
+}
+
 bool LLProcessLauncher::kill(void)
 {
 	bool result = true;
diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h
index 1daa980c58..63193abd8f 100644
--- a/indra/llcommon/llprocesslauncher.h
+++ b/indra/llcommon/llprocesslauncher.h
@@ -54,6 +54,8 @@ public:
 	void addArgument(const std::string &arg);
 		
 	int launch(void);
+	// isRunning isn't const because, if child isn't running, it clears stored
+	// process ID
 	bool isRunning(void);
 	
 	// Attempt to kill the process -- returns true if the process is no longer running when it returns.
@@ -72,10 +74,23 @@ public:
 	// Accessors for platform-specific process ID
 #if LL_WINDOWS
 	// (Windows flavor unused as of 2012-01-12)
-	HANDLE getProcessHandle() { return mProcessHandle; };
+	typedef HANDLE ll_pid_t;
+	HANDLE getProcessHandle() const { return mProcessHandle; }
+	ll_pid_t getProcessID() const { return mProcessHandle; }
 #else
-	pid_t getProcessID() { return mProcessID; };
+	typedef pid_t ll_pid_t;
+	ll_pid_t getProcessID() const { return mProcessID; };
 #endif	
+	/**
+	 * Test if a process (ll_pid_t obtained from getProcessID()) is still
+	 * running. Return is same nonzero ll_pid_t value if still running, else
+	 * zero, so you can test it like a bool. But if you want to update a
+	 * stored variable as a side effect, you can write code like this:
+	 * @code
+	 * childpid = LLProcessLauncher::isRunning(childpid);
+	 * @endcode
+	 */
+	static ll_pid_t isRunning(ll_pid_t);
 	
 private:
 	std::string mExecutable;
-- 
cgit v1.2.3


From ff4addd1b427344c6064734bdb59952e78f759fd Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 18 Jan 2012 01:10:52 -0500
Subject: Add tests for implicit-kill-on-destroy, also orphan() method.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 110 +++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 4f6a6ed922..7c0f0eaa84 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -566,7 +566,7 @@ namespace tut
     template<> template<>
     void object::test<5>()
     {
-        set_test_name("kill()");
+        set_test_name("explicit kill()");
         PythonProcessLauncher py("kill()",
                                  "import sys, time\n"
                                  "with open(sys.argv[1], 'w') as f:\n"
@@ -601,4 +601,112 @@ namespace tut
         // not have had that chance.
         ensure_equals("kill() script output", readfile(out.getName()), "ok");
     }
+
+    template<> template<>
+    void object::test<6>()
+    {
+        set_test_name("implicit kill()");
+        NamedTempFile out("out", "not started");
+        LLProcessLauncher::ll_pid_t pid(0);
+        {
+            PythonProcessLauncher py("kill()",
+                                     "import sys, time\n"
+                                     "with open(sys.argv[1], 'w') as f:\n"
+                                     "    f.write('ok')\n"
+                                     "# now sleep; expect caller to kill\n"
+                                     "time.sleep(120)\n"
+                                     "# if caller hasn't managed to kill by now, bad\n"
+                                     "with open(sys.argv[1], 'w') as f:\n"
+                                     "    f.write('bad')\n");
+            py.mPy.addArgument(out.getName());
+            ensure_equals("couldn't launch kill() script", py.mPy.launch(), 0);
+            // Capture ll_pid_t for later
+            pid = py.mPy.getProcessID();
+            // Wait for the script to wake up and do its first write
+            int i = 0, timeout = 60;
+            for ( ; i < timeout; ++i)
+            {
+                sleep(1);
+                if (readfile(out.getName(), "from kill() script") == "ok")
+                    break;
+            }
+            // If we broke this loop because of the counter, something's wrong
+            ensure("script never started", i < timeout);
+            // Script has performed its first write and should now be sleeping.
+            // Destroy the LLProcessLauncher, which should kill the child.
+        }
+        // wait for the script to terminate... one way or another.
+        while (LLProcessLauncher::isRunning(pid))
+        {
+            sleep(1);
+        }
+        // If kill() failed, the script would have woken up on its own and
+        // overwritten the file with 'bad'. But if kill() succeeded, it should
+        // not have had that chance.
+        ensure_equals("kill() script output", readfile(out.getName()), "ok");
+    }
+
+    template<> template<>
+    void object::test<7>()
+    {
+        set_test_name("orphan()");
+        NamedTempFile from("from", "not started");
+        NamedTempFile to("to", "");
+        LLProcessLauncher::ll_pid_t pid(0);
+        {
+            PythonProcessLauncher py("orphan()",
+                                     "import sys, time\n"
+                                     "with open(sys.argv[1], 'w') as f:\n"
+                                     "    f.write('ok')\n"
+                                     "# wait for 'go' from test program\n"
+                                     "for i in xrange(60):\n"
+                                     "    time.sleep(1)\n"
+                                     "    with open(sys.argv[2]) as f:\n"
+                                     "        go = f.read()\n"
+                                     "    if go == 'go':\n"
+                                     "        break\n"
+                                     "else:\n"
+                                     "    with open(sys.argv[1], 'w') as f:\n"
+                                     "        f.write('never saw go')\n"
+                                     "    sys.exit(1)\n"
+                                     "# okay, saw 'go', write 'ack'\n"
+                                     "with open(sys.argv[1], 'w') as f:\n"
+                                     "    f.write('ack')\n");
+            py.mPy.addArgument(from.getName());
+            py.mPy.addArgument(to.getName());
+            ensure_equals("couldn't launch kill() script", py.mPy.launch(), 0);
+            // Capture ll_pid_t for later
+            pid = py.mPy.getProcessID();
+            // Wait for the script to wake up and do its first write
+            int i = 0, timeout = 60;
+            for ( ; i < timeout; ++i)
+            {
+                sleep(1);
+                if (readfile(from.getName(), "from orphan() script") == "ok")
+                    break;
+            }
+            // If we broke this loop because of the counter, something's wrong
+            ensure("script never started", i < timeout);
+            // Script has performed its first write and should now be waiting
+            // for us. Orphan it.
+            py.mPy.orphan();
+            // Now destroy the LLProcessLauncher, which should NOT kill the child!
+        }
+        // If the destructor killed the child anyway, give it time to die
+        sleep(2);
+        // How do we know it's not terminated? By making it respond to
+        // a specific stimulus in a specific way.
+        {
+            std::ofstream outf(to.getName().c_str());
+            outf << "go";
+        } // flush and close.
+        // now wait for the script to terminate... one way or another.
+        while (LLProcessLauncher::isRunning(pid))
+        {
+            sleep(1);
+        }
+        // If the LLProcessLauncher destructor implicitly called kill(), the
+        // script could not have written 'ack' as we expect.
+        ensure_equals("orphan() script output", readfile(from.getName()), "ack");
+    }
 } // namespace tut
-- 
cgit v1.2.3


From 1ed5bb3adaea0b4fee1e471575459039df8ced2f Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 18 Jan 2012 10:56:13 -0500
Subject: Make embedded Python scripts compatible with Python 2.5 *SIGH*
 Apparently our TeamCity build machines are still not up to Python 2.6.

---
 indra/llcommon/tests/llprocesslauncher_test.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
index 7c0f0eaa84..057f83631e 100644
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ b/indra/llcommon/tests/llprocesslauncher_test.cpp
@@ -181,6 +181,7 @@ public:
     // realpath() to compare properly.
     NamedTempDir():
         mPath(python_out("mkdtemp()",
+                         "from __future__ import with_statement\n"
                          "import os.path, sys, tempfile\n"
                          "with open(sys.argv[1], 'w') as f:\n"
                          "    f.write(os.path.realpath(tempfile.mkdtemp()))\n"))
@@ -518,6 +519,7 @@ namespace tut
         // create one. Naturally, ensure we clean it up when done.
         NamedTempDir tempdir;
         PythonProcessLauncher py("getcwd()",
+                                 "from __future__ import with_statement\n"
                                  "import os, sys\n"
                                  "with open(sys.argv[1], 'w') as f:\n"
                                  "    f.write(os.getcwd())\n");
@@ -531,6 +533,7 @@ namespace tut
     {
         set_test_name("clearArguments()");
         PythonProcessLauncher py("args",
+                                 "from __future__ import with_statement\n"
                                  "import sys\n"
                                  // note nonstandard output-file arg!
                                  "with open(sys.argv[3], 'w') as f:\n"
@@ -568,6 +571,7 @@ namespace tut
     {
         set_test_name("explicit kill()");
         PythonProcessLauncher py("kill()",
+                                 "from __future__ import with_statement\n"
                                  "import sys, time\n"
                                  "with open(sys.argv[1], 'w') as f:\n"
                                  "    f.write('ok')\n"
@@ -610,6 +614,7 @@ namespace tut
         LLProcessLauncher::ll_pid_t pid(0);
         {
             PythonProcessLauncher py("kill()",
+                                     "from __future__ import with_statement\n"
                                      "import sys, time\n"
                                      "with open(sys.argv[1], 'w') as f:\n"
                                      "    f.write('ok')\n"
@@ -655,6 +660,7 @@ namespace tut
         LLProcessLauncher::ll_pid_t pid(0);
         {
             PythonProcessLauncher py("orphan()",
+                                     "from __future__ import with_statement\n"
                                      "import sys, time\n"
                                      "with open(sys.argv[1], 'w') as f:\n"
                                      "    f.write('ok')\n"
-- 
cgit v1.2.3


From 0c1fc78bd94014ee19da690f16cef64c13e50771 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 18 Jan 2012 12:40:11 -0600
Subject: SH-2794 Map buffer now performs as well as buffersubdata

---
 indra/llrender/llvertexbuffer.cpp    | 63 ++++++++++++++++++++++++------------
 indra/llrender/llvertexbuffer.h      |  2 ++
 indra/newview/lldrawpoolavatar.cpp   |  2 +-
 indra/newview/llface.cpp             |  5 ++-
 indra/newview/llspatialpartition.cpp |  6 ++--
 indra/newview/llviewerobject.cpp     |  5 +--
 indra/newview/llvovolume.cpp         | 15 +++++----
 indra/newview/llvowater.cpp          |  2 +-
 indra/newview/llvowlsky.cpp          |  2 +-
 9 files changed, 68 insertions(+), 34 deletions(-)

diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index f8c2a55820..62be5c7368 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -169,7 +169,7 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)
 		glBufferDataARB(mType, size, 0, mUsage);
 		LLVertexBuffer::sAllocatedBytes += size;
 
-		if (LLVertexBuffer::sDisableVBOMapping)
+		if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
 		{
 			ret = (U8*) ll_aligned_malloc_16(size);
 		}
@@ -201,8 +201,15 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
 	rec.mClientData = buffer;
 
 	sBytesPooled += size;
-
-	mFreeList[i].push_back(rec);
+	
+	if (!LLVertexBuffer::sDisableVBOMapping && mUsage == GL_DYNAMIC_DRAW_ARB)
+	{
+		glDeleteBuffersARB(1, &rec.mGLName);
+	}
+	else
+	{
+		mFreeList[i].push_back(rec);
+	}
 }
 
 void LLVBOPool::cleanup()
@@ -536,7 +543,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
 void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
 {
 	validateRange(start, end, count, indices_offset);
-
+	mMappable = FALSE;
 	gGL.syncMatrices();
 
 	llassert(mNumVerts >= 0);
@@ -591,7 +598,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
 void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
 {
 	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
-
+	mMappable = FALSE;
 	gGL.syncMatrices();
 
 	llassert(mNumIndices >= 0);
@@ -637,7 +644,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
 void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
 {
 	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
-	
+	mMappable = FALSE;
 	gGL.syncMatrices();
 	
 	llassert(mNumVerts >= 0);
@@ -790,6 +797,15 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
 		mUsage = GL_DYNAMIC_DRAW_ARB;
 	}
 		
+	if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping)
+	{
+		mMappable = TRUE;
+	}
+	else
+	{
+		mMappable = FALSE;
+	}
+
 	//zero out offsets
 	for (U32 i = 0; i < TYPE_MAX; i++)
 	{
@@ -1301,7 +1317,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
 		
 	if (useVBOs())
 	{
-		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
+		if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
 		{
 			if (count == -1)
 			{
@@ -1326,7 +1342,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
 			if (!mapped)
 			{
 				//not already mapped, map new region
-				MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count);
+				MappedRegion region(type, mMappable && map_range ? -1 : index, count);
 				mMappedVertexRegions.push_back(region);
 			}
 		}
@@ -1343,7 +1359,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
 			sMappedCount++;
 			stop_glerror();	
 
-			if(sDisableVBOMapping)
+			if(!mMappable)
 			{
 				map_range = false;
 			}
@@ -1421,7 +1437,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
 			//check the availability of memory
 			LLMemory::logMemoryInfo(TRUE) ; 
 			
-				if(!sDisableVBOMapping)
+				if(mMappable)
 				{			
 					//--------------------
 					//print out more debug info before crash
@@ -1453,7 +1469,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
 		map_range = false;
 	}
 	
-	if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping)
+	if (map_range && gGLManager.mHasMapBufferRange && mMappable)
 	{
 		return mMappedData;
 	}
@@ -1482,7 +1498,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
 
 	if (useVBOs())
 	{
-		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
+		if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
 		{
 			if (count == -1)
 			{
@@ -1504,7 +1520,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
 			if (!mapped)
 			{
 				//not already mapped, map new region
-				MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count);
+				MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count);
 				mMappedIndexRegions.push_back(region);
 			}
 		}
@@ -1533,7 +1549,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
 				}
 			}
 
-			if(sDisableVBOMapping)
+			if(!mMappable)
 			{
 				map_range = false;
 			}
@@ -1599,7 +1615,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
 			log_glerror();
 			LLMemory::logMemoryInfo(TRUE) ;
 
-			if(!sDisableVBOMapping)
+			if(mMappable)
 			{
 				GLint buff;
 				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
@@ -1621,7 +1637,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
 		map_range = false;
 	}
 
-	if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping)
+	if (map_range && gGLManager.mHasMapBufferRange && mMappable)
 	{
 		return mMappedIndexData;
 	}
@@ -1632,6 +1648,11 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
 }
 
 static LLFastTimer::DeclareTimer FTM_VBO_UNMAP("VBO Unmap");
+static LLFastTimer::DeclareTimer FTM_VBO_FLUSH_RANGE("Flush VBO Range");
+
+
+static LLFastTimer::DeclareTimer FTM_IBO_UNMAP("IBO Unmap");
+static LLFastTimer::DeclareTimer FTM_IBO_FLUSH_RANGE("Flush IBO Range");
 
 void LLVertexBuffer::unmapBuffer()
 {
@@ -1641,16 +1662,15 @@ void LLVertexBuffer::unmapBuffer()
 		return ; //nothing to unmap
 	}
 
-	LLFastTimer t(FTM_VBO_UNMAP);
-
 	bool updated_all = false ;
 
 	if (mMappedData && mVertexLocked)
 	{
+		LLFastTimer t(FTM_VBO_UNMAP);
 		bindGLBuffer(true);
 		updated_all = mIndexLocked; //both vertex and index buffers done updating
 
-		if(sDisableVBOMapping)
+		if(!mMappable)
 		{
 			if (!mMappedVertexRegions.empty())
 			{
@@ -1687,6 +1707,7 @@ void LLVertexBuffer::unmapBuffer()
 						S32 length = sTypeSize[region.mType]*region.mCount;
 						if (gGLManager.mHasMapBufferRange)
 						{
+							LLFastTimer t(FTM_VBO_FLUSH_RANGE);
 #ifdef GL_ARB_map_buffer_range
 							glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
 #endif
@@ -1714,8 +1735,9 @@ void LLVertexBuffer::unmapBuffer()
 	
 	if (mMappedIndexData && mIndexLocked)
 	{
+		LLFastTimer t(FTM_IBO_UNMAP);
 		bindGLIndices();
-		if(sDisableVBOMapping)
+		if(!mMappable)
 		{
 			if (!mMappedIndexRegions.empty())
 			{
@@ -1750,6 +1772,7 @@ void LLVertexBuffer::unmapBuffer()
 						S32 length = sizeof(U16)*region.mCount;
 						if (gGLManager.mHasMapBufferRange)
 						{
+							LLFastTimer t(FTM_IBO_FLUSH_RANGE);
 #ifdef GL_ARB_map_buffer_range
 							glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
 #endif
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 5b93a0389f..dde2b7e152 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -254,6 +254,7 @@ public:
 	volatile U8* getMappedIndices() const			{ return mMappedIndexData; }
 	S32 getOffset(S32 type) const			{ return mOffsets[type]; }
 	S32 getUsage() const					{ return mUsage; }
+	BOOL isWriteable() const				{ return (sDisableVBOMapping || mMappable || mUsage == GL_STREAM_DRAW_ARB) ? TRUE : FALSE; }
 
 	void draw(U32 mode, U32 count, U32 indices_offset) const;
 	void drawArrays(U32 mode, U32 offset, U32 count) const;
@@ -284,6 +285,7 @@ protected:
 	BOOL	mIndexLocked;			// if TRUE, index buffer is being or has been written to in client memory
 	BOOL	mFinal;			// if TRUE, buffer can not be mapped again
 	BOOL	mEmpty;			// if TRUE, client buffer is empty (or NULL). Old values have been discarded.	
+	mutable BOOL	mMappable;     // if TRUE, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData)
 	S32		mOffsets[TYPE_MAX];
 
 	std::vector<MappedRegion> mMappedVertexRegions;
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 55b314fbb1..e75e34df06 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1285,7 +1285,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
 		face->setGeomIndex(0);
 		face->setIndicesIndex(0);
 		
-		if (buffer.isNull() || buffer->getTypeMask() != data_mask)
+		if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable())
 		{ //make a new buffer
 			if (sShaderLevel > 0)
 			{
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 941b8db2cf..cd33a19a2a 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1131,7 +1131,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		updateRebuildFlags();
 	}
 
-	bool map_range = gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange;
+
+	//don't use map range (generates many redundant unmap calls)
+	bool map_range = false; //gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange;
 
 	if (mVertexBuffer.notNull())
 	{
@@ -1921,6 +1923,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		mTexExtents[1][1] *= et ;
 	}
 
+
 	mLastVertexBuffer = mVertexBuffer;
 	mLastGeomCount = mGeomCount;
 	mLastGeomIndex = mGeomIndex;
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 900f126049..4aa5f32d8a 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -264,7 +264,7 @@ static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion");
 
 void LLSpatialGroup::buildOcclusion()
 {
-	if (mOcclusionVerts.isNull())
+	//if (mOcclusionVerts.isNull())
 	{
 		mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 
 			LLVertexBuffer::sUseStreamDraw ? mBufferUsage : 0); //if GL has a hard time with VBOs, don't use them for occlusion culling.
@@ -726,7 +726,9 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
 	if (vertex_count > 0 && index_count > 0)
 	{ //create vertex buffer containing volume geometry for this node
 		group->mBuilt = 1.f;
-		if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))
+		if (group->mVertexBuffer.isNull() ||
+			!group->mVertexBuffer->isWriteable() ||
+			(group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))
 		{
 			group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage);
 			group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true);
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index b8772971aa..37fb77a10a 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -5520,11 +5520,12 @@ void LLViewerObject::dirtyMesh()
 {
 	if (mDrawable)
 	{
-		LLSpatialGroup* group = mDrawable->getSpatialGroup();
+		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL);
+		/*LLSpatialGroup* group = mDrawable->getSpatialGroup();
 		if (group)
 		{
 			group->dirtyMesh();
-		}
+		}*/
 	}
 }
 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 20f8674655..e68fd2697a 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4806,17 +4806,20 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 	
 		//create/delete/resize vertex buffer if needed
 		LLVertexBuffer* buffer = NULL;
-		LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter);
+
+		{ //try to find a buffer to reuse
+			LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter);
 		
-		if (found_iter != group->mBufferMap[mask].end())
-		{
-			if ((U32) buffer_index < found_iter->second.size())
+			if (found_iter != group->mBufferMap[mask].end())
 			{
-				buffer = found_iter->second[buffer_index];
+				if ((U32) buffer_index < found_iter->second.size())
+				{
+					buffer = found_iter->second[buffer_index];
+				}
 			}
 		}
 						
-		if (!buffer)
+		if (!buffer || !buffer->isWriteable())
 		{ //create new buffer if needed
 			buffer = createVertexBuffer(mask, buffer_usage);
 			buffer->allocateBuffer(geom_count, index_count, TRUE);
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index 7df50ec815..315616e8a5 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -167,7 +167,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
 				  indices_per_quad * num_quads);
 	
 	LLVertexBuffer* buff = face->getVertexBuffer();
-	if (!buff)
+	if (!buff || !buff->isWriteable())
 	{
 		buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
 		buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index f1c5499d84..afd902201b 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -774,7 +774,7 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable)
 	LLStrider<LLColor4U> colorsp;
 	LLStrider<LLVector2> texcoordsp;
 
-	if (mStarsVerts.isNull())
+	if (mStarsVerts.isNull() || !mStarsVerts->isWriteable())
 	{
 		mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW);
 		mStarsVerts->allocateBuffer(getStarsNumVerts()*6, 0, TRUE);
-- 
cgit v1.2.3


From 40687a930c2e37a4da15ff15f004611a734583d7 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 18 Jan 2012 12:59:44 -0800
Subject: EXP-1812 FIX Cannot resize location bar / favorites in top navigation
 bar in viewer

---
 indra/llui/lllayoutstack.cpp                       |  13 +-
 indra/llui/lllayoutstack.h                         |   6 +-
 indra/newview/app_settings/settings.xml            |  11 -
 .../skins/default/xui/en/panel_navigation_bar.xml  | 235 +++++++++++----------
 4 files changed, 130 insertions(+), 135 deletions(-)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index a309e3ff97..9909032707 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -201,6 +201,7 @@ LLLayoutStack::Params::Params()
 	clip("clip", true),
 	open_time_constant("open_time_constant", 0.02f),
 	close_time_constant("close_time_constant", 0.03f),
+	resize_bar_overlap("resize_bar_overlap", 1),
 	border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0))
 {}
 
@@ -213,7 +214,8 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
 	mNeedsLayout(true),
 	mClip(p.clip),
 	mOpenTimeConstant(p.open_time_constant),
-	mCloseTimeConstant(p.close_time_constant)
+	mCloseTimeConstant(p.close_time_constant),
+	mResizeBarOverlap(p.resize_bar_overlap)
 {}
 
 LLLayoutStack::~LLLayoutStack()
@@ -409,21 +411,20 @@ void LLLayoutStack::updateLayout()
 		panelp->setShape(panel_rect);
 		panelp->setIgnoreReshape(false);
 
-		static LLUICachedControl<S32> resize_bar_overlap ("UIResizeBarOverlap", 0);
 		LLRect resize_bar_rect(panel_rect);
 
 		F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount();
 		if (mOrientation == HORIZONTAL)
 		{
-			resize_bar_rect.mLeft = panel_rect.mRight - resize_bar_overlap;
-			resize_bar_rect.mRight = panel_rect.mRight + panel_spacing + resize_bar_overlap;
+			resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap;
+			resize_bar_rect.mRight = panel_rect.mRight + panel_spacing + mResizeBarOverlap;
 
 			cur_pos += panel_visible_dim + panel_spacing;
 		}
 		else //VERTICAL
 		{
-			resize_bar_rect.mTop = panel_rect.mBottom + resize_bar_overlap;
-			resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing - resize_bar_overlap;
+			resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap;
+			resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing - mResizeBarOverlap;
 
 			cur_pos -= panel_visible_dim + panel_spacing;
 		}
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index a343e11cec..f00d5e759b 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -60,6 +60,7 @@ public:
 								clip;
 		Optional<F32>			open_time_constant,
 								close_time_constant;
+		Optional<S32>			resize_bar_overlap;
 
 		Params();
 	};
@@ -122,9 +123,10 @@ private:
 	bool mAnimatedThisFrame;
 	bool mAnimate;
 	bool mClip;
-	F32 mOpenTimeConstant;
-	F32 mCloseTimeConstant;
+	F32  mOpenTimeConstant;
+	F32  mCloseTimeConstant;
 	bool mNeedsLayout;
+	S32  mResizeBarOverlap;
 }; // end class LLLayoutStack
 
 
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a4806e3b77..28ba9fd704 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11378,17 +11378,6 @@
       <key>Value</key>
       <real>3</real>
     </map>
-    <key>UIResizeBarOverlap</key>
-    <map>
-      <key>Comment</key>
-      <string>Size of UI resize bar overlap</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>S32</string>
-      <key>Value</key>
-      <real>1</real>
-    </map>
     <key>UIScaleFactor</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index 9dee68efa7..305ce70fcb 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -59,6 +59,8 @@
        follows="all"
        height="34"
        layout="topleft"
+       border_size="0"
+       resize_bar_overlap="3"
        left="0"
        mouse_opaque="false"
        name="nvp_stack"
@@ -73,129 +75,130 @@
            min_width="480"
            name="navigation_layout_panel"
            width="480">
-	<panel
-	 background_visible="false"
-	 follows="left|top|right"
-	 top="3"
-	 height="23"
-	 layout="topleft"
-               left="0"
-	 name="navigation_panel"
-     width="480">
-	     <pull_button
-	     follows="left|top"
-	     direction="down"
-	     height="23"
-	     image_overlay="Arrow_Left_Off"
-	     image_bottom_pad="1"
-	     layout="topleft"
-	     left="10"
-	     name="back_btn"
-	     tool_tip="Go back to previous location"
-	     top="2"
-	     width="31" />
-	    <pull_button
-	     follows="left|top"
-	     direction="down"
-	     height="23"
-	     image_overlay="Arrow_Right_Off"
-	     image_bottom_pad="1"
-	     layout="topleft"
-	     left_pad="0"
-	     name="forward_btn"
-	     tool_tip="Go forward one location"
-	     top_delta="0"
-	     width="31" />
-	    <button
-	     follows="left|top"
-	     height="23"
-	     image_bottom_pad="1"
-	     image_overlay="Home_Off"
-	     layout="topleft"
-	     left_pad="7"
-	     name="home_btn"
-	     tool_tip="Teleport to my home location"
-	     top_delta="0"
-	     width="32" />
-	    <location_input
-                   follows="all"
-	     halign="right"
-	     height="23"
-	     label="Location"
-	     layout="topleft"
-	     left_pad="7"
-	     max_chars="254"
-	     mouse_opaque="false"
-	     name="location_combo"
-	     top_delta="0"
-            width="355">
-         <combo_list
-         mouse_wheel_opaque="true"/>
-	    </location_input>
-             </panel>
-         </layout_panel>
-         
-         <layout_panel
-           auto_resize="false"
-           layout="topleft"
-           max_width="5"
-           min_width="5"
-           name="nav_bar_resize_handle_panel"
-           width="5">
-             <icon
-               follows="top|right"
-               height="25"
-               image_name="ChatBarHandle"
-               layout="topleft"
-               left="-6"
-               name="resize_handle"
-               top="4"
-               width="5" />
-         </layout_panel>
-         
+	        <panel
+	         background_visible="false"
+	         follows="left|top|right"
+	         top="3"
+	         height="23"
+	         layout="topleft"
+                       left="0"
+	         name="navigation_panel"
+             width="480">
+	         <pull_button
+	         follows="left|top"
+	         direction="down"
+	         height="23"
+	         image_overlay="Arrow_Left_Off"
+	         image_bottom_pad="1"
+	         layout="topleft"
+	         left="10"
+	         name="back_btn"
+	         tool_tip="Go back to previous location"
+	         top="2"
+	         width="31" />
+	        <pull_button
+	         follows="left|top"
+	         direction="down"
+	         height="23"
+	         image_overlay="Arrow_Right_Off"
+	         image_bottom_pad="1"
+	         layout="topleft"
+	         left_pad="0"
+	         name="forward_btn"
+	         tool_tip="Go forward one location"
+	         top_delta="0"
+	         width="31" />
+	        <button
+	         follows="left|top"
+	         height="23"
+	         image_bottom_pad="1"
+	         image_overlay="Home_Off"
+	         layout="topleft"
+	         left_pad="7"
+	         name="home_btn"
+	         tool_tip="Teleport to my home location"
+	         top_delta="0"
+	         width="32" />
+	        <location_input
+                       follows="all"
+	         halign="right"
+	         height="23"
+	         label="Location"
+	         layout="topleft"
+	         left_pad="7"
+	         max_chars="254"
+	         mouse_opaque="false"
+	         name="location_combo"
+	         top_delta="0"
+                width="355">
+             <combo_list
+             mouse_wheel_opaque="true"/>
+	        </location_input>
+         </panel>
+          <icon
+             follows="top|right"
+             height="25"
+             image_name="ChatBarHandle"
+             layout="topleft"
+             left="-3"
+             name="resize_handle"
+             top="4"
+             width="5" />
+        </layout_panel>
          <layout_panel
            follows="top|left"
-	     layout="topleft"
+	         layout="topleft"
            auto_resize="true"
            user_resize="true"
            min_width="315"
            name="favorites_layout_panel"
            width="315">
-    <favorites_bar
-     follows="left|right|top"
-     font="SansSerifSmall"
-               height="20"
-     layout="topleft"
-     left="0"
-     name="favorite"
-     image_drag_indication="Accordion_ArrowOpened_Off"
-     tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
-               width="311">
-        <label
-         follows="left|top"
-         height="15"
-         layout="topleft"
-         left="10"
-         name="favorites_bar_label"
-         text_color="LtGray"
-         tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
-         top="12"
-         width="102">
-          Favorites Bar
-        </label>
-                 <!-- More button actually is a text box. -->
-                 <more_button
-                   follows="left|bottom"
-                   name=">>"
-                   tab_stop="false"
-                   tool_tip="Show more of My Favorites"
-                   top="13"
-                   width="50"
-                   bottom="0"
-                   valign="bottom">
-                   More &#9660;
-                   </more_button>
-  </favorites_bar>
+           <icon
+             follows="top|left"
+             height="25"
+             image_name="ChatBarHandle"
+             layout="topleft"
+             left="-318"
+             name="resize_handle"
+             top="4"
+             width="5" />
+
+           <favorites_bar
+             follows="left|right|top"
+             font="SansSerifSmall"
+             height="20"
+             layout="topleft"
+             left="0"
+             top="4"
+             name="favorite"
+             image_drag_indication="Accordion_ArrowOpened_Off"
+             tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
+             width="311">
+            <label
+             follows="left|top"
+             height="15"
+             layout="topleft"
+             left="10"
+             name="favorites_bar_label"
+             text_color="LtGray"
+             tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
+             top="12"
+             width="102">
+              Favorites Bar
+            </label>
+              <!-- More button actually is a text box. -->
+              <more_button
+                follows="left|bottom"
+                name=">>"
+                tab_stop="false"
+                tool_tip="Show more of My Favorites"
+                top="13"
+                width="50"
+                bottom="0"
+                valign="bottom">
+                More &#9660;
+                </more_button>
+         </favorites_bar>
          </layout_panel>
      
      </layout_stack>
-- 
cgit v1.2.3


From eee28bd007178ac83053dfb891a7951d368bcc6e Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 18 Jan 2012 13:03:19 -0800
Subject: EXP-1125 FIX -- New tags always shown in Received Items inbox when
 Inventory window is detached from side panel EXP-1578 FIX -- received items
 folder shows shadows of content when scrolling through lots of folders in
 same window

* Put in guard to prevent the inventory panel from being created multiple times
---
 indra/newview/llsidepanelinventory.cpp | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index e7d486e058..3761eb5777 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -71,8 +71,6 @@ static const char * const INBOX_BUTTON_NAME = "inbox_btn";
 static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel";
 static const char * const MAIN_INVENTORY_LAYOUT_PANEL_NAME = "main_inventory_layout_panel";
 
-static const char * const INBOX_INVENTORY_PANEL = "inventory_inbox";
-
 static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack";
 
 static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox";
@@ -288,34 +286,44 @@ void LLSidepanelInventory::observeInboxCreation()
 
 void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID)
 {
+	//
+	// Silently do nothing if we already have an inbox inventory panel set up
+	// (this can happen multiple times on the initial session that creates the inbox)
+	//
+
+	if (mInventoryPanelInbox != NULL)
+	{
+		return;
+	}
+
 	//
 	// Track inbox folder changes
 	//
-	
+
 	if (inboxID.isNull())
 	{
-		llwarns << "Attempting to track modifications to non-existant inbox" << llendl;
+		llwarns << "Attempting to track modifications to non-existent inbox" << llendl;
 		return;
 	}
-	
+
 	if (mCategoriesObserver == NULL)
 	{
 		mCategoriesObserver = new LLInventoryCategoriesObserver();
 		gInventory.addObserver(mCategoriesObserver);
 	}
-	
+
 	mCategoriesObserver->addCategory(inboxID, boost::bind(&LLSidepanelInventory::onInboxChanged, this, inboxID));
-	
+
 	//
 	// Trigger a load for the entire contents of the Inbox
 	//
-	
+
 	LLInventoryModelBackgroundFetch::instance().start(inboxID);
-	
+
 	//
 	// Set up the inbox inventory view
 	//
-	
+
 	LLPanelMarketplaceInbox * inbox = getChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
 	mInventoryPanelInbox = inbox->setupInventoryPanel();
 }
-- 
cgit v1.2.3


From b18d54be9fb4998854e39df8fbaa271ceb2b8f89 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 18 Jan 2012 13:11:57 -0800
Subject: EXP-1816 FIX -- Drag area in outbox can remain highlighted after drag
 and drop ends

* Added handleHover function to clear highlight
---
 indra/newview/llfloateroutbox.cpp | 10 ++++++++++
 indra/newview/llfloateroutbox.h   |  1 +
 2 files changed, 11 insertions(+)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 297736f3bd..08cd8082aa 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -419,6 +419,16 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 	return handled;
 }
 
+BOOL LLFloaterOutbox::handleHover(S32 x, S32 y, MASK mask)
+{
+	if (mOutboxTopLevelDropZone)
+	{
+		mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
+	}
+
+	return LLFloater::handleHover(x, y, mask);
+}
+
 void LLFloaterOutbox::onMouseLeave(S32 x, S32 y, MASK mask)
 {
 	if (mOutboxTopLevelDropZone)
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
index 796c533059..18baccf1c9 100644
--- a/indra/newview/llfloateroutbox.h
+++ b/indra/newview/llfloateroutbox.h
@@ -66,6 +66,7 @@ public:
 	
 	void showNotification(const LLSD& notify);
 
+	BOOL handleHover(S32 x, S32 y, MASK mask);
 	void onMouseLeave(S32 x, S32 y, MASK mask);
 
 protected:
-- 
cgit v1.2.3


From 28fc3cbadb2b4d46b87938b74d61d5537f6c9701 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 18 Jan 2012 13:35:00 -0800
Subject: removed some invalid attributes

---
 indra/newview/skins/default/xui/en/panel_navigation_bar.xml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index 305ce70fcb..4bf420b79f 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -54,8 +54,6 @@
     width="800"
     height="2"/>
 	 <layout_stack
-       use_border="true"
-       bevel_style="none"
        follows="all"
        height="34"
        layout="topleft"
-- 
cgit v1.2.3


From 852700fbfb6fd751a61f295f5f77afe1e2db38ed Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 18 Jan 2012 15:38:25 -0600
Subject: SH-2598 Fix for crash when rendering mesh silhouette (workaround
 driver bug by rendering from client memory instead of using face VBO).

---
 indra/newview/llselectmgr.cpp | 51 +++++++++++++++++++++----------------------
 1 file changed, 25 insertions(+), 26 deletions(-)

diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 5d0d1ef9a3..6111255a66 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -5556,38 +5556,37 @@ BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power)
 //helper function for pushing relevant vertices from drawable to GL
 void pushWireframe(LLDrawable* drawable)
 {
-	if (drawable->isState(LLDrawable::RIGGED))
-	{ //render straight from rigged volume if this is a rigged attachment
-		LLVOVolume* vobj = drawable->getVOVolume();
-		if (vobj)
-		{
-			vobj->updateRiggedVolume();
-			LLRiggedVolume* rigged_volume = vobj->getRiggedVolume();
-			if (rigged_volume)
-			{
-				LLVertexBuffer::unbind();
-				gGL.pushMatrix();
-				gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix);
-				for (S32 i = 0; i < rigged_volume->getNumVolumeFaces(); ++i)
-				{
-					const LLVolumeFace& face = rigged_volume->getVolumeFace(i);
-					LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices);
-				}
-				gGL.popMatrix();
-			}
-		}
-	}
-	else
+	LLVOVolume* vobj = drawable->getVOVolume();
+	if (vobj)
 	{
-		for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+		LLVertexBuffer::unbind();
+		gGL.pushMatrix();
+		gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix);
+
+		LLVolume* volume = NULL;
+
+		if (drawable->isState(LLDrawable::RIGGED))
+		{
+				vobj->updateRiggedVolume();
+				volume = vobj->getRiggedVolume();
+		}
+		else
+		{
+			volume = vobj->getVolume();
+		}
+
+		if (volume)
 		{
-			LLFace* face = drawable->getFace(i);
-			if (face->verify())
+			for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
 			{
-				pushVerts(face, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
+				const LLVolumeFace& face = volume->getVolumeFace(i);
+				LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices);
 			}
 		}
+
+		gGL.popMatrix();
 	}
+	
 }
 
 void LLSelectNode::renderOneWireframe(const LLColor4& color)
-- 
cgit v1.2.3


From 245f29ca2646157958f1a86bd2bae6cb54275223 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 18 Jan 2012 13:39:04 -0800
Subject: EXP-1550 FIX -- New tag shown and not removed on click when rezzing
 an item from Received Items panel and taking back into inventory.

* Inventory folder creation dates are now only set once, rather than being
  updated every time a new item is added.
---
 indra/newview/llfolderviewitem.cpp | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index aee5a47011..8d6114c887 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -2146,8 +2146,14 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
 	
 	item->dirtyFilter();
 
-	// Update the folder creation date if the child is newer than our current date
-	setCreationDate(llmax<time_t>(mCreationDate, item->getCreationDate()));
+	// Update the folder creation date if the folder has no creation date
+	bool setting_date = false;
+	const time_t item_creation_date = item->getCreationDate();
+	if ((item_creation_date > 0) && (mCreationDate == 0))
+	{
+		setCreationDate(item_creation_date);
+		setting_date = true;
+	}
 
 	// Handle sorting
 	requestArrange();
@@ -2157,8 +2163,11 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
 	LLFolderViewFolder* parentp = getParentFolder();
 	while (parentp)
 	{
-		// Update the folder creation date if the child is newer than our current date
-		parentp->setCreationDate(llmax<time_t>(parentp->mCreationDate, item->getCreationDate()));
+		// Update the parent folder creation date
+		if (setting_date && (parentp->mCreationDate == 0))
+		{
+			parentp->setCreationDate(item_creation_date);
+		}
 
 		if (parentp->mSortFunction.isByDate())
 		{
-- 
cgit v1.2.3


From 098bbfef99b6a52855af9076837ca521d2cdd525 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Wed, 18 Jan 2012 13:53:05 -0800
Subject: EXP-1704 FIX -- Updated text for Empty Received Items panel in Viewer

* Updated to latest text per Leo's comment in the JIRA.
---
 indra/newview/skins/default/xui/en/strings.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 3b00969fd4..3351ffe00f 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2037,7 +2037,7 @@ Returns a string with the requested data about the region
 	<string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string>
 	<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
 	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
-	<string name="InventoryInboxNoItems">When you purchase or otherwise receive an item, it will appear here so you can drag it to a folder in your inventory, or delete it if you do not wish to keep it.</string>
+	<string name="InventoryInboxNoItems">Certain items you receive, such as premium gifts, will appear here.  You may then drag them into your inventory.</string>
 	<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string>
 	<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string>
 	<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string>
-- 
cgit v1.2.3


From 05cff1ad7f71f6ca74af44bdcf1f119cd5149b93 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Wed, 18 Jan 2012 15:26:30 -0700
Subject: fix for SH-2827: [crashhunters] Crash in
 LLPipeline::generateWaterReflection()

---
 indra/llrender/llrender.cpp | 2 --
 indra/newview/pipeline.cpp  | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 03a9884c2b..cd827f5091 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1434,8 +1434,6 @@ void LLRender::loadIdentity()
 	flush();
 
 	{
-		llassert_always(mMatrixMode < NUM_MATRIX_MODES) ;
-
 		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();
 		mMatHash[mMatrixMode]++;
 	}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 8449e74fb6..737c5b51a2 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -3765,6 +3765,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");
 	
 	// Initialize lots of GL state to "safe" values
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 	gGL.matrixMode(LLRender::MM_TEXTURE);
 	gGL.loadIdentity();
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
-- 
cgit v1.2.3


From 02641d4ef33fd6f296a9a29700ecdd55ef9dffd8 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 18 Jan 2012 16:32:07 -0800
Subject: Fix a Linux compilation failure

---
 indra/llui/lllayoutstack.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 9909032707..34d13610b7 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -417,14 +417,14 @@ void LLLayoutStack::updateLayout()
 		if (mOrientation == HORIZONTAL)
 		{
 			resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap;
-			resize_bar_rect.mRight = panel_rect.mRight + panel_spacing + mResizeBarOverlap;
+			resize_bar_rect.mRight = panel_rect.mRight + (S32)(llround(panel_spacing)) + mResizeBarOverlap;
 
 			cur_pos += panel_visible_dim + panel_spacing;
 		}
 		else //VERTICAL
 		{
 			resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap;
-			resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing - mResizeBarOverlap;
+			resize_bar_rect.mBottom = panel_rect.mBottom - (S32)(llround(panel_spacing)) - mResizeBarOverlap;
 
 			cur_pos -= panel_visible_dim + panel_spacing;
 		}
-- 
cgit v1.2.3


From f42c3ff51abf4bd33888765630f5491f6d2014b0 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Thu, 19 Jan 2012 11:10:22 -0600
Subject: SH-2885 Add mesh requests pending/processing line to "Show Render
 Info"

---
 indra/newview/llmeshrepository.cpp | 8 ++++++++
 indra/newview/llmeshrepository.h   | 2 ++
 indra/newview/llviewerwindow.cpp   | 4 +++-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index a97e256c89..1d0c262190 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -88,6 +88,9 @@ const S32 MAX_MESH_VERSION = 999;
 U32 LLMeshRepository::sBytesReceived = 0;
 U32 LLMeshRepository::sHTTPRequestCount = 0;
 U32 LLMeshRepository::sHTTPRetryCount = 0;
+U32 LLMeshRepository::sLODProcessing = 0;
+U32 LLMeshRepository::sLODPending = 0;
+
 U32 LLMeshRepository::sCacheBytesRead = 0;
 U32 LLMeshRepository::sCacheBytesWritten = 0;
 U32 LLMeshRepository::sPeakKbps = 0;
@@ -497,6 +500,7 @@ void LLMeshRepoThread::run()
 					mMutex->lock();
 					LODRequest req = mLODReqQ.front();
 					mLODReqQ.pop();
+					LLMeshRepository::sLODProcessing--;
 					mMutex->unlock();
 					if (fetchMeshLOD(req.mMeshParams, req.mLOD))
 					{
@@ -603,6 +607,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 		{
 			LLMutexLock lock(mMutex);
 			mLODReqQ.push(req);
+			LLMeshRepository::sLODProcessing++;
 		}
 	}
 	else
@@ -1045,6 +1050,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
 			{
 				LODRequest req(mesh_params, iter->second[i]);
 				mLODReqQ.push(req);
+				LLMeshRepository::sLODProcessing++;
 			}
 		}
 		mPendingLOD.erase(iter);
@@ -2147,6 +2153,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
 			//first request for this mesh
 			mLoadingMeshes[detail][mesh_params].insert(vobj->getID());
 			mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail));
+			LLMeshRepository::sLODPending++;
 		}
 	}
 
@@ -2359,6 +2366,7 @@ void LLMeshRepository::notifyLoadedMeshes()
 			LLMeshRepoThread::LODRequest& request = mPendingRequests.front();
 			mThread->loadMeshLOD(request.mMeshParams, request.mLOD);
 			mPendingRequests.erase(mPendingRequests.begin());
+			LLMeshRepository::sLODPending--;
 			push_count--;
 		}
 	}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 31b84ea0d9..1bdbc2856b 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -441,6 +441,8 @@ public:
 	static U32 sBytesReceived;
 	static U32 sHTTPRequestCount;
 	static U32 sHTTPRetryCount;
+	static U32 sLODPending;
+	static U32 sLODProcessing;
 	static U32 sCacheBytesRead;
 	static U32 sCacheBytesWritten;
 	static U32 sPeakKbps;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index bf698e02d2..0534246559 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -613,7 +613,9 @@ public:
 				
 				addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount,
 					LLMeshRepository::sHTTPRetryCount));
-				
+				ypos += y_inc;
+
+				addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing));
 				ypos += y_inc;
 
 				addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f)));
-- 
cgit v1.2.3


From f7cee997df9d7ca40aa40f56c87ff3968821d13a Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Thu, 19 Jan 2012 12:40:44 -0600
Subject: SH-2779 Fix for some transparent rigged attachments not being
 rendered correctly.

---
 indra/newview/lldrawpoolavatar.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index e75e34df06..b002c11af5 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1319,7 +1319,9 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
 		LLMatrix3 mat_normal(mat3);				
 
 		//let getGeometryVolume know if alpha should override shiny
-		if (face->getFaceColor().mV[3] < 1.f)
+		U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture());
+
+		if (type == LLDrawPool::POOL_ALPHA)
 		{
 			face->setPoolType(LLDrawPool::POOL_ALPHA);
 		}
-- 
cgit v1.2.3


From 810b0286a93ae03d3d986a12a8dec352a7e511d9 Mon Sep 17 00:00:00 2001
From: "Debi King (Dessie)" <dessie@lindenlab.com>
Date: Thu, 19 Jan 2012 15:43:12 -0500
Subject: Added tag DRTVWR-111_3.2.7-beta1, 3.2.7-beta1 for changeset
 3d75c836d178

---
 .hgtags | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.hgtags b/.hgtags
index 7de138937e..f3deea990e 100644
--- a/.hgtags
+++ b/.hgtags
@@ -254,3 +254,5 @@ bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release
 c6175c955a19e9b9353d242889ec1779b5762522 DRTVWR-105_3.2.5-release
 c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release
 4891c46a56fed7512c783b9cbe7cb7260727bf0c 3.2.7-start
+3d75c836d178c7c7e788f256afe195f6cab764a2 DRTVWR-111_3.2.7-beta1
+3d75c836d178c7c7e788f256afe195f6cab764a2 3.2.7-beta1
-- 
cgit v1.2.3


From 655505d304fb527df61ee8222904940ad6c70db8 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Thu, 19 Jan 2012 14:57:07 -0600
Subject: SH-2794 Fix for bad textures on some hardware when vbo mapping
 disabled (always use GL_STREAM_DRAW as the usage hint when mapping is
 disabled as geometry will be uploaded again and again)

---
 indra/llrender/llvertexbuffer.cpp | 19 ++++++++++++++++---
 indra/llrender/llvertexbuffer.h   |  2 +-
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 62be5c7368..eb302392bb 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -166,13 +166,18 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)
 		//make a new buffer
 		glGenBuffersARB(1, &name);
 		glBindBufferARB(mType, name);
-		glBufferDataARB(mType, size, 0, mUsage);
 		LLVertexBuffer::sAllocatedBytes += size;
 
 		if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
 		{
+			glBufferDataARB(mType, size, 0, mUsage);
 			ret = (U8*) ll_aligned_malloc_16(size);
 		}
+		else
+		{ //always use a true hint of static draw when allocating non-client-backed buffers
+			glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB);
+		}
+
 		glBindBufferARB(mType, 0);
 	}
 	else
@@ -794,9 +799,17 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
 
 	if (mUsage && mUsage != GL_STREAM_DRAW_ARB)
 	{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
-		mUsage = GL_DYNAMIC_DRAW_ARB;
+		if (sDisableVBOMapping)
+		{ //always use stream draw if VBO mapping is disabled
+			mUsage = GL_STREAM_DRAW_ARB;
+		}
+		else
+		{
+			mUsage = GL_DYNAMIC_DRAW_ARB;
+		}
 	}
-		
+	
+
 	if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping)
 	{
 		mMappable = TRUE;
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index dde2b7e152..e1cbfd3b61 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -254,7 +254,7 @@ public:
 	volatile U8* getMappedIndices() const			{ return mMappedIndexData; }
 	S32 getOffset(S32 type) const			{ return mOffsets[type]; }
 	S32 getUsage() const					{ return mUsage; }
-	BOOL isWriteable() const				{ return (sDisableVBOMapping || mMappable || mUsage == GL_STREAM_DRAW_ARB) ? TRUE : FALSE; }
+	BOOL isWriteable() const				{ return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? TRUE : FALSE; }
 
 	void draw(U32 mode, U32 count, U32 indices_offset) const;
 	void drawArrays(U32 mode, U32 offset, U32 count) const;
-- 
cgit v1.2.3


From 6fddfab6dd8e49dcbf4933bde23dbcdfe3e213db Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 19 Jan 2012 16:41:17 -0500
Subject: Try to fix argument quoting on Windows. Despite LLProcessLauncher's
 list-of-argument-strings API, on Windows it must ram them all into a single
 command-line string anyway. This means that if arguments contain spaces (or
 anything else that would confuse Windows command- line parsing), the target
 process won't receive the intended arguments. Introduce double quotes for any
 arguments not already double-quoted by caller.

---
 indra/llcommon/llprocesslauncher.cpp | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp
index e1af49c2fb..adad3546fe 100644
--- a/indra/llcommon/llprocesslauncher.cpp
+++ b/indra/llcommon/llprocesslauncher.cpp
@@ -75,6 +75,28 @@ void LLProcessLauncher::addArgument(const std::string &arg)
 
 #if LL_WINDOWS
 
+static std::string quote(const std::string& str)
+{
+    std::string::size_type len(str.length());
+    // If the string is already quoted, assume user knows what s/he's doing.
+    if (len >= 2 && str[0] == '"' && str[len-1] == '"')
+    {
+        return str;
+    }
+
+    // Not already quoted: do it.
+    std::string result("\"");
+    for (std::string::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
+    {
+        if (*ci == '"')
+        {
+            result.append("\\");
+        }
+        result.append(*ci);
+    }
+    return result + "\"";
+}
+
 int LLProcessLauncher::launch(void)
 {
 	// If there was already a process associated with this object, kill it.
@@ -87,11 +109,11 @@ int LLProcessLauncher::launch(void)
 	STARTUPINFOA sinfo;
 	memset(&sinfo, 0, sizeof(sinfo));
 	
-	std::string args = mExecutable;
+	std::string args = quote(mExecutable);
 	for(int i = 0; i < (int)mLaunchArguments.size(); i++)
 	{
 		args += " ";
-		args += mLaunchArguments[i];
+		args += quote(mLaunchArguments[i]);
 	}
 	
 	// So retarded.  Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
-- 
cgit v1.2.3


From bb79bbf3209fbb962ca1b284076738eb5ba6019c Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 19 Jan 2012 13:53:48 -0800
Subject: EXP-1827 FIX -- Drag area in outbox does not always highlight green
 when indicating a top level drop

* Updated the outbox drop area highlight to include top level drops within the
  outbox inventory panel itself.
---
 indra/newview/llfloateroutbox.cpp | 55 +++++++++++++++------------------------
 1 file changed, 21 insertions(+), 34 deletions(-)

diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
index 08cd8082aa..540f977305 100644
--- a/indra/newview/llfloateroutbox.cpp
+++ b/indra/newview/llfloateroutbox.cpp
@@ -376,44 +376,37 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 	
 	LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
 	BOOL handled = (handled_view != NULL);
+
+	// Determine if the mouse is inside the inventory panel itself or just within the floater
+	bool pointInInventoryPanel = false;
+	bool pointInInventoryPanelChild = false;
+	LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder();
+	if (mOutboxInventoryPanel->getVisible())
+	{
+		S32 inv_x, inv_y;
+		localPointToOtherView(x, y, &inv_x, &inv_y, mOutboxInventoryPanel);
+
+		pointInInventoryPanel = mOutboxInventoryPanel->getRect().pointInRect(inv_x, inv_y);
+
+		LLView * inventory_panel_child_at_point = mOutboxInventoryPanel->childFromPoint(inv_x, inv_y, true);
+		pointInInventoryPanelChild = (inventory_panel_child_at_point != root_folder);
+	}
 	
 	// Pass all drag and drop for this floater to the outbox inventory control
 	if (!handled || !isAccepted(*accept))
 	{
-		// Always assume we are going to move the drag and drop operation to the outbox root folder
-		bool move_to_root = true;
-		
-		// If the inventory panel is visible, then only override it to the outbox root if we're outside the inventory panel
+		// Handle the drag and drop directly to the root of the outbox if we're not in the inventory panel
 		// (otherwise the inventory panel itself will handle the drag and drop operation, without any override)
-		if (mOutboxInventoryPanel->getVisible())
-		{
-			S32 inv_x, inv_y;
-			localPointToOtherView(x, y, &inv_x, &inv_y, mOutboxInventoryPanel);
-			
-			const LLRect& inv_rect = mOutboxInventoryPanel->getRect();
-
-			move_to_root = !inv_rect.pointInRect(inv_x, inv_y);
-		}
-		
-		// Handle the drag and drop directly to the root of the outbox
-		if (move_to_root)
+		if (!pointInInventoryPanel)
 		{
-			LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder();
-			
 			handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
 		}
 
-		if (mOutboxTopLevelDropZone)
-		{
-			mOutboxTopLevelDropZone->setBackgroundVisible(handled && !drop && isAccepted(*accept));
-		}
+		mOutboxTopLevelDropZone->setBackgroundVisible(handled && !drop && isAccepted(*accept));
 	}
 	else
 	{
-		if (mOutboxTopLevelDropZone)
-		{
-			mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
-		}
+		mOutboxTopLevelDropZone->setBackgroundVisible(!pointInInventoryPanelChild);
 	}
 	
 	return handled;
@@ -421,20 +414,14 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 
 BOOL LLFloaterOutbox::handleHover(S32 x, S32 y, MASK mask)
 {
-	if (mOutboxTopLevelDropZone)
-	{
-		mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
-	}
+	mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
 
 	return LLFloater::handleHover(x, y, mask);
 }
 
 void LLFloaterOutbox::onMouseLeave(S32 x, S32 y, MASK mask)
 {
-	if (mOutboxTopLevelDropZone)
-	{
-		mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
-	}
+	mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
 
 	LLFloater::onMouseLeave(x, y, mask);
 }
-- 
cgit v1.2.3


From 00fc2d5a5c24b1cf2aedd81090bf769207fbf41b Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 19 Jan 2012 13:54:32 -0800
Subject: * Added member variables to avoid several per-frame getChild calls.

---
 indra/newview/llpanelmarketplaceinbox.cpp | 19 ++++++++++++-------
 indra/newview/llpanelmarketplaceinbox.h   |  7 +++++--
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp
index a5e964f563..66c9c323cb 100644
--- a/indra/newview/llpanelmarketplaceinbox.cpp
+++ b/indra/newview/llpanelmarketplaceinbox.cpp
@@ -48,6 +48,8 @@ const LLPanelMarketplaceInbox::Params& LLPanelMarketplaceInbox::getDefaultParams
 // protected
 LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p)
 	: LLPanel(p)
+	, mFreshCountCtrl(NULL)
+	, mInboxButton(NULL)
 	, mInventoryPanel(NULL)
 {
 }
@@ -60,6 +62,9 @@ LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox()
 BOOL LLPanelMarketplaceInbox::postBuild()
 {
 	LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceInbox::onFocusReceived, this));
+
+	mFreshCountCtrl = getChild<LLUICtrl>("inbox_fresh_new_count");
+	mInboxButton = getChild<LLButton>("inbox_btn");
 	
 	return TRUE;
 }
@@ -216,7 +221,7 @@ void LLPanelMarketplaceInbox::draw()
 {
 	U32 item_count = getTotalItemCount();
 
-	LLView * fresh_new_count_view = getChildView("inbox_fresh_new_count");
+	llassert(mFreshCountCtrl != NULL);
 
 	if (item_count > 0)
 	{
@@ -224,26 +229,26 @@ void LLPanelMarketplaceInbox::draw()
 
 		LLStringUtil::format_map_t args;
 		args["[NUM]"] = item_count_str;
-		getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelWithArg", args));
+		mInboxButton->setLabel(getString("InboxLabelWithArg", args));
 
 #if SUPPORTING_FRESH_ITEM_COUNT
 		// set green text to fresh item count
 		U32 fresh_item_count = getFreshItemCount();
-		fresh_new_count_view->setVisible((fresh_item_count > 0));
+		mFreshCountCtrl->setVisible((fresh_item_count > 0));
 
 		if (fresh_item_count > 0)
 		{
-			getChild<LLUICtrl>("inbox_fresh_new_count")->setTextArg("[NUM]", llformat("%d", fresh_item_count));
+			mFreshCountCtrl->setTextArg("[NUM]", llformat("%d", fresh_item_count));
 		}
 #else
-		fresh_new_count_view->setVisible(FALSE);
+		mFreshCountCtrl->setVisible(FALSE);
 #endif
 	}
 	else
 	{
-		getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelNoArg"));
+		mInboxButton->setLabel(getString("InboxLabelNoArg"));
 
-		fresh_new_count_view->setVisible(FALSE);
+		mFreshCountCtrl->setVisible(FALSE);
 	}
 		
 	LLPanel::draw();
diff --git a/indra/newview/llpanelmarketplaceinbox.h b/indra/newview/llpanelmarketplaceinbox.h
index 3531518e51..9eb74581a2 100644
--- a/indra/newview/llpanelmarketplaceinbox.h
+++ b/indra/newview/llpanelmarketplaceinbox.h
@@ -29,7 +29,9 @@
 
 #include "llpanel.h"
 
+class LLButton;
 class LLInventoryPanel;
+class LLUICtrl;
 
 class LLPanelMarketplaceInbox : public LLPanel
 {
@@ -66,9 +68,10 @@ private:
 	void onFocusReceived();
 
 private:
-	LLInventoryPanel* mInventoryPanel;
+	LLUICtrl *			mFreshCountCtrl;
+	LLButton *			mInboxButton;
+	LLInventoryPanel *	mInventoryPanel;
 };
 
 
 #endif //LL_LLPANELMARKETPLACEINBOX_H
-
-- 
cgit v1.2.3


From 083a9e0927144a9e2f052bc8573da8a26259a257 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 19 Jan 2012 17:04:55 -0500
Subject: To grow std::string by a char, use push_back() instead of append().

---
 indra/llcommon/llprocesslauncher.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp
index adad3546fe..5791d14ec0 100644
--- a/indra/llcommon/llprocesslauncher.cpp
+++ b/indra/llcommon/llprocesslauncher.cpp
@@ -92,7 +92,7 @@ static std::string quote(const std::string& str)
         {
             result.append("\\");
         }
-        result.append(*ci);
+        result.push_back(*ci);
     }
     return result + "\"";
 }
-- 
cgit v1.2.3


From bcdecbdae1510a55d5406a85786bab399e180cac Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 19 Jan 2012 14:23:01 -0800
Subject: EXP-1828 FIX -- Drag and drop to an open folder in the outbox causes
 it to close automatically

* Updated auto-open behavior to ignore items that are already open.
---
 indra/newview/llfolderview.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 6bf0f09747..e0d7d67f7d 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -1199,7 +1199,9 @@ void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_f
 
 void LLFolderView::autoOpenItem( LLFolderViewFolder* item )
 {
-	if (mAutoOpenItems.check() == item || mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH)
+	if ((mAutoOpenItems.check() == item) || 
+		(mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) ||
+		item->isOpen())
 	{
 		return;
 	}
-- 
cgit v1.2.3


From 216ac700431af0ab7ee45ec5fef03c928f235063 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 19 Jan 2012 15:24:29 -0800
Subject: EXP-1829 FIX -- Selecting a valid item last allows other selected
 invalid items to be copied to Outbox with context menu option

* Updated context menu default enabled state to use the last state rather than
  TRUE.  Once per frame, the states are all reset to TRUE so this has the effect
  of AND'ing together successive buildContextMenu functions rather than ignoring
  previous states.
---
 indra/newview/llinventorybridge.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3929183be2..12322b2921 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -471,7 +471,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
 
 void hide_context_entries(LLMenuGL& menu, 
 						  const menuentry_vec_t &entries_to_show,
-						  const menuentry_vec_t &disabled_entries) // If append is TRUE, then new enabled entries 
+						  const menuentry_vec_t &disabled_entries)
 {
 	const LLView::child_list_t *list = menu.getChildList();
 
@@ -493,7 +493,6 @@ void hide_context_entries(LLMenuGL& menu,
 			hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
 		}
 
-
 		bool found = false;
 		menuentry_vec_t::const_iterator itor2;
 		for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
@@ -529,7 +528,7 @@ void hide_context_entries(LLMenuGL& menu,
 			// so that some other UI element from multi-select doesn't later set this invisible.
 			menu_item->pushVisible(TRUE);
 
-			BOOL enabled = TRUE;
+			BOOL enabled = menu_item->getEnabled();
 			for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
 			{
 				if (*itor2 == name)
-- 
cgit v1.2.3


From a662b888ed02691b7790c23e31c7d8bcf7cf7f5b Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 19 Jan 2012 19:40:46 -0800
Subject: EXP-1824 FIX Received Items panel does not collapse correct when
 Height of panel is maximized in Inventory window

---
 indra/llui/lllayoutstack.cpp           | 120 ++++++++++++++++++---------------
 indra/llui/lllayoutstack.h             |  12 ++--
 indra/llui/llscrollcontainer.cpp       |  99 ++++++++++++++-------------
 indra/llui/llwindowshade.cpp           |   2 +-
 indra/newview/llsidepanelinventory.cpp |   2 +-
 5 files changed, 123 insertions(+), 112 deletions(-)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 34d13610b7..073592b6ec 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -36,6 +36,9 @@
 #include "llcriticaldamp.h"
 #include "boost/foreach.hpp"
 
+static const F32 MIN_FRACTIONAL_SIZE = 0.0001f;
+static const F32 MAX_FRACTIONAL_SIZE = 1.f;
+
 static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack");
 static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel");
 
@@ -60,7 +63,6 @@ LLLayoutPanel::Params::Params()
 
 LLLayoutPanel::LLLayoutPanel(const Params& p)	
 :	LLPanel(p),
-	mExpandedMinDimSpecified(false),
 	mExpandedMinDim(p.min_dim),
  	mMinDim(p.min_dim), 
  	mAutoResize(p.auto_resize),
@@ -69,7 +71,7 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
 	mCollapseAmt(0.f),
 	mVisibleAmt(1.f), // default to fully visible
 	mResizeBar(NULL),
-	mFractionalSize(0.f),
+	mFractionalSize(MIN_FRACTIONAL_SIZE),
 	mTargetDim(0),
 	mIgnoreReshape(false),
 	mOrientation(LLLayoutStack::HORIZONTAL)
@@ -77,7 +79,6 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
 	// Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value
 	if (p.expanded_min_dim.isProvided())
 	{
-		mExpandedMinDimSpecified = true;
 		mExpandedMinDim = p.expanded_min_dim();
 	}
 	
@@ -134,18 +135,6 @@ void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientatio
 		? getRect().getWidth()
 		: getRect().getHeight()));
 
-	if (mMinDim == -1)
-	{
-		if (!mAutoResize)
-		{
-			setMinDim(layout_dim);
-		}
-		else
-		{
-			setMinDim(0);
-		}
-	}
-
 	mTargetDim = llmax(layout_dim, getMinDim());
 }
  
@@ -164,6 +153,8 @@ void LLLayoutPanel::setVisible( BOOL visible )
 
 void LLLayoutPanel::reshape( S32 width, S32 height, BOOL called_from_parent /*= TRUE*/ )
 {
+	if (width == getRect().getWidth() && height == getRect().getHeight()) return;
+
 	if (!mIgnoreReshape && !mAutoResize)
 	{
 		mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height;
@@ -347,6 +338,7 @@ void LLLayoutStack::updateLayout()
 
 	bool animation_in_progress = animatePanels();
 	F32 total_visible_fraction = 0.f;
+	F32 total_open_fraction = 0.f;
 	S32 space_to_distribute = (mOrientation == HORIZONTAL)
 							? getRect().getWidth()
 							: getRect().getHeight();
@@ -358,9 +350,13 @@ void LLLayoutStack::updateLayout()
 		if (panelp->mAutoResize)
 		{
 			panelp->mTargetDim = panelp->getRelevantMinDim();
+			if (!panelp->mCollapsed && panelp->getVisible())
+			{
+				total_open_fraction += panelp->mFractionalSize;
+			}
 		}
 		space_to_distribute -= panelp->getVisibleDim() + llround((F32)mPanelSpacing * panelp->getVisibleAmount());
-		total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor();
+		total_visible_fraction += panelp->mFractionalSize;
 	}
 
 	llassert(total_visible_fraction < 1.01f);
@@ -368,28 +364,45 @@ void LLLayoutStack::updateLayout()
 	// don't need spacing after last panel
 	space_to_distribute += panelp ? llround((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0;
 
-	// scale up space to distribute, since some of might will go to an invisible fraction of the auto-resize space
-	space_to_distribute = (total_visible_fraction > 0.f)
-						? llround((F32)space_to_distribute / total_visible_fraction)
-						: space_to_distribute;
-
-	if (space_to_distribute > 0)
-	{	// give space proportionally to auto resize panels, even invisible ones
+	F32 fraction_distributed = 0.f;
+	if (space_to_distribute > 0 && total_visible_fraction > 0.f)
+	{	// give space proportionally to visible auto resize panels
 		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
 		{
 			if (panelp->mAutoResize == TRUE)
 			{
-				S32 delta = llround((F32)space_to_distribute * panelp->mFractionalSize/* * panelp->getAutoResizeFactor()*/);
+				F32 fraction_to_distribute = (panelp->mFractionalSize * panelp->getAutoResizeFactor()) / (total_visible_fraction);
+				S32 delta = llround((F32)space_to_distribute * fraction_to_distribute);
+				fraction_distributed += fraction_to_distribute;
 				panelp->mTargetDim += delta;
 			}
 		}
 	}
 
+	if (fraction_distributed < total_visible_fraction)
+	{	// distribute any left over pixels to non-collapsed, visible panels
+		F32 fraction_left = total_visible_fraction - fraction_distributed;
+		S32 space_left = llround((F32)space_to_distribute * (fraction_left / total_visible_fraction));
+
+		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+		{
+			if (panelp->mAutoResize 
+				&& !panelp->mCollapsed 
+				&& panelp->getVisible())
+			{
+				S32 space_for_panel = llmax(0, llround((F32)space_left * (panelp->mFractionalSize / total_open_fraction)));
+				panelp->mTargetDim += space_for_panel;
+				space_left -= space_for_panel;
+				total_open_fraction -= panelp->mFractionalSize;
+			}
+		}
+	}
+
 	F32 cur_pos = (mOrientation == HORIZONTAL) ? 0.f : (F32)getRect().getHeight();
 
 	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
 	{
-		F32 panel_dim = panelp->mTargetDim;
+		F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim);
 		F32 panel_visible_dim = panelp->getVisibleDim();
 
 		LLRect panel_rect;
@@ -403,9 +416,9 @@ void LLLayoutStack::updateLayout()
 		else
 		{
 			panel_rect.setLeftTopAndSize(0,
-				llround(cur_pos),
-				getRect().getWidth(),
-				llround(panel_dim));
+										llround(cur_pos),
+										getRect().getWidth(),
+										llround(panel_dim));
 		}
 		panelp->setIgnoreReshape(true);
 		panelp->setShape(panel_rect);
@@ -531,13 +544,12 @@ void LLLayoutStack::updateFractionalSizes()
 	{
 		if (panelp->mAutoResize)
 		{
-			F32 panel_resizable_dim = llmax(0.f, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim()));
-			panelp->mFractionalSize = llmin(1.f, (panel_resizable_dim == 0.f)
-																	? 0.f
-																	: panel_resizable_dim / total_resizable_dim);
+			F32 panel_resizable_dim = llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim()));
+			panelp->mFractionalSize = panel_resizable_dim > 0.f 
+										? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE)
+										: MIN_FRACTIONAL_SIZE;
 			total_fractional_size += panelp->mFractionalSize;
-			// check for NaNs
-			llassert(panelp->mFractionalSize == panelp->mFractionalSize);
+			llassert(!llisnan(panelp->mFractionalSize));
 		}
 	}
 
@@ -547,7 +559,7 @@ void LLLayoutStack::updateFractionalSizes()
 		{
 			if (panelp->mAutoResize)
 			{
-				panelp->mFractionalSize = 1.f / (F32)num_auto_resize_panels;
+				panelp->mFractionalSize = MAX_FRACTIONAL_SIZE / (F32)num_auto_resize_panels;
 			}
 		}
 	}
@@ -685,11 +697,6 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 		delta_auto_resize_headroom += delta_dim;
 	}
 
-
-	//delta_auto_resize_headroom = (total_visible_fraction > 0.f)
-	//								? delta_auto_resize_headroom / total_visible_fraction
-	//								: 0.f;
-
 	F32 fraction_given_up = 0.f;
 	F32 fraction_remaining = 1.f;
 	F32 updated_auto_resize_headroom = total_auto_resize_headroom + delta_auto_resize_headroom;
@@ -718,8 +725,8 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 			{	// freeze current size as fraction of overall auto_resize space
 				F32 fractional_adjustment_factor = total_auto_resize_headroom / updated_auto_resize_headroom;
 				F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor,
-													0.f,
-													1.f);
+													MIN_FRACTIONAL_SIZE,
+													MAX_FRACTIONAL_SIZE);
 				F32 fraction_delta = (new_fractional_size - panelp->mFractionalSize);
 				fraction_given_up -= fraction_delta;
 				fraction_remaining -= panelp->mFractionalSize;
@@ -735,8 +742,8 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 			if (panelp->mAutoResize)
 			{	// freeze new size as fraction
 				F32 new_fractional_size = (updated_auto_resize_headroom == 0.f)
-					? 1.f
-					: llmin(1.f, ((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom));
+					? MAX_FRACTIONAL_SIZE
+					: llclamp((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
 				fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
 				fraction_remaining -= panelp->mFractionalSize;
 				panelp->mFractionalSize = new_fractional_size;
@@ -755,14 +762,15 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 				fraction_remaining -= panelp->mFractionalSize;
 				if (fraction_given_up != 0.f)
 				{
-					panelp->mFractionalSize += fraction_given_up;
+					panelp->mFractionalSize = llclamp(panelp->mFractionalSize + fraction_given_up, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
 					fraction_given_up = 0.f;
 				}
 				else
 				{
-					F32 new_fractional_size = llmin(1.f, 
-													(F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) 
-														/ updated_auto_resize_headroom);
+					F32 new_fractional_size = llclamp((F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) 
+														/ updated_auto_resize_headroom,
+													MIN_FRACTIONAL_SIZE,
+													MAX_FRACTIONAL_SIZE);
 					fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
 					panelp->mFractionalSize = new_fractional_size;
 				}
@@ -776,7 +784,9 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 		case AFTER_RESIZED_PANEL:
 			if (panelp->mAutoResize)
 			{
-				panelp->mFractionalSize += (panelp->mFractionalSize / fraction_remaining) * fraction_given_up;
+				panelp->mFractionalSize = llclamp(panelp->mFractionalSize + (panelp->mFractionalSize / fraction_remaining) * fraction_given_up,
+												MIN_FRACTIONAL_SIZE,
+												MAX_FRACTIONAL_SIZE);
 			}
 		default:
 			break;
@@ -802,15 +812,15 @@ void LLLayoutStack::updateResizeBarLimits()
 		}
 
 		// toggle resize bars based on panel visibility, resizability, etc
-		if (previous_visible_panelp 
-			&& (visible_panelp->mUserResize 
-				|| previous_visible_panelp->mUserResize))
+		if (previous_visible_panelp
+			&& (visible_panelp->mUserResize || previous_visible_panelp->mUserResize)				// one of the pair is user resizable
+			&& (visible_panelp->mAutoResize || visible_panelp->mUserResize)							// current panel is resizable
+			&& (previous_visible_panelp->mAutoResize || previous_visible_panelp->mUserResize))		// previous panel is resizable
 		{
 			visible_panelp->mResizeBar->setVisible(TRUE);
+			S32 previous_panel_headroom = previous_visible_panelp->getVisibleDim() - previous_visible_panelp->getRelevantMinDim();
 			visible_panelp->mResizeBar->setResizeLimits(visible_panelp->getRelevantMinDim(), 
-														visible_panelp->getVisibleDim() 
-															+ (previous_visible_panelp->getVisibleDim() 
-																- previous_visible_panelp->getRelevantMinDim()));
+														visible_panelp->getVisibleDim() + previous_panel_headroom);
 		}
 		else
 		{
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index f00d5e759b..da63593f7f 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -157,11 +157,11 @@ public:
 	void setVisible(BOOL visible);
 
 	S32 getLayoutDim() const;
-	S32 getMinDim() const { return mMinDim; }
-	void setMinDim(S32 value) { mMinDim = value; if (!mExpandedMinDimSpecified) mExpandedMinDim = value; }
+	S32 getMinDim() const { return (mMinDim >= 0 || mAutoResize) ? llmax(0, mMinDim) : getLayoutDim(); }
+	void setMinDim(S32 value) { mMinDim = value; }
 
-	S32 getExpandedMinDim() const { return mExpandedMinDim; }
-	void setExpandedMinDim(S32 value) { mExpandedMinDim = value; mExpandedMinDimSpecified = true; }
+	S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : mMinDim; }
+	void setExpandedMinDim(S32 value) { mExpandedMinDim = value; }
 	
 	S32 getRelevantMinDim() const
 	{
@@ -169,7 +169,7 @@ public:
 		
 		if (!mCollapsed)
 		{
-			min_dim = mExpandedMinDim;
+			min_dim = getExpandedMinDim();
 		}
 		
 		return min_dim;
@@ -187,9 +187,7 @@ public:
 protected:
 	LLLayoutPanel(const Params& p);
 	
-	bool	mExpandedMinDimSpecified;
 	S32		mExpandedMinDim;
-	
 	S32		mMinDim;
 	bool	mAutoResize;
 	bool	mUserResize;
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index fe3f688fc5..ad4cc20d9a 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -424,63 +424,66 @@ void LLScrollContainer::draw()
 		focusFirstItem();
 	}
 
-	// Draw background
-	if( mIsOpaque )
+	if (getRect().isValid()) 
 	{
-		F32 alpha = getCurrentTransparency();
+		// Draw background
+		if( mIsOpaque )
+		{
+			F32 alpha = getCurrentTransparency();
 
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		gl_rect_2d(mInnerRect, mBackgroundColor.get() % alpha);
-	}
+			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			gl_rect_2d(mInnerRect, mBackgroundColor.get() % alpha);
+		}
 	
-	// Draw mScrolledViews and update scroll bars.
-	// get a scissor region ready, and draw the scrolling view. The
-	// scissor region ensures that we don't draw outside of the bounds
-	// of the rectangle.
-	if( mScrolledView )
-	{
-		updateScroll();
-
-		// Draw the scrolled area.
+		// Draw mScrolledViews and update scroll bars.
+		// get a scissor region ready, and draw the scrolling view. The
+		// scissor region ensures that we don't draw outside of the bounds
+		// of the rectangle.
+		if( mScrolledView )
 		{
-			S32 visible_width = 0;
-			S32 visible_height = 0;
-			BOOL show_v_scrollbar = FALSE;
-			BOOL show_h_scrollbar = FALSE;
-			calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
-
-			LLLocalClipRect clip(LLRect(mInnerRect.mLeft, 
-					mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height,
-					mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0),
-					mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0)
-					));
-			drawChild(mScrolledView);
-		}
-	}
-
-	// Highlight border if a child of this container has keyboard focus
-	if( mBorder->getVisible() )
-	{
-		mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus(this) );
-	}
+			updateScroll();
 
-	// Draw all children except mScrolledView
-	// Note: scrollbars have been adjusted by above drawing code
-	for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin();
-		 child_iter != getChildList()->rend(); ++child_iter)
-	{
-		LLView *viewp = *child_iter;
-		if( sDebugRects )
-		{
-			sDepth++;
+			// Draw the scrolled area.
+			{
+				S32 visible_width = 0;
+				S32 visible_height = 0;
+				BOOL show_v_scrollbar = FALSE;
+				BOOL show_h_scrollbar = FALSE;
+				calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
+
+				LLLocalClipRect clip(LLRect(mInnerRect.mLeft, 
+						mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height,
+						mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0),
+						mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0)
+						));
+				drawChild(mScrolledView);
+			}
 		}
-		if( (viewp != mScrolledView) && viewp->getVisible() )
+
+		// Highlight border if a child of this container has keyboard focus
+		if( mBorder->getVisible() )
 		{
-			drawChild(viewp);
+			mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus(this) );
 		}
-		if( sDebugRects )
+
+		// Draw all children except mScrolledView
+		// Note: scrollbars have been adjusted by above drawing code
+		for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin();
+			 child_iter != getChildList()->rend(); ++child_iter)
 		{
-			sDepth--;
+			LLView *viewp = *child_iter;
+			if( sDebugRects )
+			{
+				sDepth++;
+			}
+			if( (viewp != mScrolledView) && viewp->getVisible() )
+			{
+				drawChild(viewp);
+			}
+			if( sDebugRects )
+			{
+				sDepth--;
+			}
 		}
 	}
 } // end draw
diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp
index 48a232c33e..f5c463c961 100644
--- a/indra/llui/llwindowshade.cpp
+++ b/indra/llui/llwindowshade.cpp
@@ -160,7 +160,7 @@ void LLWindowShade::draw()
 
 	notification_area->reshape(notification_area->getRect().getWidth(), 
 		llclamp(message_rect.getHeight() + 15, 
-				llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT),
+				llmax(mFormHeight, MIN_NOTIFICATION_AREA_HEIGHT),
 				MAX_NOTIFICATION_AREA_HEIGHT));
 
 	LLUICtrl::draw();
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 3761eb5777..ccf8305c63 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -369,7 +369,7 @@ void LLSidepanelInventory::onToggleInboxBtn()
 	const bool inbox_expanded = inboxButton->getToggleState();
 	
 	// Enable user_resize on main inventory panel only when inbox is expanded
-	inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, inbox_expanded);
+	//inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, inbox_expanded);
 	
 	// Expand/collapse the indicated panel
 	inv_stack->collapsePanel(inboxPanel, !inbox_expanded);
-- 
cgit v1.2.3


From 29ad432c8bdc3a69c7241de28e217d27b71947d6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 19 Jan 2012 19:52:49 -0800
Subject: made layoutPanels have constant user_resize and auto_resize
 attributes

---
 indra/llui/lllayoutstack.cpp                       | 38 ++--------------------
 indra/llui/lllayoutstack.h                         |  8 ++---
 indra/newview/llchicletbar.cpp                     |  2 --
 indra/newview/llsidepanelinventory.cpp             |  6 ----
 .../skins/default/xui/en/panel_chiclet_bar.xml     |  1 +
 5 files changed, 7 insertions(+), 48 deletions(-)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 073592b6ec..2f1c2a47c9 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -63,7 +63,7 @@ LLLayoutPanel::Params::Params()
 
 LLLayoutPanel::LLLayoutPanel(const Params& p)	
 :	LLPanel(p),
-	mExpandedMinDim(p.min_dim),
+	mExpandedMinDim(p.expanded_min_dim.isProvided() ? p.expanded_min_dim : p.min_dim),
  	mMinDim(p.min_dim), 
  	mAutoResize(p.auto_resize),
  	mUserResize(p.user_resize),
@@ -76,12 +76,6 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
 	mIgnoreReshape(false),
 	mOrientation(LLLayoutStack::HORIZONTAL)
 {
-	// Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value
-	if (p.expanded_min_dim.isProvided())
-	{
-		mExpandedMinDim = p.expanded_min_dim();
-	}
-	
 	// panels initialized as hidden should not start out partially visible
 	if (!getVisible())
 	{
@@ -155,7 +149,7 @@ void LLLayoutPanel::reshape( S32 width, S32 height, BOOL called_from_parent /*=
 {
 	if (width == getRect().getWidth() && height == getRect().getHeight()) return;
 
-	if (!mIgnoreReshape && !mAutoResize)
+	if (!mIgnoreReshape && mAutoResize == false)
 	{
 		mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height;
 		LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent());
@@ -302,32 +296,6 @@ void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
 	mNeedsLayout = true;
 }
 
-void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize)
-{
-	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
-	
-	if (panel)
-	{
-		panel->mAutoResize = auto_resize;
-	}
-
-	mNeedsLayout = true;
-}
-
-void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize)
-{
-	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
-
-	if (panel)
-	{
-		panel->mUserResize = user_resize;
-	}
-
-	mNeedsLayout = true;
-	updateFractionalSizes();
-}
-
-
 static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks");
 
 void LLLayoutStack::updateLayout()
@@ -369,7 +337,7 @@ void LLLayoutStack::updateLayout()
 	{	// give space proportionally to visible auto resize panels
 		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
 		{
-			if (panelp->mAutoResize == TRUE)
+			if (panelp->mAutoResize)
 			{
 				F32 fraction_to_distribute = (panelp->mFractionalSize * panelp->getAutoResizeFactor()) / (total_visible_fraction);
 				S32 delta = llround((F32)space_to_distribute * fraction_to_distribute);
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index da63593f7f..efe93f6def 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -88,9 +88,6 @@ public:
 	void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
 	S32 getNumPanels() { return mPanels.size(); }
 
-	void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize);
-	void setPanelUserResize(const std::string& panel_name, BOOL user_resize);
-	
 	void updateLayout();
 
 	S32 getPanelSpacing() const { return mPanelSpacing; }
@@ -187,10 +184,11 @@ public:
 protected:
 	LLLayoutPanel(const Params& p);
 	
+	const bool	mAutoResize;
+	const bool	mUserResize;
+
 	S32		mExpandedMinDim;
 	S32		mMinDim;
-	bool	mAutoResize;
-	bool	mUserResize;
 	bool	mCollapsed;
 	F32		mVisibleAmt;
 	F32		mCollapseAmt;
diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp
index a32fd307f1..f1bc51fbe7 100644
--- a/indra/newview/llchicletbar.cpp
+++ b/indra/newview/llchicletbar.cpp
@@ -212,8 +212,6 @@ void LLChicletBar::reshape(S32 width, S32 height, BOOL called_from_parent)
 	{
 		// Firstly, update layout stack to ensure we deal with correct panel sizes.
 		{
-			// Set chiclet panel to be autoresized by default.
-			mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE);
 			// Force the updating of layout to reset panels collapse factor.
 			mToolbarStack->updateLayout();
 		}
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index ccf8305c63..038b18afbd 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -217,9 +217,6 @@ BOOL LLSidepanelInventory::postBuild()
 	{
 		LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
 
-		// Disable user_resize on main inventory panel by default
-		inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false);
-
 		// Collapse inbox panel
 		inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true);
 		
@@ -368,9 +365,6 @@ void LLSidepanelInventory::onToggleInboxBtn()
 	
 	const bool inbox_expanded = inboxButton->getToggleState();
 	
-	// Enable user_resize on main inventory panel only when inbox is expanded
-	//inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, inbox_expanded);
-	
 	// Expand/collapse the indicated panel
 	inv_stack->collapsePanel(inboxPanel, !inbox_expanded);
 
diff --git a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml
index 6d4008a4ed..ff0146490b 100644
--- a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml
@@ -27,6 +27,7 @@
          min_width="95"
          mouse_opaque="false"
          name="chiclet_list_panel"
+         auto_resize="true"
          top="0"
          width="189">
       <chiclet_panel
-- 
cgit v1.2.3


From f42a8a768c3028e81a48b19ac75943f15bfedf1e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 19 Jan 2012 20:00:42 -0800
Subject: fixed build

---
 indra/newview/llimfloater.cpp | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 228260c41a..f67464078b 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -234,12 +234,6 @@ LLIMFloater::~LLIMFloater()
 //virtual
 BOOL LLIMFloater::postBuild()
 {
-	// User-resizable control panels in P2P sessions look ugly (EXT-3470).
-	if (mDialog == IM_NOTHING_SPECIAL || mDialog == IM_SESSION_P2P_INVITE)
-	{
-		getChild<LLLayoutStack>("im_panels")->setPanelUserResize("panel_im_control_panel", FALSE);
-	}
-
 	const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID);
 	if (other_party_id.notNull())
 	{
-- 
cgit v1.2.3


From 9e6a5d721193f181c39e58fe00073bece74b081a Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Fri, 20 Jan 2012 11:55:15 -0700
Subject: fix for SH-2823 and SH-2824: LLCurl crash inside
 LLBufferArray::countAfter() and LLBufferArray::copyIntoBuffers

---
 indra/llcommon/llthread.cpp        | 15 ++++---
 indra/llcommon/llthread.h          |  1 +
 indra/llmessage/llbuffer.cpp       | 90 +++++++++++++++++++++++++++++++++++++-
 indra/llmessage/llbuffer.h         | 25 +++++++++++
 indra/llmessage/llbufferstream.cpp |  8 ++++
 indra/llmessage/llcurl.cpp         |  3 ++
 indra/llmessage/lliohttpserver.cpp |  4 +-
 indra/llmessage/lliosocket.cpp     |  3 ++
 indra/llmessage/llpumpio.cpp       |  1 +
 9 files changed, 142 insertions(+), 8 deletions(-)

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 4063cc730b..a6ad6b125c 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -337,11 +337,7 @@ LLMutex::~LLMutex()
 
 void LLMutex::lock()
 {
-#if LL_DARWIN
-	if (mLockingThread == LLThread::currentID())
-#else
-	if (mLockingThread == sThreadID)
-#endif
+	if(isSelfLocked())
 	{ //redundant lock
 		mCount++;
 		return;
@@ -398,6 +394,15 @@ bool LLMutex::isLocked()
 	}
 }
 
+bool LLMutex::isSelfLocked()
+{
+#if LL_DARWIN
+	return mLockingThread == LLThread::currentID();
+#else
+	return mLockingThread == sThreadID;
+#endif
+}
+
 U32 LLMutex::lockingThread() const
 {
 	return mLockingThread;
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index f0e0de6173..b52e70ab2e 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -151,6 +151,7 @@ public:
 	void lock();		// blocks
 	void unlock();
 	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free
+	bool isSelfLocked(); //return true if locked in a same thread
 	U32 lockingThread() const; //get ID of locking thread
 	
 protected:
diff --git a/indra/llmessage/llbuffer.cpp b/indra/llmessage/llbuffer.cpp
index 0316797f00..250cace6e9 100644
--- a/indra/llmessage/llbuffer.cpp
+++ b/indra/llmessage/llbuffer.cpp
@@ -32,6 +32,9 @@
 #include "llmath.h"
 #include "llmemtype.h"
 #include "llstl.h"
+#include "llthread.h"
+
+#define ASSERT_LLBUFFERARRAY_MUTEX_LOCKED llassert(!mMutexp || mMutexp->isSelfLocked());
 
 /** 
  * LLSegment
@@ -224,7 +227,8 @@ void LLHeapBuffer::allocate(S32 size)
  * LLBufferArray
  */
 LLBufferArray::LLBufferArray() :
-	mNextBaseChannel(0)
+	mNextBaseChannel(0),
+	mMutexp(NULL)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 }
@@ -233,6 +237,8 @@ LLBufferArray::~LLBufferArray()
 {
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 	std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer());
+
+	delete mMutexp;
 }
 
 // static
@@ -243,14 +249,57 @@ LLChannelDescriptors LLBufferArray::makeChannelConsumer(
 	return rv;
 }
 
+void LLBufferArray::lock()
+{
+	if(mMutexp)
+	{
+		mMutexp->lock() ;
+	}
+}
+
+void LLBufferArray::unlock()
+{
+	if(mMutexp)
+	{
+		mMutexp->unlock() ;
+	}
+}
+
+LLMutex* LLBufferArray::getMutex()
+{
+	return mMutexp ;
+}
+
+void LLBufferArray::setThreaded(bool threaded)
+{
+	if(threaded)
+	{
+		if(!mMutexp)
+		{
+			mMutexp = new LLMutex(NULL);
+		}
+	}
+	else
+	{
+		if(mMutexp)
+		{
+			delete mMutexp ;
+			mMutexp = NULL ;
+		}
+	}
+}
+
 LLChannelDescriptors LLBufferArray::nextChannel()
 {
 	LLChannelDescriptors rv(mNextBaseChannel++);
 	return rv;
 }
 
+//mMutexp should be locked before calling this.
 S32 LLBufferArray::capacity() const
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
+
 	S32 total = 0;
 	const_buffer_iterator_t iter = mBuffers.begin();
 	const_buffer_iterator_t end = mBuffers.end();
@@ -263,6 +312,8 @@ S32 LLBufferArray::capacity() const
 
 bool LLBufferArray::append(S32 channel, const U8* src, S32 len)
 {
+	LLMutexLock lock(mMutexp) ;
+
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 	std::vector<LLSegment> segments;
 	if(copyIntoBuffers(channel, src, len, segments))
@@ -273,8 +324,11 @@ bool LLBufferArray::append(S32 channel, const U8* src, S32 len)
 	return false;
 }
 
+//mMutexp should be locked before calling this.
 bool LLBufferArray::prepend(S32 channel, const U8* src, S32 len)
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
+
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 	std::vector<LLSegment> segments;
 	if(copyIntoBuffers(channel, src, len, segments))
@@ -293,6 +347,8 @@ bool LLBufferArray::insertAfter(
 {
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 	std::vector<LLSegment> segments;
+
+	LLMutexLock lock(mMutexp) ;
 	if(mSegments.end() != segment)
 	{
 		++segment;
@@ -305,8 +361,11 @@ bool LLBufferArray::insertAfter(
 	return false;
 }
 
+//mMutexp should be locked before calling this.
 LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
+
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 	segment_iterator_t end = mSegments.end();
 	segment_iterator_t it = getSegment(address);
@@ -335,20 +394,26 @@ LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)
 	return rv;
 }
 							   
+//mMutexp should be locked before calling this.
 LLBufferArray::segment_iterator_t LLBufferArray::beginSegment()
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
 	return mSegments.begin();
 }
 
+//mMutexp should be locked before calling this.
 LLBufferArray::segment_iterator_t LLBufferArray::endSegment()
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
 	return mSegments.end();
 }
 
+//mMutexp should be locked before calling this.
 LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(
 	U8* address,
 	LLSegment& segment)
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 	segment_iterator_t rv = mSegments.begin();
 	segment_iterator_t end = mSegments.end();
@@ -395,8 +460,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(
 	return rv;
 }
 
+//mMutexp should be locked before calling this.
 LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
 	segment_iterator_t end = mSegments.end();
 	if(!address)
 	{
@@ -414,9 +481,11 @@ LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)
 	return end;
 }
 
+//mMutexp should be locked before calling this.
 LLBufferArray::const_segment_iterator_t LLBufferArray::getSegment(
 	U8* address) const
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
 	const_segment_iterator_t end = mSegments.end();
 	if(!address)
 	{
@@ -466,6 +535,8 @@ S32 LLBufferArray::countAfter(S32 channel, U8* start) const
 	S32 count = 0;
 	S32 offset = 0;
 	const_segment_iterator_t it;
+
+	LLMutexLock lock(mMutexp) ;
 	const_segment_iterator_t end = mSegments.end();
 	if(start)
 	{
@@ -517,6 +588,8 @@ U8* LLBufferArray::readAfter(
 	len = 0;
 	S32 bytes_to_copy = 0;
 	const_segment_iterator_t it;
+
+	LLMutexLock lock(mMutexp) ;
 	const_segment_iterator_t end = mSegments.end();
 	if(start)
 	{
@@ -568,6 +641,7 @@ U8* LLBufferArray::seek(
 	U8* start,
 	S32 delta) const
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 	const_segment_iterator_t it;
 	const_segment_iterator_t end = mSegments.end();
@@ -709,9 +783,14 @@ U8* LLBufferArray::seek(
 	return rv;
 }
 
+//test use only
 bool LLBufferArray::takeContents(LLBufferArray& source)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+
+	LLMutexLock lock(mMutexp);
+	source.lock();
+
 	std::copy(
 		source.mBuffers.begin(),
 		source.mBuffers.end(),
@@ -723,13 +802,17 @@ bool LLBufferArray::takeContents(LLBufferArray& source)
 		std::back_insert_iterator<segment_list_t>(mSegments));
 	source.mSegments.clear();
 	source.mNextBaseChannel = 0;
+	source.unlock();
+
 	return true;
 }
 
+//mMutexp should be locked before calling this.
 LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(
 	S32 channel,
 	S32 len)
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 	// start at the end of the buffers, because it is the most likely
 	// to have free space.
@@ -765,8 +848,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(
 	return send;
 }
 
+//mMutexp should be locked before calling this.
 bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 
 	// Find out which buffer contains the segment, and if it is found,
@@ -792,13 +877,14 @@ bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)
 	return rv;
 }
 
-
+//mMutexp should be locked before calling this.
 bool LLBufferArray::copyIntoBuffers(
 	S32 channel,
 	const U8* src,
 	S32 len,
 	std::vector<LLSegment>& segments)
 {
+	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED
 	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
 	if(!src || !len) return false;
 	S32 copied = 0;
diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h
index 1c42b6fbc6..ccdb9fa7ee 100644
--- a/indra/llmessage/llbuffer.h
+++ b/indra/llmessage/llbuffer.h
@@ -39,6 +39,7 @@
 #include <list>
 #include <vector>
 
+class LLMutex;
 /** 
  * @class LLChannelDescriptors
  * @brief A way simple interface to accesss channels inside a buffer
@@ -564,6 +565,29 @@ public:
 	 * @return Returns true on success.
 	 */
 	bool eraseSegment(const segment_iterator_t& iter);
+
+	/**
+	* @brief Lock the mutex if it exists
+	* This method locks mMutexp to make accessing LLBufferArray thread-safe
+	*/
+	void lock();
+
+	/**
+	* @brief Unlock the mutex if it exists
+	*/
+	void unlock();
+
+	/**
+	* @brief Return mMutexp
+	*/
+	LLMutex* getMutex();
+
+	/**
+	* @brief Set LLBufferArray to be shared across threads or not
+	* This method is to create mMutexp if is threaded.
+	* @param threaded Indicates this LLBufferArray instance is shared across threads if true.
+	*/
+	void setThreaded(bool threaded);
 	//@}
 
 protected:
@@ -595,6 +619,7 @@ protected:
 	S32 mNextBaseChannel;
 	buffer_list_t mBuffers;
 	segment_list_t mSegments;
+	LLMutex* mMutexp;
 };
 
 #endif // LL_LLBUFFER_H
diff --git a/indra/llmessage/llbufferstream.cpp b/indra/llmessage/llbufferstream.cpp
index 6257983c43..8d8ad05ad5 100644
--- a/indra/llmessage/llbufferstream.cpp
+++ b/indra/llmessage/llbufferstream.cpp
@@ -31,6 +31,7 @@
 
 #include "llbuffer.h"
 #include "llmemtype.h"
+#include "llthread.h"
 
 static const S32 DEFAULT_OUTPUT_SEGMENT_SIZE = 1024 * 4;
 
@@ -62,6 +63,7 @@ int LLBufferStreamBuf::underflow()
 		return EOF;
 	}
 
+	LLMutexLock lock(mBuffer->getMutex());
 	LLBufferArray::segment_iterator_t iter;
 	LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
 	U8* last_pos = (U8*)gptr();
@@ -149,6 +151,7 @@ int LLBufferStreamBuf::overflow(int c)
 	// since we got here, we have a buffer, and we have a character to
 	// put on it.
 	LLBufferArray::segment_iterator_t it;
+	LLMutexLock lock(mBuffer->getMutex());
 	it = mBuffer->makeSegment(mChannels.out(), DEFAULT_OUTPUT_SEGMENT_SIZE);
 	if(it != mBuffer->endSegment())
 	{
@@ -210,6 +213,7 @@ int LLBufferStreamBuf::sync()
 
 	// *NOTE: I bet we could just --address if address is not NULL.
 	// Need to think about that.
+	LLMutexLock lock(mBuffer->getMutex());
 	address = mBuffer->seek(mChannels.out(), address, -1);
 	if(address)
 	{
@@ -273,6 +277,8 @@ streampos LLBufferStreamBuf::seekoff(
 			// NULL is fine
 			break;
 		}
+
+		LLMutexLock lock(mBuffer->getMutex());
 		address = mBuffer->seek(mChannels.in(), base_addr, off);
 		if(address)
 		{
@@ -304,6 +310,8 @@ streampos LLBufferStreamBuf::seekoff(
 			// NULL is fine
 			break;
 		}
+
+		LLMutexLock lock(mBuffer->getMutex());
 		address = mBuffer->seek(mChannels.out(), base_addr, off);
 		if(address)
 		{
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 5edf0dc8c0..1ab82a273b 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -228,6 +228,8 @@ LLMutex* LLCurl::Easy::sHandleMutexp = NULL ;
 //static
 CURL* LLCurl::Easy::allocEasyHandle()
 {
+	llassert(LLCurl::getCurlThread()) ;
+
 	CURL* ret = NULL;
 
 	LLMutexLock lock(sHandleMutexp) ;
@@ -489,6 +491,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 	LLProxy::getInstance()->applyProxySettings(this);
 
 	mOutput.reset(new LLBufferArray);
+	mOutput->setThreaded(true);
 	setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback);
 	setopt(CURLOPT_WRITEDATA, (void*)this);
 
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 73e8a69085..987f386aa3 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -818,6 +818,8 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 
   			// Copy everything after mLast read to the out.
 			LLBufferArray::segment_iterator_t seg_iter;
+
+			buffer->lock();
 			seg_iter = buffer->splitAfter(mLastRead);
 			if(seg_iter != buffer->endSegment())
 			{
@@ -838,7 +840,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 				}
 #endif
 			}
-
+			buffer->unlock();
 			//
 			// *FIX: get rid of extra bytes off the end
 			//
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index 54ceab3422..d5b4d45821 100644
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -445,6 +445,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
 	// efficient - not only because writev() is better, but also
 	// because we won't have to do as much work to find the start
 	// address.
+	buffer->lock();
 	LLBufferArray::segment_iterator_t it;
 	LLBufferArray::segment_iterator_t end = buffer->endSegment();
 	LLSegment segment;
@@ -524,6 +525,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
 		}
 
 	}
+	buffer->unlock();
+
 	PUMP_DEBUG;
 	if(done && eos)
 	{
diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index 0ff300efd0..f3ef4f2684 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -207,6 +207,7 @@ bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request
 	info.mHasCurlRequest = has_curl_request;
 	info.setTimeoutSeconds(timeout);
 	info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray);
+	info.mData->setThreaded(has_curl_request);
 	LLLinkInfo link;
 #if LL_DEBUG_PIPE_TYPE_IN_PUMP
 	lldebugs << "LLPumpIO::addChain() " << chain[0] << " '"
-- 
cgit v1.2.3


From a73013f7081db15aae93cc82feb895139b1847db Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 20 Jan 2012 13:41:43 -0800
Subject: EXP-1799 FIX -- Replace and Add to Outfit options appear as grayed
 out in Inventory

* Modified build context menu code to not disable items that are invisible so
  secondary background fetch can coalesce menu options with proper state.
* Removed "Move to Merchant Outbox" context menu option.
---
 indra/newview/llinventorybridge.cpp                   | 17 +++++------------
 indra/newview/skins/default/xui/en/menu_inventory.xml |  8 --------
 2 files changed, 5 insertions(+), 20 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 12322b2921..97e61f4c99 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -519,7 +519,6 @@ void hide_context_entries(LLMenuGL& menu,
 			{
 				menu_item->setVisible(FALSE);
 			}
-			menu_item->setEnabled(FALSE);
 		}
 		else
 		{
@@ -528,14 +527,10 @@ void hide_context_entries(LLMenuGL& menu,
 			// so that some other UI element from multi-select doesn't later set this invisible.
 			menu_item->pushVisible(TRUE);
 
-			BOOL enabled = menu_item->getEnabled();
-			for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
+			bool enabled = (menu_item->getEnabled() == TRUE);
+			for (itor2 = disabled_entries.begin(); enabled && (itor2 != disabled_entries.end()); ++itor2)
 			{
-				if (*itor2 == name)
-				{
-					enabled = FALSE;
-					break;
-				}
+				enabled &= (*itor2 != name);
 			}
 
 			menu_item->setEnabled(enabled);
@@ -613,12 +608,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 					copyable = inv_item->getPermissions().allowCopyBy(gAgent.getID());
 				}
 
-				const std::string merchant_action = ((copyable == true) ? "Merchant Copy" : "Merchant Move");
-				items.push_back(merchant_action);
-
+				items.push_back(std::string("Merchant Copy"));
 				if (!canListOnMarketplaceNow())
 				{
-					disabled_items.push_back(merchant_action);
+					disabled_items.push_back(std::string("Merchant Copy"));
 				}
 			}
 		}
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 31dcdfffbb..ef4a1bc061 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -685,14 +685,6 @@
 		 function="Inventory.DoToSelected"
 		 parameter="copy_to_outbox" />
 	</menu_item_call>
-	<menu_item_call
-	 label="Move to Merchant Outbox"
-	 layout="topleft"
-	 name="Merchant Move">
-		<menu_item_call.on_click
-		 function="Inventory.DoToSelected"
-		 parameter="move_to_outbox" />
-	</menu_item_call>
 	<menu_item_call
 	 label="Send to Marketplace"
 	 layout="topleft"
-- 
cgit v1.2.3


From 057da807ac55f9b0583ff334cd12b3568ab81a18 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 20 Jan 2012 13:51:46 -0800
Subject: removed LLXUIXML library moved LLInitParam, and LLRegistry to
 llcommon moved LLUIColor, LLTrans, and LLXUIParser to llui reviewed by Nat

---
 indra/CMakeLists.txt                               |    1 -
 .../integration_tests/llui_libtest/CMakeLists.txt  |    2 -
 indra/llcommon/CMakeLists.txt                      |    3 +
 indra/llcommon/llinitparam.cpp                     |  469 ++++
 indra/llcommon/llinitparam.h                       | 2294 ++++++++++++++++++++
 indra/llcommon/llregistry.h                        |  351 +++
 indra/llui/CMakeLists.txt                          |    8 +-
 indra/llui/lltrans.cpp                             |  295 +++
 indra/llui/lltrans.h                               |  133 ++
 indra/llui/lluicolor.cpp                           |   87 +
 indra/llui/lluicolor.h                             |   71 +
 indra/llui/llxuiparser.cpp                         | 1756 +++++++++++++++
 indra/llui/llxuiparser.h                           |  242 +++
 indra/llui/tests/llurlentry_stub.cpp               |   22 -
 indra/llui/tests/llurlentry_test.cpp               |   15 -
 indra/llui/tests/llurlmatch_test.cpp               |   34 -
 indra/llxuixml/CMakeLists.txt                      |   45 -
 indra/llxuixml/llinitparam.cpp                     |  469 ----
 indra/llxuixml/llinitparam.h                       | 2294 --------------------
 indra/llxuixml/llregistry.h                        |  351 ---
 indra/llxuixml/lltrans.cpp                         |  295 ---
 indra/llxuixml/lltrans.h                           |  133 --
 indra/llxuixml/lluicolor.cpp                       |   87 -
 indra/llxuixml/lluicolor.h                         |   71 -
 indra/llxuixml/llxuiparser.cpp                     | 1756 ---------------
 indra/llxuixml/llxuiparser.h                       |  242 ---
 indra/newview/CMakeLists.txt                       |    3 -
 indra/newview/llviewerprecompiledheaders.h         |    4 +-
 28 files changed, 5709 insertions(+), 5824 deletions(-)
 create mode 100644 indra/llcommon/llinitparam.cpp
 create mode 100644 indra/llcommon/llinitparam.h
 create mode 100644 indra/llcommon/llregistry.h
 create mode 100644 indra/llui/lltrans.cpp
 create mode 100644 indra/llui/lltrans.h
 create mode 100644 indra/llui/lluicolor.cpp
 create mode 100644 indra/llui/lluicolor.h
 create mode 100644 indra/llui/llxuiparser.cpp
 create mode 100644 indra/llui/llxuiparser.h
 delete mode 100644 indra/llxuixml/CMakeLists.txt
 delete mode 100644 indra/llxuixml/llinitparam.cpp
 delete mode 100644 indra/llxuixml/llinitparam.h
 delete mode 100644 indra/llxuixml/llregistry.h
 delete mode 100644 indra/llxuixml/lltrans.cpp
 delete mode 100644 indra/llxuixml/lltrans.h
 delete mode 100644 indra/llxuixml/lluicolor.cpp
 delete mode 100644 indra/llxuixml/lluicolor.h
 delete mode 100644 indra/llxuixml/llxuiparser.cpp
 delete mode 100644 indra/llxuixml/llxuiparser.h

diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 4b1bf49d07..1cebb53a07 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -66,7 +66,6 @@ if (VIEWER)
   add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
   add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
   add_subdirectory(${LIBS_OPEN_PREFIX}llui)
-  add_subdirectory(${LIBS_OPEN_PREFIX}llxuixml)
   add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
 
   # Legacy C++ tests. Build always, run if LL_TESTS is true.
diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt
index 1180460f4b..633ad84159 100644
--- a/indra/integration_tests/llui_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llui_libtest/CMakeLists.txt
@@ -18,7 +18,6 @@ include(LLWindow)
 include(LLUI)
 include(LLVFS)        # ugh, needed for LLDir
 include(LLXML)
-include(LLXUIXML)
 include(Linking)
 # include(Tut)
 
@@ -32,7 +31,6 @@ include_directories(
     ${LLVFS_INCLUDE_DIRS}
     ${LLWINDOW_INCLUDE_DIRS}
     ${LLXML_INCLUDE_DIRS}
-    ${LLXUIXML_INCLUDE_DIRS}
     )
 
 set(llui_libtest_SOURCE_FILES
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 0a3eaec5c5..72b1d363b0 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -61,6 +61,7 @@ set(llcommon_SOURCE_FILES
     llformat.cpp
     llframetimer.cpp
     llheartbeat.cpp
+    llinitparam.cpp
     llinstancetracker.cpp
     llliveappconfig.cpp
     lllivefile.cpp
@@ -173,6 +174,7 @@ set(llcommon_HEADER_FILES
     llheartbeat.h
     llhttpstatuscodes.h
     llindexedqueue.h
+    llinitparam.h
     llinstancetracker.h
     llkeythrottle.h
     lllazy.h
@@ -204,6 +206,7 @@ set(llcommon_HEADER_FILES
     llqueuedthread.h
     llrand.h
     llrefcount.h
+    llregistry.h
     llrun.h
     llrefcount.h
     llsafehandle.h
diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
new file mode 100644
index 0000000000..db72aa19b9
--- /dev/null
+++ b/indra/llcommon/llinitparam.cpp
@@ -0,0 +1,469 @@
+/** 
+ * @file llinitparam.cpp
+ * @brief parameter block abstraction for creating complex objects and 
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&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 "llinitparam.h"
+
+
+namespace LLInitParam
+{
+	//
+	// Param
+	//
+	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 = 0x7FFFffff & (U32)(my_addr - block_addr);
+	}
+
+	//
+	// ParamDescriptor
+	//
+	ParamDescriptor::ParamDescriptor(param_handle_t p, 
+									merge_func_t merge_func, 
+									deserialize_func_t deserialize_func, 
+									serialize_func_t serialize_func,
+									validation_func_t validation_func,
+									inspect_func_t inspect_func,
+									S32 min_count,
+									S32 max_count)
+	:	mParamHandle(p),
+		mMergeFunc(merge_func),
+		mDeserializeFunc(deserialize_func),
+		mSerializeFunc(serialize_func),
+		mValidationFunc(validation_func),
+		mInspectFunc(inspect_func),
+		mMinCount(min_count),
+		mMaxCount(max_count),
+		mUserData(NULL)
+	{}
+
+	ParamDescriptor::ParamDescriptor()
+	:	mParamHandle(0),
+		mMergeFunc(NULL),
+		mDeserializeFunc(NULL),
+		mSerializeFunc(NULL),
+		mValidationFunc(NULL),
+		mInspectFunc(NULL),
+		mMinCount(0),
+		mMaxCount(0),
+		mUserData(NULL)
+	{}
+
+	ParamDescriptor::~ParamDescriptor()
+	{
+		delete mUserData;
+	}
+
+	//
+	// Parser
+	//
+	Parser::~Parser()
+	{}
+
+	void Parser::parserWarning(const std::string& message)
+	{
+		if (mParseSilently) return;
+		llwarns << message << llendl;
+	}
+	
+	void Parser::parserError(const std::string& message)
+	{
+		if (mParseSilently) return;
+		llerrs << message << llendl;
+	}
+
+
+	//
+	// BlockDescriptor
+	//
+	void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data) 
+	{
+		mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end());
+		std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams));
+		std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList));
+		std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
+	}
+
+	BlockDescriptor::BlockDescriptor()
+	:	mMaxParamOffset(0),
+		mInitializationState(UNINITIALIZED),
+		mCurrentBlockPtr(NULL)
+	{}
+
+	// called by each derived class in least to most derived order
+	void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+	{
+		descriptor.mCurrentBlockPtr = this;
+		descriptor.mMaxParamOffset = block_size;
+
+		switch(descriptor.mInitializationState)
+		{
+		case BlockDescriptor::UNINITIALIZED:
+			// copy params from base class here
+			descriptor.aggregateBlockData(base_descriptor);
+
+			descriptor.mInitializationState = BlockDescriptor::INITIALIZING;
+			break;
+		case BlockDescriptor::INITIALIZING:
+			descriptor.mInitializationState = BlockDescriptor::INITIALIZED;
+			break;
+		case BlockDescriptor::INITIALIZED:
+			// nothing to do
+			break;
+		}
+	}
+
+	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const
+	{
+		const U8* param_address = reinterpret_cast<const U8*>(param);
+		const U8* baseblock_address = reinterpret_cast<const U8*>(this);
+		return (param_address - baseblock_address);
+	}
+
+	bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)
+	{
+		if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true))
+		{
+			if (!silent)
+			{
+				p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str()));
+			}
+			return false;
+		}
+		return true;
+	}
+
+
+	bool BaseBlock::validateBlock(bool emit_errors) const
+	{
+		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+		for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
+		{
+			const Param* param = getParamFromHandle(it->first);
+			if (!it->second(param))
+			{
+				if (emit_errors)
+				{
+					llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
+				}
+				return false;
+			}
+		}
+		return true;
+	}
+
+	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const
+	{
+		// named param is one like LLView::Params::follows
+		// unnamed param is like LLView::Params::rect - implicit
+		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+
+		for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); 
+			it != block_data.mUnnamedParams.end(); 
+			++it)
+		{
+			param_handle_t param_handle = (*it)->mParamHandle;
+			const Param* param = getParamFromHandle(param_handle);
+			ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc;
+			if (serialize_func)
+			{
+				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
+				// each param descriptor remembers its serial number
+				// so we can inspect the same param under different names
+				// and see that it has the same number
+				name_stack.push_back(std::make_pair("", true));
+				serialize_func(*param, parser, name_stack, diff_param);
+				name_stack.pop_back();
+			}
+		}
+
+		for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
+			it != block_data.mNamedParams.end();
+			++it)
+		{
+			param_handle_t param_handle = it->second->mParamHandle;
+			const Param* param = getParamFromHandle(param_handle);
+			ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc;
+			if (serialize_func && param->anyProvided())
+			{
+				// Ensure this param has not already been serialized
+				// Prevents <rect> from being serialized as its own tag.
+				bool duplicate = false;
+				for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); 
+					it2 != block_data.mUnnamedParams.end(); 
+					++it2)
+				{
+					if (param_handle == (*it2)->mParamHandle)
+					{
+						duplicate = true;
+						break;
+					}
+				}
+
+				//FIXME: for now, don't attempt to serialize values under synonyms, as current parsers
+				// don't know how to detect them
+				if (duplicate) 
+				{
+					continue;
+				}
+
+				name_stack.push_back(std::make_pair(it->first, !duplicate));
+				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
+				serialize_func(*param, parser, name_stack, diff_param);
+				name_stack.pop_back();
+			}
+		}
+	}
+
+	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const
+	{
+		// named param is one like LLView::Params::follows
+		// unnamed param is like LLView::Params::rect - implicit
+		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+
+		for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); 
+			it != block_data.mUnnamedParams.end(); 
+			++it)
+		{
+			param_handle_t param_handle = (*it)->mParamHandle;
+			const Param* param = getParamFromHandle(param_handle);
+			ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc;
+			if (inspect_func)
+			{
+				name_stack.push_back(std::make_pair("", true));
+				inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount);
+				name_stack.pop_back();
+			}
+		}
+
+		for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
+			it != block_data.mNamedParams.end();
+			++it)
+		{
+			param_handle_t param_handle = it->second->mParamHandle;
+			const Param* param = getParamFromHandle(param_handle);
+			ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc;
+			if (inspect_func)
+			{
+				// Ensure this param has not already been inspected
+				bool duplicate = false;
+				for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); 
+					it2 != block_data.mUnnamedParams.end(); 
+					++it2)
+				{
+					if (param_handle == (*it2)->mParamHandle)
+					{
+						duplicate = true;
+						break;
+					}
+				}
+
+				name_stack.push_back(std::make_pair(it->first, !duplicate));
+				inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
+				name_stack.pop_back();
+			}
+		}
+
+		return true;
+	}
+
+	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored)
+	{
+		BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+		bool names_left = name_stack_range.first != name_stack_range.second;
+
+		bool new_name = names_left
+						? name_stack_range.first->second
+						: true;
+
+		if (names_left)
+		{
+			const std::string& top_name = name_stack_range.first->first;
+
+			ParamDescriptor::deserialize_func_t deserialize_func = NULL;
+			Param* paramp = NULL;
+
+			BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);
+			if (found_it != block_data.mNamedParams.end())
+			{
+				// find pointer to member parameter from offset table
+				paramp = getParamFromHandle(found_it->second->mParamHandle);
+				deserialize_func = found_it->second->mDeserializeFunc;
+					
+				Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);
+				++new_name_stack.first;
+				if (deserialize_func(*paramp, p, new_name_stack, new_name))
+				{
+					// value is no longer new, we know about it now
+					name_stack_range.first->second = false;
+					return true;
+				}
+				else
+				{
+					return false;
+				}
+			}
+		}
+
+		// try to parse unnamed parameters, in declaration order
+		for ( BlockDescriptor::param_list_t::iterator it = block_data.mUnnamedParams.begin(); 
+			it != block_data.mUnnamedParams.end(); 
+			++it)
+		{
+			Param* paramp = getParamFromHandle((*it)->mParamHandle);
+			ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc;
+
+			if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name))
+			{
+				return true;
+			}
+		}
+
+		// if no match, and no names left on stack, this is just an existence assertion of this block
+		// verify by calling readValue with NoParamValue type, an inherently unparseable type
+		if (!names_left)
+		{
+			Flag no_value;
+			return p.readValue(no_value);
+		}
+
+		return false;
+	}
+
+	//static 
+	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name)
+	{
+		// create a copy of the param descriptor in mAllParams
+		// so other data structures can store a pointer to it
+		block_data.mAllParams.push_back(in_param);
+		ParamDescriptorPtr param(block_data.mAllParams.back());
+
+		std::string name(char_name);
+		if ((size_t)param->mParamHandle > block_data.mMaxParamOffset)
+		{
+			llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
+		}
+
+		if (name.empty())
+		{
+			block_data.mUnnamedParams.push_back(param);
+		}
+		else
+		{
+			// don't use insert, since we want to overwrite existing entries
+			block_data.mNamedParams[name] = param;
+		}
+
+		if (param->mValidationFunc)
+		{
+			block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc));
+		}
+	}
+
+	void BaseBlock::addSynonym(Param& param, const std::string& synonym)
+	{
+		BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+		if (block_data.mInitializationState == BlockDescriptor::INITIALIZING)
+		{
+			param_handle_t handle = getHandleFromParam(&param);
+			
+			// check for invalid derivation from a paramblock (i.e. without using
+			// Block<T, Base_Class>
+			if ((size_t)handle > block_data.mMaxParamOffset)
+			{
+				llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
+			}
+
+			ParamDescriptorPtr param_descriptor = findParamDescriptor(param);
+			if (param_descriptor)
+			{
+				if (synonym.empty())
+				{
+					block_data.mUnnamedParams.push_back(param_descriptor);
+				}
+				else
+				{
+					block_data.mNamedParams[synonym] = param_descriptor;
+				}
+			}
+		}
+	}
+
+	const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const
+	{
+		param_handle_t handle = getHandleFromParam(paramp);
+		for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it)
+		{
+			if (it->second->mParamHandle == handle)
+			{
+				return it->first;
+			}
+		}
+
+		return LLStringUtil::null;
+	}
+
+	ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param)
+	{
+		param_handle_t handle = getHandleFromParam(&param);
+		BlockDescriptor& descriptor = mostDerivedBlockDescriptor();
+		BlockDescriptor::all_params_list_t::iterator end_it = descriptor.mAllParams.end();
+		for (BlockDescriptor::all_params_list_t::iterator it = descriptor.mAllParams.begin();
+			it != end_it;
+			++it)
+		{
+			if ((*it)->mParamHandle == handle) return *it;
+		}
+		return ParamDescriptorPtr();
+	}
+
+	// take all provided params from other and apply to self
+	// NOTE: this requires that "other" is of the same derived type as this
+	bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
+	{
+		bool some_param_changed = false;
+		BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end();
+		for (BlockDescriptor::all_params_list_t::const_iterator it = block_data.mAllParams.begin();
+			it != end_it;
+			++it)
+		{
+			const Param* other_paramp = other.getParamFromHandle((*it)->mParamHandle);
+			ParamDescriptor::merge_func_t merge_func = (*it)->mMergeFunc;
+			if (merge_func)
+			{
+				Param* paramp = getParamFromHandle((*it)->mParamHandle);
+				llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle);
+				some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);
+			}
+		}
+		return some_param_changed;
+	}
+}
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
new file mode 100644
index 0000000000..550e1608cc
--- /dev/null
+++ b/indra/llcommon/llinitparam.h
@@ -0,0 +1,2294 @@
+/** 
+ * @file llinitparam.h
+ * @brief parameter block abstraction for creating complex objects and 
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&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 LL_LLPARAM_H
+#define LL_LLPARAM_H
+
+#include <vector>
+#include <boost/function.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "llerror.h"
+
+namespace LLInitParam
+{
+	// used to indicate no matching value to a given name when parsing
+	struct Flag{};
+
+	template<typename T> const T& defaultValue() { static T value; return value; }
+
+	template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >
+    struct ParamCompare 
+	{
+    	static bool equals(const T &a, const T &b)
+		{
+			return a == b;
+		}
+    };
+
+	// boost function types are not comparable
+	template<typename T>
+	struct ParamCompare<T, true>
+	{
+		static bool equals(const T&a, const T &b)
+		{
+			return false;
+		}
+	};
+
+	template<> 
+	struct ParamCompare<LLSD, false>
+	{
+		static bool equals(const LLSD &a, const LLSD &b) { return false; }
+	};
+
+	template<>
+	struct ParamCompare<Flag, false>
+	{
+		static bool equals(const Flag& a, const Flag& b) { return false; }
+	};
+
+
+	// helper functions and classes
+	typedef ptrdiff_t param_handle_t;
+
+	// empty default implementation of key cache
+	// leverages empty base class optimization
+	template <typename T>
+	class TypeValues
+	{
+	private:
+		struct Inaccessable{};
+	public:
+		typedef std::map<std::string, T> value_name_map_t;
+		typedef Inaccessable name_t;
+
+		void setValueName(const std::string& key) {}
+		std::string getValueName() const { return ""; }
+		std::string calcValueName(const T& value) const { return ""; }
+		void clearValueName() const {}
+
+		static bool getValueFromName(const std::string& name, T& value)
+		{
+			return false;
+		}
+
+		static bool valueNamesExist()
+		{
+			return false;
+		}
+
+		static std::vector<std::string>* getPossibleValues()
+		{
+			return NULL;
+		}
+
+		static value_name_map_t* getValueNames() {return NULL;}
+	};
+
+	template <typename T, typename DERIVED_TYPE = TypeValues<T> >
+	class TypeValuesHelper
+	{
+	public:
+		typedef typename std::map<std::string, T> value_name_map_t;
+		typedef std::string name_t;
+
+		//TODO: cache key by index to save on param block size
+		void setValueName(const std::string& value_name) 
+		{
+			mValueName = value_name; 
+		}
+
+		std::string getValueName() const
+		{ 
+			return mValueName; 
+		}
+
+		std::string calcValueName(const T& value) const
+		{
+			value_name_map_t* map = getValueNames();
+			for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end();
+				it != end_it;
+				++it)
+			{
+				if (ParamCompare<T>::equals(it->second, value))
+				{
+					return it->first;
+				}
+			}
+
+			return "";
+		}
+
+		void clearValueName() const
+		{
+			mValueName.clear();
+		}
+
+		static bool getValueFromName(const std::string& name, T& value)
+		{
+			value_name_map_t* map = getValueNames();
+			typename value_name_map_t::iterator found_it = map->find(name);
+			if (found_it == map->end()) return false;
+
+			value = found_it->second;
+			return true;
+		}
+
+		static bool valueNamesExist()
+		{
+			return !getValueNames()->empty();
+		}
+	
+		static value_name_map_t* getValueNames()
+		{
+			static value_name_map_t sMap;
+			static bool sInitialized = false;
+
+			if (!sInitialized)
+			{
+				sInitialized = true;
+				DERIVED_TYPE::declareValues();
+			}
+			return &sMap;
+		}
+
+		static std::vector<std::string>* getPossibleValues()
+		{
+			static std::vector<std::string> sValues;
+
+			value_name_map_t* map = getValueNames();
+			for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end();
+				 it != end_it;
+				 ++it)
+			{
+				sValues.push_back(it->first);
+			}
+			return &sValues;
+		}
+
+		static void declare(const std::string& name, const T& value)
+		{
+			(*getValueNames())[name] = value;
+		}
+
+	protected:
+		static void getName(const std::string& name, const T& value)
+		{}
+
+		mutable std::string	mValueName;
+	};
+
+	class LL_COMMON_API Parser
+	{
+		LOG_CLASS(Parser);
+
+	public:
+		
+		struct CompareTypeID
+		{
+			bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
+			{
+				return lhs->before(*rhs);
+			}
+		};
+
+		typedef std::vector<std::pair<std::string, bool> >					name_stack_t;
+		typedef std::pair<name_stack_t::iterator, name_stack_t::iterator>	name_stack_range_t;
+		typedef std::vector<std::string>									possible_values_t;
+
+		typedef bool (*parser_read_func_t)(Parser& parser, void* output);
+		typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
+		typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
+
+		typedef std::map<const std::type_info*, parser_read_func_t, CompareTypeID>		parser_read_func_map_t;
+		typedef std::map<const std::type_info*, parser_write_func_t, CompareTypeID>		parser_write_func_map_t;
+		typedef std::map<const std::type_info*, parser_inspect_func_t, CompareTypeID>	parser_inspect_func_map_t;
+
+		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
+		:	mParseSilently(false),
+			mParserReadFuncs(&read_map),
+			mParserWriteFuncs(&write_map),
+			mParserInspectFuncs(&inspect_map)
+		{}
+		virtual ~Parser();
+
+		template <typename T> bool readValue(T& param)
+	    {
+		    parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+		    if (found_it != mParserReadFuncs->end())
+		    {
+			    return found_it->second(*this, (void*)&param);
+		    }
+		    return false;
+	    }
+
+		template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
+		{
+		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
+		    if (found_it != mParserWriteFuncs->end())
+		    {
+			    return found_it->second(*this, (const void*)&param, name_stack);
+		    }
+		    return false;
+		}
+
+		// dispatch inspection to registered inspection functions, for each parameter in a param block
+		template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
+		{
+		    parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
+		    if (found_it != mParserInspectFuncs->end())
+		    {
+			    found_it->second(name_stack, min_count, max_count, possible_values);
+				return true;
+		    }
+			return false;
+		}
+
+		virtual std::string getCurrentElementName() = 0;
+		virtual void parserWarning(const std::string& message);
+		virtual void parserError(const std::string& message);
+		void setParseSilently(bool silent) { mParseSilently = silent; }
+
+	protected:
+		template <typename T>
+		void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
+		{
+			mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
+			mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
+		}
+
+		template <typename T>
+		void registerInspectFunc(parser_inspect_func_t inspect_func)
+		{
+			mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
+		}
+
+		bool				mParseSilently;
+
+	private:
+		parser_read_func_map_t*		mParserReadFuncs;
+		parser_write_func_map_t*	mParserWriteFuncs;
+		parser_inspect_func_map_t*	mParserInspectFuncs;
+	};
+
+	class Param;
+
+	// various callbacks and constraints associated with an individual param
+	struct LL_COMMON_API ParamDescriptor
+	{
+		struct UserData
+		{
+			virtual ~UserData() {}
+		};
+
+		typedef bool(*merge_func_t)(Param&, const Param&, bool);
+		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool);
+		typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
+		typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
+		typedef bool(*validation_func_t)(const Param*);
+
+		ParamDescriptor(param_handle_t p, 
+						merge_func_t merge_func, 
+						deserialize_func_t deserialize_func, 
+						serialize_func_t serialize_func,
+						validation_func_t validation_func,
+						inspect_func_t inspect_func,
+						S32 min_count,
+						S32 max_count);
+
+		ParamDescriptor();
+		~ParamDescriptor();
+
+		param_handle_t		mParamHandle;
+		merge_func_t		mMergeFunc;
+		deserialize_func_t	mDeserializeFunc;
+		serialize_func_t	mSerializeFunc;
+		inspect_func_t		mInspectFunc;
+		validation_func_t	mValidationFunc;
+		S32					mMinCount;
+		S32					mMaxCount;
+		S32					mNumRefs;
+		UserData*			mUserData;
+	};
+
+	typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
+
+	// each derived Block class keeps a static data structure maintaining offsets to various params
+	class LL_COMMON_API BlockDescriptor
+	{
+	public:
+		BlockDescriptor();
+
+		typedef enum e_initialization_state
+		{
+			UNINITIALIZED,
+			INITIALIZING,
+			INITIALIZED
+		} EInitializationState;
+
+		void aggregateBlockData(BlockDescriptor& src_block_data);
+
+		typedef boost::unordered_map<const std::string, ParamDescriptorPtr>						param_map_t; 
+		typedef std::vector<ParamDescriptorPtr>													param_list_t; 
+		typedef std::list<ParamDescriptorPtr>													all_params_list_t;
+		typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> >		param_validation_list_t;
+
+		param_map_t						mNamedParams;			// parameters with associated names
+		param_list_t					mUnnamedParams;			// parameters with_out_ associated names
+		param_validation_list_t			mValidationList;		// parameters that must be validated
+		all_params_list_t				mAllParams;				// all parameters, owns descriptors
+		size_t							mMaxParamOffset;
+		EInitializationState			mInitializationState;	// whether or not static block data has been initialized
+		class BaseBlock*				mCurrentBlockPtr;		// pointer to block currently being constructed
+	};
+
+	class LL_COMMON_API BaseBlock
+	{
+	public:
+		//TODO: implement in terms of owned_ptr
+		template<typename T>
+		class Lazy
+		{
+		public:
+			Lazy()
+				: mPtr(NULL)
+			{}
+
+			~Lazy()
+			{
+				delete mPtr;
+			}
+
+			Lazy(const Lazy& other)
+			{
+				if (other.mPtr)
+				{
+					mPtr = new T(*other.mPtr);
+				}
+				else
+				{
+					mPtr = NULL;
+				}
+			}
+
+			Lazy<T>& operator = (const Lazy<T>& other)
+			{
+				if (other.mPtr)
+				{
+					mPtr = new T(*other.mPtr);
+				}
+				else
+				{
+					mPtr = NULL;
+				}
+				return *this;
+			}
+
+			bool empty() const
+			{
+				return mPtr == NULL;
+			}
+
+			void set(const T& other)
+			{
+				delete mPtr;
+				mPtr = new T(other);
+			}
+
+			const T& get() const
+			{
+				return ensureInstance();
+			}
+
+			T& get()
+			{
+				return ensureInstance();
+			}
+
+		private:
+			// lazily allocate an instance of T
+			T* ensureInstance() const
+			{
+				if (mPtr == NULL)
+				{
+					mPtr = new T();
+				}
+				return mPtr;
+			}
+
+		private:
+			// if you get a compilation error with this, that means you are using a forward declared struct for T
+			// unfortunately, the type traits we rely on don't work with forward declared typed
+			//static const int dummy = sizeof(T);
+
+			mutable T* mPtr;
+		};
+
+		// "Multiple" constraint types, put here in root class to avoid ambiguity during use
+		struct AnyAmount
+		{
+			enum { minCount = 0 };
+			enum { maxCount = U32_MAX };
+		};
+
+		template<U32 MIN_AMOUNT>
+		struct AtLeast
+		{
+			enum { minCount = MIN_AMOUNT };
+			enum { maxCount = U32_MAX };
+		};
+
+		template<U32 MAX_AMOUNT>
+		struct AtMost
+		{
+			enum { minCount = 0 };
+			enum { maxCount = MAX_AMOUNT };
+		};
+
+		template<U32 MIN_AMOUNT, U32 MAX_AMOUNT>
+		struct Between
+		{
+			enum { minCount = MIN_AMOUNT };
+			enum { maxCount = MAX_AMOUNT };
+		};
+
+		template<U32 EXACT_COUNT>
+		struct Exactly
+		{
+			enum { minCount = EXACT_COUNT };
+			enum { maxCount = EXACT_COUNT };
+		};
+
+		// this typedef identifies derived classes as being blocks
+		typedef void baseblock_base_class_t;
+		LOG_CLASS(BaseBlock);
+		friend class Param;
+
+		virtual ~BaseBlock() {}
+		bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
+
+		param_handle_t getHandleFromParam(const Param* param) const;
+		bool validateBlock(bool emit_errors = true) const;
+
+		Param* getParamFromHandle(const param_handle_t param_handle)
+		{
+			if (param_handle == 0) return NULL;
+
+			U8* baseblock_address = reinterpret_cast<U8*>(this);
+			return reinterpret_cast<Param*>(baseblock_address + param_handle);
+		}
+
+		const Param* getParamFromHandle(const param_handle_t param_handle) const
+		{
+			const U8* baseblock_address = reinterpret_cast<const U8*>(this);
+			return reinterpret_cast<const Param*>(baseblock_address + param_handle);
+		}
+
+		void addSynonym(Param& param, const std::string& synonym);
+
+		// Blocks can override this to do custom tracking of changes
+		virtual void paramChanged(const Param& changed_param, bool user_provided) {}
+
+		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
+		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
+		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
+
+		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
+		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
+
+		// take all provided params from other and apply to self
+		bool overwriteFrom(const BaseBlock& other)
+		{
+			return false;
+		}
+
+		// take all provided params that are not already provided, and apply to self
+		bool fillFrom(const BaseBlock& other)
+		{
+			return false;
+		}
+
+		static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name);
+
+		ParamDescriptorPtr findParamDescriptor(const Param& param);
+
+	protected:
+		void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size);
+
+
+		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
+		{
+			return mergeBlock(block_data, source, overwrite);
+		}
+		// take all provided params from other and apply to self
+		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite);
+
+		static BlockDescriptor& selfBlockDescriptor()
+		{
+			static BlockDescriptor sBlockDescriptor;
+			return sBlockDescriptor;
+		}
+
+	private:
+		const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
+	};
+
+	template<typename T>
+	struct ParamCompare<BaseBlock::Lazy<T>, false >
+	{
+		static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) { return !a.empty() || !b.empty(); }
+	};
+
+	class LL_COMMON_API Param
+	{
+	public:
+		void setProvided(bool is_provided = true)
+		{
+			mIsProvided = is_provided;
+			enclosingBlock().paramChanged(*this, is_provided);
+		}
+
+		Param& operator =(const Param& other)
+		{
+			mIsProvided = other.mIsProvided;
+			// don't change mEnclosingblockoffset
+			return *this;
+		}
+	protected:
+
+		bool anyProvided() const { return mIsProvided; }
+
+		Param(BaseBlock* enclosing_block);
+
+		// store pointer to enclosing block as offset to reduce space and allow for quick copying
+		BaseBlock& enclosingBlock() const
+		{ 
+			const U8* my_addr = reinterpret_cast<const U8*>(this);
+			// get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class
+			return *const_cast<BaseBlock*>
+				(reinterpret_cast<const BaseBlock*>
+					(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset));
+		}
+
+	private:
+		friend class BaseBlock;
+
+		U32		mEnclosingBlockOffset:31;
+		U32		mIsProvided:1;
+
+	};
+
+	// these templates allow us to distinguish between template parameters
+	// that derive from BaseBlock and those that don't
+	template<typename T, typename Void = void>
+	struct IsBlock
+	{
+		static const bool value = false;
+		struct EmptyBase {};
+		typedef EmptyBase base_class_t;
+	};
+
+	template<typename T>
+	struct IsBlock<T, typename T::baseblock_base_class_t>
+	{
+		static const bool value = true;
+		typedef BaseBlock base_class_t;
+	};
+
+	template<typename T>
+	struct IsBlock<BaseBlock::Lazy<T>, typename T::baseblock_base_class_t >
+	{
+		static const bool value = true;
+		typedef BaseBlock base_class_t;
+	};
+
+	template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value>
+	class ParamValue : public NAME_VALUE_LOOKUP
+	{
+	public:
+		typedef const T&							value_assignment_t;
+		typedef T									value_t;
+		typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK>	self_t;
+
+		ParamValue(): mValue() {}
+		ParamValue(value_assignment_t other) : mValue(other) {}
+
+		void setValue(value_assignment_t val)
+		{
+			mValue = val;
+		}
+
+		value_assignment_t getValue() const
+		{
+			return mValue;
+		}
+
+		T& getValue()
+		{
+			return mValue;
+		}
+
+		operator value_assignment_t() const
+		{
+			return mValue;
+		}
+
+		value_assignment_t operator()() const
+		{
+			return mValue;
+		}
+
+		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name)
+		{
+			*this = name;
+		}
+
+		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
+		{
+			if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue))
+			{
+				setValueName(name);
+			}
+
+			return *this;
+		}
+
+	protected:
+		T mValue;
+	};
+
+	template<typename T, typename NAME_VALUE_LOOKUP>
+	class ParamValue<T, NAME_VALUE_LOOKUP, true> 
+	:	public T,
+		public NAME_VALUE_LOOKUP
+	{
+	public:
+		typedef const T&							value_assignment_t;
+		typedef T									value_t;
+		typedef ParamValue<T, NAME_VALUE_LOOKUP, true>	self_t;
+
+		ParamValue() 
+		:	T(),
+			mValidated(false)
+		{}
+
+		ParamValue(value_assignment_t other)
+		:	T(other),
+			mValidated(false)
+		{}
+
+		void setValue(value_assignment_t val)
+		{
+			*this = val;
+		}
+
+		value_assignment_t getValue() const
+		{
+			return *this;
+		}
+
+		T& getValue()
+		{
+			return *this;
+		}
+
+		operator value_assignment_t() const
+		{
+			return *this;
+		}
+		
+		value_assignment_t operator()() const
+		{
+			return *this;
+		}
+
+		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name)
+		{
+			*this = name;
+		}
+
+		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
+		{
+			if (NAME_VALUE_LOOKUP::getValueFromName(name, *this))
+			{
+				setValueName(name);
+			}
+
+			return *this;
+		}
+
+	protected:
+		mutable bool 	mValidated; // lazy validation flag
+	};
+
+	template<typename NAME_VALUE_LOOKUP>
+	class ParamValue<std::string, NAME_VALUE_LOOKUP, false>
+	: public NAME_VALUE_LOOKUP
+	{
+	public:
+		typedef const std::string&	value_assignment_t;
+		typedef std::string			value_t;
+		typedef ParamValue<std::string, NAME_VALUE_LOOKUP, false>	self_t;
+
+		ParamValue(): mValue() {}
+		ParamValue(value_assignment_t other) : mValue(other) {}
+
+		void setValue(value_assignment_t val)
+		{
+			if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue))
+			{
+				NAME_VALUE_LOOKUP::setValueName(val);
+			}
+			else
+			{
+				mValue = val;
+			}
+		}
+
+		value_assignment_t getValue() const
+		{
+			return mValue;
+		}
+
+		std::string& getValue()
+		{
+			return mValue;
+		}
+
+		operator value_assignment_t() const
+		{
+			return mValue;
+		}
+
+		value_assignment_t operator()() const
+		{
+			return mValue;
+		}
+
+	protected:
+		std::string mValue;
+	};
+
+
+	template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+	struct ParamIterator
+	{
+		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator		const_iterator;
+		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator			iterator;
+	};
+
+	// specialize for custom parsing/decomposition of specific classes
+	// e.g. TypedParam<LLRect> has left, top, right, bottom, etc...
+	template<typename	T,
+			typename	NAME_VALUE_LOOKUP = TypeValues<T>,
+			bool		HAS_MULTIPLE_VALUES = false,
+			bool		VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>
+	class TypedParam 
+	:	public Param, 
+		public ParamValue<T, NAME_VALUE_LOOKUP>
+	{
+	public:
+		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>		self_t;
+		typedef ParamValue<T, NAME_VALUE_LOOKUP>											param_value_t;
+		typedef typename param_value_t::value_assignment_t				value_assignment_t;
+		typedef NAME_VALUE_LOOKUP															name_value_lookup_t;
+
+		using param_value_t::operator();
+
+		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
+		:	Param(block_descriptor.mCurrentBlockPtr)
+		{
+			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+			{
+ 				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+												&mergeWith,
+												&deserializeParam,
+												&serializeParam,
+												validate_func,
+												&inspectParam,
+												min_count, max_count));
+				BaseBlock::addParam(block_descriptor, param_descriptor, name);
+			}
+
+			setValue(value);
+		} 
+
+		bool isProvided() const { return Param::anyProvided(); }
+
+		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
+		{ 
+			self_t& typed_param = static_cast<self_t&>(param);
+			// no further names in stack, attempt to parse value now
+			if (name_stack_range.first == name_stack_range.second)
+			{
+				if (parser.readValue(typed_param.getValue()))
+				{
+					typed_param.clearValueName();
+					typed_param.setProvided();
+					return true;
+				}
+				
+				// try to parse a known named value
+				if(name_value_lookup_t::valueNamesExist())
+				{
+					// try to parse a known named value
+					std::string name;
+					if (parser.readValue(name))
+					{
+						// try to parse a per type named value
+						if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))
+						{
+							typed_param.setValueName(name);
+							typed_param.setProvided();
+							return true;
+						}
+
+					}
+				}
+			}
+			return false;
+		}
+
+		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		{
+			const self_t& typed_param = static_cast<const self_t&>(param);
+			if (!typed_param.isProvided()) return;
+
+			if (!name_stack.empty())
+			{
+				name_stack.back().second = true;
+			}
+
+			std::string key = typed_param.getValueName();
+
+			// first try to write out name of name/value pair
+
+			if (!key.empty())
+			{
+				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
+				{
+					parser.writeValue(key, name_stack);
+				}
+			}
+			// then try to serialize value directly
+			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue()))
+			{
+				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
+				{
+					std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
+					if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))
+					{
+						parser.writeValue(calculated_key, name_stack);
+					}
+				}
+			}
+		}
+
+		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+		{
+			// tell parser about our actual type
+			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
+			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
+			if (name_value_lookup_t::getPossibleValues())
+			{
+				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());
+			}
+		}
+
+		void set(value_assignment_t val, bool flag_as_provided = true)
+		{
+			param_value_t::clearValueName();
+			setValue(val);
+			setProvided(flag_as_provided);
+		}
+
+		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
+		{
+			return static_cast<self_t&>(param_value_t::operator =(name));
+		}
+
+	protected:
+
+		self_t& operator =(const self_t& other)
+		{
+			param_value_t::operator =(other);
+			Param::operator =(other);
+			return *this;
+		}
+
+		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+		{
+			const self_t& src_typed_param = static_cast<const self_t&>(src);
+			self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+			if (src_typed_param.isProvided()
+				&& (overwrite || !dst_typed_param.isProvided()))
+			{
+				dst_typed_param.set(src_typed_param.getValue());
+				return true;
+			}
+			return false;
+		}
+	};
+
+	// parameter that is a block
+	template <typename T, typename NAME_VALUE_LOOKUP>
+	class TypedParam<T, NAME_VALUE_LOOKUP, false, true> 
+	:	public Param,
+		public ParamValue<T, NAME_VALUE_LOOKUP>
+	{
+	public:
+		typedef ParamValue<T, NAME_VALUE_LOOKUP>				param_value_t;
+		typedef typename param_value_t::value_assignment_t		value_assignment_t;
+		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true>	self_t;
+		typedef NAME_VALUE_LOOKUP								name_value_lookup_t;
+
+		using param_value_t::operator();
+
+		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+		:	Param(block_descriptor.mCurrentBlockPtr),
+			param_value_t(value)
+		{
+			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+			{
+				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+												&mergeWith,
+												&deserializeParam,
+												&serializeParam,
+												validate_func, 
+												&inspectParam,
+												min_count, max_count));
+				BaseBlock::addParam(block_descriptor, param_descriptor, name);
+			}
+		}
+
+		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
+		{ 
+			self_t& typed_param = static_cast<self_t&>(param);
+			// attempt to parse block...
+			if(typed_param.deserializeBlock(parser, name_stack_range, new_name))
+			{
+				typed_param.clearValueName();
+				typed_param.setProvided();
+				return true;
+			}
+
+			if(name_value_lookup_t::valueNamesExist())
+			{
+				// try to parse a known named value
+				std::string name;
+				if (parser.readValue(name))
+				{
+					// try to parse a per type named value
+					if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))
+					{
+						typed_param.setValueName(name);
+						typed_param.setProvided();
+						return true;
+					}
+
+				}
+			}
+			return false;
+		}
+
+		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		{
+			const self_t& typed_param = static_cast<const self_t&>(param);
+			if (!typed_param.isProvided()) return;
+
+			if (!name_stack.empty())
+			{
+				name_stack.back().second = true;
+			}
+
+			std::string key = typed_param.getValueName();
+			if (!key.empty())
+			{
+				if (!parser.writeValue(key, name_stack))
+				{
+					return;
+				}
+			}
+			else
+			{
+				typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param));
+			}
+		}
+
+		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+		{
+			// I am a param that is also a block, so just recurse into my contents
+			const self_t& typed_param = static_cast<const self_t&>(param);
+			typed_param.inspectBlock(parser, name_stack, min_count, max_count);
+		}
+
+		// a param-that-is-a-block is provided when the user has set one of its child params
+		// *and* the block as a whole validates
+		bool isProvided() const 
+		{ 
+			// only validate block when it hasn't already passed validation with current data
+			if (Param::anyProvided() && !param_value_t::mValidated)
+			{
+				// a sub-block is "provided" when it has been filled in enough to be valid
+				param_value_t::mValidated = param_value_t::validateBlock(false);
+			}
+			return Param::anyProvided() && param_value_t::mValidated;
+		}
+
+		// assign block contents to this param-that-is-a-block
+		void set(value_assignment_t val, bool flag_as_provided = true)
+		{
+			setValue(val);
+			param_value_t::clearValueName();
+			// force revalidation of block
+			// next call to isProvided() will update provision status based on validity
+			param_value_t::mValidated = false;
+			setProvided(flag_as_provided);
+		}
+
+		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
+		{
+			return static_cast<self_t&>(param_value_t::operator =(name));
+		}
+
+		// propagate changed status up to enclosing block
+		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
+		{ 
+			param_value_t::paramChanged(changed_param, user_provided);
+			if (user_provided)
+			{
+				// a child param has been explicitly changed
+				// so *some* aspect of this block is now provided
+				param_value_t::mValidated = false;
+				setProvided();
+				param_value_t::clearValueName();
+			}
+			else
+			{
+				Param::enclosingBlock().paramChanged(*this, user_provided);
+			}
+		}
+
+	protected:
+
+		self_t& operator =(const self_t& other)
+		{
+			param_value_t::operator =(other);
+			Param::operator =(other);
+			return *this;
+		}
+
+		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+		{
+			const self_t& src_typed_param = static_cast<const self_t&>(src);
+			self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+			if (src_typed_param.anyProvided())
+			{
+				if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite))
+				{
+					dst_typed_param.clearValueName();
+					dst_typed_param.setProvided(true);
+					return true;
+				}
+			}
+			return false;
+		}
+	};
+
+	// container of non-block parameters
+	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
+	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> 
+	:	public Param
+	{
+	public:
+		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>		self_t;
+		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>					param_value_t;
+		typedef typename std::vector<param_value_t>							container_t;
+		typedef const container_t&											value_assignment_t;
+
+		typedef typename param_value_t::value_t								value_t;
+		typedef NAME_VALUE_LOOKUP											name_value_lookup_t;
+		
+		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
+		:	Param(block_descriptor.mCurrentBlockPtr)
+		{
+			std::copy(value.begin(), value.end(), std::back_inserter(mValues));
+
+			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+			{
+				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+												&mergeWith,
+												&deserializeParam,
+												&serializeParam,
+												validate_func,
+												&inspectParam,
+												min_count, max_count));
+				BaseBlock::addParam(block_descriptor, param_descriptor, name);
+			}
+		} 
+
+		bool isProvided() const { return Param::anyProvided(); }
+
+		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
+		{ 
+			self_t& typed_param = static_cast<self_t&>(param);
+			value_t value;
+			// no further names in stack, attempt to parse value now
+			if (name_stack_range.first == name_stack_range.second)
+			{
+				// attempt to read value directly
+				if (parser.readValue(value))
+				{
+					typed_param.add(value);
+					return true;
+				}
+				
+				// try to parse a known named value
+				if(name_value_lookup_t::valueNamesExist())
+				{
+					// try to parse a known named value
+					std::string name;
+					if (parser.readValue(name))
+					{
+						// try to parse a per type named value
+						if (name_value_lookup_t::getValueFromName(name, value))
+						{
+							typed_param.add(value);
+							typed_param.mValues.back().setValueName(name);
+							return true;
+						}
+
+					}
+				}
+			}
+			return false;
+		}
+
+		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		{
+			const self_t& typed_param = static_cast<const self_t&>(param);
+			if (!typed_param.isProvided() || name_stack.empty()) return;
+
+			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
+				it != end_it;
+				++it)
+			{
+				std::string key = it->getValueName();
+				name_stack.back().second = true;
+
+				if(key.empty())
+				// not parsed via name values, write out value directly
+				{
+					bool value_written = parser.writeValue(*it, name_stack);
+					if (!value_written)
+					{
+						std::string calculated_key = it->calcValueName(it->getValue());
+						if (!parser.writeValue(calculated_key, name_stack))
+						{
+							break;
+						}
+					}
+				}
+				else 
+				{
+					if(!parser.writeValue(key, name_stack))
+					{
+						break;
+					}
+				}
+			}
+		}
+
+		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+		{
+			parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL);
+			if (name_value_lookup_t::getPossibleValues())
+			{
+				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());
+			}
+		}
+
+		void set(value_assignment_t val, bool flag_as_provided = true)
+		{
+			mValues = val;
+			setProvided(flag_as_provided);
+		}
+
+		param_value_t& add()
+		{
+			mValues.push_back(param_value_t(value_t()));
+			Param::setProvided();
+			return mValues.back();
+		}
+
+		void add(const value_t& item)
+		{
+			param_value_t param_value;
+			param_value.setValue(item);
+			mValues.push_back(param_value);
+			setProvided();
+		}
+
+		void add(const typename name_value_lookup_t::name_t& name)
+		{
+			value_t value;
+
+			// try to parse a per type named value
+			if (name_value_lookup_t::getValueFromName(name, value))
+			{
+				add(value);
+				mValues.back().setValueName(name);
+			}
+		}
+
+		// implicit conversion
+		operator value_assignment_t() const { return mValues; } 
+		// explicit conversion		
+		value_assignment_t operator()() const { return mValues; }
+
+		typedef typename container_t::iterator iterator;
+		typedef typename container_t::const_iterator const_iterator;
+		iterator begin() { return mValues.begin(); }
+		iterator end() { return mValues.end(); }
+		const_iterator begin() const { return mValues.begin(); }
+		const_iterator end() const { return mValues.end(); }
+		bool empty() const { return mValues.empty(); }
+		size_t size() const { return mValues.size(); }
+
+		U32 numValidElements() const
+		{
+			return mValues.size();
+		}
+
+	protected:
+		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+		{
+			const self_t& src_typed_param = static_cast<const self_t&>(src);
+			self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+			if (overwrite)
+			{
+				std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
+			}
+			else
+			{
+				container_t new_values(src_typed_param.mValues);
+				std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
+				std::swap(dst_typed_param.mValues, new_values);
+			}
+
+			if (src_typed_param.begin() != src_typed_param.end())
+			{
+				dst_typed_param.setProvided();
+			}
+			return true;
+		}
+
+		container_t		mValues;
+	};
+
+	// container of block parameters
+	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
+	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> 
+	:	public Param
+	{
+	public:
+		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>	self_t;
+		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>				param_value_t;
+		typedef typename std::vector<param_value_t>						container_t;
+		typedef const container_t&										value_assignment_t;
+		typedef typename param_value_t::value_t							value_t;
+		typedef NAME_VALUE_LOOKUP										name_value_lookup_t;
+
+		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
+		:	Param(block_descriptor.mCurrentBlockPtr)
+		{
+			std::copy(value.begin(), value.end(), back_inserter(mValues));
+
+			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+			{
+				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+												&mergeWith,
+												&deserializeParam,
+												&serializeParam,
+												validate_func,
+												&inspectParam,
+												min_count, max_count));
+				BaseBlock::addParam(block_descriptor, param_descriptor, name);
+			}
+		} 
+
+		bool isProvided() const { return Param::anyProvided(); }
+
+		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) 
+		{ 
+			self_t& typed_param = static_cast<self_t&>(param);
+			bool new_value = false;
+
+			if (new_name || typed_param.mValues.empty())
+			{
+				new_value = true;
+				typed_param.mValues.push_back(value_t());
+			}
+
+			param_value_t& value = typed_param.mValues.back();
+
+			// attempt to parse block...
+			if(value.deserializeBlock(parser, name_stack_range, new_name))
+			{
+				typed_param.setProvided();
+				return true;
+			}
+			else if(name_value_lookup_t::valueNamesExist())
+			{
+				// try to parse a known named value
+				std::string name;
+				if (parser.readValue(name))
+				{
+					// try to parse a per type named value
+					if (name_value_lookup_t::getValueFromName(name, value.getValue()))
+					{
+						typed_param.mValues.back().setValueName(name);
+						typed_param.setProvided();
+						return true;
+					}
+
+				}
+			}
+
+			if (new_value)
+			{	// failed to parse new value, pop it off
+				typed_param.mValues.pop_back();
+			}
+
+			return false;
+		}
+
+		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		{
+			const self_t& typed_param = static_cast<const self_t&>(param);
+			if (!typed_param.isProvided() || name_stack.empty()) return;
+
+			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
+				it != end_it;
+				++it)
+			{
+				name_stack.back().second = true;
+
+				std::string key = it->getValueName();
+				if (!key.empty())
+				{
+					parser.writeValue(key, name_stack);
+				}
+				// Not parsed via named values, write out value directly
+				// NOTE: currently we don't worry about removing default values in Multiple
+				else 
+				{
+					it->serializeBlock(parser, name_stack, NULL);
+				}
+			}
+		}
+
+		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+		{
+			// I am a vector of blocks, so describe my contents recursively
+			param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count);
+		}
+
+		void set(value_assignment_t val, bool flag_as_provided = true)
+		{
+			mValues = val;
+			setProvided(flag_as_provided);
+		}
+
+		param_value_t& add()
+		{
+			mValues.push_back(value_t());
+			setProvided();
+			return mValues.back();
+		}
+
+		void add(const value_t& item)
+		{
+			mValues.push_back(item);
+			setProvided();
+		}
+
+		void add(const typename name_value_lookup_t::name_t& name)
+		{
+			value_t value;
+
+			// try to parse a per type named value
+			if (name_value_lookup_t::getValueFromName(name, value))
+			{
+				add(value);
+				mValues.back().setValueName(name);
+			}
+		}
+
+		// implicit conversion
+		operator value_assignment_t() const { return mValues; } 
+		// explicit conversion
+		value_assignment_t operator()() const { return mValues; }
+
+		typedef typename container_t::iterator iterator;
+		typedef typename container_t::const_iterator const_iterator;
+		iterator begin() { return mValues.begin(); }
+		iterator end() { return mValues.end(); }
+		const_iterator begin() const { return mValues.begin(); }
+		const_iterator end() const { return mValues.end(); }
+		bool empty() const { return mValues.empty(); }
+		size_t size() const { return mValues.size(); }
+
+		U32 numValidElements() const
+		{
+			U32 count = 0;
+			for (const_iterator it = mValues.begin(), end_it = mValues.end();
+				it != end_it;
+				++it)
+			{
+				if(it->validateBlock(false)) count++;
+			}
+			return count;
+		}
+
+	protected:
+
+		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+		{
+			const self_t& src_typed_param = static_cast<const self_t&>(src);
+			self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+			if (overwrite)
+			{
+				std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
+			}
+			else
+			{
+				container_t new_values(src_typed_param.mValues);
+				std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
+				std::swap(dst_typed_param.mValues, new_values);
+			}
+
+			if (src_typed_param.begin() != src_typed_param.end())
+			{
+				dst_typed_param.setProvided();
+			}
+
+			return true;
+		}
+
+		container_t			mValues;
+	};
+
+	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
+	class ChoiceBlock : public BASE_BLOCK
+	{
+		typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK>	self_t;
+		typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK>	enclosing_block_t;
+		typedef BASE_BLOCK								base_block_t;
+		
+		LOG_CLASS(self_t);
+	public:
+		// take all provided params from other and apply to self
+		bool overwriteFrom(const self_t& other)
+		{
+			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true);
+		}
+
+		// take all provided params that are not already provided, and apply to self
+		bool fillFrom(const self_t& other)
+		{
+			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false);
+		}
+
+		bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
+		{
+			bool source_override = source_provided && (overwrite || !dest_provided);
+
+			if (source_override || source.mCurChoice == mCurChoice)
+			{
+				return mergeBlock(block_data, source, overwrite);
+			}
+			return false;
+		}
+
+		// merge with other block
+		bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite)
+		{
+			mCurChoice = other.mCurChoice;
+			return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite);
+		}
+
+		// clear out old choice when param has changed
+		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
+		{ 
+			param_handle_t changed_param_handle = base_block_t::getHandleFromParam(&changed_param);
+			// if we have a new choice...
+			if (changed_param_handle != mCurChoice)
+			{
+				// clear provided flag on previous choice
+				Param* previous_choice = base_block_t::getParamFromHandle(mCurChoice);
+				if (previous_choice) 
+				{
+					previous_choice->setProvided(false);
+				}
+				mCurChoice = changed_param_handle;
+			}
+			base_block_t::paramChanged(changed_param, user_provided);
+		}
+
+		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
+		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
+
+	protected:
+		ChoiceBlock()
+		:	mCurChoice(0)
+		{
+			BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK));
+		}
+
+		// Alternatives are mutually exclusive wrt other Alternatives in the same block.  
+		// One alternative in a block will always have isChosen() == true.
+		// At most one alternative in a block will have isProvided() == true.
+		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+		class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>
+		{
+		public:
+			friend class ChoiceBlock<DERIVED_BLOCK>;
+
+			typedef Alternative<T, NAME_VALUE_LOOKUP>									self_t;
+			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;
+			typedef typename super_t::value_assignment_t								value_assignment_t;
+
+			using super_t::operator =;
+
+			explicit Alternative(const char* name = "", value_assignment_t val = defaultValue<T>())
+			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1),
+				mOriginalValue(val)
+			{
+				// assign initial choice to first declared option
+				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr);
+				if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))
+				{
+					if(blockp->mCurChoice == 0)
+					{
+						blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this);
+					}
+				}
+			}
+
+			void choose()
+			{
+				static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true);
+			}
+
+			void chooseAs(value_assignment_t val)
+			{
+				super_t::set(val);
+			}
+
+			void operator =(value_assignment_t val)
+			{
+				super_t::set(val);
+			}
+
+			void operator()(typename super_t::value_assignment_t val) 
+			{ 
+				super_t::set(val);
+			}
+
+			operator value_assignment_t() const 
+			{
+				return (*this)();
+			} 
+
+			value_assignment_t operator()() const 
+			{ 
+				if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)
+				{
+					return super_t::getValue(); 
+				}
+				return mOriginalValue;
+			} 
+
+			bool isChosen() const
+			{
+				return static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this;
+			}
+		
+		private:
+			T			mOriginalValue;
+		};
+
+	protected:
+		static BlockDescriptor& selfBlockDescriptor()
+		{
+			static BlockDescriptor sBlockDescriptor;
+			return sBlockDescriptor;
+		}
+
+	private:
+		param_handle_t	mCurChoice;
+
+		const Param* getCurrentChoice() const
+		{
+			return base_block_t::getParamFromHandle(mCurChoice);
+		}
+	};
+
+	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
+	class Block 
+	:	public BASE_BLOCK
+	{
+		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	self_t;
+		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	block_t;
+
+	public:
+		typedef BASE_BLOCK base_block_t;
+
+		// take all provided params from other and apply to self
+		bool overwriteFrom(const self_t& other)
+		{
+			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true);
+		}
+
+		// take all provided params that are not already provided, and apply to self
+		bool fillFrom(const self_t& other)
+		{
+			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false);
+		}
+
+		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
+		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
+
+	protected:
+		Block()
+		{
+			//#pragma message("Parsing LLInitParam::Block")
+			BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK));
+		}
+
+		//
+		// Nested classes for declaring parameters
+		//
+		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+		class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>
+		{
+		public:
+			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;
+			typedef typename super_t::value_assignment_t								value_assignment_t;
+
+			using super_t::operator();
+			using super_t::operator =;
+			
+			explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>())
+			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1)
+			{
+				//#pragma message("Parsing LLInitParam::Block::Optional")
+			}
+
+			Optional& operator =(value_assignment_t val)
+			{
+				set(val);
+				return *this;
+			}
+
+			DERIVED_BLOCK& operator()(value_assignment_t val)
+			{
+				super_t::set(val);
+				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+			}
+		};
+
+		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+		class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
+		{
+		public:
+			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;
+			typedef Mandatory<T, NAME_VALUE_LOOKUP>										self_t;
+			typedef typename super_t::value_assignment_t								value_assignment_t;
+
+			using super_t::operator();
+			using super_t::operator =;
+
+			// mandatory parameters require a name to be parseable
+			explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>())
+			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1)
+			{}
+
+			Mandatory& operator =(value_assignment_t val)
+			{
+				set(val);
+				return *this;
+			}
+
+			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
+			{
+				super_t::set(val);
+				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+			}
+
+			static bool validate(const Param* p)
+			{
+				// valid only if provided
+				return static_cast<const self_t*>(p)->isProvided();
+			}
+
+		};
+
+		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+		class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>
+		{
+		public:
+			typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>	super_t;
+			typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP>							self_t;
+			typedef typename super_t::container_t									container_t;
+			typedef typename super_t::value_assignment_t							value_assignment_t;
+			typedef typename super_t::iterator										iterator;
+			typedef typename super_t::const_iterator								const_iterator;
+
+			explicit Multiple(const char* name = "")
+			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)
+			{}
+
+			Multiple& operator =(value_assignment_t val)
+			{
+				set(val);
+				return *this;
+			}
+
+			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
+			{
+				super_t::set(val);
+				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+			}
+
+			static bool validate(const Param* paramp) 
+			{
+				U32 num_valid = ((super_t*)paramp)->numValidElements();
+				return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount;
+			}
+		};
+
+		class Deprecated : public Param
+		{
+		public:
+			explicit Deprecated(const char* name)
+			:	Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr)
+			{
+				BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor();
+				if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+				{
+					ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+													block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+													NULL,
+													&deserializeParam,
+													NULL,
+													NULL,
+													NULL, 
+													0, S32_MAX));
+					BaseBlock::addParam(block_descriptor, param_descriptor, name);
+				}
+			}
+			
+			static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
+			{
+				if (name_stack_range.first == name_stack_range.second)
+				{
+					//std::string message = llformat("Deprecated value %s ignored", getName().c_str());
+					//parser.parserWarning(message);
+					return true;
+				}
+
+				return false;
+			}
+		};
+
+		// different semantics for documentation purposes, but functionally identical
+		typedef Deprecated Ignored;
+
+	protected:
+		static BlockDescriptor& selfBlockDescriptor()
+		{
+			static BlockDescriptor sBlockDescriptor;
+			return sBlockDescriptor;
+		}
+
+		template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block>
+		void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param, 
+			typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value)
+		{
+			if (!param.isProvided())
+			{
+				param.set(value, false);
+			}
+		}
+
+	};
+	
+	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
+	class BatchBlock
+	:	public Block<DERIVED_BLOCK, BASE_BLOCK>
+	{
+	public:
+		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> self_t;
+		typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t;
+
+		BatchBlock()
+		{}
+
+		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)
+		{
+			if (new_name)
+			{
+				// reset block
+				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
+			}
+			return super_t::deserializeBlock(p, name_stack_range, new_name);
+		}
+
+		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
+		{
+			if (overwrite)
+			{
+				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
+				// merge individual parameters into destination
+				return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite);
+			}
+			return false;
+		}
+	protected:
+		static const DERIVED_BLOCK& defaultBatchValue()
+		{
+			static DERIVED_BLOCK default_value;
+			return default_value;
+		}
+	};
+
+	// FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class
+	// and not the derived class with the actual params
+	template<typename DERIVED_BLOCK,
+			typename BASE_BLOCK,
+			typename NAME_VALUE_LOOKUP>
+	class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>,
+					NAME_VALUE_LOOKUP,
+					true>
+	:	public NAME_VALUE_LOOKUP,
+		protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK>
+	{
+	public:
+		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t;
+		typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>&	value_assignment_t;
+		typedef block_t value_t;
+
+		ParamValue()
+		:	block_t(),
+			mValidated(false)
+		{}
+
+		ParamValue(value_assignment_t other)
+		:	block_t(other),
+			mValidated(false)
+		{
+		}
+
+		void setValue(value_assignment_t val)
+		{
+			*this = val;
+		}
+
+		value_assignment_t getValue() const
+		{
+			return *this;
+		}
+
+		BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& getValue()
+		{
+			return *this;
+		}
+
+		operator value_assignment_t() const
+		{
+			return *this;
+		}
+
+		value_assignment_t operator()() const
+		{
+			return *this;
+		}
+
+	protected:
+		mutable bool 	mValidated; // lazy validation flag
+	};
+
+	template<typename T, bool IS_BLOCK>
+	class ParamValue <BaseBlock::Lazy<T>,
+					TypeValues<T>,
+					IS_BLOCK>
+	:	public IsBlock<T>::base_class_t
+	{
+	public:
+		typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<T>, false> self_t;
+		typedef const T& value_assignment_t;
+		typedef T value_t;
+	
+		ParamValue()
+		:	mValue(),
+			mValidated(false)
+		{}
+
+		ParamValue(value_assignment_t other)
+		:	mValue(other),
+			mValidated(false)
+		{}
+
+		void setValue(value_assignment_t val)
+		{
+			mValue.set(val);
+		}
+
+		value_assignment_t getValue() const
+		{
+			return mValue.get();
+		}
+
+		T& getValue()
+		{
+			return mValue.get();
+		}
+
+		operator value_assignment_t() const
+		{
+			return mValue.get();
+		}
+
+		value_assignment_t operator()() const
+		{
+			return mValue.get();
+		}
+
+		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)
+		{
+			return mValue.get().deserializeBlock(p, name_stack_range, new_name);
+		}
+
+		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
+		{
+			if (mValue.empty()) return;
+			
+			mValue.get().serializeBlock(p, name_stack, diff_block);
+		}
+
+		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
+		{
+			if (mValue.empty()) return false;
+
+			return mValue.get().inspectBlock(p, name_stack, min_count, max_count);
+		}
+
+	protected:
+		mutable bool 	mValidated; // lazy validation flag
+
+	private:
+		BaseBlock::Lazy<T>	mValue;
+	};
+
+	template <>
+	class ParamValue <LLSD,
+					TypeValues<LLSD>,
+					false>
+	:	public TypeValues<LLSD>,
+		public BaseBlock
+	{
+	public:
+		typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t;
+		typedef const LLSD&	value_assignment_t;
+
+		ParamValue()
+		:	mValidated(false)
+		{}
+
+		ParamValue(value_assignment_t other)
+		:	mValue(other),
+			mValidated(false)
+		{}
+
+		void setValue(value_assignment_t val) { mValue = val; }
+
+		value_assignment_t getValue() const { return mValue; }
+		LLSD& getValue() { return mValue; }
+
+		operator value_assignment_t() const { return mValue; }
+		value_assignment_t operator()() const { return mValue; }
+		
+
+		// block param interface
+		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
+		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
+		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
+		{
+			//TODO: implement LLSD params as schema type Any
+			return true;
+		}
+
+	protected:
+		mutable bool 	mValidated; // lazy validation flag
+
+	private:
+		static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack);
+
+		LLSD mValue;
+	};
+
+	template<typename T>
+	class CustomParamValue
+	:	public Block<ParamValue<T, TypeValues<T> > >,
+		public TypeValues<T>
+	{
+	public:
+		typedef enum e_value_age
+		{	
+			VALUE_NEEDS_UPDATE,		// mValue needs to be refreshed from the block parameters
+			VALUE_AUTHORITATIVE,	// mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue)
+			BLOCK_AUTHORITATIVE		// mValue is derived from the block parameters, which are authoritative
+		} EValueAge;
+
+		typedef ParamValue<T, TypeValues<T> >	derived_t;
+		typedef CustomParamValue<T>				self_t;
+		typedef Block<derived_t>				block_t;
+		typedef const T&						value_assignment_t;
+		typedef T								value_t;
+
+
+		CustomParamValue(const T& value = T())
+		:	mValue(value),
+			mValueAge(VALUE_AUTHORITATIVE),
+			mValidated(false)
+		{}
+
+		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name)
+		{
+			derived_t& typed_param = static_cast<derived_t&>(*this);
+			// try to parse direct value T
+			if (name_stack_range.first == name_stack_range.second)
+			{
+				if(parser.readValue(typed_param.mValue))
+				{
+					typed_param.mValueAge = VALUE_AUTHORITATIVE;
+					typed_param.updateBlockFromValue(false);
+
+					typed_param.clearValueName();
+
+					return true;
+				}
+			}
+
+			// fall back on parsing block components for T
+			return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
+		}
+
+		void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
+		{
+			const derived_t& typed_param = static_cast<const derived_t&>(*this);
+			const derived_t* diff_param = static_cast<const derived_t*>(diff_block);
+			
+			std::string key = typed_param.getValueName();
+
+			// first try to write out name of name/value pair
+			if (!key.empty())
+			{
+				if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key))
+				{
+					parser.writeValue(key, name_stack);
+				}
+			}
+			// then try to serialize value directly
+			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))
+            {
+				
+				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
+				{
+					//RN: *always* serialize provided components of BlockValue (don't pass diff_param on),
+					// since these tend to be viewed as the constructor arguments for the value T.  It seems
+					// cleaner to treat the uniqueness of a BlockValue according to the generated value, and
+					// not the individual components.  This way <color red="0" green="1" blue="0"/> will not
+					// be exported as <color green="1"/>, since it was probably the intent of the user to 
+					// be specific about the RGB color values.  This also fixes an issue where we distinguish
+					// between rect.left not being provided and rect.left being explicitly set to 0 (same as default)
+
+					if (typed_param.mValueAge == VALUE_AUTHORITATIVE)
+					{
+						// if the value is authoritative but the parser doesn't accept the value type
+						// go ahead and make a copy, and splat the value out to its component params
+						// and serialize those params
+						derived_t copy(typed_param);
+						copy.updateBlockFromValue(true);
+						copy.block_t::serializeBlock(parser, name_stack, NULL);
+					}
+					else
+					{
+						block_t::serializeBlock(parser, name_stack, NULL);
+					}
+				}
+			}
+		}
+
+		bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
+		{
+			// first, inspect with actual type...
+			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
+			if (TypeValues<T>::getPossibleValues())
+			{
+				//...then inspect with possible string values...
+				parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues());
+			}
+			// then recursively inspect contents...
+			return block_t::inspectBlock(parser, name_stack, min_count, max_count);
+		}
+
+		bool validateBlock(bool emit_errors = true) const
+		{
+			if (mValueAge == VALUE_NEEDS_UPDATE)
+			{
+				if (block_t::validateBlock(emit_errors))
+				{
+					// clear stale keyword associated with old value
+					TypeValues<T>::clearValueName();
+					mValueAge = BLOCK_AUTHORITATIVE;
+					static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();
+					return true;
+				}
+				else
+				{
+					//block value incomplete, so not considered provided
+					// will attempt to revalidate on next call to isProvided()
+					return false;  
+				}
+			}
+			else
+			{
+				// we have a valid value in hand
+				return true;
+			}
+		}
+
+ 		// propagate change status up to enclosing block
+		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
+		{ 
+			BaseBlock::paramChanged(changed_param, user_provided);
+			if (user_provided)
+			{
+				// a parameter changed, so our value is out of date
+				mValueAge = VALUE_NEEDS_UPDATE;
+			}
+		}
+			
+		void setValue(value_assignment_t val)
+		{
+			derived_t& typed_param = static_cast<derived_t&>(*this);
+			// set param version number to be up to date, so we ignore block contents
+			mValueAge = VALUE_AUTHORITATIVE;
+			mValue = val;
+			typed_param.clearValueName();
+			static_cast<derived_t*>(this)->updateBlockFromValue(false);
+		}
+
+		value_assignment_t getValue() const
+		{
+			validateBlock(true);
+			return mValue;
+		}
+
+		T& getValue() 
+		{
+			validateBlock(true);
+			return mValue;
+		}
+
+		operator value_assignment_t() const
+		{
+			return getValue();
+		}
+
+		value_assignment_t operator()() const
+		{
+			return getValue();
+		}
+
+	protected:
+
+		// use this from within updateValueFromBlock() to set the value without making it authoritative
+		void updateValue(value_assignment_t value)
+		{
+			mValue = value;
+		}
+
+		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
+		{
+			bool source_override = source_provided && (overwrite || !dst_provided);
+
+			const derived_t& src_typed_param = static_cast<const derived_t&>(source);
+
+			if (source_override && src_typed_param.mValueAge == VALUE_AUTHORITATIVE)
+			{
+				// copy value over
+				setValue(src_typed_param.getValue());
+				return true;
+			}
+			// merge individual parameters into destination
+			if (mValueAge == VALUE_AUTHORITATIVE)
+			{
+				static_cast<derived_t*>(this)->updateBlockFromValue(dst_provided);
+			}
+			return mergeBlock(block_data, source, overwrite);
+		}
+
+		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
+		{
+			return block_t::mergeBlock(block_data, source, overwrite);
+		}
+
+		mutable bool 		mValidated; // lazy validation flag
+
+	private:
+		mutable T			mValue;
+		mutable EValueAge	mValueAge;
+	};
+}
+
+
+#endif // LL_LLPARAM_H
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
new file mode 100644
index 0000000000..36ce6a97b7
--- /dev/null
+++ b/indra/llcommon/llregistry.h
@@ -0,0 +1,351 @@
+/** 
+ * @file llregistry.h
+ * @brief template classes for registering name, value pairs in nested scopes, statically, etc.
+ *
+ * $LicenseInfo:firstyear=2001&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 LL_LLREGISTRY_H
+#define LL_LLREGISTRY_H
+
+#include <list>
+
+#include <boost/type_traits.hpp>
+#include "llsingleton.h"
+
+template <typename T>
+class LLRegistryDefaultComparator
+{
+	bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; }
+};
+
+template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
+class LLRegistry
+{
+public:
+	typedef LLRegistry<KEY, VALUE, COMPARATOR>											registry_t;
+	typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type	ref_const_key_t;
+	typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type	ref_const_value_t;
+	typedef typename boost::add_reference<VALUE>::type									ref_value_t;
+	typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type	ptr_const_value_t;
+	typedef typename boost::add_pointer<VALUE>::type									ptr_value_t;
+
+	class Registrar
+	{
+		friend class LLRegistry<KEY, VALUE, COMPARATOR>;
+	public:
+		typedef typename std::map<KEY, VALUE> registry_map_t;
+
+		bool add(ref_const_key_t key, ref_const_value_t value)
+		{
+			if (mMap.insert(std::make_pair(key, value)).second == false)
+			{
+				llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
+				return false;
+			}
+			return true;
+		}
+
+		void remove(ref_const_key_t key)
+		{
+			mMap.erase(key);
+		}
+
+		void replace(ref_const_key_t key, ref_const_value_t value)
+		{
+			mMap[key] = value;
+		}
+
+		typename registry_map_t::const_iterator beginItems() const
+		{
+			return mMap.begin();
+		}
+
+		typename registry_map_t::const_iterator endItems() const
+		{
+			return mMap.end();
+		}
+
+	protected:
+		ptr_value_t getValue(ref_const_key_t key)
+		{
+			typename registry_map_t::iterator found_it = mMap.find(key);
+			if (found_it != mMap.end())
+			{
+				return &(found_it->second);
+			}
+			return NULL;
+		}
+
+		ptr_const_value_t getValue(ref_const_key_t key) const
+		{
+			typename registry_map_t::const_iterator found_it = mMap.find(key);
+			if (found_it != mMap.end())
+			{
+				return &(found_it->second);
+			}
+			return NULL;
+		}
+
+		// if the registry is used to store pointers, and null values are valid entries
+		// then use this function to check the existence of an entry
+		bool exists(ref_const_key_t key) const
+		{
+			return mMap.find(key) != mMap.end();
+		}
+
+		bool empty() const
+		{
+			return mMap.empty();
+		}
+
+	protected:
+		// use currentRegistrar() or defaultRegistrar()
+		Registrar() {}
+		~Registrar() {}
+
+	private:
+		registry_map_t											mMap;
+	};
+	
+	typedef typename std::list<Registrar*> scope_list_t;
+	typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
+	typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
+	
+	LLRegistry() 
+	{}
+
+	~LLRegistry() {}
+
+	ptr_value_t getValue(ref_const_key_t key)
+	{
+		for(scope_list_iterator_t it = mActiveScopes.begin();
+			it != mActiveScopes.end();
+			++it)
+		{
+			ptr_value_t valuep = (*it)->getValue(key);
+			if (valuep != NULL) return valuep;
+		}
+		return mDefaultRegistrar.getValue(key);
+	}
+
+	ptr_const_value_t getValue(ref_const_key_t key) const
+	{
+		for(scope_list_const_iterator_t it = mActiveScopes.begin();
+			it != mActiveScopes.end();
+			++it)
+		{
+			ptr_value_t valuep = (*it)->getValue(key);
+			if (valuep != NULL) return valuep;
+		}
+		return mDefaultRegistrar.getValue(key);
+	}
+
+	bool exists(ref_const_key_t key) const
+	{
+		for(scope_list_const_iterator_t it = mActiveScopes.begin();
+			it != mActiveScopes.end();
+			++it)
+		{
+			if ((*it)->exists(key)) return true;
+		}
+
+		return mDefaultRegistrar.exists(key);
+	}
+
+	bool empty() const
+	{
+		for(scope_list_const_iterator_t it = mActiveScopes.begin();
+			it != mActiveScopes.end();
+			++it)
+		{
+			if (!(*it)->empty()) return false;
+		}
+
+		return mDefaultRegistrar.empty();
+	}
+
+
+	Registrar& defaultRegistrar()
+	{
+		return mDefaultRegistrar;
+	}
+
+	const Registrar& defaultRegistrar() const
+	{
+		return mDefaultRegistrar;
+	}
+
+
+	Registrar& currentRegistrar()
+	{
+		if (!mActiveScopes.empty()) 
+		{
+			return *mActiveScopes.front();
+		}
+
+		return mDefaultRegistrar;
+	}
+
+	const Registrar& currentRegistrar() const
+	{
+		if (!mActiveScopes.empty()) 
+		{
+			return *mActiveScopes.front();
+		}
+
+		return mDefaultRegistrar;
+	}
+
+
+protected:
+	void addScope(Registrar* scope)
+	{
+		// newer scopes go up front
+		mActiveScopes.insert(mActiveScopes.begin(), scope);
+	}
+
+	void removeScope(Registrar* scope)
+	{
+		// O(N) but should be near the beggining and N should be small and this is safer than storing iterators
+		scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
+		if (iter != mActiveScopes.end())
+		{
+			mActiveScopes.erase(iter);
+		}
+	}
+
+private:
+	scope_list_t	mActiveScopes;
+	Registrar		mDefaultRegistrar;
+};
+
+template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
+class LLRegistrySingleton
+	:	public LLRegistry<KEY, VALUE, COMPARATOR>,
+		public LLSingleton<DERIVED_TYPE>
+{
+	friend class LLSingleton<DERIVED_TYPE>;
+public:
+	typedef LLRegistry<KEY, VALUE, COMPARATOR>		registry_t;
+	typedef const KEY&								ref_const_key_t;
+	typedef const VALUE&							ref_const_value_t;
+	typedef VALUE*									ptr_value_t;
+	typedef const VALUE*							ptr_const_value_t;
+	typedef LLSingleton<DERIVED_TYPE>				singleton_t;
+
+	class ScopedRegistrar : public registry_t::Registrar
+	{
+	public:
+		ScopedRegistrar(bool push_scope = true) 
+		{
+			if (push_scope)
+			{
+				pushScope();
+			}
+		}
+
+		~ScopedRegistrar()
+		{
+			if (!singleton_t::destroyed())
+			{
+				popScope();
+			}
+		}
+
+		void pushScope()
+		{
+			singleton_t::instance().addScope(this);
+		}
+		
+		void popScope()
+		{
+			singleton_t::instance().removeScope(this);
+		}
+		
+		ptr_value_t getValueFromScope(ref_const_key_t key)
+		{
+			return getValue(key);
+		}
+
+		ptr_const_value_t getValueFromScope(ref_const_key_t key) const
+		{
+			return getValue(key);
+		}
+
+	private:
+		typename std::list<typename registry_t::Registrar*>::iterator	mListIt;
+	};
+
+	class StaticRegistrar : public registry_t::Registrar
+	{
+	public:
+		virtual ~StaticRegistrar() {}
+		StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
+		{
+			singleton_t::instance().mStaticScope->add(key, value);
+		}
+	};
+
+	// convenience functions
+	typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
+	static ref_registrar_t currentRegistrar()
+	{
+		return singleton_t::instance().registry_t::currentRegistrar();
+	}
+
+	static ref_registrar_t defaultRegistrar()
+	{
+		return singleton_t::instance().registry_t::defaultRegistrar();
+	}
+	
+	static ptr_value_t getValue(ref_const_key_t key)
+	{
+		return singleton_t::instance().registry_t::getValue(key);
+	}
+
+protected:
+	// DERIVED_TYPE needs to derive from LLRegistrySingleton
+	LLRegistrySingleton()
+		: mStaticScope(NULL)
+	{}
+
+	virtual void initSingleton()
+	{
+		mStaticScope = new ScopedRegistrar();
+	}
+
+	virtual ~LLRegistrySingleton() 
+	{
+		delete mStaticScope;
+	}
+
+private:
+	ScopedRegistrar*	mStaticScope;
+};
+
+// helper macro for doing static registration
+#define GLUED_TOKEN(x, y) x ## y
+#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y)
+#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE);
+
+#endif
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 772f173f17..9226f36e73 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -12,7 +12,6 @@ include(LLRender)
 include(LLWindow)
 include(LLVFS)
 include(LLXML)
-include(LLXUIXML)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
@@ -24,7 +23,6 @@ include_directories(
     ${LLWINDOW_INCLUDE_DIRS}
     ${LLVFS_INCLUDE_DIRS}
     ${LLXML_INCLUDE_DIRS}
-    ${LLXUIXML_INCLUDE_DIRS}
     )
 
 set(llui_SOURCE_FILES
@@ -100,11 +98,13 @@ set(llui_SOURCE_FILES
     lltextutil.cpp
     lltextvalidate.cpp
     lltimectrl.cpp
+    lltrans.cpp
     lltransutil.cpp
     lltoggleablemenu.cpp
     lltoolbar.cpp
     lltooltip.cpp
     llui.cpp
+    lluicolor.cpp
     lluicolortable.cpp
     lluictrl.cpp
     lluictrlfactory.cpp
@@ -121,6 +121,7 @@ set(llui_SOURCE_FILES
     llview.cpp
     llviewquery.cpp
     llwindowshade.cpp
+    llxuiparser.cpp
     )
     
 set(llui_HEADER_FILES
@@ -208,6 +209,7 @@ set(llui_HEADER_FILES
     lltoggleablemenu.h
     lltoolbar.h
     lltooltip.h
+    lltrans.h
     lltransutil.h
     lluicolortable.h
     lluiconstants.h
@@ -215,6 +217,7 @@ set(llui_HEADER_FILES
     lluictrl.h
     lluifwd.h
     llui.h
+    lluicolor.h
     lluiimage.h
     lluistring.h
     llundo.h
@@ -228,6 +231,7 @@ set(llui_HEADER_FILES
     llview.h
     llviewquery.h
     llwindowshade.h
+    llxuiparser.h
     )
 
 set_source_files_properties(${llui_HEADER_FILES}
diff --git a/indra/llui/lltrans.cpp b/indra/llui/lltrans.cpp
new file mode 100644
index 0000000000..5388069c24
--- /dev/null
+++ b/indra/llui/lltrans.cpp
@@ -0,0 +1,295 @@
+/**
+ * @file lltrans.cpp
+ * @brief LLTrans implementation
+ *
+ * $LicenseInfo:firstyear=2000&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 "lltrans.h"
+
+#include "llfasttimer.h"	// for call count statistics
+#include "llxuiparser.h"
+#include "llsd.h"
+#include "llxmlnode.h"
+
+#include <map>
+
+LLTrans::template_map_t LLTrans::sStringTemplates;
+LLStringUtil::format_map_t LLTrans::sDefaultArgs;
+
+struct StringDef : public LLInitParam::Block<StringDef>
+{
+	Mandatory<std::string> name;
+	Mandatory<std::string> value;
+
+	StringDef()
+	:	name("name"),
+		value("value")
+	{}
+};
+
+struct StringTable : public LLInitParam::Block<StringTable>
+{
+	Multiple<StringDef> strings;
+	StringTable()
+	:	strings("string")
+	{}
+};
+
+//static 
+bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& default_args)
+{
+	std::string xml_filename = "(strings file)";
+	if (!root->hasName("strings"))
+	{
+		llerrs << "Invalid root node name in " << xml_filename 
+			<< ": was " << root->getName() << ", expected \"strings\"" << llendl;
+	}
+
+	StringTable string_table;
+	LLXUIParser parser;
+	parser.readXUI(root, string_table, xml_filename);
+
+	if (!string_table.validateBlock())
+	{
+		llerrs << "Problem reading strings: " << xml_filename << llendl;
+		return false;
+	}
+	
+	sStringTemplates.clear();
+	sDefaultArgs.clear();
+	
+	for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings.begin();
+		it != string_table.strings.end();
+		++it)
+	{
+		LLTransTemplate xml_template(it->name, it->value);
+		sStringTemplates[xml_template.mName] = xml_template;
+		
+		std::set<std::string>::const_iterator iter = default_args.find(xml_template.mName);
+		if (iter != default_args.end())
+		{
+			std::string name = *iter;
+			if (name[0] != '[')
+				name = llformat("[%s]",name.c_str());
+			sDefaultArgs[name] = xml_template.mText;
+		}
+	}
+
+	return true;
+}
+
+
+//static
+bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root)
+{
+	std::string xml_filename = "(language strings file)";
+	if (!root->hasName("strings"))
+	{
+		llerrs << "Invalid root node name in " << xml_filename 
+		<< ": was " << root->getName() << ", expected \"strings\"" << llendl;
+	}
+	
+	StringTable string_table;
+	LLXUIParser parser;
+	parser.readXUI(root, string_table, xml_filename);
+	
+	if (!string_table.validateBlock())
+	{
+		llerrs << "Problem reading strings: " << xml_filename << llendl;
+		return false;
+	}
+		
+	for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings.begin();
+		it != string_table.strings.end();
+		++it)
+	{
+		// share the same map with parseStrings() so we can search the strings using the same getString() function.- angela
+		LLTransTemplate xml_template(it->name, it->value);
+		sStringTemplates[xml_template.mName] = xml_template;
+	}
+	
+	return true;
+}
+
+
+
+static LLFastTimer::DeclareTimer FTM_GET_TRANS("Translate string");
+
+//static 
+std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args)
+{
+	// Don't care about time as much as call count.  Make sure we're not
+	// calling LLTrans::getString() in an inner loop. JC
+	LLFastTimer timer(FTM_GET_TRANS);
+	
+	template_map_t::iterator iter = sStringTemplates.find(xml_desc);
+	if (iter != sStringTemplates.end())
+	{
+		std::string text = iter->second.mText;
+		LLStringUtil::format_map_t args = sDefaultArgs;
+		args.insert(msg_args.begin(), msg_args.end());
+		LLStringUtil::format(text, args);
+		
+		return text;
+	}
+	else
+	{
+		LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;
+		return "MissingString("+xml_desc+")";
+	}
+}
+
+//static
+std::string LLTrans::getString(const std::string &xml_desc, const LLSD& msg_args)
+{
+	// Don't care about time as much as call count.  Make sure we're not
+	// calling LLTrans::getString() in an inner loop. JC
+	LLFastTimer timer(FTM_GET_TRANS);
+
+	template_map_t::iterator iter = sStringTemplates.find(xml_desc);
+	if (iter != sStringTemplates.end())
+	{
+		std::string text = iter->second.mText;
+		LLStringUtil::format(text, msg_args);
+		return text;
+	}
+	else
+	{
+		LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;
+		return "MissingString("+xml_desc+")";
+	}
+}
+
+//static 
+bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args)
+{
+	LLFastTimer timer(FTM_GET_TRANS);
+	
+	template_map_t::iterator iter = sStringTemplates.find(xml_desc);
+	if (iter != sStringTemplates.end())
+	{
+		std::string text = iter->second.mText;
+		LLStringUtil::format_map_t args = sDefaultArgs;
+		args.insert(msg_args.begin(), msg_args.end());
+		LLStringUtil::format(text, args);
+		result = text;
+		return true;
+	}
+	else
+	{
+		LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;	
+		return false;
+	}
+}
+
+//static
+bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLSD& msg_args)
+{
+	LLFastTimer timer(FTM_GET_TRANS);
+
+	template_map_t::iterator iter = sStringTemplates.find(xml_desc);
+	if (iter != sStringTemplates.end())
+	{
+		std::string text = iter->second.mText;
+		LLStringUtil::format(text, msg_args);
+		result = text;
+		return true;
+	}
+	else
+	{
+		LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;	
+		return false;
+	}
+}
+
+//static
+std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count)
+{
+	// Compute which string identifier to use
+	const char* form = "";
+	if (language == "ru") // Russian
+	{
+		// From GNU ngettext()
+		// Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
+		if (count % 10 == 1
+			&& count % 100 != 11)
+		{
+			// singular, "1 item"
+			form = "A";
+		}
+		else if (count % 10 >= 2
+			&& count % 10 <= 4
+			&& (count % 100 < 10 || count % 100 >= 20) )
+		{
+			// special case "2 items", "23 items", but not "13 items"
+			form = "B";
+		}
+		else
+		{
+			// English-style plural, "5 items"
+			form = "C";
+		}
+	}
+	else if (language == "fr" || language == "pt") // French, Brazilian Portuguese
+	{
+		// French and Portuguese treat zero as a singular "0 item" not "0 items"
+		if (count == 0 || count == 1)
+		{
+			form = "A";
+		}
+		else
+		{
+			// English-style plural
+			form = "B";
+		}
+	}
+	else // default
+	{
+		// languages like English with 2 forms, singular and plural
+		if (count == 1)
+		{
+			// "1 item"
+			form = "A";
+		}
+		else
+		{
+			// "2 items", also use plural for "0 items"
+			form = "B";
+		}
+	}
+
+	// Translate that string
+	LLStringUtil::format_map_t args;
+	args["[COUNT]"] = llformat("%d", count);
+
+	// Look up "AgeYearsB" or "AgeWeeksC" including the "form"
+	std::string key = llformat("%s%s", xml_desc.c_str(), form);
+	return getString(key, args);
+}
+
+void LLTrans::setDefaultArg(const std::string& name, const std::string& value)
+{
+	sDefaultArgs[name] = value;
+}
diff --git a/indra/llui/lltrans.h b/indra/llui/lltrans.h
new file mode 100644
index 0000000000..128b51d383
--- /dev/null
+++ b/indra/llui/lltrans.h
@@ -0,0 +1,133 @@
+/**
+ * @file lltrans.h
+ * @brief LLTrans definition
+ *
+ * $LicenseInfo:firstyear=2000&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 LL_TRANS_H
+#define LL_TRANS_H
+
+#include <map>
+
+#include "llpointer.h"
+#include "llstring.h"
+
+class LLXMLNode;
+
+class LLSD;
+
+/**
+ * @brief String template loaded from strings.xml
+ */
+class LLTransTemplate
+{
+public:
+	LLTransTemplate(const std::string& name = LLStringUtil::null, const std::string& text = LLStringUtil::null) : mName(name), mText(text) {}
+
+	std::string mName;
+	std::string mText;
+};
+
+/**
+ * @brief Localized strings class
+ * This class is used to retrieve translations of strings used to build larger ones, as well as
+ * strings with a general usage that don't belong to any specific floater. For example,
+ * "Owner:", "Retrieving..." used in the place of a not yet known name, etc.
+ */
+class LLTrans
+{
+public:
+	LLTrans();
+
+	/**
+	 * @brief Parses the xml root that holds the strings. Used once on startup
+// *FIXME	 * @param xml_filename Filename to parse
+	 * @param default_args Set of strings (expected to be in the file) to use as default replacement args, e.g. "SECOND_LIFE"
+	 * @returns true if the file was parsed successfully, true if something went wrong
+	 */
+	static bool parseStrings(LLPointer<LLXMLNode> & root, const std::set<std::string>& default_args);
+
+	static bool parseLanguageStrings(LLPointer<LLXMLNode> & root);
+
+	/**
+	 * @brief Returns a translated string
+	 * @param xml_desc String's description
+	 * @param args A list of substrings to replace in the string
+	 * @returns Translated string
+	 */
+	static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args);
+	static std::string getString(const std::string &xml_desc, const LLSD& args);
+	static bool findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& args);
+	static bool findString(std::string &result, const std::string &xml_desc, const LLSD& args);
+
+	// Returns translated string with [COUNT] replaced with a number, following
+	// special per-language logic for plural nouns.  For example, some languages
+	// may have different plurals for 0, 1, 2 and > 2.
+	// See "AgeWeeksA", "AgeWeeksB", etc. in strings.xml for examples.
+	static std::string getCountString(const std::string& language, const std::string& xml_desc, S32 count);
+
+	/**
+	 * @brief Returns a translated string
+	 * @param xml_desc String's description
+	 * @returns Translated string
+	 */
+	static std::string getString(const std::string &xml_desc)
+	{
+		LLStringUtil::format_map_t empty;
+		return getString(xml_desc, empty);
+	}
+
+	static bool findString(std::string &result, const std::string &xml_desc)
+	{
+		LLStringUtil::format_map_t empty;
+		return findString(result, xml_desc, empty);
+	}
+
+	static std::string getKeyboardString(const char* keystring)
+	{
+		std::string key_str(keystring);
+		std::string trans_str;
+		return findString(trans_str, key_str) ? trans_str : key_str; 
+	}
+
+	// get the default args
+	static const LLStringUtil::format_map_t& getDefaultArgs()
+	{
+		return sDefaultArgs;
+	}
+
+	static void setDefaultArg(const std::string& name, const std::string& value);
+
+	// insert default args into an arg list
+	static void getArgs(LLStringUtil::format_map_t& args)
+	{
+		args.insert(sDefaultArgs.begin(), sDefaultArgs.end());
+	}
+	
+private:
+	typedef std::map<std::string, LLTransTemplate > template_map_t;
+	static template_map_t sStringTemplates;
+	static LLStringUtil::format_map_t sDefaultArgs;
+};
+
+#endif
diff --git a/indra/llui/lluicolor.cpp b/indra/llui/lluicolor.cpp
new file mode 100644
index 0000000000..f9bb80f8c5
--- /dev/null
+++ b/indra/llui/lluicolor.cpp
@@ -0,0 +1,87 @@
+/** 
+ * @file lluicolor.cpp
+ * @brief brief LLUIColor class implementation file
+ *
+ * $LicenseInfo:firstyear=2009&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 "lluicolor.h"
+
+LLUIColor::LLUIColor()
+	:mColorPtr(NULL)
+{
+}
+
+
+LLUIColor::LLUIColor(const LLColor4& color)
+:	mColor(color), 
+	mColorPtr(NULL)
+{
+}
+
+LLUIColor::LLUIColor(const LLUIColor* color)
+:	mColorPtr(color)
+{
+}
+
+void LLUIColor::set(const LLColor4& color)
+{
+	mColor = color;
+	mColorPtr = NULL;
+}
+
+void LLUIColor::set(const LLUIColor* color)
+{
+	mColorPtr = color;
+}
+
+const LLColor4& LLUIColor::get() const
+{
+	return (mColorPtr == NULL ? mColor : mColorPtr->get());
+}
+
+LLUIColor::operator const LLColor4& () const
+{
+	return get();
+}
+
+const LLColor4& LLUIColor::operator()() const
+{
+	return get();
+}
+
+bool LLUIColor::isReference() const
+{
+	return mColorPtr != NULL;
+}
+
+namespace LLInitParam
+{
+	// used to detect equivalence with default values on export
+	bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
+	{
+		// do not detect value equivalence, treat pointers to colors as distinct from color values
+		return (a.mColorPtr == NULL && b.mColorPtr == NULL ? a.mColor == b.mColor : a.mColorPtr == b.mColorPtr);
+	}
+}
diff --git a/indra/llui/lluicolor.h b/indra/llui/lluicolor.h
new file mode 100644
index 0000000000..97ebea854a
--- /dev/null
+++ b/indra/llui/lluicolor.h
@@ -0,0 +1,71 @@
+/** 
+ * @file lluicolor.h
+ * @brief brief LLUIColor class header file
+ *
+ * $LicenseInfo:firstyear=2009&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 LL_LLUICOLOR_H_
+#define LL_LLUICOLOR_H_
+
+#include "v4color.h"
+
+namespace LLInitParam
+{
+	template<typename T, bool>
+	struct ParamCompare;
+}
+
+class LLUIColor
+{
+public:
+	LLUIColor();
+	LLUIColor(const LLColor4& color);
+	LLUIColor(const LLUIColor* color);
+
+	void set(const LLColor4& color);
+	void set(const LLUIColor* color);
+
+	const LLColor4& get() const;
+
+	operator const LLColor4& () const;
+	const LLColor4& operator()() const;
+
+	bool isReference() const;
+
+private:
+	friend struct LLInitParam::ParamCompare<LLUIColor, false>;
+
+	const LLUIColor* mColorPtr;
+	LLColor4 mColor;
+};
+
+namespace LLInitParam
+{
+	template<>
+	struct ParamCompare<LLUIColor, false>
+	{
+		static bool equals(const LLUIColor& a, const LLUIColor& b);
+	};
+}
+
+#endif
diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp
new file mode 100644
index 0000000000..afc76024d1
--- /dev/null
+++ b/indra/llui/llxuiparser.cpp
@@ -0,0 +1,1756 @@
+/** 
+ * @file llxuiparser.cpp
+ * @brief Utility functions for handling XUI structures in XML
+ *
+ * $LicenseInfo:firstyear=2003&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 "llxuiparser.h"
+
+#include "llxmlnode.h"
+
+#ifdef LL_STANDALONE
+#include <expat.h>
+#else
+#include "expat/expat.h"
+#endif
+
+#include <fstream>
+#include <boost/tokenizer.hpp>
+//#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/classic_core.hpp>
+
+#include "lluicolor.h"
+
+using namespace BOOST_SPIRIT_CLASSIC_NS;
+
+const S32 MAX_STRING_ATTRIBUTE_SIZE = 40;
+
+static 	LLInitParam::Parser::parser_read_func_map_t sXSDReadFuncs;
+static 	LLInitParam::Parser::parser_write_func_map_t sXSDWriteFuncs;
+static 	LLInitParam::Parser::parser_inspect_func_map_t sXSDInspectFuncs;
+
+static 	LLInitParam::Parser::parser_read_func_map_t sSimpleXUIReadFuncs;
+static 	LLInitParam::Parser::parser_write_func_map_t sSimpleXUIWriteFuncs;
+static 	LLInitParam::Parser::parser_inspect_func_map_t sSimpleXUIInspectFuncs;
+
+const char* NO_VALUE_MARKER = "no_value";
+
+const S32 LINE_NUMBER_HERE = 0;
+
+struct MaxOccursValues : public LLInitParam::TypeValuesHelper<U32, MaxOccursValues>
+{
+	static void declareValues()
+	{
+		declare("unbounded", U32_MAX);
+	}
+};
+
+struct Occurs : public LLInitParam::Block<Occurs>
+{
+	Optional<U32>					minOccurs;
+	Optional<U32, MaxOccursValues>	maxOccurs;
+
+	Occurs()
+	:	minOccurs("minOccurs", 0),
+		maxOccurs("maxOccurs", U32_MAX)
+
+	{}
+};
+
+
+typedef enum
+{
+	USE_REQUIRED,
+	USE_OPTIONAL
+} EUse;
+
+namespace LLInitParam
+{
+	template<>
+	struct TypeValues<EUse> : public TypeValuesHelper<EUse>
+	{
+		static void declareValues()
+		{
+			declare("required", USE_REQUIRED);
+			declare("optional", USE_OPTIONAL);
+		}
+	};
+}
+
+struct Element;
+struct Group;
+struct Choice;
+struct Sequence;
+struct Any;
+
+struct Attribute : public LLInitParam::Block<Attribute>
+{
+	Mandatory<std::string>	name;
+	Mandatory<std::string>	type;
+	Mandatory<EUse>			use;
+	
+	Attribute()
+	:	name("name"),
+		type("type"),
+		use("use")
+	{}
+};
+
+struct Any : public LLInitParam::Block<Any, Occurs>
+{
+	Optional<std::string> _namespace;
+
+	Any()
+	:	_namespace("namespace")
+	{}
+};
+
+struct All : public LLInitParam::Block<All, Occurs>
+{
+	Multiple< Lazy<Element> > elements;
+
+	All()
+	:	elements("element")
+	{
+		maxOccurs = 1;
+	}
+};
+
+struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs>
+{
+	Alternative< Lazy<Element> >	element;
+	Alternative< Lazy<Group> >		group;
+	Alternative< Lazy<Choice> >		choice;
+	Alternative< Lazy<Sequence> >	sequence;
+	Alternative< Lazy<Any> >		any;
+
+	Choice()
+	:	element("element"),
+		group("group"),
+		choice("choice"),
+		sequence("sequence"),
+		any("any")
+	{}
+
+};
+
+struct Sequence : public LLInitParam::ChoiceBlock<Sequence, Occurs>
+{
+	Alternative< Lazy<Element> >	element;
+	Alternative< Lazy<Group> >		group;
+	Alternative< Lazy<Choice> >		choice;
+	Alternative< Lazy<Sequence> >	sequence;
+	Alternative< Lazy<Any> >		any;
+};
+
+struct GroupContents : public LLInitParam::ChoiceBlock<GroupContents, Occurs>
+{
+	Alternative<All>		all;
+	Alternative<Choice>		choice;
+	Alternative<Sequence>	sequence;
+
+	GroupContents()
+	:	all("all"),
+		choice("choice"),
+		sequence("sequence")
+	{}
+};
+
+struct Group : public LLInitParam::Block<Group, GroupContents>
+{
+	Optional<std::string>	name,
+							ref;
+
+	Group()
+	:	name("name"),
+		ref("ref")
+	{}
+};
+
+struct Restriction : public LLInitParam::Block<Restriction>
+{
+};
+
+struct Extension : public LLInitParam::Block<Extension>
+{
+};
+
+struct SimpleContent : public LLInitParam::ChoiceBlock<SimpleContent>
+{
+	Alternative<Restriction> restriction;
+	Alternative<Extension> extension;
+
+	SimpleContent()
+	:	restriction("restriction"),
+		extension("extension")
+	{}
+};
+
+struct SimpleType : public LLInitParam::Block<SimpleType>
+{
+	// TODO
+};
+
+struct ComplexContent : public LLInitParam::Block<ComplexContent, SimpleContent>
+{
+	Optional<bool> mixed;
+
+	ComplexContent()
+	:	mixed("mixed", true)
+	{}
+};
+
+struct ComplexTypeContents : public LLInitParam::ChoiceBlock<ComplexTypeContents>
+{
+	Alternative<SimpleContent>	simple_content;
+	Alternative<ComplexContent> complex_content;
+	Alternative<Group>			group;
+	Alternative<All>			all;
+	Alternative<Choice>			choice;
+	Alternative<Sequence>		sequence;
+
+	ComplexTypeContents()
+	:	simple_content("simpleContent"),
+		complex_content("complexContent"),
+		group("group"),
+		all("all"),
+		choice("choice"),
+		sequence("sequence")
+	{}
+};
+
+struct ComplexType : public LLInitParam::Block<ComplexType, ComplexTypeContents>
+{
+	Optional<std::string>			name;
+	Optional<bool>					mixed;
+
+	Multiple<Attribute>				attribute;
+	Multiple< Lazy<Element> >			elements;
+
+	ComplexType()
+	:	name("name"),
+		attribute("xs:attribute"),
+		elements("xs:element"),
+		mixed("mixed")
+	{
+	}
+};
+
+struct ElementContents : public LLInitParam::ChoiceBlock<ElementContents, Occurs>
+{
+	Alternative<SimpleType>		simpleType;
+	Alternative<ComplexType>	complexType;
+
+	ElementContents()
+	:	simpleType("simpleType"),
+		complexType("complexType")
+	{}
+};
+
+struct Element : public LLInitParam::Block<Element, ElementContents>
+{
+	Optional<std::string>	name,
+							ref,
+							type;
+
+	Element()
+	:	name("xs:name"),
+		ref("xs:ref"),
+		type("xs:type")
+	{}
+};
+
+struct Schema : public LLInitParam::Block<Schema>
+{
+private:
+	Mandatory<std::string>	targetNamespace,
+							xmlns,
+							xs;
+
+public:
+	Optional<std::string>	attributeFormDefault,
+							elementFormDefault;
+
+	Mandatory<Element>		root_element;
+	
+	void setNameSpace(const std::string& ns) {targetNamespace = ns; xmlns = ns;}
+
+	Schema(const std::string& ns = LLStringUtil::null)
+	:	attributeFormDefault("attributeFormDefault"),
+		elementFormDefault("elementFormDefault"),
+		xs("xmlns:xs"),
+		targetNamespace("targetNamespace"),
+		xmlns("xmlns"),
+		root_element("xs:element")
+	{
+		attributeFormDefault = "unqualified";
+		elementFormDefault = "qualified";
+		xs = "http://www.w3.org/2001/XMLSchema";
+		if (!ns.empty())
+		{
+			setNameSpace(ns);
+		};
+	}
+
+};
+
+//
+// LLXSDWriter
+//
+LLXSDWriter::LLXSDWriter()
+: Parser(sXSDReadFuncs, sXSDWriteFuncs, sXSDInspectFuncs)
+{
+	registerInspectFunc<bool>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:boolean", _1, _2, _3, _4));
+	registerInspectFunc<std::string>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+	registerInspectFunc<U8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedByte", _1, _2, _3, _4));
+	registerInspectFunc<S8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedByte", _1, _2, _3, _4));
+	registerInspectFunc<U16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedShort", _1, _2, _3, _4));
+	registerInspectFunc<S16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedShort", _1, _2, _3, _4));
+	registerInspectFunc<U32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedInt", _1, _2, _3, _4));
+	registerInspectFunc<S32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:integer", _1, _2, _3, _4));
+	registerInspectFunc<F32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:float", _1, _2, _3, _4));
+	registerInspectFunc<F64>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:double", _1, _2, _3, _4));
+	registerInspectFunc<LLColor4>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+	registerInspectFunc<LLUIColor>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+	registerInspectFunc<LLUUID>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+	registerInspectFunc<LLSD>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+}
+
+void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace)
+{
+	Schema schema(xml_namespace);
+
+	schema.root_element.name = type_name;
+	Choice& choice = schema.root_element.complexType.choice;
+
+	choice.minOccurs = 0;
+	choice.maxOccurs = "unbounded";
+
+	mSchemaNode = node;
+	//node->setName("xs:schema");
+	//node->createChild("attributeFormDefault", true)->setStringValue("unqualified");
+	//node->createChild("elementFormDefault", true)->setStringValue("qualified");
+	//node->createChild("targetNamespace", true)->setStringValue(xml_namespace);
+	//node->createChild("xmlns:xs", true)->setStringValue("http://www.w3.org/2001/XMLSchema");
+	//node->createChild("xmlns", true)->setStringValue(xml_namespace);
+
+	//node = node->createChild("xs:complexType", false);
+	//node->createChild("name", true)->setStringValue(type_name);
+	//node->createChild("mixed", true)->setStringValue("true");
+
+	//mAttributeNode = node;
+	//mElementNode = node->createChild("xs:choice", false);
+	//mElementNode->createChild("minOccurs", true)->setStringValue("0");
+	//mElementNode->createChild("maxOccurs", true)->setStringValue("unbounded");
+	block.inspectBlock(*this);
+
+	// duplicate element choices
+	LLXMLNodeList children;
+	mElementNode->getChildren("xs:element", children, FALSE);
+	for (LLXMLNodeList::iterator child_it = children.begin(); child_it != children.end(); ++child_it)
+	{
+		LLXMLNodePtr child_copy = child_it->second->deepCopy();
+		std::string child_name;
+		child_copy->getAttributeString("name", child_name);
+		child_copy->setAttributeString("name", type_name + "." + child_name);
+		mElementNode->addChild(child_copy);
+	}
+
+	LLXMLNodePtr element_declaration_node = mSchemaNode->createChild("xs:element", false);
+	element_declaration_node->createChild("name", true)->setStringValue(type_name);
+	element_declaration_node->createChild("type", true)->setStringValue(type_name);
+}
+
+void LLXSDWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values)
+{
+	name_stack_t non_empty_names;
+	std::string attribute_name;
+	for (name_stack_t::const_iterator it = stack.begin();
+		it != stack.end();
+		++it)
+	{
+		const std::string& name = it->first;
+		if (!name.empty())
+		{
+			non_empty_names.push_back(*it);
+		}
+	}
+
+	for (name_stack_t::const_iterator it = non_empty_names.begin();
+		it != non_empty_names.end();
+		++it)
+	{
+		if (!attribute_name.empty())
+		{
+			attribute_name += ".";
+		}
+		attribute_name += it->first;
+	}
+
+	// only flag non-nested attributes as mandatory, nested attributes have variant syntax
+	// that can't be properly constrained in XSD
+	// e.g. <foo mandatory.value="bar"/> vs <foo><mandatory value="bar"/></foo>
+	bool attribute_mandatory = min_count == 1 && max_count == 1 && non_empty_names.size() == 1;
+
+	// don't bother supporting "Multiple" params as xml attributes
+	if (max_count <= 1)
+	{
+		// add compound attribute to root node
+		addAttributeToSchema(mAttributeNode, attribute_name, type, attribute_mandatory, possible_values);
+	}
+
+	// now generated nested elements for compound attributes
+	if (non_empty_names.size() > 1 && !attribute_mandatory)
+	{
+		std::string element_name;
+
+		// traverse all but last element, leaving that as an attribute name
+		name_stack_t::const_iterator end_it = non_empty_names.end();
+		end_it--;
+
+		for (name_stack_t::const_iterator it = non_empty_names.begin();
+			it != end_it;
+			++it)
+		{
+			if (it != non_empty_names.begin())
+			{
+				element_name += ".";
+			}
+			element_name += it->first;
+		}
+
+		std::string short_attribute_name = non_empty_names.back().first;
+
+		LLXMLNodePtr complex_type_node;
+
+		// find existing element node here, starting at tail of child list
+		if (mElementNode->mChildren.notNull())
+		{
+			for(LLXMLNodePtr element = mElementNode->mChildren->tail;
+				element.notNull(); 
+				element = element->mPrev)
+			{
+				std::string name;
+				if(element->getAttributeString("name", name) && name == element_name)
+				{
+					complex_type_node = element->mChildren->head;
+					break;
+				}
+			}
+		}
+		//create complex_type node
+		//
+		//<xs:element
+        //    maxOccurs="1"
+        //    minOccurs="0"
+        //    name="name">
+        //       <xs:complexType>
+        //       </xs:complexType>
+        //</xs:element>
+		if(complex_type_node.isNull())
+		{
+			complex_type_node = mElementNode->createChild("xs:element", false);
+
+			complex_type_node->createChild("minOccurs", true)->setIntValue(min_count);
+			complex_type_node->createChild("maxOccurs", true)->setIntValue(max_count);
+			complex_type_node->createChild("name",		true)->setStringValue(element_name);
+			complex_type_node = complex_type_node->createChild("xs:complexType", false);
+		}
+
+		addAttributeToSchema(complex_type_node, short_attribute_name, type, false, possible_values);
+	}
+}
+
+void LLXSDWriter::addAttributeToSchema(LLXMLNodePtr type_declaration_node, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector<std::string>* possible_values)
+{
+	if (!attribute_name.empty())
+	{
+		LLXMLNodePtr new_enum_type_node;
+		if (possible_values != NULL)
+		{
+			// custom attribute type, for example
+			//<xs:simpleType>
+			 // <xs:restriction
+			 //    base="xs:string">
+			 //     <xs:enumeration
+			 //      value="a" />
+			 //     <xs:enumeration
+			 //      value="b" />
+			 //   </xs:restriction>
+			 // </xs:simpleType>
+			new_enum_type_node = new LLXMLNode("xs:simpleType", false);
+
+			LLXMLNodePtr restriction_node = new_enum_type_node->createChild("xs:restriction", false);
+			restriction_node->createChild("base", true)->setStringValue("xs:string");
+
+			for (std::vector<std::string>::const_iterator it = possible_values->begin();
+				it != possible_values->end();
+				++it)
+			{
+				LLXMLNodePtr enum_node = restriction_node->createChild("xs:enumeration", false);
+				enum_node->createChild("value", true)->setStringValue(*it);
+			}
+		}
+
+		string_set_t& attributes_written = mAttributesWritten[type_declaration_node];
+
+		string_set_t::iterator found_it = attributes_written.lower_bound(attribute_name);
+
+		// attribute not yet declared
+		if (found_it == attributes_written.end() || attributes_written.key_comp()(attribute_name, *found_it))
+		{
+			attributes_written.insert(found_it, attribute_name);
+
+			LLXMLNodePtr attribute_node = type_declaration_node->createChild("xs:attribute", false);
+
+			// attribute name
+			attribute_node->createChild("name", true)->setStringValue(attribute_name);
+
+			if (new_enum_type_node.notNull())
+			{
+				attribute_node->addChild(new_enum_type_node);
+			}
+			else
+			{
+				// simple attribute type
+				attribute_node->createChild("type", true)->setStringValue(type);
+			}
+
+			// required or optional
+			attribute_node->createChild("use", true)->setStringValue(mandatory ? "required" : "optional");
+		}
+		 // attribute exists...handle collision of same name attributes with potentially different types
+		else
+		{
+			LLXMLNodePtr attribute_declaration;
+			if (type_declaration_node.notNull())
+			{
+				for(LLXMLNodePtr node = type_declaration_node->mChildren->tail; 
+					node.notNull(); 
+					node = node->mPrev)
+				{
+					std::string name;
+					if (node->getAttributeString("name", name) && name == attribute_name)
+					{
+						attribute_declaration = node;
+						break;
+					}
+				}
+			}
+
+			bool new_type_is_enum = new_enum_type_node.notNull();
+			bool existing_type_is_enum = !attribute_declaration->hasAttribute("type");
+
+			// either type is enum, revert to string in collision
+			// don't bother to check for enum equivalence
+			if (new_type_is_enum || existing_type_is_enum)
+			{
+				if (attribute_declaration->hasAttribute("type"))
+				{
+					attribute_declaration->setAttributeString("type", "xs:string");
+				}
+				else
+				{
+					attribute_declaration->createChild("type", true)->setStringValue("xs:string");
+				}
+				attribute_declaration->deleteChildren("xs:simpleType");
+			}
+			else 
+			{
+				// check for collision of different standard types
+				std::string existing_type;
+				attribute_declaration->getAttributeString("type", existing_type);
+				// if current type is not the same as the new type, revert to strnig
+				if (existing_type != type)
+				{
+					// ...than use most general type, string
+					attribute_declaration->setAttributeString("type", "string");
+				}
+			}
+		}
+	}
+}
+
+//
+// LLXUIXSDWriter
+//
+void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& path, const LLInitParam::BaseBlock& block)
+{
+	std::string file_name(path);
+	file_name += type_name + ".xsd";
+	LLXMLNodePtr root_nodep = new LLXMLNode();
+
+	LLXSDWriter::writeXSD(type_name, root_nodep, block, "http://www.lindenlab.com/xui");
+
+	// add includes for all possible children
+	const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
+	const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);
+
+	// add choices for valid children
+	if (widget_registryp)
+	{
+		// add include declarations for all valid children
+		for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
+		     it != widget_registryp->currentRegistrar().endItems();
+		     ++it)
+		{
+			std::string widget_name = it->first;
+			if (widget_name == type_name)
+			{
+				continue;
+			}
+			LLXMLNodePtr nodep = new LLXMLNode("xs:include", false);
+			nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd");
+			
+			// add to front of schema
+			mSchemaNode->addChild(nodep, mSchemaNode);
+		}
+
+		for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
+			it != widget_registryp->currentRegistrar().endItems();
+			++it)
+		{
+			std::string widget_name = it->first;
+			//<xs:element name="widget_name" type="widget_name">
+			LLXMLNodePtr widget_node = mElementNode->createChild("xs:element", false);
+			widget_node->createChild("name", true)->setStringValue(widget_name);
+			widget_node->createChild("type", true)->setStringValue(widget_name);
+		}
+	}
+
+	LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), "w");
+	LLXMLNode::writeHeaderToFile(xsd_file);
+	root_nodep->writeToFile(xsd_file);
+	fclose(xsd_file);
+}
+
+static 	LLInitParam::Parser::parser_read_func_map_t sXUIReadFuncs;
+static 	LLInitParam::Parser::parser_write_func_map_t sXUIWriteFuncs;
+static 	LLInitParam::Parser::parser_inspect_func_map_t sXUIInspectFuncs;
+
+//
+// LLXUIParser
+//
+LLXUIParser::LLXUIParser()
+:	Parser(sXUIReadFuncs, sXUIWriteFuncs, sXUIInspectFuncs),
+	mCurReadDepth(0)
+{
+	if (sXUIReadFuncs.empty())
+	{
+		registerParserFuncs<LLInitParam::Flag>(readFlag, writeFlag);
+		registerParserFuncs<bool>(readBoolValue, writeBoolValue);
+		registerParserFuncs<std::string>(readStringValue, writeStringValue);
+		registerParserFuncs<U8>(readU8Value, writeU8Value);
+		registerParserFuncs<S8>(readS8Value, writeS8Value);
+		registerParserFuncs<U16>(readU16Value, writeU16Value);
+		registerParserFuncs<S16>(readS16Value, writeS16Value);
+		registerParserFuncs<U32>(readU32Value, writeU32Value);
+		registerParserFuncs<S32>(readS32Value, writeS32Value);
+		registerParserFuncs<F32>(readF32Value, writeF32Value);
+		registerParserFuncs<F64>(readF64Value, writeF64Value);
+		registerParserFuncs<LLColor4>(readColor4Value, writeColor4Value);
+		registerParserFuncs<LLUIColor>(readUIColorValue, writeUIColorValue);
+		registerParserFuncs<LLUUID>(readUUIDValue, writeUUIDValue);
+		registerParserFuncs<LLSD>(readSDValue, writeSDValue);
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing");
+const LLXMLNodePtr DUMMY_NODE = new LLXMLNode();
+
+void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename, bool silent)
+{
+	LLFastTimer timer(FTM_PARSE_XUI);
+	mNameStack.clear();
+	mRootNodeName = node->getName()->mString;
+	mCurFileName = filename;
+	mCurReadDepth = 0;
+	setParseSilently(silent);
+
+	if (node.isNull())
+	{
+		parserWarning("Invalid node");
+	}
+	else
+	{
+		readXUIImpl(node, block);
+	}
+}
+
+bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
+{
+	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+	boost::char_separator<char> sep(".");
+
+	bool values_parsed = false;
+	bool silent = mCurReadDepth > 0;
+
+	if (nodep->getFirstChild().isNull() 
+		&& nodep->mAttributes.empty() 
+		&& nodep->getSanitizedValue().empty())
+	{
+		// empty node, just parse as flag
+		mCurReadNode = DUMMY_NODE;
+		return block.submitValue(mNameStack, *this, silent);
+	}
+
+	// submit attributes for current node
+	values_parsed |= readAttributes(nodep, block);
+
+	// treat text contents of xml node as "value" parameter
+	std::string text_contents = nodep->getSanitizedValue();
+	if (!text_contents.empty())
+	{
+		mCurReadNode = nodep;
+		mNameStack.push_back(std::make_pair(std::string("value"), true));
+		// child nodes are not necessarily valid parameters (could be a child widget)
+		// so don't complain once we've recursed
+		if (!block.submitValue(mNameStack, *this, true))
+		{
+			mNameStack.pop_back();
+			block.submitValue(mNameStack, *this, silent);
+		}
+		else
+		{
+			mNameStack.pop_back();
+		}
+	}
+
+	// then traverse children
+	// child node must start with last name of parent node (our "scope")
+	// for example: "<button><button.param nested_param1="foo"><param.nested_param2 nested_param3="bar"/></button.param></button>"
+	// which equates to the following nesting:
+	// button
+	//     param
+	//         nested_param1
+	//         nested_param2
+	//             nested_param3	
+	mCurReadDepth++;
+	for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();)
+	{
+		std::string child_name(childp->getName()->mString);
+		S32 num_tokens_pushed = 0;
+
+		// for non "dotted" child nodes	check to see if child node maps to another widget type
+		// and if not, treat as a child element of the current node
+		// e.g. <button><rect left="10"/></button> will interpret <rect> as "button.rect"
+		// since there is no widget named "rect"
+		if (child_name.find(".") == std::string::npos) 
+		{
+			mNameStack.push_back(std::make_pair(child_name, true));
+			num_tokens_pushed++;
+		}
+		else
+		{
+			// parse out "dotted" name into individual tokens
+			tokenizer name_tokens(child_name, sep);
+
+			tokenizer::iterator name_token_it = name_tokens.begin();
+			if(name_token_it == name_tokens.end()) 
+			{
+				childp = childp->getNextSibling();
+				continue;
+			}
+
+			// check for proper nesting
+			if (mNameStack.empty())
+			{
+				if (*name_token_it != mRootNodeName)
+				{
+					childp = childp->getNextSibling();
+					continue;
+				}
+			}
+			else if(mNameStack.back().first != *name_token_it)
+			{
+				childp = childp->getNextSibling();
+				continue;
+			}
+
+			// now ignore first token
+			++name_token_it; 
+
+			// copy remaining tokens on to our running token list
+			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
+			{
+				mNameStack.push_back(std::make_pair(*token_to_push, true));
+				num_tokens_pushed++;
+			}
+		}
+
+		// recurse and visit children XML nodes
+		if(readXUIImpl(childp, block))
+		{
+			// child node successfully parsed, remove from DOM
+
+			values_parsed = true;
+			LLXMLNodePtr node_to_remove = childp;
+			childp = childp->getNextSibling();
+
+			nodep->deleteChild(node_to_remove);
+		}
+		else
+		{
+			childp = childp->getNextSibling();
+		}
+
+		while(num_tokens_pushed-- > 0)
+		{
+			mNameStack.pop_back();
+		}
+	}
+	mCurReadDepth--;
+	return values_parsed;
+}
+
+bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
+{
+	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+	boost::char_separator<char> sep(".");
+
+	bool any_parsed = false;
+	bool silent = mCurReadDepth > 0;
+
+	for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin(); 
+		attribute_it != nodep->mAttributes.end(); 
+		++attribute_it)
+	{
+		S32 num_tokens_pushed = 0;
+		std::string attribute_name(attribute_it->first->mString);
+		mCurReadNode = attribute_it->second;
+
+		tokenizer name_tokens(attribute_name, sep);
+		// copy remaining tokens on to our running token list
+		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
+		{
+			mNameStack.push_back(std::make_pair(*token_to_push, true));
+			num_tokens_pushed++;
+		}
+
+		// child nodes are not necessarily valid attributes, so don't complain once we've recursed
+		any_parsed |= block.submitValue(mNameStack, *this, silent);
+		
+		while(num_tokens_pushed-- > 0)
+		{
+			mNameStack.pop_back();
+		}
+	}
+
+	return any_parsed;
+}
+
+void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block)
+{
+	mWriteRootNode = node;
+	name_stack_t name_stack = Parser::name_stack_t();
+	block.serializeBlock(*this, name_stack, diff_block);
+	mOutNodes.clear();
+}
+
+// go from a stack of names to a specific XML node
+LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack)
+{
+	LLXMLNodePtr out_node = mWriteRootNode;
+
+	name_stack_t::iterator next_it = stack.begin();
+	for (name_stack_t::iterator it = stack.begin();
+		it != stack.end();
+		it = next_it)
+	{
+		++next_it;
+		if (it->first.empty())
+		{
+			it->second = false;
+			continue;
+		}
+
+		out_nodes_t::iterator found_it = mOutNodes.find(it->first);
+
+		// node with this name not yet written
+		if (found_it == mOutNodes.end() || it->second)
+		{
+			// make an attribute if we are the last element on the name stack
+			bool is_attribute = next_it == stack.end();
+			LLXMLNodePtr new_node = new LLXMLNode(it->first.c_str(), is_attribute);
+			out_node->addChild(new_node);
+			mOutNodes[it->first] = new_node;
+			out_node = new_node;
+			it->second = false;
+		}
+		else
+		{
+			out_node = found_it->second;
+		}
+	}
+
+	return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node);
+}
+
+bool LLXUIParser::readFlag(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode == DUMMY_NODE;
+}
+
+bool LLXUIParser::writeFlag(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	// just create node
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	return node.notNull();
+}
+
+bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr)
+{
+	S32 value;
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	bool success = self.mCurReadNode->getBoolValue(1, &value);
+	*((bool*)val_ptr) = (value != FALSE);
+	return success;
+}
+
+bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setBoolValue(*((bool*)val_ptr));
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	*((std::string*)val_ptr) = self.mCurReadNode->getSanitizedValue();
+	return true;
+}
+
+bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		const std::string* string_val = reinterpret_cast<const std::string*>(val_ptr);
+		if (string_val->find('\n') != std::string::npos 
+			|| string_val->size() > MAX_STRING_ATTRIBUTE_SIZE)
+		{
+			// don't write strings with newlines into attributes
+			std::string attribute_name = node->getName()->mString;
+			LLXMLNodePtr parent_node = node->mParent;
+			parent_node->deleteChild(node);
+			// write results in text contents of node
+			if (attribute_name == "value")
+			{
+				// "value" is implicit, just write to parent
+				node = parent_node;
+			}
+			else
+			{
+				// create a child that is not an attribute, but with same name
+				node = parent_node->createChild(attribute_name.c_str(), false);
+			}
+		}
+		node->setStringValue(*string_val);
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getByteValue(1, (U8*)val_ptr);
+}
+
+bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setUnsignedValue(*((U8*)val_ptr));
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	S32 value;
+	if(self.mCurReadNode->getIntValue(1, &value))
+	{
+		*((S8*)val_ptr) = value;
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setIntValue(*((S8*)val_ptr));
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	U32 value;
+	if(self.mCurReadNode->getUnsignedValue(1, &value))
+	{
+		*((U16*)val_ptr) = value;
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setUnsignedValue(*((U16*)val_ptr));
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	S32 value;
+	if(self.mCurReadNode->getIntValue(1, &value))
+	{
+		*((S16*)val_ptr) = value;
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setIntValue(*((S16*)val_ptr));
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
+}
+
+bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setUnsignedValue(*((U32*)val_ptr));
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getIntValue(1, (S32*)val_ptr);
+}
+
+bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setIntValue(*((S32*)val_ptr));
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr);
+}
+
+bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setFloatValue(*((F32*)val_ptr));
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
+}
+
+bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setDoubleValue(*((F64*)val_ptr));
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLColor4* colorp = (LLColor4*)val_ptr;
+	if(self.mCurReadNode->getFloatValue(4, colorp->mV) >= 3)
+	{
+		return true;
+	}
+
+	return false;
+}
+
+bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		LLColor4 color = *((LLColor4*)val_ptr);
+		node->setFloatValue(4, color.mV);
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLUIColor* param = (LLUIColor*)val_ptr;
+	LLColor4 color;
+	bool success =  self.mCurReadNode->getFloatValue(4, color.mV) >= 3;
+	if (success)
+	{
+		param->set(color);
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		LLUIColor color = *((LLUIColor*)val_ptr);
+		//RN: don't write out the color that is represented by a function
+		// rely on param block exporting to get the reference to the color settings
+		if (color.isReference()) return false;
+		node->setFloatValue(4, color.get().mV);
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLUUID temp_id;
+	// LLUUID::set is destructive, so use temporary value
+	if (temp_id.set(self.mCurReadNode->getSanitizedValue()))
+	{
+		*(LLUUID*)(val_ptr) = temp_id;
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		node->setStringValue(((LLUUID*)val_ptr)->asString());
+		return true;
+	}
+	return false;
+}
+
+bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	*((LLSD*)val_ptr) = LLSD(self.mCurReadNode->getSanitizedValue());
+	return true;
+}
+
+bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
+{
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+
+	LLXMLNodePtr node = self.getNode(stack);
+	if (node.notNull())
+	{
+		std::string string_val = ((LLSD*)val_ptr)->asString();
+		if (string_val.find('\n') != std::string::npos || string_val.size() > MAX_STRING_ATTRIBUTE_SIZE)
+		{
+			// don't write strings with newlines into attributes
+			std::string attribute_name = node->getName()->mString;
+			LLXMLNodePtr parent_node = node->mParent;
+			parent_node->deleteChild(node);
+			// write results in text contents of node
+			if (attribute_name == "value")
+			{
+				// "value" is implicit, just write to parent
+				node = parent_node;
+			}
+			else
+			{
+				node = parent_node->createChild(attribute_name.c_str(), false);
+			}
+		}
+
+		node->setStringValue(string_val);
+		return true;
+	}
+	return false;
+}
+
+/*virtual*/ std::string LLXUIParser::getCurrentElementName()
+{
+	std::string full_name;
+	for (name_stack_t::iterator it = mNameStack.begin();	
+		it != mNameStack.end();
+		++it)
+	{
+		full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
+	}
+
+	return full_name;
+}
+
+void LLXUIParser::parserWarning(const std::string& message)
+{
+#ifdef LL_WINDOWS
+	// use Visual Studo friendly formatting of output message for easy access to originating xml
+	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
+	utf16str += '\n';
+	OutputDebugString(utf16str.c_str());
+#else
+	Parser::parserWarning(message);
+#endif
+}
+
+void LLXUIParser::parserError(const std::string& message)
+{
+#ifdef LL_WINDOWS
+	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
+	utf16str += '\n';
+	OutputDebugString(utf16str.c_str());
+#else
+	Parser::parserError(message);
+#endif
+}
+
+
+//
+// LLSimpleXUIParser
+//
+
+struct ScopedFile
+{
+	ScopedFile( const std::string& filename, const char* accessmode )
+	{
+		mFile = LLFile::fopen(filename, accessmode);
+	}
+
+	~ScopedFile()
+	{
+		fclose(mFile);
+		mFile = NULL;
+	}
+
+	S32 getRemainingBytes()
+	{
+		if (!isOpen()) return 0;
+
+		S32 cur_pos = ftell(mFile);
+		fseek(mFile, 0L, SEEK_END);
+		S32 file_size = ftell(mFile);
+		fseek(mFile, cur_pos, SEEK_SET);
+		return file_size - cur_pos;
+	}
+
+	bool isOpen() { return mFile != NULL; }
+
+	LLFILE* mFile;
+};
+LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb)
+:	Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs),
+	mCurReadDepth(0),
+	mElementCB(element_cb)
+{
+	if (sSimpleXUIReadFuncs.empty())
+	{
+		registerParserFuncs<LLInitParam::Flag>(readFlag);
+		registerParserFuncs<bool>(readBoolValue);
+		registerParserFuncs<std::string>(readStringValue);
+		registerParserFuncs<U8>(readU8Value);
+		registerParserFuncs<S8>(readS8Value);
+		registerParserFuncs<U16>(readU16Value);
+		registerParserFuncs<S16>(readS16Value);
+		registerParserFuncs<U32>(readU32Value);
+		registerParserFuncs<S32>(readS32Value);
+		registerParserFuncs<F32>(readF32Value);
+		registerParserFuncs<F64>(readF64Value);
+		registerParserFuncs<LLColor4>(readColor4Value);
+		registerParserFuncs<LLUIColor>(readUIColorValue);
+		registerParserFuncs<LLUUID>(readUUIDValue);
+		registerParserFuncs<LLSD>(readSDValue);
+	}
+}
+
+LLSimpleXUIParser::~LLSimpleXUIParser()
+{
+}
+
+
+bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent)
+{
+	LLFastTimer timer(FTM_PARSE_XUI);
+
+	mParser = XML_ParserCreate(NULL);
+	XML_SetUserData(mParser, this);
+	XML_SetElementHandler(			mParser,	startElementHandler, endElementHandler);
+	XML_SetCharacterDataHandler(	mParser,	characterDataHandler);
+
+	mOutputStack.push_back(std::make_pair(&block, 0));
+	mNameStack.clear();
+	mCurFileName = filename;
+	mCurReadDepth = 0;
+	setParseSilently(silent);
+
+	ScopedFile file(filename, "rb");
+	if( !file.isOpen() )
+	{
+		LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL;
+		XML_ParserFree( mParser );
+		return false;
+	}
+
+	S32 bytes_read = 0;
+	
+	S32 buffer_size = file.getRemainingBytes();
+	void* buffer = XML_GetBuffer(mParser, buffer_size);
+	if( !buffer ) 
+	{
+		LL_WARNS("ReadXUI") << "Unable to allocate XML buffer while reading file " << filename << LL_ENDL;
+		XML_ParserFree( mParser );
+		return false;
+	}
+
+	bytes_read = (S32)fread(buffer, 1, buffer_size, file.mFile);
+	if( bytes_read <= 0 )
+	{
+		LL_WARNS("ReadXUI") << "Error while reading file  " << filename << LL_ENDL;
+		XML_ParserFree( mParser );
+		return false;
+	}
+	
+	mEmptyLeafNode.push_back(false);
+
+	if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) )
+	{
+		LL_WARNS("ReadXUI") << "Error while parsing file  " << filename << LL_ENDL;
+		XML_ParserFree( mParser );
+		return false;
+	}
+
+	mEmptyLeafNode.pop_back();
+
+	XML_ParserFree( mParser );
+	return true;
+}
+
+void LLSimpleXUIParser::startElementHandler(void *userData, const char *name, const char **atts)
+{
+	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
+	self->startElement(name, atts);
+}
+
+void LLSimpleXUIParser::endElementHandler(void *userData, const char *name)
+{
+	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
+	self->endElement(name);
+}
+
+void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int len)
+{
+	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
+	self->characterData(s, len);
+}
+
+void LLSimpleXUIParser::characterData(const char *s, int len)
+{
+	mTextContents += std::string(s, len);
+}
+
+void LLSimpleXUIParser::startElement(const char *name, const char **atts)
+{
+	processText();
+
+	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+	boost::char_separator<char> sep(".");
+
+	if (mElementCB) 
+	{
+		LLInitParam::BaseBlock* blockp = mElementCB(*this, name);
+		if (blockp)
+		{
+			mOutputStack.push_back(std::make_pair(blockp, 0));
+		}
+	}
+
+	mOutputStack.back().second++;
+	S32 num_tokens_pushed = 0;
+	std::string child_name(name);
+
+	if (mOutputStack.back().second == 1)
+	{	// root node for this block
+		mScope.push_back(child_name);
+	}
+	else
+	{	// compound attribute
+		if (child_name.find(".") == std::string::npos) 
+		{
+			mNameStack.push_back(std::make_pair(child_name, true));
+			num_tokens_pushed++;
+			mScope.push_back(child_name);
+		}
+		else
+		{
+			// parse out "dotted" name into individual tokens
+			tokenizer name_tokens(child_name, sep);
+
+			tokenizer::iterator name_token_it = name_tokens.begin();
+			if(name_token_it == name_tokens.end()) 
+			{
+				return;
+			}
+
+			// check for proper nesting
+			if(!mScope.empty() && *name_token_it != mScope.back())
+			{
+				return;
+			}
+
+			// now ignore first token
+			++name_token_it; 
+
+			// copy remaining tokens on to our running token list
+			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
+			{
+				mNameStack.push_back(std::make_pair(*token_to_push, true));
+				num_tokens_pushed++;
+			}
+			mScope.push_back(mNameStack.back().first);
+		}
+	}
+
+	// parent node is not empty
+	mEmptyLeafNode.back() = false;
+	// we are empty if we have no attributes
+	mEmptyLeafNode.push_back(atts[0] == NULL);
+
+	mTokenSizeStack.push_back(num_tokens_pushed);
+	readAttributes(atts);
+
+}
+
+void LLSimpleXUIParser::endElement(const char *name)
+{
+	bool has_text = processText();
+
+	// no text, attributes, or children
+	if (!has_text && mEmptyLeafNode.back())
+	{
+		// submit this as a valueless name (even though there might be text contents we haven't seen yet)
+		mCurAttributeValueBegin = NO_VALUE_MARKER;
+		mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
+	}
+
+	if (--mOutputStack.back().second == 0)
+	{
+		if (mOutputStack.empty())
+		{
+			LL_ERRS("ReadXUI") << "Parameter block output stack popped while empty." << LL_ENDL;
+		}
+		mOutputStack.pop_back();
+	}
+
+	S32 num_tokens_to_pop = mTokenSizeStack.back();
+	mTokenSizeStack.pop_back();
+	while(num_tokens_to_pop-- > 0)
+	{
+		mNameStack.pop_back();
+	}
+	mScope.pop_back();
+	mEmptyLeafNode.pop_back();
+}
+
+bool LLSimpleXUIParser::readAttributes(const char **atts)
+{
+	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+	boost::char_separator<char> sep(".");
+
+	bool any_parsed = false;
+	for(S32 i = 0; atts[i] && atts[i+1]; i += 2 )
+	{
+		std::string attribute_name(atts[i]);
+		mCurAttributeValueBegin = atts[i+1];
+		
+		S32 num_tokens_pushed = 0;
+		tokenizer name_tokens(attribute_name, sep);
+		// copy remaining tokens on to our running token list
+		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
+		{
+			mNameStack.push_back(std::make_pair(*token_to_push, true));
+			num_tokens_pushed++;
+		}
+
+		// child nodes are not necessarily valid attributes, so don't complain once we've recursed
+		any_parsed |= mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
+		
+		while(num_tokens_pushed-- > 0)
+		{
+			mNameStack.pop_back();
+		}
+	}
+	return any_parsed;
+}
+
+bool LLSimpleXUIParser::processText()
+{
+	if (!mTextContents.empty())
+	{
+		LLStringUtil::trim(mTextContents);
+		if (!mTextContents.empty())
+		{
+			mNameStack.push_back(std::make_pair(std::string("value"), true));
+			mCurAttributeValueBegin = mTextContents.c_str();
+			mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
+			mNameStack.pop_back();
+		}
+		mTextContents.clear();
+		return true;
+	}
+	return false;
+}
+
+/*virtual*/ std::string LLSimpleXUIParser::getCurrentElementName()
+{
+	std::string full_name;
+	for (name_stack_t::iterator it = mNameStack.begin();	
+		it != mNameStack.end();
+		++it)
+	{
+		full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
+	}
+
+	return full_name;
+}
+
+void LLSimpleXUIParser::parserWarning(const std::string& message)
+{
+#ifdef LL_WINDOWS
+	// use Visual Studo friendly formatting of output message for easy access to originating xml
+	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str());
+	utf16str += '\n';
+	OutputDebugString(utf16str.c_str());
+#else
+	Parser::parserWarning(message);
+#endif
+}
+
+void LLSimpleXUIParser::parserError(const std::string& message)
+{
+#ifdef LL_WINDOWS
+	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str());
+	utf16str += '\n';
+	OutputDebugString(utf16str.c_str());
+#else
+	Parser::parserError(message);
+#endif
+}
+
+bool LLSimpleXUIParser::readFlag(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return self.mCurAttributeValueBegin == NO_VALUE_MARKER;
+}
+
+bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	if (!strcmp(self.mCurAttributeValueBegin, "true")) 
+	{
+		*((bool*)val_ptr) = true;
+		return true;
+	}
+	else if (!strcmp(self.mCurAttributeValueBegin, "false"))
+	{
+		*((bool*)val_ptr) = false;
+		return true;
+	}
+
+	return false;
+}
+
+bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	*((std::string*)val_ptr) = self.mCurAttributeValueBegin;
+	return true;
+}
+
+bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full;
+}
+	
+bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	LLColor4 value;
+
+	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
+	{
+		*(LLColor4*)(val_ptr) = value;
+		return true;
+	}
+	return false;
+}
+
+bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	LLColor4 value;
+	LLUIColor* colorp = (LLUIColor*)val_ptr;
+
+	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
+	{
+		colorp->set(value);
+		return true;
+	}
+	return false;
+}
+
+bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	LLUUID temp_id;
+	// LLUUID::set is destructive, so use temporary value
+	if (temp_id.set(std::string(self.mCurAttributeValueBegin)))
+	{
+		*(LLUUID*)(val_ptr) = temp_id;
+		return true;
+	}
+	return false;
+}
+
+bool LLSimpleXUIParser::readSDValue(Parser& parser, void* val_ptr)
+{
+	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+	*((LLSD*)val_ptr) = LLSD(self.mCurAttributeValueBegin);
+	return true;
+}
diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h
new file mode 100644
index 0000000000..d7cd256967
--- /dev/null
+++ b/indra/llui/llxuiparser.h
@@ -0,0 +1,242 @@
+/** 
+ * @file llxuiparser.h
+ * @brief Utility functions for handling XUI structures in XML
+ *
+ * $LicenseInfo:firstyear=2003&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 LLXUIPARSER_H
+#define LLXUIPARSER_H
+
+#include "llinitparam.h"
+#include "llregistry.h"
+#include "llpointer.h"
+
+#include <boost/function.hpp>
+#include <iosfwd>
+#include <stack>
+#include <set>
+
+
+
+class LLView;
+
+
+typedef LLPointer<class LLXMLNode> LLXMLNodePtr;
+
+
+// lookup widget type by name
+class LLWidgetTypeRegistry
+:	public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry>
+{};
+
+
+// global static instance for registering all widget types
+typedef boost::function<LLView* (LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)> LLWidgetCreatorFunc;
+
+typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t;
+
+class LLChildRegistryRegistry
+: public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry>
+{};
+
+
+
+class LLXSDWriter : public LLInitParam::Parser
+{
+	LOG_CLASS(LLXSDWriter);
+public:
+	void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace);
+
+	/*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; }
+
+	LLXSDWriter();
+
+protected:
+	void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values);
+	void addAttributeToSchema(LLXMLNodePtr nodep, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector<std::string>* possible_values);
+	LLXMLNodePtr mAttributeNode;
+	LLXMLNodePtr mElementNode;
+	LLXMLNodePtr mSchemaNode;
+
+	typedef std::set<std::string> string_set_t;
+	typedef std::map<LLXMLNodePtr, string_set_t> attributes_map_t;
+	attributes_map_t	mAttributesWritten;
+};
+
+
+
+// NOTE: DOES NOT WORK YET
+// should support child widgets for XUI
+class LLXUIXSDWriter : public LLXSDWriter
+{
+public:
+	void writeXSD(const std::string& name, const std::string& path, const LLInitParam::BaseBlock& block);
+};
+
+
+class LLXUIParserImpl;
+
+class LLXUIParser : public LLInitParam::Parser
+{
+LOG_CLASS(LLXUIParser);
+
+public:
+	LLXUIParser();
+	typedef LLInitParam::Parser::name_stack_t name_stack_t;
+
+	/*virtual*/ std::string getCurrentElementName();
+	/*virtual*/ void parserWarning(const std::string& message);
+	/*virtual*/ void parserError(const std::string& message);
+
+	void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false);
+	void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL);
+
+private:
+	bool readXUIImpl(LLXMLNodePtr node, LLInitParam::BaseBlock& block);
+	bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block);
+
+	//reader helper functions
+	static bool readFlag(Parser& parser, void* val_ptr);
+	static bool readBoolValue(Parser& parser, void* val_ptr);
+	static bool readStringValue(Parser& parser, void* val_ptr);
+	static bool readU8Value(Parser& parser, void* val_ptr);
+	static bool readS8Value(Parser& parser, void* val_ptr);
+	static bool readU16Value(Parser& parser, void* val_ptr);
+	static bool readS16Value(Parser& parser, void* val_ptr);
+	static bool readU32Value(Parser& parser, void* val_ptr);
+	static bool readS32Value(Parser& parser, void* val_ptr);
+	static bool readF32Value(Parser& parser, void* val_ptr);
+	static bool readF64Value(Parser& parser, void* val_ptr);
+	static bool readColor4Value(Parser& parser, void* val_ptr);
+	static bool readUIColorValue(Parser& parser, void* val_ptr);
+	static bool readUUIDValue(Parser& parser, void* val_ptr);
+	static bool readSDValue(Parser& parser, void* val_ptr);
+
+	//writer helper functions
+	static bool writeFlag(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeStringValue(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeU8Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeS8Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeU16Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeS16Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeU32Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeSDValue(Parser& parser, const void* val_ptr, name_stack_t&);
+
+	LLXMLNodePtr getNode(name_stack_t& stack);
+
+private:
+	Parser::name_stack_t			mNameStack;
+	LLXMLNodePtr					mCurReadNode;
+	// Root of the widget XML sub-tree, for example, "line_editor"
+	LLXMLNodePtr					mWriteRootNode;
+	
+	typedef std::map<std::string, LLXMLNodePtr>	out_nodes_t;
+	out_nodes_t						mOutNodes;
+	LLXMLNodePtr					mLastWrittenChild;
+	S32								mCurReadDepth;
+	std::string						mCurFileName;
+	std::string						mRootNodeName;
+};
+
+// LLSimpleXUIParser is a streamlined SAX-based XUI parser that does not support localization 
+// or parsing of a tree of independent param blocks, such as child widgets.
+// Use this for reading non-localized files that only need a single param block as a result.
+//
+// NOTE: In order to support nested block parsing, we need callbacks for start element that
+// push new blocks contexts on the mScope stack.
+// NOTE: To support localization without building a DOM, we need to enforce consistent 
+// ordering of child elements from base file to localized diff file.  Then we can use a pair
+// of coroutines to perform matching of xml nodes during parsing.  Not sure if the overhead
+// of coroutines would offset the gain from SAX parsing
+class LLSimpleXUIParserImpl;
+
+class LLSimpleXUIParser : public LLInitParam::Parser
+{
+LOG_CLASS(LLSimpleXUIParser);
+public:
+	typedef LLInitParam::Parser::name_stack_t name_stack_t;
+	typedef LLInitParam::BaseBlock* (*element_start_callback_t)(LLSimpleXUIParser&, const char* block_name);
+
+	LLSimpleXUIParser(element_start_callback_t element_cb = NULL);
+	virtual ~LLSimpleXUIParser();
+
+	/*virtual*/ std::string getCurrentElementName();
+	/*virtual*/ void parserWarning(const std::string& message);
+	/*virtual*/ void parserError(const std::string& message);
+
+	bool readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent=false);
+
+
+private:
+	//reader helper functions
+	static bool readFlag(Parser&, void* val_ptr);
+	static bool readBoolValue(Parser&, void* val_ptr);
+	static bool readStringValue(Parser&, void* val_ptr);
+	static bool readU8Value(Parser&, void* val_ptr);
+	static bool readS8Value(Parser&, void* val_ptr);
+	static bool readU16Value(Parser&, void* val_ptr);
+	static bool readS16Value(Parser&, void* val_ptr);
+	static bool readU32Value(Parser&, void* val_ptr);
+	static bool readS32Value(Parser&, void* val_ptr);
+	static bool readF32Value(Parser&, void* val_ptr);
+	static bool readF64Value(Parser&, void* val_ptr);
+	static bool readColor4Value(Parser&, void* val_ptr);
+	static bool readUIColorValue(Parser&, void* val_ptr);
+	static bool readUUIDValue(Parser&, void* val_ptr);
+	static bool readSDValue(Parser&, void* val_ptr);
+
+private:
+	static void startElementHandler(void *userData, const char *name, const char **atts);
+	static void endElementHandler(void *userData, const char *name);
+	static void characterDataHandler(void *userData, const char *s, int len);
+
+	void startElement(const char *name, const char **atts);
+	void endElement(const char *name);
+	void characterData(const char *s, int len);
+	bool readAttributes(const char **atts);
+	bool processText();
+
+	Parser::name_stack_t			mNameStack;
+	struct XML_ParserStruct*		mParser;
+	LLXMLNodePtr					mLastWrittenChild;
+	S32								mCurReadDepth;
+	std::string						mCurFileName;
+	std::string						mTextContents;
+	const char*						mCurAttributeValueBegin;
+	std::vector<S32>				mTokenSizeStack;
+	std::vector<std::string>		mScope;
+	std::vector<bool>				mEmptyLeafNode;
+	element_start_callback_t		mElementCB;
+
+	std::vector<std::pair<LLInitParam::BaseBlock*, S32> > mOutputStack;
+};
+
+
+#endif //LLXUIPARSER_H
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index c75df86891..cb3b7abb14 100644
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -105,28 +105,6 @@ LLStyle::Params::Params()
 
 namespace LLInitParam
 {
-	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::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){}
-	void BaseBlock::addSynonym(Param& param, const std::string& synonym) {}
-	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
-	
-	void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
-	{
-		descriptor.mCurrentBlockPtr = this;
-	}
-	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; }
-	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const {}
-	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_value, S32 max_value) const { return true; }
-	bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
-	bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
-
 	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color)
 	:	super_t(color)
 	{}
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index c1fb050206..8f0a48018f 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -70,21 +70,6 @@ S32 LLUIImage::getHeight() const
 	return 0;
 }
 
-namespace LLInitParam
-{
-	BlockDescriptor::BlockDescriptor() {}
-	ParamDescriptor::ParamDescriptor(param_handle_t p, 
-						merge_func_t merge_func, 
-						deserialize_func_t deserialize_func, 
-						serialize_func_t serialize_func,
-						validation_func_t validation_func,
-						inspect_func_t inspect_func,
-						S32 min_count,
-						S32 max_count){}
-	ParamDescriptor::~ParamDescriptor() {}
-
-}
-
 namespace tut
 {
 	struct LLUrlEntryData
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index 7183413463..963473c92a 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -63,40 +63,6 @@ S32 LLUIImage::getHeight() const
 
 namespace LLInitParam
 {
-	BlockDescriptor::BlockDescriptor() {}
-	ParamDescriptor::ParamDescriptor(param_handle_t p, 
-						merge_func_t merge_func, 
-						deserialize_func_t deserialize_func, 
-						serialize_func_t serialize_func,
-						validation_func_t validation_func,
-						inspect_func_t inspect_func,
-						S32 min_count,
-						S32 max_count){}
-	ParamDescriptor::~ParamDescriptor() {}
-
-	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){}
-	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
-	void BaseBlock::addSynonym(Param& param, const std::string& synonym) {}
-
-	void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
-	{
-		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 = 0x7FFFffff & ((U32)(my_addr - block_addr));
-	}
-
-	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; }
-	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const {}
-	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const { return true; }
-	bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
-	bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
-
 	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color)
 	:	super_t(color)
 	{}
diff --git a/indra/llxuixml/CMakeLists.txt b/indra/llxuixml/CMakeLists.txt
deleted file mode 100644
index daed4de6ce..0000000000
--- a/indra/llxuixml/CMakeLists.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- cmake -*-
-
-project(llxuixml)
-
-include(00-Common)
-include(LLCommon)
-include(LLMath)
-include(LLXML)
-
-include_directories(
-    ${LLCOMMON_INCLUDE_DIRS}
-    ${LLMATH_INCLUDE_DIRS}
-    ${LLXML_INCLUDE_DIRS}
-    )
-
-set(llxuixml_SOURCE_FILES
-    llinitparam.cpp
-    lltrans.cpp
-    lluicolor.cpp
-    llxuiparser.cpp
-    )
-    
-set(llxuixml_HEADER_FILES
-    CMakeLists.txt
-
-    llinitparam.h
-    lltrans.h
-    llregistry.h
-    lluicolor.h
-    llxuiparser.h
-    )
-
-set_source_files_properties(${llxuixml_HEADER_FILES}
-                            PROPERTIES HEADER_FILE_ONLY TRUE)
-
-list(APPEND llxuixml_SOURCE_FILES ${llxuixml_HEADER_FILES})
-
-add_library (llxuixml ${llxuixml_SOURCE_FILES})
-# Libraries on which this library depends, needed for Linux builds
-# Sort by high-level to low-level
-target_link_libraries(llxuixml
-    llxml
-    llcommon
-    llmath
-    )
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
deleted file mode 100644
index db72aa19b9..0000000000
--- a/indra/llxuixml/llinitparam.cpp
+++ /dev/null
@@ -1,469 +0,0 @@
-/** 
- * @file llinitparam.cpp
- * @brief parameter block abstraction for creating complex objects and 
- * parsing construction parameters from xml and LLSD
- *
- * $LicenseInfo:firstyear=2008&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 "llinitparam.h"
-
-
-namespace LLInitParam
-{
-	//
-	// Param
-	//
-	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 = 0x7FFFffff & (U32)(my_addr - block_addr);
-	}
-
-	//
-	// ParamDescriptor
-	//
-	ParamDescriptor::ParamDescriptor(param_handle_t p, 
-									merge_func_t merge_func, 
-									deserialize_func_t deserialize_func, 
-									serialize_func_t serialize_func,
-									validation_func_t validation_func,
-									inspect_func_t inspect_func,
-									S32 min_count,
-									S32 max_count)
-	:	mParamHandle(p),
-		mMergeFunc(merge_func),
-		mDeserializeFunc(deserialize_func),
-		mSerializeFunc(serialize_func),
-		mValidationFunc(validation_func),
-		mInspectFunc(inspect_func),
-		mMinCount(min_count),
-		mMaxCount(max_count),
-		mUserData(NULL)
-	{}
-
-	ParamDescriptor::ParamDescriptor()
-	:	mParamHandle(0),
-		mMergeFunc(NULL),
-		mDeserializeFunc(NULL),
-		mSerializeFunc(NULL),
-		mValidationFunc(NULL),
-		mInspectFunc(NULL),
-		mMinCount(0),
-		mMaxCount(0),
-		mUserData(NULL)
-	{}
-
-	ParamDescriptor::~ParamDescriptor()
-	{
-		delete mUserData;
-	}
-
-	//
-	// Parser
-	//
-	Parser::~Parser()
-	{}
-
-	void Parser::parserWarning(const std::string& message)
-	{
-		if (mParseSilently) return;
-		llwarns << message << llendl;
-	}
-	
-	void Parser::parserError(const std::string& message)
-	{
-		if (mParseSilently) return;
-		llerrs << message << llendl;
-	}
-
-
-	//
-	// BlockDescriptor
-	//
-	void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data) 
-	{
-		mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end());
-		std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams));
-		std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList));
-		std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
-	}
-
-	BlockDescriptor::BlockDescriptor()
-	:	mMaxParamOffset(0),
-		mInitializationState(UNINITIALIZED),
-		mCurrentBlockPtr(NULL)
-	{}
-
-	// called by each derived class in least to most derived order
-	void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
-	{
-		descriptor.mCurrentBlockPtr = this;
-		descriptor.mMaxParamOffset = block_size;
-
-		switch(descriptor.mInitializationState)
-		{
-		case BlockDescriptor::UNINITIALIZED:
-			// copy params from base class here
-			descriptor.aggregateBlockData(base_descriptor);
-
-			descriptor.mInitializationState = BlockDescriptor::INITIALIZING;
-			break;
-		case BlockDescriptor::INITIALIZING:
-			descriptor.mInitializationState = BlockDescriptor::INITIALIZED;
-			break;
-		case BlockDescriptor::INITIALIZED:
-			// nothing to do
-			break;
-		}
-	}
-
-	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const
-	{
-		const U8* param_address = reinterpret_cast<const U8*>(param);
-		const U8* baseblock_address = reinterpret_cast<const U8*>(this);
-		return (param_address - baseblock_address);
-	}
-
-	bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)
-	{
-		if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true))
-		{
-			if (!silent)
-			{
-				p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str()));
-			}
-			return false;
-		}
-		return true;
-	}
-
-
-	bool BaseBlock::validateBlock(bool emit_errors) const
-	{
-		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
-		for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
-		{
-			const Param* param = getParamFromHandle(it->first);
-			if (!it->second(param))
-			{
-				if (emit_errors)
-				{
-					llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
-				}
-				return false;
-			}
-		}
-		return true;
-	}
-
-	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const
-	{
-		// named param is one like LLView::Params::follows
-		// unnamed param is like LLView::Params::rect - implicit
-		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
-
-		for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); 
-			it != block_data.mUnnamedParams.end(); 
-			++it)
-		{
-			param_handle_t param_handle = (*it)->mParamHandle;
-			const Param* param = getParamFromHandle(param_handle);
-			ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc;
-			if (serialize_func)
-			{
-				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
-				// each param descriptor remembers its serial number
-				// so we can inspect the same param under different names
-				// and see that it has the same number
-				name_stack.push_back(std::make_pair("", true));
-				serialize_func(*param, parser, name_stack, diff_param);
-				name_stack.pop_back();
-			}
-		}
-
-		for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
-			it != block_data.mNamedParams.end();
-			++it)
-		{
-			param_handle_t param_handle = it->second->mParamHandle;
-			const Param* param = getParamFromHandle(param_handle);
-			ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc;
-			if (serialize_func && param->anyProvided())
-			{
-				// Ensure this param has not already been serialized
-				// Prevents <rect> from being serialized as its own tag.
-				bool duplicate = false;
-				for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); 
-					it2 != block_data.mUnnamedParams.end(); 
-					++it2)
-				{
-					if (param_handle == (*it2)->mParamHandle)
-					{
-						duplicate = true;
-						break;
-					}
-				}
-
-				//FIXME: for now, don't attempt to serialize values under synonyms, as current parsers
-				// don't know how to detect them
-				if (duplicate) 
-				{
-					continue;
-				}
-
-				name_stack.push_back(std::make_pair(it->first, !duplicate));
-				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
-				serialize_func(*param, parser, name_stack, diff_param);
-				name_stack.pop_back();
-			}
-		}
-	}
-
-	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const
-	{
-		// named param is one like LLView::Params::follows
-		// unnamed param is like LLView::Params::rect - implicit
-		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
-
-		for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); 
-			it != block_data.mUnnamedParams.end(); 
-			++it)
-		{
-			param_handle_t param_handle = (*it)->mParamHandle;
-			const Param* param = getParamFromHandle(param_handle);
-			ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc;
-			if (inspect_func)
-			{
-				name_stack.push_back(std::make_pair("", true));
-				inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount);
-				name_stack.pop_back();
-			}
-		}
-
-		for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
-			it != block_data.mNamedParams.end();
-			++it)
-		{
-			param_handle_t param_handle = it->second->mParamHandle;
-			const Param* param = getParamFromHandle(param_handle);
-			ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc;
-			if (inspect_func)
-			{
-				// Ensure this param has not already been inspected
-				bool duplicate = false;
-				for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); 
-					it2 != block_data.mUnnamedParams.end(); 
-					++it2)
-				{
-					if (param_handle == (*it2)->mParamHandle)
-					{
-						duplicate = true;
-						break;
-					}
-				}
-
-				name_stack.push_back(std::make_pair(it->first, !duplicate));
-				inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
-				name_stack.pop_back();
-			}
-		}
-
-		return true;
-	}
-
-	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored)
-	{
-		BlockDescriptor& block_data = mostDerivedBlockDescriptor();
-		bool names_left = name_stack_range.first != name_stack_range.second;
-
-		bool new_name = names_left
-						? name_stack_range.first->second
-						: true;
-
-		if (names_left)
-		{
-			const std::string& top_name = name_stack_range.first->first;
-
-			ParamDescriptor::deserialize_func_t deserialize_func = NULL;
-			Param* paramp = NULL;
-
-			BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);
-			if (found_it != block_data.mNamedParams.end())
-			{
-				// find pointer to member parameter from offset table
-				paramp = getParamFromHandle(found_it->second->mParamHandle);
-				deserialize_func = found_it->second->mDeserializeFunc;
-					
-				Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);
-				++new_name_stack.first;
-				if (deserialize_func(*paramp, p, new_name_stack, new_name))
-				{
-					// value is no longer new, we know about it now
-					name_stack_range.first->second = false;
-					return true;
-				}
-				else
-				{
-					return false;
-				}
-			}
-		}
-
-		// try to parse unnamed parameters, in declaration order
-		for ( BlockDescriptor::param_list_t::iterator it = block_data.mUnnamedParams.begin(); 
-			it != block_data.mUnnamedParams.end(); 
-			++it)
-		{
-			Param* paramp = getParamFromHandle((*it)->mParamHandle);
-			ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc;
-
-			if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name))
-			{
-				return true;
-			}
-		}
-
-		// if no match, and no names left on stack, this is just an existence assertion of this block
-		// verify by calling readValue with NoParamValue type, an inherently unparseable type
-		if (!names_left)
-		{
-			Flag no_value;
-			return p.readValue(no_value);
-		}
-
-		return false;
-	}
-
-	//static 
-	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name)
-	{
-		// create a copy of the param descriptor in mAllParams
-		// so other data structures can store a pointer to it
-		block_data.mAllParams.push_back(in_param);
-		ParamDescriptorPtr param(block_data.mAllParams.back());
-
-		std::string name(char_name);
-		if ((size_t)param->mParamHandle > block_data.mMaxParamOffset)
-		{
-			llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
-		}
-
-		if (name.empty())
-		{
-			block_data.mUnnamedParams.push_back(param);
-		}
-		else
-		{
-			// don't use insert, since we want to overwrite existing entries
-			block_data.mNamedParams[name] = param;
-		}
-
-		if (param->mValidationFunc)
-		{
-			block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc));
-		}
-	}
-
-	void BaseBlock::addSynonym(Param& param, const std::string& synonym)
-	{
-		BlockDescriptor& block_data = mostDerivedBlockDescriptor();
-		if (block_data.mInitializationState == BlockDescriptor::INITIALIZING)
-		{
-			param_handle_t handle = getHandleFromParam(&param);
-			
-			// check for invalid derivation from a paramblock (i.e. without using
-			// Block<T, Base_Class>
-			if ((size_t)handle > block_data.mMaxParamOffset)
-			{
-				llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
-			}
-
-			ParamDescriptorPtr param_descriptor = findParamDescriptor(param);
-			if (param_descriptor)
-			{
-				if (synonym.empty())
-				{
-					block_data.mUnnamedParams.push_back(param_descriptor);
-				}
-				else
-				{
-					block_data.mNamedParams[synonym] = param_descriptor;
-				}
-			}
-		}
-	}
-
-	const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const
-	{
-		param_handle_t handle = getHandleFromParam(paramp);
-		for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it)
-		{
-			if (it->second->mParamHandle == handle)
-			{
-				return it->first;
-			}
-		}
-
-		return LLStringUtil::null;
-	}
-
-	ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param)
-	{
-		param_handle_t handle = getHandleFromParam(&param);
-		BlockDescriptor& descriptor = mostDerivedBlockDescriptor();
-		BlockDescriptor::all_params_list_t::iterator end_it = descriptor.mAllParams.end();
-		for (BlockDescriptor::all_params_list_t::iterator it = descriptor.mAllParams.begin();
-			it != end_it;
-			++it)
-		{
-			if ((*it)->mParamHandle == handle) return *it;
-		}
-		return ParamDescriptorPtr();
-	}
-
-	// take all provided params from other and apply to self
-	// NOTE: this requires that "other" is of the same derived type as this
-	bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
-	{
-		bool some_param_changed = false;
-		BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end();
-		for (BlockDescriptor::all_params_list_t::const_iterator it = block_data.mAllParams.begin();
-			it != end_it;
-			++it)
-		{
-			const Param* other_paramp = other.getParamFromHandle((*it)->mParamHandle);
-			ParamDescriptor::merge_func_t merge_func = (*it)->mMergeFunc;
-			if (merge_func)
-			{
-				Param* paramp = getParamFromHandle((*it)->mParamHandle);
-				llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle);
-				some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);
-			}
-		}
-		return some_param_changed;
-	}
-}
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
deleted file mode 100644
index ab20957760..0000000000
--- a/indra/llxuixml/llinitparam.h
+++ /dev/null
@@ -1,2294 +0,0 @@
-/** 
- * @file llinitparam.h
- * @brief parameter block abstraction for creating complex objects and 
- * parsing construction parameters from xml and LLSD
- *
- * $LicenseInfo:firstyear=2008&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 LL_LLPARAM_H
-#define LL_LLPARAM_H
-
-#include <vector>
-#include <boost/function.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/unordered_map.hpp>
-#include <boost/shared_ptr.hpp>
-
-#include "llerror.h"
-
-namespace LLInitParam
-{
-	// used to indicate no matching value to a given name when parsing
-	struct Flag{};
-
-	template<typename T> const T& defaultValue() { static T value; return value; }
-
-	template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >
-    struct ParamCompare 
-	{
-    	static bool equals(const T &a, const T &b)
-		{
-			return a == b;
-		}
-    };
-
-	// boost function types are not comparable
-	template<typename T>
-	struct ParamCompare<T, true>
-	{
-		static bool equals(const T&a, const T &b)
-		{
-			return false;
-		}
-	};
-
-	template<> 
-	struct ParamCompare<LLSD, false>
-	{
-		static bool equals(const LLSD &a, const LLSD &b) { return false; }
-	};
-
-	template<>
-	struct ParamCompare<Flag, false>
-	{
-		static bool equals(const Flag& a, const Flag& b) { return false; }
-	};
-
-
-	// helper functions and classes
-	typedef ptrdiff_t param_handle_t;
-
-	// empty default implementation of key cache
-	// leverages empty base class optimization
-	template <typename T>
-	class TypeValues
-	{
-	private:
-		struct Inaccessable{};
-	public:
-		typedef std::map<std::string, T> value_name_map_t;
-		typedef Inaccessable name_t;
-
-		void setValueName(const std::string& key) {}
-		std::string getValueName() const { return ""; }
-		std::string calcValueName(const T& value) const { return ""; }
-		void clearValueName() const {}
-
-		static bool getValueFromName(const std::string& name, T& value)
-		{
-			return false;
-		}
-
-		static bool valueNamesExist()
-		{
-			return false;
-		}
-
-		static std::vector<std::string>* getPossibleValues()
-		{
-			return NULL;
-		}
-
-		static value_name_map_t* getValueNames() {return NULL;}
-	};
-
-	template <typename T, typename DERIVED_TYPE = TypeValues<T> >
-	class TypeValuesHelper
-	{
-	public:
-		typedef typename std::map<std::string, T> value_name_map_t;
-		typedef std::string name_t;
-
-		//TODO: cache key by index to save on param block size
-		void setValueName(const std::string& value_name) 
-		{
-			mValueName = value_name; 
-		}
-
-		std::string getValueName() const
-		{ 
-			return mValueName; 
-		}
-
-		std::string calcValueName(const T& value) const
-		{
-			value_name_map_t* map = getValueNames();
-			for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end();
-				it != end_it;
-				++it)
-			{
-				if (ParamCompare<T>::equals(it->second, value))
-				{
-					return it->first;
-				}
-			}
-
-			return "";
-		}
-
-		void clearValueName() const
-		{
-			mValueName.clear();
-		}
-
-		static bool getValueFromName(const std::string& name, T& value)
-		{
-			value_name_map_t* map = getValueNames();
-			typename value_name_map_t::iterator found_it = map->find(name);
-			if (found_it == map->end()) return false;
-
-			value = found_it->second;
-			return true;
-		}
-
-		static bool valueNamesExist()
-		{
-			return !getValueNames()->empty();
-		}
-	
-		static value_name_map_t* getValueNames()
-		{
-			static value_name_map_t sMap;
-			static bool sInitialized = false;
-
-			if (!sInitialized)
-			{
-				sInitialized = true;
-				DERIVED_TYPE::declareValues();
-			}
-			return &sMap;
-		}
-
-		static std::vector<std::string>* getPossibleValues()
-		{
-			static std::vector<std::string> sValues;
-
-			value_name_map_t* map = getValueNames();
-			for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end();
-				 it != end_it;
-				 ++it)
-			{
-				sValues.push_back(it->first);
-			}
-			return &sValues;
-		}
-
-		static void declare(const std::string& name, const T& value)
-		{
-			(*getValueNames())[name] = value;
-		}
-
-	protected:
-		static void getName(const std::string& name, const T& value)
-		{}
-
-		mutable std::string	mValueName;
-	};
-
-	class Parser
-	{
-		LOG_CLASS(Parser);
-
-	public:
-		
-		struct CompareTypeID
-		{
-			bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
-			{
-				return lhs->before(*rhs);
-			}
-		};
-
-		typedef std::vector<std::pair<std::string, bool> >					name_stack_t;
-		typedef std::pair<name_stack_t::iterator, name_stack_t::iterator>	name_stack_range_t;
-		typedef std::vector<std::string>									possible_values_t;
-
-		typedef bool (*parser_read_func_t)(Parser& parser, void* output);
-		typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
-		typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
-
-		typedef std::map<const std::type_info*, parser_read_func_t, CompareTypeID>		parser_read_func_map_t;
-		typedef std::map<const std::type_info*, parser_write_func_t, CompareTypeID>		parser_write_func_map_t;
-		typedef std::map<const std::type_info*, parser_inspect_func_t, CompareTypeID>	parser_inspect_func_map_t;
-
-		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
-		:	mParseSilently(false),
-			mParserReadFuncs(&read_map),
-			mParserWriteFuncs(&write_map),
-			mParserInspectFuncs(&inspect_map)
-		{}
-		virtual ~Parser();
-
-		template <typename T> bool readValue(T& param)
-	    {
-		    parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
-		    if (found_it != mParserReadFuncs->end())
-		    {
-			    return found_it->second(*this, (void*)&param);
-		    }
-		    return false;
-	    }
-
-		template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
-		{
-		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
-		    if (found_it != mParserWriteFuncs->end())
-		    {
-			    return found_it->second(*this, (const void*)&param, name_stack);
-		    }
-		    return false;
-		}
-
-		// dispatch inspection to registered inspection functions, for each parameter in a param block
-		template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
-		{
-		    parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
-		    if (found_it != mParserInspectFuncs->end())
-		    {
-			    found_it->second(name_stack, min_count, max_count, possible_values);
-				return true;
-		    }
-			return false;
-		}
-
-		virtual std::string getCurrentElementName() = 0;
-		virtual void parserWarning(const std::string& message);
-		virtual void parserError(const std::string& message);
-		void setParseSilently(bool silent) { mParseSilently = silent; }
-
-	protected:
-		template <typename T>
-		void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
-		{
-			mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
-			mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
-		}
-
-		template <typename T>
-		void registerInspectFunc(parser_inspect_func_t inspect_func)
-		{
-			mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
-		}
-
-		bool				mParseSilently;
-
-	private:
-		parser_read_func_map_t*		mParserReadFuncs;
-		parser_write_func_map_t*	mParserWriteFuncs;
-		parser_inspect_func_map_t*	mParserInspectFuncs;
-	};
-
-	class Param;
-
-	// various callbacks and constraints associated with an individual param
-	struct ParamDescriptor
-	{
-		struct UserData
-		{
-			virtual ~UserData() {}
-		};
-
-		typedef bool(*merge_func_t)(Param&, const Param&, bool);
-		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool);
-		typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
-		typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
-		typedef bool(*validation_func_t)(const Param*);
-
-		ParamDescriptor(param_handle_t p, 
-						merge_func_t merge_func, 
-						deserialize_func_t deserialize_func, 
-						serialize_func_t serialize_func,
-						validation_func_t validation_func,
-						inspect_func_t inspect_func,
-						S32 min_count,
-						S32 max_count);
-
-		ParamDescriptor();
-		~ParamDescriptor();
-
-		param_handle_t		mParamHandle;
-		merge_func_t		mMergeFunc;
-		deserialize_func_t	mDeserializeFunc;
-		serialize_func_t	mSerializeFunc;
-		inspect_func_t		mInspectFunc;
-		validation_func_t	mValidationFunc;
-		S32					mMinCount;
-		S32					mMaxCount;
-		S32					mNumRefs;
-		UserData*			mUserData;
-	};
-
-	typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
-
-	// each derived Block class keeps a static data structure maintaining offsets to various params
-	class BlockDescriptor
-	{
-	public:
-		BlockDescriptor();
-
-		typedef enum e_initialization_state
-		{
-			UNINITIALIZED,
-			INITIALIZING,
-			INITIALIZED
-		} EInitializationState;
-
-		void aggregateBlockData(BlockDescriptor& src_block_data);
-
-		typedef boost::unordered_map<const std::string, ParamDescriptorPtr>						param_map_t; 
-		typedef std::vector<ParamDescriptorPtr>													param_list_t; 
-		typedef std::list<ParamDescriptorPtr>													all_params_list_t;
-		typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> >		param_validation_list_t;
-
-		param_map_t						mNamedParams;			// parameters with associated names
-		param_list_t					mUnnamedParams;			// parameters with_out_ associated names
-		param_validation_list_t			mValidationList;		// parameters that must be validated
-		all_params_list_t				mAllParams;				// all parameters, owns descriptors
-		size_t							mMaxParamOffset;
-		EInitializationState			mInitializationState;	// whether or not static block data has been initialized
-		class BaseBlock*				mCurrentBlockPtr;		// pointer to block currently being constructed
-	};
-
-	class BaseBlock
-	{
-	public:
-		//TODO: implement in terms of owned_ptr
-		template<typename T>
-		class Lazy
-		{
-		public:
-			Lazy()
-				: mPtr(NULL)
-			{}
-
-			~Lazy()
-			{
-				delete mPtr;
-			}
-
-			Lazy(const Lazy& other)
-			{
-				if (other.mPtr)
-				{
-					mPtr = new T(*other.mPtr);
-				}
-				else
-				{
-					mPtr = NULL;
-				}
-			}
-
-			Lazy<T>& operator = (const Lazy<T>& other)
-			{
-				if (other.mPtr)
-				{
-					mPtr = new T(*other.mPtr);
-				}
-				else
-				{
-					mPtr = NULL;
-				}
-				return *this;
-			}
-
-			bool empty() const
-			{
-				return mPtr == NULL;
-			}
-
-			void set(const T& other)
-			{
-				delete mPtr;
-				mPtr = new T(other);
-			}
-
-			const T& get() const
-			{
-				return ensureInstance();
-			}
-
-			T& get()
-			{
-				return ensureInstance();
-			}
-
-		private:
-			// lazily allocate an instance of T
-			T* ensureInstance() const
-			{
-				if (mPtr == NULL)
-				{
-					mPtr = new T();
-				}
-				return mPtr;
-			}
-
-		private:
-			// if you get a compilation error with this, that means you are using a forward declared struct for T
-			// unfortunately, the type traits we rely on don't work with forward declared typed
-			//static const int dummy = sizeof(T);
-
-			mutable T* mPtr;
-		};
-
-		// "Multiple" constraint types, put here in root class to avoid ambiguity during use
-		struct AnyAmount
-		{
-			enum { minCount = 0 };
-			enum { maxCount = U32_MAX };
-		};
-
-		template<U32 MIN_AMOUNT>
-		struct AtLeast
-		{
-			enum { minCount = MIN_AMOUNT };
-			enum { maxCount = U32_MAX };
-		};
-
-		template<U32 MAX_AMOUNT>
-		struct AtMost
-		{
-			enum { minCount = 0 };
-			enum { maxCount = MAX_AMOUNT };
-		};
-
-		template<U32 MIN_AMOUNT, U32 MAX_AMOUNT>
-		struct Between
-		{
-			enum { minCount = MIN_AMOUNT };
-			enum { maxCount = MAX_AMOUNT };
-		};
-
-		template<U32 EXACT_COUNT>
-		struct Exactly
-		{
-			enum { minCount = EXACT_COUNT };
-			enum { maxCount = EXACT_COUNT };
-		};
-
-		// this typedef identifies derived classes as being blocks
-		typedef void baseblock_base_class_t;
-		LOG_CLASS(BaseBlock);
-		friend class Param;
-
-		virtual ~BaseBlock() {}
-		bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
-
-		param_handle_t getHandleFromParam(const Param* param) const;
-		bool validateBlock(bool emit_errors = true) const;
-
-		Param* getParamFromHandle(const param_handle_t param_handle)
-		{
-			if (param_handle == 0) return NULL;
-
-			U8* baseblock_address = reinterpret_cast<U8*>(this);
-			return reinterpret_cast<Param*>(baseblock_address + param_handle);
-		}
-
-		const Param* getParamFromHandle(const param_handle_t param_handle) const
-		{
-			const U8* baseblock_address = reinterpret_cast<const U8*>(this);
-			return reinterpret_cast<const Param*>(baseblock_address + param_handle);
-		}
-
-		void addSynonym(Param& param, const std::string& synonym);
-
-		// Blocks can override this to do custom tracking of changes
-		virtual void paramChanged(const Param& changed_param, bool user_provided) {}
-
-		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
-		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
-		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
-
-		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
-		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
-
-		// take all provided params from other and apply to self
-		bool overwriteFrom(const BaseBlock& other)
-		{
-			return false;
-		}
-
-		// take all provided params that are not already provided, and apply to self
-		bool fillFrom(const BaseBlock& other)
-		{
-			return false;
-		}
-
-		static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name);
-
-		ParamDescriptorPtr findParamDescriptor(const Param& param);
-
-	protected:
-		void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size);
-
-
-		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
-		{
-			return mergeBlock(block_data, source, overwrite);
-		}
-		// take all provided params from other and apply to self
-		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite);
-
-		static BlockDescriptor& selfBlockDescriptor()
-		{
-			static BlockDescriptor sBlockDescriptor;
-			return sBlockDescriptor;
-		}
-
-	private:
-		const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
-	};
-
-	template<typename T>
-	struct ParamCompare<BaseBlock::Lazy<T>, false >
-	{
-		static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) { return !a.empty() || !b.empty(); }
-	};
-
-	class Param
-	{
-	public:
-		void setProvided(bool is_provided = true)
-		{
-			mIsProvided = is_provided;
-			enclosingBlock().paramChanged(*this, is_provided);
-		}
-
-		Param& operator =(const Param& other)
-		{
-			mIsProvided = other.mIsProvided;
-			// don't change mEnclosingblockoffset
-			return *this;
-		}
-	protected:
-
-		bool anyProvided() const { return mIsProvided; }
-
-		Param(BaseBlock* enclosing_block);
-
-		// store pointer to enclosing block as offset to reduce space and allow for quick copying
-		BaseBlock& enclosingBlock() const
-		{ 
-			const U8* my_addr = reinterpret_cast<const U8*>(this);
-			// get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class
-			return *const_cast<BaseBlock*>
-				(reinterpret_cast<const BaseBlock*>
-					(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset));
-		}
-
-	private:
-		friend class BaseBlock;
-
-		U32		mEnclosingBlockOffset:31;
-		U32		mIsProvided:1;
-
-	};
-
-	// these templates allow us to distinguish between template parameters
-	// that derive from BaseBlock and those that don't
-	template<typename T, typename Void = void>
-	struct IsBlock
-	{
-		static const bool value = false;
-		struct EmptyBase {};
-		typedef EmptyBase base_class_t;
-	};
-
-	template<typename T>
-	struct IsBlock<T, typename T::baseblock_base_class_t>
-	{
-		static const bool value = true;
-		typedef BaseBlock base_class_t;
-	};
-
-	template<typename T>
-	struct IsBlock<BaseBlock::Lazy<T>, typename T::baseblock_base_class_t >
-	{
-		static const bool value = true;
-		typedef BaseBlock base_class_t;
-	};
-
-	template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value>
-	class ParamValue : public NAME_VALUE_LOOKUP
-	{
-	public:
-		typedef const T&							value_assignment_t;
-		typedef T									value_t;
-		typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK>	self_t;
-
-		ParamValue(): mValue() {}
-		ParamValue(value_assignment_t other) : mValue(other) {}
-
-		void setValue(value_assignment_t val)
-		{
-			mValue = val;
-		}
-
-		value_assignment_t getValue() const
-		{
-			return mValue;
-		}
-
-		T& getValue()
-		{
-			return mValue;
-		}
-
-		operator value_assignment_t() const
-		{
-			return mValue;
-		}
-
-		value_assignment_t operator()() const
-		{
-			return mValue;
-		}
-
-		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name)
-		{
-			*this = name;
-		}
-
-		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
-		{
-			if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue))
-			{
-				setValueName(name);
-			}
-
-			return *this;
-		}
-
-	protected:
-		T mValue;
-	};
-
-	template<typename T, typename NAME_VALUE_LOOKUP>
-	class ParamValue<T, NAME_VALUE_LOOKUP, true> 
-	:	public T,
-		public NAME_VALUE_LOOKUP
-	{
-	public:
-		typedef const T&							value_assignment_t;
-		typedef T									value_t;
-		typedef ParamValue<T, NAME_VALUE_LOOKUP, true>	self_t;
-
-		ParamValue() 
-		:	T(),
-			mValidated(false)
-		{}
-
-		ParamValue(value_assignment_t other)
-		:	T(other),
-			mValidated(false)
-		{}
-
-		void setValue(value_assignment_t val)
-		{
-			*this = val;
-		}
-
-		value_assignment_t getValue() const
-		{
-			return *this;
-		}
-
-		T& getValue()
-		{
-			return *this;
-		}
-
-		operator value_assignment_t() const
-		{
-			return *this;
-		}
-		
-		value_assignment_t operator()() const
-		{
-			return *this;
-		}
-
-		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name)
-		{
-			*this = name;
-		}
-
-		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
-		{
-			if (NAME_VALUE_LOOKUP::getValueFromName(name, *this))
-			{
-				setValueName(name);
-			}
-
-			return *this;
-		}
-
-	protected:
-		mutable bool 	mValidated; // lazy validation flag
-	};
-
-	template<typename NAME_VALUE_LOOKUP>
-	class ParamValue<std::string, NAME_VALUE_LOOKUP, false>
-	: public NAME_VALUE_LOOKUP
-	{
-	public:
-		typedef const std::string&	value_assignment_t;
-		typedef std::string			value_t;
-		typedef ParamValue<std::string, NAME_VALUE_LOOKUP, false>	self_t;
-
-		ParamValue(): mValue() {}
-		ParamValue(value_assignment_t other) : mValue(other) {}
-
-		void setValue(value_assignment_t val)
-		{
-			if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue))
-			{
-				NAME_VALUE_LOOKUP::setValueName(val);
-			}
-			else
-			{
-				mValue = val;
-			}
-		}
-
-		value_assignment_t getValue() const
-		{
-			return mValue;
-		}
-
-		std::string& getValue()
-		{
-			return mValue;
-		}
-
-		operator value_assignment_t() const
-		{
-			return mValue;
-		}
-
-		value_assignment_t operator()() const
-		{
-			return mValue;
-		}
-
-	protected:
-		std::string mValue;
-	};
-
-
-	template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
-	struct ParamIterator
-	{
-		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator		const_iterator;
-		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator			iterator;
-	};
-
-	// specialize for custom parsing/decomposition of specific classes
-	// e.g. TypedParam<LLRect> has left, top, right, bottom, etc...
-	template<typename	T,
-			typename	NAME_VALUE_LOOKUP = TypeValues<T>,
-			bool		HAS_MULTIPLE_VALUES = false,
-			bool		VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>
-	class TypedParam 
-	:	public Param, 
-		public ParamValue<T, NAME_VALUE_LOOKUP>
-	{
-	public:
-		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>		self_t;
-		typedef ParamValue<T, NAME_VALUE_LOOKUP>											param_value_t;
-		typedef typename param_value_t::value_assignment_t				value_assignment_t;
-		typedef NAME_VALUE_LOOKUP															name_value_lookup_t;
-
-		using param_value_t::operator();
-
-		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
-		:	Param(block_descriptor.mCurrentBlockPtr)
-		{
-			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
-			{
- 				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
-												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
-												&mergeWith,
-												&deserializeParam,
-												&serializeParam,
-												validate_func,
-												&inspectParam,
-												min_count, max_count));
-				BaseBlock::addParam(block_descriptor, param_descriptor, name);
-			}
-
-			setValue(value);
-		} 
-
-		bool isProvided() const { return Param::anyProvided(); }
-
-		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
-		{ 
-			self_t& typed_param = static_cast<self_t&>(param);
-			// no further names in stack, attempt to parse value now
-			if (name_stack_range.first == name_stack_range.second)
-			{
-				if (parser.readValue(typed_param.getValue()))
-				{
-					typed_param.clearValueName();
-					typed_param.setProvided();
-					return true;
-				}
-				
-				// try to parse a known named value
-				if(name_value_lookup_t::valueNamesExist())
-				{
-					// try to parse a known named value
-					std::string name;
-					if (parser.readValue(name))
-					{
-						// try to parse a per type named value
-						if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))
-						{
-							typed_param.setValueName(name);
-							typed_param.setProvided();
-							return true;
-						}
-
-					}
-				}
-			}
-			return false;
-		}
-
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
-		{
-			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return;
-
-			if (!name_stack.empty())
-			{
-				name_stack.back().second = true;
-			}
-
-			std::string key = typed_param.getValueName();
-
-			// first try to write out name of name/value pair
-
-			if (!key.empty())
-			{
-				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
-				{
-					parser.writeValue(key, name_stack);
-				}
-			}
-			// then try to serialize value directly
-			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue()))
-			{
-				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
-				{
-					std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
-					if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))
-					{
-						parser.writeValue(calculated_key, name_stack);
-					}
-				}
-			}
-		}
-
-		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
-		{
-			// tell parser about our actual type
-			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
-			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
-			if (name_value_lookup_t::getPossibleValues())
-			{
-				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());
-			}
-		}
-
-		void set(value_assignment_t val, bool flag_as_provided = true)
-		{
-			param_value_t::clearValueName();
-			setValue(val);
-			setProvided(flag_as_provided);
-		}
-
-		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
-		{
-			return static_cast<self_t&>(param_value_t::operator =(name));
-		}
-
-	protected:
-
-		self_t& operator =(const self_t& other)
-		{
-			param_value_t::operator =(other);
-			Param::operator =(other);
-			return *this;
-		}
-
-		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
-		{
-			const self_t& src_typed_param = static_cast<const self_t&>(src);
-			self_t& dst_typed_param = static_cast<self_t&>(dst);
-
-			if (src_typed_param.isProvided()
-				&& (overwrite || !dst_typed_param.isProvided()))
-			{
-				dst_typed_param.set(src_typed_param.getValue());
-				return true;
-			}
-			return false;
-		}
-	};
-
-	// parameter that is a block
-	template <typename T, typename NAME_VALUE_LOOKUP>
-	class TypedParam<T, NAME_VALUE_LOOKUP, false, true> 
-	:	public Param,
-		public ParamValue<T, NAME_VALUE_LOOKUP>
-	{
-	public:
-		typedef ParamValue<T, NAME_VALUE_LOOKUP>				param_value_t;
-		typedef typename param_value_t::value_assignment_t		value_assignment_t;
-		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true>	self_t;
-		typedef NAME_VALUE_LOOKUP								name_value_lookup_t;
-
-		using param_value_t::operator();
-
-		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
-		:	Param(block_descriptor.mCurrentBlockPtr),
-			param_value_t(value)
-		{
-			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
-			{
-				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
-												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
-												&mergeWith,
-												&deserializeParam,
-												&serializeParam,
-												validate_func, 
-												&inspectParam,
-												min_count, max_count));
-				BaseBlock::addParam(block_descriptor, param_descriptor, name);
-			}
-		}
-
-		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
-		{ 
-			self_t& typed_param = static_cast<self_t&>(param);
-			// attempt to parse block...
-			if(typed_param.deserializeBlock(parser, name_stack_range, new_name))
-			{
-				typed_param.clearValueName();
-				typed_param.setProvided();
-				return true;
-			}
-
-			if(name_value_lookup_t::valueNamesExist())
-			{
-				// try to parse a known named value
-				std::string name;
-				if (parser.readValue(name))
-				{
-					// try to parse a per type named value
-					if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))
-					{
-						typed_param.setValueName(name);
-						typed_param.setProvided();
-						return true;
-					}
-
-				}
-			}
-			return false;
-		}
-
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
-		{
-			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return;
-
-			if (!name_stack.empty())
-			{
-				name_stack.back().second = true;
-			}
-
-			std::string key = typed_param.getValueName();
-			if (!key.empty())
-			{
-				if (!parser.writeValue(key, name_stack))
-				{
-					return;
-				}
-			}
-			else
-			{
-				typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param));
-			}
-		}
-
-		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
-		{
-			// I am a param that is also a block, so just recurse into my contents
-			const self_t& typed_param = static_cast<const self_t&>(param);
-			typed_param.inspectBlock(parser, name_stack, min_count, max_count);
-		}
-
-		// a param-that-is-a-block is provided when the user has set one of its child params
-		// *and* the block as a whole validates
-		bool isProvided() const 
-		{ 
-			// only validate block when it hasn't already passed validation with current data
-			if (Param::anyProvided() && !param_value_t::mValidated)
-			{
-				// a sub-block is "provided" when it has been filled in enough to be valid
-				param_value_t::mValidated = param_value_t::validateBlock(false);
-			}
-			return Param::anyProvided() && param_value_t::mValidated;
-		}
-
-		// assign block contents to this param-that-is-a-block
-		void set(value_assignment_t val, bool flag_as_provided = true)
-		{
-			setValue(val);
-			param_value_t::clearValueName();
-			// force revalidation of block
-			// next call to isProvided() will update provision status based on validity
-			param_value_t::mValidated = false;
-			setProvided(flag_as_provided);
-		}
-
-		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
-		{
-			return static_cast<self_t&>(param_value_t::operator =(name));
-		}
-
-		// propagate changed status up to enclosing block
-		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
-		{ 
-			param_value_t::paramChanged(changed_param, user_provided);
-			if (user_provided)
-			{
-				// a child param has been explicitly changed
-				// so *some* aspect of this block is now provided
-				param_value_t::mValidated = false;
-				setProvided();
-				param_value_t::clearValueName();
-			}
-			else
-			{
-				Param::enclosingBlock().paramChanged(*this, user_provided);
-			}
-		}
-
-	protected:
-
-		self_t& operator =(const self_t& other)
-		{
-			param_value_t::operator =(other);
-			Param::operator =(other);
-			return *this;
-		}
-
-		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
-		{
-			const self_t& src_typed_param = static_cast<const self_t&>(src);
-			self_t& dst_typed_param = static_cast<self_t&>(dst);
-
-			if (src_typed_param.anyProvided())
-			{
-				if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite))
-				{
-					dst_typed_param.clearValueName();
-					dst_typed_param.setProvided(true);
-					return true;
-				}
-			}
-			return false;
-		}
-	};
-
-	// container of non-block parameters
-	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
-	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> 
-	:	public Param
-	{
-	public:
-		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>		self_t;
-		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>					param_value_t;
-		typedef typename std::vector<param_value_t>							container_t;
-		typedef const container_t&											value_assignment_t;
-
-		typedef typename param_value_t::value_t								value_t;
-		typedef NAME_VALUE_LOOKUP											name_value_lookup_t;
-		
-		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
-		:	Param(block_descriptor.mCurrentBlockPtr)
-		{
-			std::copy(value.begin(), value.end(), std::back_inserter(mValues));
-
-			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
-			{
-				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
-												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
-												&mergeWith,
-												&deserializeParam,
-												&serializeParam,
-												validate_func,
-												&inspectParam,
-												min_count, max_count));
-				BaseBlock::addParam(block_descriptor, param_descriptor, name);
-			}
-		} 
-
-		bool isProvided() const { return Param::anyProvided(); }
-
-		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
-		{ 
-			self_t& typed_param = static_cast<self_t&>(param);
-			value_t value;
-			// no further names in stack, attempt to parse value now
-			if (name_stack_range.first == name_stack_range.second)
-			{
-				// attempt to read value directly
-				if (parser.readValue(value))
-				{
-					typed_param.add(value);
-					return true;
-				}
-				
-				// try to parse a known named value
-				if(name_value_lookup_t::valueNamesExist())
-				{
-					// try to parse a known named value
-					std::string name;
-					if (parser.readValue(name))
-					{
-						// try to parse a per type named value
-						if (name_value_lookup_t::getValueFromName(name, value))
-						{
-							typed_param.add(value);
-							typed_param.mValues.back().setValueName(name);
-							return true;
-						}
-
-					}
-				}
-			}
-			return false;
-		}
-
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
-		{
-			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided() || name_stack.empty()) return;
-
-			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
-				it != end_it;
-				++it)
-			{
-				std::string key = it->getValueName();
-				name_stack.back().second = true;
-
-				if(key.empty())
-				// not parsed via name values, write out value directly
-				{
-					bool value_written = parser.writeValue(*it, name_stack);
-					if (!value_written)
-					{
-						std::string calculated_key = it->calcValueName(it->getValue());
-						if (!parser.writeValue(calculated_key, name_stack))
-						{
-							break;
-						}
-					}
-				}
-				else 
-				{
-					if(!parser.writeValue(key, name_stack))
-					{
-						break;
-					}
-				}
-			}
-		}
-
-		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
-		{
-			parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL);
-			if (name_value_lookup_t::getPossibleValues())
-			{
-				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());
-			}
-		}
-
-		void set(value_assignment_t val, bool flag_as_provided = true)
-		{
-			mValues = val;
-			setProvided(flag_as_provided);
-		}
-
-		param_value_t& add()
-		{
-			mValues.push_back(param_value_t(value_t()));
-			Param::setProvided();
-			return mValues.back();
-		}
-
-		void add(const value_t& item)
-		{
-			param_value_t param_value;
-			param_value.setValue(item);
-			mValues.push_back(param_value);
-			setProvided();
-		}
-
-		void add(const typename name_value_lookup_t::name_t& name)
-		{
-			value_t value;
-
-			// try to parse a per type named value
-			if (name_value_lookup_t::getValueFromName(name, value))
-			{
-				add(value);
-				mValues.back().setValueName(name);
-			}
-		}
-
-		// implicit conversion
-		operator value_assignment_t() const { return mValues; } 
-		// explicit conversion		
-		value_assignment_t operator()() const { return mValues; }
-
-		typedef typename container_t::iterator iterator;
-		typedef typename container_t::const_iterator const_iterator;
-		iterator begin() { return mValues.begin(); }
-		iterator end() { return mValues.end(); }
-		const_iterator begin() const { return mValues.begin(); }
-		const_iterator end() const { return mValues.end(); }
-		bool empty() const { return mValues.empty(); }
-		size_t size() const { return mValues.size(); }
-
-		U32 numValidElements() const
-		{
-			return mValues.size();
-		}
-
-	protected:
-		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
-		{
-			const self_t& src_typed_param = static_cast<const self_t&>(src);
-			self_t& dst_typed_param = static_cast<self_t&>(dst);
-
-			if (overwrite)
-			{
-				std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
-			}
-			else
-			{
-				container_t new_values(src_typed_param.mValues);
-				std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
-				std::swap(dst_typed_param.mValues, new_values);
-			}
-
-			if (src_typed_param.begin() != src_typed_param.end())
-			{
-				dst_typed_param.setProvided();
-			}
-			return true;
-		}
-
-		container_t		mValues;
-	};
-
-	// container of block parameters
-	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
-	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> 
-	:	public Param
-	{
-	public:
-		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>	self_t;
-		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>				param_value_t;
-		typedef typename std::vector<param_value_t>						container_t;
-		typedef const container_t&										value_assignment_t;
-		typedef typename param_value_t::value_t							value_t;
-		typedef NAME_VALUE_LOOKUP										name_value_lookup_t;
-
-		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
-		:	Param(block_descriptor.mCurrentBlockPtr)
-		{
-			std::copy(value.begin(), value.end(), back_inserter(mValues));
-
-			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
-			{
-				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
-												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
-												&mergeWith,
-												&deserializeParam,
-												&serializeParam,
-												validate_func,
-												&inspectParam,
-												min_count, max_count));
-				BaseBlock::addParam(block_descriptor, param_descriptor, name);
-			}
-		} 
-
-		bool isProvided() const { return Param::anyProvided(); }
-
-		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) 
-		{ 
-			self_t& typed_param = static_cast<self_t&>(param);
-			bool new_value = false;
-
-			if (new_name || typed_param.mValues.empty())
-			{
-				new_value = true;
-				typed_param.mValues.push_back(value_t());
-			}
-
-			param_value_t& value = typed_param.mValues.back();
-
-			// attempt to parse block...
-			if(value.deserializeBlock(parser, name_stack_range, new_name))
-			{
-				typed_param.setProvided();
-				return true;
-			}
-			else if(name_value_lookup_t::valueNamesExist())
-			{
-				// try to parse a known named value
-				std::string name;
-				if (parser.readValue(name))
-				{
-					// try to parse a per type named value
-					if (name_value_lookup_t::getValueFromName(name, value.getValue()))
-					{
-						typed_param.mValues.back().setValueName(name);
-						typed_param.setProvided();
-						return true;
-					}
-
-				}
-			}
-
-			if (new_value)
-			{	// failed to parse new value, pop it off
-				typed_param.mValues.pop_back();
-			}
-
-			return false;
-		}
-
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
-		{
-			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided() || name_stack.empty()) return;
-
-			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
-				it != end_it;
-				++it)
-			{
-				name_stack.back().second = true;
-
-				std::string key = it->getValueName();
-				if (!key.empty())
-				{
-					parser.writeValue(key, name_stack);
-				}
-				// Not parsed via named values, write out value directly
-				// NOTE: currently we don't worry about removing default values in Multiple
-				else 
-				{
-					it->serializeBlock(parser, name_stack, NULL);
-				}
-			}
-		}
-
-		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
-		{
-			// I am a vector of blocks, so describe my contents recursively
-			param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count);
-		}
-
-		void set(value_assignment_t val, bool flag_as_provided = true)
-		{
-			mValues = val;
-			setProvided(flag_as_provided);
-		}
-
-		param_value_t& add()
-		{
-			mValues.push_back(value_t());
-			setProvided();
-			return mValues.back();
-		}
-
-		void add(const value_t& item)
-		{
-			mValues.push_back(item);
-			setProvided();
-		}
-
-		void add(const typename name_value_lookup_t::name_t& name)
-		{
-			value_t value;
-
-			// try to parse a per type named value
-			if (name_value_lookup_t::getValueFromName(name, value))
-			{
-				add(value);
-				mValues.back().setValueName(name);
-			}
-		}
-
-		// implicit conversion
-		operator value_assignment_t() const { return mValues; } 
-		// explicit conversion
-		value_assignment_t operator()() const { return mValues; }
-
-		typedef typename container_t::iterator iterator;
-		typedef typename container_t::const_iterator const_iterator;
-		iterator begin() { return mValues.begin(); }
-		iterator end() { return mValues.end(); }
-		const_iterator begin() const { return mValues.begin(); }
-		const_iterator end() const { return mValues.end(); }
-		bool empty() const { return mValues.empty(); }
-		size_t size() const { return mValues.size(); }
-
-		U32 numValidElements() const
-		{
-			U32 count = 0;
-			for (const_iterator it = mValues.begin(), end_it = mValues.end();
-				it != end_it;
-				++it)
-			{
-				if(it->validateBlock(false)) count++;
-			}
-			return count;
-		}
-
-	protected:
-
-		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
-		{
-			const self_t& src_typed_param = static_cast<const self_t&>(src);
-			self_t& dst_typed_param = static_cast<self_t&>(dst);
-
-			if (overwrite)
-			{
-				std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
-			}
-			else
-			{
-				container_t new_values(src_typed_param.mValues);
-				std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
-				std::swap(dst_typed_param.mValues, new_values);
-			}
-
-			if (src_typed_param.begin() != src_typed_param.end())
-			{
-				dst_typed_param.setProvided();
-			}
-
-			return true;
-		}
-
-		container_t			mValues;
-	};
-
-	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
-	class ChoiceBlock : public BASE_BLOCK
-	{
-		typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK>	self_t;
-		typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK>	enclosing_block_t;
-		typedef BASE_BLOCK								base_block_t;
-		
-		LOG_CLASS(self_t);
-	public:
-		// take all provided params from other and apply to self
-		bool overwriteFrom(const self_t& other)
-		{
-			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true);
-		}
-
-		// take all provided params that are not already provided, and apply to self
-		bool fillFrom(const self_t& other)
-		{
-			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false);
-		}
-
-		bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
-		{
-			bool source_override = source_provided && (overwrite || !dest_provided);
-
-			if (source_override || source.mCurChoice == mCurChoice)
-			{
-				return mergeBlock(block_data, source, overwrite);
-			}
-			return false;
-		}
-
-		// merge with other block
-		bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite)
-		{
-			mCurChoice = other.mCurChoice;
-			return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite);
-		}
-
-		// clear out old choice when param has changed
-		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
-		{ 
-			param_handle_t changed_param_handle = base_block_t::getHandleFromParam(&changed_param);
-			// if we have a new choice...
-			if (changed_param_handle != mCurChoice)
-			{
-				// clear provided flag on previous choice
-				Param* previous_choice = base_block_t::getParamFromHandle(mCurChoice);
-				if (previous_choice) 
-				{
-					previous_choice->setProvided(false);
-				}
-				mCurChoice = changed_param_handle;
-			}
-			base_block_t::paramChanged(changed_param, user_provided);
-		}
-
-		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
-		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
-
-	protected:
-		ChoiceBlock()
-		:	mCurChoice(0)
-		{
-			BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK));
-		}
-
-		// Alternatives are mutually exclusive wrt other Alternatives in the same block.  
-		// One alternative in a block will always have isChosen() == true.
-		// At most one alternative in a block will have isProvided() == true.
-		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
-		class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>
-		{
-		public:
-			friend class ChoiceBlock<DERIVED_BLOCK>;
-
-			typedef Alternative<T, NAME_VALUE_LOOKUP>									self_t;
-			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;
-			typedef typename super_t::value_assignment_t								value_assignment_t;
-
-			using super_t::operator =;
-
-			explicit Alternative(const char* name = "", value_assignment_t val = defaultValue<T>())
-			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1),
-				mOriginalValue(val)
-			{
-				// assign initial choice to first declared option
-				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr);
-				if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))
-				{
-					if(blockp->mCurChoice == 0)
-					{
-						blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this);
-					}
-				}
-			}
-
-			void choose()
-			{
-				static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true);
-			}
-
-			void chooseAs(value_assignment_t val)
-			{
-				super_t::set(val);
-			}
-
-			void operator =(value_assignment_t val)
-			{
-				super_t::set(val);
-			}
-
-			void operator()(typename super_t::value_assignment_t val) 
-			{ 
-				super_t::set(val);
-			}
-
-			operator value_assignment_t() const 
-			{
-				return (*this)();
-			} 
-
-			value_assignment_t operator()() const 
-			{ 
-				if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)
-				{
-					return super_t::getValue(); 
-				}
-				return mOriginalValue;
-			} 
-
-			bool isChosen() const
-			{
-				return static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this;
-			}
-		
-		private:
-			T			mOriginalValue;
-		};
-
-	protected:
-		static BlockDescriptor& selfBlockDescriptor()
-		{
-			static BlockDescriptor sBlockDescriptor;
-			return sBlockDescriptor;
-		}
-
-	private:
-		param_handle_t	mCurChoice;
-
-		const Param* getCurrentChoice() const
-		{
-			return base_block_t::getParamFromHandle(mCurChoice);
-		}
-	};
-
-	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
-	class Block 
-	:	public BASE_BLOCK
-	{
-		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	self_t;
-		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	block_t;
-
-	public:
-		typedef BASE_BLOCK base_block_t;
-
-		// take all provided params from other and apply to self
-		bool overwriteFrom(const self_t& other)
-		{
-			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true);
-		}
-
-		// take all provided params that are not already provided, and apply to self
-		bool fillFrom(const self_t& other)
-		{
-			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false);
-		}
-
-		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
-		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
-
-	protected:
-		Block()
-		{
-			//#pragma message("Parsing LLInitParam::Block")
-			BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK));
-		}
-
-		//
-		// Nested classes for declaring parameters
-		//
-		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
-		class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>
-		{
-		public:
-			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;
-			typedef typename super_t::value_assignment_t								value_assignment_t;
-
-			using super_t::operator();
-			using super_t::operator =;
-			
-			explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>())
-			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1)
-			{
-				//#pragma message("Parsing LLInitParam::Block::Optional")
-			}
-
-			Optional& operator =(value_assignment_t val)
-			{
-				set(val);
-				return *this;
-			}
-
-			DERIVED_BLOCK& operator()(value_assignment_t val)
-			{
-				super_t::set(val);
-				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
-			}
-		};
-
-		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
-		class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
-		{
-		public:
-			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;
-			typedef Mandatory<T, NAME_VALUE_LOOKUP>										self_t;
-			typedef typename super_t::value_assignment_t								value_assignment_t;
-
-			using super_t::operator();
-			using super_t::operator =;
-
-			// mandatory parameters require a name to be parseable
-			explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>())
-			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1)
-			{}
-
-			Mandatory& operator =(value_assignment_t val)
-			{
-				set(val);
-				return *this;
-			}
-
-			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
-			{
-				super_t::set(val);
-				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
-			}
-
-			static bool validate(const Param* p)
-			{
-				// valid only if provided
-				return static_cast<const self_t*>(p)->isProvided();
-			}
-
-		};
-
-		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> >
-		class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>
-		{
-		public:
-			typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>	super_t;
-			typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP>							self_t;
-			typedef typename super_t::container_t									container_t;
-			typedef typename super_t::value_assignment_t							value_assignment_t;
-			typedef typename super_t::iterator										iterator;
-			typedef typename super_t::const_iterator								const_iterator;
-
-			explicit Multiple(const char* name = "")
-			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)
-			{}
-
-			Multiple& operator =(value_assignment_t val)
-			{
-				set(val);
-				return *this;
-			}
-
-			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
-			{
-				super_t::set(val);
-				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
-			}
-
-			static bool validate(const Param* paramp) 
-			{
-				U32 num_valid = ((super_t*)paramp)->numValidElements();
-				return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount;
-			}
-		};
-
-		class Deprecated : public Param
-		{
-		public:
-			explicit Deprecated(const char* name)
-			:	Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr)
-			{
-				BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor();
-				if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
-				{
-					ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
-													block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
-													NULL,
-													&deserializeParam,
-													NULL,
-													NULL,
-													NULL, 
-													0, S32_MAX));
-					BaseBlock::addParam(block_descriptor, param_descriptor, name);
-				}
-			}
-			
-			static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
-			{
-				if (name_stack_range.first == name_stack_range.second)
-				{
-					//std::string message = llformat("Deprecated value %s ignored", getName().c_str());
-					//parser.parserWarning(message);
-					return true;
-				}
-
-				return false;
-			}
-		};
-
-		// different semantics for documentation purposes, but functionally identical
-		typedef Deprecated Ignored;
-
-	protected:
-		static BlockDescriptor& selfBlockDescriptor()
-		{
-			static BlockDescriptor sBlockDescriptor;
-			return sBlockDescriptor;
-		}
-
-		template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block>
-		void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param, 
-			typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value)
-		{
-			if (!param.isProvided())
-			{
-				param.set(value, false);
-			}
-		}
-
-	};
-	
-	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
-	class BatchBlock
-	:	public Block<DERIVED_BLOCK, BASE_BLOCK>
-	{
-	public:
-		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> self_t;
-		typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t;
-
-		BatchBlock()
-		{}
-
-		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)
-		{
-			if (new_name)
-			{
-				// reset block
-				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
-			}
-			return super_t::deserializeBlock(p, name_stack_range, new_name);
-		}
-
-		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
-		{
-			if (overwrite)
-			{
-				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
-				// merge individual parameters into destination
-				return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite);
-			}
-			return false;
-		}
-	protected:
-		static const DERIVED_BLOCK& defaultBatchValue()
-		{
-			static DERIVED_BLOCK default_value;
-			return default_value;
-		}
-	};
-
-	// FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class
-	// and not the derived class with the actual params
-	template<typename DERIVED_BLOCK,
-			typename BASE_BLOCK,
-			typename NAME_VALUE_LOOKUP>
-	class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>,
-					NAME_VALUE_LOOKUP,
-					true>
-	:	public NAME_VALUE_LOOKUP,
-		protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK>
-	{
-	public:
-		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t;
-		typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>&	value_assignment_t;
-		typedef block_t value_t;
-
-		ParamValue()
-		:	block_t(),
-			mValidated(false)
-		{}
-
-		ParamValue(value_assignment_t other)
-		:	block_t(other),
-			mValidated(false)
-		{
-		}
-
-		void setValue(value_assignment_t val)
-		{
-			*this = val;
-		}
-
-		value_assignment_t getValue() const
-		{
-			return *this;
-		}
-
-		BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& getValue()
-		{
-			return *this;
-		}
-
-		operator value_assignment_t() const
-		{
-			return *this;
-		}
-
-		value_assignment_t operator()() const
-		{
-			return *this;
-		}
-
-	protected:
-		mutable bool 	mValidated; // lazy validation flag
-	};
-
-	template<typename T, bool IS_BLOCK>
-	class ParamValue <BaseBlock::Lazy<T>,
-					TypeValues<T>,
-					IS_BLOCK>
-	:	public IsBlock<T>::base_class_t
-	{
-	public:
-		typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<T>, false> self_t;
-		typedef const T& value_assignment_t;
-		typedef T value_t;
-	
-		ParamValue()
-		:	mValue(),
-			mValidated(false)
-		{}
-
-		ParamValue(value_assignment_t other)
-		:	mValue(other),
-			mValidated(false)
-		{}
-
-		void setValue(value_assignment_t val)
-		{
-			mValue.set(val);
-		}
-
-		value_assignment_t getValue() const
-		{
-			return mValue.get();
-		}
-
-		T& getValue()
-		{
-			return mValue.get();
-		}
-
-		operator value_assignment_t() const
-		{
-			return mValue.get();
-		}
-
-		value_assignment_t operator()() const
-		{
-			return mValue.get();
-		}
-
-		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)
-		{
-			return mValue.get().deserializeBlock(p, name_stack_range, new_name);
-		}
-
-		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
-		{
-			if (mValue.empty()) return;
-			
-			mValue.get().serializeBlock(p, name_stack, diff_block);
-		}
-
-		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
-		{
-			if (mValue.empty()) return false;
-
-			return mValue.get().inspectBlock(p, name_stack, min_count, max_count);
-		}
-
-	protected:
-		mutable bool 	mValidated; // lazy validation flag
-
-	private:
-		BaseBlock::Lazy<T>	mValue;
-	};
-
-	template <>
-	class ParamValue <LLSD,
-					TypeValues<LLSD>,
-					false>
-	:	public TypeValues<LLSD>,
-		public BaseBlock
-	{
-	public:
-		typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t;
-		typedef const LLSD&	value_assignment_t;
-
-		ParamValue()
-		:	mValidated(false)
-		{}
-
-		ParamValue(value_assignment_t other)
-		:	mValue(other),
-			mValidated(false)
-		{}
-
-		void setValue(value_assignment_t val) { mValue = val; }
-
-		value_assignment_t getValue() const { return mValue; }
-		LLSD& getValue() { return mValue; }
-
-		operator value_assignment_t() const { return mValue; }
-		value_assignment_t operator()() const { return mValue; }
-		
-
-		// block param interface
-		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
-		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
-		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
-		{
-			//TODO: implement LLSD params as schema type Any
-			return true;
-		}
-
-	protected:
-		mutable bool 	mValidated; // lazy validation flag
-
-	private:
-		static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack);
-
-		LLSD mValue;
-	};
-
-	template<typename T>
-	class CustomParamValue
-	:	public Block<ParamValue<T, TypeValues<T> > >,
-		public TypeValues<T>
-	{
-	public:
-		typedef enum e_value_age
-		{	
-			VALUE_NEEDS_UPDATE,		// mValue needs to be refreshed from the block parameters
-			VALUE_AUTHORITATIVE,	// mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue)
-			BLOCK_AUTHORITATIVE		// mValue is derived from the block parameters, which are authoritative
-		} EValueAge;
-
-		typedef ParamValue<T, TypeValues<T> >	derived_t;
-		typedef CustomParamValue<T>				self_t;
-		typedef Block<derived_t>				block_t;
-		typedef const T&						value_assignment_t;
-		typedef T								value_t;
-
-
-		CustomParamValue(const T& value = T())
-		:	mValue(value),
-			mValueAge(VALUE_AUTHORITATIVE),
-			mValidated(false)
-		{}
-
-		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name)
-		{
-			derived_t& typed_param = static_cast<derived_t&>(*this);
-			// try to parse direct value T
-			if (name_stack_range.first == name_stack_range.second)
-			{
-				if(parser.readValue(typed_param.mValue))
-				{
-					typed_param.mValueAge = VALUE_AUTHORITATIVE;
-					typed_param.updateBlockFromValue(false);
-
-					typed_param.clearValueName();
-
-					return true;
-				}
-			}
-
-			// fall back on parsing block components for T
-			return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
-		}
-
-		void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
-		{
-			const derived_t& typed_param = static_cast<const derived_t&>(*this);
-			const derived_t* diff_param = static_cast<const derived_t*>(diff_block);
-			
-			std::string key = typed_param.getValueName();
-
-			// first try to write out name of name/value pair
-			if (!key.empty())
-			{
-				if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key))
-				{
-					parser.writeValue(key, name_stack);
-				}
-			}
-			// then try to serialize value directly
-			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))
-            {
-				
-				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
-				{
-					//RN: *always* serialize provided components of BlockValue (don't pass diff_param on),
-					// since these tend to be viewed as the constructor arguments for the value T.  It seems
-					// cleaner to treat the uniqueness of a BlockValue according to the generated value, and
-					// not the individual components.  This way <color red="0" green="1" blue="0"/> will not
-					// be exported as <color green="1"/>, since it was probably the intent of the user to 
-					// be specific about the RGB color values.  This also fixes an issue where we distinguish
-					// between rect.left not being provided and rect.left being explicitly set to 0 (same as default)
-
-					if (typed_param.mValueAge == VALUE_AUTHORITATIVE)
-					{
-						// if the value is authoritative but the parser doesn't accept the value type
-						// go ahead and make a copy, and splat the value out to its component params
-						// and serialize those params
-						derived_t copy(typed_param);
-						copy.updateBlockFromValue(true);
-						copy.block_t::serializeBlock(parser, name_stack, NULL);
-					}
-					else
-					{
-						block_t::serializeBlock(parser, name_stack, NULL);
-					}
-				}
-			}
-		}
-
-		bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
-		{
-			// first, inspect with actual type...
-			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
-			if (TypeValues<T>::getPossibleValues())
-			{
-				//...then inspect with possible string values...
-				parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues());
-			}
-			// then recursively inspect contents...
-			return block_t::inspectBlock(parser, name_stack, min_count, max_count);
-		}
-
-		bool validateBlock(bool emit_errors = true) const
-		{
-			if (mValueAge == VALUE_NEEDS_UPDATE)
-			{
-				if (block_t::validateBlock(emit_errors))
-				{
-					// clear stale keyword associated with old value
-					TypeValues<T>::clearValueName();
-					mValueAge = BLOCK_AUTHORITATIVE;
-					static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();
-					return true;
-				}
-				else
-				{
-					//block value incomplete, so not considered provided
-					// will attempt to revalidate on next call to isProvided()
-					return false;  
-				}
-			}
-			else
-			{
-				// we have a valid value in hand
-				return true;
-			}
-		}
-
- 		// propagate change status up to enclosing block
-		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
-		{ 
-			BaseBlock::paramChanged(changed_param, user_provided);
-			if (user_provided)
-			{
-				// a parameter changed, so our value is out of date
-				mValueAge = VALUE_NEEDS_UPDATE;
-			}
-		}
-			
-		void setValue(value_assignment_t val)
-		{
-			derived_t& typed_param = static_cast<derived_t&>(*this);
-			// set param version number to be up to date, so we ignore block contents
-			mValueAge = VALUE_AUTHORITATIVE;
-			mValue = val;
-			typed_param.clearValueName();
-			static_cast<derived_t*>(this)->updateBlockFromValue(false);
-		}
-
-		value_assignment_t getValue() const
-		{
-			validateBlock(true);
-			return mValue;
-		}
-
-		T& getValue() 
-		{
-			validateBlock(true);
-			return mValue;
-		}
-
-		operator value_assignment_t() const
-		{
-			return getValue();
-		}
-
-		value_assignment_t operator()() const
-		{
-			return getValue();
-		}
-
-	protected:
-
-		// use this from within updateValueFromBlock() to set the value without making it authoritative
-		void updateValue(value_assignment_t value)
-		{
-			mValue = value;
-		}
-
-		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
-		{
-			bool source_override = source_provided && (overwrite || !dst_provided);
-
-			const derived_t& src_typed_param = static_cast<const derived_t&>(source);
-
-			if (source_override && src_typed_param.mValueAge == VALUE_AUTHORITATIVE)
-			{
-				// copy value over
-				setValue(src_typed_param.getValue());
-				return true;
-			}
-			// merge individual parameters into destination
-			if (mValueAge == VALUE_AUTHORITATIVE)
-			{
-				static_cast<derived_t*>(this)->updateBlockFromValue(dst_provided);
-			}
-			return mergeBlock(block_data, source, overwrite);
-		}
-
-		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
-		{
-			return block_t::mergeBlock(block_data, source, overwrite);
-		}
-
-		mutable bool 		mValidated; // lazy validation flag
-
-	private:
-		mutable T			mValue;
-		mutable EValueAge	mValueAge;
-	};
-}
-
-
-#endif // LL_LLPARAM_H
diff --git a/indra/llxuixml/llregistry.h b/indra/llxuixml/llregistry.h
deleted file mode 100644
index 36ce6a97b7..0000000000
--- a/indra/llxuixml/llregistry.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/** 
- * @file llregistry.h
- * @brief template classes for registering name, value pairs in nested scopes, statically, etc.
- *
- * $LicenseInfo:firstyear=2001&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 LL_LLREGISTRY_H
-#define LL_LLREGISTRY_H
-
-#include <list>
-
-#include <boost/type_traits.hpp>
-#include "llsingleton.h"
-
-template <typename T>
-class LLRegistryDefaultComparator
-{
-	bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; }
-};
-
-template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
-class LLRegistry
-{
-public:
-	typedef LLRegistry<KEY, VALUE, COMPARATOR>											registry_t;
-	typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type	ref_const_key_t;
-	typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type	ref_const_value_t;
-	typedef typename boost::add_reference<VALUE>::type									ref_value_t;
-	typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type	ptr_const_value_t;
-	typedef typename boost::add_pointer<VALUE>::type									ptr_value_t;
-
-	class Registrar
-	{
-		friend class LLRegistry<KEY, VALUE, COMPARATOR>;
-	public:
-		typedef typename std::map<KEY, VALUE> registry_map_t;
-
-		bool add(ref_const_key_t key, ref_const_value_t value)
-		{
-			if (mMap.insert(std::make_pair(key, value)).second == false)
-			{
-				llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
-				return false;
-			}
-			return true;
-		}
-
-		void remove(ref_const_key_t key)
-		{
-			mMap.erase(key);
-		}
-
-		void replace(ref_const_key_t key, ref_const_value_t value)
-		{
-			mMap[key] = value;
-		}
-
-		typename registry_map_t::const_iterator beginItems() const
-		{
-			return mMap.begin();
-		}
-
-		typename registry_map_t::const_iterator endItems() const
-		{
-			return mMap.end();
-		}
-
-	protected:
-		ptr_value_t getValue(ref_const_key_t key)
-		{
-			typename registry_map_t::iterator found_it = mMap.find(key);
-			if (found_it != mMap.end())
-			{
-				return &(found_it->second);
-			}
-			return NULL;
-		}
-
-		ptr_const_value_t getValue(ref_const_key_t key) const
-		{
-			typename registry_map_t::const_iterator found_it = mMap.find(key);
-			if (found_it != mMap.end())
-			{
-				return &(found_it->second);
-			}
-			return NULL;
-		}
-
-		// if the registry is used to store pointers, and null values are valid entries
-		// then use this function to check the existence of an entry
-		bool exists(ref_const_key_t key) const
-		{
-			return mMap.find(key) != mMap.end();
-		}
-
-		bool empty() const
-		{
-			return mMap.empty();
-		}
-
-	protected:
-		// use currentRegistrar() or defaultRegistrar()
-		Registrar() {}
-		~Registrar() {}
-
-	private:
-		registry_map_t											mMap;
-	};
-	
-	typedef typename std::list<Registrar*> scope_list_t;
-	typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
-	typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
-	
-	LLRegistry() 
-	{}
-
-	~LLRegistry() {}
-
-	ptr_value_t getValue(ref_const_key_t key)
-	{
-		for(scope_list_iterator_t it = mActiveScopes.begin();
-			it != mActiveScopes.end();
-			++it)
-		{
-			ptr_value_t valuep = (*it)->getValue(key);
-			if (valuep != NULL) return valuep;
-		}
-		return mDefaultRegistrar.getValue(key);
-	}
-
-	ptr_const_value_t getValue(ref_const_key_t key) const
-	{
-		for(scope_list_const_iterator_t it = mActiveScopes.begin();
-			it != mActiveScopes.end();
-			++it)
-		{
-			ptr_value_t valuep = (*it)->getValue(key);
-			if (valuep != NULL) return valuep;
-		}
-		return mDefaultRegistrar.getValue(key);
-	}
-
-	bool exists(ref_const_key_t key) const
-	{
-		for(scope_list_const_iterator_t it = mActiveScopes.begin();
-			it != mActiveScopes.end();
-			++it)
-		{
-			if ((*it)->exists(key)) return true;
-		}
-
-		return mDefaultRegistrar.exists(key);
-	}
-
-	bool empty() const
-	{
-		for(scope_list_const_iterator_t it = mActiveScopes.begin();
-			it != mActiveScopes.end();
-			++it)
-		{
-			if (!(*it)->empty()) return false;
-		}
-
-		return mDefaultRegistrar.empty();
-	}
-
-
-	Registrar& defaultRegistrar()
-	{
-		return mDefaultRegistrar;
-	}
-
-	const Registrar& defaultRegistrar() const
-	{
-		return mDefaultRegistrar;
-	}
-
-
-	Registrar& currentRegistrar()
-	{
-		if (!mActiveScopes.empty()) 
-		{
-			return *mActiveScopes.front();
-		}
-
-		return mDefaultRegistrar;
-	}
-
-	const Registrar& currentRegistrar() const
-	{
-		if (!mActiveScopes.empty()) 
-		{
-			return *mActiveScopes.front();
-		}
-
-		return mDefaultRegistrar;
-	}
-
-
-protected:
-	void addScope(Registrar* scope)
-	{
-		// newer scopes go up front
-		mActiveScopes.insert(mActiveScopes.begin(), scope);
-	}
-
-	void removeScope(Registrar* scope)
-	{
-		// O(N) but should be near the beggining and N should be small and this is safer than storing iterators
-		scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
-		if (iter != mActiveScopes.end())
-		{
-			mActiveScopes.erase(iter);
-		}
-	}
-
-private:
-	scope_list_t	mActiveScopes;
-	Registrar		mDefaultRegistrar;
-};
-
-template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
-class LLRegistrySingleton
-	:	public LLRegistry<KEY, VALUE, COMPARATOR>,
-		public LLSingleton<DERIVED_TYPE>
-{
-	friend class LLSingleton<DERIVED_TYPE>;
-public:
-	typedef LLRegistry<KEY, VALUE, COMPARATOR>		registry_t;
-	typedef const KEY&								ref_const_key_t;
-	typedef const VALUE&							ref_const_value_t;
-	typedef VALUE*									ptr_value_t;
-	typedef const VALUE*							ptr_const_value_t;
-	typedef LLSingleton<DERIVED_TYPE>				singleton_t;
-
-	class ScopedRegistrar : public registry_t::Registrar
-	{
-	public:
-		ScopedRegistrar(bool push_scope = true) 
-		{
-			if (push_scope)
-			{
-				pushScope();
-			}
-		}
-
-		~ScopedRegistrar()
-		{
-			if (!singleton_t::destroyed())
-			{
-				popScope();
-			}
-		}
-
-		void pushScope()
-		{
-			singleton_t::instance().addScope(this);
-		}
-		
-		void popScope()
-		{
-			singleton_t::instance().removeScope(this);
-		}
-		
-		ptr_value_t getValueFromScope(ref_const_key_t key)
-		{
-			return getValue(key);
-		}
-
-		ptr_const_value_t getValueFromScope(ref_const_key_t key) const
-		{
-			return getValue(key);
-		}
-
-	private:
-		typename std::list<typename registry_t::Registrar*>::iterator	mListIt;
-	};
-
-	class StaticRegistrar : public registry_t::Registrar
-	{
-	public:
-		virtual ~StaticRegistrar() {}
-		StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
-		{
-			singleton_t::instance().mStaticScope->add(key, value);
-		}
-	};
-
-	// convenience functions
-	typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
-	static ref_registrar_t currentRegistrar()
-	{
-		return singleton_t::instance().registry_t::currentRegistrar();
-	}
-
-	static ref_registrar_t defaultRegistrar()
-	{
-		return singleton_t::instance().registry_t::defaultRegistrar();
-	}
-	
-	static ptr_value_t getValue(ref_const_key_t key)
-	{
-		return singleton_t::instance().registry_t::getValue(key);
-	}
-
-protected:
-	// DERIVED_TYPE needs to derive from LLRegistrySingleton
-	LLRegistrySingleton()
-		: mStaticScope(NULL)
-	{}
-
-	virtual void initSingleton()
-	{
-		mStaticScope = new ScopedRegistrar();
-	}
-
-	virtual ~LLRegistrySingleton() 
-	{
-		delete mStaticScope;
-	}
-
-private:
-	ScopedRegistrar*	mStaticScope;
-};
-
-// helper macro for doing static registration
-#define GLUED_TOKEN(x, y) x ## y
-#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y)
-#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE);
-
-#endif
diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp
deleted file mode 100644
index 5388069c24..0000000000
--- a/indra/llxuixml/lltrans.cpp
+++ /dev/null
@@ -1,295 +0,0 @@
-/**
- * @file lltrans.cpp
- * @brief LLTrans implementation
- *
- * $LicenseInfo:firstyear=2000&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 "lltrans.h"
-
-#include "llfasttimer.h"	// for call count statistics
-#include "llxuiparser.h"
-#include "llsd.h"
-#include "llxmlnode.h"
-
-#include <map>
-
-LLTrans::template_map_t LLTrans::sStringTemplates;
-LLStringUtil::format_map_t LLTrans::sDefaultArgs;
-
-struct StringDef : public LLInitParam::Block<StringDef>
-{
-	Mandatory<std::string> name;
-	Mandatory<std::string> value;
-
-	StringDef()
-	:	name("name"),
-		value("value")
-	{}
-};
-
-struct StringTable : public LLInitParam::Block<StringTable>
-{
-	Multiple<StringDef> strings;
-	StringTable()
-	:	strings("string")
-	{}
-};
-
-//static 
-bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& default_args)
-{
-	std::string xml_filename = "(strings file)";
-	if (!root->hasName("strings"))
-	{
-		llerrs << "Invalid root node name in " << xml_filename 
-			<< ": was " << root->getName() << ", expected \"strings\"" << llendl;
-	}
-
-	StringTable string_table;
-	LLXUIParser parser;
-	parser.readXUI(root, string_table, xml_filename);
-
-	if (!string_table.validateBlock())
-	{
-		llerrs << "Problem reading strings: " << xml_filename << llendl;
-		return false;
-	}
-	
-	sStringTemplates.clear();
-	sDefaultArgs.clear();
-	
-	for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings.begin();
-		it != string_table.strings.end();
-		++it)
-	{
-		LLTransTemplate xml_template(it->name, it->value);
-		sStringTemplates[xml_template.mName] = xml_template;
-		
-		std::set<std::string>::const_iterator iter = default_args.find(xml_template.mName);
-		if (iter != default_args.end())
-		{
-			std::string name = *iter;
-			if (name[0] != '[')
-				name = llformat("[%s]",name.c_str());
-			sDefaultArgs[name] = xml_template.mText;
-		}
-	}
-
-	return true;
-}
-
-
-//static
-bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root)
-{
-	std::string xml_filename = "(language strings file)";
-	if (!root->hasName("strings"))
-	{
-		llerrs << "Invalid root node name in " << xml_filename 
-		<< ": was " << root->getName() << ", expected \"strings\"" << llendl;
-	}
-	
-	StringTable string_table;
-	LLXUIParser parser;
-	parser.readXUI(root, string_table, xml_filename);
-	
-	if (!string_table.validateBlock())
-	{
-		llerrs << "Problem reading strings: " << xml_filename << llendl;
-		return false;
-	}
-		
-	for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings.begin();
-		it != string_table.strings.end();
-		++it)
-	{
-		// share the same map with parseStrings() so we can search the strings using the same getString() function.- angela
-		LLTransTemplate xml_template(it->name, it->value);
-		sStringTemplates[xml_template.mName] = xml_template;
-	}
-	
-	return true;
-}
-
-
-
-static LLFastTimer::DeclareTimer FTM_GET_TRANS("Translate string");
-
-//static 
-std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args)
-{
-	// Don't care about time as much as call count.  Make sure we're not
-	// calling LLTrans::getString() in an inner loop. JC
-	LLFastTimer timer(FTM_GET_TRANS);
-	
-	template_map_t::iterator iter = sStringTemplates.find(xml_desc);
-	if (iter != sStringTemplates.end())
-	{
-		std::string text = iter->second.mText;
-		LLStringUtil::format_map_t args = sDefaultArgs;
-		args.insert(msg_args.begin(), msg_args.end());
-		LLStringUtil::format(text, args);
-		
-		return text;
-	}
-	else
-	{
-		LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;
-		return "MissingString("+xml_desc+")";
-	}
-}
-
-//static
-std::string LLTrans::getString(const std::string &xml_desc, const LLSD& msg_args)
-{
-	// Don't care about time as much as call count.  Make sure we're not
-	// calling LLTrans::getString() in an inner loop. JC
-	LLFastTimer timer(FTM_GET_TRANS);
-
-	template_map_t::iterator iter = sStringTemplates.find(xml_desc);
-	if (iter != sStringTemplates.end())
-	{
-		std::string text = iter->second.mText;
-		LLStringUtil::format(text, msg_args);
-		return text;
-	}
-	else
-	{
-		LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;
-		return "MissingString("+xml_desc+")";
-	}
-}
-
-//static 
-bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args)
-{
-	LLFastTimer timer(FTM_GET_TRANS);
-	
-	template_map_t::iterator iter = sStringTemplates.find(xml_desc);
-	if (iter != sStringTemplates.end())
-	{
-		std::string text = iter->second.mText;
-		LLStringUtil::format_map_t args = sDefaultArgs;
-		args.insert(msg_args.begin(), msg_args.end());
-		LLStringUtil::format(text, args);
-		result = text;
-		return true;
-	}
-	else
-	{
-		LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;	
-		return false;
-	}
-}
-
-//static
-bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLSD& msg_args)
-{
-	LLFastTimer timer(FTM_GET_TRANS);
-
-	template_map_t::iterator iter = sStringTemplates.find(xml_desc);
-	if (iter != sStringTemplates.end())
-	{
-		std::string text = iter->second.mText;
-		LLStringUtil::format(text, msg_args);
-		result = text;
-		return true;
-	}
-	else
-	{
-		LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;	
-		return false;
-	}
-}
-
-//static
-std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count)
-{
-	// Compute which string identifier to use
-	const char* form = "";
-	if (language == "ru") // Russian
-	{
-		// From GNU ngettext()
-		// Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
-		if (count % 10 == 1
-			&& count % 100 != 11)
-		{
-			// singular, "1 item"
-			form = "A";
-		}
-		else if (count % 10 >= 2
-			&& count % 10 <= 4
-			&& (count % 100 < 10 || count % 100 >= 20) )
-		{
-			// special case "2 items", "23 items", but not "13 items"
-			form = "B";
-		}
-		else
-		{
-			// English-style plural, "5 items"
-			form = "C";
-		}
-	}
-	else if (language == "fr" || language == "pt") // French, Brazilian Portuguese
-	{
-		// French and Portuguese treat zero as a singular "0 item" not "0 items"
-		if (count == 0 || count == 1)
-		{
-			form = "A";
-		}
-		else
-		{
-			// English-style plural
-			form = "B";
-		}
-	}
-	else // default
-	{
-		// languages like English with 2 forms, singular and plural
-		if (count == 1)
-		{
-			// "1 item"
-			form = "A";
-		}
-		else
-		{
-			// "2 items", also use plural for "0 items"
-			form = "B";
-		}
-	}
-
-	// Translate that string
-	LLStringUtil::format_map_t args;
-	args["[COUNT]"] = llformat("%d", count);
-
-	// Look up "AgeYearsB" or "AgeWeeksC" including the "form"
-	std::string key = llformat("%s%s", xml_desc.c_str(), form);
-	return getString(key, args);
-}
-
-void LLTrans::setDefaultArg(const std::string& name, const std::string& value)
-{
-	sDefaultArgs[name] = value;
-}
diff --git a/indra/llxuixml/lltrans.h b/indra/llxuixml/lltrans.h
deleted file mode 100644
index 128b51d383..0000000000
--- a/indra/llxuixml/lltrans.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * @file lltrans.h
- * @brief LLTrans definition
- *
- * $LicenseInfo:firstyear=2000&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 LL_TRANS_H
-#define LL_TRANS_H
-
-#include <map>
-
-#include "llpointer.h"
-#include "llstring.h"
-
-class LLXMLNode;
-
-class LLSD;
-
-/**
- * @brief String template loaded from strings.xml
- */
-class LLTransTemplate
-{
-public:
-	LLTransTemplate(const std::string& name = LLStringUtil::null, const std::string& text = LLStringUtil::null) : mName(name), mText(text) {}
-
-	std::string mName;
-	std::string mText;
-};
-
-/**
- * @brief Localized strings class
- * This class is used to retrieve translations of strings used to build larger ones, as well as
- * strings with a general usage that don't belong to any specific floater. For example,
- * "Owner:", "Retrieving..." used in the place of a not yet known name, etc.
- */
-class LLTrans
-{
-public:
-	LLTrans();
-
-	/**
-	 * @brief Parses the xml root that holds the strings. Used once on startup
-// *FIXME	 * @param xml_filename Filename to parse
-	 * @param default_args Set of strings (expected to be in the file) to use as default replacement args, e.g. "SECOND_LIFE"
-	 * @returns true if the file was parsed successfully, true if something went wrong
-	 */
-	static bool parseStrings(LLPointer<LLXMLNode> & root, const std::set<std::string>& default_args);
-
-	static bool parseLanguageStrings(LLPointer<LLXMLNode> & root);
-
-	/**
-	 * @brief Returns a translated string
-	 * @param xml_desc String's description
-	 * @param args A list of substrings to replace in the string
-	 * @returns Translated string
-	 */
-	static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args);
-	static std::string getString(const std::string &xml_desc, const LLSD& args);
-	static bool findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& args);
-	static bool findString(std::string &result, const std::string &xml_desc, const LLSD& args);
-
-	// Returns translated string with [COUNT] replaced with a number, following
-	// special per-language logic for plural nouns.  For example, some languages
-	// may have different plurals for 0, 1, 2 and > 2.
-	// See "AgeWeeksA", "AgeWeeksB", etc. in strings.xml for examples.
-	static std::string getCountString(const std::string& language, const std::string& xml_desc, S32 count);
-
-	/**
-	 * @brief Returns a translated string
-	 * @param xml_desc String's description
-	 * @returns Translated string
-	 */
-	static std::string getString(const std::string &xml_desc)
-	{
-		LLStringUtil::format_map_t empty;
-		return getString(xml_desc, empty);
-	}
-
-	static bool findString(std::string &result, const std::string &xml_desc)
-	{
-		LLStringUtil::format_map_t empty;
-		return findString(result, xml_desc, empty);
-	}
-
-	static std::string getKeyboardString(const char* keystring)
-	{
-		std::string key_str(keystring);
-		std::string trans_str;
-		return findString(trans_str, key_str) ? trans_str : key_str; 
-	}
-
-	// get the default args
-	static const LLStringUtil::format_map_t& getDefaultArgs()
-	{
-		return sDefaultArgs;
-	}
-
-	static void setDefaultArg(const std::string& name, const std::string& value);
-
-	// insert default args into an arg list
-	static void getArgs(LLStringUtil::format_map_t& args)
-	{
-		args.insert(sDefaultArgs.begin(), sDefaultArgs.end());
-	}
-	
-private:
-	typedef std::map<std::string, LLTransTemplate > template_map_t;
-	static template_map_t sStringTemplates;
-	static LLStringUtil::format_map_t sDefaultArgs;
-};
-
-#endif
diff --git a/indra/llxuixml/lluicolor.cpp b/indra/llxuixml/lluicolor.cpp
deleted file mode 100644
index f9bb80f8c5..0000000000
--- a/indra/llxuixml/lluicolor.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/** 
- * @file lluicolor.cpp
- * @brief brief LLUIColor class implementation file
- *
- * $LicenseInfo:firstyear=2009&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 "lluicolor.h"
-
-LLUIColor::LLUIColor()
-	:mColorPtr(NULL)
-{
-}
-
-
-LLUIColor::LLUIColor(const LLColor4& color)
-:	mColor(color), 
-	mColorPtr(NULL)
-{
-}
-
-LLUIColor::LLUIColor(const LLUIColor* color)
-:	mColorPtr(color)
-{
-}
-
-void LLUIColor::set(const LLColor4& color)
-{
-	mColor = color;
-	mColorPtr = NULL;
-}
-
-void LLUIColor::set(const LLUIColor* color)
-{
-	mColorPtr = color;
-}
-
-const LLColor4& LLUIColor::get() const
-{
-	return (mColorPtr == NULL ? mColor : mColorPtr->get());
-}
-
-LLUIColor::operator const LLColor4& () const
-{
-	return get();
-}
-
-const LLColor4& LLUIColor::operator()() const
-{
-	return get();
-}
-
-bool LLUIColor::isReference() const
-{
-	return mColorPtr != NULL;
-}
-
-namespace LLInitParam
-{
-	// used to detect equivalence with default values on export
-	bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
-	{
-		// do not detect value equivalence, treat pointers to colors as distinct from color values
-		return (a.mColorPtr == NULL && b.mColorPtr == NULL ? a.mColor == b.mColor : a.mColorPtr == b.mColorPtr);
-	}
-}
diff --git a/indra/llxuixml/lluicolor.h b/indra/llxuixml/lluicolor.h
deleted file mode 100644
index 97ebea854a..0000000000
--- a/indra/llxuixml/lluicolor.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/** 
- * @file lluicolor.h
- * @brief brief LLUIColor class header file
- *
- * $LicenseInfo:firstyear=2009&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 LL_LLUICOLOR_H_
-#define LL_LLUICOLOR_H_
-
-#include "v4color.h"
-
-namespace LLInitParam
-{
-	template<typename T, bool>
-	struct ParamCompare;
-}
-
-class LLUIColor
-{
-public:
-	LLUIColor();
-	LLUIColor(const LLColor4& color);
-	LLUIColor(const LLUIColor* color);
-
-	void set(const LLColor4& color);
-	void set(const LLUIColor* color);
-
-	const LLColor4& get() const;
-
-	operator const LLColor4& () const;
-	const LLColor4& operator()() const;
-
-	bool isReference() const;
-
-private:
-	friend struct LLInitParam::ParamCompare<LLUIColor, false>;
-
-	const LLUIColor* mColorPtr;
-	LLColor4 mColor;
-};
-
-namespace LLInitParam
-{
-	template<>
-	struct ParamCompare<LLUIColor, false>
-	{
-		static bool equals(const LLUIColor& a, const LLUIColor& b);
-	};
-}
-
-#endif
diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp
deleted file mode 100644
index afc76024d1..0000000000
--- a/indra/llxuixml/llxuiparser.cpp
+++ /dev/null
@@ -1,1756 +0,0 @@
-/** 
- * @file llxuiparser.cpp
- * @brief Utility functions for handling XUI structures in XML
- *
- * $LicenseInfo:firstyear=2003&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 "llxuiparser.h"
-
-#include "llxmlnode.h"
-
-#ifdef LL_STANDALONE
-#include <expat.h>
-#else
-#include "expat/expat.h"
-#endif
-
-#include <fstream>
-#include <boost/tokenizer.hpp>
-//#include <boost/spirit/include/qi.hpp>
-#include <boost/spirit/include/classic_core.hpp>
-
-#include "lluicolor.h"
-
-using namespace BOOST_SPIRIT_CLASSIC_NS;
-
-const S32 MAX_STRING_ATTRIBUTE_SIZE = 40;
-
-static 	LLInitParam::Parser::parser_read_func_map_t sXSDReadFuncs;
-static 	LLInitParam::Parser::parser_write_func_map_t sXSDWriteFuncs;
-static 	LLInitParam::Parser::parser_inspect_func_map_t sXSDInspectFuncs;
-
-static 	LLInitParam::Parser::parser_read_func_map_t sSimpleXUIReadFuncs;
-static 	LLInitParam::Parser::parser_write_func_map_t sSimpleXUIWriteFuncs;
-static 	LLInitParam::Parser::parser_inspect_func_map_t sSimpleXUIInspectFuncs;
-
-const char* NO_VALUE_MARKER = "no_value";
-
-const S32 LINE_NUMBER_HERE = 0;
-
-struct MaxOccursValues : public LLInitParam::TypeValuesHelper<U32, MaxOccursValues>
-{
-	static void declareValues()
-	{
-		declare("unbounded", U32_MAX);
-	}
-};
-
-struct Occurs : public LLInitParam::Block<Occurs>
-{
-	Optional<U32>					minOccurs;
-	Optional<U32, MaxOccursValues>	maxOccurs;
-
-	Occurs()
-	:	minOccurs("minOccurs", 0),
-		maxOccurs("maxOccurs", U32_MAX)
-
-	{}
-};
-
-
-typedef enum
-{
-	USE_REQUIRED,
-	USE_OPTIONAL
-} EUse;
-
-namespace LLInitParam
-{
-	template<>
-	struct TypeValues<EUse> : public TypeValuesHelper<EUse>
-	{
-		static void declareValues()
-		{
-			declare("required", USE_REQUIRED);
-			declare("optional", USE_OPTIONAL);
-		}
-	};
-}
-
-struct Element;
-struct Group;
-struct Choice;
-struct Sequence;
-struct Any;
-
-struct Attribute : public LLInitParam::Block<Attribute>
-{
-	Mandatory<std::string>	name;
-	Mandatory<std::string>	type;
-	Mandatory<EUse>			use;
-	
-	Attribute()
-	:	name("name"),
-		type("type"),
-		use("use")
-	{}
-};
-
-struct Any : public LLInitParam::Block<Any, Occurs>
-{
-	Optional<std::string> _namespace;
-
-	Any()
-	:	_namespace("namespace")
-	{}
-};
-
-struct All : public LLInitParam::Block<All, Occurs>
-{
-	Multiple< Lazy<Element> > elements;
-
-	All()
-	:	elements("element")
-	{
-		maxOccurs = 1;
-	}
-};
-
-struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs>
-{
-	Alternative< Lazy<Element> >	element;
-	Alternative< Lazy<Group> >		group;
-	Alternative< Lazy<Choice> >		choice;
-	Alternative< Lazy<Sequence> >	sequence;
-	Alternative< Lazy<Any> >		any;
-
-	Choice()
-	:	element("element"),
-		group("group"),
-		choice("choice"),
-		sequence("sequence"),
-		any("any")
-	{}
-
-};
-
-struct Sequence : public LLInitParam::ChoiceBlock<Sequence, Occurs>
-{
-	Alternative< Lazy<Element> >	element;
-	Alternative< Lazy<Group> >		group;
-	Alternative< Lazy<Choice> >		choice;
-	Alternative< Lazy<Sequence> >	sequence;
-	Alternative< Lazy<Any> >		any;
-};
-
-struct GroupContents : public LLInitParam::ChoiceBlock<GroupContents, Occurs>
-{
-	Alternative<All>		all;
-	Alternative<Choice>		choice;
-	Alternative<Sequence>	sequence;
-
-	GroupContents()
-	:	all("all"),
-		choice("choice"),
-		sequence("sequence")
-	{}
-};
-
-struct Group : public LLInitParam::Block<Group, GroupContents>
-{
-	Optional<std::string>	name,
-							ref;
-
-	Group()
-	:	name("name"),
-		ref("ref")
-	{}
-};
-
-struct Restriction : public LLInitParam::Block<Restriction>
-{
-};
-
-struct Extension : public LLInitParam::Block<Extension>
-{
-};
-
-struct SimpleContent : public LLInitParam::ChoiceBlock<SimpleContent>
-{
-	Alternative<Restriction> restriction;
-	Alternative<Extension> extension;
-
-	SimpleContent()
-	:	restriction("restriction"),
-		extension("extension")
-	{}
-};
-
-struct SimpleType : public LLInitParam::Block<SimpleType>
-{
-	// TODO
-};
-
-struct ComplexContent : public LLInitParam::Block<ComplexContent, SimpleContent>
-{
-	Optional<bool> mixed;
-
-	ComplexContent()
-	:	mixed("mixed", true)
-	{}
-};
-
-struct ComplexTypeContents : public LLInitParam::ChoiceBlock<ComplexTypeContents>
-{
-	Alternative<SimpleContent>	simple_content;
-	Alternative<ComplexContent> complex_content;
-	Alternative<Group>			group;
-	Alternative<All>			all;
-	Alternative<Choice>			choice;
-	Alternative<Sequence>		sequence;
-
-	ComplexTypeContents()
-	:	simple_content("simpleContent"),
-		complex_content("complexContent"),
-		group("group"),
-		all("all"),
-		choice("choice"),
-		sequence("sequence")
-	{}
-};
-
-struct ComplexType : public LLInitParam::Block<ComplexType, ComplexTypeContents>
-{
-	Optional<std::string>			name;
-	Optional<bool>					mixed;
-
-	Multiple<Attribute>				attribute;
-	Multiple< Lazy<Element> >			elements;
-
-	ComplexType()
-	:	name("name"),
-		attribute("xs:attribute"),
-		elements("xs:element"),
-		mixed("mixed")
-	{
-	}
-};
-
-struct ElementContents : public LLInitParam::ChoiceBlock<ElementContents, Occurs>
-{
-	Alternative<SimpleType>		simpleType;
-	Alternative<ComplexType>	complexType;
-
-	ElementContents()
-	:	simpleType("simpleType"),
-		complexType("complexType")
-	{}
-};
-
-struct Element : public LLInitParam::Block<Element, ElementContents>
-{
-	Optional<std::string>	name,
-							ref,
-							type;
-
-	Element()
-	:	name("xs:name"),
-		ref("xs:ref"),
-		type("xs:type")
-	{}
-};
-
-struct Schema : public LLInitParam::Block<Schema>
-{
-private:
-	Mandatory<std::string>	targetNamespace,
-							xmlns,
-							xs;
-
-public:
-	Optional<std::string>	attributeFormDefault,
-							elementFormDefault;
-
-	Mandatory<Element>		root_element;
-	
-	void setNameSpace(const std::string& ns) {targetNamespace = ns; xmlns = ns;}
-
-	Schema(const std::string& ns = LLStringUtil::null)
-	:	attributeFormDefault("attributeFormDefault"),
-		elementFormDefault("elementFormDefault"),
-		xs("xmlns:xs"),
-		targetNamespace("targetNamespace"),
-		xmlns("xmlns"),
-		root_element("xs:element")
-	{
-		attributeFormDefault = "unqualified";
-		elementFormDefault = "qualified";
-		xs = "http://www.w3.org/2001/XMLSchema";
-		if (!ns.empty())
-		{
-			setNameSpace(ns);
-		};
-	}
-
-};
-
-//
-// LLXSDWriter
-//
-LLXSDWriter::LLXSDWriter()
-: Parser(sXSDReadFuncs, sXSDWriteFuncs, sXSDInspectFuncs)
-{
-	registerInspectFunc<bool>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:boolean", _1, _2, _3, _4));
-	registerInspectFunc<std::string>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
-	registerInspectFunc<U8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedByte", _1, _2, _3, _4));
-	registerInspectFunc<S8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedByte", _1, _2, _3, _4));
-	registerInspectFunc<U16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedShort", _1, _2, _3, _4));
-	registerInspectFunc<S16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedShort", _1, _2, _3, _4));
-	registerInspectFunc<U32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedInt", _1, _2, _3, _4));
-	registerInspectFunc<S32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:integer", _1, _2, _3, _4));
-	registerInspectFunc<F32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:float", _1, _2, _3, _4));
-	registerInspectFunc<F64>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:double", _1, _2, _3, _4));
-	registerInspectFunc<LLColor4>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
-	registerInspectFunc<LLUIColor>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
-	registerInspectFunc<LLUUID>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
-	registerInspectFunc<LLSD>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
-}
-
-void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace)
-{
-	Schema schema(xml_namespace);
-
-	schema.root_element.name = type_name;
-	Choice& choice = schema.root_element.complexType.choice;
-
-	choice.minOccurs = 0;
-	choice.maxOccurs = "unbounded";
-
-	mSchemaNode = node;
-	//node->setName("xs:schema");
-	//node->createChild("attributeFormDefault", true)->setStringValue("unqualified");
-	//node->createChild("elementFormDefault", true)->setStringValue("qualified");
-	//node->createChild("targetNamespace", true)->setStringValue(xml_namespace);
-	//node->createChild("xmlns:xs", true)->setStringValue("http://www.w3.org/2001/XMLSchema");
-	//node->createChild("xmlns", true)->setStringValue(xml_namespace);
-
-	//node = node->createChild("xs:complexType", false);
-	//node->createChild("name", true)->setStringValue(type_name);
-	//node->createChild("mixed", true)->setStringValue("true");
-
-	//mAttributeNode = node;
-	//mElementNode = node->createChild("xs:choice", false);
-	//mElementNode->createChild("minOccurs", true)->setStringValue("0");
-	//mElementNode->createChild("maxOccurs", true)->setStringValue("unbounded");
-	block.inspectBlock(*this);
-
-	// duplicate element choices
-	LLXMLNodeList children;
-	mElementNode->getChildren("xs:element", children, FALSE);
-	for (LLXMLNodeList::iterator child_it = children.begin(); child_it != children.end(); ++child_it)
-	{
-		LLXMLNodePtr child_copy = child_it->second->deepCopy();
-		std::string child_name;
-		child_copy->getAttributeString("name", child_name);
-		child_copy->setAttributeString("name", type_name + "." + child_name);
-		mElementNode->addChild(child_copy);
-	}
-
-	LLXMLNodePtr element_declaration_node = mSchemaNode->createChild("xs:element", false);
-	element_declaration_node->createChild("name", true)->setStringValue(type_name);
-	element_declaration_node->createChild("type", true)->setStringValue(type_name);
-}
-
-void LLXSDWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values)
-{
-	name_stack_t non_empty_names;
-	std::string attribute_name;
-	for (name_stack_t::const_iterator it = stack.begin();
-		it != stack.end();
-		++it)
-	{
-		const std::string& name = it->first;
-		if (!name.empty())
-		{
-			non_empty_names.push_back(*it);
-		}
-	}
-
-	for (name_stack_t::const_iterator it = non_empty_names.begin();
-		it != non_empty_names.end();
-		++it)
-	{
-		if (!attribute_name.empty())
-		{
-			attribute_name += ".";
-		}
-		attribute_name += it->first;
-	}
-
-	// only flag non-nested attributes as mandatory, nested attributes have variant syntax
-	// that can't be properly constrained in XSD
-	// e.g. <foo mandatory.value="bar"/> vs <foo><mandatory value="bar"/></foo>
-	bool attribute_mandatory = min_count == 1 && max_count == 1 && non_empty_names.size() == 1;
-
-	// don't bother supporting "Multiple" params as xml attributes
-	if (max_count <= 1)
-	{
-		// add compound attribute to root node
-		addAttributeToSchema(mAttributeNode, attribute_name, type, attribute_mandatory, possible_values);
-	}
-
-	// now generated nested elements for compound attributes
-	if (non_empty_names.size() > 1 && !attribute_mandatory)
-	{
-		std::string element_name;
-
-		// traverse all but last element, leaving that as an attribute name
-		name_stack_t::const_iterator end_it = non_empty_names.end();
-		end_it--;
-
-		for (name_stack_t::const_iterator it = non_empty_names.begin();
-			it != end_it;
-			++it)
-		{
-			if (it != non_empty_names.begin())
-			{
-				element_name += ".";
-			}
-			element_name += it->first;
-		}
-
-		std::string short_attribute_name = non_empty_names.back().first;
-
-		LLXMLNodePtr complex_type_node;
-
-		// find existing element node here, starting at tail of child list
-		if (mElementNode->mChildren.notNull())
-		{
-			for(LLXMLNodePtr element = mElementNode->mChildren->tail;
-				element.notNull(); 
-				element = element->mPrev)
-			{
-				std::string name;
-				if(element->getAttributeString("name", name) && name == element_name)
-				{
-					complex_type_node = element->mChildren->head;
-					break;
-				}
-			}
-		}
-		//create complex_type node
-		//
-		//<xs:element
-        //    maxOccurs="1"
-        //    minOccurs="0"
-        //    name="name">
-        //       <xs:complexType>
-        //       </xs:complexType>
-        //</xs:element>
-		if(complex_type_node.isNull())
-		{
-			complex_type_node = mElementNode->createChild("xs:element", false);
-
-			complex_type_node->createChild("minOccurs", true)->setIntValue(min_count);
-			complex_type_node->createChild("maxOccurs", true)->setIntValue(max_count);
-			complex_type_node->createChild("name",		true)->setStringValue(element_name);
-			complex_type_node = complex_type_node->createChild("xs:complexType", false);
-		}
-
-		addAttributeToSchema(complex_type_node, short_attribute_name, type, false, possible_values);
-	}
-}
-
-void LLXSDWriter::addAttributeToSchema(LLXMLNodePtr type_declaration_node, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector<std::string>* possible_values)
-{
-	if (!attribute_name.empty())
-	{
-		LLXMLNodePtr new_enum_type_node;
-		if (possible_values != NULL)
-		{
-			// custom attribute type, for example
-			//<xs:simpleType>
-			 // <xs:restriction
-			 //    base="xs:string">
-			 //     <xs:enumeration
-			 //      value="a" />
-			 //     <xs:enumeration
-			 //      value="b" />
-			 //   </xs:restriction>
-			 // </xs:simpleType>
-			new_enum_type_node = new LLXMLNode("xs:simpleType", false);
-
-			LLXMLNodePtr restriction_node = new_enum_type_node->createChild("xs:restriction", false);
-			restriction_node->createChild("base", true)->setStringValue("xs:string");
-
-			for (std::vector<std::string>::const_iterator it = possible_values->begin();
-				it != possible_values->end();
-				++it)
-			{
-				LLXMLNodePtr enum_node = restriction_node->createChild("xs:enumeration", false);
-				enum_node->createChild("value", true)->setStringValue(*it);
-			}
-		}
-
-		string_set_t& attributes_written = mAttributesWritten[type_declaration_node];
-
-		string_set_t::iterator found_it = attributes_written.lower_bound(attribute_name);
-
-		// attribute not yet declared
-		if (found_it == attributes_written.end() || attributes_written.key_comp()(attribute_name, *found_it))
-		{
-			attributes_written.insert(found_it, attribute_name);
-
-			LLXMLNodePtr attribute_node = type_declaration_node->createChild("xs:attribute", false);
-
-			// attribute name
-			attribute_node->createChild("name", true)->setStringValue(attribute_name);
-
-			if (new_enum_type_node.notNull())
-			{
-				attribute_node->addChild(new_enum_type_node);
-			}
-			else
-			{
-				// simple attribute type
-				attribute_node->createChild("type", true)->setStringValue(type);
-			}
-
-			// required or optional
-			attribute_node->createChild("use", true)->setStringValue(mandatory ? "required" : "optional");
-		}
-		 // attribute exists...handle collision of same name attributes with potentially different types
-		else
-		{
-			LLXMLNodePtr attribute_declaration;
-			if (type_declaration_node.notNull())
-			{
-				for(LLXMLNodePtr node = type_declaration_node->mChildren->tail; 
-					node.notNull(); 
-					node = node->mPrev)
-				{
-					std::string name;
-					if (node->getAttributeString("name", name) && name == attribute_name)
-					{
-						attribute_declaration = node;
-						break;
-					}
-				}
-			}
-
-			bool new_type_is_enum = new_enum_type_node.notNull();
-			bool existing_type_is_enum = !attribute_declaration->hasAttribute("type");
-
-			// either type is enum, revert to string in collision
-			// don't bother to check for enum equivalence
-			if (new_type_is_enum || existing_type_is_enum)
-			{
-				if (attribute_declaration->hasAttribute("type"))
-				{
-					attribute_declaration->setAttributeString("type", "xs:string");
-				}
-				else
-				{
-					attribute_declaration->createChild("type", true)->setStringValue("xs:string");
-				}
-				attribute_declaration->deleteChildren("xs:simpleType");
-			}
-			else 
-			{
-				// check for collision of different standard types
-				std::string existing_type;
-				attribute_declaration->getAttributeString("type", existing_type);
-				// if current type is not the same as the new type, revert to strnig
-				if (existing_type != type)
-				{
-					// ...than use most general type, string
-					attribute_declaration->setAttributeString("type", "string");
-				}
-			}
-		}
-	}
-}
-
-//
-// LLXUIXSDWriter
-//
-void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& path, const LLInitParam::BaseBlock& block)
-{
-	std::string file_name(path);
-	file_name += type_name + ".xsd";
-	LLXMLNodePtr root_nodep = new LLXMLNode();
-
-	LLXSDWriter::writeXSD(type_name, root_nodep, block, "http://www.lindenlab.com/xui");
-
-	// add includes for all possible children
-	const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
-	const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);
-
-	// add choices for valid children
-	if (widget_registryp)
-	{
-		// add include declarations for all valid children
-		for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
-		     it != widget_registryp->currentRegistrar().endItems();
-		     ++it)
-		{
-			std::string widget_name = it->first;
-			if (widget_name == type_name)
-			{
-				continue;
-			}
-			LLXMLNodePtr nodep = new LLXMLNode("xs:include", false);
-			nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd");
-			
-			// add to front of schema
-			mSchemaNode->addChild(nodep, mSchemaNode);
-		}
-
-		for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
-			it != widget_registryp->currentRegistrar().endItems();
-			++it)
-		{
-			std::string widget_name = it->first;
-			//<xs:element name="widget_name" type="widget_name">
-			LLXMLNodePtr widget_node = mElementNode->createChild("xs:element", false);
-			widget_node->createChild("name", true)->setStringValue(widget_name);
-			widget_node->createChild("type", true)->setStringValue(widget_name);
-		}
-	}
-
-	LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), "w");
-	LLXMLNode::writeHeaderToFile(xsd_file);
-	root_nodep->writeToFile(xsd_file);
-	fclose(xsd_file);
-}
-
-static 	LLInitParam::Parser::parser_read_func_map_t sXUIReadFuncs;
-static 	LLInitParam::Parser::parser_write_func_map_t sXUIWriteFuncs;
-static 	LLInitParam::Parser::parser_inspect_func_map_t sXUIInspectFuncs;
-
-//
-// LLXUIParser
-//
-LLXUIParser::LLXUIParser()
-:	Parser(sXUIReadFuncs, sXUIWriteFuncs, sXUIInspectFuncs),
-	mCurReadDepth(0)
-{
-	if (sXUIReadFuncs.empty())
-	{
-		registerParserFuncs<LLInitParam::Flag>(readFlag, writeFlag);
-		registerParserFuncs<bool>(readBoolValue, writeBoolValue);
-		registerParserFuncs<std::string>(readStringValue, writeStringValue);
-		registerParserFuncs<U8>(readU8Value, writeU8Value);
-		registerParserFuncs<S8>(readS8Value, writeS8Value);
-		registerParserFuncs<U16>(readU16Value, writeU16Value);
-		registerParserFuncs<S16>(readS16Value, writeS16Value);
-		registerParserFuncs<U32>(readU32Value, writeU32Value);
-		registerParserFuncs<S32>(readS32Value, writeS32Value);
-		registerParserFuncs<F32>(readF32Value, writeF32Value);
-		registerParserFuncs<F64>(readF64Value, writeF64Value);
-		registerParserFuncs<LLColor4>(readColor4Value, writeColor4Value);
-		registerParserFuncs<LLUIColor>(readUIColorValue, writeUIColorValue);
-		registerParserFuncs<LLUUID>(readUUIDValue, writeUUIDValue);
-		registerParserFuncs<LLSD>(readSDValue, writeSDValue);
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing");
-const LLXMLNodePtr DUMMY_NODE = new LLXMLNode();
-
-void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename, bool silent)
-{
-	LLFastTimer timer(FTM_PARSE_XUI);
-	mNameStack.clear();
-	mRootNodeName = node->getName()->mString;
-	mCurFileName = filename;
-	mCurReadDepth = 0;
-	setParseSilently(silent);
-
-	if (node.isNull())
-	{
-		parserWarning("Invalid node");
-	}
-	else
-	{
-		readXUIImpl(node, block);
-	}
-}
-
-bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
-{
-	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-	boost::char_separator<char> sep(".");
-
-	bool values_parsed = false;
-	bool silent = mCurReadDepth > 0;
-
-	if (nodep->getFirstChild().isNull() 
-		&& nodep->mAttributes.empty() 
-		&& nodep->getSanitizedValue().empty())
-	{
-		// empty node, just parse as flag
-		mCurReadNode = DUMMY_NODE;
-		return block.submitValue(mNameStack, *this, silent);
-	}
-
-	// submit attributes for current node
-	values_parsed |= readAttributes(nodep, block);
-
-	// treat text contents of xml node as "value" parameter
-	std::string text_contents = nodep->getSanitizedValue();
-	if (!text_contents.empty())
-	{
-		mCurReadNode = nodep;
-		mNameStack.push_back(std::make_pair(std::string("value"), true));
-		// child nodes are not necessarily valid parameters (could be a child widget)
-		// so don't complain once we've recursed
-		if (!block.submitValue(mNameStack, *this, true))
-		{
-			mNameStack.pop_back();
-			block.submitValue(mNameStack, *this, silent);
-		}
-		else
-		{
-			mNameStack.pop_back();
-		}
-	}
-
-	// then traverse children
-	// child node must start with last name of parent node (our "scope")
-	// for example: "<button><button.param nested_param1="foo"><param.nested_param2 nested_param3="bar"/></button.param></button>"
-	// which equates to the following nesting:
-	// button
-	//     param
-	//         nested_param1
-	//         nested_param2
-	//             nested_param3	
-	mCurReadDepth++;
-	for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();)
-	{
-		std::string child_name(childp->getName()->mString);
-		S32 num_tokens_pushed = 0;
-
-		// for non "dotted" child nodes	check to see if child node maps to another widget type
-		// and if not, treat as a child element of the current node
-		// e.g. <button><rect left="10"/></button> will interpret <rect> as "button.rect"
-		// since there is no widget named "rect"
-		if (child_name.find(".") == std::string::npos) 
-		{
-			mNameStack.push_back(std::make_pair(child_name, true));
-			num_tokens_pushed++;
-		}
-		else
-		{
-			// parse out "dotted" name into individual tokens
-			tokenizer name_tokens(child_name, sep);
-
-			tokenizer::iterator name_token_it = name_tokens.begin();
-			if(name_token_it == name_tokens.end()) 
-			{
-				childp = childp->getNextSibling();
-				continue;
-			}
-
-			// check for proper nesting
-			if (mNameStack.empty())
-			{
-				if (*name_token_it != mRootNodeName)
-				{
-					childp = childp->getNextSibling();
-					continue;
-				}
-			}
-			else if(mNameStack.back().first != *name_token_it)
-			{
-				childp = childp->getNextSibling();
-				continue;
-			}
-
-			// now ignore first token
-			++name_token_it; 
-
-			// copy remaining tokens on to our running token list
-			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
-			{
-				mNameStack.push_back(std::make_pair(*token_to_push, true));
-				num_tokens_pushed++;
-			}
-		}
-
-		// recurse and visit children XML nodes
-		if(readXUIImpl(childp, block))
-		{
-			// child node successfully parsed, remove from DOM
-
-			values_parsed = true;
-			LLXMLNodePtr node_to_remove = childp;
-			childp = childp->getNextSibling();
-
-			nodep->deleteChild(node_to_remove);
-		}
-		else
-		{
-			childp = childp->getNextSibling();
-		}
-
-		while(num_tokens_pushed-- > 0)
-		{
-			mNameStack.pop_back();
-		}
-	}
-	mCurReadDepth--;
-	return values_parsed;
-}
-
-bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
-{
-	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-	boost::char_separator<char> sep(".");
-
-	bool any_parsed = false;
-	bool silent = mCurReadDepth > 0;
-
-	for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin(); 
-		attribute_it != nodep->mAttributes.end(); 
-		++attribute_it)
-	{
-		S32 num_tokens_pushed = 0;
-		std::string attribute_name(attribute_it->first->mString);
-		mCurReadNode = attribute_it->second;
-
-		tokenizer name_tokens(attribute_name, sep);
-		// copy remaining tokens on to our running token list
-		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
-		{
-			mNameStack.push_back(std::make_pair(*token_to_push, true));
-			num_tokens_pushed++;
-		}
-
-		// child nodes are not necessarily valid attributes, so don't complain once we've recursed
-		any_parsed |= block.submitValue(mNameStack, *this, silent);
-		
-		while(num_tokens_pushed-- > 0)
-		{
-			mNameStack.pop_back();
-		}
-	}
-
-	return any_parsed;
-}
-
-void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block)
-{
-	mWriteRootNode = node;
-	name_stack_t name_stack = Parser::name_stack_t();
-	block.serializeBlock(*this, name_stack, diff_block);
-	mOutNodes.clear();
-}
-
-// go from a stack of names to a specific XML node
-LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack)
-{
-	LLXMLNodePtr out_node = mWriteRootNode;
-
-	name_stack_t::iterator next_it = stack.begin();
-	for (name_stack_t::iterator it = stack.begin();
-		it != stack.end();
-		it = next_it)
-	{
-		++next_it;
-		if (it->first.empty())
-		{
-			it->second = false;
-			continue;
-		}
-
-		out_nodes_t::iterator found_it = mOutNodes.find(it->first);
-
-		// node with this name not yet written
-		if (found_it == mOutNodes.end() || it->second)
-		{
-			// make an attribute if we are the last element on the name stack
-			bool is_attribute = next_it == stack.end();
-			LLXMLNodePtr new_node = new LLXMLNode(it->first.c_str(), is_attribute);
-			out_node->addChild(new_node);
-			mOutNodes[it->first] = new_node;
-			out_node = new_node;
-			it->second = false;
-		}
-		else
-		{
-			out_node = found_it->second;
-		}
-	}
-
-	return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node);
-}
-
-bool LLXUIParser::readFlag(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	return self.mCurReadNode == DUMMY_NODE;
-}
-
-bool LLXUIParser::writeFlag(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	// just create node
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	return node.notNull();
-}
-
-bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr)
-{
-	S32 value;
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	bool success = self.mCurReadNode->getBoolValue(1, &value);
-	*((bool*)val_ptr) = (value != FALSE);
-	return success;
-}
-
-bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setBoolValue(*((bool*)val_ptr));
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	*((std::string*)val_ptr) = self.mCurReadNode->getSanitizedValue();
-	return true;
-}
-
-bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		const std::string* string_val = reinterpret_cast<const std::string*>(val_ptr);
-		if (string_val->find('\n') != std::string::npos 
-			|| string_val->size() > MAX_STRING_ATTRIBUTE_SIZE)
-		{
-			// don't write strings with newlines into attributes
-			std::string attribute_name = node->getName()->mString;
-			LLXMLNodePtr parent_node = node->mParent;
-			parent_node->deleteChild(node);
-			// write results in text contents of node
-			if (attribute_name == "value")
-			{
-				// "value" is implicit, just write to parent
-				node = parent_node;
-			}
-			else
-			{
-				// create a child that is not an attribute, but with same name
-				node = parent_node->createChild(attribute_name.c_str(), false);
-			}
-		}
-		node->setStringValue(*string_val);
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	return self.mCurReadNode->getByteValue(1, (U8*)val_ptr);
-}
-
-bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setUnsignedValue(*((U8*)val_ptr));
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	S32 value;
-	if(self.mCurReadNode->getIntValue(1, &value))
-	{
-		*((S8*)val_ptr) = value;
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setIntValue(*((S8*)val_ptr));
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	U32 value;
-	if(self.mCurReadNode->getUnsignedValue(1, &value))
-	{
-		*((U16*)val_ptr) = value;
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setUnsignedValue(*((U16*)val_ptr));
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	S32 value;
-	if(self.mCurReadNode->getIntValue(1, &value))
-	{
-		*((S16*)val_ptr) = value;
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setIntValue(*((S16*)val_ptr));
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
-}
-
-bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setUnsignedValue(*((U32*)val_ptr));
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	return self.mCurReadNode->getIntValue(1, (S32*)val_ptr);
-}
-
-bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setIntValue(*((S32*)val_ptr));
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr);
-}
-
-bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setFloatValue(*((F32*)val_ptr));
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
-}
-
-bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setDoubleValue(*((F64*)val_ptr));
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLColor4* colorp = (LLColor4*)val_ptr;
-	if(self.mCurReadNode->getFloatValue(4, colorp->mV) >= 3)
-	{
-		return true;
-	}
-
-	return false;
-}
-
-bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		LLColor4 color = *((LLColor4*)val_ptr);
-		node->setFloatValue(4, color.mV);
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLUIColor* param = (LLUIColor*)val_ptr;
-	LLColor4 color;
-	bool success =  self.mCurReadNode->getFloatValue(4, color.mV) >= 3;
-	if (success)
-	{
-		param->set(color);
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		LLUIColor color = *((LLUIColor*)val_ptr);
-		//RN: don't write out the color that is represented by a function
-		// rely on param block exporting to get the reference to the color settings
-		if (color.isReference()) return false;
-		node->setFloatValue(4, color.get().mV);
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLUUID temp_id;
-	// LLUUID::set is destructive, so use temporary value
-	if (temp_id.set(self.mCurReadNode->getSanitizedValue()))
-	{
-		*(LLUUID*)(val_ptr) = temp_id;
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		node->setStringValue(((LLUUID*)val_ptr)->asString());
-		return true;
-	}
-	return false;
-}
-
-bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-	*((LLSD*)val_ptr) = LLSD(self.mCurReadNode->getSanitizedValue());
-	return true;
-}
-
-bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
-{
-	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
-
-	LLXMLNodePtr node = self.getNode(stack);
-	if (node.notNull())
-	{
-		std::string string_val = ((LLSD*)val_ptr)->asString();
-		if (string_val.find('\n') != std::string::npos || string_val.size() > MAX_STRING_ATTRIBUTE_SIZE)
-		{
-			// don't write strings with newlines into attributes
-			std::string attribute_name = node->getName()->mString;
-			LLXMLNodePtr parent_node = node->mParent;
-			parent_node->deleteChild(node);
-			// write results in text contents of node
-			if (attribute_name == "value")
-			{
-				// "value" is implicit, just write to parent
-				node = parent_node;
-			}
-			else
-			{
-				node = parent_node->createChild(attribute_name.c_str(), false);
-			}
-		}
-
-		node->setStringValue(string_val);
-		return true;
-	}
-	return false;
-}
-
-/*virtual*/ std::string LLXUIParser::getCurrentElementName()
-{
-	std::string full_name;
-	for (name_stack_t::iterator it = mNameStack.begin();	
-		it != mNameStack.end();
-		++it)
-	{
-		full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
-	}
-
-	return full_name;
-}
-
-void LLXUIParser::parserWarning(const std::string& message)
-{
-#ifdef LL_WINDOWS
-	// use Visual Studo friendly formatting of output message for easy access to originating xml
-	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
-	utf16str += '\n';
-	OutputDebugString(utf16str.c_str());
-#else
-	Parser::parserWarning(message);
-#endif
-}
-
-void LLXUIParser::parserError(const std::string& message)
-{
-#ifdef LL_WINDOWS
-	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
-	utf16str += '\n';
-	OutputDebugString(utf16str.c_str());
-#else
-	Parser::parserError(message);
-#endif
-}
-
-
-//
-// LLSimpleXUIParser
-//
-
-struct ScopedFile
-{
-	ScopedFile( const std::string& filename, const char* accessmode )
-	{
-		mFile = LLFile::fopen(filename, accessmode);
-	}
-
-	~ScopedFile()
-	{
-		fclose(mFile);
-		mFile = NULL;
-	}
-
-	S32 getRemainingBytes()
-	{
-		if (!isOpen()) return 0;
-
-		S32 cur_pos = ftell(mFile);
-		fseek(mFile, 0L, SEEK_END);
-		S32 file_size = ftell(mFile);
-		fseek(mFile, cur_pos, SEEK_SET);
-		return file_size - cur_pos;
-	}
-
-	bool isOpen() { return mFile != NULL; }
-
-	LLFILE* mFile;
-};
-LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb)
-:	Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs),
-	mCurReadDepth(0),
-	mElementCB(element_cb)
-{
-	if (sSimpleXUIReadFuncs.empty())
-	{
-		registerParserFuncs<LLInitParam::Flag>(readFlag);
-		registerParserFuncs<bool>(readBoolValue);
-		registerParserFuncs<std::string>(readStringValue);
-		registerParserFuncs<U8>(readU8Value);
-		registerParserFuncs<S8>(readS8Value);
-		registerParserFuncs<U16>(readU16Value);
-		registerParserFuncs<S16>(readS16Value);
-		registerParserFuncs<U32>(readU32Value);
-		registerParserFuncs<S32>(readS32Value);
-		registerParserFuncs<F32>(readF32Value);
-		registerParserFuncs<F64>(readF64Value);
-		registerParserFuncs<LLColor4>(readColor4Value);
-		registerParserFuncs<LLUIColor>(readUIColorValue);
-		registerParserFuncs<LLUUID>(readUUIDValue);
-		registerParserFuncs<LLSD>(readSDValue);
-	}
-}
-
-LLSimpleXUIParser::~LLSimpleXUIParser()
-{
-}
-
-
-bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent)
-{
-	LLFastTimer timer(FTM_PARSE_XUI);
-
-	mParser = XML_ParserCreate(NULL);
-	XML_SetUserData(mParser, this);
-	XML_SetElementHandler(			mParser,	startElementHandler, endElementHandler);
-	XML_SetCharacterDataHandler(	mParser,	characterDataHandler);
-
-	mOutputStack.push_back(std::make_pair(&block, 0));
-	mNameStack.clear();
-	mCurFileName = filename;
-	mCurReadDepth = 0;
-	setParseSilently(silent);
-
-	ScopedFile file(filename, "rb");
-	if( !file.isOpen() )
-	{
-		LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL;
-		XML_ParserFree( mParser );
-		return false;
-	}
-
-	S32 bytes_read = 0;
-	
-	S32 buffer_size = file.getRemainingBytes();
-	void* buffer = XML_GetBuffer(mParser, buffer_size);
-	if( !buffer ) 
-	{
-		LL_WARNS("ReadXUI") << "Unable to allocate XML buffer while reading file " << filename << LL_ENDL;
-		XML_ParserFree( mParser );
-		return false;
-	}
-
-	bytes_read = (S32)fread(buffer, 1, buffer_size, file.mFile);
-	if( bytes_read <= 0 )
-	{
-		LL_WARNS("ReadXUI") << "Error while reading file  " << filename << LL_ENDL;
-		XML_ParserFree( mParser );
-		return false;
-	}
-	
-	mEmptyLeafNode.push_back(false);
-
-	if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) )
-	{
-		LL_WARNS("ReadXUI") << "Error while parsing file  " << filename << LL_ENDL;
-		XML_ParserFree( mParser );
-		return false;
-	}
-
-	mEmptyLeafNode.pop_back();
-
-	XML_ParserFree( mParser );
-	return true;
-}
-
-void LLSimpleXUIParser::startElementHandler(void *userData, const char *name, const char **atts)
-{
-	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
-	self->startElement(name, atts);
-}
-
-void LLSimpleXUIParser::endElementHandler(void *userData, const char *name)
-{
-	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
-	self->endElement(name);
-}
-
-void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int len)
-{
-	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
-	self->characterData(s, len);
-}
-
-void LLSimpleXUIParser::characterData(const char *s, int len)
-{
-	mTextContents += std::string(s, len);
-}
-
-void LLSimpleXUIParser::startElement(const char *name, const char **atts)
-{
-	processText();
-
-	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-	boost::char_separator<char> sep(".");
-
-	if (mElementCB) 
-	{
-		LLInitParam::BaseBlock* blockp = mElementCB(*this, name);
-		if (blockp)
-		{
-			mOutputStack.push_back(std::make_pair(blockp, 0));
-		}
-	}
-
-	mOutputStack.back().second++;
-	S32 num_tokens_pushed = 0;
-	std::string child_name(name);
-
-	if (mOutputStack.back().second == 1)
-	{	// root node for this block
-		mScope.push_back(child_name);
-	}
-	else
-	{	// compound attribute
-		if (child_name.find(".") == std::string::npos) 
-		{
-			mNameStack.push_back(std::make_pair(child_name, true));
-			num_tokens_pushed++;
-			mScope.push_back(child_name);
-		}
-		else
-		{
-			// parse out "dotted" name into individual tokens
-			tokenizer name_tokens(child_name, sep);
-
-			tokenizer::iterator name_token_it = name_tokens.begin();
-			if(name_token_it == name_tokens.end()) 
-			{
-				return;
-			}
-
-			// check for proper nesting
-			if(!mScope.empty() && *name_token_it != mScope.back())
-			{
-				return;
-			}
-
-			// now ignore first token
-			++name_token_it; 
-
-			// copy remaining tokens on to our running token list
-			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
-			{
-				mNameStack.push_back(std::make_pair(*token_to_push, true));
-				num_tokens_pushed++;
-			}
-			mScope.push_back(mNameStack.back().first);
-		}
-	}
-
-	// parent node is not empty
-	mEmptyLeafNode.back() = false;
-	// we are empty if we have no attributes
-	mEmptyLeafNode.push_back(atts[0] == NULL);
-
-	mTokenSizeStack.push_back(num_tokens_pushed);
-	readAttributes(atts);
-
-}
-
-void LLSimpleXUIParser::endElement(const char *name)
-{
-	bool has_text = processText();
-
-	// no text, attributes, or children
-	if (!has_text && mEmptyLeafNode.back())
-	{
-		// submit this as a valueless name (even though there might be text contents we haven't seen yet)
-		mCurAttributeValueBegin = NO_VALUE_MARKER;
-		mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
-	}
-
-	if (--mOutputStack.back().second == 0)
-	{
-		if (mOutputStack.empty())
-		{
-			LL_ERRS("ReadXUI") << "Parameter block output stack popped while empty." << LL_ENDL;
-		}
-		mOutputStack.pop_back();
-	}
-
-	S32 num_tokens_to_pop = mTokenSizeStack.back();
-	mTokenSizeStack.pop_back();
-	while(num_tokens_to_pop-- > 0)
-	{
-		mNameStack.pop_back();
-	}
-	mScope.pop_back();
-	mEmptyLeafNode.pop_back();
-}
-
-bool LLSimpleXUIParser::readAttributes(const char **atts)
-{
-	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-	boost::char_separator<char> sep(".");
-
-	bool any_parsed = false;
-	for(S32 i = 0; atts[i] && atts[i+1]; i += 2 )
-	{
-		std::string attribute_name(atts[i]);
-		mCurAttributeValueBegin = atts[i+1];
-		
-		S32 num_tokens_pushed = 0;
-		tokenizer name_tokens(attribute_name, sep);
-		// copy remaining tokens on to our running token list
-		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
-		{
-			mNameStack.push_back(std::make_pair(*token_to_push, true));
-			num_tokens_pushed++;
-		}
-
-		// child nodes are not necessarily valid attributes, so don't complain once we've recursed
-		any_parsed |= mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
-		
-		while(num_tokens_pushed-- > 0)
-		{
-			mNameStack.pop_back();
-		}
-	}
-	return any_parsed;
-}
-
-bool LLSimpleXUIParser::processText()
-{
-	if (!mTextContents.empty())
-	{
-		LLStringUtil::trim(mTextContents);
-		if (!mTextContents.empty())
-		{
-			mNameStack.push_back(std::make_pair(std::string("value"), true));
-			mCurAttributeValueBegin = mTextContents.c_str();
-			mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
-			mNameStack.pop_back();
-		}
-		mTextContents.clear();
-		return true;
-	}
-	return false;
-}
-
-/*virtual*/ std::string LLSimpleXUIParser::getCurrentElementName()
-{
-	std::string full_name;
-	for (name_stack_t::iterator it = mNameStack.begin();	
-		it != mNameStack.end();
-		++it)
-	{
-		full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
-	}
-
-	return full_name;
-}
-
-void LLSimpleXUIParser::parserWarning(const std::string& message)
-{
-#ifdef LL_WINDOWS
-	// use Visual Studo friendly formatting of output message for easy access to originating xml
-	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str());
-	utf16str += '\n';
-	OutputDebugString(utf16str.c_str());
-#else
-	Parser::parserWarning(message);
-#endif
-}
-
-void LLSimpleXUIParser::parserError(const std::string& message)
-{
-#ifdef LL_WINDOWS
-	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str());
-	utf16str += '\n';
-	OutputDebugString(utf16str.c_str());
-#else
-	Parser::parserError(message);
-#endif
-}
-
-bool LLSimpleXUIParser::readFlag(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	return self.mCurAttributeValueBegin == NO_VALUE_MARKER;
-}
-
-bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	if (!strcmp(self.mCurAttributeValueBegin, "true")) 
-	{
-		*((bool*)val_ptr) = true;
-		return true;
-	}
-	else if (!strcmp(self.mCurAttributeValueBegin, "false"))
-	{
-		*((bool*)val_ptr) = false;
-		return true;
-	}
-
-	return false;
-}
-
-bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	*((std::string*)val_ptr) = self.mCurAttributeValueBegin;
-	return true;
-}
-
-bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full;
-}
-
-bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full;
-}
-
-bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full;
-}
-
-bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full;
-}
-
-bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full;
-}
-
-bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full;
-}
-
-bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full;
-}
-
-bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full;
-}
-	
-bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	LLColor4 value;
-
-	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
-	{
-		*(LLColor4*)(val_ptr) = value;
-		return true;
-	}
-	return false;
-}
-
-bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	LLColor4 value;
-	LLUIColor* colorp = (LLUIColor*)val_ptr;
-
-	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
-	{
-		colorp->set(value);
-		return true;
-	}
-	return false;
-}
-
-bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	LLUUID temp_id;
-	// LLUUID::set is destructive, so use temporary value
-	if (temp_id.set(std::string(self.mCurAttributeValueBegin)))
-	{
-		*(LLUUID*)(val_ptr) = temp_id;
-		return true;
-	}
-	return false;
-}
-
-bool LLSimpleXUIParser::readSDValue(Parser& parser, void* val_ptr)
-{
-	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
-	*((LLSD*)val_ptr) = LLSD(self.mCurAttributeValueBegin);
-	return true;
-}
diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h
deleted file mode 100644
index d7cd256967..0000000000
--- a/indra/llxuixml/llxuiparser.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/** 
- * @file llxuiparser.h
- * @brief Utility functions for handling XUI structures in XML
- *
- * $LicenseInfo:firstyear=2003&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 LLXUIPARSER_H
-#define LLXUIPARSER_H
-
-#include "llinitparam.h"
-#include "llregistry.h"
-#include "llpointer.h"
-
-#include <boost/function.hpp>
-#include <iosfwd>
-#include <stack>
-#include <set>
-
-
-
-class LLView;
-
-
-typedef LLPointer<class LLXMLNode> LLXMLNodePtr;
-
-
-// lookup widget type by name
-class LLWidgetTypeRegistry
-:	public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry>
-{};
-
-
-// global static instance for registering all widget types
-typedef boost::function<LLView* (LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)> LLWidgetCreatorFunc;
-
-typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t;
-
-class LLChildRegistryRegistry
-: public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry>
-{};
-
-
-
-class LLXSDWriter : public LLInitParam::Parser
-{
-	LOG_CLASS(LLXSDWriter);
-public:
-	void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace);
-
-	/*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; }
-
-	LLXSDWriter();
-
-protected:
-	void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values);
-	void addAttributeToSchema(LLXMLNodePtr nodep, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector<std::string>* possible_values);
-	LLXMLNodePtr mAttributeNode;
-	LLXMLNodePtr mElementNode;
-	LLXMLNodePtr mSchemaNode;
-
-	typedef std::set<std::string> string_set_t;
-	typedef std::map<LLXMLNodePtr, string_set_t> attributes_map_t;
-	attributes_map_t	mAttributesWritten;
-};
-
-
-
-// NOTE: DOES NOT WORK YET
-// should support child widgets for XUI
-class LLXUIXSDWriter : public LLXSDWriter
-{
-public:
-	void writeXSD(const std::string& name, const std::string& path, const LLInitParam::BaseBlock& block);
-};
-
-
-class LLXUIParserImpl;
-
-class LLXUIParser : public LLInitParam::Parser
-{
-LOG_CLASS(LLXUIParser);
-
-public:
-	LLXUIParser();
-	typedef LLInitParam::Parser::name_stack_t name_stack_t;
-
-	/*virtual*/ std::string getCurrentElementName();
-	/*virtual*/ void parserWarning(const std::string& message);
-	/*virtual*/ void parserError(const std::string& message);
-
-	void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false);
-	void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL);
-
-private:
-	bool readXUIImpl(LLXMLNodePtr node, LLInitParam::BaseBlock& block);
-	bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block);
-
-	//reader helper functions
-	static bool readFlag(Parser& parser, void* val_ptr);
-	static bool readBoolValue(Parser& parser, void* val_ptr);
-	static bool readStringValue(Parser& parser, void* val_ptr);
-	static bool readU8Value(Parser& parser, void* val_ptr);
-	static bool readS8Value(Parser& parser, void* val_ptr);
-	static bool readU16Value(Parser& parser, void* val_ptr);
-	static bool readS16Value(Parser& parser, void* val_ptr);
-	static bool readU32Value(Parser& parser, void* val_ptr);
-	static bool readS32Value(Parser& parser, void* val_ptr);
-	static bool readF32Value(Parser& parser, void* val_ptr);
-	static bool readF64Value(Parser& parser, void* val_ptr);
-	static bool readColor4Value(Parser& parser, void* val_ptr);
-	static bool readUIColorValue(Parser& parser, void* val_ptr);
-	static bool readUUIDValue(Parser& parser, void* val_ptr);
-	static bool readSDValue(Parser& parser, void* val_ptr);
-
-	//writer helper functions
-	static bool writeFlag(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeStringValue(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeU8Value(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeS8Value(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeU16Value(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeS16Value(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeU32Value(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&);
-	static bool writeSDValue(Parser& parser, const void* val_ptr, name_stack_t&);
-
-	LLXMLNodePtr getNode(name_stack_t& stack);
-
-private:
-	Parser::name_stack_t			mNameStack;
-	LLXMLNodePtr					mCurReadNode;
-	// Root of the widget XML sub-tree, for example, "line_editor"
-	LLXMLNodePtr					mWriteRootNode;
-	
-	typedef std::map<std::string, LLXMLNodePtr>	out_nodes_t;
-	out_nodes_t						mOutNodes;
-	LLXMLNodePtr					mLastWrittenChild;
-	S32								mCurReadDepth;
-	std::string						mCurFileName;
-	std::string						mRootNodeName;
-};
-
-// LLSimpleXUIParser is a streamlined SAX-based XUI parser that does not support localization 
-// or parsing of a tree of independent param blocks, such as child widgets.
-// Use this for reading non-localized files that only need a single param block as a result.
-//
-// NOTE: In order to support nested block parsing, we need callbacks for start element that
-// push new blocks contexts on the mScope stack.
-// NOTE: To support localization without building a DOM, we need to enforce consistent 
-// ordering of child elements from base file to localized diff file.  Then we can use a pair
-// of coroutines to perform matching of xml nodes during parsing.  Not sure if the overhead
-// of coroutines would offset the gain from SAX parsing
-class LLSimpleXUIParserImpl;
-
-class LLSimpleXUIParser : public LLInitParam::Parser
-{
-LOG_CLASS(LLSimpleXUIParser);
-public:
-	typedef LLInitParam::Parser::name_stack_t name_stack_t;
-	typedef LLInitParam::BaseBlock* (*element_start_callback_t)(LLSimpleXUIParser&, const char* block_name);
-
-	LLSimpleXUIParser(element_start_callback_t element_cb = NULL);
-	virtual ~LLSimpleXUIParser();
-
-	/*virtual*/ std::string getCurrentElementName();
-	/*virtual*/ void parserWarning(const std::string& message);
-	/*virtual*/ void parserError(const std::string& message);
-
-	bool readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent=false);
-
-
-private:
-	//reader helper functions
-	static bool readFlag(Parser&, void* val_ptr);
-	static bool readBoolValue(Parser&, void* val_ptr);
-	static bool readStringValue(Parser&, void* val_ptr);
-	static bool readU8Value(Parser&, void* val_ptr);
-	static bool readS8Value(Parser&, void* val_ptr);
-	static bool readU16Value(Parser&, void* val_ptr);
-	static bool readS16Value(Parser&, void* val_ptr);
-	static bool readU32Value(Parser&, void* val_ptr);
-	static bool readS32Value(Parser&, void* val_ptr);
-	static bool readF32Value(Parser&, void* val_ptr);
-	static bool readF64Value(Parser&, void* val_ptr);
-	static bool readColor4Value(Parser&, void* val_ptr);
-	static bool readUIColorValue(Parser&, void* val_ptr);
-	static bool readUUIDValue(Parser&, void* val_ptr);
-	static bool readSDValue(Parser&, void* val_ptr);
-
-private:
-	static void startElementHandler(void *userData, const char *name, const char **atts);
-	static void endElementHandler(void *userData, const char *name);
-	static void characterDataHandler(void *userData, const char *s, int len);
-
-	void startElement(const char *name, const char **atts);
-	void endElement(const char *name);
-	void characterData(const char *s, int len);
-	bool readAttributes(const char **atts);
-	bool processText();
-
-	Parser::name_stack_t			mNameStack;
-	struct XML_ParserStruct*		mParser;
-	LLXMLNodePtr					mLastWrittenChild;
-	S32								mCurReadDepth;
-	std::string						mCurFileName;
-	std::string						mTextContents;
-	const char*						mCurAttributeValueBegin;
-	std::vector<S32>				mTokenSizeStack;
-	std::vector<std::string>		mScope;
-	std::vector<bool>				mEmptyLeafNode;
-	element_start_callback_t		mElementCB;
-
-	std::vector<std::pair<LLInitParam::BaseBlock*, S32> > mOutputStack;
-};
-
-
-#endif //LLXUIPARSER_H
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 6b2fe1e45a..baf7627f06 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -30,7 +30,6 @@ include(LLUI)
 include(LLVFS)
 include(LLWindow)
 include(LLXML)
-include(LLXUIXML)
 include(LScript)
 include(Linking)
 include(NDOF)
@@ -65,7 +64,6 @@ include_directories(
     ${LLVFS_INCLUDE_DIRS}
     ${LLWINDOW_INCLUDE_DIRS}
     ${LLXML_INCLUDE_DIRS}
-    ${LLXUIXML_INCLUDE_DIRS}
     ${LSCRIPT_INCLUDE_DIRS}
     ${LSCRIPT_INCLUDE_DIRS}/lscript_compile
     ${LLLOGIN_INCLUDE_DIRS}
@@ -1740,7 +1738,6 @@ target_link_libraries(${VIEWER_BINARY_NAME}
     ${LLVFS_LIBRARIES}
     ${LLWINDOW_LIBRARIES}
     ${LLXML_LIBRARIES}
-    ${LLXUIXML_LIBRARIES}
     ${LSCRIPT_LIBRARIES}
     ${LLMATH_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index f738b84bb9..6c8a827ba3 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -57,6 +57,8 @@
 #include "lldeleteutils.h"
 #include "imageids.h"
 #include "indra_constants.h"
+#include "llinitparam.h"
+
 //#include "linden_common.h"
 //#include "llpreprocessor.h"
 #include "llallocator.h"
@@ -124,7 +126,5 @@
 // Library includes from llmessage project
 #include "llcachename.h"
 
-// Library includes from llxuixml
-#include "llinitparam.h"
 
 #endif
-- 
cgit v1.2.3


From 18e7f1bffd875bb933212367f0d62dfc4da871b9 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Fri, 20 Jan 2012 16:42:57 -0600
Subject: SH-2889 Add visual auto-muting controls

---
 indra/llmath/llvolume.cpp                          |  3 +
 indra/llmath/llvolume.h                            |  2 +
 indra/newview/app_settings/settings.xml            | 22 +++++++
 indra/newview/lldrawable.cpp                       | 10 ++++
 indra/newview/llspatialpartition.cpp               | 15 ++++-
 indra/newview/llspatialpartition.h                 | 18 ++++--
 indra/newview/llviewermenu.cpp                     |  4 ++
 indra/newview/llvoavatar.cpp                       | 20 ++++++-
 indra/newview/llvoavatar.h                         |  5 ++
 indra/newview/llvovolume.cpp                       | 70 +++++++++++++++++++---
 indra/newview/pipeline.cpp                         |  2 +-
 indra/newview/pipeline.h                           | 57 +++++++++---------
 indra/newview/skins/default/xui/en/menu_viewer.xml | 10 ++++
 13 files changed, 193 insertions(+), 45 deletions(-)

diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 0c6cf1dfae..761fc171c4 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2078,6 +2078,7 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
 	mFaceMask = 0x0;
 	mDetail = detail;
 	mSculptLevel = -2;
+	mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims
 	mIsMeshAssetLoaded = FALSE;
 	mLODScaleBias.setVec(1,1,1);
 	mHullPoints = NULL;
@@ -3144,6 +3145,8 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
 		{
 			F32 area = sculptGetSurfaceArea();
 
+			mSurfaceArea = area;
+
 			const F32 SCULPT_MAX_AREA = 384.f;
 
 			if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index afd1ec5eed..76cf9de613 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -963,6 +963,7 @@ public:
 	S32	getNumFaces() const;
 	S32 getNumVolumeFaces() const							{ return mVolumeFaces.size(); }
 	F32 getDetail() const									{ return mDetail; }
+	F32 getSurfaceArea() const								{ return mSurfaceArea; }
 	const LLVolumeParams& getParams() const					{ return mParams; }
 	LLVolumeParams getCopyOfParams() const					{ return mParams; }
 	const LLProfile& getProfile() const						{ return *mProfilep; }
@@ -1065,6 +1066,7 @@ public:
 	BOOL mUnique;
 	F32 mDetail;
 	S32 mSculptLevel;
+	F32 mSurfaceArea; //unscaled surface area
 	BOOL mIsMeshAssetLoaded;
 	
 	LLVolumeParams mParams;
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 1ea623791d..3acc8a2446 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -9024,6 +9024,28 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+  <key>RenderAutoMuteByteLimit</key>
+  <map>
+    <key>Comment</key>
+    <string>Maximum bytes of attachments before an avatar is automatically visually muted (0 for no limit).</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+  <key>RenderAutoMuteSurfaceAreaLimit</key>
+  <map>
+    <key>Comment</key>
+    <string>Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit).</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
     <key>RenderUseShaderLOD</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index debac9dcbf..21b21c152a 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -1077,6 +1077,7 @@ BOOL LLDrawable::isVisible() const
 LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask)
 : LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB)
 {
+	mBridge = this;
 	mDrawable = root;
 	root->setSpatialBridge(this);
 	
@@ -1105,6 +1106,15 @@ LLSpatialBridge::~LLSpatialBridge()
 	{
 		group->mSpatialPartition->remove(this, group);
 	}
+
+	//delete octree here so listeners will still be able to access bridge specific state
+	destroyTree();
+}
+
+void LLSpatialBridge::destroyTree()
+{
+	delete mOctree;
+	mOctree = NULL;
 }
 
 void LLSpatialBridge::updateSpatialExtents()
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 4aa5f32d8a..5d196a465f 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -1187,6 +1187,8 @@ void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode)
 
 LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
 	mState(0),
+	mGeometryBytes(0),
+	mSurfaceArea(0.f),
 	mBuilt(0.f),
 	mOctreeNode(node),
 	mSpatialPartition(part),
@@ -1412,6 +1414,17 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node)
 		}
 	}
 	
+	//clean up avatar attachment stats
+	LLSpatialBridge* bridge = mSpatialPartition->asBridge();
+	if (bridge)
+	{
+		if (bridge->mAvatar.notNull())
+		{
+			bridge->mAvatar->mAttachmentGeometryBytes -= mGeometryBytes;
+			bridge->mAvatar->mAttachmentSurfaceArea -= mSurfaceArea;
+		}
+	}
+
 	clearDrawMap();
 	mVertexBuffer = NULL;
 	mBufferMap.clear();
@@ -1767,7 +1780,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
 //==============================================
 
 LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage)
-: mRenderByGroup(render_by_group)
+: mRenderByGroup(render_by_group), mBridge(NULL)
 {
 	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
 	mOcclusionEnabled = TRUE;
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 899547ae4d..6c14ecf452 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -405,6 +405,9 @@ public:
 	bridge_list_t mBridgeList;
 	buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers
 
+	U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node
+	F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node
+
 	F32 mBuilt;
 	OctreeNode* mOctreeNode;
 	LLSpatialPartition* mSpatialPartition;
@@ -474,8 +477,8 @@ public:
 	BOOL isVisible(const LLVector3& v);
 	bool isHUDPartition() ;
 	
-	virtual LLSpatialBridge* asBridge() { return NULL; }
-	virtual BOOL isBridge() { return asBridge() != NULL; }
+	LLSpatialBridge* asBridge() { return mBridge; }
+	BOOL isBridge() { return asBridge() != NULL; }
 
 	void renderPhysicsShapes();
 	void renderDebug();
@@ -487,6 +490,9 @@ public:
 
 public:
 	LLSpatialGroup::OctreeNode* mOctree;
+	LLSpatialBridge* mBridge; // NULL for non-LLSpatialBridge instances, otherwise, mBridge == this
+							// use a pointer instead of making "isBridge" and "asBridge" virtual so it's safe
+							// to call asBridge() from the destructor
 	BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed
 	BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane
 	U32 mBufferUsage;
@@ -511,8 +517,9 @@ public:
 	
 	LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask);
 	
-	virtual BOOL isSpatialBridge() const		{ return TRUE; }
+	void destroyTree();
 
+	virtual BOOL isSpatialBridge() const		{ return TRUE; }
 	virtual void updateSpatialExtents();
 	virtual void updateBinRadius();
 	virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE);
@@ -523,11 +530,12 @@ public:
 	virtual void shiftPos(const LLVector4a& vec);
 	virtual void cleanupReferences();
 	virtual LLSpatialPartition* asPartition()		{ return this; }
-	virtual LLSpatialBridge* asBridge()				{ return this; }
-	
+		
 	virtual LLCamera transformCamera(LLCamera& camera);
 	
 	LLDrawable* mDrawable;
+	LLPointer<LLVOAvatar> mAvatar;
+
 };
 
 class LLCullResult 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 0104d35e53..e6619e3e08 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -947,6 +947,10 @@ U32 info_display_from_string(std::string info_display)
 	{
 		return LLPipeline::RENDER_DEBUG_COMPOSITION;
 	}
+	else if ("attachment bytes" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES;
+	}
 	else if ("glow" == info_display)
 	{
 		return LLPipeline::RENDER_DEBUG_GLOW;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 68637a7ed9..bc7f5a9744 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -651,6 +651,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	LLViewerObject(id, pcode, regionp),
 	mIsDummy(FALSE),
 	mSpecialRenderMode(0),
+	mAttachmentGeometryBytes(0),
+	mAttachmentSurfaceArea(0.f),
 	mTurning(FALSE),
 	mPelvisToFoot(0.f),
 	mLastSkeletonSerialNum( 0 ),
@@ -3363,6 +3365,16 @@ void LLVOAvatar::slamPosition()
 	mRoot.updateWorldMatrixChildren();
 }
 
+bool LLVOAvatar::isVisuallyMuted()
+{
+	static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");
+	static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");
+	
+	return LLMuteList::getInstance()->isMuted(getID()) ||
+			(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) ||
+			(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f);
+}
+
 //------------------------------------------------------------------------
 // updateCharacter()
 // called on both your avatar and other avatars
@@ -3429,8 +3441,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		size.setSub(ext[1],ext[0]);
 		F32 mag = size.getLength3().getF32()*0.5f;
 
+		
 		F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
-		if (LLMuteList::getInstance()->isMuted(getID()))
+		if (isVisuallyMuted())
 		{ // muted avatars update at 16 hz
 			mUpdatePeriod = 16;
 		}
@@ -8333,6 +8346,11 @@ void LLVOAvatar::idleUpdateRenderCost()
 
 	static std::set<LLUUID> all_textures;
 
+	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES))
+	{ //set debug text to attachment geometry bytes here so render cost will override
+		setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea));
+	}
+
 	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
 	{
 		return;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 59796370ae..4cd61cecf9 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -380,6 +380,8 @@ private:
 
 public:
 	U32 		renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
+	bool		isVisuallyMuted();
+
 	U32 		renderRigid();
 	U32 		renderSkinned(EAvatarRenderPass pass);
 	F32			getLastSkinTime() { return mLastSkinTime; }
@@ -391,6 +393,9 @@ public:
 	static void	restoreGL();
 	BOOL 		mIsDummy; // for special views
 	S32			mSpecialRenderMode; // special lighting
+	U32			mAttachmentGeometryBytes; //number of bytes in attached geometry
+	F32			mAttachmentSurfaceArea; //estimated surface area of attachments
+
 private:
 	bool		shouldAlphaMask();
 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e68fd2697a..7492a06784 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4097,6 +4097,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 	LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB);
 
+	LLVOAvatar* pAvatarVO = NULL;
+
+	LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+	if (bridge)
+	{
+		if (bridge->mAvatar.isNull())
+		{
+			LLViewerObject* vobj = bridge->mDrawable->getVObj();
+			if (vobj)
+			{
+				bridge->mAvatar = vobj->getAvatar();
+			}
+		}
+
+		pAvatarVO = bridge->mAvatar;
+	}
+
+	if (pAvatarVO)
+	{
+		pAvatarVO->mAttachmentGeometryBytes -= group->mGeometryBytes;
+		pAvatarVO->mAttachmentSurfaceArea -= group->mSurfaceArea;
+	}
+
+	group->mGeometryBytes = 0;
+	group->mSurfaceArea = 0;
+	
 	group->clearDrawMap();
 
 	mFaceList.clear();
@@ -4133,12 +4159,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 		LLVOVolume* vobj = drawablep->getVOVolume();
 
+		if (!vobj)
+		{
+			continue;
+		}
+
 		if (vobj->isMesh() &&
 			(vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled()))
 		{
 			continue;
 		}
 
+		LLVolume* volume = vobj->getVolume();
+		if (volume)
+		{
+			const LLVector3& scale = vobj->getScale();
+			group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]);
+		}
+
 		llassert_always(vobj);
 		vobj->updateTextureVirtualSize(true);
 		vobj->preRebuild();
@@ -4183,7 +4221,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 				//Determine if we've received skininfo that contains an
 				//alternate bind matrix - if it does then apply the translational component
 				//to the joints of the avatar.
-				LLVOAvatar* pAvatarVO = vobj->getAvatar();
 				bool pelvisGotSet = false;
 
 				if ( pAvatarVO )
@@ -4253,13 +4290,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 					if (type == LLDrawPool::POOL_ALPHA)
 					{
-						if (te->getFullbright())
+						if (te->getColor().mV[3] > 0.f)
 						{
-							pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
-						}
-						else
-						{
-							pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
+							if (te->getFullbright())
+							{
+								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
+							}
+							else
+							{
+								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
+							}
 						}
 					}
 					else if (te->getShiny())
@@ -4392,8 +4432,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 					}
 					else
 					{
-						drawablep->setState(LLDrawable::HAS_ALPHA);
-						alpha_faces.push_back(facep);
+						if (te->getColor().mV[3] > 0.f)
+						{
+							drawablep->setState(LLDrawable::HAS_ALPHA);
+							alpha_faces.push_back(facep);
+						}
 					}
 				}
 				else
@@ -4510,6 +4553,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 	}
 
 	mFaceList.clear();
+
+	if (pAvatarVO)
+	{
+		pAvatarVO->mAttachmentGeometryBytes += group->mGeometryBytes;
+		pAvatarVO->mAttachmentSurfaceArea += group->mSurfaceArea;
+	}
 }
 
 static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry");
@@ -4838,6 +4887,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 			}
 		}
 
+		group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize();
+
+
 		buffer_map[mask][*face_iter].push_back(buffer);
 
 		//add face geometry
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 737c5b51a2..df8f8793d1 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -9420,7 +9420,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 
 	assertInitialized();
 
-	BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID());
+	bool muted = avatar->isVisuallyMuted();		
 
 	pushRenderTypeMask();
 	
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 2815d736e4..9c78048c46 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -432,34 +432,35 @@ public:
 
 	enum LLRenderDebugMask
 	{
-		RENDER_DEBUG_COMPOSITION		= 0x0000001,
-		RENDER_DEBUG_VERIFY				= 0x0000002,
-		RENDER_DEBUG_BBOXES				= 0x0000004,
-		RENDER_DEBUG_OCTREE				= 0x0000008,
-		RENDER_DEBUG_WIND_VECTORS		= 0x0000010,
-		RENDER_DEBUG_OCCLUSION			= 0x0000020,
-		RENDER_DEBUG_POINTS				= 0x0000040,
-		RENDER_DEBUG_TEXTURE_PRIORITY	= 0x0000080,
-		RENDER_DEBUG_TEXTURE_AREA		= 0x0000100,
-		RENDER_DEBUG_FACE_AREA			= 0x0000200,
-		RENDER_DEBUG_PARTICLES			= 0x0000400,
-		RENDER_DEBUG_GLOW				= 0x0000800,
-		RENDER_DEBUG_TEXTURE_ANIM		= 0x0001000,
-		RENDER_DEBUG_LIGHTS				= 0x0002000,
-		RENDER_DEBUG_BATCH_SIZE			= 0x0004000,
-		RENDER_DEBUG_ALPHA_BINS			= 0x0008000,
-		RENDER_DEBUG_RAYCAST            = 0x0010000,
-		RENDER_DEBUG_SHAME				= 0x0020000,
-		RENDER_DEBUG_SHADOW_FRUSTA		= 0x0040000,
-		RENDER_DEBUG_SCULPTED           = 0x0080000,
-		RENDER_DEBUG_AVATAR_VOLUME      = 0x0100000,
-		RENDER_DEBUG_BUILD_QUEUE		= 0x0200000,
-		RENDER_DEBUG_AGENT_TARGET       = 0x0400000,
-		RENDER_DEBUG_UPDATE_TYPE		= 0x0800000,
-		RENDER_DEBUG_PHYSICS_SHAPES     = 0x1000000,
-		RENDER_DEBUG_NORMALS	        = 0x2000000,
-		RENDER_DEBUG_LOD_INFO	        = 0x4000000,
-		RENDER_DEBUG_RENDER_COMPLEXITY  = 0x8000000
+		RENDER_DEBUG_COMPOSITION		= 0x00000001,
+		RENDER_DEBUG_VERIFY				= 0x00000002,
+		RENDER_DEBUG_BBOXES				= 0x00000004,
+		RENDER_DEBUG_OCTREE				= 0x00000008,
+		RENDER_DEBUG_WIND_VECTORS		= 0x00000010,
+		RENDER_DEBUG_OCCLUSION			= 0x00000020,
+		RENDER_DEBUG_POINTS				= 0x00000040,
+		RENDER_DEBUG_TEXTURE_PRIORITY	= 0x00000080,
+		RENDER_DEBUG_TEXTURE_AREA		= 0x00000100,
+		RENDER_DEBUG_FACE_AREA			= 0x00000200,
+		RENDER_DEBUG_PARTICLES			= 0x00000400,
+		RENDER_DEBUG_GLOW				= 0x00000800,
+		RENDER_DEBUG_TEXTURE_ANIM		= 0x00001000,
+		RENDER_DEBUG_LIGHTS				= 0x00002000,
+		RENDER_DEBUG_BATCH_SIZE			= 0x00004000,
+		RENDER_DEBUG_ALPHA_BINS			= 0x00008000,
+		RENDER_DEBUG_RAYCAST            = 0x00010000,
+		RENDER_DEBUG_SHAME				= 0x00020000,
+		RENDER_DEBUG_SHADOW_FRUSTA		= 0x00040000,
+		RENDER_DEBUG_SCULPTED           = 0x00080000,
+		RENDER_DEBUG_AVATAR_VOLUME      = 0x00100000,
+		RENDER_DEBUG_BUILD_QUEUE		= 0x00200000,
+		RENDER_DEBUG_AGENT_TARGET       = 0x00400000,
+		RENDER_DEBUG_UPDATE_TYPE		= 0x00800000,
+		RENDER_DEBUG_PHYSICS_SHAPES     = 0x01000000,
+		RENDER_DEBUG_NORMALS	        = 0x02000000,
+		RENDER_DEBUG_LOD_INFO	        = 0x04000000,
+		RENDER_DEBUG_RENDER_COMPLEXITY  = 0x08000000,
+		RENDER_DEBUG_ATTACHMENT_BYTES	= 0x10000000,
 	};
 
 public:
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index ec2dd10248..b3a0c3379d 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2499,6 +2499,16 @@
           <menu_item_check.on_click
            function="Advanced.ToggleInfoDisplay"
            parameter="rendercomplexity" />
+        </menu_item_check>
+        <menu_item_check
+         label="Attachment Bytes"
+         name="attachment bytes">
+          <menu_item_check.on_check
+           function="Advanced.CheckInfoDisplay"
+           parameter="attachment bytes" />
+          <menu_item_check.on_click
+           function="Advanced.ToggleInfoDisplay"
+           parameter="attachment bytes" />
         </menu_item_check>
 		<menu_item_check
          label="Sculpt"
-- 
cgit v1.2.3


From 0bf73f73b8167900a2582a494d600fa6e5189b7e Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Fri, 20 Jan 2012 15:48:51 -0700
Subject: trivial: remove debug code for SH-2828 [crashhunters] Crash in
 LLRefCount::unref(), bad stacks

---
 indra/newview/llviewerwindow.cpp | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 0534246559..5f64dba100 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1960,43 +1960,34 @@ void LLViewerWindow::shutdownViews()
 	// clean up warning logger
 	LLError::removeRecorder(RecordToChatConsole::getInstance());
 
-	llinfos << "Warning logger is cleaned." << llendl ;
-
 	delete mDebugText;
 	mDebugText = NULL;
 	
-	llinfos << "DebugText deleted." << llendl ;
-
 	// Cleanup global views
 	if (gMorphView)
 	{
 		gMorphView->setVisible(FALSE);
 	}
-	llinfos << "Global views cleaned." << llendl ;
-
+	
 	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
 	// will crump with LL_ERRS.
 	LLModalDialog::shutdownModals();
-	llinfos << "LLModalDialog shut down." << llendl; 
-
+	
 	// destroy the nav bar, not currently part of gViewerWindow
 	// *TODO: Make LLNavigationBar part of gViewerWindow
 	if (LLNavigationBar::instanceExists())
 	{
 		delete LLNavigationBar::getInstance();
 	}
-	llinfos << "LLNavigationBar destroyed." << llendl ;
-
+	
 	// destroy menus after instantiating navbar above, as it needs
 	// access to gMenuHolder
 	cleanup_menus();
-	llinfos << "menus destroyed." << llendl ;
-
+	
 	// Delete all child views.
 	delete mRootView;
 	mRootView = NULL;
-	llinfos << "RootView deleted." << llendl ;
-
+	
 	// Automatically deleted as children of mRootView.  Fix the globals.
 	gStatusBar = NULL;
 	gIMMgr = NULL;
-- 
cgit v1.2.3


From 4287dcaacf0804a5a73dbf37c629471e2855733c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 20 Jan 2012 14:55:39 -0800
Subject: moved LLSDParam to llcommon so that LLSD<->Param Block conversion are
 usable by everyone

---
 indra/llcommon/CMakeLists.txt |   2 +
 indra/llcommon/llinitparam.h  |   4 +-
 indra/llcommon/llsdparam.cpp  | 342 ++++++++++++++++++++++++++++++++++++++++++
 indra/llcommon/llsdparam.h    | 126 ++++++++++++++++
 indra/llui/CMakeLists.txt     |   2 -
 indra/llui/llsdparam.cpp      | 342 ------------------------------------------
 indra/llui/llsdparam.h        | 126 ----------------
 7 files changed, 472 insertions(+), 472 deletions(-)
 create mode 100644 indra/llcommon/llsdparam.cpp
 create mode 100644 indra/llcommon/llsdparam.h
 delete mode 100644 indra/llui/llsdparam.cpp
 delete mode 100644 indra/llui/llsdparam.h

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 72b1d363b0..a1aa887d3a 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -82,6 +82,7 @@ set(llcommon_SOURCE_FILES
     llrefcount.cpp
     llrun.cpp
     llsd.cpp
+    llsdparam.cpp
     llsdserialize.cpp
     llsdserialize_xml.cpp
     llsdutil.cpp
@@ -211,6 +212,7 @@ set(llcommon_HEADER_FILES
     llrefcount.h
     llsafehandle.h
     llsd.h
+    llsdparam.h
     llsdserialize.h
     llsdserialize_xml.h
     llsdutil.h
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 550e1608cc..beaf07e56b 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -2057,8 +2057,8 @@ namespace LLInitParam
 		
 
 		// block param interface
-		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
-		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
+		LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
+		LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
 		{
 			//TODO: implement LLSD params as schema type Any
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
new file mode 100644
index 0000000000..0e29873bb0
--- /dev/null
+++ b/indra/llcommon/llsdparam.cpp
@@ -0,0 +1,342 @@
+/** 
+ * @file llsdparam.cpp
+ * @brief parameter block abstraction for creating complex objects and 
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&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"
+
+// Project includes
+#include "llsdparam.h"
+#include "llsdutil.h"
+
+static 	LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
+static 	LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
+static 	LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
+static const LLSD NO_VALUE_MARKER;
+
+LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
+
+//
+// LLParamSDParser
+//
+LLParamSDParser::LLParamSDParser()
+: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
+{
+	using boost::bind;
+
+	if (sReadFuncs.empty())
+	{
+		registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);
+		registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
+		registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
+		registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
+		registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
+		registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
+		registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
+		registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
+		registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
+		registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
+		registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
+	}
+}
+
+// special case handling of U32 due to ambiguous LLSD::assign overload
+bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
+{
+	LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
+	if (!sdparser.mWriteRootSD) return false;
+	
+	parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
+	LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
+	sd_to_write.assign((S32)*((const U32*)val_ptr));
+
+	return true;
+}
+
+bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
+{
+	LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
+	if (!sdparser.mWriteRootSD) return false;
+
+	parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
+	LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
+
+	return true;
+}
+
+void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack)
+{
+	mCurReadSD = &sd;
+	block.submitValue(name_stack, *this);
+}
+
+void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
+{
+	mCurReadSD = NULL;
+	mNameStack.clear();
+	setParseSilently(silent);
+
+	LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
+	//readSDValues(sd, block);
+}
+
+void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
+{
+	mNameStack.clear();
+	mWriteRootSD = &sd;
+
+	name_stack_t name_stack;
+	block.serializeBlock(*this, name_stack);
+}
+
+/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
+{
+	std::string full_name = "sd";
+	for (name_stack_t::iterator it = mNameStack.begin();	
+		it != mNameStack.end();
+		++it)
+	{
+		full_name += llformat("[%s]", it->first.c_str());
+	}
+
+	return full_name;
+}
+
+
+bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+	return self.mCurReadSD == &NO_VALUE_MARKER;
+}
+
+
+bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((S32*)val_ptr) = self.mCurReadSD->asInteger();
+    return true;
+}
+
+bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((U32*)val_ptr) = self.mCurReadSD->asInteger();
+    return true;
+}
+
+bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((F32*)val_ptr) = self.mCurReadSD->asReal();
+    return true;
+}
+
+bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((F64*)val_ptr) = self.mCurReadSD->asReal();
+    return true;
+}
+
+bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+    *((bool*)val_ptr) = self.mCurReadSD->asBoolean();
+    return true;
+}
+
+bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((std::string*)val_ptr) = self.mCurReadSD->asString();
+    return true;
+}
+
+bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
+    return true;
+}
+
+bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((LLDate*)val_ptr) = self.mCurReadSD->asDate();
+    return true;
+}
+
+bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((LLURI*)val_ptr) = self.mCurReadSD->asURI();
+    return true;
+}
+
+bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
+{
+	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+	*((LLSD*)val_ptr) = *self.mCurReadSD;
+    return true;
+}
+
+// static
+LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range)
+{
+	LLSD* sd_to_write = &input;
+	
+	for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
+		it != name_stack_range.second;
+		++it)
+	{
+		bool new_traversal = it->second;
+
+		LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
+
+		if (child_sd->isArray())
+		{
+			if (new_traversal)
+			{
+				// write to new element at end
+				sd_to_write = &(*child_sd)[child_sd->size()];
+			}
+			else
+			{
+				// write to last of existing elements, or first element if empty
+				sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
+			}
+		}
+		else
+		{
+			if (new_traversal 
+				&& child_sd->isDefined() 
+				&& !child_sd->isArray())
+			{
+				// copy child contents into first element of an array
+				LLSD new_array = LLSD::emptyArray();
+				new_array.append(*child_sd);
+				// assign array to slot that previously held the single value
+				*child_sd = new_array;
+				// return next element in that array
+				sd_to_write = &((*child_sd)[1]);
+			}
+			else
+			{
+				sd_to_write = child_sd;
+			}
+		}
+		it->second = false;
+	}
+	
+	return *sd_to_write;
+}
+
+//static
+void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack)
+{
+	if (sd.isMap())
+	{
+		for (LLSD::map_const_iterator it = sd.beginMap();
+			it != sd.endMap();
+			++it)
+		{
+			stack.push_back(make_pair(it->first, true));
+			readSDValues(cb, it->second, stack);
+			stack.pop_back();
+		}
+	}
+	else if (sd.isArray())
+	{
+		for (LLSD::array_const_iterator it = sd.beginArray();
+			it != sd.endArray();
+			++it)
+		{
+			stack.back().second = true;
+			readSDValues(cb, *it, stack);
+		}
+	}
+	else if (sd.isUndefined())
+	{
+		if (!cb.empty())
+		{
+			cb(NO_VALUE_MARKER, stack);
+		}
+	}
+	else
+	{
+		if (!cb.empty())
+		{
+			cb(sd, stack);
+		}
+	}
+}
+
+//static
+void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)
+{
+	LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
+	readSDValues(cb, sd, stack);
+}
+namespace LLInitParam
+{
+	// LLSD specialization
+	// block param interface
+	bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
+	{
+		LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
+
+		LLSD::String string;
+
+		if (p.readValue<LLSD::String>(string))
+		{
+			sd = string;
+			return true;
+		}
+		return false;
+	}
+
+	//static
+	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
+	{
+		p.writeValue<LLSD::String>(sd.asString(), name_stack);
+	}
+
+	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
+	{
+		// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
+		Parser::name_stack_t stack;
+		LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack);
+	}
+}
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
new file mode 100644
index 0000000000..6ef5debd7b
--- /dev/null
+++ b/indra/llcommon/llsdparam.h
@@ -0,0 +1,126 @@
+/** 
+ * @file llsdparam.h
+ * @brief parameter block abstraction for creating complex objects and 
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&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 LL_LLSDPARAM_H
+#define LL_LLSDPARAM_H
+
+#include "llinitparam.h"
+#include "boost/function.hpp"
+
+struct LL_COMMON_API LLParamSDParserUtilities
+{
+	static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range);
+
+	typedef boost::function<void (const LLSD&, LLInitParam::Parser::name_stack_t&)> read_sd_cb_t;
+	static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack);
+	static void readSDValues(read_sd_cb_t cb, const LLSD& sd);
+};
+
+class LL_COMMON_API LLParamSDParser 
+:	public LLInitParam::Parser
+{
+LOG_CLASS(LLParamSDParser);
+
+typedef LLInitParam::Parser parser_t;
+
+public:
+	LLParamSDParser();
+	void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
+	void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
+
+	/*virtual*/ std::string getCurrentElementName();
+
+private:
+	void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
+
+	template<typename T>
+	static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
+	{
+		LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
+		if (!sdparser.mWriteRootSD) return false;
+		
+		LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end());
+		LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
+
+		sd_to_write.assign(*((const T*)val_ptr));
+		return true;
+	}
+
+	static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
+	static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
+
+	static bool readFlag(Parser& parser, void* val_ptr);
+	static bool readS32(Parser& parser, void* val_ptr);
+	static bool readU32(Parser& parser, void* val_ptr);
+	static bool readF32(Parser& parser, void* val_ptr);
+	static bool readF64(Parser& parser, void* val_ptr);
+	static bool readBool(Parser& parser, void* val_ptr);
+	static bool readString(Parser& parser, void* val_ptr);
+	static bool readUUID(Parser& parser, void* val_ptr);
+	static bool readDate(Parser& parser, void* val_ptr);
+	static bool readURI(Parser& parser, void* val_ptr);
+	static bool readSD(Parser& parser, void* val_ptr);
+
+	Parser::name_stack_t	mNameStack;
+	const LLSD*				mCurReadSD;
+	LLSD*					mWriteRootSD;
+	LLSD*					mCurWriteSD;
+};
+
+
+extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR;
+template<typename T>
+class LLSDParamAdapter : public T
+{
+public:
+	LLSDParamAdapter() {}
+	LLSDParamAdapter(const LLSD& sd)
+	{
+		LLFastTimer _(FTM_SD_PARAM_ADAPTOR);
+		LLParamSDParser parser;
+		// don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
+		bool parse_silently = true;
+		parser.readSD(sd, *this, parse_silently);
+	}
+
+	operator LLSD() const
+	{
+		LLParamSDParser parser;
+		LLSD sd;
+		parser.writeSD(sd, *this);
+		return sd;
+	}
+		
+	LLSDParamAdapter(const T& val)
+	: T(val)
+	{
+		T::operator=(val);
+	}
+};
+
+#endif // LL_LLSDPARAM_H
+
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 9226f36e73..20c3456a56 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -81,7 +81,6 @@ set(llui_SOURCE_FILES
     llscrolllistcolumn.cpp
     llscrolllistctrl.cpp
     llscrolllistitem.cpp
-    llsdparam.cpp
     llsearcheditor.cpp
     llslider.cpp
     llsliderctrl.cpp
@@ -190,7 +189,6 @@ set(llui_HEADER_FILES
     llscrolllistcolumn.h
     llscrolllistctrl.h
     llscrolllistitem.h
-    llsdparam.h
     llsliderctrl.h
     llslider.h
     llspinctrl.h
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
deleted file mode 100644
index 0e29873bb0..0000000000
--- a/indra/llui/llsdparam.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/** 
- * @file llsdparam.cpp
- * @brief parameter block abstraction for creating complex objects and 
- * parsing construction parameters from xml and LLSD
- *
- * $LicenseInfo:firstyear=2008&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"
-
-// Project includes
-#include "llsdparam.h"
-#include "llsdutil.h"
-
-static 	LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
-static 	LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
-static 	LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
-static const LLSD NO_VALUE_MARKER;
-
-LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
-
-//
-// LLParamSDParser
-//
-LLParamSDParser::LLParamSDParser()
-: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
-{
-	using boost::bind;
-
-	if (sReadFuncs.empty())
-	{
-		registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);
-		registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
-		registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
-		registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
-		registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
-		registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
-		registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
-		registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
-		registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
-		registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
-		registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
-	}
-}
-
-// special case handling of U32 due to ambiguous LLSD::assign overload
-bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
-{
-	LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
-	if (!sdparser.mWriteRootSD) return false;
-	
-	parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
-	LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
-	sd_to_write.assign((S32)*((const U32*)val_ptr));
-
-	return true;
-}
-
-bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
-{
-	LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
-	if (!sdparser.mWriteRootSD) return false;
-
-	parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
-	LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
-
-	return true;
-}
-
-void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack)
-{
-	mCurReadSD = &sd;
-	block.submitValue(name_stack, *this);
-}
-
-void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
-{
-	mCurReadSD = NULL;
-	mNameStack.clear();
-	setParseSilently(silent);
-
-	LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
-	//readSDValues(sd, block);
-}
-
-void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
-{
-	mNameStack.clear();
-	mWriteRootSD = &sd;
-
-	name_stack_t name_stack;
-	block.serializeBlock(*this, name_stack);
-}
-
-/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
-{
-	std::string full_name = "sd";
-	for (name_stack_t::iterator it = mNameStack.begin();	
-		it != mNameStack.end();
-		++it)
-	{
-		full_name += llformat("[%s]", it->first.c_str());
-	}
-
-	return full_name;
-}
-
-
-bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-	return self.mCurReadSD == &NO_VALUE_MARKER;
-}
-
-
-bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-    *((S32*)val_ptr) = self.mCurReadSD->asInteger();
-    return true;
-}
-
-bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-    *((U32*)val_ptr) = self.mCurReadSD->asInteger();
-    return true;
-}
-
-bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-    *((F32*)val_ptr) = self.mCurReadSD->asReal();
-    return true;
-}
-
-bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-    *((F64*)val_ptr) = self.mCurReadSD->asReal();
-    return true;
-}
-
-bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-    *((bool*)val_ptr) = self.mCurReadSD->asBoolean();
-    return true;
-}
-
-bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-	*((std::string*)val_ptr) = self.mCurReadSD->asString();
-    return true;
-}
-
-bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-	*((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
-    return true;
-}
-
-bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-	*((LLDate*)val_ptr) = self.mCurReadSD->asDate();
-    return true;
-}
-
-bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-	*((LLURI*)val_ptr) = self.mCurReadSD->asURI();
-    return true;
-}
-
-bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
-{
-	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
-
-	*((LLSD*)val_ptr) = *self.mCurReadSD;
-    return true;
-}
-
-// static
-LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range)
-{
-	LLSD* sd_to_write = &input;
-	
-	for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
-		it != name_stack_range.second;
-		++it)
-	{
-		bool new_traversal = it->second;
-
-		LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
-
-		if (child_sd->isArray())
-		{
-			if (new_traversal)
-			{
-				// write to new element at end
-				sd_to_write = &(*child_sd)[child_sd->size()];
-			}
-			else
-			{
-				// write to last of existing elements, or first element if empty
-				sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
-			}
-		}
-		else
-		{
-			if (new_traversal 
-				&& child_sd->isDefined() 
-				&& !child_sd->isArray())
-			{
-				// copy child contents into first element of an array
-				LLSD new_array = LLSD::emptyArray();
-				new_array.append(*child_sd);
-				// assign array to slot that previously held the single value
-				*child_sd = new_array;
-				// return next element in that array
-				sd_to_write = &((*child_sd)[1]);
-			}
-			else
-			{
-				sd_to_write = child_sd;
-			}
-		}
-		it->second = false;
-	}
-	
-	return *sd_to_write;
-}
-
-//static
-void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack)
-{
-	if (sd.isMap())
-	{
-		for (LLSD::map_const_iterator it = sd.beginMap();
-			it != sd.endMap();
-			++it)
-		{
-			stack.push_back(make_pair(it->first, true));
-			readSDValues(cb, it->second, stack);
-			stack.pop_back();
-		}
-	}
-	else if (sd.isArray())
-	{
-		for (LLSD::array_const_iterator it = sd.beginArray();
-			it != sd.endArray();
-			++it)
-		{
-			stack.back().second = true;
-			readSDValues(cb, *it, stack);
-		}
-	}
-	else if (sd.isUndefined())
-	{
-		if (!cb.empty())
-		{
-			cb(NO_VALUE_MARKER, stack);
-		}
-	}
-	else
-	{
-		if (!cb.empty())
-		{
-			cb(sd, stack);
-		}
-	}
-}
-
-//static
-void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)
-{
-	LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
-	readSDValues(cb, sd, stack);
-}
-namespace LLInitParam
-{
-	// LLSD specialization
-	// block param interface
-	bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
-	{
-		LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
-
-		LLSD::String string;
-
-		if (p.readValue<LLSD::String>(string))
-		{
-			sd = string;
-			return true;
-		}
-		return false;
-	}
-
-	//static
-	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
-	{
-		p.writeValue<LLSD::String>(sd.asString(), name_stack);
-	}
-
-	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
-	{
-		// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
-		Parser::name_stack_t stack;
-		LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack);
-	}
-}
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
deleted file mode 100644
index 3dfc6d020e..0000000000
--- a/indra/llui/llsdparam.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/** 
- * @file llsdparam.h
- * @brief parameter block abstraction for creating complex objects and 
- * parsing construction parameters from xml and LLSD
- *
- * $LicenseInfo:firstyear=2008&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 LL_LLSDPARAM_H
-#define LL_LLSDPARAM_H
-
-#include "llinitparam.h"
-#include "boost/function.hpp"
-
-struct LLParamSDParserUtilities
-{
-	static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range);
-
-	typedef boost::function<void (const LLSD&, LLInitParam::Parser::name_stack_t&)> read_sd_cb_t;
-	static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack);
-	static void readSDValues(read_sd_cb_t cb, const LLSD& sd);
-};
-
-class LLParamSDParser 
-:	public LLInitParam::Parser
-{
-LOG_CLASS(LLParamSDParser);
-
-typedef LLInitParam::Parser parser_t;
-
-public:
-	LLParamSDParser();
-	void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
-	void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
-
-	/*virtual*/ std::string getCurrentElementName();
-
-private:
-	void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
-
-	template<typename T>
-	static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
-	{
-		LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
-		if (!sdparser.mWriteRootSD) return false;
-		
-		LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end());
-		LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
-
-		sd_to_write.assign(*((const T*)val_ptr));
-		return true;
-	}
-
-	static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
-	static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
-
-	static bool readFlag(Parser& parser, void* val_ptr);
-	static bool readS32(Parser& parser, void* val_ptr);
-	static bool readU32(Parser& parser, void* val_ptr);
-	static bool readF32(Parser& parser, void* val_ptr);
-	static bool readF64(Parser& parser, void* val_ptr);
-	static bool readBool(Parser& parser, void* val_ptr);
-	static bool readString(Parser& parser, void* val_ptr);
-	static bool readUUID(Parser& parser, void* val_ptr);
-	static bool readDate(Parser& parser, void* val_ptr);
-	static bool readURI(Parser& parser, void* val_ptr);
-	static bool readSD(Parser& parser, void* val_ptr);
-
-	Parser::name_stack_t	mNameStack;
-	const LLSD*				mCurReadSD;
-	LLSD*					mWriteRootSD;
-	LLSD*					mCurWriteSD;
-};
-
-
-extern LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR;
-template<typename T>
-class LLSDParamAdapter : public T
-{
-public:
-	LLSDParamAdapter() {}
-	LLSDParamAdapter(const LLSD& sd)
-	{
-		LLFastTimer _(FTM_SD_PARAM_ADAPTOR);
-		LLParamSDParser parser;
-		// don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
-		bool parse_silently = true;
-		parser.readSD(sd, *this, parse_silently);
-	}
-
-	operator LLSD() const
-	{
-		LLParamSDParser parser;
-		LLSD sd;
-		parser.writeSD(sd, *this);
-		return sd;
-	}
-		
-	LLSDParamAdapter(const T& val)
-	: T(val)
-	{
-		T::operator=(val);
-	}
-};
-
-#endif // LL_LLSDPARAM_H
-
-- 
cgit v1.2.3


From f0dbb878337082d3f581874c12e6df2f4659a464 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 20 Jan 2012 18:10:40 -0500
Subject: Per Richard, replace LLProcessLauncher with LLProcess.
 LLProcessLauncher had the somewhat fuzzy mandate of (1) accumulating
 parameters with which to launch a child process and (2) sometimes tracking
 the lifespan of the ensuing child process. But a valid LLProcessLauncher
 object might or might not have ever been associated with an actual child
 process. LLProcess specifically tracks a child process. In effect, it's a
 fairly thin wrapper around a process HANDLE (on Windows) or pid_t
 (elsewhere), with lifespan management thrown in. A static LLProcess::create()
 method launches a new child; create() accepts an LLSD bundle with child
 parameters. So building up a parameter bundle is deferred to LLSD rather than
 conflated with the process management object. Reconcile all known
 LLProcessLauncher consumers in the viewer code base, notably the class unit
 tests.

---
 indra/llcommon/CMakeLists.txt                      |   6 +-
 indra/llcommon/llprocess.cpp                       | 338 ++++++++++
 indra/llcommon/llprocess.h                         | 106 +++
 indra/llcommon/llprocesslauncher.cpp               | 394 -----------
 indra/llcommon/llprocesslauncher.h                 | 107 ---
 indra/llcommon/tests/llprocess_test.cpp            | 706 ++++++++++++++++++++
 indra/llcommon/tests/llprocesslauncher_test.cpp    | 718 ---------------------
 indra/llcommon/tests/llsdserialize_test.cpp        |  13 +-
 indra/llplugin/llpluginprocessparent.cpp           |  47 +-
 indra/llplugin/llpluginprocessparent.h             |  10 +-
 indra/newview/llexternaleditor.cpp                 |  73 +--
 indra/newview/llexternaleditor.h                   |   5 +-
 .../updater/llupdateinstaller.cpp                  |  20 +-
 13 files changed, 1238 insertions(+), 1305 deletions(-)
 create mode 100644 indra/llcommon/llprocess.cpp
 create mode 100644 indra/llcommon/llprocess.h
 delete mode 100644 indra/llcommon/llprocesslauncher.cpp
 delete mode 100644 indra/llcommon/llprocesslauncher.h
 create mode 100644 indra/llcommon/tests/llprocess_test.cpp
 delete mode 100644 indra/llcommon/tests/llprocesslauncher_test.cpp

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 2c376bb016..e2af7265aa 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -74,7 +74,7 @@ set(llcommon_SOURCE_FILES
     llmortician.cpp
     lloptioninterface.cpp
     llptrto.cpp 
-    llprocesslauncher.cpp
+    llprocess.cpp
     llprocessor.cpp
     llqueuedthread.cpp
     llrand.cpp
@@ -197,7 +197,7 @@ set(llcommon_HEADER_FILES
     llpointer.h
     llpreprocessor.h
     llpriqueuemap.h
-    llprocesslauncher.h
+    llprocess.h
     llprocessor.h
     llptrskiplist.h
     llptrskipmap.h
@@ -328,7 +328,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llprocesslauncher "" "${test_libs}"
+  LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}"
                           "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
   LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
 
diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
new file mode 100644
index 0000000000..8c0caca680
--- /dev/null
+++ b/indra/llcommon/llprocess.cpp
@@ -0,0 +1,338 @@
+/** 
+ * @file llprocess.cpp
+ * @brief Utility class for launching, terminating, and tracking the state of processes.
+ *
+ * $LicenseInfo:firstyear=2008&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 "llprocess.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "stringize.h"
+
+#include <boost/foreach.hpp>
+#include <iostream>
+#include <stdexcept>
+
+/// Need an exception to avoid constructing an invalid LLProcess object, but
+/// internal use only
+struct LLProcessError: public std::runtime_error
+{
+	LLProcessError(const std::string& msg): std::runtime_error(msg) {}
+};
+
+LLProcessPtr LLProcess::create(const LLSD& params)
+{
+	try
+	{
+		return LLProcessPtr(new LLProcess(params));
+	}
+	catch (const LLProcessError& e)
+	{
+		LL_WARNS("LLProcess") << e.what() << LL_ENDL;
+		return LLProcessPtr();
+	}
+}
+
+LLProcess::LLProcess(const LLSD& params):
+	mProcessID(0),
+	mAutokill(params["autokill"].asBoolean())
+{
+	// nonstandard default bool value
+	if (! params.has("autokill"))
+		mAutokill = true;
+	if (! params.has("executable"))
+	{
+		throw LLProcessError(STRINGIZE("not launched: missing 'executable'\n"
+									   << LLSDNotationStreamer(params)));
+	}
+
+	launch(params);
+}
+
+LLProcess::~LLProcess()
+{
+	if (mAutokill)
+	{
+		kill();
+	}
+}
+
+bool LLProcess::isRunning(void)
+{
+	mProcessID = isRunning(mProcessID);
+	return (mProcessID != 0);
+}
+
+#if LL_WINDOWS
+
+static std::string quote(const std::string& str)
+{
+	std::string::size_type len(str.length());
+	// If the string is already quoted, assume user knows what s/he's doing.
+	if (len >= 2 && str[0] == '"' && str[len-1] == '"')
+	{
+		return str;
+	}
+
+	// Not already quoted: do it.
+	std::string result("\"");
+	for (std::string::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
+	{
+		if (*ci == '"')
+		{
+			result.append("\\");
+		}
+		result.push_back(*ci);
+	}
+	return result + "\"";
+}
+
+void LLProcess::launch(const LLSD& params)
+{
+	PROCESS_INFORMATION pinfo;
+	STARTUPINFOA sinfo;
+	memset(&sinfo, 0, sizeof(sinfo));
+	
+	std::string args = quote(params["executable"]);
+	BOOST_FOREACH(const std::string& arg, llsd::inArray(params["args"]))
+	{
+		args += " ";
+		args += quote(arg);
+	}
+	
+	// So retarded.  Windows requires that the second parameter to
+	// CreateProcessA be a writable (non-const) string...
+	std::vector<char> args2(args.begin(), args.end());
+	args2.push_back('\0');
+
+	// Convert wrapper to a real std::string so we can use c_str(); but use a
+	// named variable instead of a temporary so c_str() pointer remains valid.
+	std::string cwd(params["cwd"]);
+	const char * working_directory = 0;
+	if (! cwd.empty())
+		working_directory = cwd.c_str();
+	if( ! CreateProcessA( NULL, &args2[0], NULL, NULL, FALSE, 0, NULL, working_directory, &sinfo, &pinfo ) )
+	{
+		int result = GetLastError();
+
+		LPTSTR error_str = 0;
+		if(
+			FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+				NULL,
+				result,
+				0,
+				(LPTSTR)&error_str,
+				0,
+				NULL) 
+			!= 0) 
+		{
+			char message[256];
+			wcstombs(message, error_str, sizeof(message));
+			message[sizeof(message)-1] = 0;
+			LocalFree(error_str);
+			throw LLProcessError(STRINGIZE("CreateProcessA failed (" << result << "): "
+										   << message));
+		}
+		throw LLProcessError(STRINGIZE("CreateProcessA failed (" << result
+									   << "), but FormatMessage() did not explain"));
+	}
+
+	// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
+	// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
+	mProcessID = pinfo.hProcess;
+	CloseHandle(pinfo.hThread); // stops leaks - nothing else
+}
+
+LLProcess::id LLProcess::isRunning(id handle)
+{
+	if (! handle)
+		return 0;
+
+	DWORD waitresult = WaitForSingleObject(handle, 0);
+	if(waitresult == WAIT_OBJECT_0)
+	{
+		// the process has completed.
+		return 0;
+	}
+
+	return handle;
+}
+
+bool LLProcess::kill(void)
+{
+	if (! mProcessID)
+		return false;
+
+	TerminateProcess(mProcessID, 0);
+	return ! isRunning();
+}
+
+#else // Mac and linux
+
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise.
+static bool reap_pid(pid_t pid)
+{
+	pid_t wait_result = ::waitpid(pid, NULL, WNOHANG);
+	if (wait_result == pid)
+	{
+		return true;
+	}
+	if (wait_result == -1 && errno == ECHILD)
+	{
+		// No such process -- this may mean we're ignoring SIGCHILD.
+		return true;
+	}
+	
+	return false;
+}
+
+void LLProcess::launch(const LLSD& params)
+{
+	// flush all buffers before the child inherits them
+	::fflush(NULL);
+
+	pid_t child = vfork();
+	if (child == 0)
+	{
+		// child process
+
+		std::string cwd(params["cwd"]);
+		if (! cwd.empty())
+		{
+			// change to the desired child working directory
+			if (::chdir(cwd.c_str()))
+			{
+				// chdir failed
+				LL_WARNS("LLProcess") << "could not chdir(\"" << cwd << "\")" << LL_ENDL;
+				// pointless to throw; this is child process...
+				_exit(248);
+			}
+		}
+
+		// create an argv vector for the child process
+		std::vector<const char*> fake_argv;
+
+		// add the executable path
+		std::string executable(params["executable"]);
+		fake_argv.push_back(executable.c_str());
+
+		// and any arguments
+		const LLSD& params_args(params["args"]);
+		std::vector<std::string> args(params_args.beginArray(), params_args.endArray());
+		BOOST_FOREACH(const std::string& arg, args)
+		{
+			fake_argv.push_back(arg.c_str());
+		}
+
+		// terminate with a null pointer
+		fake_argv.push_back(NULL);
+
+		::execv(executable.c_str(), const_cast<char* const*>(&fake_argv[0]));
+
+		// If we reach this point, the exec failed.
+		LL_WARNS("LLProcess") << "failed to launch: ";
+		BOOST_FOREACH(const char* arg, fake_argv)
+		{
+			LL_CONT << arg << ' ';
+		}
+		LL_CONT << LL_ENDL;
+		// Use _exit() instead of exit() per the vfork man page. Exit with a
+		// distinctive rc: someday soon we'll be able to retrieve it, and it
+		// would be nice to be able to tell that the child process failed!
+		_exit(249);
+	}
+
+	// parent process
+	mProcessID = child;
+}
+
+LLProcess::id LLProcess::isRunning(id pid)
+{
+	if (! pid)
+		return 0;
+
+	// Check whether the process has exited, and reap it if it has.
+	if(reap_pid(pid))
+	{
+		// the process has exited.
+		return 0;
+	}
+
+	return pid;
+}
+
+bool LLProcess::kill(void)
+{
+	if (! mProcessID)
+		return false;
+
+	// Try to kill the process. We'll do approximately the same thing whether
+	// the kill returns an error or not, so we ignore the result.
+	(void)::kill(mProcessID, SIGTERM);
+
+	// This will have the side-effect of reaping the zombie if the process has exited.
+	return ! isRunning();
+}
+
+/*==========================================================================*|
+static std::list<pid_t> sZombies;
+
+void LLProcess::orphan(void)
+{
+	// Disassociate the process from this object
+	if(mProcessID != 0)
+	{	
+		// We may still need to reap the process's zombie eventually
+		sZombies.push_back(mProcessID);
+	
+		mProcessID = 0;
+	}
+}
+
+// static 
+void LLProcess::reap(void)
+{
+	// Attempt to real all saved process ID's.
+	
+	std::list<pid_t>::iterator iter = sZombies.begin();
+	while(iter != sZombies.end())
+	{
+		if(reap_pid(*iter))
+		{
+			iter = sZombies.erase(iter);
+		}
+		else
+		{
+			iter++;
+		}
+	}
+}
+|*==========================================================================*/
+
+#endif
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
new file mode 100644
index 0000000000..9a74cfe829
--- /dev/null
+++ b/indra/llcommon/llprocess.h
@@ -0,0 +1,106 @@
+/** 
+ * @file llprocess.h
+ * @brief Utility class for launching, terminating, and tracking child processes.
+ *
+ * $LicenseInfo:firstyear=2008&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 LL_LLPROCESS_H
+#define LL_LLPROCESS_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+#if LL_WINDOWS
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+class LLSD;
+
+class LLProcess;
+/// LLProcess instances are created on the heap by static factory methods and
+/// managed by ref-counted pointers.
+typedef boost::shared_ptr<LLProcess> LLProcessPtr;
+
+/**
+ *	LLProcess handles launching external processes with specified command line arguments.
+ *	It also keeps track of whether the process is still running, and can kill it if required.
+*/
+class LL_COMMON_API LLProcess: public boost::noncopyable
+{
+	LOG_CLASS(LLProcess);
+public:
+
+	/**
+	 * Factory accepting LLSD::Map.
+	 * MAY RETURN DEFAULT-CONSTRUCTED LLProcessPtr if params invalid!
+	 *
+	 * executable (required, string):				executable pathname
+	 * args		  (optional, string array):			extra command-line arguments
+	 * cwd		  (optional, string, dft no chdir): change to this directory before executing
+	 * autokill	  (optional, bool, dft true):		implicit kill() on ~LLProcess
+	 */
+	static LLProcessPtr create(const LLSD& params);
+	virtual ~LLProcess();
+
+	// isRunning isn't const because, if child isn't running, it clears stored
+	// process ID
+	bool isRunning(void);
+	
+	// Attempt to kill the process -- returns true if the process is no longer running when it returns.
+	// Note that even if this returns false, the process may exit some time after it's called.
+	bool kill(void);
+
+#if LL_WINDOWS
+	typedef HANDLE id;
+#else
+	typedef pid_t  id;
+#endif	
+	/// Get platform-specific process ID
+	id getProcessID() const { return mProcessID; };
+
+	/**
+	 * Test if a process (id obtained from getProcessID()) is still
+	 * running. Return is same nonzero id value if still running, else
+	 * zero, so you can test it like a bool. But if you want to update a
+	 * stored variable as a side effect, you can write code like this:
+	 * @code
+	 * childpid = LLProcess::isRunning(childpid);
+	 * @endcode
+	 * @note This method is intended as a unit-test hook, not as the first of
+	 * a whole set of operations supported on freestanding @c id values. New
+	 * functionality should be added as nonstatic members operating on
+	 * mProcessID.
+	 */
+	static id isRunning(id);
+	
+private:
+	/// constructor is private: use create() instead
+	LLProcess(const LLSD& params);
+	void launch(const LLSD& params);
+
+	id mProcessID;
+	bool mAutokill;
+};
+
+#endif // LL_LLPROCESS_H
diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp
deleted file mode 100644
index 5791d14ec0..0000000000
--- a/indra/llcommon/llprocesslauncher.cpp
+++ /dev/null
@@ -1,394 +0,0 @@
-/** 
- * @file llprocesslauncher.cpp
- * @brief Utility class for launching, terminating, and tracking the state of processes.
- *
- * $LicenseInfo:firstyear=2008&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 "llprocesslauncher.h"
-
-#include <iostream>
-#if LL_DARWIN || LL_LINUX
-// not required or present on Win32
-#include <sys/wait.h>
-#endif
-
-LLProcessLauncher::LLProcessLauncher()
-{
-#if LL_WINDOWS
-	mProcessHandle = 0;
-#else
-	mProcessID = 0;
-#endif
-}
-
-LLProcessLauncher::~LLProcessLauncher()
-{
-	kill();
-}
-
-void LLProcessLauncher::setExecutable(const std::string &executable)
-{
-	mExecutable = executable;
-}
-
-void LLProcessLauncher::setWorkingDirectory(const std::string &dir)
-{
-	mWorkingDir = dir;
-}
-
-const std::string& LLProcessLauncher::getExecutable() const
-{
-	return mExecutable;
-}
-
-void LLProcessLauncher::clearArguments()
-{
-	mLaunchArguments.clear();
-}
-
-void LLProcessLauncher::addArgument(const std::string &arg)
-{
-	mLaunchArguments.push_back(arg);
-}
-
-#if LL_WINDOWS
-
-static std::string quote(const std::string& str)
-{
-    std::string::size_type len(str.length());
-    // If the string is already quoted, assume user knows what s/he's doing.
-    if (len >= 2 && str[0] == '"' && str[len-1] == '"')
-    {
-        return str;
-    }
-
-    // Not already quoted: do it.
-    std::string result("\"");
-    for (std::string::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
-    {
-        if (*ci == '"')
-        {
-            result.append("\\");
-        }
-        result.push_back(*ci);
-    }
-    return result + "\"";
-}
-
-int LLProcessLauncher::launch(void)
-{
-	// If there was already a process associated with this object, kill it.
-	kill();
-	orphan();
-
-	int result = 0;
-	
-	PROCESS_INFORMATION pinfo;
-	STARTUPINFOA sinfo;
-	memset(&sinfo, 0, sizeof(sinfo));
-	
-	std::string args = quote(mExecutable);
-	for(int i = 0; i < (int)mLaunchArguments.size(); i++)
-	{
-		args += " ";
-		args += quote(mLaunchArguments[i]);
-	}
-	
-	// So retarded.  Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
-	char *args2 = new char[args.size() + 1];
-	strcpy(args2, args.c_str());
-
-	const char * working_directory = 0;
-	if(!mWorkingDir.empty()) working_directory = mWorkingDir.c_str();
-	if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, working_directory, &sinfo, &pinfo ) )
-	{
-		result = GetLastError();
-
-		LPTSTR error_str = 0;
-		if(
-			FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-				NULL,
-				result,
-				0,
-				(LPTSTR)&error_str,
-				0,
-				NULL) 
-			!= 0) 
-		{
-			char message[256];
-			wcstombs(message, error_str, 256);
-			message[255] = 0;
-			llwarns << "CreateProcessA failed: " << message << llendl;
-			LocalFree(error_str);
-		}
-
-		if(result == 0)
-		{
-			// Make absolutely certain we return a non-zero value on failure.
-			result = -1;
-		}
-	}
-	else
-	{
-		// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
-		// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
-		mProcessHandle = pinfo.hProcess;
-		CloseHandle(pinfo.hThread); // stops leaks - nothing else
-	}		
-	
-	delete[] args2;
-	
-	return result;
-}
-
-bool LLProcessLauncher::isRunning(void)
-{
-	mProcessHandle = isRunning(mProcessHandle);
-	return (mProcessHandle != 0);
-}
-
-LLProcessLauncher::ll_pid_t LLProcessLauncher::isRunning(ll_pid_t handle)
-{
-	if (! handle)
-		return 0;
-
-	DWORD waitresult = WaitForSingleObject(handle, 0);
-	if(waitresult == WAIT_OBJECT_0)
-	{
-		// the process has completed.
-		return 0;
-	}
-
-	return handle;
-}
-
-bool LLProcessLauncher::kill(void)
-{
-	bool result = true;
-	
-	if(mProcessHandle != 0)
-	{
-		TerminateProcess(mProcessHandle,0);
-
-		if(isRunning())
-		{
-			result = false;
-		}
-	}
-	
-	return result;
-}
-
-void LLProcessLauncher::orphan(void)
-{
-	// Forget about the process
-	mProcessHandle = 0;
-}
-
-// static 
-void LLProcessLauncher::reap(void)
-{
-	// No actions necessary on Windows.
-}
-
-#else // Mac and linux
-
-#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
-
-static std::list<pid_t> sZombies;
-
-// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise.
-static bool reap_pid(pid_t pid)
-{
-	bool result = false;
-	
-	pid_t wait_result = ::waitpid(pid, NULL, WNOHANG);
-	if(wait_result == pid)
-	{
-		result = true;
-	}
-	else if(wait_result == -1)
-	{
-		if(errno == ECHILD)
-		{
-			// No such process -- this may mean we're ignoring SIGCHILD.
-			result = true;
-		}
-	}
-	
-	return result;
-}
-
-int LLProcessLauncher::launch(void)
-{
-	// If there was already a process associated with this object, kill it.
-	kill();
-	orphan();
-	
-	int result = 0;
-	int current_wd = -1;
-	
-	// create an argv vector for the child process
-	const char ** fake_argv = new const char *[mLaunchArguments.size() + 2];  // 1 for the executable path, 1 for the NULL terminator
-
-	int i = 0;
-	
-	// add the executable path
-	fake_argv[i++] = mExecutable.c_str();
-	
-	// and any arguments
-	for(int j=0; j < mLaunchArguments.size(); j++)
-		fake_argv[i++] = mLaunchArguments[j].c_str();
-	
-	// terminate with a null pointer
-	fake_argv[i] = NULL;
-	
-	if(!mWorkingDir.empty())
-	{
-		// save the current working directory
-		current_wd = ::open(".", O_RDONLY);
-	
-		// and change to the one the child will be executed in
-		if (::chdir(mWorkingDir.c_str()))
-		{
-			// chdir failed
-		}
-	}
-		
- 	// flush all buffers before the child inherits them
- 	::fflush(NULL);
-
-	pid_t id = vfork();
-	if(id == 0)
-	{
-		// child process
-		::execv(mExecutable.c_str(), (char * const *)fake_argv);
-
-		// If we reach this point, the exec failed.
-        LL_WARNS("LLProcessLauncher") << "failed to launch: ";
-        for (const char * const * ai = fake_argv; *ai; ++ai)
-        {
-            LL_CONT << *ai << ' ';
-        }
-        LL_CONT << LL_ENDL;
-		// Use _exit() instead of exit() per the vfork man page. Exit with a
-		// distinctive rc: someday soon we'll be able to retrieve it, and it
-		// would be nice to be able to tell that the child process failed!
-		_exit(249);
-	}
-
-	// parent process
-	
-	if(current_wd >= 0)
-	{
-		// restore the previous working directory
-		if (::fchdir(current_wd))
-		{
-			// chdir failed
-		}
-		::close(current_wd);
-	}
-	
-	delete[] fake_argv;
-	
-	mProcessID = id;
-
-	return result;
-}
-
-bool LLProcessLauncher::isRunning(void)
-{
-	mProcessID = isRunning(mProcessID);
-	return (mProcessID != 0);
-}
-
-LLProcessLauncher::ll_pid_t LLProcessLauncher::isRunning(ll_pid_t pid)
-{
-    if (! pid)
-        return 0;
-
-    // Check whether the process has exited, and reap it if it has.
-    if(reap_pid(pid))
-    {
-        // the process has exited.
-        return 0;
-    }
-
-    return pid;
-}
-
-bool LLProcessLauncher::kill(void)
-{
-	bool result = true;
-	
-	if(mProcessID != 0)
-	{
-		// Try to kill the process.  We'll do approximately the same thing whether the kill returns an error or not, so we ignore the result.
-		(void)::kill(mProcessID, SIGTERM);
-		
-		// This will have the side-effect of reaping the zombie if the process has exited.
-		if(isRunning())
-		{
-			result = false;
-		}
-	}
-	
-	return result;
-}
-
-void LLProcessLauncher::orphan(void)
-{
-	// Disassociate the process from this object
-	if(mProcessID != 0)
-	{	
-		// We may still need to reap the process's zombie eventually
-		sZombies.push_back(mProcessID);
-	
-		mProcessID = 0;
-	}
-}
-
-// static 
-void LLProcessLauncher::reap(void)
-{
-	// Attempt to real all saved process ID's.
-	
-	std::list<pid_t>::iterator iter = sZombies.begin();
-	while(iter != sZombies.end())
-	{
-		if(reap_pid(*iter))
-		{
-			iter = sZombies.erase(iter);
-		}
-		else
-		{
-			iter++;
-		}
-	}
-}
-
-#endif
diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h
deleted file mode 100644
index 63193abd8f..0000000000
--- a/indra/llcommon/llprocesslauncher.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/** 
- * @file llprocesslauncher.h
- * @brief Utility class for launching, terminating, and tracking the state of processes.
- *
- * $LicenseInfo:firstyear=2008&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 LL_LLPROCESSLAUNCHER_H
-#define LL_LLPROCESSLAUNCHER_H
-
-#if LL_WINDOWS
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
-
-/*
-	LLProcessLauncher handles launching external processes with specified command line arguments.
-	It also keeps track of whether the process is still running, and can kill it if required.
-*/
-
-class LL_COMMON_API LLProcessLauncher
-{
-	LOG_CLASS(LLProcessLauncher);
-public:
-	LLProcessLauncher();
-	virtual ~LLProcessLauncher();
-	
-	void setExecutable(const std::string &executable);
-	void setWorkingDirectory(const std::string &dir);
-
-	const std::string& getExecutable() const;
-
-	void clearArguments();
-	void addArgument(const std::string &arg);
-		
-	int launch(void);
-	// isRunning isn't const because, if child isn't running, it clears stored
-	// process ID
-	bool isRunning(void);
-	
-	// Attempt to kill the process -- returns true if the process is no longer running when it returns.
-	// Note that even if this returns false, the process may exit some time after it's called.
-	bool kill(void);
-	
-	// Use this if you want the external process to continue execution after the LLProcessLauncher instance controlling it is deleted.
-	// Normally, the destructor will attempt to kill the process and wait for termination.
-	// This should only be used if the viewer is about to exit -- otherwise, the child process will become a zombie after it exits.
-	void orphan(void);	
-	
-	// This needs to be called periodically on Mac/Linux to clean up zombie processes.
-	// (However, as of 2012-01-12 there are no such calls in the viewer code base. :-P )
-	static void reap(void);
-	
-	// Accessors for platform-specific process ID
-#if LL_WINDOWS
-	// (Windows flavor unused as of 2012-01-12)
-	typedef HANDLE ll_pid_t;
-	HANDLE getProcessHandle() const { return mProcessHandle; }
-	ll_pid_t getProcessID() const { return mProcessHandle; }
-#else
-	typedef pid_t ll_pid_t;
-	ll_pid_t getProcessID() const { return mProcessID; };
-#endif	
-	/**
-	 * Test if a process (ll_pid_t obtained from getProcessID()) is still
-	 * running. Return is same nonzero ll_pid_t value if still running, else
-	 * zero, so you can test it like a bool. But if you want to update a
-	 * stored variable as a side effect, you can write code like this:
-	 * @code
-	 * childpid = LLProcessLauncher::isRunning(childpid);
-	 * @endcode
-	 */
-	static ll_pid_t isRunning(ll_pid_t);
-	
-private:
-	std::string mExecutable;
-	std::string mWorkingDir;
-	std::vector<std::string> mLaunchArguments;
-	
-#if LL_WINDOWS
-	HANDLE mProcessHandle;
-#else
-	pid_t mProcessID;
-#endif
-};
-
-#endif // LL_LLPROCESSLAUNCHER_H
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
new file mode 100644
index 0000000000..55e22abd81
--- /dev/null
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -0,0 +1,706 @@
+/**
+ * @file   llprocess_test.cpp
+ * @author Nat Goodspeed
+ * @date   2011-12-19
+ * @brief  Test for llprocess.
+ * 
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Copyright (c) 2011, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llprocess.h"
+// STL headers
+#include <vector>
+#include <list>
+// std headers
+#include <fstream>
+// external library headers
+#include "llapr.h"
+#include "apr_thread_proc.h"
+#include <boost/foreach.hpp>
+#include <boost/function.hpp>
+#include <boost/algorithm/string/find_iterator.hpp>
+#include <boost/algorithm/string/finder.hpp>
+//#include <boost/lambda/lambda.hpp>
+//#include <boost/lambda/bind.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+#include "../test/manageapr.h"
+#include "../test/namedtempfile.h"
+#include "stringize.h"
+#include "llsdutil.h"
+
+#if defined(LL_WINDOWS)
+#define sleep(secs) _sleep((secs) * 1000)
+#define EOL "\r\n"
+#else
+#define EOL "\n"
+#include <sys/wait.h>
+#endif
+
+//namespace lambda = boost::lambda;
+
+// static instance of this manages APR init/cleanup
+static ManageAPR manager;
+
+/*****************************************************************************
+*   Helpers
+*****************************************************************************/
+
+#define ensure_equals_(left, right) \
+        ensure_equals(STRINGIZE(#left << " != " << #right), (left), (right))
+
+#define aprchk(expr) aprchk_(#expr, (expr))
+static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
+{
+    tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << manager.strerror(rv)),
+                       rv, expected);
+}
+
+/**
+ * Read specified file using std::getline(). It is assumed to be an error if
+ * the file is empty: don't use this function if that's an acceptable case.
+ * Last line will not end with '\n'; this is to facilitate the usual case of
+ * string compares with a single line of output.
+ * @param pathname The file to read.
+ * @param desc Optional description of the file for error message;
+ * defaults to "in <pathname>"
+ */
+static std::string readfile(const std::string& pathname, const std::string& desc="")
+{
+    std::string use_desc(desc);
+    if (use_desc.empty())
+    {
+        use_desc = STRINGIZE("in " << pathname);
+    }
+    std::ifstream inf(pathname.c_str());
+    std::string output;
+    tut::ensure(STRINGIZE("No output " << use_desc), std::getline(inf, output));
+    std::string more;
+    while (std::getline(inf, more))
+    {
+        output += '\n' + more;
+    }
+    return output;
+}
+
+/**
+ * Construct an LLProcess to run a Python script.
+ */
+struct PythonProcessLauncher
+{
+    /**
+     * @param desc Arbitrary description for error messages
+     * @param script Python script, any form acceptable to NamedTempFile,
+     * typically either a std::string or an expression of the form
+     * (lambda::_1 << "script content with " << variable_data)
+     */
+    template <typename CONTENT>
+    PythonProcessLauncher(const std::string& desc, const CONTENT& script):
+        mDesc(desc),
+        mScript("py", script)
+    {
+        const char* PYTHON(getenv("PYTHON"));
+        tut::ensure("Set $PYTHON to the Python interpreter", PYTHON);
+
+        mParams["executable"] = PYTHON;
+        mParams["args"].append(mScript.getName());
+    }
+
+    /// Run Python script and wait for it to complete.
+    void run()
+    {
+        mPy = LLProcess::create(mParams);
+        tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), mPy);
+        // One of the irritating things about LLProcess is that
+        // there's no API to wait for the child to terminate -- but given
+        // its use in our graphics-intensive interactive viewer, it's
+        // understandable.
+        while (mPy->isRunning())
+        {
+            sleep(1);
+        }
+    }
+
+    /**
+     * Run a Python script using LLProcess, expecting that it will
+     * write to the file passed as its sys.argv[1]. Retrieve that output.
+     *
+     * Until January 2012, LLProcess provided distressingly few
+     * mechanisms for a child process to communicate back to its caller --
+     * not even its return code. We've introduced a convention by which we
+     * create an empty temp file, pass the name of that file to our child
+     * as sys.argv[1] and expect the script to write its output to that
+     * file. This function implements the C++ (parent process) side of
+     * that convention.
+     */
+    std::string run_read()
+    {
+        NamedTempFile out("out", ""); // placeholder
+        // pass name of this temporary file to the script
+        mParams["args"].append(out.getName());
+        run();
+        // assuming the script wrote to that file, read it
+        return readfile(out.getName(), STRINGIZE("from " << mDesc << " script"));
+    }
+
+    LLSD mParams;
+    LLProcessPtr mPy;
+    std::string mDesc;
+    NamedTempFile mScript;
+};
+
+/// convenience function for PythonProcessLauncher::run()
+template <typename CONTENT>
+static void python(const std::string& desc, const CONTENT& script)
+{
+    PythonProcessLauncher py(desc, script);
+    py.run();
+}
+
+/// convenience function for PythonProcessLauncher::run_read()
+template <typename CONTENT>
+static std::string python_out(const std::string& desc, const CONTENT& script)
+{
+    PythonProcessLauncher py(desc, script);
+    return py.run_read();
+}
+
+/// Create a temporary directory and clean it up later.
+class NamedTempDir: public boost::noncopyable
+{
+public:
+    // Use python() function to create a temp directory: I've found
+    // nothing in either Boost.Filesystem or APR quite like Python's
+    // tempfile.mkdtemp().
+    // Special extra bonus: on Mac, mkdtemp() reports a pathname
+    // starting with /var/folders/something, whereas that's really a
+    // symlink to /private/var/folders/something. Have to use
+    // realpath() to compare properly.
+    NamedTempDir():
+        mPath(python_out("mkdtemp()",
+                         "from __future__ import with_statement\n"
+                         "import os.path, sys, tempfile\n"
+                         "with open(sys.argv[1], 'w') as f:\n"
+                         "    f.write(os.path.realpath(tempfile.mkdtemp()))\n"))
+    {}
+
+    ~NamedTempDir()
+    {
+        aprchk(apr_dir_remove(mPath.c_str(), gAPRPoolp));
+    }
+
+    std::string getName() const { return mPath; }
+
+private:
+    std::string mPath;
+};
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct llprocess_data
+    {
+        LLAPRPool pool;
+    };
+    typedef test_group<llprocess_data> llprocess_group;
+    typedef llprocess_group::object object;
+    llprocess_group llprocessgrp("llprocess");
+
+    struct Item
+    {
+        Item(): tries(0) {}
+        unsigned    tries;
+        std::string which;
+        std::string what;
+    };
+
+/*==========================================================================*|
+#define tabent(symbol) { symbol, #symbol }
+    static struct ReasonCode
+    {
+        int code;
+        const char* name;
+    } reasons[] =
+    {
+        tabent(APR_OC_REASON_DEATH),
+        tabent(APR_OC_REASON_UNWRITABLE),
+        tabent(APR_OC_REASON_RESTART),
+        tabent(APR_OC_REASON_UNREGISTER),
+        tabent(APR_OC_REASON_LOST),
+        tabent(APR_OC_REASON_RUNNING)
+    };
+#undef tabent
+|*==========================================================================*/
+
+    struct WaitInfo
+    {
+        WaitInfo(apr_proc_t* child_):
+            child(child_),
+            rv(-1),                 // we haven't yet called apr_proc_wait()
+            rc(0),
+            why(apr_exit_why_e(0))
+        {}
+        apr_proc_t* child;          // which subprocess
+        apr_status_t rv;            // return from apr_proc_wait()
+        int rc;                     // child's exit code
+        apr_exit_why_e why;         // APR_PROC_EXIT, APR_PROC_SIGNAL, APR_PROC_SIGNAL_CORE
+    };
+
+    void child_status_callback(int reason, void* data, int status)
+    {
+/*==========================================================================*|
+        std::string reason_str;
+        BOOST_FOREACH(const ReasonCode& rcp, reasons)
+        {
+            if (reason == rcp.code)
+            {
+                reason_str = rcp.name;
+                break;
+            }
+        }
+        if (reason_str.empty())
+        {
+            reason_str = STRINGIZE("unknown reason " << reason);
+        }
+        std::cout << "child_status_callback(" << reason_str << ")\n";
+|*==========================================================================*/
+
+        if (reason == APR_OC_REASON_DEATH || reason == APR_OC_REASON_LOST)
+        {
+            // Somewhat oddly, APR requires that you explicitly unregister
+            // even when it already knows the child has terminated.
+            apr_proc_other_child_unregister(data);
+
+            WaitInfo* wi(static_cast<WaitInfo*>(data));
+            // It's just wrong to call apr_proc_wait() here. The only way APR
+            // knows to call us with APR_OC_REASON_DEATH is that it's already
+            // reaped this child process, so calling wait() will only produce
+            // "huh?" from the OS. We must rely on the status param passed in,
+            // which unfortunately comes straight from the OS wait() call.
+//          wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
+            wi->rv = APR_CHILD_DONE; // fake apr_proc_wait() results
+#if defined(LL_WINDOWS)
+            wi->why = APR_PROC_EXIT;
+            wi->rc  = status;         // no encoding on Windows (no signals)
+#else  // Posix
+            if (WIFEXITED(status))
+            {
+                wi->why = APR_PROC_EXIT;
+                wi->rc  = WEXITSTATUS(status);
+            }
+            else if (WIFSIGNALED(status))
+            {
+                wi->why = APR_PROC_SIGNAL;
+                wi->rc  = WTERMSIG(status);
+            }
+            else                    // uh, shouldn't happen?
+            {
+                wi->why = APR_PROC_EXIT;
+                wi->rc  = status;   // someone else will have to decode
+            }
+#endif // Posix
+        }
+    }
+
+    template<> template<>
+    void object::test<1>()
+    {
+        set_test_name("raw APR nonblocking I/O");
+
+        // Create a script file in a temporary place.
+        NamedTempFile script("py",
+            "import sys" EOL
+            "import time" EOL
+            EOL
+            "time.sleep(2)" EOL
+            "print >>sys.stdout, 'stdout after wait'" EOL
+            "sys.stdout.flush()" EOL
+            "time.sleep(2)" EOL
+            "print >>sys.stderr, 'stderr after wait'" EOL
+            "sys.stderr.flush()" EOL
+            );
+
+        // Arrange to track the history of our interaction with child: what we
+        // fetched, which pipe it came from, how many tries it took before we
+        // got it.
+        std::vector<Item> history;
+        history.push_back(Item());
+
+        // Run the child process.
+        apr_procattr_t *procattr = NULL;
+        aprchk(apr_procattr_create(&procattr, pool.getAPRPool()));
+        aprchk(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK));
+        aprchk(apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH));
+
+        std::vector<const char*> argv;
+        apr_proc_t child;
+        argv.push_back("python");
+        // Have to have a named copy of this std::string so its c_str() value
+        // will persist.
+        std::string scriptname(script.getName());
+        argv.push_back(scriptname.c_str());
+        argv.push_back(NULL);
+
+        aprchk(apr_proc_create(&child, argv[0],
+                               &argv[0],
+                               NULL, // if we wanted to pass explicit environment
+                               procattr,
+                               pool.getAPRPool()));
+
+        // We do not want this child process to outlive our APR pool. On
+        // destruction of the pool, forcibly kill the process. Tell APR to try
+        // SIGTERM and wait 3 seconds. If that didn't work, use SIGKILL.
+        apr_pool_note_subprocess(pool.getAPRPool(), &child, APR_KILL_AFTER_TIMEOUT);
+
+        // arrange to call child_status_callback()
+        WaitInfo wi(&child);
+        apr_proc_other_child_register(&child, child_status_callback, &wi, child.in, pool.getAPRPool());
+
+        // TODO:
+        // Stuff child.in until it (would) block to verify EWOULDBLOCK/EAGAIN.
+        // Have child script clear it later, then write one more line to prove
+        // that it gets through.
+
+        // Monitor two different output pipes. Because one will be closed
+        // before the other, keep them in a list so we can drop whichever of
+        // them is closed first.
+        typedef std::pair<std::string, apr_file_t*> DescFile;
+        typedef std::list<DescFile> DescFileList;
+        DescFileList outfiles;
+        outfiles.push_back(DescFile("out", child.out));
+        outfiles.push_back(DescFile("err", child.err));
+
+        while (! outfiles.empty())
+        {
+            // This peculiar for loop is designed to let us erase(dfli). With
+            // a list, that invalidates only dfli itself -- but even so, we
+            // lose the ability to increment it for the next item. So at the
+            // top of every loop, while dfli is still valid, increment
+            // dflnext. Then before the next iteration, set dfli to dflnext.
+            for (DescFileList::iterator
+                     dfli(outfiles.begin()), dflnext(outfiles.begin()), dflend(outfiles.end());
+                 dfli != dflend; dfli = dflnext)
+            {
+                // Only valid to increment dflnext once we're sure it's not
+                // already at dflend.
+                ++dflnext;
+
+                char buf[4096];
+
+                apr_status_t rv = apr_file_gets(buf, sizeof(buf), dfli->second);
+                if (APR_STATUS_IS_EOF(rv))
+                {
+//                  std::cout << "(EOF on " << dfli->first << ")\n";
+//                  history.back().which = dfli->first;
+//                  history.back().what  = "*eof*";
+//                  history.push_back(Item());
+                    outfiles.erase(dfli);
+                    continue;
+                }
+                if (rv == EWOULDBLOCK || rv == EAGAIN)
+                {
+//                  std::cout << "(waiting; apr_file_gets(" << dfli->first << ") => " << rv << ": " << manager.strerror(rv) << ")\n";
+                    ++history.back().tries;
+                    continue;
+                }
+                aprchk_("apr_file_gets(buf, sizeof(buf), dfli->second)", rv);
+                // Is it even possible to get APR_SUCCESS but read 0 bytes?
+                // Hope not, but defend against that anyway.
+                if (buf[0])
+                {
+//                  std::cout << dfli->first << ": " << buf;
+                    history.back().which = dfli->first;
+                    history.back().what.append(buf);
+                    if (buf[strlen(buf) - 1] == '\n')
+                        history.push_back(Item());
+                    else
+                    {
+                        // Just for pretty output... if we only read a partial
+                        // line, terminate it.
+//                      std::cout << "...\n";
+                    }
+                }
+            }
+            // Do this once per tick, as we expect the viewer will
+            apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
+            sleep(1);
+        }
+        apr_file_close(child.in);
+        apr_file_close(child.out);
+        apr_file_close(child.err);
+
+        // Okay, we've broken the loop because our pipes are all closed. If we
+        // haven't yet called wait, give the callback one more chance. This
+        // models the fact that unlike this small test program, the viewer
+        // will still be running.
+        if (wi.rv == -1)
+        {
+            std::cout << "last gasp apr_proc_other_child_refresh_all()\n";
+            apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
+        }
+
+        if (wi.rv == -1)
+        {
+            std::cout << "child_status_callback(APR_OC_REASON_DEATH) wasn't called" << std::endl;
+            wi.rv = apr_proc_wait(wi.child, &wi.rc, &wi.why, APR_NOWAIT);
+        }
+//      std::cout << "child done: rv = " << rv << " (" << manager.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
+        aprchk_("apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT)", wi.rv, APR_CHILD_DONE);
+        ensure_equals_(wi.why, APR_PROC_EXIT);
+        ensure_equals_(wi.rc, 0);
+
+        // Beyond merely executing all the above successfully, verify that we
+        // obtained expected output -- and that we duly got control while
+        // waiting, proving the non-blocking nature of these pipes.
+        try
+        {
+            unsigned i = 0;
+            ensure("blocking I/O on child pipe (0)", history[i].tries);
+            ensure_equals_(history[i].which, "out");
+            ensure_equals_(history[i].what,  "stdout after wait" EOL);
+//          ++i;
+//          ensure_equals_(history[i].which, "out");
+//          ensure_equals_(history[i].what,  "*eof*");
+            ++i;
+            ensure("blocking I/O on child pipe (1)", history[i].tries);
+            ensure_equals_(history[i].which, "err");
+            ensure_equals_(history[i].what,  "stderr after wait" EOL);
+//          ++i;
+//          ensure_equals_(history[i].which, "err");
+//          ensure_equals_(history[i].what,  "*eof*");
+        }
+        catch (const failure&)
+        {
+            std::cout << "History:\n";
+            BOOST_FOREACH(const Item& item, history)
+            {
+                std::string what(item.what);
+                if ((! what.empty()) && what[what.length() - 1] == '\n')
+                {
+                    what.erase(what.length() - 1);
+                    if ((! what.empty()) && what[what.length() - 1] == '\r')
+                    {
+                        what.erase(what.length() - 1);
+                        what.append("\\r");
+                    }
+                    what.append("\\n");
+                }
+                std::cout << "  " << item.which << ": '" << what << "' ("
+                          << item.tries << " tries)\n";
+            }
+            std::cout << std::flush;
+            // re-raise same error; just want to enrich the output
+            throw;
+        }
+    }
+
+    template<> template<>
+    void object::test<2>()
+    {
+        set_test_name("setWorkingDirectory()");
+        // We want to test setWorkingDirectory(). But what directory is
+        // guaranteed to exist on every machine, under every OS? Have to
+        // create one. Naturally, ensure we clean it up when done.
+        NamedTempDir tempdir;
+        PythonProcessLauncher py("getcwd()",
+                                 "from __future__ import with_statement\n"
+                                 "import os, sys\n"
+                                 "with open(sys.argv[1], 'w') as f:\n"
+                                 "    f.write(os.getcwd())\n");
+        // Before running, call setWorkingDirectory()
+        py.mParams["cwd"] = tempdir.getName();
+        ensure_equals("os.getcwd()", py.run_read(), tempdir.getName());
+    }
+
+    template<> template<>
+    void object::test<3>()
+    {
+        set_test_name("arguments");
+        PythonProcessLauncher py("args",
+                                 "from __future__ import with_statement\n"
+                                 "import sys\n"
+                                 // note nonstandard output-file arg!
+                                 "with open(sys.argv[3], 'w') as f:\n"
+                                 "    for arg in sys.argv[1:]:\n"
+                                 "        print >>f, arg\n");
+        // We expect that PythonProcessLauncher has already appended
+        // its own NamedTempFile to mParams["args"] (sys.argv[0]).
+        py.mParams["args"].append("first arg");          // sys.argv[1]
+        py.mParams["args"].append("second arg");         // sys.argv[2]
+        // run_read() appends() one more argument, hence [3]
+        std::string output(py.run_read());
+        boost::split_iterator<std::string::const_iterator>
+            li(output, boost::first_finder("\n")), lend;
+        ensure("didn't get first arg", li != lend);
+        std::string arg(li->begin(), li->end());
+        ensure_equals(arg, "first arg");
+        ++li;
+        ensure("didn't get second arg", li != lend);
+        arg.assign(li->begin(), li->end());
+        ensure_equals(arg, "second arg");
+        ++li;
+        ensure("didn't get output filename?!", li != lend);
+        arg.assign(li->begin(), li->end());
+        ensure("output filename empty?!", ! arg.empty());
+        ++li;
+        ensure("too many args", li == lend);
+    }
+
+    template<> template<>
+    void object::test<4>()
+    {
+        set_test_name("explicit kill()");
+        PythonProcessLauncher py("kill()",
+                                 "from __future__ import with_statement\n"
+                                 "import sys, time\n"
+                                 "with open(sys.argv[1], 'w') as f:\n"
+                                 "    f.write('ok')\n"
+                                 "# now sleep; expect caller to kill\n"
+                                 "time.sleep(120)\n"
+                                 "# if caller hasn't managed to kill by now, bad\n"
+                                 "with open(sys.argv[1], 'w') as f:\n"
+                                 "    f.write('bad')\n");
+        NamedTempFile out("out", "not started");
+        py.mParams["args"].append(out.getName());
+        py.mPy = LLProcess::create(py.mParams);
+        ensure("couldn't launch kill() script", py.mPy);
+        // Wait for the script to wake up and do its first write
+        int i = 0, timeout = 60;
+        for ( ; i < timeout; ++i)
+        {
+            sleep(1);
+            if (readfile(out.getName(), "from kill() script") == "ok")
+                break;
+        }
+        // If we broke this loop because of the counter, something's wrong
+        ensure("script never started", i < timeout);
+        // script has performed its first write and should now be sleeping.
+        py.mPy->kill();
+        // wait for the script to terminate... one way or another.
+        while (py.mPy->isRunning())
+        {
+            sleep(1);
+        }
+        // If kill() failed, the script would have woken up on its own and
+        // overwritten the file with 'bad'. But if kill() succeeded, it should
+        // not have had that chance.
+        ensure_equals("kill() script output", readfile(out.getName()), "ok");
+    }
+
+    template<> template<>
+    void object::test<5>()
+    {
+        set_test_name("implicit kill()");
+        NamedTempFile out("out", "not started");
+        LLProcess::id pid(0);
+        {
+            PythonProcessLauncher py("kill()",
+                                     "from __future__ import with_statement\n"
+                                     "import sys, time\n"
+                                     "with open(sys.argv[1], 'w') as f:\n"
+                                     "    f.write('ok')\n"
+                                     "# now sleep; expect caller to kill\n"
+                                     "time.sleep(120)\n"
+                                     "# if caller hasn't managed to kill by now, bad\n"
+                                     "with open(sys.argv[1], 'w') as f:\n"
+                                     "    f.write('bad')\n");
+            py.mParams["args"].append(out.getName());
+            py.mPy = LLProcess::create(py.mParams);
+            ensure("couldn't launch kill() script", py.mPy);
+            // Capture id for later
+            pid = py.mPy->getProcessID();
+            // Wait for the script to wake up and do its first write
+            int i = 0, timeout = 60;
+            for ( ; i < timeout; ++i)
+            {
+                sleep(1);
+                if (readfile(out.getName(), "from kill() script") == "ok")
+                    break;
+            }
+            // If we broke this loop because of the counter, something's wrong
+            ensure("script never started", i < timeout);
+            // Script has performed its first write and should now be sleeping.
+            // Destroy the LLProcess, which should kill the child.
+        }
+        // wait for the script to terminate... one way or another.
+        while (LLProcess::isRunning(pid))
+        {
+            sleep(1);
+        }
+        // If kill() failed, the script would have woken up on its own and
+        // overwritten the file with 'bad'. But if kill() succeeded, it should
+        // not have had that chance.
+        ensure_equals("kill() script output", readfile(out.getName()), "ok");
+    }
+
+    template<> template<>
+    void object::test<6>()
+    {
+        set_test_name("autokill");
+        NamedTempFile from("from", "not started");
+        NamedTempFile to("to", "");
+        LLProcess::id pid(0);
+        {
+            PythonProcessLauncher py("autokill",
+                                     "from __future__ import with_statement\n"
+                                     "import sys, time\n"
+                                     "with open(sys.argv[1], 'w') as f:\n"
+                                     "    f.write('ok')\n"
+                                     "# wait for 'go' from test program\n"
+                                     "for i in xrange(60):\n"
+                                     "    time.sleep(1)\n"
+                                     "    with open(sys.argv[2]) as f:\n"
+                                     "        go = f.read()\n"
+                                     "    if go == 'go':\n"
+                                     "        break\n"
+                                     "else:\n"
+                                     "    with open(sys.argv[1], 'w') as f:\n"
+                                     "        f.write('never saw go')\n"
+                                     "    sys.exit(1)\n"
+                                     "# okay, saw 'go', write 'ack'\n"
+                                     "with open(sys.argv[1], 'w') as f:\n"
+                                     "    f.write('ack')\n");
+            py.mParams["args"].append(from.getName());
+            py.mParams["args"].append(to.getName());
+            py.mParams["autokill"] = false;
+            py.mPy = LLProcess::create(py.mParams);
+            ensure("couldn't launch kill() script", py.mPy);
+            // Capture id for later
+            pid = py.mPy->getProcessID();
+            // Wait for the script to wake up and do its first write
+            int i = 0, timeout = 60;
+            for ( ; i < timeout; ++i)
+            {
+                sleep(1);
+                if (readfile(from.getName(), "from autokill script") == "ok")
+                    break;
+            }
+            // If we broke this loop because of the counter, something's wrong
+            ensure("script never started", i < timeout);
+            // Now destroy the LLProcess, which should NOT kill the child!
+        }
+        // If the destructor killed the child anyway, give it time to die
+        sleep(2);
+        // How do we know it's not terminated? By making it respond to
+        // a specific stimulus in a specific way.
+        {
+            std::ofstream outf(to.getName().c_str());
+            outf << "go";
+        } // flush and close.
+        // now wait for the script to terminate... one way or another.
+        while (LLProcess::isRunning(pid))
+        {
+            sleep(1);
+        }
+        // If the LLProcess destructor implicitly called kill(), the
+        // script could not have written 'ack' as we expect.
+        ensure_equals("autokill script output", readfile(from.getName()), "ack");
+    }
+} // namespace tut
diff --git a/indra/llcommon/tests/llprocesslauncher_test.cpp b/indra/llcommon/tests/llprocesslauncher_test.cpp
deleted file mode 100644
index 057f83631e..0000000000
--- a/indra/llcommon/tests/llprocesslauncher_test.cpp
+++ /dev/null
@@ -1,718 +0,0 @@
-/**
- * @file   llprocesslauncher_test.cpp
- * @author Nat Goodspeed
- * @date   2011-12-19
- * @brief  Test for llprocesslauncher.
- * 
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Copyright (c) 2011, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-// Precompiled header
-#include "linden_common.h"
-// associated header
-#include "llprocesslauncher.h"
-// STL headers
-#include <vector>
-#include <list>
-// std headers
-#include <fstream>
-// external library headers
-#include "llapr.h"
-#include "apr_thread_proc.h"
-#include <boost/foreach.hpp>
-#include <boost/function.hpp>
-#include <boost/algorithm/string/find_iterator.hpp>
-#include <boost/algorithm/string/finder.hpp>
-//#include <boost/lambda/lambda.hpp>
-//#include <boost/lambda/bind.hpp>
-// other Linden headers
-#include "../test/lltut.h"
-#include "../test/manageapr.h"
-#include "../test/namedtempfile.h"
-#include "stringize.h"
-
-#if defined(LL_WINDOWS)
-#define sleep(secs) _sleep((secs) * 1000)
-#define EOL "\r\n"
-#else
-#define EOL "\n"
-#include <sys/wait.h>
-#endif
-
-//namespace lambda = boost::lambda;
-
-// static instance of this manages APR init/cleanup
-static ManageAPR manager;
-
-/*****************************************************************************
-*   Helpers
-*****************************************************************************/
-
-#define ensure_equals_(left, right) \
-        ensure_equals(STRINGIZE(#left << " != " << #right), (left), (right))
-
-#define aprchk(expr) aprchk_(#expr, (expr))
-static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
-{
-    tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << manager.strerror(rv)),
-                       rv, expected);
-}
-
-/**
- * Read specified file using std::getline(). It is assumed to be an error if
- * the file is empty: don't use this function if that's an acceptable case.
- * Last line will not end with '\n'; this is to facilitate the usual case of
- * string compares with a single line of output.
- * @param pathname The file to read.
- * @param desc Optional description of the file for error message;
- * defaults to "in <pathname>"
- */
-static std::string readfile(const std::string& pathname, const std::string& desc="")
-{
-    std::string use_desc(desc);
-    if (use_desc.empty())
-    {
-        use_desc = STRINGIZE("in " << pathname);
-    }
-    std::ifstream inf(pathname.c_str());
-    std::string output;
-    tut::ensure(STRINGIZE("No output " << use_desc), std::getline(inf, output));
-    std::string more;
-    while (std::getline(inf, more))
-    {
-        output += '\n' + more;
-    }
-    return output;
-}
-
-/**
- * Construct an LLProcessLauncher to run a Python script.
- */
-struct PythonProcessLauncher
-{
-    /**
-     * @param desc Arbitrary description for error messages
-     * @param script Python script, any form acceptable to NamedTempFile,
-     * typically either a std::string or an expression of the form
-     * (lambda::_1 << "script content with " << variable_data)
-     */
-    template <typename CONTENT>
-    PythonProcessLauncher(const std::string& desc, const CONTENT& script):
-        mDesc(desc),
-        mScript("py", script)
-    {
-        const char* PYTHON(getenv("PYTHON"));
-        tut::ensure("Set $PYTHON to the Python interpreter", PYTHON);
-
-        mPy.setExecutable(PYTHON);
-        mPy.addArgument(mScript.getName());
-    }
-
-    /// Run Python script and wait for it to complete.
-    void run()
-    {
-        tut::ensure_equals(STRINGIZE("Couldn't launch " << mDesc << " script"),
-                           mPy.launch(), 0);
-        // One of the irritating things about LLProcessLauncher is that
-        // there's no API to wait for the child to terminate -- but given
-        // its use in our graphics-intensive interactive viewer, it's
-        // understandable.
-        while (mPy.isRunning())
-        {
-            sleep(1);
-        }
-    }
-
-    /**
-     * Run a Python script using LLProcessLauncher, expecting that it will
-     * write to the file passed as its sys.argv[1]. Retrieve that output.
-     *
-     * Until January 2012, LLProcessLauncher provided distressingly few
-     * mechanisms for a child process to communicate back to its caller --
-     * not even its return code. We've introduced a convention by which we
-     * create an empty temp file, pass the name of that file to our child
-     * as sys.argv[1] and expect the script to write its output to that
-     * file. This function implements the C++ (parent process) side of
-     * that convention.
-     */
-    std::string run_read()
-    {
-        NamedTempFile out("out", ""); // placeholder
-        // pass name of this temporary file to the script
-        mPy.addArgument(out.getName());
-        run();
-        // assuming the script wrote to that file, read it
-        return readfile(out.getName(), STRINGIZE("from " << mDesc << " script"));
-    }
-
-    LLProcessLauncher mPy;
-    std::string mDesc;
-    NamedTempFile mScript;
-};
-
-/// convenience function for PythonProcessLauncher::run()
-template <typename CONTENT>
-static void python(const std::string& desc, const CONTENT& script)
-{
-    PythonProcessLauncher py(desc, script);
-    py.run();
-}
-
-/// convenience function for PythonProcessLauncher::run_read()
-template <typename CONTENT>
-static std::string python_out(const std::string& desc, const CONTENT& script)
-{
-    PythonProcessLauncher py(desc, script);
-    return py.run_read();
-}
-
-/// Create a temporary directory and clean it up later.
-class NamedTempDir: public boost::noncopyable
-{
-public:
-    // Use python() function to create a temp directory: I've found
-    // nothing in either Boost.Filesystem or APR quite like Python's
-    // tempfile.mkdtemp().
-    // Special extra bonus: on Mac, mkdtemp() reports a pathname
-    // starting with /var/folders/something, whereas that's really a
-    // symlink to /private/var/folders/something. Have to use
-    // realpath() to compare properly.
-    NamedTempDir():
-        mPath(python_out("mkdtemp()",
-                         "from __future__ import with_statement\n"
-                         "import os.path, sys, tempfile\n"
-                         "with open(sys.argv[1], 'w') as f:\n"
-                         "    f.write(os.path.realpath(tempfile.mkdtemp()))\n"))
-    {}
-
-    ~NamedTempDir()
-    {
-        aprchk(apr_dir_remove(mPath.c_str(), gAPRPoolp));
-    }
-
-    std::string getName() const { return mPath; }
-
-private:
-    std::string mPath;
-};
-
-/*****************************************************************************
-*   TUT
-*****************************************************************************/
-namespace tut
-{
-    struct llprocesslauncher_data
-    {
-        LLAPRPool pool;
-    };
-    typedef test_group<llprocesslauncher_data> llprocesslauncher_group;
-    typedef llprocesslauncher_group::object object;
-    llprocesslauncher_group llprocesslaunchergrp("llprocesslauncher");
-
-    struct Item
-    {
-        Item(): tries(0) {}
-        unsigned    tries;
-        std::string which;
-        std::string what;
-    };
-
-/*==========================================================================*|
-#define tabent(symbol) { symbol, #symbol }
-    static struct ReasonCode
-    {
-        int code;
-        const char* name;
-    } reasons[] =
-    {
-        tabent(APR_OC_REASON_DEATH),
-        tabent(APR_OC_REASON_UNWRITABLE),
-        tabent(APR_OC_REASON_RESTART),
-        tabent(APR_OC_REASON_UNREGISTER),
-        tabent(APR_OC_REASON_LOST),
-        tabent(APR_OC_REASON_RUNNING)
-    };
-#undef tabent
-|*==========================================================================*/
-
-    struct WaitInfo
-    {
-        WaitInfo(apr_proc_t* child_):
-            child(child_),
-            rv(-1),                 // we haven't yet called apr_proc_wait()
-            rc(0),
-            why(apr_exit_why_e(0))
-        {}
-        apr_proc_t* child;          // which subprocess
-        apr_status_t rv;            // return from apr_proc_wait()
-        int rc;                     // child's exit code
-        apr_exit_why_e why;         // APR_PROC_EXIT, APR_PROC_SIGNAL, APR_PROC_SIGNAL_CORE
-    };
-
-    void child_status_callback(int reason, void* data, int status)
-    {
-/*==========================================================================*|
-        std::string reason_str;
-        BOOST_FOREACH(const ReasonCode& rcp, reasons)
-        {
-            if (reason == rcp.code)
-            {
-                reason_str = rcp.name;
-                break;
-            }
-        }
-        if (reason_str.empty())
-        {
-            reason_str = STRINGIZE("unknown reason " << reason);
-        }
-        std::cout << "child_status_callback(" << reason_str << ")\n";
-|*==========================================================================*/
-
-        if (reason == APR_OC_REASON_DEATH || reason == APR_OC_REASON_LOST)
-        {
-            // Somewhat oddly, APR requires that you explicitly unregister
-            // even when it already knows the child has terminated.
-            apr_proc_other_child_unregister(data);
-
-            WaitInfo* wi(static_cast<WaitInfo*>(data));
-            // It's just wrong to call apr_proc_wait() here. The only way APR
-            // knows to call us with APR_OC_REASON_DEATH is that it's already
-            // reaped this child process, so calling wait() will only produce
-            // "huh?" from the OS. We must rely on the status param passed in,
-            // which unfortunately comes straight from the OS wait() call.
-//          wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
-            wi->rv = APR_CHILD_DONE; // fake apr_proc_wait() results
-#if defined(LL_WINDOWS)
-            wi->why = APR_PROC_EXIT;
-            wi->rc  = status;         // no encoding on Windows (no signals)
-#else  // Posix
-            if (WIFEXITED(status))
-            {
-                wi->why = APR_PROC_EXIT;
-                wi->rc  = WEXITSTATUS(status);
-            }
-            else if (WIFSIGNALED(status))
-            {
-                wi->why = APR_PROC_SIGNAL;
-                wi->rc  = WTERMSIG(status);
-            }
-            else                    // uh, shouldn't happen?
-            {
-                wi->why = APR_PROC_EXIT;
-                wi->rc  = status;   // someone else will have to decode
-            }
-#endif // Posix
-        }
-    }
-
-    template<> template<>
-    void object::test<1>()
-    {
-        set_test_name("raw APR nonblocking I/O");
-
-        // Create a script file in a temporary place.
-        NamedTempFile script("py",
-            "import sys" EOL
-            "import time" EOL
-            EOL
-            "time.sleep(2)" EOL
-            "print >>sys.stdout, 'stdout after wait'" EOL
-            "sys.stdout.flush()" EOL
-            "time.sleep(2)" EOL
-            "print >>sys.stderr, 'stderr after wait'" EOL
-            "sys.stderr.flush()" EOL
-            );
-
-        // Arrange to track the history of our interaction with child: what we
-        // fetched, which pipe it came from, how many tries it took before we
-        // got it.
-        std::vector<Item> history;
-        history.push_back(Item());
-
-        // Run the child process.
-        apr_procattr_t *procattr = NULL;
-        aprchk(apr_procattr_create(&procattr, pool.getAPRPool()));
-        aprchk(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK));
-        aprchk(apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH));
-
-        std::vector<const char*> argv;
-        apr_proc_t child;
-        argv.push_back("python");
-        // Have to have a named copy of this std::string so its c_str() value
-        // will persist.
-        std::string scriptname(script.getName());
-        argv.push_back(scriptname.c_str());
-        argv.push_back(NULL);
-
-        aprchk(apr_proc_create(&child, argv[0],
-                               &argv[0],
-                               NULL, // if we wanted to pass explicit environment
-                               procattr,
-                               pool.getAPRPool()));
-
-        // We do not want this child process to outlive our APR pool. On
-        // destruction of the pool, forcibly kill the process. Tell APR to try
-        // SIGTERM and wait 3 seconds. If that didn't work, use SIGKILL.
-        apr_pool_note_subprocess(pool.getAPRPool(), &child, APR_KILL_AFTER_TIMEOUT);
-
-        // arrange to call child_status_callback()
-        WaitInfo wi(&child);
-        apr_proc_other_child_register(&child, child_status_callback, &wi, child.in, pool.getAPRPool());
-
-        // TODO:
-        // Stuff child.in until it (would) block to verify EWOULDBLOCK/EAGAIN.
-        // Have child script clear it later, then write one more line to prove
-        // that it gets through.
-
-        // Monitor two different output pipes. Because one will be closed
-        // before the other, keep them in a list so we can drop whichever of
-        // them is closed first.
-        typedef std::pair<std::string, apr_file_t*> DescFile;
-        typedef std::list<DescFile> DescFileList;
-        DescFileList outfiles;
-        outfiles.push_back(DescFile("out", child.out));
-        outfiles.push_back(DescFile("err", child.err));
-
-        while (! outfiles.empty())
-        {
-            // This peculiar for loop is designed to let us erase(dfli). With
-            // a list, that invalidates only dfli itself -- but even so, we
-            // lose the ability to increment it for the next item. So at the
-            // top of every loop, while dfli is still valid, increment
-            // dflnext. Then before the next iteration, set dfli to dflnext.
-            for (DescFileList::iterator
-                     dfli(outfiles.begin()), dflnext(outfiles.begin()), dflend(outfiles.end());
-                 dfli != dflend; dfli = dflnext)
-            {
-                // Only valid to increment dflnext once we're sure it's not
-                // already at dflend.
-                ++dflnext;
-
-                char buf[4096];
-
-                apr_status_t rv = apr_file_gets(buf, sizeof(buf), dfli->second);
-                if (APR_STATUS_IS_EOF(rv))
-                {
-//                  std::cout << "(EOF on " << dfli->first << ")\n";
-//                  history.back().which = dfli->first;
-//                  history.back().what  = "*eof*";
-//                  history.push_back(Item());
-                    outfiles.erase(dfli);
-                    continue;
-                }
-                if (rv == EWOULDBLOCK || rv == EAGAIN)
-                {
-//                  std::cout << "(waiting; apr_file_gets(" << dfli->first << ") => " << rv << ": " << manager.strerror(rv) << ")\n";
-                    ++history.back().tries;
-                    continue;
-                }
-                aprchk_("apr_file_gets(buf, sizeof(buf), dfli->second)", rv);
-                // Is it even possible to get APR_SUCCESS but read 0 bytes?
-                // Hope not, but defend against that anyway.
-                if (buf[0])
-                {
-//                  std::cout << dfli->first << ": " << buf;
-                    history.back().which = dfli->first;
-                    history.back().what.append(buf);
-                    if (buf[strlen(buf) - 1] == '\n')
-                        history.push_back(Item());
-                    else
-                    {
-                        // Just for pretty output... if we only read a partial
-                        // line, terminate it.
-//                      std::cout << "...\n";
-                    }
-                }
-            }
-            // Do this once per tick, as we expect the viewer will
-            apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
-            sleep(1);
-        }
-        apr_file_close(child.in);
-        apr_file_close(child.out);
-        apr_file_close(child.err);
-
-        // Okay, we've broken the loop because our pipes are all closed. If we
-        // haven't yet called wait, give the callback one more chance. This
-        // models the fact that unlike this small test program, the viewer
-        // will still be running.
-        if (wi.rv == -1)
-        {
-            std::cout << "last gasp apr_proc_other_child_refresh_all()\n";
-            apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
-        }
-
-        if (wi.rv == -1)
-        {
-            std::cout << "child_status_callback(APR_OC_REASON_DEATH) wasn't called" << std::endl;
-            wi.rv = apr_proc_wait(wi.child, &wi.rc, &wi.why, APR_NOWAIT);
-        }
-//      std::cout << "child done: rv = " << rv << " (" << manager.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n';
-        aprchk_("apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT)", wi.rv, APR_CHILD_DONE);
-        ensure_equals_(wi.why, APR_PROC_EXIT);
-        ensure_equals_(wi.rc, 0);
-
-        // Beyond merely executing all the above successfully, verify that we
-        // obtained expected output -- and that we duly got control while
-        // waiting, proving the non-blocking nature of these pipes.
-        try
-        {
-            unsigned i = 0;
-            ensure("blocking I/O on child pipe (0)", history[i].tries);
-            ensure_equals_(history[i].which, "out");
-            ensure_equals_(history[i].what,  "stdout after wait" EOL);
-//          ++i;
-//          ensure_equals_(history[i].which, "out");
-//          ensure_equals_(history[i].what,  "*eof*");
-            ++i;
-            ensure("blocking I/O on child pipe (1)", history[i].tries);
-            ensure_equals_(history[i].which, "err");
-            ensure_equals_(history[i].what,  "stderr after wait" EOL);
-//          ++i;
-//          ensure_equals_(history[i].which, "err");
-//          ensure_equals_(history[i].what,  "*eof*");
-        }
-        catch (const failure&)
-        {
-            std::cout << "History:\n";
-            BOOST_FOREACH(const Item& item, history)
-            {
-                std::string what(item.what);
-                if ((! what.empty()) && what[what.length() - 1] == '\n')
-                {
-                    what.erase(what.length() - 1);
-                    if ((! what.empty()) && what[what.length() - 1] == '\r')
-                    {
-                        what.erase(what.length() - 1);
-                        what.append("\\r");
-                    }
-                    what.append("\\n");
-                }
-                std::cout << "  " << item.which << ": '" << what << "' ("
-                          << item.tries << " tries)\n";
-            }
-            std::cout << std::flush;
-            // re-raise same error; just want to enrich the output
-            throw;
-        }
-    }
-
-    template<> template<>
-    void object::test<2>()
-    {
-        set_test_name("set/getExecutable()");
-        LLProcessLauncher child;
-        child.setExecutable("nonsense string");
-        ensure_equals("setExecutable() 0", child.getExecutable(), "nonsense string");
-        child.setExecutable("python");
-        ensure_equals("setExecutable() 1", child.getExecutable(), "python");
-    }
-
-    template<> template<>
-    void object::test<3>()
-    {
-        set_test_name("setWorkingDirectory()");
-        // We want to test setWorkingDirectory(). But what directory is
-        // guaranteed to exist on every machine, under every OS? Have to
-        // create one. Naturally, ensure we clean it up when done.
-        NamedTempDir tempdir;
-        PythonProcessLauncher py("getcwd()",
-                                 "from __future__ import with_statement\n"
-                                 "import os, sys\n"
-                                 "with open(sys.argv[1], 'w') as f:\n"
-                                 "    f.write(os.getcwd())\n");
-        // Before running, call setWorkingDirectory()
-        py.mPy.setWorkingDirectory(tempdir.getName());
-        ensure_equals("os.getcwd()", py.run_read(), tempdir.getName());
-    }
-
-    template<> template<>
-    void object::test<4>()
-    {
-        set_test_name("clearArguments()");
-        PythonProcessLauncher py("args",
-                                 "from __future__ import with_statement\n"
-                                 "import sys\n"
-                                 // note nonstandard output-file arg!
-                                 "with open(sys.argv[3], 'w') as f:\n"
-                                 "    for arg in sys.argv[1:]:\n"
-                                 "        print >>f, arg\n");
-        // We expect that PythonProcessLauncher has already called
-        // addArgument() with the name of its own NamedTempFile. But let's
-        // change it up.
-        py.mPy.clearArguments();
-        // re-add script pathname
-        py.mPy.addArgument(py.mScript.getName()); // sys.argv[0]
-        py.mPy.addArgument("first arg");          // sys.argv[1]
-        py.mPy.addArgument("second arg");         // sys.argv[2]
-        // run_read() calls addArgument() one more time, hence [3]
-        std::string output(py.run_read());
-        boost::split_iterator<std::string::const_iterator>
-            li(output, boost::first_finder("\n")), lend;
-        ensure("didn't get first arg", li != lend);
-        std::string arg(li->begin(), li->end());
-        ensure_equals(arg, "first arg");
-        ++li;
-        ensure("didn't get second arg", li != lend);
-        arg.assign(li->begin(), li->end());
-        ensure_equals(arg, "second arg");
-        ++li;
-        ensure("didn't get output filename?!", li != lend);
-        arg.assign(li->begin(), li->end());
-        ensure("output filename empty?!", ! arg.empty());
-        ++li;
-        ensure("too many args", li == lend);
-    }
-
-    template<> template<>
-    void object::test<5>()
-    {
-        set_test_name("explicit kill()");
-        PythonProcessLauncher py("kill()",
-                                 "from __future__ import with_statement\n"
-                                 "import sys, time\n"
-                                 "with open(sys.argv[1], 'w') as f:\n"
-                                 "    f.write('ok')\n"
-                                 "# now sleep; expect caller to kill\n"
-                                 "time.sleep(120)\n"
-                                 "# if caller hasn't managed to kill by now, bad\n"
-                                 "with open(sys.argv[1], 'w') as f:\n"
-                                 "    f.write('bad')\n");
-        NamedTempFile out("out", "not started");
-        py.mPy.addArgument(out.getName());
-        ensure_equals("couldn't launch kill() script", py.mPy.launch(), 0);
-        // Wait for the script to wake up and do its first write
-        int i = 0, timeout = 60;
-        for ( ; i < timeout; ++i)
-        {
-            sleep(1);
-            if (readfile(out.getName(), "from kill() script") == "ok")
-                break;
-        }
-        // If we broke this loop because of the counter, something's wrong
-        ensure("script never started", i < timeout);
-        // script has performed its first write and should now be sleeping.
-        py.mPy.kill();
-        // wait for the script to terminate... one way or another.
-        while (py.mPy.isRunning())
-        {
-            sleep(1);
-        }
-        // If kill() failed, the script would have woken up on its own and
-        // overwritten the file with 'bad'. But if kill() succeeded, it should
-        // not have had that chance.
-        ensure_equals("kill() script output", readfile(out.getName()), "ok");
-    }
-
-    template<> template<>
-    void object::test<6>()
-    {
-        set_test_name("implicit kill()");
-        NamedTempFile out("out", "not started");
-        LLProcessLauncher::ll_pid_t pid(0);
-        {
-            PythonProcessLauncher py("kill()",
-                                     "from __future__ import with_statement\n"
-                                     "import sys, time\n"
-                                     "with open(sys.argv[1], 'w') as f:\n"
-                                     "    f.write('ok')\n"
-                                     "# now sleep; expect caller to kill\n"
-                                     "time.sleep(120)\n"
-                                     "# if caller hasn't managed to kill by now, bad\n"
-                                     "with open(sys.argv[1], 'w') as f:\n"
-                                     "    f.write('bad')\n");
-            py.mPy.addArgument(out.getName());
-            ensure_equals("couldn't launch kill() script", py.mPy.launch(), 0);
-            // Capture ll_pid_t for later
-            pid = py.mPy.getProcessID();
-            // Wait for the script to wake up and do its first write
-            int i = 0, timeout = 60;
-            for ( ; i < timeout; ++i)
-            {
-                sleep(1);
-                if (readfile(out.getName(), "from kill() script") == "ok")
-                    break;
-            }
-            // If we broke this loop because of the counter, something's wrong
-            ensure("script never started", i < timeout);
-            // Script has performed its first write and should now be sleeping.
-            // Destroy the LLProcessLauncher, which should kill the child.
-        }
-        // wait for the script to terminate... one way or another.
-        while (LLProcessLauncher::isRunning(pid))
-        {
-            sleep(1);
-        }
-        // If kill() failed, the script would have woken up on its own and
-        // overwritten the file with 'bad'. But if kill() succeeded, it should
-        // not have had that chance.
-        ensure_equals("kill() script output", readfile(out.getName()), "ok");
-    }
-
-    template<> template<>
-    void object::test<7>()
-    {
-        set_test_name("orphan()");
-        NamedTempFile from("from", "not started");
-        NamedTempFile to("to", "");
-        LLProcessLauncher::ll_pid_t pid(0);
-        {
-            PythonProcessLauncher py("orphan()",
-                                     "from __future__ import with_statement\n"
-                                     "import sys, time\n"
-                                     "with open(sys.argv[1], 'w') as f:\n"
-                                     "    f.write('ok')\n"
-                                     "# wait for 'go' from test program\n"
-                                     "for i in xrange(60):\n"
-                                     "    time.sleep(1)\n"
-                                     "    with open(sys.argv[2]) as f:\n"
-                                     "        go = f.read()\n"
-                                     "    if go == 'go':\n"
-                                     "        break\n"
-                                     "else:\n"
-                                     "    with open(sys.argv[1], 'w') as f:\n"
-                                     "        f.write('never saw go')\n"
-                                     "    sys.exit(1)\n"
-                                     "# okay, saw 'go', write 'ack'\n"
-                                     "with open(sys.argv[1], 'w') as f:\n"
-                                     "    f.write('ack')\n");
-            py.mPy.addArgument(from.getName());
-            py.mPy.addArgument(to.getName());
-            ensure_equals("couldn't launch kill() script", py.mPy.launch(), 0);
-            // Capture ll_pid_t for later
-            pid = py.mPy.getProcessID();
-            // Wait for the script to wake up and do its first write
-            int i = 0, timeout = 60;
-            for ( ; i < timeout; ++i)
-            {
-                sleep(1);
-                if (readfile(from.getName(), "from orphan() script") == "ok")
-                    break;
-            }
-            // If we broke this loop because of the counter, something's wrong
-            ensure("script never started", i < timeout);
-            // Script has performed its first write and should now be waiting
-            // for us. Orphan it.
-            py.mPy.orphan();
-            // Now destroy the LLProcessLauncher, which should NOT kill the child!
-        }
-        // If the destructor killed the child anyway, give it time to die
-        sleep(2);
-        // How do we know it's not terminated? By making it respond to
-        // a specific stimulus in a specific way.
-        {
-            std::ofstream outf(to.getName().c_str());
-            outf << "go";
-        } // flush and close.
-        // now wait for the script to terminate... one way or another.
-        while (LLProcessLauncher::isRunning(pid))
-        {
-            sleep(1);
-        }
-        // If the LLProcessLauncher destructor implicitly called kill(), the
-        // script could not have written 'ack' as we expect.
-        ensure_equals("orphan() script output", readfile(from.getName()), "ack");
-    }
-} // namespace tut
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 4359e9afb9..7756ba6226 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -40,7 +40,7 @@ typedef U32 uint32_t;
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
-#include "llprocesslauncher.h"
+#include "llprocess.h"
 #endif
 
 #include "boost/range.hpp"
@@ -1557,14 +1557,15 @@ namespace tut
             }
 
 #else  // LL_DARWIN, LL_LINUX
-            LLProcessLauncher py;
-            py.setExecutable(PYTHON);
-            py.addArgument(scriptfile.getName());
-            ensure_equals(STRINGIZE("Couldn't launch " << desc << " script"), py.launch(), 0);
+            LLSD params;
+            params["executable"] = PYTHON;
+            params["args"].append(scriptfile.getName());
+            LLProcessPtr py(LLProcess::create(params));
+            ensure(STRINGIZE("Couldn't launch " << desc << " script"), py);
             // Implementing timeout would mean messing with alarm() and
             // catching SIGALRM... later maybe...
             int status(0);
-            if (waitpid(py.getProcessID(), &status, 0) == -1)
+            if (waitpid(py->getProcessID(), &status, 0) == -1)
             {
                 int waitpid_errno(errno);
                 ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: "
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 110fac0f23..9b225cabb8 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -31,6 +31,7 @@
 #include "llpluginprocessparent.h"
 #include "llpluginmessagepipe.h"
 #include "llpluginmessageclasses.h"
+#include "stringize.h"
 
 #include "llapr.h"
 
@@ -134,7 +135,10 @@ LLPluginProcessParent::~LLPluginProcessParent()
 		mSharedMemoryRegions.erase(iter);
 	}
 	
-	mProcess.kill();
+	if (mProcess)
+	{
+		mProcess->kill();
+	}
 	killSockets();
 }
 
@@ -159,8 +163,8 @@ void LLPluginProcessParent::errorState(void)
 
 void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
 {	
-	mProcess.setExecutable(launcher_filename);
-	mProcess.setWorkingDirectory(plugin_dir);
+	mProcessParams["executable"] = launcher_filename;
+	mProcessParams["cwd"] = plugin_dir;
 	mPluginFile = plugin_filename;
 	mPluginDir = plugin_dir;
 	mCPUUsage = 0.0f;
@@ -371,10 +375,8 @@ void LLPluginProcessParent::idle(void)
 				// Launch the plugin process.
 				
 				// Only argument to the launcher is the port number we're listening on
-				std::stringstream stream;
-				stream << mBoundPort;
-				mProcess.addArgument(stream.str());
-				if(mProcess.launch() != 0)
+				mProcessParams["args"].append(stringize(mBoundPort));
+				if (! (mProcess = LLProcess::create(mProcessParams)))
 				{
 					errorState();
 				}
@@ -388,19 +390,18 @@ void LLPluginProcessParent::idle(void)
 						// The command we're constructing would look like this on the command line:
 						// osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
 
-						std::stringstream cmd;
-						
-						mDebugger.setExecutable("/usr/bin/osascript");
-						mDebugger.addArgument("-e");
-						mDebugger.addArgument("tell application \"Terminal\"");
-						mDebugger.addArgument("-e");
-						cmd << "set win to do script \"gdb -pid " << mProcess.getProcessID() << "\"";
-						mDebugger.addArgument(cmd.str());
-						mDebugger.addArgument("-e");
-						mDebugger.addArgument("do script \"continue\" in win");
-						mDebugger.addArgument("-e");
-						mDebugger.addArgument("end tell");
-						mDebugger.launch();
+						LLSD params;
+						params["executable"] = "/usr/bin/osascript";
+						params["args"].append("-e");
+						params["args"].append("tell application \"Terminal\"");
+						params["args"].append("-e");
+						params["args"].append(STRINGIZE("set win to do script \"gdb -pid "
+														<< mProcess->getProcessID() << "\""));
+						params["args"].append("-e");
+						params["args"].append("do script \"continue\" in win");
+						params["args"].append("-e");
+						params["args"].append("end tell");
+						mDebugger = LLProcess::create(params);
 
 						#endif
 					}
@@ -470,7 +471,7 @@ void LLPluginProcessParent::idle(void)
 			break;
 			
 			case STATE_EXITING:
-				if(!mProcess.isRunning())
+				if (! mProcess->isRunning())
 				{
 					setState(STATE_CLEANUP);
 				}
@@ -498,7 +499,7 @@ void LLPluginProcessParent::idle(void)
 			break;
 			
 			case STATE_CLEANUP:
-				mProcess.kill();
+				mProcess->kill();
 				killSockets();
 				setState(STATE_DONE);
 			break;
@@ -1077,7 +1078,7 @@ bool LLPluginProcessParent::pluginLockedUpOrQuit()
 {
 	bool result = false;
 	
-	if(!mProcess.isRunning())
+	if (! mProcess->isRunning())
 	{
 		LL_WARNS("Plugin") << "child exited" << LL_ENDL;
 		result = true;
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index c66723f175..e8bcba75e0 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -30,13 +30,14 @@
 #define LL_LLPLUGINPROCESSPARENT_H
 
 #include "llapr.h"
-#include "llprocesslauncher.h"
+#include "llprocess.h"
 #include "llpluginmessage.h"
 #include "llpluginmessagepipe.h"
 #include "llpluginsharedmemory.h"
 
 #include "lliosocket.h"
 #include "llthread.h"
+#include "llsd.h"
 
 class LLPluginProcessParentOwner
 {
@@ -148,8 +149,9 @@ private:
 	LLSocket::ptr_t mListenSocket;
 	LLSocket::ptr_t mSocket;
 	U32 mBoundPort;
-	
-	LLProcessLauncher mProcess;
+
+	LLSD mProcessParams;
+	LLProcessPtr mProcess;
 	
 	std::string mPluginFile;
 	std::string mPluginDir;
@@ -171,7 +173,7 @@ private:
 	bool mBlocked;
 	bool mPolledInput;
 
-	LLProcessLauncher mDebugger;
+	LLProcessPtr mDebugger;
 	
 	F32 mPluginLaunchTimeout;		// Somewhat longer timeout for initial launch.
 	F32 mPluginLockupTimeout;		// If we don't receive a heartbeat in this many seconds, we declare the plugin locked up.
diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp
index ed1d7e860a..ba58cd8067 100644
--- a/indra/newview/llexternaleditor.cpp
+++ b/indra/newview/llexternaleditor.cpp
@@ -29,6 +29,9 @@
 
 #include "lltrans.h"
 #include "llui.h"
+#include "llprocess.h"
+#include "llsdutil.h"
+#include <boost/foreach.hpp>
 
 // static
 const std::string LLExternalEditor::sFilenameMarker = "%s";
@@ -45,19 +48,8 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env
 		return EC_NOT_SPECIFIED;
 	}
 
-	// Add the filename marker if missing.
-	if (cmd.find(sFilenameMarker) == std::string::npos)
-	{
-		cmd += " \"" + sFilenameMarker + "\"";
-		llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl;
-	}
-
 	string_vec_t tokens;
-	if (tokenize(tokens, cmd) < 2) // 2 = bin + at least one arg (%s)
-	{
-		llwarns << "Error parsing editor command" << llendl;
-		return EC_PARSE_ERROR;
-	}
+	tokenize(tokens, cmd);
 
 	// Check executable for existence.
 	std::string bin_path = tokens[0];
@@ -68,51 +60,60 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env
 	}
 
 	// Save command.
-	mProcess.setExecutable(bin_path);
-	mArgs.clear();
+	mProcessParams["executable"] = bin_path;
+	mProcessParams["args"].clear();
 	for (size_t i = 1; i < tokens.size(); ++i)
 	{
-		if (i > 1) mArgs += " ";
-		mArgs += "\"" + tokens[i] + "\"";
+		mProcessParams["args"].append(tokens[i]);
+	}
+
+	// Add the filename marker if missing.
+	if (cmd.find(sFilenameMarker) == std::string::npos)
+	{
+		mProcessParams["args"].append(sFilenameMarker);
+		llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl;
+	}
+
+	llinfos << "Setting command [" << bin_path;
+	BOOST_FOREACH(const std::string& arg, llsd::inArray(mProcessParams["args"]))
+	{
+		llcont << " \"" << arg << "\"";
 	}
-	llinfos << "Setting command [" << bin_path << " " << mArgs << "]" << llendl;
+	llcont << "]" << llendl;
 
 	return EC_SUCCESS;
 }
 
 LLExternalEditor::EErrorCode LLExternalEditor::run(const std::string& file_path)
 {
-	std::string args = mArgs;
-	if (mProcess.getExecutable().empty() || args.empty())
+	if (mProcessParams["executable"].asString().empty() || ! mProcessParams["args"].size())
 	{
 		llwarns << "Editor command not set" << llendl;
 		return EC_NOT_SPECIFIED;
 	}
 
-	// Substitute the filename marker in the command with the actual passed file name.
-	LLStringUtil::replaceString(args, sFilenameMarker, file_path);
-
-	// Split command into separate tokens.
-	string_vec_t tokens;
-	tokenize(tokens, args);
+	// Copy params block so we can replace sFilenameMarker
+	LLSD params(mProcessParams);
 
-	// Set process arguments taken from the command.
-	mProcess.clearArguments();
-	for (string_vec_t::const_iterator arg_it = tokens.begin(); arg_it != tokens.end(); ++arg_it)
+	// Substitute the filename marker in the command with the actual passed file name.
+	LLSD& args(params["args"]);
+	for (LLSD::array_iterator ai(args.beginArray()), aend(args.endArray()); ai != aend; ++ai)
 	{
-		mProcess.addArgument(*arg_it);
+		std::string sarg(*ai);
+		LLStringUtil::replaceString(sarg, sFilenameMarker, file_path);
+		*ai = sarg;
 	}
 
 	// Run the editor.
-	llinfos << "Running editor command [" << mProcess.getExecutable() + " " + args << "]" << llendl;
-	int result = mProcess.launch();
-	if (result == 0)
+	llinfos << "Running editor command [" << params["executable"];
+	BOOST_FOREACH(const std::string& arg, llsd::inArray(params["args"]))
 	{
-		// Prevent killing the process in destructor (will add it to the zombies list).
-		mProcess.orphan();
+		llcont << " \"" << arg << "\"";
 	}
-
-	return result == 0 ? EC_SUCCESS : EC_FAILED_TO_RUN;
+	llcont << "]" << llendl;
+	// Prevent killing the process in destructor.
+	params["autokill"] = false;
+	return LLProcess::create(params) ? EC_SUCCESS : EC_FAILED_TO_RUN;
 }
 
 // static
diff --git a/indra/newview/llexternaleditor.h b/indra/newview/llexternaleditor.h
index ef5db56c6e..e81c360c24 100644
--- a/indra/newview/llexternaleditor.h
+++ b/indra/newview/llexternaleditor.h
@@ -27,7 +27,7 @@
 #ifndef LL_LLEXTERNALEDITOR_H
 #define LL_LLEXTERNALEDITOR_H
 
-#include <llprocesslauncher.h>
+#include "llsd.h"
 
 /**
  * Usage:
@@ -98,8 +98,7 @@ private:
 	static const std::string sSetting;
 
 
-	std::string			mArgs;
-	LLProcessLauncher	mProcess;
+	LLSD				mProcessParams;
 };
 
 #endif // LL_LLEXTERNALEDITOR_H
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index 84f23b3acc..e99fd0af7e 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -26,10 +26,10 @@
 #include "linden_common.h"
 #include <apr_file_io.h>
 #include "llapr.h"
-#include "llprocesslauncher.h"
+#include "llprocess.h"
 #include "llupdateinstaller.h"
 #include "lldir.h" 
-
+#include "llsd.h"
 
 #if defined(LL_WINDOWS)
 #pragma warning(disable: 4702)      // disable 'unreachable code' so we can use lexical_cast (really!).
@@ -78,15 +78,13 @@ int ll_install_update(std::string const & script,
 	llinfos << "UpdateInstaller: installing " << updatePath << " using " <<
 		actualScriptPath << LL_ENDL;
 	
-	LLProcessLauncher launcher;
-	launcher.setExecutable(actualScriptPath);
-	launcher.addArgument(updatePath);
-	launcher.addArgument(ll_install_failed_marker_path());
-	launcher.addArgument(boost::lexical_cast<std::string>(required));
-	int result = launcher.launch();
-	launcher.orphan();
-	
-	return result;
+	LLSD params;
+	params["executable"] = actualScriptPath;
+	params["args"].append(updatePath);
+	params["args"].append(ll_install_failed_marker_path());
+	params["args"].append(boost::lexical_cast<std::string>(required));
+	params["autokill"] = false;
+	return LLProcess::create(params)? 0 : -1;
 }
 
 
-- 
cgit v1.2.3


From c8a2f6515a47c625d97802bd9f7bd833be65fe2c Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 20 Jan 2012 16:10:32 -0800
Subject: EXP-1799 FIX -- Replace and Add to Outfit options appear as grayed
 out in Inventory

* Refactored LLFolderBridge::buildContextMenu fetch to clear and rebuild basic
  context menu options after the fetch rather than trying to merge the two.
---
 indra/newview/llinventorybridge.cpp | 86 +++++++++++++++++++++++--------------
 indra/newview/llinventorybridge.h   |  8 +++-
 2 files changed, 59 insertions(+), 35 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 97e61f4c99..472be8cf5c 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -519,6 +519,8 @@ void hide_context_entries(LLMenuGL& menu,
 			{
 				menu_item->setVisible(FALSE);
 			}
+
+			menu_item->setEnabled(FALSE);
 		}
 		else
 		{
@@ -601,13 +603,6 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 			{
 				items.push_back(std::string("Marketplace Separator"));
 
-				bool copyable = true;
-				LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID);
-				if (inv_item)
-				{
-					copyable = inv_item->getPermissions().allowCopyBy(gAgent.getID());
-				}
-
 				items.push_back(std::string("Merchant Copy"));
 				if (!canListOnMarketplaceNow())
 				{
@@ -1138,12 +1133,6 @@ bool LLInvFVBridge::canListOnMarketplace() const
 		return false;
 	}
 	
-	const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
-	if (outbox_id.isNull())
-	{
-		return false;
-	}
-
 	LLViewerInventoryItem * item = model->getItem(mUUID);
 	if (item)
 	{
@@ -2415,7 +2404,6 @@ public:
 		delete this;
 	}
 
-
 protected:
 	LLUUID mCatID;
 	bool mCopyItems;
@@ -2945,12 +2933,38 @@ void LLFolderBridge::staticFolderOptionsMenu()
 	LLFolderBridge* selfp = sSelf.get();
 	if (selfp)
 	{
-		selfp->folderOptionsMenu();
+		selfp->folderOptionsMenuAfterFetch();
 	}
 }
 
-void LLFolderBridge::folderOptionsMenu()
+void LLFolderBridge::folderOptionsMenuAfterFetch()
 {
+	const U32 flags = mContextMenuFlags;
+
+	mItems.clear();
+	mDisabledItems.clear();
+	mContextMenuFlags = 0x0;
+
+	LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get());
+	if (!menup) return;
+
+	// Reset the menu
+	{
+		const LLView::child_list_t *list = menup->getChildList();
+
+		LLView::child_list_t::const_iterator menu_itor;
+		for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor)
+		{
+			(*menu_itor)->setVisible(FALSE);
+			(*menu_itor)->pushVisible(TRUE);
+			(*menu_itor)->setEnabled(TRUE);
+		}
+	}
+
+	// Build basic menu back up
+	buildContextMenuBaseOptions(*menup, flags);
+
+	// Build folder specific options back up
 	LLInventoryModel* model = getInventoryModel();
 	if(!model) return;
 
@@ -3032,15 +3046,12 @@ void LLFolderBridge::folderOptionsMenu()
 		}
 		mItems.push_back(std::string("Outfit Separator"));
 	}
-	LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get());
-	if (menup)
-	{
-		hide_context_entries(*menup, mItems, mDisabledItems);
 
-		// Reposition the menu, in case we're adding items to an existing menu.
-		menup->needsArrange();
-		menup->arrangeAndClear();
-	}
+	hide_context_entries(*menup, mItems, mDisabledItems);
+
+	// Reposition the menu, in case we're adding items to an existing menu.
+	menup->needsArrange();
+	menup->arrangeAndClear();
 }
 
 BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
@@ -3055,17 +3066,11 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv
 	return ((item_array.count() > 0) ? TRUE : FALSE );
 }
 
-// Flags unused
-void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+void LLFolderBridge::buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags)
 {
-	mItems.clear();
-	mDisabledItems.clear();
-
-	lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
-
-//	menuentry_vec_t disabled_items;
 	LLInventoryModel* model = getInventoryModel();
-	if(!model) return;
+	llassert(model != NULL);
+
 	const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
 	const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
 
@@ -3186,6 +3191,21 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 			mDisabledItems.push_back(std::string("Share"));
 		}
 	}
+}
+
+// Flags unused
+void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+	mItems.clear();
+	mDisabledItems.clear();
+	mContextMenuFlags = flags;
+
+	lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
+
+	LLInventoryModel* model = getInventoryModel();
+	if(!model) return;
+
+	buildContextMenuBaseOptions(menu, flags);
 
 	hide_context_entries(menu, mItems, mDisabledItems);
 
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index cb378b7d7a..56301ce728 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -235,7 +235,8 @@ public:
 				   const LLUUID& uuid) :
 		LLInvFVBridge(inventory, root, uuid),
 		mCallingCards(FALSE),
-		mWearables(FALSE)
+		mWearables(FALSE),
+		mContextMenuFlags(0x0)
 	{}
 		
 	BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg);
@@ -282,6 +283,8 @@ public:
 	LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; }
 
 protected:
+	void buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags);
+
 	//--------------------------------------------------------------------
 	// Menu callbacks
 	//--------------------------------------------------------------------
@@ -317,7 +320,7 @@ protected:
 public:
 	static LLHandle<LLFolderBridge> sSelf;
 	static void staticFolderOptionsMenu();
-	void folderOptionsMenu();
+	void folderOptionsMenuAfterFetch();
 
 private:
 	BOOL				mCallingCards;
@@ -325,6 +328,7 @@ private:
 	LLHandle<LLView>	mMenu;
 	menuentry_vec_t		mItems;
 	menuentry_vec_t		mDisabledItems;
+	U32					mContextMenuFlags;
 	LLRootHandle<LLFolderBridge> mHandle;
 };
 
-- 
cgit v1.2.3


From 039cd701c4fa1dcc32bc63f57aab5a5f995f7498 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Fri, 20 Jan 2012 16:36:25 -0800
Subject: * Modified so "Copy" context menu option is not available for "no
 copy" items.

---
 indra/newview/llinventorybridge.cpp | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 472be8cf5c..bce3511c80 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1654,11 +1654,7 @@ BOOL LLItemBridge::isItemCopyable() const
 			return FALSE;
 		}
 
-		// All items can be copied in god mode since you can
-		// at least paste-as-link the item, though you 
-		// still may not be able paste the item.
-		return TRUE;
-		// return (item->getPermissions().allowCopyBy(gAgent.getID()));
+		return item->getPermissions().allowCopyBy(gAgent.getID()) || gSavedSettings.getBOOL("InventoryLinking");
 	}
 	return FALSE;
 }
@@ -1771,12 +1767,8 @@ BOOL LLFolderBridge::isUpToDate() const
 
 BOOL LLFolderBridge::isItemCopyable() const
 {
-	if (gSavedSettings.getBOOL("InventoryLinking"))
-	{
-		// Can copy folders to paste-as-link, but not for straight paste.
-		return TRUE;
-	}
-	return FALSE;
+	// Can copy folders to paste-as-link, but not for straight paste.
+	return gSavedSettings.getBOOL("InventoryLinking");
 }
 
 BOOL LLFolderBridge::copyToClipboard() const
-- 
cgit v1.2.3


From 6e214960ce203d1d50d7bd6bd04eedee3afd0fa3 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 20 Jan 2012 20:19:50 -0500
Subject: Define LLProcess::Params; accept create(const
 LLSDParamAdapter<Params>&). This allows callers to pass either LLSD formatted
 as before -- which all callers still do -- or an actual LLProcess::Params
 block.

---
 indra/llcommon/llprocess.cpp | 31 +++++++++++++------------------
 indra/llcommon/llprocess.h   | 33 +++++++++++++++++++++++++++------
 2 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 8c0caca680..dfb2ed69e9 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -26,7 +26,6 @@
 
 #include "linden_common.h"
 #include "llprocess.h"
-#include "llsd.h"
 #include "llsdserialize.h"
 #include "stringize.h"
 
@@ -41,7 +40,7 @@ struct LLProcessError: public std::runtime_error
 	LLProcessError(const std::string& msg): std::runtime_error(msg) {}
 };
 
-LLProcessPtr LLProcess::create(const LLSD& params)
+LLProcessPtr LLProcess::create(const LLSDParamAdapter<Params>& params)
 {
 	try
 	{
@@ -54,16 +53,13 @@ LLProcessPtr LLProcess::create(const LLSD& params)
 	}
 }
 
-LLProcess::LLProcess(const LLSD& params):
+LLProcess::LLProcess(const LLSDParamAdapter<Params>& params):
 	mProcessID(0),
-	mAutokill(params["autokill"].asBoolean())
+	mAutokill(params.autokill)
 {
-	// nonstandard default bool value
-	if (! params.has("autokill"))
-		mAutokill = true;
-	if (! params.has("executable"))
+	if (! params.validateBlock(true))
 	{
-		throw LLProcessError(STRINGIZE("not launched: missing 'executable'\n"
+		throw LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
 									   << LLSDNotationStreamer(params)));
 	}
 
@@ -108,14 +104,14 @@ static std::string quote(const std::string& str)
 	return result + "\"";
 }
 
-void LLProcess::launch(const LLSD& params)
+void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 {
 	PROCESS_INFORMATION pinfo;
 	STARTUPINFOA sinfo;
 	memset(&sinfo, 0, sizeof(sinfo));
 	
-	std::string args = quote(params["executable"]);
-	BOOST_FOREACH(const std::string& arg, llsd::inArray(params["args"]))
+	std::string args = quote(params.executable);
+	BOOST_FOREACH(const std::string& arg, params.args)
 	{
 		args += " ";
 		args += quote(arg);
@@ -128,7 +124,7 @@ void LLProcess::launch(const LLSD& params)
 
 	// Convert wrapper to a real std::string so we can use c_str(); but use a
 	// named variable instead of a temporary so c_str() pointer remains valid.
-	std::string cwd(params["cwd"]);
+	std::string cwd(params.cwd);
 	const char * working_directory = 0;
 	if (! cwd.empty())
 		working_directory = cwd.c_str();
@@ -212,7 +208,7 @@ static bool reap_pid(pid_t pid)
 	return false;
 }
 
-void LLProcess::launch(const LLSD& params)
+void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 {
 	// flush all buffers before the child inherits them
 	::fflush(NULL);
@@ -222,7 +218,7 @@ void LLProcess::launch(const LLSD& params)
 	{
 		// child process
 
-		std::string cwd(params["cwd"]);
+		std::string cwd(params.cwd);
 		if (! cwd.empty())
 		{
 			// change to the desired child working directory
@@ -239,12 +235,11 @@ void LLProcess::launch(const LLSD& params)
 		std::vector<const char*> fake_argv;
 
 		// add the executable path
-		std::string executable(params["executable"]);
+		std::string executable(params.executable);
 		fake_argv.push_back(executable.c_str());
 
 		// and any arguments
-		const LLSD& params_args(params["args"]);
-		std::vector<std::string> args(params_args.beginArray(), params_args.endArray());
+		std::vector<std::string> args(params.args.begin(), params.args.end());
 		BOOST_FOREACH(const std::string& arg, args)
 		{
 			fake_argv.push_back(arg.c_str());
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 9a74cfe829..9ea129baf2 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -27,6 +27,8 @@
 #ifndef LL_LLPROCESS_H
 #define LL_LLPROCESS_H
 
+#include "llinitparam.h"
+#include "llsdparam.h"
 #include <boost/shared_ptr.hpp>
 #include <boost/noncopyable.hpp>
 
@@ -35,8 +37,6 @@
 #include <windows.h>
 #endif
 
-class LLSD;
-
 class LLProcess;
 /// LLProcess instances are created on the heap by static factory methods and
 /// managed by ref-counted pointers.
@@ -50,17 +50,38 @@ class LL_COMMON_API LLProcess: public boost::noncopyable
 {
 	LOG_CLASS(LLProcess);
 public:
+	/// Param block definition
+	struct Params: public LLInitParam::Block<Params>
+	{
+		Params():
+			executable("executable"),
+			args("args"),
+			cwd("cwd"),
+			autokill("autokill", true)
+		{}
+
+		/// pathname of executable
+		Mandatory<std::string> executable;
+		/// zero or more additional command-line arguments
+		Multiple<std::string> args;
+		/// current working directory, if need it changed
+		Optional<std::string> cwd;
+		/// implicitly kill process on destruction of LLProcess object
+		Optional<bool> autokill;
+	};
 
 	/**
-	 * Factory accepting LLSD::Map.
+	 * Factory accepting either plain LLSD::Map or Params block.
 	 * MAY RETURN DEFAULT-CONSTRUCTED LLProcessPtr if params invalid!
 	 *
+	 * Redundant with Params definition above?
+	 *
 	 * executable (required, string):				executable pathname
 	 * args		  (optional, string array):			extra command-line arguments
 	 * cwd		  (optional, string, dft no chdir): change to this directory before executing
 	 * autokill	  (optional, bool, dft true):		implicit kill() on ~LLProcess
 	 */
-	static LLProcessPtr create(const LLSD& params);
+	static LLProcessPtr create(const LLSDParamAdapter<Params>& params);
 	virtual ~LLProcess();
 
 	// isRunning isn't const because, if child isn't running, it clears stored
@@ -96,8 +117,8 @@ public:
 	
 private:
 	/// constructor is private: use create() instead
-	LLProcess(const LLSD& params);
-	void launch(const LLSD& params);
+	LLProcess(const LLSDParamAdapter<Params>& params);
+	void launch(const LLSDParamAdapter<Params>& params);
 
 	id mProcessID;
 	bool mAutokill;
-- 
cgit v1.2.3


From 47d94757075e338c480ba4d7d24948242a85a9bb Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 21 Jan 2012 11:45:15 -0500
Subject: Convert LLProcess consumers from LLSD to LLProcess::Params block.
 Using a Params block gives compile-time checking against attribute typos. One
 might inadvertently set myLLSD["autofill"] = false and only discover it when
 things behave strangely at runtime; but trying to set myParams.autofill will
 produce a compile error. However, it's excellent that the same
 LLProcess::create() method can accept either LLProcess::Params or a
 properly-constructed LLSD block.

---
 indra/llcommon/tests/llprocess_test.cpp            | 26 ++++++++---------
 indra/llcommon/tests/llsdserialize_test.cpp        |  6 ++--
 indra/llplugin/llpluginprocessparent.cpp           | 28 +++++++++---------
 indra/llplugin/llpluginprocessparent.h             | 12 ++++----
 indra/newview/llexternaleditor.cpp                 | 33 ++++++++++++----------
 indra/newview/llexternaleditor.h                   |  5 ++--
 .../updater/llupdateinstaller.cpp                  | 12 ++++----
 7 files changed, 62 insertions(+), 60 deletions(-)

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 55e22abd81..405540e436 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -107,8 +107,8 @@ struct PythonProcessLauncher
         const char* PYTHON(getenv("PYTHON"));
         tut::ensure("Set $PYTHON to the Python interpreter", PYTHON);
 
-        mParams["executable"] = PYTHON;
-        mParams["args"].append(mScript.getName());
+        mParams.executable = PYTHON;
+        mParams.args.add(mScript.getName());
     }
 
     /// Run Python script and wait for it to complete.
@@ -142,13 +142,13 @@ struct PythonProcessLauncher
     {
         NamedTempFile out("out", ""); // placeholder
         // pass name of this temporary file to the script
-        mParams["args"].append(out.getName());
+        mParams.args.add(out.getName());
         run();
         // assuming the script wrote to that file, read it
         return readfile(out.getName(), STRINGIZE("from " << mDesc << " script"));
     }
 
-    LLSD mParams;
+    LLProcess::Params mParams;
     LLProcessPtr mPy;
     std::string mDesc;
     NamedTempFile mScript;
@@ -515,7 +515,7 @@ namespace tut
                                  "with open(sys.argv[1], 'w') as f:\n"
                                  "    f.write(os.getcwd())\n");
         // Before running, call setWorkingDirectory()
-        py.mParams["cwd"] = tempdir.getName();
+        py.mParams.cwd = tempdir.getName();
         ensure_equals("os.getcwd()", py.run_read(), tempdir.getName());
     }
 
@@ -531,9 +531,9 @@ namespace tut
                                  "    for arg in sys.argv[1:]:\n"
                                  "        print >>f, arg\n");
         // We expect that PythonProcessLauncher has already appended
-        // its own NamedTempFile to mParams["args"] (sys.argv[0]).
-        py.mParams["args"].append("first arg");          // sys.argv[1]
-        py.mParams["args"].append("second arg");         // sys.argv[2]
+        // its own NamedTempFile to mParams.args (sys.argv[0]).
+        py.mParams.args.add("first arg");          // sys.argv[1]
+        py.mParams.args.add("second arg");         // sys.argv[2]
         // run_read() appends() one more argument, hence [3]
         std::string output(py.run_read());
         boost::split_iterator<std::string::const_iterator>
@@ -568,7 +568,7 @@ namespace tut
                                  "with open(sys.argv[1], 'w') as f:\n"
                                  "    f.write('bad')\n");
         NamedTempFile out("out", "not started");
-        py.mParams["args"].append(out.getName());
+        py.mParams.args.add(out.getName());
         py.mPy = LLProcess::create(py.mParams);
         ensure("couldn't launch kill() script", py.mPy);
         // Wait for the script to wake up and do its first write
@@ -611,7 +611,7 @@ namespace tut
                                      "# if caller hasn't managed to kill by now, bad\n"
                                      "with open(sys.argv[1], 'w') as f:\n"
                                      "    f.write('bad')\n");
-            py.mParams["args"].append(out.getName());
+            py.mParams.args.add(out.getName());
             py.mPy = LLProcess::create(py.mParams);
             ensure("couldn't launch kill() script", py.mPy);
             // Capture id for later
@@ -667,9 +667,9 @@ namespace tut
                                      "# okay, saw 'go', write 'ack'\n"
                                      "with open(sys.argv[1], 'w') as f:\n"
                                      "    f.write('ack')\n");
-            py.mParams["args"].append(from.getName());
-            py.mParams["args"].append(to.getName());
-            py.mParams["autokill"] = false;
+            py.mParams.args.add(from.getName());
+            py.mParams.args.add(to.getName());
+            py.mParams.autokill = false;
             py.mPy = LLProcess::create(py.mParams);
             ensure("couldn't launch kill() script", py.mPy);
             // Capture id for later
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 7756ba6226..e625545763 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1557,9 +1557,9 @@ namespace tut
             }
 
 #else  // LL_DARWIN, LL_LINUX
-            LLSD params;
-            params["executable"] = PYTHON;
-            params["args"].append(scriptfile.getName());
+            LLProcess::Params params;
+            params.executable = PYTHON;
+            params.args.add(scriptfile.getName());
             LLProcessPtr py(LLProcess::create(params));
             ensure(STRINGIZE("Couldn't launch " << desc << " script"), py);
             // Implementing timeout would mean messing with alarm() and
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 9b225cabb8..f10eaee5b4 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -163,8 +163,8 @@ void LLPluginProcessParent::errorState(void)
 
 void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
 {	
-	mProcessParams["executable"] = launcher_filename;
-	mProcessParams["cwd"] = plugin_dir;
+	mProcessParams.executable = launcher_filename;
+	mProcessParams.cwd = plugin_dir;
 	mPluginFile = plugin_filename;
 	mPluginDir = plugin_dir;
 	mCPUUsage = 0.0f;
@@ -375,7 +375,7 @@ void LLPluginProcessParent::idle(void)
 				// Launch the plugin process.
 				
 				// Only argument to the launcher is the port number we're listening on
-				mProcessParams["args"].append(stringize(mBoundPort));
+				mProcessParams.args.add(stringize(mBoundPort));
 				if (! (mProcess = LLProcess::create(mProcessParams)))
 				{
 					errorState();
@@ -390,17 +390,17 @@ void LLPluginProcessParent::idle(void)
 						// The command we're constructing would look like this on the command line:
 						// osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
 
-						LLSD params;
-						params["executable"] = "/usr/bin/osascript";
-						params["args"].append("-e");
-						params["args"].append("tell application \"Terminal\"");
-						params["args"].append("-e");
-						params["args"].append(STRINGIZE("set win to do script \"gdb -pid "
-														<< mProcess->getProcessID() << "\""));
-						params["args"].append("-e");
-						params["args"].append("do script \"continue\" in win");
-						params["args"].append("-e");
-						params["args"].append("end tell");
+						LLProcess::Params params;
+						params.executable = "/usr/bin/osascript";
+						params.args.add("-e");
+						params.args.add("tell application \"Terminal\"");
+						params.args.add("-e");
+						params.args.add(STRINGIZE("set win to do script \"gdb -pid "
+												  << mProcess->getProcessID() << "\""));
+						params.args.add("-e");
+						params.args.add("do script \"continue\" in win");
+						params.args.add("-e");
+						params.args.add("end tell");
 						mDebugger = LLProcess::create(params);
 
 						#endif
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index e8bcba75e0..990fc5cbae 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -140,27 +140,27 @@ private:
 	};
 	EState mState;
 	void setState(EState state);
-	
+
 	bool pluginLockedUp();
 	bool pluginLockedUpOrQuit();
 
 	bool accept();
-		
+
 	LLSocket::ptr_t mListenSocket;
 	LLSocket::ptr_t mSocket;
 	U32 mBoundPort;
 
-	LLSD mProcessParams;
+	LLProcess::Params mProcessParams;
 	LLProcessPtr mProcess;
-	
+
 	std::string mPluginFile;
 	std::string mPluginDir;
 
 	LLPluginProcessParentOwner *mOwner;
-	
+
 	typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType;
 	sharedMemoryRegionsType mSharedMemoryRegions;
-	
+
 	LLSD mMessageClassVersions;
 	std::string mPluginVersionString;
 	
diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp
index ba58cd8067..3dfebad958 100644
--- a/indra/newview/llexternaleditor.cpp
+++ b/indra/newview/llexternaleditor.cpp
@@ -60,22 +60,22 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env
 	}
 
 	// Save command.
-	mProcessParams["executable"] = bin_path;
-	mProcessParams["args"].clear();
+	mProcessParams = LLProcess::Params();
+	mProcessParams.executable = bin_path;
 	for (size_t i = 1; i < tokens.size(); ++i)
 	{
-		mProcessParams["args"].append(tokens[i]);
+		mProcessParams.args.add(tokens[i]);
 	}
 
 	// Add the filename marker if missing.
 	if (cmd.find(sFilenameMarker) == std::string::npos)
 	{
-		mProcessParams["args"].append(sFilenameMarker);
+		mProcessParams.args.add(sFilenameMarker);
 		llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl;
 	}
 
 	llinfos << "Setting command [" << bin_path;
-	BOOST_FOREACH(const std::string& arg, llsd::inArray(mProcessParams["args"]))
+	BOOST_FOREACH(const std::string& arg, mProcessParams.args)
 	{
 		llcont << " \"" << arg << "\"";
 	}
@@ -86,33 +86,36 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env
 
 LLExternalEditor::EErrorCode LLExternalEditor::run(const std::string& file_path)
 {
-	if (mProcessParams["executable"].asString().empty() || ! mProcessParams["args"].size())
+	// LLInitParams type wrappers don't seem to have empty() or size()
+	// methods; try determining emptiness by comparing begin/end iterators.
+	if (std::string(mProcessParams.executable).empty() ||
+	    (mProcessParams.args.begin() == mProcessParams.args.end()))
 	{
 		llwarns << "Editor command not set" << llendl;
 		return EC_NOT_SPECIFIED;
 	}
 
 	// Copy params block so we can replace sFilenameMarker
-	LLSD params(mProcessParams);
+	LLProcess::Params params;
+	params.executable = mProcessParams.executable;
 
 	// Substitute the filename marker in the command with the actual passed file name.
-	LLSD& args(params["args"]);
-	for (LLSD::array_iterator ai(args.beginArray()), aend(args.endArray()); ai != aend; ++ai)
+	BOOST_FOREACH(const std::string& arg, mProcessParams.args)
 	{
-		std::string sarg(*ai);
-		LLStringUtil::replaceString(sarg, sFilenameMarker, file_path);
-		*ai = sarg;
+		std::string fixed(arg);
+		LLStringUtil::replaceString(fixed, sFilenameMarker, file_path);
+		params.args.add(fixed);
 	}
 
 	// Run the editor.
-	llinfos << "Running editor command [" << params["executable"];
-	BOOST_FOREACH(const std::string& arg, llsd::inArray(params["args"]))
+	llinfos << "Running editor command [" << std::string(params.executable);
+	BOOST_FOREACH(const std::string& arg, params.args)
 	{
 		llcont << " \"" << arg << "\"";
 	}
 	llcont << "]" << llendl;
 	// Prevent killing the process in destructor.
-	params["autokill"] = false;
+	params.autokill = false;
 	return LLProcess::create(params) ? EC_SUCCESS : EC_FAILED_TO_RUN;
 }
 
diff --git a/indra/newview/llexternaleditor.h b/indra/newview/llexternaleditor.h
index e81c360c24..fd2c25020c 100644
--- a/indra/newview/llexternaleditor.h
+++ b/indra/newview/llexternaleditor.h
@@ -27,7 +27,7 @@
 #ifndef LL_LLEXTERNALEDITOR_H
 #define LL_LLEXTERNALEDITOR_H
 
-#include "llsd.h"
+#include "llprocess.h"
 
 /**
  * Usage:
@@ -97,8 +97,7 @@ private:
 	 */
 	static const std::string sSetting;
 
-
-	LLSD				mProcessParams;
+	LLProcess::Params		mProcessParams;
 };
 
 #endif // LL_LLEXTERNALEDITOR_H
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index e99fd0af7e..2f87d59373 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -78,12 +78,12 @@ int ll_install_update(std::string const & script,
 	llinfos << "UpdateInstaller: installing " << updatePath << " using " <<
 		actualScriptPath << LL_ENDL;
 	
-	LLSD params;
-	params["executable"] = actualScriptPath;
-	params["args"].append(updatePath);
-	params["args"].append(ll_install_failed_marker_path());
-	params["args"].append(boost::lexical_cast<std::string>(required));
-	params["autokill"] = false;
+	LLProcess::Params params;
+	params.executable = actualScriptPath;
+	params.args.add(updatePath);
+	params.args.add(ll_install_failed_marker_path());
+	params.args.add(boost::lexical_cast<std::string>(required));
+	params.autokill = false;
 	return LLProcess::create(params)? 0 : -1;
 }
 
-- 
cgit v1.2.3


From e690373b059117e316f7704309321aaca2839668 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 21 Jan 2012 19:46:46 -0500
Subject: Since lltrans.h moved to llui, fix linux_updater/CMakeLists.txt.

---
 indra/linux_updater/CMakeLists.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/linux_updater/CMakeLists.txt b/indra/linux_updater/CMakeLists.txt
index 00a78b2a8f..4377a6333c 100644
--- a/indra/linux_updater/CMakeLists.txt
+++ b/indra/linux_updater/CMakeLists.txt
@@ -10,14 +10,14 @@ include(UI)
 include(LLCommon)
 include(LLVFS)
 include(LLXML)
-include(LLXUIXML)
+include(LLUI)
 include(Linking)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
     ${LLVFS_INCLUDE_DIRS}
     ${LLXML_INCLUDE_DIRS}
-    ${LLXUIXML_INCLUDE_DIRS}
+    ${LLUI_INCLUDE_DIRS}
     ${CURL_INCLUDE_DIRS}
     ${CARES_INCLUDE_DIRS}
     ${OPENSSL_INCLUDE_DIRS}
@@ -42,7 +42,7 @@ target_link_libraries(linux-updater
     ${CRYPTO_LIBRARIES}
     ${UI_LIBRARIES}
     ${LLXML_LIBRARIES}
-    ${LLXUIXML_LIBRARIES}
+    ${LLUI_LIBRARIES}
     ${LLVFS_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
     )
-- 
cgit v1.2.3


From b9a03b95aafb07eb32a8f99a671f2216acce96d4 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sun, 22 Jan 2012 09:16:11 -0500
Subject: On Windows, introduce viewer Job Object and assign children to it.
 The idea is that, with the right flag settings, this will cause the OS to
 terminate remaining viewer child processes when the viewer terminates --
 whether or not it terminates intentionally. Of course, if LLProcess's caller
 specifies autokill=false, e.g. to run the viewer updater, that asserts that
 we WANT the child to persist beyond the viewer session itself.

---
 indra/llcommon/llprocess.cpp | 167 +++++++++++++++++++++++++++++++++----------
 1 file changed, 128 insertions(+), 39 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index dfb2ed69e9..d30d87411d 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -27,6 +27,7 @@
 #include "linden_common.h"
 #include "llprocess.h"
 #include "llsdserialize.h"
+#include "llsingleton.h"
 #include "stringize.h"
 
 #include <boost/foreach.hpp>
@@ -80,43 +81,84 @@ bool LLProcess::isRunning(void)
 	return (mProcessID != 0);
 }
 
+/*****************************************************************************
+*   Windows specific
+*****************************************************************************/
 #if LL_WINDOWS
 
-static std::string quote(const std::string& str)
+static std::string WindowsErrorString(const std::string& operation);
+static std::string quote(const std::string&);
+
+/**
+ * Wrap a Windows Job Object for use in managing child-process lifespan.
+ *
+ * On Windows, we use a Job Object to constrain the lifespan of any
+ * autokill=true child process to the viewer's own lifespan:
+ * http://stackoverflow.com/questions/53208/how-do-i-automatically-destroy-child-processes-in-windows
+ * (thanks Richard!).
+ *
+ * We manage it using an LLSingleton for a couple of reasons:
+ *
+ * # Lazy initialization: if some viewer session never launches a child
+ *   process, we should never have to create a Job Object.
+ * # Cross-DLL support: be wary of C++ statics when multiple DLLs are
+ *   involved.
+ */
+class LLJob: public LLSingleton<LLJob>
 {
-	std::string::size_type len(str.length());
-	// If the string is already quoted, assume user knows what s/he's doing.
-	if (len >= 2 && str[0] == '"' && str[len-1] == '"')
+public:
+	void assignProcess(const std::string& prog, HANDLE hProcess)
 	{
-		return str;
+		// If we never managed to initialize this Job Object, can't use it --
+		// but don't keep spamming the log, we already emitted warnings when
+		// we first tried to create.
+		if (! mJob)
+			return;
+
+		if (! AssignProcessToJobObject(mJob, hProcess))
+		{
+			LL_WARNS("LLProcess") << WindowsErrorString(STRINGIZE("AssignProcessToJobObject(\""
+																  << prog << "\")")) << LL_ENDL;
+		}
 	}
 
-	// Not already quoted: do it.
-	std::string result("\"");
-	for (std::string::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
+private:
+	LLJob():
+		mJob(0)
 	{
-		if (*ci == '"')
+		mJob = CreateJobObject(NULL, NULL);
+		if (! mJob)
 		{
-			result.append("\\");
+			LL_WARNS("LLProcess") << WindowsErrorString("CreateJobObject()") << LL_ENDL;
+			return;
+		}
+
+		JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
+
+		// Configure all child processes associated with this new job object
+		// to terminate when the calling process (us!) terminates.
+		jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+		if (! SetInformationJobObject(mJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
+		{
+			LL_WARNS("LLProcess") << WindowsErrorString("SetInformationJobObject()") << LL_ENDL;
 		}
-		result.push_back(*ci);
 	}
-	return result + "\"";
-}
+
+	HANDLE mJob;
+};
 
 void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 {
 	PROCESS_INFORMATION pinfo;
-	STARTUPINFOA sinfo;
-	memset(&sinfo, 0, sizeof(sinfo));
-	
+	STARTUPINFOA sinfo = { sizeof(sinfo) };
+
 	std::string args = quote(params.executable);
 	BOOST_FOREACH(const std::string& arg, params.args)
 	{
 		args += " ";
 		args += quote(arg);
 	}
-	
+
 	// So retarded.  Windows requires that the second parameter to
 	// CreateProcessA be a writable (non-const) string...
 	std::vector<char> args2(args.begin(), args.end());
@@ -130,28 +172,14 @@ void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 		working_directory = cwd.c_str();
 	if( ! CreateProcessA( NULL, &args2[0], NULL, NULL, FALSE, 0, NULL, working_directory, &sinfo, &pinfo ) )
 	{
-		int result = GetLastError();
-
-		LPTSTR error_str = 0;
-		if(
-			FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-				NULL,
-				result,
-				0,
-				(LPTSTR)&error_str,
-				0,
-				NULL) 
-			!= 0) 
-		{
-			char message[256];
-			wcstombs(message, error_str, sizeof(message));
-			message[sizeof(message)-1] = 0;
-			LocalFree(error_str);
-			throw LLProcessError(STRINGIZE("CreateProcessA failed (" << result << "): "
-										   << message));
-		}
-		throw LLProcessError(STRINGIZE("CreateProcessA failed (" << result
-									   << "), but FormatMessage() did not explain"));
+		throw LLProcessError(WindowsErrorString("CreateProcessA"));
+	}
+
+	// Now associate the new child process with our Job Object -- unless
+	// autokill is false, i.e. caller asserts the child should persist.
+	if (params.autokill)
+	{
+		LLJob::instance().assignProcess(params.executable, pinfo.hProcess);
 	}
 
 	// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
@@ -184,6 +212,67 @@ bool LLProcess::kill(void)
 	return ! isRunning();
 }
 
+/**
+ * Double-quote an argument string, unless it's already double-quoted. If we
+ * quote it, escape any embedded double-quote with backslash.
+ *
+ * LLProcess::create()'s caller passes a Unix-style array of strings for
+ * command-line arguments. Our caller can and should expect that these will be
+ * passed to the child process as individual arguments, regardless of content
+ * (e.g. embedded spaces). But because Windows invokes any child process with
+ * a single command-line string, this means we must quote each argument behind
+ * the scenes.
+ */
+static std::string quote(const std::string& str)
+{
+	std::string::size_type len(str.length());
+	// If the string is already quoted, assume user knows what s/he's doing.
+	if (len >= 2 && str[0] == '"' && str[len-1] == '"')
+	{
+		return str;
+	}
+
+	// Not already quoted: do it.
+	std::string result("\"");
+	for (std::string::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
+	{
+		if (*ci == '"')
+		{
+			result.append("\\");
+		}
+		result.push_back(*ci);
+	}
+	return result + "\"";
+}
+
+/// GetLastError()/FormatMessage() boilerplate
+static std::string WindowsErrorString(const std::string& operation)
+{
+	int result = GetLastError();
+
+	LPTSTR error_str = 0;
+	if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+					   NULL,
+					   result,
+					   0,
+					   (LPTSTR)&error_str,
+					   0,
+					   NULL)
+		!= 0) 
+	{
+		char message[256];
+		wcstombs(message, error_str, sizeof(message));
+		message[sizeof(message)-1] = 0;
+		LocalFree(error_str);
+		return STRINGIZE(operation << " failed (" << result << "): " << message);
+	}
+	return STRINGIZE(operation << " failed (" << result
+					 << "), but FormatMessage() did not explain");
+}
+
+/*****************************************************************************
+*   Non-Windows specific
+*****************************************************************************/
 #else // Mac and linux
 
 #include <signal.h>
-- 
cgit v1.2.3


From aa1bbe3277842a9a6e7db5227b35f1fbea50b7a6 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sun, 22 Jan 2012 10:58:16 -0500
Subject: Make LLProcess::Params streamable; use that in LLExternalEditor.

---
 indra/llcommon/llprocess.cpp       | 15 +++++++++++++++
 indra/llcommon/llprocess.h         |  4 ++++
 indra/newview/llexternaleditor.cpp | 14 ++------------
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index d30d87411d..9d6c19f1dd 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -81,6 +81,21 @@ bool LLProcess::isRunning(void)
 	return (mProcessID != 0);
 }
 
+std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
+{
+	std::string cwd(params.cwd);
+	if (! cwd.empty())
+	{
+		out << "cd '" << cwd << "': ";
+	}
+	out << '"' << std::string(params.executable) << '"';
+	BOOST_FOREACH(const std::string& arg, params.args)
+	{
+		out << " \"" << arg << '"';
+	}
+	return out;
+}
+
 /*****************************************************************************
 *   Windows specific
 *****************************************************************************/
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 9ea129baf2..7dbdf23679 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -31,6 +31,7 @@
 #include "llsdparam.h"
 #include <boost/shared_ptr.hpp>
 #include <boost/noncopyable.hpp>
+#include <iosfwd>                   // std::ostream
 
 #if LL_WINDOWS
 #define WIN32_LEAN_AND_MEAN
@@ -124,4 +125,7 @@ private:
 	bool mAutokill;
 };
 
+/// for logging
+LL_COMMON_API std::ostream& operator<<(std::ostream&, const LLProcess::Params&);
+
 #endif // LL_LLPROCESS_H
diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp
index 3dfebad958..0d3ed0ba35 100644
--- a/indra/newview/llexternaleditor.cpp
+++ b/indra/newview/llexternaleditor.cpp
@@ -74,12 +74,7 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env
 		llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl;
 	}
 
-	llinfos << "Setting command [" << bin_path;
-	BOOST_FOREACH(const std::string& arg, mProcessParams.args)
-	{
-		llcont << " \"" << arg << "\"";
-	}
-	llcont << "]" << llendl;
+	llinfos << "Setting command [" << mProcessParams << "]" << llendl;
 
 	return EC_SUCCESS;
 }
@@ -108,12 +103,7 @@ LLExternalEditor::EErrorCode LLExternalEditor::run(const std::string& file_path)
 	}
 
 	// Run the editor.
-	llinfos << "Running editor command [" << std::string(params.executable);
-	BOOST_FOREACH(const std::string& arg, params.args)
-	{
-		llcont << " \"" << arg << "\"";
-	}
-	llcont << "]" << llendl;
+	llinfos << "Running editor command [" << params << "]" << llendl;
 	// Prevent killing the process in destructor.
 	params.autokill = false;
 	return LLProcess::create(params) ? EC_SUCCESS : EC_FAILED_TO_RUN;
-- 
cgit v1.2.3


From 748d1b311fdecf123df40bd7d22dd7e19afaca84 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sun, 22 Jan 2012 11:56:38 -0500
Subject: Add LLProcess logging on launch(), kill(), isRunning(). Much as I
 dislike viewer log spam, seems to me starting a child process, killing it and
 observing its termination are noteworthy events. New logging makes
 LLExternalEditor launch message redundant; removed.

---
 indra/llcommon/llprocess.cpp       | 34 +++++++++++++++++++++++++---------
 indra/llcommon/llprocess.h         |  7 ++++---
 indra/newview/llexternaleditor.cpp |  4 +---
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 9d6c19f1dd..6d329a3fa1 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -77,7 +77,7 @@ LLProcess::~LLProcess()
 
 bool LLProcess::isRunning(void)
 {
-	mProcessID = isRunning(mProcessID);
+	mProcessID = isRunning(mProcessID, mDesc);
 	return (mProcessID != 0);
 }
 
@@ -190,20 +190,23 @@ void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 		throw LLProcessError(WindowsErrorString("CreateProcessA"));
 	}
 
+	// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
+	// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
+	mProcessID = pinfo.hProcess;
+	CloseHandle(pinfo.hThread); // stops leaks - nothing else
+
+	mDesc = STRINGIZE('"' << std::string(params.executable) << "\" (" << pinfo.dwProcessId << ')');
+	LL_INFOS("LLProcess") << "Launched " << params << " (" << pinfo.dwProcessId << ")" << LL_ENDL;
+
 	// Now associate the new child process with our Job Object -- unless
 	// autokill is false, i.e. caller asserts the child should persist.
 	if (params.autokill)
 	{
-		LLJob::instance().assignProcess(params.executable, pinfo.hProcess);
+		LLJob::instance().assignProcess(mDesc, mProcessID);
 	}
-
-	// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
-	// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
-	mProcessID = pinfo.hProcess;
-	CloseHandle(pinfo.hThread); // stops leaks - nothing else
 }
 
-LLProcess::id LLProcess::isRunning(id handle)
+LLProcess::id LLProcess::isRunning(id handle, const std::string& desc)
 {
 	if (! handle)
 		return 0;
@@ -212,6 +215,10 @@ LLProcess::id LLProcess::isRunning(id handle)
 	if(waitresult == WAIT_OBJECT_0)
 	{
 		// the process has completed.
+		if (! desc.empty())
+		{
+			LL_INFOS("LLProcess") << desc << " terminated" << LL_ENDL;
+		}
 		return 0;
 	}
 
@@ -223,6 +230,7 @@ bool LLProcess::kill(void)
 	if (! mProcessID)
 		return false;
 
+	LL_INFOS("LLProcess") << "killing " << mDesc << LL_ENDL;
 	TerminateProcess(mProcessID, 0);
 	return ! isRunning();
 }
@@ -369,9 +377,12 @@ void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 
 	// parent process
 	mProcessID = child;
+
+	mDesc = STRINGIZE('"' << std::string(params.executable) << "\" (" << mProcessID << ')');
+	LL_INFOS("LLProcess") << "Launched " << params << " (" << mProcessID << ")" << LL_ENDL;
 }
 
-LLProcess::id LLProcess::isRunning(id pid)
+LLProcess::id LLProcess::isRunning(id pid, const std::string& desc)
 {
 	if (! pid)
 		return 0;
@@ -380,6 +391,10 @@ LLProcess::id LLProcess::isRunning(id pid)
 	if(reap_pid(pid))
 	{
 		// the process has exited.
+		if (! desc.empty())
+		{
+			LL_INFOS("LLProcess") << desc << " terminated" << LL_ENDL;
+		}
 		return 0;
 	}
 
@@ -393,6 +408,7 @@ bool LLProcess::kill(void)
 
 	// Try to kill the process. We'll do approximately the same thing whether
 	// the kill returns an error or not, so we ignore the result.
+	LL_INFOS("LLProcess") << "killing " << mDesc << LL_ENDL;
 	(void)::kill(mProcessID, SIGTERM);
 
 	// This will have the side-effect of reaping the zombie if the process has exited.
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 7dbdf23679..019c33592c 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -97,7 +97,7 @@ public:
 	typedef HANDLE id;
 #else
 	typedef pid_t  id;
-#endif	
+#endif
 	/// Get platform-specific process ID
 	id getProcessID() const { return mProcessID; };
 
@@ -114,13 +114,14 @@ public:
 	 * functionality should be added as nonstatic members operating on
 	 * mProcessID.
 	 */
-	static id isRunning(id);
-	
+	static id isRunning(id, const std::string& desc="");
+
 private:
 	/// constructor is private: use create() instead
 	LLProcess(const LLSDParamAdapter<Params>& params);
 	void launch(const LLSDParamAdapter<Params>& params);
 
+	std::string mDesc;
 	id mProcessID;
 	bool mAutokill;
 };
diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp
index 0d3ed0ba35..561b87618c 100644
--- a/indra/newview/llexternaleditor.cpp
+++ b/indra/newview/llexternaleditor.cpp
@@ -102,9 +102,7 @@ LLExternalEditor::EErrorCode LLExternalEditor::run(const std::string& file_path)
 		params.args.add(fixed);
 	}
 
-	// Run the editor.
-	llinfos << "Running editor command [" << params << "]" << llendl;
-	// Prevent killing the process in destructor.
+	// Run the editor. Prevent killing the process in destructor.
 	params.autokill = false;
 	return LLProcess::create(params) ? EC_SUCCESS : EC_FAILED_TO_RUN;
 }
-- 
cgit v1.2.3


From 323c0ef64ee02d64c983c35eee4f7ac09851e116 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sun, 22 Jan 2012 12:06:26 -0500
Subject: Use LLProcess::create() to launch SLVoice, rather than inline code.
 This appears to close a long-pending action item, as it seems the original
 LLProcessLauncher implementation was in fact cloned-and-edited from this
 logic in LLVivoxVoiceClient::stateMachine(). In any case, leveraging
 LLProcess buys us: - reduced redundancy; fewer maintenance points - logging
 for both success and errors - (possibly) better SLVoice.exe lifespan
 management.

---
 indra/newview/llvoicevivox.cpp | 140 +++++------------------------------------
 1 file changed, 16 insertions(+), 124 deletions(-)

diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index df1d3f2955..820d1d73e1 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -27,8 +27,6 @@
 #include "llviewerprecompiledheaders.h"
 #include "llvoicevivox.h"
 
-#include <boost/tokenizer.hpp>
-
 #include "llsdutil.h"
 
 // Linden library includes
@@ -47,6 +45,7 @@
 #include "llbase64.h"
 #include "llviewercontrol.h"
 #include "llappviewer.h"	// for gDisconnected, gDisableVoice
+#include "llprocess.h"
 
 // Viewer includes
 #include "llmutelist.h"  // to check for muted avatars
@@ -242,59 +241,21 @@ void LLVivoxVoiceClientCapResponder::result(const LLSD& content)
 	}
 }
 
-
-
-#if LL_WINDOWS
-static HANDLE sGatewayHandle = 0;
+static LLProcessPtr sGatewayPtr;
 
 static bool isGatewayRunning()
 {
-	bool result = false;
-	if(sGatewayHandle != 0)		
-	{
-		DWORD waitresult = WaitForSingleObject(sGatewayHandle, 0);
-		if(waitresult != WAIT_OBJECT_0)
-		{
-			result = true;
-		}			
-	}
-	return result;
-}
-static void killGateway()
-{
-	if(sGatewayHandle != 0)
-	{
-		TerminateProcess(sGatewayHandle,0);
-	}
-}
-
-#else // Mac and linux
-
-static pid_t sGatewayPID = 0;
-static bool isGatewayRunning()
-{
-	bool result = false;
-	if(sGatewayPID != 0)
-	{
-		// A kill with signal number 0 has no effect, just does error checking.  It should return an error if the process no longer exists.
-		if(kill(sGatewayPID, 0) == 0)
-		{
-			result = true;
-		}
-	}
-	return result;
+	return sGatewayPtr && sGatewayPtr->isRunning();
 }
 
 static void killGateway()
 {
-	if(sGatewayPID != 0)
+	if (sGatewayPtr)
 	{
-		kill(sGatewayPID, SIGTERM);
+		sGatewayPtr->kill();
 	}
 }
 
-#endif
-
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 LLVivoxVoiceClient::LLVivoxVoiceClient() :
@@ -790,7 +751,7 @@ void LLVivoxVoiceClient::stateMachine()
 			}
 			else if(!isGatewayRunning())
 			{
-				if(true)
+				if (true)           // production build, not test
 				{
 					// Launch the voice daemon
 					
@@ -809,102 +770,33 @@ void LLVivoxVoiceClient::stateMachine()
 #endif
 					// See if the vivox executable exists
 					llstat s;
-					if(!LLFile::stat(exe_path, &s))
+					if (!LLFile::stat(exe_path, &s))
 					{
 						// vivox executable exists.  Build the command line and launch the daemon.
+						LLProcess::Params params;
+						params.executable = exe_path;
 						// SLIM SDK: these arguments are no longer necessary.
 //						std::string args = " -p tcp -h -c";
-						std::string args;
-						std::string cmd;
 						std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
-						
 						if(loglevel.empty())
 						{
 							loglevel = "-1";	// turn logging off completely
 						}
-						
-						args += " -ll ";
-						args += loglevel;
-						
-						LL_DEBUGS("Voice") << "Args for SLVoice: " << args << LL_ENDL;
-
-#if LL_WINDOWS
-						PROCESS_INFORMATION pinfo;
-						STARTUPINFOA sinfo;
-						
-						memset(&sinfo, 0, sizeof(sinfo));
-						
-						std::string exe_dir = gDirUtilp->getAppRODataDir();
-						cmd = "SLVoice.exe";
-						cmd += args;
-
-						// So retarded.  Windows requires that the second parameter to CreateProcessA be writable (non-const) string...
-						char *args2 = new char[args.size() + 1];
-						strcpy(args2, args.c_str());
-						if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo))
-						{
-//							DWORD dwErr = GetLastError();
-						}
-						else
-						{
-							// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
-							// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
-							sGatewayHandle = pinfo.hProcess;
-							CloseHandle(pinfo.hThread); // stops leaks - nothing else
-						}		
-						
-						delete[] args2;
-#else	// LL_WINDOWS
-						// This should be the same for mac and linux
-						{
-							std::vector<std::string> arglist;
-							arglist.push_back(exe_path);
-							
-							// Split the argument string into separate strings for each argument
-							typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-							boost::char_separator<char> sep(" ");
-							tokenizer tokens(args, sep);
-							tokenizer::iterator token_iter;
 
-							for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
-							{
-								arglist.push_back(*token_iter);
-							}
-							
-							// create an argv vector for the child process
-							char **fakeargv = new char*[arglist.size() + 1];
-							int i;
-							for(i=0; i < arglist.size(); i++)
-								fakeargv[i] = const_cast<char*>(arglist[i].c_str());
+						params.args.add("-ll");
+						params.args.add(loglevel);
+						params.cwd = gDirUtilp->getAppRODataDir();
+						sGatewayPtr = LLProcess::create(params);
 
-							fakeargv[i] = NULL;
-							
-							fflush(NULL); // flush all buffers before the child inherits them
-							pid_t id = vfork();
-							if(id == 0)
-							{
-								// child
-								execv(exe_path.c_str(), fakeargv);
-								
-								// If we reach this point, the exec failed.
-								// Use _exit() instead of exit() per the vfork man page.
-								_exit(0);
-							}
-
-							// parent
-							delete[] fakeargv;
-							sGatewayPID = id;
-						}
-#endif	// LL_WINDOWS
 						mDaemonHost = LLHost(gSavedSettings.getString("VivoxVoiceHost").c_str(), gSavedSettings.getU32("VivoxVoicePort"));
-					}	
+					}
 					else
 					{
 						LL_INFOS("Voice") << exe_path << " not found." << LL_ENDL;
-					}	
+					}
 				}
 				else
-				{		
+				{
 					// SLIM SDK: port changed from 44124 to 44125.
 					// We can connect to a client gateway running on another host.  This is useful for testing.
 					// To do this, launch the gateway on a nearby host like this:
-- 
cgit v1.2.3


From 738483e6302af5a9ad00fa3df17efe5336a03a41 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sun, 22 Jan 2012 13:05:34 -0500
Subject: Every singleton needs a friend...

---
 indra/llcommon/llprocess.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 6d329a3fa1..eb7ce4129b 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -138,6 +138,7 @@ public:
 	}
 
 private:
+	friend class LLSingleton<LLJob>;
 	LLJob():
 		mJob(0)
 	{
-- 
cgit v1.2.3


From e2d4309ba56b103bbcd215b09c9d877ceb71dc38 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 23 Jan 2012 11:45:47 -0800
Subject: EXP-1799 FIX -- Replace and Add to Outfit options and Copy to
 Merchant Outbox options can appear in invalid state when a valid folder is
 last selection EXP-1834 FIX -- Right click context menus on Folders in
 Merchant Outbox and Library folders can show all inventory options including
 admin options EXP-1835 FIX -- Right clicking on a folder and selecting New
 Folder creates folder under My Inventory not within selected folder

* Updated folder context menu building to build full options in one step or
  trigger a load which will rebuild top-level context menu for all selected
  items when complete.  Previous code had an implicit assumption that the
  selected folder was the only selection after background fetch.
---
 indra/newview/llinventorybridge.cpp | 257 ++++++++++++++++--------------------
 indra/newview/llinventorybridge.h   |   9 +-
 2 files changed, 116 insertions(+), 150 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index bce3511c80..9e21e2fceb 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2923,127 +2923,11 @@ void LLFolderBridge::pasteLinkFromClipboard()
 void LLFolderBridge::staticFolderOptionsMenu()
 {
 	LLFolderBridge* selfp = sSelf.get();
-	if (selfp)
-	{
-		selfp->folderOptionsMenuAfterFetch();
-	}
-}
-
-void LLFolderBridge::folderOptionsMenuAfterFetch()
-{
-	const U32 flags = mContextMenuFlags;
-
-	mItems.clear();
-	mDisabledItems.clear();
-	mContextMenuFlags = 0x0;
-
-	LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get());
-	if (!menup) return;
-
-	// Reset the menu
-	{
-		const LLView::child_list_t *list = menup->getChildList();
-
-		LLView::child_list_t::const_iterator menu_itor;
-		for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor)
-		{
-			(*menu_itor)->setVisible(FALSE);
-			(*menu_itor)->pushVisible(TRUE);
-			(*menu_itor)->setEnabled(TRUE);
-		}
-	}
-
-	// Build basic menu back up
-	buildContextMenuBaseOptions(*menup, flags);
-
-	// Build folder specific options back up
-	LLInventoryModel* model = getInventoryModel();
-	if(!model) return;
-
-	const LLInventoryCategory* category = model->getCategory(mUUID);
-	if(!category) return;
-
-	const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
-	if (trash_id == mUUID) return;
-	if (isItemInTrash()) return;
-	if (!isAgentInventory()) return;
-	if (isOutboxFolder()) return;
-
-	LLFolderType::EType type = category->getPreferredType();
-	const bool is_system_folder = LLFolderType::lookupIsProtectedType(type);
-	// BAP change once we're no longer treating regular categories as ensembles.
-	const bool is_ensemble = (type == LLFolderType::FT_NONE ||
-							  LLFolderType::lookupIsEnsembleType(type));
-
-	// Only enable calling-card related options for non-system folders.
-	if (!is_system_folder)
-	{
-		LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
-		if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
-		{
-			mItems.push_back(std::string("Calling Card Separator"));
-			mItems.push_back(std::string("Conference Chat Folder"));
-			mItems.push_back(std::string("IM All Contacts In Folder"));
-		}
-	}
-
-	if (!isItemRemovable())
-	{
-		mDisabledItems.push_back(std::string("Delete"));
-	}
 
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-	if (LLFolderType::lookupIsProtectedType(type))
+	if (selfp && selfp->mRoot)
 	{
-		mItems.push_back(std::string("Delete System Folder"));
+		selfp->mRoot->updateMenu();
 	}
-#endif
-
-	// wearables related functionality for folders.
-	//is_wearable
-	LLFindWearables is_wearable;
-	LLIsType is_object( LLAssetType::AT_OBJECT );
-	LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
-	if (mWearables ||
-		checkFolderForContentsOfType(model, is_wearable)  ||
-		checkFolderForContentsOfType(model, is_object) ||
-		checkFolderForContentsOfType(model, is_gesture) )
-	{
-		mItems.push_back(std::string("Folder Wearables Separator"));
-
-		// Only enable add/replace outfit for non-system folders.
-		if (!is_system_folder)
-		{
-			// Adding an outfit onto another (versus replacing) doesn't make sense.
-			if (type != LLFolderType::FT_OUTFIT)
-			{
-				mItems.push_back(std::string("Add To Outfit"));
-			}
-
-			mItems.push_back(std::string("Replace Outfit"));
-		}
-		if (is_ensemble)
-		{
-			mItems.push_back(std::string("Wear As Ensemble"));
-		}
-		mItems.push_back(std::string("Remove From Outfit"));
-		if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))
-		{
-			mDisabledItems.push_back(std::string("Remove From Outfit"));
-		}
-		if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))
-		{
-			mDisabledItems.push_back(std::string("Replace Outfit"));
-		}
-		mItems.push_back(std::string("Outfit Separator"));
-	}
-
-	hide_context_entries(*menup, mItems, mDisabledItems);
-
-	// Reposition the menu, in case we're adding items to an existing menu.
-	menup->needsArrange();
-	menup->arrangeAndClear();
 }
 
 BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
@@ -3058,7 +2942,7 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv
 	return ((item_array.count() > 0) ? TRUE : FALSE );
 }
 
-void LLFolderBridge::buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags)
+void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)
 {
 	LLInventoryModel* model = getInventoryModel();
 	llassert(model != NULL);
@@ -3079,10 +2963,6 @@ void LLFolderBridge::buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags)
 		mDisabledItems.push_back(std::string("New Body Parts"));
 	}
 
-	// clear out old menu and folder pointers
-	mMenu.markDead();
-	sSelf.markDead();
-
 	if(trash_id == mUUID)
 	{
 		// This is the trash.
@@ -3185,45 +3065,134 @@ void LLFolderBridge::buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags)
 	}
 }
 
+void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)
+{
+	// Build folder specific options back up
+	LLInventoryModel* model = getInventoryModel();
+	if(!model) return;
+
+	const LLInventoryCategory* category = model->getCategory(mUUID);
+	if(!category) return;
+
+	const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+	if (trash_id == mUUID) return;
+	if (isItemInTrash()) return;
+	if (!isAgentInventory()) return;
+	if (isOutboxFolder()) return;
+
+	LLFolderType::EType type = category->getPreferredType();
+	const bool is_system_folder = LLFolderType::lookupIsProtectedType(type);
+	// BAP change once we're no longer treating regular categories as ensembles.
+	const bool is_ensemble = (type == LLFolderType::FT_NONE ||
+		LLFolderType::lookupIsEnsembleType(type));
+
+	// Only enable calling-card related options for non-system folders.
+	if (!is_system_folder)
+	{
+		LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
+		if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
+		{
+			mItems.push_back(std::string("Calling Card Separator"));
+			mItems.push_back(std::string("Conference Chat Folder"));
+			mItems.push_back(std::string("IM All Contacts In Folder"));
+		}
+	}
+
+	if (!isItemRemovable())
+	{
+		mDisabledItems.push_back(std::string("Delete"));
+	}
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	if (LLFolderType::lookupIsProtectedType(type))
+	{
+		mItems.push_back(std::string("Delete System Folder"));
+	}
+#endif
+
+	// wearables related functionality for folders.
+	//is_wearable
+	LLFindWearables is_wearable;
+	LLIsType is_object( LLAssetType::AT_OBJECT );
+	LLIsType is_gesture( LLAssetType::AT_GESTURE );
+
+	if (mWearables ||
+		checkFolderForContentsOfType(model, is_wearable)  ||
+		checkFolderForContentsOfType(model, is_object) ||
+		checkFolderForContentsOfType(model, is_gesture) )
+	{
+		mItems.push_back(std::string("Folder Wearables Separator"));
+
+		// Only enable add/replace outfit for non-system folders.
+		if (!is_system_folder)
+		{
+			// Adding an outfit onto another (versus replacing) doesn't make sense.
+			if (type != LLFolderType::FT_OUTFIT)
+			{
+				mItems.push_back(std::string("Add To Outfit"));
+			}
+
+			mItems.push_back(std::string("Replace Outfit"));
+		}
+		if (is_ensemble)
+		{
+			mItems.push_back(std::string("Wear As Ensemble"));
+		}
+		mItems.push_back(std::string("Remove From Outfit"));
+		if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))
+		{
+			mDisabledItems.push_back(std::string("Remove From Outfit"));
+		}
+		if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))
+		{
+			mDisabledItems.push_back(std::string("Replace Outfit"));
+		}
+		mItems.push_back(std::string("Outfit Separator"));
+	}
+}
+
 // Flags unused
 void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 {
+	sSelf.markDead();
+
 	mItems.clear();
 	mDisabledItems.clear();
-	mContextMenuFlags = flags;
 
 	lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
 
 	LLInventoryModel* model = getInventoryModel();
 	if(!model) return;
 
-	buildContextMenuBaseOptions(menu, flags);
-
-	hide_context_entries(menu, mItems, mDisabledItems);
+	buildContextMenuBaseOptions(flags);
 
 	// Add menu items that are dependent on the contents of the folder.
-	uuid_vec_t folders;
-	LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+	LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID);
 	if (category)
 	{
+		uuid_vec_t folders;
 		folders.push_back(category->getUUID());
-	}
 
-	mMenu = menu.getHandle();
-	sSelf = getHandle();
-	LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE);
-	fetch->startFetch();
-	inc_busy_count();
-	if(fetch->isFinished())
-	{
-		// everything is already here - call done.
-		fetch->done();
-	}
-	else
-	{
-		// it's all on its way - add an observer, and the inventory will call done for us when everything is here.
-		gInventory.addObserver(fetch);
+		sSelf = getHandle();
+		LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE);
+		fetch->startFetch();
+		inc_busy_count();
+		if (fetch->isFinished())
+		{
+			buildContextMenuFolderOptions(flags);
+		}
+		else
+		{
+			// it's all on its way - add an observer, and the inventory will call done for us when everything is here.
+			gInventory.addObserver(fetch);
+		}
 	}
+
+	hide_context_entries(menu, mItems, mDisabledItems);
+
+	// Reposition the menu, in case we're adding items to an existing menu.
+	menu.needsArrange();
+	menu.arrangeAndClear();
 }
 
 BOOL LLFolderBridge::hasChildren() const
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 56301ce728..871657a58a 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -235,8 +235,7 @@ public:
 				   const LLUUID& uuid) :
 		LLInvFVBridge(inventory, root, uuid),
 		mCallingCards(FALSE),
-		mWearables(FALSE),
-		mContextMenuFlags(0x0)
+		mWearables(FALSE)
 	{}
 		
 	BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg);
@@ -283,7 +282,8 @@ public:
 	LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; }
 
 protected:
-	void buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags);
+	void buildContextMenuBaseOptions(U32 flags);
+	void buildContextMenuFolderOptions(U32 flags);
 
 	//--------------------------------------------------------------------
 	// Menu callbacks
@@ -320,15 +320,12 @@ protected:
 public:
 	static LLHandle<LLFolderBridge> sSelf;
 	static void staticFolderOptionsMenu();
-	void folderOptionsMenuAfterFetch();
 
 private:
 	BOOL				mCallingCards;
 	BOOL				mWearables;
-	LLHandle<LLView>	mMenu;
 	menuentry_vec_t		mItems;
 	menuentry_vec_t		mDisabledItems;
-	U32					mContextMenuFlags;
 	LLRootHandle<LLFolderBridge> mHandle;
 };
 
-- 
cgit v1.2.3


From 507e136f9a25179992b2093e10ade1093cc71698 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 23 Jan 2012 16:24:33 -0500
Subject: Per Richard: close unusable Job Object; move quote() to LLStringUtil.
 If LLProcess can't set the right flag on a Windows Job Object, the object
 isn't useful to us, so we might as well discard it. quote() is sufficiently
 general that it belongs in LLStringUtil instead of buried as a static helper
 function in llprocess.cpp.

---
 indra/llcommon/llprocess.cpp |  49 +++-------
 indra/llcommon/llstring.h    | 223 +++++++++++++++++++++++++------------------
 2 files changed, 141 insertions(+), 131 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index eb7ce4129b..2c7512419d 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -28,6 +28,7 @@
 #include "llprocess.h"
 #include "llsdserialize.h"
 #include "llsingleton.h"
+#include "llstring.h"
 #include "stringize.h"
 
 #include <boost/foreach.hpp>
@@ -102,7 +103,6 @@ std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
 #if LL_WINDOWS
 
 static std::string WindowsErrorString(const std::string& operation);
-static std::string quote(const std::string&);
 
 /**
  * Wrap a Windows Job Object for use in managing child-process lifespan.
@@ -157,6 +157,10 @@ private:
 		if (! SetInformationJobObject(mJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
 		{
 			LL_WARNS("LLProcess") << WindowsErrorString("SetInformationJobObject()") << LL_ENDL;
+			// This Job Object is useless to us
+			CloseHandle(mJob);
+			// prevent assignProcess() from trying to use it
+			mJob = 0;
 		}
 	}
 
@@ -168,11 +172,17 @@ void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 	PROCESS_INFORMATION pinfo;
 	STARTUPINFOA sinfo = { sizeof(sinfo) };
 
-	std::string args = quote(params.executable);
+	// LLProcess::create()'s caller passes a Unix-style array of strings for
+	// command-line arguments. Our caller can and should expect that these will be
+	// passed to the child process as individual arguments, regardless of content
+	// (e.g. embedded spaces). But because Windows invokes any child process with
+	// a single command-line string, this means we must quote each argument behind
+	// the scenes.
+	std::string args = LLStringUtil::quote(params.executable);
 	BOOST_FOREACH(const std::string& arg, params.args)
 	{
 		args += " ";
-		args += quote(arg);
+		args += LLStringUtil::quote(arg);
 	}
 
 	// So retarded.  Windows requires that the second parameter to
@@ -236,39 +246,6 @@ bool LLProcess::kill(void)
 	return ! isRunning();
 }
 
-/**
- * Double-quote an argument string, unless it's already double-quoted. If we
- * quote it, escape any embedded double-quote with backslash.
- *
- * LLProcess::create()'s caller passes a Unix-style array of strings for
- * command-line arguments. Our caller can and should expect that these will be
- * passed to the child process as individual arguments, regardless of content
- * (e.g. embedded spaces). But because Windows invokes any child process with
- * a single command-line string, this means we must quote each argument behind
- * the scenes.
- */
-static std::string quote(const std::string& str)
-{
-	std::string::size_type len(str.length());
-	// If the string is already quoted, assume user knows what s/he's doing.
-	if (len >= 2 && str[0] == '"' && str[len-1] == '"')
-	{
-		return str;
-	}
-
-	// Not already quoted: do it.
-	std::string result("\"");
-	for (std::string::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
-	{
-		if (*ci == '"')
-		{
-			result.append("\\");
-		}
-		result.push_back(*ci);
-	}
-	return result + "\"";
-}
-
 /// GetLastError()/FormatMessage() boilerplate
 static std::string WindowsErrorString(const std::string& operation)
 {
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 7e41e787b5..d3f1d01aa2 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -237,40 +237,41 @@ private:
 	static std::string sLocale;
 
 public:
-	typedef typename std::basic_string<T>::size_type size_type;
+	typedef std::basic_string<T> string_type;
+	typedef typename string_type::size_type size_type;
 	
 public:
 	/////////////////////////////////////////////////////////////////////////////////////////
 	// Static Utility functions that operate on std::strings
 
-	static const std::basic_string<T> null;
+	static const string_type null;
 	
 	typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
-	LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
-	LL_COMMON_API static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
-	LL_COMMON_API static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
-	LL_COMMON_API static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
-	LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
-	LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
-	LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions);
+	LL_COMMON_API static void getTokens(const string_type& instr, std::vector<string_type >& tokens, const string_type& delims);
+	LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals);
+	LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch);
+	LL_COMMON_API static S32 format(string_type& s, const format_map_t& substitutions);
+	LL_COMMON_API static S32 format(string_type& s, const LLSD& substitutions);
+	LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const format_map_t& substitutions);
+	LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const LLSD& substitutions);
 	LL_COMMON_API static void setLocale (std::string inLocale);
 	LL_COMMON_API static std::string getLocale (void);
 	
-	static bool isValidIndex(const std::basic_string<T>& string, size_type i)
+	static bool isValidIndex(const string_type& string, size_type i)
 	{
 		return !string.empty() && (0 <= i) && (i <= string.size());
 	}
 
-	static void	trimHead(std::basic_string<T>& string);
-	static void	trimTail(std::basic_string<T>& string);
-	static void	trim(std::basic_string<T>& string)	{ trimHead(string); trimTail(string); }
-	static void truncate(std::basic_string<T>& string, size_type count);
+	static void	trimHead(string_type& string);
+	static void	trimTail(string_type& string);
+	static void	trim(string_type& string)	{ trimHead(string); trimTail(string); }
+	static void truncate(string_type& string, size_type count);
 
-	static void	toUpper(std::basic_string<T>& string);
-	static void	toLower(std::basic_string<T>& string);
+	static void	toUpper(string_type& string);
+	static void	toLower(string_type& string);
 	
 	// True if this is the head of s.
-	static BOOL	isHead( const std::basic_string<T>& string, const T* s ); 
+	static BOOL	isHead( const string_type& string, const T* s ); 
 
 	/**
 	 * @brief Returns true if string starts with substr
@@ -278,8 +279,8 @@ public:
 	 * If etither string or substr are empty, this method returns false.
 	 */
 	static bool startsWith(
-		const std::basic_string<T>& string,
-		const std::basic_string<T>& substr);
+		const string_type& string,
+		const string_type& substr);
 
 	/**
 	 * @brief Returns true if string ends in substr
@@ -287,19 +288,26 @@ public:
 	 * If etither string or substr are empty, this method returns false.
 	 */
 	static bool endsWith(
-		const std::basic_string<T>& string,
-		const std::basic_string<T>& substr);
+		const string_type& string,
+		const string_type& substr);
 
-	static void	addCRLF(std::basic_string<T>& string);
-	static void	removeCRLF(std::basic_string<T>& string);
+	static void	addCRLF(string_type& string);
+	static void	removeCRLF(string_type& string);
 
-	static void	replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab );
-	static void	replaceNonstandardASCII( std::basic_string<T>& string, T replacement );
-	static void	replaceChar( std::basic_string<T>& string, T target, T replacement );
-	static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement );
+	static void	replaceTabsWithSpaces( string_type& string, size_type spaces_per_tab );
+	static void	replaceNonstandardASCII( string_type& string, T replacement );
+	static void	replaceChar( string_type& string, T target, T replacement );
+	static void replaceString( string_type& string, string_type target, string_type replacement );
 	
-	static BOOL	containsNonprintable(const std::basic_string<T>& string);
-	static void	stripNonprintable(std::basic_string<T>& string);
+	static BOOL	containsNonprintable(const string_type& string);
+	static void	stripNonprintable(string_type& string);
+
+	/**
+	 * Double-quote an argument string, unless it's already double-quoted. If we
+	 * quote it, escape any embedded double-quote with the escape string (default
+	 * backslash).
+	 */
+	string_type quote(const string_type& str, const string_type& escape="\\");
 
 	/**
 	 * @brief Unsafe way to make ascii characters. You should probably
@@ -308,18 +316,18 @@ public:
 	 * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII
 	 * should work.
 	 */
-	static void _makeASCII(std::basic_string<T>& string);
+	static void _makeASCII(string_type& string);
 
 	// Conversion to other data types
-	static BOOL	convertToBOOL(const std::basic_string<T>& string, BOOL& value);
-	static BOOL	convertToU8(const std::basic_string<T>& string, U8& value);
-	static BOOL	convertToS8(const std::basic_string<T>& string, S8& value);
-	static BOOL	convertToS16(const std::basic_string<T>& string, S16& value);
-	static BOOL	convertToU16(const std::basic_string<T>& string, U16& value);
-	static BOOL	convertToU32(const std::basic_string<T>& string, U32& value);
-	static BOOL	convertToS32(const std::basic_string<T>& string, S32& value);
-	static BOOL	convertToF32(const std::basic_string<T>& string, F32& value);
-	static BOOL	convertToF64(const std::basic_string<T>& string, F64& value);
+	static BOOL	convertToBOOL(const string_type& string, BOOL& value);
+	static BOOL	convertToU8(const string_type& string, U8& value);
+	static BOOL	convertToS8(const string_type& string, S8& value);
+	static BOOL	convertToS16(const string_type& string, S16& value);
+	static BOOL	convertToU16(const string_type& string, U16& value);
+	static BOOL	convertToU32(const string_type& string, U32& value);
+	static BOOL	convertToS32(const string_type& string, S32& value);
+	static BOOL	convertToF32(const string_type& string, F32& value);
+	static BOOL	convertToF64(const string_type& string, F64& value);
 
 	/////////////////////////////////////////////////////////////////////////////////////////
 	// Utility functions for working with char*'s and strings
@@ -327,24 +335,24 @@ public:
 	// Like strcmp but also handles empty strings. Uses
 	// current locale.
 	static S32		compareStrings(const T* lhs, const T* rhs);
-	static S32		compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
+	static S32		compareStrings(const string_type& lhs, const string_type& rhs);
 	
 	// case insensitive version of above. Uses current locale on
 	// Win32, and falls back to a non-locale aware comparison on
 	// Linux.
 	static S32		compareInsensitive(const T* lhs, const T* rhs);
-	static S32		compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
+	static S32		compareInsensitive(const string_type& lhs, const string_type& rhs);
 
 	// Case sensitive comparison with good handling of numbers.  Does not use current locale.
 	// a.k.a. strdictcmp()
-	static S32		compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b);
+	static S32		compareDict(const string_type& a, const string_type& b);
 
 	// Case *in*sensitive comparison with good handling of numbers.  Does not use current locale.
 	// a.k.a. strdictcmp()
-	static S32		compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b);
+	static S32		compareDictInsensitive(const string_type& a, const string_type& b);
 
 	// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
-	static BOOL		precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
+	static BOOL		precedesDict( const string_type& a, const string_type& b );
 
 	// A replacement for strncpy.
 	// If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds
@@ -352,7 +360,7 @@ public:
 	static void		copy(T* dst, const T* src, size_type dst_size);
 	
 	// Copies src into dst at a given offset.  
-	static void		copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset);
+	static void		copyInto(string_type& dst, const string_type& src, size_type offset);
 	
 	static bool		isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); }
 
@@ -362,7 +370,7 @@ public:
 #endif
 
 private:
-	LL_COMMON_API static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
+	LL_COMMON_API static size_type getSubstitution(const string_type& instr, size_type& start, std::vector<string_type >& tokens);
 };
 
 template<class T> const std::basic_string<T> LLStringUtilBase<T>::null;
@@ -669,7 +677,7 @@ S32 LLStringUtilBase<T>::compareStrings(const T* lhs, const T* rhs)
 
 //static 
 template<class T> 
-S32 LLStringUtilBase<T>::compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
+S32 LLStringUtilBase<T>::compareStrings(const string_type& lhs, const string_type& rhs)
 {
 	return LLStringOps::collate(lhs.c_str(), rhs.c_str());
 }
@@ -695,8 +703,8 @@ S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs )
 	}
 	else
 	{
-		std::basic_string<T> lhs_string(lhs);
-		std::basic_string<T> rhs_string(rhs);
+		string_type lhs_string(lhs);
+		string_type rhs_string(rhs);
 		LLStringUtilBase<T>::toUpper(lhs_string);
 		LLStringUtilBase<T>::toUpper(rhs_string);
 		result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
@@ -706,10 +714,10 @@ S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs )
 
 //static 
 template<class T> 
-S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
+S32 LLStringUtilBase<T>::compareInsensitive(const string_type& lhs, const string_type& rhs)
 {
-	std::basic_string<T> lhs_string(lhs);
-	std::basic_string<T> rhs_string(rhs);
+	string_type lhs_string(lhs);
+	string_type rhs_string(rhs);
 	LLStringUtilBase<T>::toUpper(lhs_string);
 	LLStringUtilBase<T>::toUpper(rhs_string);
 	return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
@@ -720,7 +728,7 @@ S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, con
 
 //static 
 template<class T>
-S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
+S32 LLStringUtilBase<T>::compareDict(const string_type& astr, const string_type& bstr)
 {
 	const T* a = astr.c_str();
 	const T* b = bstr.c_str();
@@ -761,7 +769,7 @@ S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std
 
 // static
 template<class T>
-S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
+S32 LLStringUtilBase<T>::compareDictInsensitive(const string_type& astr, const string_type& bstr)
 {
 	const T* a = astr.c_str();
 	const T* b = bstr.c_str();
@@ -796,7 +804,7 @@ S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr
 // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
 // static 
 template<class T> 
-BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b )
+BOOL LLStringUtilBase<T>::precedesDict( const string_type& a, const string_type& b )
 {
 	if( a.size() && b.size() )
 	{
@@ -810,7 +818,7 @@ BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std
 
 //static
 template<class T> 
-void LLStringUtilBase<T>::toUpper(std::basic_string<T>& string)	
+void LLStringUtilBase<T>::toUpper(string_type& string)	
 { 
 	if( !string.empty() )
 	{ 
@@ -824,7 +832,7 @@ void LLStringUtilBase<T>::toUpper(std::basic_string<T>& string)
 
 //static
 template<class T> 
-void LLStringUtilBase<T>::toLower(std::basic_string<T>& string)
+void LLStringUtilBase<T>::toLower(string_type& string)
 { 
 	if( !string.empty() )
 	{ 
@@ -838,7 +846,7 @@ void LLStringUtilBase<T>::toLower(std::basic_string<T>& string)
 
 //static
 template<class T> 
-void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string)
+void LLStringUtilBase<T>::trimHead(string_type& string)
 {			
 	if( !string.empty() )
 	{
@@ -853,7 +861,7 @@ void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string)
 
 //static
 template<class T> 
-void LLStringUtilBase<T>::trimTail(std::basic_string<T>& string)
+void LLStringUtilBase<T>::trimTail(string_type& string)
 {			
 	if( string.size() )
 	{
@@ -872,7 +880,7 @@ void LLStringUtilBase<T>::trimTail(std::basic_string<T>& string)
 // Replace line feeds with carriage return-line feed pairs.
 //static
 template<class T>
-void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string)
+void LLStringUtilBase<T>::addCRLF(string_type& string)
 {
 	const T LF = 10;
 	const T CR = 13;
@@ -914,7 +922,7 @@ void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string)
 // Remove all carriage returns
 //static
 template<class T> 
-void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& string)
+void LLStringUtilBase<T>::removeCRLF(string_type& string)
 {
 	const T CR = 13;
 
@@ -935,10 +943,10 @@ void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& string)
 
 //static
 template<class T> 
-void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
+void LLStringUtilBase<T>::replaceChar( string_type& string, T target, T replacement )
 {
 	size_type found_pos = 0;
-	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) 
+	while( (found_pos = string.find(target, found_pos)) != string_type::npos ) 
 	{
 		string[found_pos] = replacement;
 		found_pos++; // avoid infinite defeat if target == replacement
@@ -947,10 +955,10 @@ void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T
 
 //static
 template<class T> 
-void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement )
+void LLStringUtilBase<T>::replaceString( string_type& string, string_type target, string_type replacement )
 {
 	size_type found_pos = 0;
-	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
+	while( (found_pos = string.find(target, found_pos)) != string_type::npos )
 	{
 		string.replace( found_pos, target.length(), replacement );
 		found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
@@ -959,7 +967,7 @@ void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basi
 
 //static
 template<class T> 
-void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T replacement )
+void LLStringUtilBase<T>::replaceNonstandardASCII( string_type& string, T replacement )
 {
 	const char LF = 10;
 	const S8 MIN = 32;
@@ -979,12 +987,12 @@ void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& string,
 
 //static
 template<class T> 
-void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab )
+void LLStringUtilBase<T>::replaceTabsWithSpaces( string_type& str, size_type spaces_per_tab )
 {
 	const T TAB = '\t';
 	const T SPACE = ' ';
 
-	std::basic_string<T> out_str;
+	string_type out_str;
 	// Replace tabs with spaces
 	for (size_type i = 0; i < str.length(); i++)
 	{
@@ -1003,7 +1011,7 @@ void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size
 
 //static
 template<class T> 
-BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& string)
+BOOL LLStringUtilBase<T>::containsNonprintable(const string_type& string)
 {
 	const char MIN = 32;
 	BOOL rv = FALSE;
@@ -1020,7 +1028,7 @@ BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& strin
 
 //static
 template<class T> 
-void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string)
+void LLStringUtilBase<T>::stripNonprintable(string_type& string)
 {
 	const char MIN = 32;
 	size_type j = 0;
@@ -1051,8 +1059,33 @@ void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string)
 	delete []c_string;
 }
 
+template<class T>
+std::basic_string<T> LLStringUtilBase<T>::quote(const string_type& str, const string_type& escape)
+{
+	size_type len(str.length());
+	// If the string is already quoted, assume user knows what s/he's doing.
+	if (len >= 2 && str[0] == '"' && str[len-1] == '"')
+	{
+		return str;
+	}
+
+	// Not already quoted: do it.
+	string_type result;
+	result.push_back('"');
+	for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
+	{
+		if (*ci == '"')
+		{
+			result.append(escape);
+		}
+		result.push_back(*ci);
+	}
+	result.push_back('"');
+	return result;
+}
+
 template<class T> 
-void LLStringUtilBase<T>::_makeASCII(std::basic_string<T>& string)
+void LLStringUtilBase<T>::_makeASCII(string_type& string)
 {
 	// Replace non-ASCII chars with LL_UNKNOWN_CHAR
 	for (size_type i = 0; i < string.length(); i++)
@@ -1082,7 +1115,7 @@ void LLStringUtilBase<T>::copy( T* dst, const T* src, size_type dst_size )
 
 // static
 template<class T> 
-void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset)
+void LLStringUtilBase<T>::copyInto(string_type& dst, const string_type& src, size_type offset)
 {
 	if ( offset == dst.length() )
 	{
@@ -1092,7 +1125,7 @@ void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_s
 	}
 	else
 	{
-		std::basic_string<T> tail = dst.substr(offset);
+		string_type tail = dst.substr(offset);
 
 		dst = dst.substr(0, offset);
 		dst += src;
@@ -1103,7 +1136,7 @@ void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_s
 // True if this is the head of s.
 //static
 template<class T> 
-BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s ) 
+BOOL LLStringUtilBase<T>::isHead( const string_type& string, const T* s ) 
 { 
 	if( string.empty() )
 	{
@@ -1119,8 +1152,8 @@ BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s
 // static
 template<class T> 
 bool LLStringUtilBase<T>::startsWith(
-	const std::basic_string<T>& string,
-	const std::basic_string<T>& substr)
+	const string_type& string,
+	const string_type& substr)
 {
 	if(string.empty() || (substr.empty())) return false;
 	if(0 == string.find(substr)) return true;
@@ -1130,8 +1163,8 @@ bool LLStringUtilBase<T>::startsWith(
 // static
 template<class T> 
 bool LLStringUtilBase<T>::endsWith(
-	const std::basic_string<T>& string,
-	const std::basic_string<T>& substr)
+	const string_type& string,
+	const string_type& substr)
 {
 	if(string.empty() || (substr.empty())) return false;
 	std::string::size_type idx = string.rfind(substr);
@@ -1141,14 +1174,14 @@ bool LLStringUtilBase<T>::endsWith(
 
 
 template<class T> 
-BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value)
+BOOL LLStringUtilBase<T>::convertToBOOL(const string_type& string, BOOL& value)
 {
 	if( string.empty() )
 	{
 		return FALSE;
 	}
 
-	std::basic_string<T> temp( string );
+	string_type temp( string );
 	trim(temp);
 	if( 
 		(temp == "1") || 
@@ -1178,7 +1211,7 @@ BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL
 }
 
 template<class T> 
-BOOL LLStringUtilBase<T>::convertToU8(const std::basic_string<T>& string, U8& value) 
+BOOL LLStringUtilBase<T>::convertToU8(const string_type& string, U8& value) 
 {
 	S32 value32 = 0;
 	BOOL success = convertToS32(string, value32);
@@ -1191,7 +1224,7 @@ BOOL LLStringUtilBase<T>::convertToU8(const std::basic_string<T>& string, U8& va
 }
 
 template<class T> 
-BOOL LLStringUtilBase<T>::convertToS8(const std::basic_string<T>& string, S8& value) 
+BOOL LLStringUtilBase<T>::convertToS8(const string_type& string, S8& value) 
 {
 	S32 value32 = 0;
 	BOOL success = convertToS32(string, value32);
@@ -1204,7 +1237,7 @@ BOOL LLStringUtilBase<T>::convertToS8(const std::basic_string<T>& string, S8& va
 }
 
 template<class T> 
-BOOL LLStringUtilBase<T>::convertToS16(const std::basic_string<T>& string, S16& value) 
+BOOL LLStringUtilBase<T>::convertToS16(const string_type& string, S16& value) 
 {
 	S32 value32 = 0;
 	BOOL success = convertToS32(string, value32);
@@ -1217,7 +1250,7 @@ BOOL LLStringUtilBase<T>::convertToS16(const std::basic_string<T>& string, S16&
 }
 
 template<class T> 
-BOOL LLStringUtilBase<T>::convertToU16(const std::basic_string<T>& string, U16& value) 
+BOOL LLStringUtilBase<T>::convertToU16(const string_type& string, U16& value) 
 {
 	S32 value32 = 0;
 	BOOL success = convertToS32(string, value32);
@@ -1230,17 +1263,17 @@ BOOL LLStringUtilBase<T>::convertToU16(const std::basic_string<T>& string, U16&
 }
 
 template<class T> 
-BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32& value) 
+BOOL LLStringUtilBase<T>::convertToU32(const string_type& string, U32& value) 
 {
 	if( string.empty() )
 	{
 		return FALSE;
 	}
 
-	std::basic_string<T> temp( string );
+	string_type temp( string );
 	trim(temp);
 	U32 v;
-	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
+	std::basic_istringstream<T> i_stream((string_type)temp);
 	if(i_stream >> v)
 	{
 		value = v;
@@ -1250,17 +1283,17 @@ BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32&
 }
 
 template<class T> 
-BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& value) 
+BOOL LLStringUtilBase<T>::convertToS32(const string_type& string, S32& value) 
 {
 	if( string.empty() )
 	{
 		return FALSE;
 	}
 
-	std::basic_string<T> temp( string );
+	string_type temp( string );
 	trim(temp);
 	S32 v;
-	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
+	std::basic_istringstream<T> i_stream((string_type)temp);
 	if(i_stream >> v)
 	{
 		//TODO: figure out overflow and underflow reporting here
@@ -1277,7 +1310,7 @@ BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32&
 }
 
 template<class T> 
-BOOL LLStringUtilBase<T>::convertToF32(const std::basic_string<T>& string, F32& value) 
+BOOL LLStringUtilBase<T>::convertToF32(const string_type& string, F32& value) 
 {
 	F64 value64 = 0.0;
 	BOOL success = convertToF64(string, value64);
@@ -1290,17 +1323,17 @@ BOOL LLStringUtilBase<T>::convertToF32(const std::basic_string<T>& string, F32&
 }
 
 template<class T> 
-BOOL LLStringUtilBase<T>::convertToF64(const std::basic_string<T>& string, F64& value)
+BOOL LLStringUtilBase<T>::convertToF64(const string_type& string, F64& value)
 {
 	if( string.empty() )
 	{
 		return FALSE;
 	}
 
-	std::basic_string<T> temp( string );
+	string_type temp( string );
 	trim(temp);
 	F64 v;
-	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
+	std::basic_istringstream<T> i_stream((string_type)temp);
 	if(i_stream >> v)
 	{
 		//TODO: figure out overflow and underflow reporting here
@@ -1317,7 +1350,7 @@ BOOL LLStringUtilBase<T>::convertToF64(const std::basic_string<T>& string, F64&
 }
 
 template<class T> 
-void LLStringUtilBase<T>::truncate(std::basic_string<T>& string, size_type count)
+void LLStringUtilBase<T>::truncate(string_type& string, size_type count)
 {
 	size_type cur_size = string.size();
 	string.resize(count < cur_size ? count : cur_size);
-- 
cgit v1.2.3


From ca9f000289f93068386835d7040e5a574507f859 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 23 Jan 2012 13:40:20 -0800
Subject: * Optimization to not waste some time doing std::string assignment
 all over the graphics code.

Reviewed by davep.
---
 indra/newview/pipeline.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index df8f8793d1..50adbad140 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1217,10 +1217,12 @@ void LLPipeline::restoreGL()
 
 BOOL LLPipeline::canUseVertexShaders()
 {
+	static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable";
+
 	if (sDisableShaders ||
 		!gGLManager.mHasVertexShader ||
 		!gGLManager.mHasFragmentShader ||
-		!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") ||
+		!LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) ||
 		(assertInitialized() && mVertexShadersLoaded != 1) )
 	{
 		return FALSE;
-- 
cgit v1.2.3


From 199e875210435cbc914e80bf3eb6be6c985fce1c Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 23 Jan 2012 17:04:18 -0500
Subject: Use LLProcess::Params::args::empty() instead of comparing iterators.

---
 indra/newview/llexternaleditor.cpp | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp
index 561b87618c..db482f023e 100644
--- a/indra/newview/llexternaleditor.cpp
+++ b/indra/newview/llexternaleditor.cpp
@@ -81,10 +81,7 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env
 
 LLExternalEditor::EErrorCode LLExternalEditor::run(const std::string& file_path)
 {
-	// LLInitParams type wrappers don't seem to have empty() or size()
-	// methods; try determining emptiness by comparing begin/end iterators.
-	if (std::string(mProcessParams.executable).empty() ||
-	    (mProcessParams.args.begin() == mProcessParams.args.end()))
+	if (std::string(mProcessParams.executable).empty() || mProcessParams.args.empty())
 	{
 		llwarns << "Editor command not set" << llendl;
 		return EC_NOT_SPECIFIED;
-- 
cgit v1.2.3


From da5d243c8f76f43a6bb4000402fade76eee0be33 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 23 Jan 2012 17:29:42 -0500
Subject: LLStringUtil methods are conventionally static.

---
 indra/llcommon/llstring.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index d3f1d01aa2..4c3936f9ab 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -307,7 +307,7 @@ public:
 	 * quote it, escape any embedded double-quote with the escape string (default
 	 * backslash).
 	 */
-	string_type quote(const string_type& str, const string_type& escape="\\");
+	static string_type quote(const string_type& str, const string_type& escape="\\");
 
 	/**
 	 * @brief Unsafe way to make ascii characters. You should probably
-- 
cgit v1.2.3


From 61e98256df80822f9504a2037d5cbb029c39506d Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 23 Jan 2012 17:38:06 -0500
Subject: Clarify that items in LLProcess::Params::args are implicitly quoted.
 That is, we try to pass through each args entry as a separate child-process
 arvg[] entry, whitespace and all.

---
 indra/llcommon/llprocess.h | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 019c33592c..51c42582ea 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -63,7 +63,16 @@ public:
 
 		/// pathname of executable
 		Mandatory<std::string> executable;
-		/// zero or more additional command-line arguments
+		/**
+		 * zero or more additional command-line arguments. Arguments are
+		 * passed through as exactly as we can manage, whitespace and all.
+		 * @note On Windows we manage this by implicitly double-quoting each
+		 * argument while assembling the command line. BUT if a given argument
+		 * is already double-quoted, we don't double-quote it again. Try to
+		 * avoid making use of this, though, as on Mac and Linux explicitly
+		 * double-quoted args will be passed to the child process including
+		 * the double quotes.
+		 */
 		Multiple<std::string> args;
 		/// current working directory, if need it changed
 		Optional<std::string> cwd;
-- 
cgit v1.2.3


From 83ca425158fb56cab08c8a44ddad93ca222e58d7 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 23 Jan 2012 15:34:01 -0800
Subject: Reverting rev 22217 changes to background fetch so search and recent
 will fully fetch user inventory

---
 indra/newview/llinventorymodelbackgroundfetch.cpp | 328 +++++++---------------
 indra/newview/llinventorymodelbackgroundfetch.h   |  16 +-
 2 files changed, 115 insertions(+), 229 deletions(-)

diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 5f0c744192..91fdd67806 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -50,7 +50,7 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :
 	mMinTimeBetweenFetches(0.3f),
 	mMaxTimeBetweenFetches(10.f),
 	mTimelyFetchPending(FALSE),
-	mFetchCount(0)
+	mBulkFetchCount(0)
 {
 }
 
@@ -60,7 +60,7 @@ LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()
 
 bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const
 {
-	return mFetchQueue.empty() && mFetchCount<=0;
+	return mFetchQueue.empty() && mBulkFetchCount<=0;
 }
 
 bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const
@@ -103,60 +103,44 @@ BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() const
 	return mBackgroundFetchActive;
 }
 
-void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)
+void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive)
 {
-	if (id.isNull()) return;
+	if (!mAllFoldersFetched || cat_id.notNull())
+	{
+		LL_DEBUGS("InventoryFetch") << "Start fetching category: " << cat_id << ", recursive: " << recursive << LL_ENDL;
 
-	LLViewerInventoryCategory* cat = gInventory.getCategory(id);
-	if (cat)
-	{	// it's a folder, do a bulk fetch
-		if (!mAllFoldersFetched)
+		mBackgroundFetchActive = TRUE;
+		if (cat_id.isNull())
 		{
-			LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL;
-
-			mBackgroundFetchActive = TRUE;
-			if (id.isNull())
+			if (!mRecursiveInventoryFetchStarted)
 			{
-				if (!mRecursiveInventoryFetchStarted)
-				{
-					mRecursiveInventoryFetchStarted |= recursive;
-					mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive));
-					gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
-				}
-				if (!mRecursiveLibraryFetchStarted)
-				{
-					mRecursiveLibraryFetchStarted |= recursive;
-					mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive));
-					gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
-				}
+				mRecursiveInventoryFetchStarted |= recursive;
+				mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive));
+				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
 			}
-			else
+			if (!mRecursiveLibraryFetchStarted)
 			{
-				// Specific folder requests go to front of queue.
-				if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)
-				{
-					mFetchQueue.push_front(FetchQueueInfo(id, recursive));
-					gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
-				}
-				if (id == gInventory.getLibraryRootFolderID())
-				{
-					mRecursiveLibraryFetchStarted |= recursive;
-				}
-				if (id == gInventory.getRootFolderID())
-				{
-					mRecursiveInventoryFetchStarted |= recursive;
-				}
+				mRecursiveLibraryFetchStarted |= recursive;
+				mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive));
+				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
 			}
 		}
-	}
-	else if (LLViewerInventoryItem* itemp = gInventory.getItem(id))
-	{
-		if (!itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id))
+		else
 		{
-			mBackgroundFetchActive = TRUE;
-
-			mFetchQueue.push_front(FetchQueueInfo(id, false, false));
-			gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
+			// Specific folder requests go to front of queue.
+			if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id)
+			{
+				mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive));
+				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
+			}
+			if (cat_id == gInventory.getLibraryRootFolderID())
+			{
+				mRecursiveLibraryFetchStarted |= recursive;
+			}
+			if (cat_id == gInventory.getRootFolderID())
+			{
+				mRecursiveInventoryFetchStarted |= recursive;
+			}
 		}
 	}
 }
@@ -174,7 +158,7 @@ void LLInventoryModelBackgroundFetch::stopBackgroundFetch()
 	{
 		mBackgroundFetchActive = FALSE;
 		gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
-		mFetchCount=0;
+		mBulkFetchCount=0;
 		mMinTimeBetweenFetches=0.0f;
 	}
 }
@@ -199,9 +183,10 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
 	if (mBackgroundFetchActive && gAgent.getRegion())
 	{
 		// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
-		if (gSavedSettings.getBOOL("UseHTTPInventory")) 
+		std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");   
+		if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty()) 
 		{
-			bulkFetch();
+			bulkFetch(url);
 			return;
 		}
 		
@@ -245,7 +230,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
 			}
 
 			const FetchQueueInfo info = mFetchQueue.front();
-			LLViewerInventoryCategory* cat = gInventory.getCategory(info.mUUID);
+			LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID);
 
 			// Category has been deleted, remove from queue.
 			if (!cat)
@@ -273,7 +258,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
 				}
 			}
 			// Do I have all my children?
-			else if (gInventory.isCategoryComplete(info.mUUID))
+			else if (gInventory.isCategoryComplete(info.mCatUUID))
 			{
 				// Finished with this category, remove from queue.
 				mFetchQueue.pop_front();
@@ -328,35 +313,15 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
 	}
 }
 
-void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching) 
+void LLInventoryModelBackgroundFetch::incrBulkFetch(S16 fetching) 
 {  
-	mFetchCount += fetching; 
-	if (mFetchCount < 0)
+	mBulkFetchCount += fetching; 
+	if (mBulkFetchCount < 0)
 	{
-		mFetchCount = 0; 
+		mBulkFetchCount = 0; 
 	}
 }
 
-class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder
-{
-public:
-	LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {};
-	void result(const LLSD& content);			
-	void error(U32 status, const std::string& reason);
-};
-
-void LLInventoryModelFetchItemResponder::result( const LLSD& content )
-{
-	LLInventoryModel::fetchInventoryResponder::result(content);
-	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
-}
-
-void LLInventoryModelFetchItemResponder::error( U32 status, const std::string& reason )
-{
-	LLInventoryModel::fetchInventoryResponder::error(status, reason);
-	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
-}
-
 
 class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
 {
@@ -493,7 +458,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
 		}
 	}
 
-	fetcher->incrFetchCount(-1);
+	fetcher->incrBulkFetch(-1);
 	
 	if (fetcher->isBulkFetchProcessingComplete())
 	{
@@ -512,7 +477,7 @@ void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::str
 	llinfos << "LLInventoryModelFetchDescendentsResponder::error "
 		<< status << ": " << reason << llendl;
 						
-	fetcher->incrFetchCount(-1);
+	fetcher->incrBulkFetch(-1);
 
 	if (status==499) // timed out
 	{
@@ -543,14 +508,12 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat
 
 // Bundle up a bunch of requests to send all at once.
 // static   
-void LLInventoryModelBackgroundFetch::bulkFetch()
+void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
 {
 	//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped.
 	//If there are items in mFetchQueue, we want to check the time since the last bulkFetch was 
 	//sent.  If it exceeds our retry time, go ahead and fire off another batch.  
 	//Stopbackgroundfetch will be run from the Responder instead of here.  
-	LLViewerRegion* region = gAgent.getRegion();
-	if (!region) return;
 
 	S16 max_concurrent_fetches=8;
 	F32 new_min_time = 0.5f;			//HACK!  Clean this up when old code goes away entirely.
@@ -560,13 +523,12 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
 	}
 	
 	if (gDisconnected ||
-		(mFetchCount > max_concurrent_fetches) ||
+		(mBulkFetchCount > max_concurrent_fetches) ||
 		(mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches))
 	{
 		return; // just bail if we are disconnected
 	}	
 
-	U32 item_count=0;
 	U32 folder_count=0;
 	U32 max_batch_size=5;
 
@@ -574,159 +536,83 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
 
 	uuid_vec_t recursive_cats;
 
-	LLSD folder_request_body;
-	LLSD folder_request_body_lib;
-	LLSD item_request_body;
-	LLSD item_request_body_lib;
+	LLSD body;
+	LLSD body_lib;
 
-	while (!(mFetchQueue.empty()) && ((item_count + folder_count) < max_batch_size))
+	while (!(mFetchQueue.empty()) && (folder_count < max_batch_size))
 	{
 		const FetchQueueInfo& fetch_info = mFetchQueue.front();
-		if (fetch_info.mIsCategory)
-		{
-
-			const LLUUID &cat_id = fetch_info.mUUID;
-			if (cat_id.isNull()) //DEV-17797
-			{
-				LLSD folder_sd;
-				folder_sd["folder_id"]		= LLUUID::null.asString();
-				folder_sd["owner_id"]		= gAgent.getID();
-				folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
-				folder_sd["fetch_folders"]	= (LLSD::Boolean)FALSE;
-				folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
-				folder_request_body["folders"].append(folder_sd);
-				folder_count++;
-			}
-			else
-			{
-				const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
+		const LLUUID &cat_id = fetch_info.mCatUUID;
+        if (cat_id.isNull()) //DEV-17797
+        {
+			LLSD folder_sd;
+			folder_sd["folder_id"]		= LLUUID::null.asString();
+			folder_sd["owner_id"]		= gAgent.getID();
+			folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
+			folder_sd["fetch_folders"]	= (LLSD::Boolean)FALSE;
+			folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
+			body["folders"].append(folder_sd);
+            folder_count++;
+        }
+        else
+        {
+		    const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
 		
-				if (cat)
-				{
-					if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
-					{
-						LLSD folder_sd;
-						folder_sd["folder_id"]		= cat->getUUID();
-						folder_sd["owner_id"]		= cat->getOwnerID();
-						folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
-						folder_sd["fetch_folders"]	= TRUE; //(LLSD::Boolean)sFullFetchStarted;
-						folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
+		    if (cat)
+		    {
+			    if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
+			    {
+				    LLSD folder_sd;
+				    folder_sd["folder_id"]		= cat->getUUID();
+				    folder_sd["owner_id"]		= cat->getOwnerID();
+				    folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
+				    folder_sd["fetch_folders"]	= TRUE; //(LLSD::Boolean)sFullFetchStarted;
+				    folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
 				    
-						if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
-							folder_request_body_lib["folders"].append(folder_sd);
-						else
-							folder_request_body["folders"].append(folder_sd);
-						folder_count++;
-					}
-					// May already have this folder, but append child folders to list.
-					if (fetch_info.mRecursive)
-					{	
-						LLInventoryModel::cat_array_t* categories;
-						LLInventoryModel::item_array_t* items;
-						gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
-						for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
-							 it != categories->end();
-							 ++it)
-						{
-							mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
-						}
-					}
-				}
-			}
-			if (fetch_info.mRecursive)
-				recursive_cats.push_back(cat_id);
-		}
-		else
-		{
-			LLViewerInventoryItem* itemp = gInventory.getItem(fetch_info.mUUID);
-			if (itemp)
-			{
-				LLSD item_sd;
-				item_sd["owner_id"] = itemp->getPermissions().getOwner();
-				item_sd["item_id"] = itemp->getUUID();
-				if (itemp->getPermissions().getOwner() == gAgent.getID())
-				{
-					item_request_body.append(item_sd);
-				}
-				else
-				{
-					item_request_body_lib.append(item_sd);
-				}
-				//itemp->fetchFromServer();
-				item_count++;
-			}
-		}
+				    if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
+					    body_lib["folders"].append(folder_sd);
+				    else
+					    body["folders"].append(folder_sd);
+				    folder_count++;
+			    }
+				// May already have this folder, but append child folders to list.
+			    if (fetch_info.mRecursive)
+			    {	
+					LLInventoryModel::cat_array_t* categories;
+					LLInventoryModel::item_array_t* items;
+					gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
+					for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
+						 it != categories->end();
+						 ++it)
+					{
+						mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
+				    }
+			    }
+		    }
+        }
+		if (fetch_info.mRecursive)
+			recursive_cats.push_back(cat_id);
 
 		mFetchQueue.pop_front();
 	}
 		
-	if (item_count + folder_count > 0)
+	if (folder_count > 0)
 	{
-		if (folder_count)
+		mBulkFetchCount++;
+		if (body["folders"].size())
 		{
-			std::string url = region->getCapability("FetchInventoryDescendents2");   
-			mFetchCount++;
-			if (folder_request_body["folders"].size())
-			{
-				LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
-				LLHTTPClient::post(url, folder_request_body, fetcher, 300.0);
-			}
-			if (folder_request_body_lib["folders"].size())
-			{
-				std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
-
-				LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
-				LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0);
-			}
+			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body, recursive_cats);
+			LLHTTPClient::post(url, body, fetcher, 300.0);
 		}
-		if (item_count)
+		if (body_lib["folders"].size())
 		{
-			std::string url;
-
-			if (item_request_body.size())
-			{
-				mFetchCount++;
-				url = region->getCapability("FetchInventory2");
-				if (!url.empty())
-				{
-					LLSD body;
-					body["agent_id"]	= gAgent.getID();
-					body["items"] = item_request_body;
-
-					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
-				}
-				//else
-				//{
-				//	LLMessageSystem* msg = gMessageSystem;
-				//	msg->newMessage("FetchInventory");
-				//	msg->nextBlock("AgentData");
-				//	msg->addUUID("AgentID", gAgent.getID());
-				//	msg->addUUID("SessionID", gAgent.getSessionID());
-				//	msg->nextBlock("InventoryData");
-				//	msg->addUUID("OwnerID", mPermissions.getOwner());
-				//	msg->addUUID("ItemID", mUUID);
-				//	gAgent.sendReliableMessage();
-				//}
-			}
-
-			if (item_request_body_lib.size())
-			{
-				mFetchCount++;
-
-				url = region->getCapability("FetchLib2");
-				if (!url.empty())
-				{
-					LLSD body;
-					body["agent_id"]	= gAgent.getID();
-					body["items"] = item_request_body_lib;
-
-					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
-				}
-			}
+			std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
+			
+			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats);
+			LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0);
 		}
 		mFetchTimer.reset();
 	}
-
 	else if (isBulkFetchProcessingComplete())
 	{
 		setAllFoldersFetched();
@@ -738,7 +624,7 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL
 	for (fetch_queue_t::const_iterator it = mFetchQueue.begin();
 		 it != mFetchQueue.end(); ++it)
 	{
-		const LLUUID& fetch_id = (*it).mUUID;
+		const LLUUID& fetch_id = (*it).mCatUUID;
 		if (gInventory.isObjectDescendentOf(fetch_id, cat_id))
 			return false;
 	}
diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h
index 0745407a8c..c35c785ceb 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.h
+++ b/indra/newview/llinventorymodelbackgroundfetch.h
@@ -60,10 +60,10 @@ public:
 	bool inventoryFetchInProgress() const;
 
     void findLostItems();	
-	void incrFetchCount(S16 fetching);
 protected:
+	void incrBulkFetch(S16 fetching);
 	bool isBulkFetchProcessingComplete() const;
-	void bulkFetch();
+	void bulkFetch(std::string url);
 
 	void backgroundFetch();
 	static void backgroundFetchCB(void*); // background fetch idle function
@@ -77,7 +77,7 @@ private:
 	BOOL mAllFoldersFetched;
 
 	BOOL mBackgroundFetchActive;
-	S16 mFetchCount;
+	S16 mBulkFetchCount;
 	BOOL mTimelyFetchPending;
 	S32 mNumFetchRetries;
 
@@ -87,11 +87,11 @@ private:
 
 	struct FetchQueueInfo
 	{
-		FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) :
-			mUUID(id), mRecursive(recursive), mIsCategory(is_category)
-		{}
-		LLUUID mUUID;
-		bool mIsCategory;
+		FetchQueueInfo(const LLUUID& id, BOOL recursive) :
+			mCatUUID(id), mRecursive(recursive)
+		{
+		}
+		LLUUID mCatUUID;
 		BOOL mRecursive;
 	};
 	typedef std::deque<FetchQueueInfo> fetch_queue_t;
-- 
cgit v1.2.3


From ea6cbc7b6b1de051a9bb1c311c4399a2b4d42cb3 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Mon, 23 Jan 2012 15:55:36 -0800
Subject: Reverting background fetch on an item to the old fetFromServer call
 to fix regression bug in inventory late loading

---
 indra/newview/llinventorybridge.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 9e21e2fceb..c0065a94e6 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1324,7 +1324,8 @@ void LLItemBridge::selectItem()
 	LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
 	if(item && !item->isFinished())
 	{
-		LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
+		item->fetchFromServer();
+		//LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
 	}
 }
 
-- 
cgit v1.2.3


From e02f007d2013e089c07f3abefe2d87d85cbcc834 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Tue, 24 Jan 2012 12:59:18 -0600
Subject: SH-1427 Fix for spot lights not working properly on alpha objects,
 and fix for alpha lighting of point lights not matching deferred lights.

---
 indra/llrender/llrender.cpp                                    |  2 +-
 .../app_settings/shaders/class1/deferred/alphaSkinnedV.glsl    |  8 ++++----
 indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl |  9 ++++-----
 .../app_settings/shaders/class1/deferred/avatarAlphaV.glsl     |  8 ++++----
 .../app_settings/shaders/class2/deferred/alphaSkinnedV.glsl    | 10 +++++-----
 indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl |  8 ++++----
 .../app_settings/shaders/class2/deferred/avatarAlphaV.glsl     |  8 ++++----
 indra/newview/pipeline.cpp                                     |  6 ++++--
 8 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index cd827f5091..f26764cc42 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -997,7 +997,7 @@ void LLLightState::setSpotDirection(const LLVector3& direction)
 		const glh::matrix4f& mat = gGL.getModelviewMatrix();
 		mat.mult_matrix_dir(dir);
 
-		mSpotDirection.set(direction);
+		mSpotDirection.set(dir.v);
 	}
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
index 0170ad4b55..40b0cf47ac 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
@@ -61,17 +61,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 	vec3 lv = lp.xyz-v;
 	
 	//get distance
-	float d = length(lv);
+	float d = dot(lv,lv);
 	
 	float da = 0.0;
 
 	if (d > 0.0 && la > 0.0 && fa > 0.0)
 	{
 		//normalize light vector
-		lv *= 1.0/d;
+		lv = normalize(lv);
 	
 		//distance attenuation
-		float dist2 = d*d/(la*la);
+		float dist2 = d/la;
 		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
 
 		// spotlight coefficient.
@@ -79,7 +79,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 		da *= spot*spot; // GL_SPOT_EXPONENT=2
 
 		//angular attenuation
-		da *= calcDirectionalLight(n, lv);
+		da *= max(dot(n, lv), 0.0);		
 	}
 
 	return da;	
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 93b1a114db..8c96d55342 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -70,17 +70,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 	vec3 lv = lp.xyz-v;
 	
 	//get distance
-	float d = length(lv);
+	float d = dot(lv,lv);
 	
 	float da = 0.0;
 
 	if (d > 0.0 && la > 0.0 && fa > 0.0)
 	{
 		//normalize light vector
-		lv *= 1.0/d;
+		lv = normalize(lv);
 	
 		//distance attenuation
-		float dist2 = d*d/(la*la);
+		float dist2 = d/la;
 		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
 
 		// spotlight coefficient.
@@ -88,7 +88,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 		da *= spot*spot; // GL_SPOT_EXPONENT=2
 
 		//angular attenuation
-		da *= calcDirectionalLight(n, lv);
+		da *= max(dot(n, lv), 0.0);		
 	}
 
 	return da;	
@@ -123,7 +123,6 @@ void main()
 	col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z);
 	
 	vary_pointlight_col = col.rgb*diffuse_color.rgb;
-
 	col.rgb = vec3(0,0,0);
 
 	// Add windlight lights
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
index d7b90978ba..c0edddc40a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
@@ -65,17 +65,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 	vec3 lv = lp.xyz-v;
 	
 	//get distance
-	float d = length(lv);
+	float d = dot(lv,lv);
 	
 	float da = 0.0;
 
 	if (d > 0.0 && la > 0.0 && fa > 0.0)
 	{
 		//normalize light vector
-		lv *= 1.0/d;
+		lv = normalize(lv);
 	
 		//distance attenuation
-		float dist2 = d*d/(la*la);
+		float dist2 = d/la;
 		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
 
 		// spotlight coefficient.
@@ -83,7 +83,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 		da *= spot*spot; // GL_SPOT_EXPONENT=2
 
 		//angular attenuation
-		da *= calcDirectionalLight(n, lv);
+		da *= max(dot(n, lv), 0.0);		
 	}
 
 	return da;	
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
index 5a3955ef00..83815b1786 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
@@ -63,21 +63,21 @@ uniform vec3 light_diffuse[8];
 
 float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
-	//get light vector
+//get light vector
 	vec3 lv = lp.xyz-v;
 	
 	//get distance
-	float d = length(lv);
+	float d = dot(lv,lv);
 	
 	float da = 0.0;
 
 	if (d > 0.0 && la > 0.0 && fa > 0.0)
 	{
 		//normalize light vector
-		lv *= 1.0/d;
+		lv = normalize(lv);
 	
 		//distance attenuation
-		float dist2 = d*d/(la*la);
+		float dist2 = d/la;
 		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
 
 		// spotlight coefficient.
@@ -85,7 +85,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 		da *= spot*spot; // GL_SPOT_EXPONENT=2
 
 		//angular attenuation
-		da *= calcDirectionalLight(n, lv);
+		da *= max(dot(n, lv), 0.0);		
 	}
 
 	return da;	
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
index 9540ddd2e8..1660f9687e 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
@@ -69,17 +69,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 	vec3 lv = lp.xyz-v;
 	
 	//get distance
-	float d = length(lv);
+	float d = dot(lv,lv);
 	
 	float da = 0.0;
 
 	if (d > 0.0 && la > 0.0 && fa > 0.0)
 	{
 		//normalize light vector
-		lv *= 1.0/d;
+		lv = normalize(lv);
 	
 		//distance attenuation
-		float dist2 = d*d/(la*la);
+		float dist2 = d/la;
 		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
 
 		// spotlight coefficient.
@@ -87,7 +87,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 		da *= spot*spot; // GL_SPOT_EXPONENT=2
 
 		//angular attenuation
-		da *= calcDirectionalLight(n, lv);
+		da *= max(dot(n, lv), 0.0);		
 	}
 
 	return da;	
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
index 9c7a332417..84c27edb26 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
@@ -66,17 +66,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 	vec3 lv = lp.xyz-v;
 	
 	//get distance
-	float d = length(lv);
+	float d = dot(lv,lv);
 	
 	float da = 0.0;
 
 	if (d > 0.0 && la > 0.0 && fa > 0.0)
 	{
 		//normalize light vector
-		lv *= 1.0/d;
+		lv = normalize(lv);
 	
 		//distance attenuation
-		float dist2 = d*d/(la*la);
+		float dist2 = d/la;
 		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
 
 		// spotlight coefficient.
@@ -84,7 +84,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 		da *= spot*spot; // GL_SPOT_EXPONENT=2
 
 		//angular attenuation
-		da *= calcDirectionalLight(n, lv);
+		da *= max(dot(n, lv), 0.0);		
 	}
 
 	return da;	
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index df8f8793d1..38f9851929 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -5297,7 +5297,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 			light_state->setConstantAttenuation(0.f);
 			if (sRenderDeferred)
 			{
-				light_state->setLinearAttenuation(light_radius*1.5f);
+				F32 size = light_radius*1.5f;
+				light_state->setLinearAttenuation(size*size);
 				light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f);
 			}
 			else
@@ -5319,7 +5320,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 				light_state->setSpotCutoff(90.f);
 				light_state->setSpotExponent(2.f);
 	
-				light_state->setSpecular(LLColor4::black);
+				const LLColor4 specular(0.f, 0.f, 0.f, 0.f);
+				light_state->setSpecular(specular);
 			}
 			else // omnidirectional (point) light
 			{
-- 
cgit v1.2.3


From 63398cd53158e683b12546f4cb2bfb27c78b77da Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Tue, 24 Jan 2012 17:37:20 -0600
Subject: SH-2791 Use request class constructor/destructor for keeping track of
 concurrent requests instead of unreliable increments/decrements sprinkled
 around the code.

---
 indra/newview/llmeshrepository.cpp | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 1d0c262190..03dc7f6bba 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -208,6 +208,12 @@ public:
 	LLMeshHeaderResponder(const LLVolumeParams& mesh_params)
 		: mMeshParams(mesh_params)
 	{
+		LLMeshRepoThread::sActiveHeaderRequests++;
+	}
+
+	~LLMeshHeaderResponder()
+	{
+		LLMeshRepoThread::sActiveHeaderRequests--;
 	}
 
 	virtual void completedRaw(U32 status, const std::string& reason,
@@ -227,6 +233,12 @@ public:
 	LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes)
 		: mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes)
 	{
+		LLMeshRepoThread::sActiveLODRequests++;
+	}
+
+	~LLMeshLODResponder()
+	{
+		LLMeshRepoThread::sActiveLODRequests--;
 	}
 
 	virtual void completedRaw(U32 status, const std::string& reason,
@@ -710,7 +722,6 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
 			{
-				++sActiveLODRequests;
 				LLMeshRepository::sHTTPRequestCount++;
 				mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
 										   new LLMeshSkinInfoResponder(mesh_id, offset, size));
@@ -783,7 +794,6 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
 			{
-				++sActiveLODRequests;
 				LLMeshRepository::sHTTPRequestCount++;
 				mCurlRequest->getByteRange(http_url, headers, offset, size,
 										   new LLMeshDecompositionResponder(mesh_id, offset, size));
@@ -856,7 +866,6 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
 			{
-				++sActiveLODRequests;
 				LLMeshRepository::sHTTPRequestCount++;
 				mCurlRequest->getByteRange(http_url, headers, offset, size,
 										   new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
@@ -907,7 +916,6 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
 	std::string http_url = constructUrl(mesh_params.getSculptID());
 	if (!http_url.empty())
 	{
-		++sActiveHeaderRequests;
 		retval = true;
 		//grab first 4KB if we're going to bother with a fetch.  Cache will prevent future fetches if a full mesh fits
 		//within the first 4KB
@@ -974,7 +982,6 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
 			{
-				++sActiveLODRequests;
 				retval = true;
 				LLMeshRepository::sHTTPRequestCount++;
 				mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
@@ -1718,7 +1725,6 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 {
 
-	LLMeshRepoThread::sActiveLODRequests--;
 	S32 data_size = buffer->countAfter(channels.in(), NULL);
 
 	if (status < 200 || status > 400)
@@ -1935,7 +1941,6 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
 							  const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 {
-	LLMeshRepoThread::sActiveHeaderRequests--;
 	if (status < 200 || status > 400)
 	{
 		//llwarns
-- 
cgit v1.2.3


From 1316f3313066beef74729c2be5a8d142d185161d Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Wed, 25 Jan 2012 16:01:56 -0700
Subject: fix for SH-2904: textures remain stuck in HTP state

---
 indra/llmessage/llcurl.cpp | 11 +++++++++++
 indra/llmessage/llcurl.h   |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 1ab82a273b..32a9cd061f 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -91,6 +91,7 @@ std::string LLCurl::sCAFile;
 LLCurlThread* LLCurl::sCurlThread = NULL ;
 LLMutex* LLCurl::sHandleMutexp = NULL ;
 S32      LLCurl::sTotalHandles = 0 ;
+bool     LLCurl::sNotQuitting = true;
 
 void check_curl_code(CURLcode code)
 {
@@ -319,6 +320,14 @@ LLCurl::Easy::~Easy()
 	--gCurlEasyCount;
 	curl_slist_free_all(mHeaders);
 	for_each(mStrings.begin(), mStrings.end(), DeletePointerArray());
+
+	if (mResponder && LLCurl::sNotQuitting) //aborted
+	{	
+		std::string reason("Request timeout, aborted.") ;
+		mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort
+			reason, mChannels, mOutput);		
+	}
+	mResponder = NULL;
 }
 
 void LLCurl::Easy::resetState()
@@ -1462,6 +1471,8 @@ void LLCurl::initClass(bool multi_threaded)
 
 void LLCurl::cleanupClass()
 {
+	sNotQuitting = false; //set quitting
+
 	//shut down curl thread
 	while(1)
 	{
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 2b23ac9763..7d2340a6cb 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -197,6 +197,8 @@ private:
 
 	static LLMutex* sHandleMutexp ;
 	static S32      sTotalHandles ;
+public:
+	static bool     sNotQuitting;
 };
 
 class LLCurl::Easy
-- 
cgit v1.2.3


From 717a6f3306d9382ea252c3e0f243b785c9cae15a Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Wed, 25 Jan 2012 18:27:40 -0700
Subject: Introduce two new parameters "CurlUseMultipleThreads" and
 "CurlRequestTimeOut" for QA to test Curl.

---
 indra/llmessage/llcurl.cpp              | 18 ++++++++++--------
 indra/llmessage/llcurl.h                |  4 +++-
 indra/newview/app_settings/settings.xml | 22 ++++++++++++++++++++++
 indra/newview/llappviewer.cpp           |  4 +++-
 4 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 32a9cd061f..3bcaffc275 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -75,9 +75,6 @@ static const S32 MULTI_PERFORM_CALL_REPEAT	= 5;
 static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation
 static const S32 MAX_ACTIVE_REQUEST_COUNT = 100;
 
-static const F32 DEFAULT_MULTI_IDLE_TIME = 120.0f ; //seconds
-static const S32 MAX_NUM_OF_HANDLES = 256 ; //max number of handles, (multi handles and easy handles combined).
-
 // DEBUG //
 S32 gCurlEasyCount = 0;
 S32 gCurlMultiCount = 0;
@@ -92,6 +89,8 @@ LLCurlThread* LLCurl::sCurlThread = NULL ;
 LLMutex* LLCurl::sHandleMutexp = NULL ;
 S32      LLCurl::sTotalHandles = 0 ;
 bool     LLCurl::sNotQuitting = true;
+F32      LLCurl::sCurlRequestTimeOut = 120.f; //seonds
+S32      LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined).
 
 void check_curl_code(CURLcode code)
 {
@@ -573,9 +572,9 @@ LLCurl::Multi::Multi(F32 idle_time_out)
 		LLCurl::getCurlThread()->addMulti(this) ;
 
 		mIdleTimeOut = idle_time_out ;
-		if(mIdleTimeOut < DEFAULT_MULTI_IDLE_TIME)
+		if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut)
 		{
-			mIdleTimeOut = DEFAULT_MULTI_IDLE_TIME ;
+			mIdleTimeOut = LLCurl::sCurlRequestTimeOut ;
 		}
 
 		++gCurlMultiCount;
@@ -1442,8 +1441,11 @@ unsigned long LLCurl::ssl_thread_id(void)
 }
 #endif
 
-void LLCurl::initClass(bool multi_threaded)
+void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool multi_threaded)
 {
+	sCurlRequestTimeOut = curl_reuest_timeout ; //seconds
+	sMaxHandles = max_number_handles ; //max number of handles, (multi handles and easy handles combined).
+
 	// Do not change this "unless you are familiar with and mean to control 
 	// internal operations of libcurl"
 	// - http://curl.haxx.se/libcurl/c/curl_global_init.html
@@ -1512,7 +1514,7 @@ CURLM* LLCurl::newMultiHandle()
 {
 	LLMutexLock lock(sHandleMutexp) ;
 
-	if(sTotalHandles + 1 > MAX_NUM_OF_HANDLES)
+	if(sTotalHandles + 1 > sMaxHandles)
 	{
 		llwarns << "no more handles available." << llendl ;
 		return NULL ; //failed
@@ -1545,7 +1547,7 @@ CURL*  LLCurl::newEasyHandle()
 {
 	LLMutexLock lock(sHandleMutexp) ;
 
-	if(sTotalHandles + 1 > MAX_NUM_OF_HANDLES)
+	if(sTotalHandles + 1 > sMaxHandles)
 	{
 		llwarns << "no more handles available." << llendl ;
 		return NULL ; //failed
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 7d2340a6cb..fd664c0fa1 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -163,7 +163,7 @@ public:
 	/**
 	 * @ brief Initialize LLCurl class
 	 */
-	static void initClass(bool multi_threaded = false);
+	static void initClass(F32 curl_reuest_timeout = 120.f, S32 max_number_handles = 256, bool multi_threaded = false);
 
 	/**
 	 * @ brief Cleanup LLCurl class
@@ -197,8 +197,10 @@ private:
 
 	static LLMutex* sHandleMutexp ;
 	static S32      sTotalHandles ;
+	static S32      sMaxHandles;
 public:
 	static bool     sNotQuitting;
+	static F32      sCurlRequestTimeOut;	
 };
 
 class LLCurl::Easy
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 1ea623791d..a29d5d2985 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1828,6 +1828,28 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+  <key>CurlMaximumNumberOfHandles</key>
+  <map>
+    <key>Comment</key>
+    <string>Maximum number of handles curl can use (requires restart)</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>S32</string>
+    <key>Value</key>
+    <integer>256</integer>
+  </map>
+  <key>CurlRequestTimeOut</key>
+  <map>
+    <key>Comment</key>
+    <string>Max idle time of a curl request before killed (requires restart)</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <real>120.0</real>
+  </map>
   <key>CurlUseMultipleThreads</key>
   <map>
     <key>Comment</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 40136adbc9..4fc306e61d 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -720,7 +720,9 @@ bool LLAppViewer::init()
 
     // *NOTE:Mani - LLCurl::initClass is not thread safe. 
     // Called before threads are created.
-    LLCurl::initClass(gSavedSettings.getBOOL("CurlUseMultipleThreads"));
+    LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"), 
+						gSavedSettings.getS32("CurlMaximumNumberOfHandles"), 
+						gSavedSettings.getBOOL("CurlUseMultipleThreads"));
 	LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;
 
     LLMachineID::init();
-- 
cgit v1.2.3


From 27df0a84564d3a886661aae0faae74c2157cd31b Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 27 Jan 2012 23:46:00 -0500
Subject: On Windows, only quote LLProcess arguments if they seem to need it.
 On Posix platforms, the OS argument mechanism makes quoting/reparsing
 unnecessary anyway, so this only affects Windows. Add optional 'triggers'
 parameter to LLStringUtils::quote() (default: space and double-quote). Only
 if the passed string contains a character in 'triggers' will it be
 double-quoted. This is observed to fix a Windows-specific problem in which
 plugin child process would fail to start because it wasn't expecting a quoted
 number. Use LLStringUtils::quote() more consistently in LLProcess
 implementation for logging.

---
 indra/llcommon/llprocess.cpp | 14 +++++++-------
 indra/llcommon/llstring.h    | 26 +++++++++++++++++++++-----
 2 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 2c7512419d..2b7a534fb3 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -87,12 +87,12 @@ std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
 	std::string cwd(params.cwd);
 	if (! cwd.empty())
 	{
-		out << "cd '" << cwd << "': ";
+		out << "cd " << LLStringUtil::quote(cwd) << ": ";
 	}
-	out << '"' << std::string(params.executable) << '"';
+	out << LLStringUtil::quote(params.executable);
 	BOOST_FOREACH(const std::string& arg, params.args)
 	{
-		out << " \"" << arg << '"';
+		out << ' ' << LLStringUtil::quote(arg);
 	}
 	return out;
 }
@@ -132,8 +132,8 @@ public:
 
 		if (! AssignProcessToJobObject(mJob, hProcess))
 		{
-			LL_WARNS("LLProcess") << WindowsErrorString(STRINGIZE("AssignProcessToJobObject(\""
-																  << prog << "\")")) << LL_ENDL;
+			LL_WARNS("LLProcess") << WindowsErrorString(STRINGIZE("AssignProcessToJobObject("
+																  << prog << ")")) << LL_ENDL;
 		}
 	}
 
@@ -206,7 +206,7 @@ void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 	mProcessID = pinfo.hProcess;
 	CloseHandle(pinfo.hThread); // stops leaks - nothing else
 
-	mDesc = STRINGIZE('"' << std::string(params.executable) << "\" (" << pinfo.dwProcessId << ')');
+	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << pinfo.dwProcessId << ')');
 	LL_INFOS("LLProcess") << "Launched " << params << " (" << pinfo.dwProcessId << ")" << LL_ENDL;
 
 	// Now associate the new child process with our Job Object -- unless
@@ -356,7 +356,7 @@ void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 	// parent process
 	mProcessID = child;
 
-	mDesc = STRINGIZE('"' << std::string(params.executable) << "\" (" << mProcessID << ')');
+	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << mProcessID << ')');
 	LL_INFOS("LLProcess") << "Launched " << params << " (" << mProcessID << ")" << LL_ENDL;
 }
 
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 4c3936f9ab..7b24b5e279 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -303,11 +303,17 @@ public:
 	static void	stripNonprintable(string_type& string);
 
 	/**
-	 * Double-quote an argument string, unless it's already double-quoted. If we
-	 * quote it, escape any embedded double-quote with the escape string (default
+	 * Double-quote an argument string if needed, unless it's already
+	 * double-quoted. Decide whether it's needed based on the presence of any
+	 * character in @a triggers (default space or double-quote). If we quote
+	 * it, escape any embedded double-quote with the @a escape string (default
 	 * backslash).
+	 *
+	 * Passing triggers="" means always quote, unless it's already double-quoted.
 	 */
-	static string_type quote(const string_type& str, const string_type& escape="\\");
+	static string_type quote(const string_type& str,
+							 const string_type& triggers=" \"",
+							 const string_type& escape="\\");
 
 	/**
 	 * @brief Unsafe way to make ascii characters. You should probably
@@ -1060,7 +1066,9 @@ void LLStringUtilBase<T>::stripNonprintable(string_type& string)
 }
 
 template<class T>
-std::basic_string<T> LLStringUtilBase<T>::quote(const string_type& str, const string_type& escape)
+std::basic_string<T> LLStringUtilBase<T>::quote(const string_type& str,
+												const string_type& triggers,
+												const string_type& escape)
 {
 	size_type len(str.length());
 	// If the string is already quoted, assume user knows what s/he's doing.
@@ -1069,7 +1077,15 @@ std::basic_string<T> LLStringUtilBase<T>::quote(const string_type& str, const st
 		return str;
 	}
 
-	// Not already quoted: do it.
+	// Not already quoted: do we need to? triggers.empty() is a special case
+	// meaning "always quote."
+	if ((! triggers.empty()) && str.find_first_of(triggers) == string_type::npos)
+	{
+		// no trigger characters, don't bother quoting
+		return str;
+	}
+
+	// For whatever reason, we must quote this string.
 	string_type result;
 	result.push_back('"');
 	for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
-- 
cgit v1.2.3


From 803acbc5efde19c0acacfc7fe4990841dbf31a3e Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 30 Jan 2012 10:14:10 -0500
Subject: Trim trailing "\r\n" from Windows FormatMessage() string for logging.

---
 indra/llcommon/llprocess.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 2b7a534fb3..8c0e8fe65e 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -261,11 +261,15 @@ static std::string WindowsErrorString(const std::string& operation)
 					   NULL)
 		!= 0) 
 	{
+        // convert from wide-char string to multi-byte string
 		char message[256];
 		wcstombs(message, error_str, sizeof(message));
 		message[sizeof(message)-1] = 0;
 		LocalFree(error_str);
-		return STRINGIZE(operation << " failed (" << result << "): " << message);
+		// convert to std::string to trim trailing whitespace
+		std::string mbsstr(message);
+		mbsstr.erase(mbsstr.find_last_not_of(" \t\r\n"));
+		return STRINGIZE(operation << " failed (" << result << "): " << mbsstr);
 	}
 	return STRINGIZE(operation << " failed (" << result
 					 << "), but FormatMessage() did not explain");
-- 
cgit v1.2.3


From 85581eefa63d8f8e8c5132c4cd7e137f6cb88869 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 30 Jan 2012 12:11:44 -0500
Subject: Expose 'handle' as well as 'id' on LLProcess objects. On Posix, these
 and the corresponding getProcessID()/getProcessHandle() accessors produce the
 same pid_t value; but on Windows, it's useful to distinguish an int-like 'id'
 useful to human log readers versus an opaque 'handle' for passing to
 platform-specific API functions. So make the distinction in a
 platform-independent way.

---
 indra/llcommon/llprocess.cpp            | 50 ++++++++++++++++++++-------------
 indra/llcommon/llprocess.h              | 42 +++++++++++++++++----------
 indra/llcommon/tests/llprocess_test.cpp | 16 +++++------
 3 files changed, 66 insertions(+), 42 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 8c0e8fe65e..a7bafb8cb0 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -42,7 +42,7 @@ struct LLProcessError: public std::runtime_error
 	LLProcessError(const std::string& msg): std::runtime_error(msg) {}
 };
 
-LLProcessPtr LLProcess::create(const LLSDParamAdapter<Params>& params)
+LLProcessPtr LLProcess::create(const LLSDOrParams& params)
 {
 	try
 	{
@@ -55,8 +55,9 @@ LLProcessPtr LLProcess::create(const LLSDParamAdapter<Params>& params)
 	}
 }
 
-LLProcess::LLProcess(const LLSDParamAdapter<Params>& params):
+LLProcess::LLProcess(const LLSDOrParams& params):
 	mProcessID(0),
+	mProcessHandle(0),
 	mAutokill(params.autokill)
 {
 	if (! params.validateBlock(true))
@@ -78,8 +79,18 @@ LLProcess::~LLProcess()
 
 bool LLProcess::isRunning(void)
 {
-	mProcessID = isRunning(mProcessID, mDesc);
-	return (mProcessID != 0);
+	mProcessHandle = isRunning(mProcessHandle, mDesc);
+	return (mProcessHandle != 0);
+}
+
+LLProcess::id LLProcess::getProcessID() const
+{
+	return mProcessID;
+}
+
+LLProcess::handle LLProcess::getProcessHandle() const
+{
+	return mProcessHandle;
 }
 
 std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
@@ -122,7 +133,7 @@ static std::string WindowsErrorString(const std::string& operation);
 class LLJob: public LLSingleton<LLJob>
 {
 public:
-	void assignProcess(const std::string& prog, HANDLE hProcess)
+	void assignProcess(const std::string& prog, handle hProcess)
 	{
 		// If we never managed to initialize this Job Object, can't use it --
 		// but don't keep spamming the log, we already emitted warnings when
@@ -164,10 +175,10 @@ private:
 		}
 	}
 
-	HANDLE mJob;
+	handle mJob;
 };
 
-void LLProcess::launch(const LLSDParamAdapter<Params>& params)
+void LLProcess::launch(const LLSDOrParams& params)
 {
 	PROCESS_INFORMATION pinfo;
 	STARTUPINFOA sinfo = { sizeof(sinfo) };
@@ -201,28 +212,28 @@ void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 		throw LLProcessError(WindowsErrorString("CreateProcessA"));
 	}
 
-	// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
 	// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
-	mProcessID = pinfo.hProcess;
+	mProcessID = pinfo.dwProcessId;
+	mProcessHandle = pinfo.hProcess;
 	CloseHandle(pinfo.hThread); // stops leaks - nothing else
 
-	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << pinfo.dwProcessId << ')');
-	LL_INFOS("LLProcess") << "Launched " << params << " (" << pinfo.dwProcessId << ")" << LL_ENDL;
+	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << mProcessID << ')');
+	LL_INFOS("LLProcess") << "Launched " << params << " (" << mProcessID << ")" << LL_ENDL;
 
 	// Now associate the new child process with our Job Object -- unless
 	// autokill is false, i.e. caller asserts the child should persist.
 	if (params.autokill)
 	{
-		LLJob::instance().assignProcess(mDesc, mProcessID);
+		LLJob::instance().assignProcess(mDesc, mProcessHandle);
 	}
 }
 
-LLProcess::id LLProcess::isRunning(id handle, const std::string& desc)
+LLProcess::handle LLProcess::isRunning(handle h, const std::string& desc)
 {
-	if (! handle)
+	if (! h)
 		return 0;
 
-	DWORD waitresult = WaitForSingleObject(handle, 0);
+	DWORD waitresult = WaitForSingleObject(h, 0);
 	if(waitresult == WAIT_OBJECT_0)
 	{
 		// the process has completed.
@@ -233,16 +244,16 @@ LLProcess::id LLProcess::isRunning(id handle, const std::string& desc)
 		return 0;
 	}
 
-	return handle;
+	return h;
 }
 
 bool LLProcess::kill(void)
 {
-	if (! mProcessID)
+	if (! mProcessHandle)
 		return false;
 
 	LL_INFOS("LLProcess") << "killing " << mDesc << LL_ENDL;
-	TerminateProcess(mProcessID, 0);
+	TerminateProcess(mProcessHandle, 0);
 	return ! isRunning();
 }
 
@@ -302,7 +313,7 @@ static bool reap_pid(pid_t pid)
 	return false;
 }
 
-void LLProcess::launch(const LLSDParamAdapter<Params>& params)
+void LLProcess::launch(const LLSDOrParams& params)
 {
 	// flush all buffers before the child inherits them
 	::fflush(NULL);
@@ -359,6 +370,7 @@ void LLProcess::launch(const LLSDParamAdapter<Params>& params)
 
 	// parent process
 	mProcessID = child;
+	mProcessHandle = child;
 
 	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << mProcessID << ')');
 	LL_INFOS("LLProcess") << "Launched " << params << " (" << mProcessID << ")" << LL_ENDL;
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 51c42582ea..8a842589ec 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -35,7 +35,7 @@
 
 #if LL_WINDOWS
 #define WIN32_LEAN_AND_MEAN
-#include <windows.h>
+#include <windows.h>                // HANDLE (eye roll)
 #endif
 
 class LLProcess;
@@ -79,6 +79,7 @@ public:
 		/// implicitly kill process on destruction of LLProcess object
 		Optional<bool> autokill;
 	};
+	typedef LLSDParamAdapter<Params> LLSDOrParams;
 
 	/**
 	 * Factory accepting either plain LLSD::Map or Params block.
@@ -91,7 +92,7 @@ public:
 	 * cwd		  (optional, string, dft no chdir): change to this directory before executing
 	 * autokill	  (optional, bool, dft true):		implicit kill() on ~LLProcess
 	 */
-	static LLProcessPtr create(const LLSDParamAdapter<Params>& params);
+	static LLProcessPtr create(const LLSDOrParams& params);
 	virtual ~LLProcess();
 
 	// isRunning isn't const because, if child isn't running, it clears stored
@@ -103,35 +104,46 @@ public:
 	bool kill(void);
 
 #if LL_WINDOWS
-	typedef HANDLE id;
+	typedef int id;                 ///< as returned by getProcessID()
+	typedef HANDLE handle;          ///< as returned by getProcessHandle()
 #else
-	typedef pid_t  id;
+	typedef pid_t id;
+	typedef pid_t handle;
 #endif
-	/// Get platform-specific process ID
-	id getProcessID() const { return mProcessID; };
+	/**
+	 * Get an int-like id value. This is primarily intended for a human reader
+	 * to differentiate processes.
+	 */
+	id getProcessID() const;
+	/**
+	 * Get a "handle" of a kind that you might pass to platform-specific API
+	 * functions to engage features not directly supported by LLProcess.
+	 */
+	handle getProcessHandle() const;
 
 	/**
-	 * Test if a process (id obtained from getProcessID()) is still
-	 * running. Return is same nonzero id value if still running, else
+	 * Test if a process (@c handle obtained from getProcessHandle()) is still
+	 * running. Return same nonzero @c handle value if still running, else
 	 * zero, so you can test it like a bool. But if you want to update a
 	 * stored variable as a side effect, you can write code like this:
 	 * @code
-	 * childpid = LLProcess::isRunning(childpid);
+	 * hchild = LLProcess::isRunning(hchild);
 	 * @endcode
 	 * @note This method is intended as a unit-test hook, not as the first of
-	 * a whole set of operations supported on freestanding @c id values. New
-	 * functionality should be added as nonstatic members operating on
-	 * mProcessID.
+	 * a whole set of operations supported on freestanding @c handle values.
+	 * New functionality should be added as nonstatic members operating on
+	 * the same data as getProcessHandle().
 	 */
-	static id isRunning(id, const std::string& desc="");
+	static handle isRunning(handle, const std::string& desc="");
 
 private:
 	/// constructor is private: use create() instead
-	LLProcess(const LLSDParamAdapter<Params>& params);
-	void launch(const LLSDParamAdapter<Params>& params);
+	LLProcess(const LLSDOrParams& params);
+	void launch(const LLSDOrParams& params);
 
 	std::string mDesc;
 	id mProcessID;
+	handle mProcessHandle;
 	bool mAutokill;
 };
 
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 405540e436..4ad45bdf27 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -599,7 +599,7 @@ namespace tut
     {
         set_test_name("implicit kill()");
         NamedTempFile out("out", "not started");
-        LLProcess::id pid(0);
+        LLProcess::handle phandle(0);
         {
             PythonProcessLauncher py("kill()",
                                      "from __future__ import with_statement\n"
@@ -614,8 +614,8 @@ namespace tut
             py.mParams.args.add(out.getName());
             py.mPy = LLProcess::create(py.mParams);
             ensure("couldn't launch kill() script", py.mPy);
-            // Capture id for later
-            pid = py.mPy->getProcessID();
+            // Capture handle for later
+            phandle = py.mPy->getProcessHandle();
             // Wait for the script to wake up and do its first write
             int i = 0, timeout = 60;
             for ( ; i < timeout; ++i)
@@ -630,7 +630,7 @@ namespace tut
             // Destroy the LLProcess, which should kill the child.
         }
         // wait for the script to terminate... one way or another.
-        while (LLProcess::isRunning(pid))
+        while (LLProcess::isRunning(phandle))
         {
             sleep(1);
         }
@@ -646,7 +646,7 @@ namespace tut
         set_test_name("autokill");
         NamedTempFile from("from", "not started");
         NamedTempFile to("to", "");
-        LLProcess::id pid(0);
+        LLProcess::handle phandle(0);
         {
             PythonProcessLauncher py("autokill",
                                      "from __future__ import with_statement\n"
@@ -672,8 +672,8 @@ namespace tut
             py.mParams.autokill = false;
             py.mPy = LLProcess::create(py.mParams);
             ensure("couldn't launch kill() script", py.mPy);
-            // Capture id for later
-            pid = py.mPy->getProcessID();
+            // Capture handle for later
+            phandle = py.mPy->getProcessHandle();
             // Wait for the script to wake up and do its first write
             int i = 0, timeout = 60;
             for ( ; i < timeout; ++i)
@@ -695,7 +695,7 @@ namespace tut
             outf << "go";
         } // flush and close.
         // now wait for the script to terminate... one way or another.
-        while (LLProcess::isRunning(pid))
+        while (LLProcess::isRunning(phandle))
         {
             sleep(1);
         }
-- 
cgit v1.2.3


From 60a777d2e3f9bec7a20e5de2df7cb3ecd2455b98 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 30 Jan 2012 12:32:05 -0500
Subject: LLProcess::handle must be qualified when used in LLJob class.

---
 indra/llcommon/llprocess.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index a7bafb8cb0..1e27f8ce1d 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -133,7 +133,7 @@ static std::string WindowsErrorString(const std::string& operation);
 class LLJob: public LLSingleton<LLJob>
 {
 public:
-	void assignProcess(const std::string& prog, handle hProcess)
+	void assignProcess(const std::string& prog, LLProcess::handle hProcess)
 	{
 		// If we never managed to initialize this Job Object, can't use it --
 		// but don't keep spamming the log, we already emitted warnings when
@@ -175,7 +175,7 @@ private:
 		}
 	}
 
-	handle mJob;
+	LLProcess::handle mJob;
 };
 
 void LLProcess::launch(const LLSDOrParams& params)
-- 
cgit v1.2.3


From bd4c629e38aa2ab7223a5ef3b8e23ad91229b512 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 30 Jan 2012 16:44:58 -0500
Subject: Added tag 3.2.8-start for changeset 89980333c99d

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index 974498551b..33cd4d37a5 100644
--- a/.hgtags
+++ b/.hgtags
@@ -258,3 +258,4 @@ c6175c955a19e9b9353d242889ec1779b5762522 DRTVWR-105_3.2.5-release
 c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release
 3d75c836d178c7c7e788f256afe195f6cab764a2 DRTVWR-111_3.2.7-beta1
 3d75c836d178c7c7e788f256afe195f6cab764a2 3.2.7-beta1
+89980333c99dbaf1787fe20784f1d8849e9b5d4f 3.2.8-start
-- 
cgit v1.2.3


From 0e609cc95b08c28bd51f5ab48160fd93df7a6b28 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 30 Jan 2012 16:45:50 -0500
Subject: increment viewer version to 3.2.9

---
 indra/llcommon/llversionviewer.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 99ab053b25..27cdfcaa4e 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
 
 const S32 LL_VERSION_MAJOR = 3;
 const S32 LL_VERSION_MINOR = 2;
-const S32 LL_VERSION_PATCH = 8;
+const S32 LL_VERSION_PATCH = 9;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";
-- 
cgit v1.2.3


From 491cd825561be1cf4a6f428a535811cbe0e3f179 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 30 Jan 2012 17:47:57 -0500
Subject: Set bit flag on CreateProcess() to allow AssignProcessToJobObject().
 Windows 7 and friends tend to create a process already implicitly allocated
 to a job object, and a process can only belong to a single job object.
 Passing CREATE_BREAKAWAY_FROM_JOB in CreateProcessA()'s dwCreationFlags seems
 to bypass the access-denied error observed with AssignProcessToJobObject()
 otherwise. This change should (!) enable OS lifespan management for
 SLVoice.exe et al.

---
 indra/llcommon/llprocess.cpp | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 1e27f8ce1d..8611d67f25 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -207,7 +207,26 @@ void LLProcess::launch(const LLSDOrParams& params)
 	const char * working_directory = 0;
 	if (! cwd.empty())
 		working_directory = cwd.c_str();
-	if( ! CreateProcessA( NULL, &args2[0], NULL, NULL, FALSE, 0, NULL, working_directory, &sinfo, &pinfo ) )
+
+	// It's important to pass CREATE_BREAKAWAY_FROM_JOB because Windows 7 et
+	// al. tend to implicitly launch new processes already bound to a job. From
+	// http://msdn.microsoft.com/en-us/library/windows/desktop/ms681949%28v=vs.85%29.aspx :
+	// "The process must not already be assigned to a job; if it is, the
+	// function fails with ERROR_ACCESS_DENIED." ...
+	// "If the process is being monitored by the Program Compatibility
+	// Assistant (PCA), it is placed into a compatibility job. Therefore, the
+	// process must be created using CREATE_BREAKAWAY_FROM_JOB before it can
+	// be placed in another job."
+	if( ! CreateProcessA(NULL,      // lpApplicationName
+                         &args2[0], // lpCommandLine
+                         NULL,      // lpProcessAttributes
+                         NULL,      // lpThreadAttributes
+                         FALSE,     // bInheritHandles
+                         CREATE_BREAKAWAY_FROM_JOB, // dwCreationFlags
+                         NULL,      // lpEnvironment
+                         working_directory, // lpCurrentDirectory
+                         &sinfo,            // lpStartupInfo
+                         &pinfo ) )         // lpProcessInformation
 	{
 		throw LLProcessError(WindowsErrorString("CreateProcessA"));
 	}
@@ -225,7 +244,7 @@ void LLProcess::launch(const LLSDOrParams& params)
 	if (params.autokill)
 	{
 		LLJob::instance().assignProcess(mDesc, mProcessHandle);
-	}
+}
 }
 
 LLProcess::handle LLProcess::isRunning(handle h, const std::string& desc)
@@ -287,7 +306,7 @@ static std::string WindowsErrorString(const std::string& operation)
 }
 
 /*****************************************************************************
-*   Non-Windows specific
+*   Posix specific
 *****************************************************************************/
 #else // Mac and linux
 
@@ -444,4 +463,4 @@ void LLProcess::reap(void)
 }
 |*==========================================================================*/
 
-#endif
+#endif  // Posix
-- 
cgit v1.2.3


From 36aba266155bdb25b9887686016ad62b2250b509 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Fri, 3 Feb 2012 11:10:13 +0200
Subject: EXP-1843 WIP Added an option to output avatar rez timing.

Use the new "Avatar Rez" debugging tag to see the output.
---
 indra/newview/llagent.cpp               |  1 +
 indra/newview/llagentwearables.cpp      | 11 +++++++++++
 indra/newview/llagentwearablesfetch.cpp |  8 ++++++++
 indra/newview/llagentwearablesfetch.h   |  2 ++
 indra/newview/llappearancemgr.cpp       |  9 +++++++++
 indra/newview/lltexlayer.h              |  2 ++
 indra/newview/llvoavatar.h              |  2 ++
 indra/newview/llvoavatarself.cpp        | 21 ++++++++++++++++++++-
 indra/newview/llvoavatarself.h          |  3 +++
 9 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 54ad3cd187..ab9b5ff436 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3314,6 +3314,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
 	}
 
 	llinfos << "Received cached texture response for " << num_results << " textures." << llendl;
+	gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them");
 
 	gAgentAvatarp->updateMeshTextures();
 
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 13b62cb019..09305a5b4d 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -185,6 +185,7 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar)
 { 
 	if (avatar)
 	{
+		avatar->outputRezTiming("Sending wearables request");
 		sendAgentWearablesRequest();
 	}
 }
@@ -949,6 +950,11 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
 	if (mInitialWearablesUpdateReceived)
 		return;
 
+	if (isAgentAvatarValid())
+	{
+		gAgentAvatarp->outputRezTiming("Received initial wearables update");
+	}
+
 	// notify subscribers that wearables started loading. See EXT-7777
 	// *TODO: find more proper place to not be called from deprecated method.
 	// Seems such place is found: LLInitialWearablesFetch::processContents()
@@ -1619,6 +1625,11 @@ void LLAgentWearables::queryWearableCache()
 	//VWR-22113: gAgent.getRegion() can return null if invalid, seen here on logout
 	if(gAgent.getRegion())
 	{
+		if (isAgentAvatarValid())
+		{
+			gAgentAvatarp->outputRezTiming("Fetching textures from cache");
+		}
+
 		llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl;
 		gMessageSystem->sendReliable(gAgent.getRegion()->getHost());
 		gAgentQueryManager.mNumPendingQueries++;
diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
index 4097ff707c..8cba54347e 100644
--- a/indra/newview/llagentwearablesfetch.cpp
+++ b/indra/newview/llagentwearablesfetch.cpp
@@ -87,6 +87,10 @@ public:
 LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :
 	LLInventoryFetchDescendentsObserver(cof_id)
 {
+	if (isAgentAvatarValid())
+	{
+		gAgentAvatarp->outputRezTiming("Initial wearables fetch started");
+	}
 }
 
 LLInitialWearablesFetch::~LLInitialWearablesFetch()
@@ -101,6 +105,10 @@ void LLInitialWearablesFetch::done()
 	// idle tick instead.
 	gInventory.removeObserver(this);
 	doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this));
+	if (isAgentAvatarValid())
+	{
+		gAgentAvatarp->outputRezTiming("Initial wearables fetch done");
+	}
 }
 
 void LLInitialWearablesFetch::add(InitialWearableData &data)
diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h
index 7dafab4a33..bedc445c0e 100644
--- a/indra/newview/llagentwearablesfetch.h
+++ b/indra/newview/llagentwearablesfetch.h
@@ -40,6 +40,8 @@
 //--------------------------------------------------------------------
 class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver
 {
+	LOG_CLASS(LLInitialWearablesFetch);
+
 public:
 	LLInitialWearablesFetch(const LLUUID& cof_id);
 	~LLInitialWearablesFetch();
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 663257042e..33f5373d7e 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -268,6 +268,8 @@ struct LLFoundData
 	
 class LLWearableHoldingPattern
 {
+	LOG_CLASS(LLWearableHoldingPattern);
+
 public:
 	LLWearableHoldingPattern();
 	~LLWearableHoldingPattern();
@@ -436,6 +438,11 @@ void LLWearableHoldingPattern::checkMissingWearables()
 
 void LLWearableHoldingPattern::onAllComplete()
 {
+	if (isAgentAvatarValid())
+	{
+		gAgentAvatarp->outputRezTiming("Agent wearables fetch complete");
+	}
+
 	if (!isMostRecent())
 	{
 		llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
@@ -2363,6 +2370,8 @@ void LLAppearanceMgr::autopopulateOutfits()
 // Handler for anything that's deferred until avatar de-clouds.
 void LLAppearanceMgr::onFirstFullyVisible()
 {
+	gAgentAvatarp->outputRezTiming("Avatar fully loaded");
+	gAgentAvatarp->reportAvatarRezTime();
 	gAgentAvatarp->debugAvatarVisible();
 
 	// The auto-populate is failing at the point of generating outfits
diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h
index 85dadb213c..4f43547dae 100644
--- a/indra/newview/lltexlayer.h
+++ b/indra/newview/lltexlayer.h
@@ -261,6 +261,8 @@ private:
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 class LLTexLayerSetBuffer : public LLViewerDynamicTexture
 {
+	LOG_CLASS(LLTexLayerSetBuffer);
+
 public:
 	LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height);
 	virtual ~LLTexLayerSetBuffer();
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 4cd61cecf9..dd0317f555 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -78,6 +78,8 @@ class LLVOAvatar :
 	public LLCharacter,
 	public boost::signals2::trackable
 {
+	LOG_CLASS(LLVOAvatar);
+
 public:
 	friend class LLVOAvatarSelf;
 protected:
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 581912f844..f1df67494f 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1574,7 +1574,7 @@ void LLVOAvatarSelf::invalidateAll()
 	{
 		invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, TRUE);
 	}
-	mDebugSelfLoadTimer.reset();
+	//mDebugSelfLoadTimer.reset();
 }
 
 //-----------------------------------------------------------------------------
@@ -1896,11 +1896,13 @@ BOOL LLVOAvatarSelf::getIsCloud()
 		gAgentWearables.getWearableCount(LLWearableType::WT_EYES) == 0 ||
 		gAgentWearables.getWearableCount(LLWearableType::WT_SKIN) == 0)	
 	{
+		lldebugs << "No body parts" << llendl;
 		return TRUE;
 	}
 
 	if (!isTextureDefined(TEX_HAIR, 0))
 	{
+		lldebugs << "No hair texture" << llendl;
 		return TRUE;
 	}
 
@@ -1909,12 +1911,14 @@ BOOL LLVOAvatarSelf::getIsCloud()
 		if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) &&
 			(!isTextureDefined(TEX_LOWER_BAKED, 0)))
 		{
+			lldebugs << "Lower textures not baked" << llendl;
 			return TRUE;
 		}
 
 		if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) &&
 			(!isTextureDefined(TEX_UPPER_BAKED, 0)))
 		{
+			lldebugs << "Upper textures not baked" << llendl;
 			return TRUE;
 		}
 
@@ -1931,10 +1935,12 @@ BOOL LLVOAvatarSelf::getIsCloud()
 			const LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 );
 			if (!baked_img || !baked_img->hasGLTexture())
 			{
+				lldebugs << "Texture at index " << i << " (texture index is " << texture_data.mTextureIndex << ") is not loaded" << llendl;
 				return TRUE;
 			}
 		}
 
+		lldebugs << "Avatar de-clouded" << llendl;
 	}
 	return FALSE;
 }
@@ -2258,6 +2264,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
 	}
 }
 
+// FIXME: This is never called. Something may be broken.
 void LLVOAvatarSelf::outputRezDiagnostics() const
 {
 	if(!gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime"))
@@ -2315,6 +2322,18 @@ void LLVOAvatarSelf::outputRezDiagnostics() const
 	}
 }
 
+void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const
+{
+	LL_DEBUGS("Avatar Rez")
+		<< llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32())
+		<< llendl;
+}
+
+void LLVOAvatarSelf::reportAvatarRezTime() const
+{
+	// TODO: report mDebugSelfLoadTimer.getElapsedTimeF32() somehow.
+}
+
 //-----------------------------------------------------------------------------
 // setCachedBakedTexture()
 // A baked texture id was received from a cache query, make it active
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 74ff47a3e4..54dbe81993 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -41,6 +41,7 @@ struct LocalTextureData;
 class LLVOAvatarSelf :
 	public LLVOAvatar
 {
+	LOG_CLASS(LLVOAvatarSelf);
 
 /********************************************************************************
  **                                                                            **
@@ -358,6 +359,8 @@ public:
 	void 					debugWearablesLoaded() { mDebugTimeWearablesLoaded = mDebugSelfLoadTimer.getElapsedTimeF32(); }
 	void 					debugAvatarVisible() { mDebugTimeAvatarVisible = mDebugSelfLoadTimer.getElapsedTimeF32(); }
 	void 					outputRezDiagnostics() const;
+	void					outputRezTiming(const std::string& msg) const;
+	void					reportAvatarRezTime() const;
 	void 					debugBakedTextureUpload(LLVOAvatarDefines::EBakedTextureIndex index, BOOL finished);
 	static void				debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
 
-- 
cgit v1.2.3


From 90ba675da4416a7f75f59340633e2c007b6cc029 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 3 Feb 2012 13:09:20 -0500
Subject: Escape all strings embedded in TeamCity service messages. TeamCity
 requires that certain characters (notably "'") must be escaped when embedded
 in service messages:
 http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages
 TUT frequently outputs messages containing "'", e.g. from ensure_equals()
 failure. We've seen TC output nesting get confused when it fails to process
 service messages properly due to parsing unescaped messages. Along with
 test<n> number, report test name (from set_test_name()) when available.
 Eliminate horsing around to produce normal output on both std::cout and
 possible output file. When output file is specified, use
 boost::iostreams::tee_device to do fanout for us. Improve placement (and
 possibly reliability) of service messages. Clean up a startling amount of
 redundancy in service-message production.

---
 indra/test/test.cpp | 183 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 112 insertions(+), 71 deletions(-)

diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index ffdb0cb976..3e7be29b39 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -37,6 +37,7 @@
 #include "linden_common.h"
 #include "llerrorcontrol.h"
 #include "lltut.h"
+#include "stringize.h"
 
 #include "apr_pools.h"
 #include "apr_getopt.h"
@@ -53,6 +54,13 @@
 #include <gtest/gtest.h>
 #endif
 
+#include <boost/iostreams/tee.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/foreach.hpp>
+#include <boost/lambda/lambda.hpp>
+
 namespace tut
 {
 	std::string sSourceDir;
@@ -69,8 +77,24 @@ public:
 	mPassedTests(0),
 	mFailedTests(0),
 	mSkippedTests(0),
-	mStream(stream)
+	// By default, capture a shared_ptr to std::cout, with a no-op "deleter"
+	// so that destroying the shared_ptr makes no attempt to delete std::cout.
+	mStream(boost::shared_ptr<std::ostream>(&std::cout, boost::lambda::_1))
 	{
+		if (stream)
+		{
+			// We want a boost::iostreams::tee_device that will stream to two
+			// std::ostreams.
+			typedef boost::iostreams::tee_device<std::ostream, std::ostream> TeeDevice;
+			// More than that, though, we want an actual stream using that
+			// device.
+			typedef boost::iostreams::stream<TeeDevice> TeeStream;
+			// Allocate and assign in two separate steps, per Herb Sutter.
+			// (Until we turn on C++11 support, have to wrap *stream with
+			// boost::ref() due to lack of perfect forwarding.)
+			boost::shared_ptr<std::ostream> pstream(new TeeStream(std::cout, boost::ref(*stream)));
+			mStream = pstream;
+		}
 	}
 
 	~LLTestCallback()
@@ -94,7 +118,10 @@ public:
 	{
 		++mTotalTests;
 		std::ostringstream out;
-		out << "[" << tr.group << ", " << tr.test << "] ";
+		out << "[" << tr.group << ", " << tr.test;
+		if (! tr.name.empty())
+			out << ": " << tr.name;
+		out << "] ";
 		switch(tr.result)
 		{
 			case tut::test_result::ok:
@@ -123,56 +150,43 @@ public:
 				break;
 			default:
 				++mFailedTests;
-				out << "unknown";
+				out << "unknown (tr.result == " << tr.result << ")";
 		}
 		if(mVerboseMode || (tr.result != tut::test_result::ok))
 		{
+			*mStream << out.str();
 			if(!tr.message.empty())
 			{
-				out << ": '" << tr.message << "'";
+				*mStream << ": '" << tr.message << "'";
 			}
-			if (mStream)
-			{
-				*mStream << out.str() << std::endl;
-			}
-			
-			std::cout << out.str() << std::endl;
-		}
-	}
-
-	virtual void run_completed()
-	{
-		if (mStream)
-		{
-			run_completed_(*mStream);
+			*mStream << std::endl;
 		}
-		run_completed_(std::cout);
 	}
 
 	virtual int getFailedTests() const { return mFailedTests; }
 
-	virtual void run_completed_(std::ostream &stream)
+	virtual void run_completed()
 	{
-		stream << "\tTotal Tests:\t" << mTotalTests << std::endl;
-		stream << "\tPassed Tests:\t" << mPassedTests;
+		*mStream << "\tTotal Tests:\t" << mTotalTests << std::endl;
+		*mStream << "\tPassed Tests:\t" << mPassedTests;
 		if (mPassedTests == mTotalTests)
 		{
-			stream << "\tYAY!! \\o/";
+			*mStream << "\tYAY!! \\o/";
 		}
-		stream << std::endl;
+		*mStream << std::endl;
 
 		if (mSkippedTests > 0)
 		{
-			stream << "\tSkipped known failures:\t" << mSkippedTests
+			*mStream << "\tSkipped known failures:\t" << mSkippedTests
 			<< std::endl;
 		}
 
 		if(mFailedTests > 0)
 		{
-			stream << "*********************************" << std::endl;
-			stream << "Failed Tests:\t" << mFailedTests << std::endl;
-			stream << "Please report or fix the problem." << std::endl;
-			stream << "*********************************" << std::endl;
+			*mStream << "*********************************" << std::endl;
+			*mStream << "Failed Tests:\t" << mFailedTests << std::endl;
+			*mStream << "Please report or fix the problem." << std::endl;
+			*mStream << "*********************************" << std::endl;
 		}
 	}
 
@@ -182,7 +196,7 @@ protected:
 	int mPassedTests;
 	int mFailedTests;
 	int mSkippedTests;
-	std::ostream *mStream;
+	boost::shared_ptr<std::ostream> mStream;
 };
 
 // TeamCity specific class which emits service messages
@@ -192,84 +206,111 @@ class LLTCTestCallback : public LLTestCallback
 {
 public:
 	LLTCTestCallback(bool verbose_mode, std::ostream *stream) :
-		LLTestCallback(verbose_mode, stream),
-		mTCStream()
+		LLTestCallback(verbose_mode, stream)
 	{
 	}
 
 	~LLTCTestCallback()
 	{
-	}	
+	}
 
 	virtual void group_started(const std::string& name) {
 		LLTestCallback::group_started(name);
-		mTCStream << "\n##teamcity[testSuiteStarted name='" << name << "']" << std::endl;
+		std::cout << "\n##teamcity[testSuiteStarted name='" << escape(name) << "']" << std::endl;
 	}
 
 	virtual void group_completed(const std::string& name) {
 		LLTestCallback::group_completed(name);
-		mTCStream << "##teamcity[testSuiteFinished name='" << name << "']" << std::endl;
+		std::cout << "##teamcity[testSuiteFinished name='" << escape(name) << "']" << std::endl;
 	}
 
 	virtual void test_completed(const tut::test_result& tr)
 	{
+		std::string testname(STRINGIZE(tr.group << "." << tr.test));
+		if (! tr.name.empty())
+		{
+			testname.append(":");
+			testname.append(tr.name);
+		}
+		testname = escape(testname);
+
+		// Sadly, tut::callback doesn't give us control at test start; have to
+		// backfill start message into TC output.
+		std::cout << "##teamcity[testStarted name='" << testname << "']" << std::endl;
+
+		// now forward call to base class so any output produced there is in
+		// the right TC context
 		LLTestCallback::test_completed(tr);
 
 		switch(tr.result)
 		{
 			case tut::test_result::ok:
-				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
-				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
 				break;
+
 			case tut::test_result::fail:
-				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
-				mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
-				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
-				break;
 			case tut::test_result::ex:
-				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
-				mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
-				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
-				break;
 			case tut::test_result::warn:
-				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
-				mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
-				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
-				break;
 			case tut::test_result::term:
-				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
-				mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
-				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+				std::cout << "##teamcity[testFailed name='" << testname
+						  << "' message='" << escape(tr.message) << "']" << std::endl;
 				break;
+
 			case tut::test_result::skip:
-				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
-				mTCStream << "##teamcity[testIgnored name='" << tr.group << "." << tr.test << "']" << std::endl;
-				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+				std::cout << "##teamcity[testIgnored name='" << testname << "']" << std::endl;
 				break;
+
 			default:
 				break;
 		}
 
+		std::cout << "##teamcity[testFinished name='" << testname << "']" << std::endl;
 	}
 
-	virtual void run_completed()
-	{
-		LLTestCallback::run_completed();
-
-		// dump the TC reporting results to cout
-		tc_run_completed_(std::cout);
-	}
-
-	virtual void tc_run_completed_(std::ostream &stream)
+	static std::string escape(const std::string& str)
 	{
-		
-		// dump the TC reporting results to cout
-		stream << mTCStream.str() << std::endl;
+		// Per http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages
+		std::string result;
+		BOOST_FOREACH(char c, str)
+		{
+			switch (c)
+			{
+			case '\'':
+				result.append("|'");
+				break;
+			case '\n':
+				result.append("|n");
+				break;
+			case '\r':
+				result.append("|r");
+				break;
+/*==========================================================================*|
+			// These are not possible 'char' values from a std::string.
+			case '\u0085':			// next line
+				result.append("|x");
+				break;
+			case '\u2028':			// line separator
+				result.append("|l");
+				break;
+			case '\u2029':			// paragraph separator
+				result.append("|p");
+				break;
+|*==========================================================================*/
+			case '|':
+				result.append("||");
+				break;
+			case '[':
+				result.append("|[");
+				break;
+			case ']':
+				result.append("|]");
+				break;
+			default:
+				result.push_back(c);
+				break;
+			}
+		}
+		return result;
 	}
-	
-protected:
-	std::ostringstream mTCStream;
-
 };
 
 
-- 
cgit v1.2.3


From 028d9b3b3433bcb84253a23e98a2027b26b08255 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 3 Feb 2012 10:45:14 -0800
Subject: EXP-1868 FIX Remove Merchant Outbox from Me menu reviewed by Leslie

---
 indra/newview/skins/default/xui/en/menu_viewer.xml | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 1f72984166..01713c539a 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -152,13 +152,6 @@
         <menu_item_call.on_click
          function="BuyCurrency" />
       </menu_item_call>
-      <menu_item_call
-         label="Merchant Outbox..."
-         name="MerchantOutbox">
-        <menu_item_call.on_click
-         function="Floater.ToggleOrBringToFront"
-         parameter="outbox" />
-      </menu_item_call>
       <menu_item_call
            label="Account dashboard..."
            name="Manage My Account">
-- 
cgit v1.2.3


From a89fbc1d3396d1fe5516571fd6d8651d60709784 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 3 Feb 2012 11:14:54 -0800
Subject: EXP-1868 FIX Remove Merchant Outbox from Me menu removed merchant
 outbox context menu reviewed by Leslie

---
 indra/newview/llinventorybridge.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index c0065a94e6..cebe93f042 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -73,7 +73,7 @@
 #include "llwearablelist.h"
 
 // Marketplace outbox current disabled
-#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1
+#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	0
 #define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0
 #define BLOCK_WORN_ITEMS_IN_OUTBOX 1
 
-- 
cgit v1.2.3


From 54bc900c952b964206d484aa0b92e42238819fc6 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 6 Feb 2012 10:00:15 -0500
Subject: Added tag 3.2.9-start for changeset 37dd400ad721

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index 33cd4d37a5..2701d2bab0 100644
--- a/.hgtags
+++ b/.hgtags
@@ -259,3 +259,4 @@ c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release
 3d75c836d178c7c7e788f256afe195f6cab764a2 DRTVWR-111_3.2.7-beta1
 3d75c836d178c7c7e788f256afe195f6cab764a2 3.2.7-beta1
 89980333c99dbaf1787fe20784f1d8849e9b5d4f 3.2.8-start
+37dd400ad721e2a89ee820ffc1e7e433c68f3ca2 3.2.9-start
-- 
cgit v1.2.3


From 289d756ea86bd3898f41592146d8f549cd056846 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 6 Feb 2012 10:01:09 -0500
Subject: increment viewer version to 3.3.0

---
 indra/llcommon/llversionviewer.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 27cdfcaa4e..a869c74189 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -28,8 +28,8 @@
 #define LL_LLVERSIONVIEWER_H
 
 const S32 LL_VERSION_MAJOR = 3;
-const S32 LL_VERSION_MINOR = 2;
-const S32 LL_VERSION_PATCH = 9;
+const S32 LL_VERSION_MINOR = 3;
+const S32 LL_VERSION_PATCH = 0;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";
-- 
cgit v1.2.3


From d99acd56cdc41d72a073a4419e3e51c356e675bb Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 6 Feb 2012 17:06:55 -0500
Subject: ManageAPR should be noncopyable. Make that explicit. Any RAII class
 should either be noncopyable or should deal appropriately with a copy
 operation. ManageAPR is intended only for extremely simple cases, and hence
 should be noncopyable.

---
 indra/test/manageapr.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/test/manageapr.h b/indra/test/manageapr.h
index 0c1ca7b7be..2452fb6ae4 100644
--- a/indra/test/manageapr.h
+++ b/indra/test/manageapr.h
@@ -13,6 +13,7 @@
 #define LL_MANAGEAPR_H
 
 #include "llapr.h"
+#include <boost/noncopyable.hpp>
 
 /**
  * Declare a static instance of this class for dead-simple ll_init_apr() at
@@ -21,7 +22,7 @@
  * instances of other classes that depend on APR already being initialized,
  * the indeterminate static-constructor-order problem rears its ugly head.
  */
-class ManageAPR
+class ManageAPR: public boost::noncopyable
 {
 public:
     ManageAPR()
-- 
cgit v1.2.3


From aafb03b29f5166e8978931ad8b717be32d942836 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 7 Feb 2012 10:53:23 -0500
Subject: Convert LLProcess implementation from platform-specific to using APR.
 Include logic to engage Linden apr_procattr_autokill_set() extension: on
 Windows, magic CreateProcess() flag must be pushed down into
 apr_proc_create() level. When using an APR package without that extension,
 present implementation should lock (e.g.) SLVoice.exe lifespan to viewer's on
 Windows XP but probably won't on Windows 7: need magic flag on
 CreateProcess(). Using APR child-termination callback requires us to define
 state (e.g. LLProcess::RUNNING). Take the opportunity to present Status,
 capturing state and (if terminated) rc or signal number; but since most of
 the time all caller really wants is to log the outcome, also present status
 string, encapsulating logic to examine state and describe exited-with-rc vs.
 killed-by-signal. New Status logic may report clearer results in the case of
 a Windows child process killed by exception. Clarify that static
 LLProcess::isRunning(handle) overload is only for use when the original
 LLProcess object has been destroyed: really only for unit tests. We
 necessarily retain our original platform-specific implementations for just
 that one method. (Nonstatic isRunning() no longer calls static method.)
 Clarify log output from llprocess_test.cpp in a couple places.

---
 indra/llcommon/llprocess.cpp            | 552 +++++++++++++++++++++++---------
 indra/llcommon/llprocess.h              |  64 +++-
 indra/llcommon/tests/llprocess_test.cpp |   6 +-
 3 files changed, 455 insertions(+), 167 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 8611d67f25..bc27002701 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -30,11 +30,15 @@
 #include "llsingleton.h"
 #include "llstring.h"
 #include "stringize.h"
+#include "llapr.h"
 
 #include <boost/foreach.hpp>
 #include <iostream>
 #include <stdexcept>
 
+static std::string empty;
+static LLProcess::Status interpret_status(int status);
+
 /// Need an exception to avoid constructing an invalid LLProcess object, but
 /// internal use only
 struct LLProcessError: public std::runtime_error
@@ -55,9 +59,14 @@ LLProcessPtr LLProcess::create(const LLSDOrParams& params)
 	}
 }
 
+/// Call an apr function returning apr_status_t. On failure, log warning and
+/// throw LLProcessError mentioning the function call that produced that
+/// result.
+#define chkapr(func)                            \
+    if (ll_apr_warn_status(func))               \
+        throw LLProcessError(#func " failed")
+
 LLProcess::LLProcess(const LLSDOrParams& params):
-	mProcessID(0),
-	mProcessHandle(0),
 	mAutokill(params.autokill)
 {
 	if (! params.validateBlock(true))
@@ -66,31 +75,298 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 									   << LLSDNotationStreamer(params)));
 	}
 
-	launch(params);
+	apr_procattr_t *procattr = NULL;
+	chkapr(apr_procattr_create(&procattr, gAPRPoolp));
+
+	// For which of stdin, stdout, stderr should we create a pipe to the
+	// child? In the viewer, there are only a couple viable
+	// apr_procattr_io_set() alternatives: inherit the viewer's own stdxxx
+	// handle (APR_NO_PIPE, e.g. for stdout, stderr), or create a pipe that's
+	// blocking on the child end but nonblocking at the viewer end
+	// (APR_CHILD_BLOCK). The viewer can't block for anything: the parent end
+	// MUST be nonblocking. As the APR documentation itself points out, it
+	// makes very little sense to set nonblocking I/O for the child end of a
+	// pipe: only a specially-written child could deal with that.
+	// Other major options could include explicitly creating a single APR pipe
+	// and passing it as both stdout and stderr (apr_procattr_child_out_set(),
+	// apr_procattr_child_err_set()), or accepting a filename, opening it and
+	// passing that apr_file_t (simple <, >, 2> redirect emulation).
+//	chkapr(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK));
+	chkapr(apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE, APR_NO_PIPE));
+
+	// Thumbs down on implicitly invoking the shell to invoke the child. From
+	// our point of view, the other major alternative to APR_PROGRAM_PATH
+	// would be APR_PROGRAM_ENV: still copy environment, but require full
+	// executable pathname. I don't see a downside to searching the PATH,
+	// though: if our caller wants (e.g.) a specific Python interpreter, s/he
+	// can still pass the full pathname.
+	chkapr(apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH));
+	// YES, do extra work if necessary to report child exec() failures back to
+	// parent process.
+	chkapr(apr_procattr_error_check_set(procattr, 1));
+	// Do not start a non-autokill child in detached state. On Posix
+	// platforms, this setting attempts to daemonize the new child, closing
+	// std handles and the like, and that's a bit more detachment than we
+	// want. autokill=false just means not to implicitly kill the child when
+	// the parent terminates!
+//	chkapr(apr_procattr_detach_set(procattr, params.autokill? 0 : 1));
+
+	if (params.autokill)
+	{
+#if defined(APR_HAS_PROCATTR_AUTOKILL_SET)
+		apr_status_t ok = apr_procattr_autokill_set(procattr, 1);
+# if LL_WINDOWS
+		// As of 2012-02-02, we only expect this to be implemented on Windows.
+		// Avoid spamming the log with warnings we fully expect.
+		ll_apr_warn_status(ok);
+# endif // LL_WINDOWS
+#else
+		LL_WARNS("LLProcess") << "This version of APR lacks Linden apr_procattr_autokill_set() extension" << LL_ENDL;
+#endif
+	}
+
+	// Have to instantiate named std::strings for string params items so their
+	// c_str() values persist.
+	std::string cwd(params.cwd);
+	if (! cwd.empty())
+	{
+		chkapr(apr_procattr_dir_set(procattr, cwd.c_str()));
+	}
+
+	// create an argv vector for the child process
+	std::vector<const char*> argv;
+
+	// add the executable path
+	std::string executable(params.executable);
+	argv.push_back(executable.c_str());
+
+	// and any arguments
+	std::vector<std::string> args(params.args.begin(), params.args.end());
+	BOOST_FOREACH(const std::string& arg, args)
+	{
+		argv.push_back(arg.c_str());
+	}
+
+	// terminate with a null pointer
+	argv.push_back(NULL);
+
+	// Launch! The NULL would be the environment block, if we were passing one.
+	chkapr(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr, gAPRPoolp));    
+
+	// arrange to call status_callback()
+	apr_proc_other_child_register(&mProcess, &LLProcess::status_callback, this, mProcess.in,
+								  gAPRPoolp);
+	mStatus.mState = RUNNING;
+
+	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << mProcess.pid << ')');
+	LL_INFOS("LLProcess") << "Launched " << params << " (" << mProcess.pid << ")" << LL_ENDL;
+
+	// Unless caller explicitly turned off autokill (child should persist),
+	// take steps to terminate the child. This is all suspenders-and-belt: in
+	// theory our destructor should kill an autokill child, but in practice
+	// that doesn't always work (e.g. VWR-21538).
+	if (params.autokill)
+	{
+		// Tie the lifespan of this child process to the lifespan of our APR
+		// pool: on destruction of the pool, forcibly kill the process. Tell
+		// APR to try SIGTERM and wait 3 seconds. If that didn't work, use
+		// SIGKILL.
+		apr_pool_note_subprocess(gAPRPoolp, &mProcess, APR_KILL_AFTER_TIMEOUT);
+
+		// On Windows, associate the new child process with our Job Object.
+		autokill();
+	}
 }
 
 LLProcess::~LLProcess()
 {
+	// Only in state RUNNING are we registered for callback. In UNSTARTED we
+	// haven't yet registered. And since receiving the callback is the only
+	// way we detect child termination, we only change from state RUNNING at
+	// the same time we unregister.
+	if (mStatus.mState == RUNNING)
+	{
+		// We're still registered for a callback: unregister. Do it before
+		// we even issue the kill(): even if kill() somehow prompted an
+		// instantaneous callback (unlikely), this object is going away! Any
+		// information updated in this object by such a callback is no longer
+		// available to any consumer anyway.
+		apr_proc_other_child_unregister(this);
+	}
+
 	if (mAutokill)
 	{
-		kill();
+		kill("destructor");
+	}
+}
+
+bool LLProcess::kill(const std::string& who)
+{
+	if (isRunning())
+	{
+		LL_INFOS("LLProcess") << who << " killing " << mDesc << LL_ENDL;
+
+#if LL_WINDOWS
+		int sig = -1;
+#else  // Posix
+		int sig = SIGTERM;
+#endif
+
+		ll_apr_warn_status(apr_proc_kill(&mProcess, sig));
 	}
+
+	return ! isRunning();
 }
 
 bool LLProcess::isRunning(void)
 {
-	mProcessHandle = isRunning(mProcessHandle, mDesc);
-	return (mProcessHandle != 0);
+	return getStatus().mState == RUNNING;
+}
+
+LLProcess::Status LLProcess::getStatus()
+{
+	// Only when mState is RUNNING might the status change dynamically. For
+	// any other value, pointless to attempt to update status: it won't
+	// change.
+	if (mStatus.mState == RUNNING)
+	{
+		// Tell APR to sense whether the child is still running and call
+		// handle_status() appropriately. We should be able to get the same
+		// info from an apr_proc_wait(APR_NOWAIT) call; but at least in APR
+		// 1.4.2, testing suggests that even with APR_NOWAIT, apr_proc_wait()
+		// blocks the caller. We can't have that in the viewer. Hence the
+		// callback rigmarole. Once we update APR, it's probably worth testing
+		// again. Also -- although there's an apr_proc_other_child_refresh()
+		// call, i.e. get that information for one specific child, it accepts
+		// an 'apr_other_child_rec_t*' that's mentioned NOWHERE else in the
+		// documentation or header files! I would use the specific call if I
+		// knew how. As it is, each call to this method will call callbacks
+		// for ALL still-running child processes. Sigh...
+		apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
+	}
+
+	return mStatus;
+}
+
+std::string LLProcess::getStatusString()
+{
+	return getStatusString(getStatus());
+}
+
+std::string LLProcess::getStatusString(const Status& status)
+{
+	return getStatusString(mDesc, status);
+}
+
+//static
+std::string LLProcess::getStatusString(const std::string& desc, const Status& status)
+{
+	if (status.mState == UNSTARTED)
+		return desc + " was never launched";
+
+	if (status.mState == RUNNING)
+		return desc + " running";
+
+	if (status.mState == EXITED)
+		return STRINGIZE(desc << " exited with code " << status.mData);
+
+	if (status.mState == KILLED)
+#if LL_WINDOWS
+		return STRINGIZE(desc << " killed with exception " << std::hex << status.mData);
+#else
+		return STRINGIZE(desc << " killed by signal " << status.mData);
+#endif
+
+
+	return STRINGIZE(desc << " in unknown state " << status.mState << " (" << status.mData << ")");
+}
+
+// Classic-C-style APR callback
+void LLProcess::status_callback(int reason, void* data, int status)
+{
+	// Our only role is to bounce this static method call back into object
+	// space.
+	static_cast<LLProcess*>(data)->handle_status(reason, status);
+}
+
+#define tabent(symbol) { symbol, #symbol }
+static struct ReasonCode
+{
+	int code;
+	const char* name;
+} reasons[] =
+{
+	tabent(APR_OC_REASON_DEATH),
+	tabent(APR_OC_REASON_UNWRITABLE),
+	tabent(APR_OC_REASON_RESTART),
+	tabent(APR_OC_REASON_UNREGISTER),
+	tabent(APR_OC_REASON_LOST),
+	tabent(APR_OC_REASON_RUNNING)
+};
+#undef tabent
+
+// Object-oriented callback
+void LLProcess::handle_status(int reason, int status)
+{
+	{
+		// This odd appearance of LL_DEBUGS is just to bracket a lookup that will
+		// only be performed if in fact we're going to produce the log message.
+		LL_DEBUGS("LLProcess") << empty;
+		std::string reason_str;
+		BOOST_FOREACH(const ReasonCode& rcp, reasons)
+		{
+			if (reason == rcp.code)
+			{
+				reason_str = rcp.name;
+				break;
+			}
+		}
+		if (reason_str.empty())
+		{
+			reason_str = STRINGIZE("unknown reason " << reason);
+		}
+		LL_CONT << mDesc << ": handle_status(" << reason_str << ", " << status << ")" << LL_ENDL;
+	}
+
+	if (! (reason == APR_OC_REASON_DEATH || reason == APR_OC_REASON_LOST))
+	{
+		// We're only interested in the call when the child terminates.
+		return;
+	}
+
+	// Somewhat oddly, APR requires that you explicitly unregister even when
+	// it already knows the child has terminated. We must pass the same 'data'
+	// pointer as for the register() call, which was our 'this'.
+	apr_proc_other_child_unregister(this);
+	// We overload mStatus.mState to indicate whether the child is registered
+	// for APR callback: only RUNNING means registered. Track that we've
+	// unregistered. We know the child has terminated; might be EXITED or
+	// KILLED; refine below.
+	mStatus.mState = EXITED;
+
+//	wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
+	// It's just wrong to call apr_proc_wait() here. The only way APR knows to
+	// call us with APR_OC_REASON_DEATH is that it's already reaped this child
+	// process, so calling wait() will only produce "huh?" from the OS. We
+	// must rely on the status param passed in, which unfortunately comes
+	// straight from the OS wait() call, which means we have to decode it by
+	// hand.
+	mStatus = interpret_status(status);
+	LL_INFOS("LLProcess") << getStatusString() << LL_ENDL;
 }
 
 LLProcess::id LLProcess::getProcessID() const
 {
-	return mProcessID;
+	return mProcess.pid;
 }
 
 LLProcess::handle LLProcess::getProcessHandle() const
 {
-	return mProcessHandle;
+#if LL_WINDOWS
+	return mProcess.hproc;
+#else
+	return mProcess.pid;
+#endif
 }
 
 std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
@@ -178,77 +454,15 @@ private:
 	LLProcess::handle mJob;
 };
 
-void LLProcess::launch(const LLSDOrParams& params)
+void LLProcess::autokill()
 {
-	PROCESS_INFORMATION pinfo;
-	STARTUPINFOA sinfo = { sizeof(sinfo) };
-
-	// LLProcess::create()'s caller passes a Unix-style array of strings for
-	// command-line arguments. Our caller can and should expect that these will be
-	// passed to the child process as individual arguments, regardless of content
-	// (e.g. embedded spaces). But because Windows invokes any child process with
-	// a single command-line string, this means we must quote each argument behind
-	// the scenes.
-	std::string args = LLStringUtil::quote(params.executable);
-	BOOST_FOREACH(const std::string& arg, params.args)
-	{
-		args += " ";
-		args += LLStringUtil::quote(arg);
-	}
-
-	// So retarded.  Windows requires that the second parameter to
-	// CreateProcessA be a writable (non-const) string...
-	std::vector<char> args2(args.begin(), args.end());
-	args2.push_back('\0');
-
-	// Convert wrapper to a real std::string so we can use c_str(); but use a
-	// named variable instead of a temporary so c_str() pointer remains valid.
-	std::string cwd(params.cwd);
-	const char * working_directory = 0;
-	if (! cwd.empty())
-		working_directory = cwd.c_str();
-
-	// It's important to pass CREATE_BREAKAWAY_FROM_JOB because Windows 7 et
-	// al. tend to implicitly launch new processes already bound to a job. From
-	// http://msdn.microsoft.com/en-us/library/windows/desktop/ms681949%28v=vs.85%29.aspx :
-	// "The process must not already be assigned to a job; if it is, the
-	// function fails with ERROR_ACCESS_DENIED." ...
-	// "If the process is being monitored by the Program Compatibility
-	// Assistant (PCA), it is placed into a compatibility job. Therefore, the
-	// process must be created using CREATE_BREAKAWAY_FROM_JOB before it can
-	// be placed in another job."
-	if( ! CreateProcessA(NULL,      // lpApplicationName
-                         &args2[0], // lpCommandLine
-                         NULL,      // lpProcessAttributes
-                         NULL,      // lpThreadAttributes
-                         FALSE,     // bInheritHandles
-                         CREATE_BREAKAWAY_FROM_JOB, // dwCreationFlags
-                         NULL,      // lpEnvironment
-                         working_directory, // lpCurrentDirectory
-                         &sinfo,            // lpStartupInfo
-                         &pinfo ) )         // lpProcessInformation
-	{
-		throw LLProcessError(WindowsErrorString("CreateProcessA"));
-	}
-
-	// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
-	mProcessID = pinfo.dwProcessId;
-	mProcessHandle = pinfo.hProcess;
-	CloseHandle(pinfo.hThread); // stops leaks - nothing else
-
-	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << mProcessID << ')');
-	LL_INFOS("LLProcess") << "Launched " << params << " (" << mProcessID << ")" << LL_ENDL;
-
-	// Now associate the new child process with our Job Object -- unless
-	// autokill is false, i.e. caller asserts the child should persist.
-	if (params.autokill)
-	{
-		LLJob::instance().assignProcess(mDesc, mProcessHandle);
-}
+	LLJob::instance().assignProcess(mDesc, mProcess.hproc);
 }
 
 LLProcess::handle LLProcess::isRunning(handle h, const std::string& desc)
 {
+	// This direct Windows implementation is because we have no access to the
+	// apr_proc_t struct: we expect it's been destroyed.
 	if (! h)
 		return 0;
 
@@ -258,22 +472,44 @@ LLProcess::handle LLProcess::isRunning(handle h, const std::string& desc)
 		// the process has completed.
 		if (! desc.empty())
 		{
-			LL_INFOS("LLProcess") << desc << " terminated" << LL_ENDL;
+			DWORD status = 0;
+			if (! GetExitCodeProcess(h, &status))
+			{
+				LL_WARNS("LLProcess") << desc << " terminated, but "
+									  << WindowsErrorString("GetExitCodeProcess()") << LL_ENDL;
+			}
+			{
+				LL_INFOS("LLProcess") << getStatusString(desc, interpret_status(status))
+									  << LL_ENDL;
+			}
 		}
+		CloseHandle(h);
 		return 0;
 	}
 
 	return h;
 }
 
-bool LLProcess::kill(void)
+static LLProcess::Status interpret_status(int status)
 {
-	if (! mProcessHandle)
-		return false;
+	LLProcess::Status result;
+
+	// This bit of code is cribbed from apr/threadproc/win32/proc.c, a
+	// function (unfortunately static) called why_from_exit_code():
+	/* See WinNT.h STATUS_ACCESS_VIOLATION and family for how
+	 * this class of failures was determined
+	 */
+	if ((status & 0xFFFF0000) == 0xC0000000)
+	{
+		result.mState = KILLED;
+	}
+	else
+	{
+		result.mState = EXITED;
+	}
+	result.mData = status;
 
-	LL_INFOS("LLProcess") << "killing " << mDesc << LL_ENDL;
-	TerminateProcess(mProcessHandle, 0);
-	return ! isRunning();
+	return result;
 }
 
 /// GetLastError()/FormatMessage() boilerplate
@@ -315,98 +551,91 @@ static std::string WindowsErrorString(const std::string& operation)
 #include <errno.h>
 #include <sys/wait.h>
 
+void LLProcess::autokill()
+{
+	// What we ought to do here is to:
+	// 1. create a unique process group and run all autokill children in that
+	//    group (see https://jira.secondlife.com/browse/SWAT-563);
+	// 2. figure out a way to intercept control when the viewer exits --
+	//    gracefully or not; 
+	// 3. when the viewer exits, kill off the aforementioned process group.
+
+	// It's point 2 that's troublesome. Although I've seen some signal-
+	// handling logic in the Posix viewer code, I haven't yet found any bit of
+	// code that's run no matter how the viewer exits (a try/finally for the
+	// whole process, as it were).
+}
+
 // Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise.
-static bool reap_pid(pid_t pid)
+static bool reap_pid(pid_t pid, LLProcess::Status* pstatus=NULL)
 {
-	pid_t wait_result = ::waitpid(pid, NULL, WNOHANG);
+	LLProcess::Status dummy;
+	if (! pstatus)
+	{
+		// If caller doesn't want to see Status, give us a target anyway so we
+		// don't have to have a bunch of conditionals.
+		pstatus = &dummy;
+	}
+
+	int status = 0;
+	pid_t wait_result = ::waitpid(pid, &status, WNOHANG);
 	if (wait_result == pid)
 	{
+		*pstatus = interpret_status(status);
 		return true;
 	}
-	if (wait_result == -1 && errno == ECHILD)
+	if (wait_result == 0)
 	{
-		// No such process -- this may mean we're ignoring SIGCHILD.
-		return true;
+		pstatus->mState = LLProcess::RUNNING;
+		pstatus->mData	= 0;
+		return false;
 	}
-	
-	return false;
-}
 
-void LLProcess::launch(const LLSDOrParams& params)
-{
-	// flush all buffers before the child inherits them
-	::fflush(NULL);
+	// Clear caller's Status block; caller must interpret UNSTARTED to mean
+	// "if this PID was ever valid, it no longer is."
+	*pstatus = LLProcess::Status();
 
-	pid_t child = vfork();
-	if (child == 0)
+	// We've dealt with the success cases: we were able to reap the child
+	// (wait_result == pid) or it's still running (wait_result == 0). It may
+	// be that the child terminated but didn't hang around long enough for us
+	// to reap. In that case we still have no Status to report, but we can at
+	// least state that it's not running.
+	if (wait_result == -1 && errno == ECHILD)
 	{
-		// child process
-
-		std::string cwd(params.cwd);
-		if (! cwd.empty())
-		{
-			// change to the desired child working directory
-			if (::chdir(cwd.c_str()))
-			{
-				// chdir failed
-				LL_WARNS("LLProcess") << "could not chdir(\"" << cwd << "\")" << LL_ENDL;
-				// pointless to throw; this is child process...
-				_exit(248);
-			}
-		}
-
-		// create an argv vector for the child process
-		std::vector<const char*> fake_argv;
-
-		// add the executable path
-		std::string executable(params.executable);
-		fake_argv.push_back(executable.c_str());
-
-		// and any arguments
-		std::vector<std::string> args(params.args.begin(), params.args.end());
-		BOOST_FOREACH(const std::string& arg, args)
-		{
-			fake_argv.push_back(arg.c_str());
-		}
-
-		// terminate with a null pointer
-		fake_argv.push_back(NULL);
-
-		::execv(executable.c_str(), const_cast<char* const*>(&fake_argv[0]));
-
-		// If we reach this point, the exec failed.
-		LL_WARNS("LLProcess") << "failed to launch: ";
-		BOOST_FOREACH(const char* arg, fake_argv)
-		{
-			LL_CONT << arg << ' ';
-		}
-		LL_CONT << LL_ENDL;
-		// Use _exit() instead of exit() per the vfork man page. Exit with a
-		// distinctive rc: someday soon we'll be able to retrieve it, and it
-		// would be nice to be able to tell that the child process failed!
-		_exit(249);
+		// No such process -- this may mean we're ignoring SIGCHILD.
+		return true;
 	}
 
-	// parent process
-	mProcessID = child;
-	mProcessHandle = child;
-
-	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << mProcessID << ')');
-	LL_INFOS("LLProcess") << "Launched " << params << " (" << mProcessID << ")" << LL_ENDL;
+	// Uh, should never happen?!
+	LL_WARNS("LLProcess") << "LLProcess::reap_pid(): waitpid(" << pid << ") returned "
+						  << wait_result << "; not meaningful?" << LL_ENDL;
+	// If caller is looping until this pid terminates, and if we can't find
+	// out, better to break the loop than to claim it's still running.
+	return true;
 }
 
 LLProcess::id LLProcess::isRunning(id pid, const std::string& desc)
 {
+	// This direct Posix implementation is because we have no access to the
+	// apr_proc_t struct: we expect it's been destroyed.
 	if (! pid)
 		return 0;
 
 	// Check whether the process has exited, and reap it if it has.
-	if(reap_pid(pid))
+	LLProcess::Status status;
+	if(reap_pid(pid, &status))
 	{
 		// the process has exited.
 		if (! desc.empty())
 		{
-			LL_INFOS("LLProcess") << desc << " terminated" << LL_ENDL;
+			std::string statstr(desc + " apparently terminated: no status available");
+			// We don't just pass UNSTARTED to getStatusString() because, in
+			// the context of reap_pid(), that state has special meaning.
+			if (status.mState != UNSTARTED)
+			{
+				statstr = getStatusString(desc, status);
+			}
+			LL_INFOS("LLProcess") << statstr << LL_ENDL;
 		}
 		return 0;
 	}
@@ -414,18 +643,27 @@ LLProcess::id LLProcess::isRunning(id pid, const std::string& desc)
 	return pid;
 }
 
-bool LLProcess::kill(void)
+static LLProcess::Status interpret_status(int status)
 {
-	if (! mProcessID)
-		return false;
+	LLProcess::Status result;
 
-	// Try to kill the process. We'll do approximately the same thing whether
-	// the kill returns an error or not, so we ignore the result.
-	LL_INFOS("LLProcess") << "killing " << mDesc << LL_ENDL;
-	(void)::kill(mProcessID, SIGTERM);
+	if (WIFEXITED(status))
+	{
+		result.mState = LLProcess::EXITED;
+		result.mData  = WEXITSTATUS(status);
+	}
+	else if (WIFSIGNALED(status))
+	{
+		result.mState = LLProcess::KILLED;
+		result.mData  = WTERMSIG(status);
+	}
+	else                            // uh, shouldn't happen?
+	{
+		result.mState = LLProcess::EXITED;
+		result.mData  = status;     // someone else will have to decode
+	}
 
-	// This will have the side-effect of reaping the zombie if the process has exited.
-	return ! isRunning();
+	return result;
 }
 
 /*==========================================================================*|
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 8a842589ec..689f8aedab 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -29,6 +29,7 @@
 
 #include "llinitparam.h"
 #include "llsdparam.h"
+#include "apr_thread_proc.h"
 #include <boost/shared_ptr.hpp>
 #include <boost/noncopyable.hpp>
 #include <iosfwd>                   // std::ostream
@@ -95,13 +96,52 @@ public:
 	static LLProcessPtr create(const LLSDOrParams& params);
 	virtual ~LLProcess();
 
-	// isRunning isn't const because, if child isn't running, it clears stored
-	// process ID
+	// isRunning() isn't const because, when child terminates, it sets stored
+	// Status
 	bool isRunning(void);
-	
+
+	/**
+	 * State of child process
+	 */
+	enum state
+	{
+		UNSTARTED,					///< initial value, invisible to consumer
+		RUNNING,					///< child process launched
+		EXITED,						///< child process terminated voluntarily
+		KILLED						///< child process terminated involuntarily
+	};
+
+	/**
+	 * Status info
+	 */
+	struct Status
+	{
+		Status():
+			mState(UNSTARTED),
+			mData(0)
+		{}
+
+		state mState;				///< @see state
+		/**
+		 * - for mState == EXITED: mData is exit() code
+		 * - for mState == KILLED: mData is signal number (Posix)
+		 * - otherwise: mData is undefined
+		 */
+		int mData;
+	};
+
+	/// Status query
+	Status getStatus();
+	/// English Status string query, for logging etc.
+	std::string getStatusString();
+	/// English Status string query for previously-captured Status
+	std::string getStatusString(const Status& status);
+	/// static English Status string query
+	static std::string getStatusString(const std::string& desc, const Status& status);
+
 	// Attempt to kill the process -- returns true if the process is no longer running when it returns.
 	// Note that even if this returns false, the process may exit some time after it's called.
-	bool kill(void);
+	bool kill(const std::string& who="");
 
 #if LL_WINDOWS
 	typedef int id;                 ///< as returned by getProcessID()
@@ -133,18 +173,28 @@ public:
 	 * a whole set of operations supported on freestanding @c handle values.
 	 * New functionality should be added as nonstatic members operating on
 	 * the same data as getProcessHandle().
+	 *
+	 * In particular, if child termination is detected by static isRunning()
+	 * rather than by nonstatic isRunning(), the LLProcess object won't be
+	 * aware of the child's changed status and may encounter OS errors trying
+	 * to obtain it. static isRunning() is only intended for after the
+	 * launching LLProcess object has been destroyed.
 	 */
 	static handle isRunning(handle, const std::string& desc="");
 
 private:
 	/// constructor is private: use create() instead
 	LLProcess(const LLSDOrParams& params);
-	void launch(const LLSDOrParams& params);
+	void autokill();
+	// Classic-C-style APR callback
+	static void status_callback(int reason, void* data, int status);
+	// Object-oriented callback
+	void handle_status(int reason, int status);
 
 	std::string mDesc;
-	id mProcessID;
-	handle mProcessHandle;
+	apr_proc_t mProcess;
 	bool mAutokill;
+	Status mStatus;
 };
 
 /// for logging
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 4ad45bdf27..60ed12ad6a 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -630,7 +630,7 @@ namespace tut
             // Destroy the LLProcess, which should kill the child.
         }
         // wait for the script to terminate... one way or another.
-        while (LLProcess::isRunning(phandle))
+        while (LLProcess::isRunning(phandle, "kill() script"))
         {
             sleep(1);
         }
@@ -643,7 +643,7 @@ namespace tut
     template<> template<>
     void object::test<6>()
     {
-        set_test_name("autokill");
+        set_test_name("autokill=false");
         NamedTempFile from("from", "not started");
         NamedTempFile to("to", "");
         LLProcess::handle phandle(0);
@@ -695,7 +695,7 @@ namespace tut
             outf << "go";
         } // flush and close.
         // now wait for the script to terminate... one way or another.
-        while (LLProcess::isRunning(phandle))
+        while (LLProcess::isRunning(phandle, "autokill script"))
         {
             sleep(1);
         }
-- 
cgit v1.2.3


From 219a010aaf4891fc2ab8480a2121b1244191c24d Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 7 Feb 2012 11:17:04 -0500
Subject: LLProcess::Status enum values need qualification in helper function.

---
 indra/llcommon/llprocess.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index bc27002701..1305c1d764 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -501,11 +501,11 @@ static LLProcess::Status interpret_status(int status)
 	 */
 	if ((status & 0xFFFF0000) == 0xC0000000)
 	{
-		result.mState = KILLED;
+		result.mState = LLProcess::KILLED;
 	}
 	else
 	{
-		result.mState = EXITED;
+		result.mState = LLProcess::EXITED;
 	}
 	result.mData = status;
 
-- 
cgit v1.2.3


From 5d2bb536324a906078b224bdc9697b368e96a6b6 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 7 Feb 2012 12:06:03 -0500
Subject: On Linux, #undef Status: we use that name for nested LLProcess
 struct. Apparently something in the Linux system header chain #defines a
 macro Status as 'int'. That's just Bad in C++ land. It should at the very
 least be a typedef! #undefining it in llprocess.h permits the viewer to
 build.

---
 indra/llcommon/llprocess.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 689f8aedab..0de033c15b 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -37,6 +37,10 @@
 #if LL_WINDOWS
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>                // HANDLE (eye roll)
+#elif LL_LINUX
+#if defined(Status)
+#undef Status
+#endif
 #endif
 
 class LLProcess;
-- 
cgit v1.2.3


From 32e11494ffde368b2ac166e16dc294d66a18492f Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 7 Feb 2012 12:28:57 -0500
Subject: Use os.path.normcase(os.path.normpath()) when comparing directories.
 Once again we've been bitten by comparison failure between "c:\somepath" and
 "C:\somepath". Normalize paths in both Python helper scripts to make that
 comparison more robust.

---
 indra/llcommon/tests/llprocess_test.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 60ed12ad6a..6d2292fb88 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -186,7 +186,7 @@ public:
                          "from __future__ import with_statement\n"
                          "import os.path, sys, tempfile\n"
                          "with open(sys.argv[1], 'w') as f:\n"
-                         "    f.write(os.path.realpath(tempfile.mkdtemp()))\n"))
+                         "    f.write(os.path.normcase(os.path.normpath(os.path.realpath(tempfile.mkdtemp()))))\n"))
     {}
 
     ~NamedTempDir()
@@ -513,7 +513,7 @@ namespace tut
                                  "from __future__ import with_statement\n"
                                  "import os, sys\n"
                                  "with open(sys.argv[1], 'w') as f:\n"
-                                 "    f.write(os.getcwd())\n");
+                                 "    f.write(os.path.normcase(os.path.normpath(os.getcwd())))\n");
         // Before running, call setWorkingDirectory()
         py.mParams.cwd = tempdir.getName();
         ensure_equals("os.getcwd()", py.run_read(), tempdir.getName());
-- 
cgit v1.2.3


From 33a42b32ca72031a79edca821966f6ebbdcddc93 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 7 Feb 2012 13:06:38 -0500
Subject: Disable MSVC warning C4702 (unreachable code) in Boost headers.

---
 indra/test/test.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 3e7be29b39..1adcfb6f45 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -54,8 +54,16 @@
 #include <gtest/gtest.h>
 #endif
 
+#if LL_MSVC
+#pragma warning (push)
+#pragma warning (disable : 4702) // warning C4702: unreachable code
+#endif
 #include <boost/iostreams/tee.hpp>
 #include <boost/iostreams/stream.hpp>
+#if LL_MSVC
+#pragma warning (pop)
+#endif
+
 #include <boost/shared_ptr.hpp>
 #include <boost/make_shared.hpp>
 #include <boost/foreach.hpp>
-- 
cgit v1.2.3


From 2d360cb08d2bee098168e3c3f5041ec37206f383 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 9 Feb 2012 07:44:23 -0500
Subject: Use new 3p-apr package builds for Windows, Mac. On Linux, new (Feb
 2012) APR package produces link errors. Until those are resolved, leave Linux
 viewer build with older (Feb 2011) APR package.

---
 autobuild.xml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 9914be6867..9cecdd7f09 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -90,9 +90,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>9868bfa0b6954e4884c49c6f30068c80</string>
+              <string>6e5172597f00380b5004b8a7911098b7</string>
               <key>url</key>
-              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.4.2-darwin-20110217.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249125/arch/Darwin/installer/apr_suite-1.4.5-darwin-20120208.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -114,9 +114,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>73785c200a5b4ef74a1230b028bb680d</string>
+              <string>a596a9974ae6bfe48dc61a2cd13bc321</string>
               <key>url</key>
-              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.4.2-windows-20110217.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249125/arch/CYGWIN/installer/apr_suite-1.4.5-windows-20120208.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
-- 
cgit v1.2.3


From 58348bd862163261fb650d8afd50fd1dc5e2695a Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 9 Feb 2012 15:07:02 -0500
Subject: Use newer (Linden extension) TC APR builds for Windows, Mac.

---
 autobuild.xml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 9cecdd7f09..80b1a8a709 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -90,9 +90,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>6e5172597f00380b5004b8a7911098b7</string>
+              <string>71d4d242c41ec9ac4807989371279708</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249125/arch/Darwin/installer/apr_suite-1.4.5-darwin-20120208.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249241/arch/Darwin/installer/apr_suite-1.4.5-darwin-20120209.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -114,9 +114,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>a596a9974ae6bfe48dc61a2cd13bc321</string>
+              <string>983378883a6eec65665875a3d1ba495f</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249125/arch/CYGWIN/installer/apr_suite-1.4.5-windows-20120208.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249241/arch/CYGWIN/installer/apr_suite-1.4.5-windows-20120209.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
-- 
cgit v1.2.3


From 90a1b67cc43792e1ca0047eaca51530aa14e134c Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 9 Feb 2012 15:22:24 -0500
Subject: Remove LLJob class: apr_procattr_autokill_set() should now handle.
 LLJob was vestigial code from before migrating Job Object support into APR.
 Also add APR signal-name string to getStatusString() output.

---
 indra/llcommon/llprocess.cpp | 70 +++-----------------------------------------
 1 file changed, 4 insertions(+), 66 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 1305c1d764..7ccbdeed01 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -31,6 +31,7 @@
 #include "llstring.h"
 #include "stringize.h"
 #include "llapr.h"
+#include "apr_signal.h"
 
 #include <boost/foreach.hpp>
 #include <iostream>
@@ -274,10 +275,10 @@ std::string LLProcess::getStatusString(const std::string& desc, const Status& st
 #if LL_WINDOWS
 		return STRINGIZE(desc << " killed with exception " << std::hex << status.mData);
 #else
-		return STRINGIZE(desc << " killed by signal " << status.mData);
+		return STRINGIZE(desc << " killed by signal " << status.mData
+						 << " (" << apr_signal_description_get(status.mData) << ")");
 #endif
 
-
 	return STRINGIZE(desc << " in unknown state " << status.mState << " (" << status.mData << ")");
 }
 
@@ -391,72 +392,9 @@ std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
 
 static std::string WindowsErrorString(const std::string& operation);
 
-/**
- * Wrap a Windows Job Object for use in managing child-process lifespan.
- *
- * On Windows, we use a Job Object to constrain the lifespan of any
- * autokill=true child process to the viewer's own lifespan:
- * http://stackoverflow.com/questions/53208/how-do-i-automatically-destroy-child-processes-in-windows
- * (thanks Richard!).
- *
- * We manage it using an LLSingleton for a couple of reasons:
- *
- * # Lazy initialization: if some viewer session never launches a child
- *   process, we should never have to create a Job Object.
- * # Cross-DLL support: be wary of C++ statics when multiple DLLs are
- *   involved.
- */
-class LLJob: public LLSingleton<LLJob>
-{
-public:
-	void assignProcess(const std::string& prog, LLProcess::handle hProcess)
-	{
-		// If we never managed to initialize this Job Object, can't use it --
-		// but don't keep spamming the log, we already emitted warnings when
-		// we first tried to create.
-		if (! mJob)
-			return;
-
-		if (! AssignProcessToJobObject(mJob, hProcess))
-		{
-			LL_WARNS("LLProcess") << WindowsErrorString(STRINGIZE("AssignProcessToJobObject("
-																  << prog << ")")) << LL_ENDL;
-		}
-	}
-
-private:
-	friend class LLSingleton<LLJob>;
-	LLJob():
-		mJob(0)
-	{
-		mJob = CreateJobObject(NULL, NULL);
-		if (! mJob)
-		{
-			LL_WARNS("LLProcess") << WindowsErrorString("CreateJobObject()") << LL_ENDL;
-			return;
-		}
-
-		JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
-
-		// Configure all child processes associated with this new job object
-		// to terminate when the calling process (us!) terminates.
-		jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
-		if (! SetInformationJobObject(mJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
-		{
-			LL_WARNS("LLProcess") << WindowsErrorString("SetInformationJobObject()") << LL_ENDL;
-			// This Job Object is useless to us
-			CloseHandle(mJob);
-			// prevent assignProcess() from trying to use it
-			mJob = 0;
-		}
-	}
-
-	LLProcess::handle mJob;
-};
-
 void LLProcess::autokill()
 {
-	LLJob::instance().assignProcess(mDesc, mProcess.hproc);
+	// hopefully now handled by apr_procattr_autokill_set()
 }
 
 LLProcess::handle LLProcess::isRunning(handle h, const std::string& desc)
-- 
cgit v1.2.3


From 028a05e79467e0c1fd7d63224fb447a964ab7a0b Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 10 Feb 2012 12:04:27 -0500
Subject: Use wildcards instead of many version-specific lib names on Linux.
 viewer_manifest.py's Linux_i686Manifest class has contained directives to
 copy library files with names like (e.g.) "libapr-1.so.0.4.2", which means
 that every update to any such library requires messing with
 viewer_manifest.py. But LLManifest.path() claims to support wildcards, and
 it's more robust to specify "libapr-1.so*" instead. Unfortunately
 LLManifest.path()'s wildcard support only used to work for files in the
 source tree (vs. the artwork tree or the build tree). The logic in path()
 tries each tree in turn, relying on an exception to make it try the next
 tree. This exception was raised for a nonexistent specific filename -- but it
 never used to raise that exception for a wildcard matching 0 files. Instead
 it would simply report "0 files" and proceed, producing an invalid viewer
 install. Raise that exception for a wildcard matching nothing. This forces
 path() to consider the artwork tree and the build tree, permitting us to use
 wildcards in library names. Define an exception specific to LLManifest:
 ManifestException rather than the generic Python RuntimeException. Make it a
 subclass of RuntimeException so any existing callers expecting to catch
 RuntimeException will continue to work.

---
 indra/lib/python/indra/util/llmanifest.py | 27 +++++++++++++-------
 indra/newview/viewer_manifest.py          | 42 +++++++++++--------------------
 2 files changed, 32 insertions(+), 37 deletions(-)

diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index c33a03034a..237153b756 100644
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -41,6 +41,9 @@ import tarfile
 import errno
 import subprocess
 
+class ManifestError(RuntimeError):
+    pass
+
 def path_ancestors(path):
     drive, path = os.path.splitdrive(os.path.normpath(path))
     result = []
@@ -180,6 +183,9 @@ def usage(srctree=""):
             arg['description'] % nd)
 
 def main():
+##  import itertools
+##  print ' '.join((("'%s'" % item) if ' ' in item else item)
+##                 for item in itertools.chain([sys.executable], sys.argv))
     option_names = [arg['name'] + '=' for arg in ARGUMENTS]
     option_names.append('help')
     options, remainder = getopt.getopt(sys.argv[1:], "", option_names)
@@ -385,7 +391,7 @@ class LLManifest(object):
         child.stdout.close()
         status = child.wait()
         if status:
-            raise RuntimeError(
+            raise ManifestError(
                 "Command %s returned non-zero status (%s) \noutput:\n%s"
                 % (command, status, output) )
         return output
@@ -395,7 +401,7 @@ class LLManifest(object):
           a) verify that you really have created it
           b) schedule it for cleanup"""
         if not os.path.exists(path):
-            raise RuntimeError, "Should be something at path " + path
+            raise ManifestError, "Should be something at path " + path
         self.created_paths.append(path)
 
     def put_in_file(self, contents, dst):
@@ -550,7 +556,7 @@ class LLManifest(object):
             except (IOError, os.error), why:
                 errors.append((srcname, dstname, why))
         if errors:
-            raise RuntimeError, errors
+            raise ManifestError, errors
 
 
     def cmakedirs(self, path):
@@ -598,13 +604,16 @@ class LLManifest(object):
 
     def check_file_exists(self, path):
         if not os.path.exists(path) and not os.path.islink(path):
-            raise RuntimeError("Path %s doesn't exist" % (
-                os.path.normpath(os.path.join(os.getcwd(), path)),))
+            raise ManifestError("Path %s doesn't exist" % (os.path.abspath(path),))
 
 
-    wildcard_pattern = re.compile('\*')
+    wildcard_pattern = re.compile(r'\*')
     def expand_globs(self, src, dst):
         src_list = glob.glob(src)
+        # Assume that if caller specifies a wildcard, s/he wants it to match
+        # at least one file...
+        if not src_list:
+            raise ManifestError("Path %s doesn't exist" % (os.path.abspath(src),))
         src_re, d_template = self.wildcard_regex(src.replace('\\', '/'),
                                                  dst.replace('\\', '/'))
         for s in src_list:
@@ -615,7 +624,7 @@ class LLManifest(object):
         sys.stdout.write("Processing %s => %s ... " % (src, dst))
         sys.stdout.flush()
         if src == None:
-            raise RuntimeError("No source file, dst is " + dst)
+            raise ManifestError("No source file, dst is " + dst)
         if dst == None:
             dst = src
         dst = os.path.join(self.get_dst_prefix(), dst)
@@ -639,10 +648,10 @@ class LLManifest(object):
             return count
         try:
             count = try_path(os.path.join(self.get_src_prefix(), src))
-        except RuntimeError:
+        except ManifestError:
             try:
                 count = try_path(os.path.join(self.get_artwork_prefix(), src))
-            except RuntimeError:
+            except ManifestError:
                 count = try_path(os.path.join(self.get_build_prefix(), src))
         print "%d files" % count
 
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 0931c4ec9b..d65d51ce32 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1025,41 +1025,27 @@ class Linux_i686Manifest(LinuxManifest):
         super(Linux_i686Manifest, self).construct()
 
         if self.prefix("../packages/lib/release", dst="lib"):
-            self.path("libapr-1.so")
-            self.path("libapr-1.so.0")
-            self.path("libapr-1.so.0.4.2")
-            self.path("libaprutil-1.so")
-            self.path("libaprutil-1.so.0")
-            self.path("libaprutil-1.so.0.3.10")
-            self.path("libbreakpad_client.so.0.0.0")
-            self.path("libbreakpad_client.so.0")
-            self.path("libbreakpad_client.so")
+            self.path("libapr-1.so*")
+            self.path("libaprutil-1.so*")
+            self.path("libbreakpad_client.so*")
             self.path("libcollada14dom.so")
-            self.path("libdb-5.1.so")
-            self.path("libdb-5.so")
-            self.path("libdb.so")
-            self.path("libcrypto.so.1.0.0")
-            self.path("libexpat.so.1.5.2")
+            self.path("libdb*.so")
+            self.path("libcrypto.so.*")
+            self.path("libexpat.so.*")
             self.path("libssl.so.1.0.0")
             self.path("libglod.so")
             self.path("libminizip.so")
-            self.path("libuuid.so")
-            self.path("libuuid.so.16")
-            self.path("libuuid.so.16.0.22")
-            self.path("libSDL-1.2.so.0.11.3")
-            self.path("libdirectfb-1.4.so.5.0.4")
-            self.path("libfusion-1.4.so.5.0.4")
-            self.path("libdirect-1.4.so.5.0.4")
-            self.path("libopenjpeg.so.1.4.0")
-            self.path("libopenjpeg.so.1")
-            self.path("libopenjpeg.so")
+            self.path("libuuid.so*")
+            self.path("libSDL-1.2.so.*")
+            self.path("libdirectfb-1.*.so.*")
+            self.path("libfusion-1.*.so.*")
+            self.path("libdirect-1.*.so.*")
+            self.path("libopenjpeg.so*")
             self.path("libalut.so")
             self.path("libopenal.so", "libopenal.so.1")
             self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
-            self.path("libfontconfig.so.1.4.4")
-            self.path("libtcmalloc.so", "libtcmalloc.so") #formerly called google perf tools
-            self.path("libtcmalloc.so.0", "libtcmalloc.so.0") #formerly called google perf tools
-            self.path("libtcmalloc.so.0.1.0", "libtcmalloc.so.0.1.0") #formerly called google perf tools
+            self.path("libfontconfig.so.*")
+            self.path("libtcmalloc.so*") #formerly called google perf tools
             try:
                     self.path("libfmod-3.75.so")
                     pass
-- 
cgit v1.2.3


From 9011b04496796d7e51c20af0241ec05796e1ccac Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 10 Feb 2012 12:11:18 -0500
Subject: Try using Log's new APR packages for Windows, Mac, Linux. This APR
 merges work from Huseby, Log, Leslie, Nat.

---
 autobuild.xml | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 80b1a8a709..a3a5dd0057 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -90,9 +90,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>71d4d242c41ec9ac4807989371279708</string>
+              <string>a2c41379bc0abc83b45246eebdafc4ab</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249241/arch/Darwin/installer/apr_suite-1.4.5-darwin-20120209.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/log_3p-apr/rev/249247/arch/Darwin/installer/apr_suite-1.4.5-darwin-20120209.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -102,9 +102,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>ff62946c518a247c86e1066c1e9a5855</string>
+              <string>1ad6e6bff18306cb5079128d5aadeb6e</string>
               <key>url</key>
-              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.4.2-linux-20110309.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/log_3p-apr-lenny/rev/249247/arch/Linux/installer/apr_suite-1.4.5-linux-20120209.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -114,9 +114,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>983378883a6eec65665875a3d1ba495f</string>
+              <string>31cd12ea119753e389dc9be5ea82cbb3</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249241/arch/CYGWIN/installer/apr_suite-1.4.5-windows-20120209.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/log_3p-apr/rev/249247/arch/CYGWIN/installer/apr_suite-1.4.5-windows-20120209.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
-- 
cgit v1.2.3


From acd46062fd2edf4b45ab646cbacaf865b169ec30 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 10 Feb 2012 16:45:18 -0500
Subject: Eliminate ManifestError for wildcards matching 0 files. Turns out
 that some (many?) wildcard LLManifest.path(wildcard) calls are "just in
 case": sweep up any (e.g.) "*.tga" files there may be, but no problem if
 there are none. Change path() logic so it tries the next tree (source,
 artwork, build) if either a specific (non-wildcard) filename doesn't exist,
 as now, OR if a wildcard matches 0 files in the current tree. This continues
 to support "just in case" wildcards, while permitting wildcards to work in
 the artwork and build trees as well as the source tree. Use a more specific
 exception than ManifestError for missing file. Only in that case should we
 try the next tree. Any other ManifestError should propagate.

---
 indra/lib/python/indra/util/llmanifest.py | 33 ++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 237153b756..a4fb77357c 100644
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -42,6 +42,11 @@ import errno
 import subprocess
 
 class ManifestError(RuntimeError):
+    """Use an exception more specific than generic Python RuntimeError"""
+    pass
+
+class MissingError(ManifestError):
+    """You specified a file that doesn't exist"""
     pass
 
 def path_ancestors(path):
@@ -604,16 +609,12 @@ class LLManifest(object):
 
     def check_file_exists(self, path):
         if not os.path.exists(path) and not os.path.islink(path):
-            raise ManifestError("Path %s doesn't exist" % (os.path.abspath(path),))
+            raise MissingError("Path %s doesn't exist" % (os.path.abspath(path),))
 
 
     wildcard_pattern = re.compile(r'\*')
     def expand_globs(self, src, dst):
         src_list = glob.glob(src)
-        # Assume that if caller specifies a wildcard, s/he wants it to match
-        # at least one file...
-        if not src_list:
-            raise ManifestError("Path %s doesn't exist" % (os.path.abspath(src),))
         src_re, d_template = self.wildcard_regex(src.replace('\\', '/'),
                                                  dst.replace('\\', '/'))
         for s in src_list:
@@ -646,13 +647,23 @@ class LLManifest(object):
                 else:
                     count += self.process_file(src, dst)
             return count
-        try:
-            count = try_path(os.path.join(self.get_src_prefix(), src))
-        except ManifestError:
+
+        for pfx in self.get_src_prefix(), self.get_artwork_prefix(), self.get_build_prefix():
             try:
-                count = try_path(os.path.join(self.get_artwork_prefix(), src))
-            except ManifestError:
-                count = try_path(os.path.join(self.get_build_prefix(), src))
+                count = try_path(os.path.join(pfx, src))
+            except MissingError:
+                # If src isn't a wildcard, and if that file doesn't exist in
+                # this pfx, try next pfx.
+                count = 0
+                continue
+
+            # Here try_path() didn't raise MissingError. Did it process any files?
+            if count:
+                break
+            # Even though try_path() didn't raise MissingError, it returned 0
+            # files. src is probably a wildcard meant for some other pfx. Loop
+            # back to try the next.
+
         print "%d files" % count
 
     def do(self, *actions):
-- 
cgit v1.2.3


From 8804fa524c084edb9f49f4122e2c7330a80c79b5 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 11 Feb 2012 06:16:39 -0500
Subject: Update viewer to official builds of http://hg.secondlife.com/3p-apr.

---
 autobuild.xml | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index a3a5dd0057..99fa201ee3 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -90,9 +90,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>a2c41379bc0abc83b45246eebdafc4ab</string>
+              <string>15333927db9f249daefcaed70fc6683c</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/log_3p-apr/rev/249247/arch/Darwin/installer/apr_suite-1.4.5-darwin-20120209.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249247/arch/Darwin/installer/apr_suite-1.4.5-darwin-20120210.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -102,9 +102,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>1ad6e6bff18306cb5079128d5aadeb6e</string>
+              <string>297508ece8b0f334bae842fd147f2962</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/log_3p-apr-lenny/rev/249247/arch/Linux/installer/apr_suite-1.4.5-linux-20120209.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249247/arch/Linux/installer/apr_suite-1.4.5-linux-20120211.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -114,9 +114,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>31cd12ea119753e389dc9be5ea82cbb3</string>
+              <string>7ad1e767f4419a6d35a70abba1edbcdc</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/log_3p-apr/rev/249247/arch/CYGWIN/installer/apr_suite-1.4.5-windows-20120209.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/249247/arch/CYGWIN/installer/apr_suite-1.4.5-windows-20120210.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
-- 
cgit v1.2.3


From 0f2882ec95fc6cd2649fbe4e952ce1bc586bb853 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 13 Feb 2012 09:41:50 -0500
Subject: Suppress a specific unused-var warning on Posix platforms.

---
 indra/llcommon/llprocess.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 7ccbdeed01..de71595f16 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -120,7 +120,9 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 		// As of 2012-02-02, we only expect this to be implemented on Windows.
 		// Avoid spamming the log with warnings we fully expect.
 		ll_apr_warn_status(ok);
-# endif // LL_WINDOWS
+#else   // ! LL_WINDOWS
+		(void)ok;                   // suppress 'unused' warning
+# endif // ! LL_WINDOWS
 #else
 		LL_WARNS("LLProcess") << "This version of APR lacks Linden apr_procattr_autokill_set() extension" << LL_ENDL;
 #endif
-- 
cgit v1.2.3


From d4f887e43ccf0a8b7a84ebbfe6889462a1d9c25f Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 13 Feb 2012 16:18:46 -0500
Subject: Add unit tests for LLProcess::Status functionality.

---
 indra/llcommon/tests/llprocess_test.cpp | 46 +++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 6d2292fb88..711715e373 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -555,6 +555,41 @@ namespace tut
 
     template<> template<>
     void object::test<4>()
+    {
+        set_test_name("exit(0)");
+        PythonProcessLauncher py("exit(0)",
+                                 "import sys\n"
+                                 "sys.exit(0)\n");
+        py.run();
+        ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED);
+        ensure_equals("Status.mData",  py.mPy->getStatus().mData,  0);
+    }
+
+    template<> template<>
+    void object::test<5>()
+    {
+        set_test_name("exit(2)");
+        PythonProcessLauncher py("exit(2)",
+                                 "import sys\n"
+                                 "sys.exit(2)\n");
+        py.run();
+        ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED);
+        ensure_equals("Status.mData",  py.mPy->getStatus().mData,  2);
+    }
+
+    template<> template<>
+    void object::test<6>()
+    {
+        set_test_name("syntax_error:");
+        PythonProcessLauncher py("syntax_error:",
+                                 "syntax_error:\n");
+        py.run();
+        ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED);
+        ensure_equals("Status.mData",  py.mPy->getStatus().mData,  1);
+    }
+
+    template<> template<>
+    void object::test<7>()
     {
         set_test_name("explicit kill()");
         PythonProcessLauncher py("kill()",
@@ -588,6 +623,13 @@ namespace tut
         {
             sleep(1);
         }
+#if LL_WINDOWS
+        ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED);
+        ensure_equals("Status.mData",  py.mPy->getStatus().mData,  -1);
+#else
+        ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::KILLED);
+        ensure_equals("Status.mData",  py.mPy->getStatus().mData,  SIGTERM);
+#endif
         // If kill() failed, the script would have woken up on its own and
         // overwritten the file with 'bad'. But if kill() succeeded, it should
         // not have had that chance.
@@ -595,7 +637,7 @@ namespace tut
     }
 
     template<> template<>
-    void object::test<5>()
+    void object::test<8>()
     {
         set_test_name("implicit kill()");
         NamedTempFile out("out", "not started");
@@ -641,7 +683,7 @@ namespace tut
     }
 
     template<> template<>
-    void object::test<6>()
+    void object::test<9>()
     {
         set_test_name("autokill=false");
         NamedTempFile from("from", "not started");
-- 
cgit v1.2.3


From aae61392be822218cabcab91d95eb1e75d471764 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 13 Feb 2012 17:38:25 -0500
Subject: Use per-frame ticks on "mainloop" LLEventPump to update LLProcess.
 When we reimplemented LLProcess on APR, necessitating APR's funny callback
 mechanism to sense child-process status, every isRunning() or getStatus()
 call called the APR poll function that calls ALL registered LLProcess
 callbacks. In other words, every time any consumer called any
 LLProcess::isRunning() method, all LLProcess callbacks were redundantly
 fired. Change that so that the single APR poll function is called once per
 frame, courtesy of the "mainloop" LLEventPump. Once per viewer frame should
 be well within the realtime duration in which it's reasonable to expect
 child-process status to change. In effect, this changes LLProcess's public
 API to introduce a dependency on "mainloop" ticks. Add such ticks to
 llprocess_test.cpp as well.

---
 indra/llcommon/llprocess.cpp            | 96 ++++++++++++++++++++++++++-------
 indra/llcommon/llprocess.h              | 20 ++++---
 indra/llcommon/tests/llprocess_test.cpp | 42 +++++++++------
 3 files changed, 114 insertions(+), 44 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index de71595f16..b13e8eb8e0 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -32,8 +32,10 @@
 #include "stringize.h"
 #include "llapr.h"
 #include "apr_signal.h"
+#include "llevents.h"
 
 #include <boost/foreach.hpp>
+#include <boost/bind.hpp>
 #include <iostream>
 #include <stdexcept>
 
@@ -47,6 +49,74 @@ struct LLProcessError: public std::runtime_error
 	LLProcessError(const std::string& msg): std::runtime_error(msg) {}
 };
 
+/**
+ * Ref-counted "mainloop" listener. As long as there are still outstanding
+ * LLProcess objects, keep listening on "mainloop" so we can keep polling APR
+ * for process status.
+ */
+class LLProcessListener
+{
+	LOG_CLASS(LLProcessListener);
+public:
+	LLProcessListener():
+		mCount(0)
+	{}
+
+	void addPoll(const LLProcess&)
+	{
+		// Unconditionally increment mCount. If it was zero before
+		// incrementing, listen on "mainloop".
+		if (mCount++ == 0)
+		{
+			LL_DEBUGS("LLProcess") << "listening on \"mainloop\"" << LL_ENDL;
+			mConnection = LLEventPumps::instance().obtain("mainloop")
+				.listen("LLProcessListener", boost::bind(&LLProcessListener::tick, this, _1));
+		}
+	}
+
+	void dropPoll(const LLProcess&)
+	{
+		// Unconditionally decrement mCount. If it's zero after decrementing,
+		// stop listening on "mainloop".
+		if (--mCount == 0)
+		{
+			LL_DEBUGS("LLProcess") << "disconnecting from \"mainloop\"" << LL_ENDL;
+			mConnection.disconnect();
+		}
+	}
+
+private:
+	/// called once per frame by the "mainloop" LLEventPump
+	bool tick(const LLSD&)
+	{
+		// Tell APR to sense whether each registered LLProcess is still
+		// running and call handle_status() appropriately. We should be able
+		// to get the same info from an apr_proc_wait(APR_NOWAIT) call; but at
+		// least in APR 1.4.2, testing suggests that even with APR_NOWAIT,
+		// apr_proc_wait() blocks the caller. We can't have that in the
+		// viewer. Hence the callback rigmarole. (Once we update APR, it's
+		// probably worth testing again.) Also -- although there's an
+		// apr_proc_other_child_refresh() call, i.e. get that information for
+		// one specific child, it accepts an 'apr_other_child_rec_t*' that's
+		// mentioned NOWHERE else in the documentation or header files! I
+		// would use the specific call in LLProcess::getStatus() if I knew
+		// how. As it is, each call to apr_proc_other_child_refresh_all() will
+		// call callbacks for ALL still-running child processes. That's why we
+		// centralize such calls, using "mainloop" to ensure it happens once
+		// per frame, and refcounting running LLProcess objects to remain
+		// registered only while needed.
+		LL_DEBUGS("LLProcess") << "calling apr_proc_other_child_refresh_all()" << LL_ENDL;
+		apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
+		return false;
+	}
+
+	/// If this object is destroyed before mCount goes to zero, stop
+	/// listening on "mainloop" anyway.
+	LLTempBoundListener mConnection;
+	unsigned mCount;
+};
+static LLProcessListener sProcessListener;
+
 LLProcessPtr LLProcess::create(const LLSDOrParams& params)
 {
 	try
@@ -159,6 +229,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 	// arrange to call status_callback()
 	apr_proc_other_child_register(&mProcess, &LLProcess::status_callback, this, mProcess.in,
 								  gAPRPoolp);
+	// and make sure we poll it once per "mainloop" tick
+	sProcessListener.addPoll(*this);
 	mStatus.mState = RUNNING;
 
 	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << mProcess.pid << ')');
@@ -195,6 +267,8 @@ LLProcess::~LLProcess()
 		// information updated in this object by such a callback is no longer
 		// available to any consumer anyway.
 		apr_proc_other_child_unregister(this);
+		// One less LLProcess to poll for
+		sProcessListener.dropPoll(*this);
 	}
 
 	if (mAutokill)
@@ -228,26 +302,6 @@ bool LLProcess::isRunning(void)
 
 LLProcess::Status LLProcess::getStatus()
 {
-	// Only when mState is RUNNING might the status change dynamically. For
-	// any other value, pointless to attempt to update status: it won't
-	// change.
-	if (mStatus.mState == RUNNING)
-	{
-		// Tell APR to sense whether the child is still running and call
-		// handle_status() appropriately. We should be able to get the same
-		// info from an apr_proc_wait(APR_NOWAIT) call; but at least in APR
-		// 1.4.2, testing suggests that even with APR_NOWAIT, apr_proc_wait()
-		// blocks the caller. We can't have that in the viewer. Hence the
-		// callback rigmarole. Once we update APR, it's probably worth testing
-		// again. Also -- although there's an apr_proc_other_child_refresh()
-		// call, i.e. get that information for one specific child, it accepts
-		// an 'apr_other_child_rec_t*' that's mentioned NOWHERE else in the
-		// documentation or header files! I would use the specific call if I
-		// knew how. As it is, each call to this method will call callbacks
-		// for ALL still-running child processes. Sigh...
-		apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
-	}
-
 	return mStatus;
 }
 
@@ -341,6 +395,8 @@ void LLProcess::handle_status(int reason, int status)
 	// it already knows the child has terminated. We must pass the same 'data'
 	// pointer as for the register() call, which was our 'this'.
 	apr_proc_other_child_unregister(this);
+	// don't keep polling for a terminated process
+	sProcessListener.dropPoll(*this);
 	// We overload mStatus.mState to indicate whether the child is registered
 	// for APR callback: only RUNNING means registered. Track that we've
 	// unregistered. We know the child has terminated; might be EXITED or
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 0de033c15b..b95ae55701 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -49,9 +49,17 @@ class LLProcess;
 typedef boost::shared_ptr<LLProcess> LLProcessPtr;
 
 /**
- *	LLProcess handles launching external processes with specified command line arguments.
- *	It also keeps track of whether the process is still running, and can kill it if required.
-*/
+ * LLProcess handles launching an external process with specified command line
+ * arguments. It also keeps track of whether the process is still running, and
+ * can kill it if required.
+ *
+ * LLProcess relies on periodic post() calls on the "mainloop" LLEventPump: an
+ * LLProcess object's Status won't update until the next "mainloop" tick. The
+ * viewer's main loop already posts to that LLEventPump once per iteration
+ * (hence the name). See indra/llcommon/tests/llprocess_test.cpp for an
+ * example of waiting for child-process termination in a standalone test
+ * context.
+ */
 class LL_COMMON_API LLProcess: public boost::noncopyable
 {
 	LOG_CLASS(LLProcess);
@@ -72,11 +80,7 @@ public:
 		 * zero or more additional command-line arguments. Arguments are
 		 * passed through as exactly as we can manage, whitespace and all.
 		 * @note On Windows we manage this by implicitly double-quoting each
-		 * argument while assembling the command line. BUT if a given argument
-		 * is already double-quoted, we don't double-quote it again. Try to
-		 * avoid making use of this, though, as on Mac and Linux explicitly
-		 * double-quoted args will be passed to the child process including
-		 * the double quotes.
+		 * argument while assembling the command line.
 		 */
 		Multiple<std::string> args;
 		/// current working directory, if need it changed
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 711715e373..8c21be196b 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -33,6 +33,7 @@
 #include "../test/namedtempfile.h"
 #include "stringize.h"
 #include "llsdutil.h"
+#include "llevents.h"
 
 #if defined(LL_WINDOWS)
 #define sleep(secs) _sleep((secs) * 1000)
@@ -88,6 +89,27 @@ static std::string readfile(const std::string& pathname, const std::string& desc
     return output;
 }
 
+/// Looping on LLProcess::isRunning() must now be accompanied by pumping
+/// "mainloop" -- otherwise the status won't update and you get an infinite
+/// loop.
+void waitfor(LLProcess& proc)
+{
+    while (proc.isRunning())
+    {
+        sleep(1);
+        LLEventPumps::instance().obtain("mainloop").post(LLSD());
+    }
+}
+
+void waitfor(LLProcess::handle h, const std::string& desc)
+{
+    while (LLProcess::isRunning(h, desc))
+    {
+        sleep(1);
+        LLEventPumps::instance().obtain("mainloop").post(LLSD());
+    }
+}
+
 /**
  * Construct an LLProcess to run a Python script.
  */
@@ -120,10 +142,7 @@ struct PythonProcessLauncher
         // there's no API to wait for the child to terminate -- but given
         // its use in our graphics-intensive interactive viewer, it's
         // understandable.
-        while (mPy->isRunning())
-        {
-            sleep(1);
-        }
+        waitfor(*mPy);
     }
 
     /**
@@ -619,10 +638,7 @@ namespace tut
         // script has performed its first write and should now be sleeping.
         py.mPy->kill();
         // wait for the script to terminate... one way or another.
-        while (py.mPy->isRunning())
-        {
-            sleep(1);
-        }
+        waitfor(*py.mPy);
 #if LL_WINDOWS
         ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED);
         ensure_equals("Status.mData",  py.mPy->getStatus().mData,  -1);
@@ -672,10 +688,7 @@ namespace tut
             // Destroy the LLProcess, which should kill the child.
         }
         // wait for the script to terminate... one way or another.
-        while (LLProcess::isRunning(phandle, "kill() script"))
-        {
-            sleep(1);
-        }
+        waitfor(phandle, "kill() script");
         // If kill() failed, the script would have woken up on its own and
         // overwritten the file with 'bad'. But if kill() succeeded, it should
         // not have had that chance.
@@ -737,10 +750,7 @@ namespace tut
             outf << "go";
         } // flush and close.
         // now wait for the script to terminate... one way or another.
-        while (LLProcess::isRunning(phandle, "autokill script"))
-        {
-            sleep(1);
-        }
+        waitfor(phandle, "autokill script");
         // If the LLProcess destructor implicitly called kill(), the
         // script could not have written 'ack' as we expect.
         ensure_equals("autokill script output", readfile(from.getName()), "ack");
-- 
cgit v1.2.3


From e239cad1f509e3d96011acb61614f2481c46af38 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 15 Feb 2012 10:07:09 -0500
Subject: Preliminary pipe support for LLProcess. Add LLProcess::FileParam to
 specify how to construct each child's standard file slot, with lots of
 comments about features designed but not yet implemented. The point is to
 design it with enough flexibility to be able to extend to foreseeable use
 cases. Add LLProcess::Params::files to collect up to 3 FileParam items.
 Naturally this extends the accepted LLSD syntax as well. Implement type=""
 (child inherits parent file descriptor) and "pipe" (parent constructs
 anonymous pipe to pass to child). Add LLProcess::FILESLOT enum, plus methods:
 getReadPipe(FILESLOT), getOptReadPipe(FILESLOT) getWritePipe(),
 getOptWritePipe() getPipeName(FILESLOT): placeholder implementation for now
 Add LLProcess::ReadPipe and WritePipe classes, as returned by get*Pipe().
 WritePipe supports get_ostream() method for streaming to child stdin.
 ReadPipe supports get_istream() method for reading from child stdout/stderr.
 It also provides getPump() returning LLEventPump& so interested parties can
 listen for arrival of new data on the aforementioned std::istream. For "pipe"
 slots, instantiate appropriate *Pipe class. ReadPipe and WritePipe classes
 are pure virtual bases for ReadPipeImpl and WritePipeImpl, respectively: all
 implementation data are hidden in the latter classes, visible only in
 llprocess.cpp. In fact each *PipeImpl class registers itself for "mainloop"
 ticks, attempting nonblocking I/O to the underlying apr_file_t on each tick.
 Data are buffered in a boost::asio::streambuf, which bridges between
 std::[io]stream and the APR I/O calls. Sanity-test ReadPipeImpl by using a
 pipe to absorb the Python "SyntaxError" output from the successful
 syntax_error test, rather than alarming the user. Add first few unit tests
 for validating FileParam. More tests coming!

---
 indra/llcommon/llprocess.cpp            | 321 ++++++++++++++++++++++++++++++--
 indra/llcommon/llprocess.h              | 235 ++++++++++++++++++++++-
 indra/llcommon/tests/llprocess_test.cpp | 171 ++++++++++++++++-
 3 files changed, 695 insertions(+), 32 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index b13e8eb8e0..55eb7e69d3 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -26,6 +26,7 @@
 
 #include "linden_common.h"
 #include "llprocess.h"
+#include "llsdutil.h"
 #include "llsdserialize.h"
 #include "llsingleton.h"
 #include "llstring.h"
@@ -36,19 +37,20 @@
 
 #include <boost/foreach.hpp>
 #include <boost/bind.hpp>
+#include <boost/asio/streambuf.hpp>
+#include <boost/asio/buffers_iterator.hpp>
 #include <iostream>
 #include <stdexcept>
+#include <limits>
+#include <algorithm>
+#include <vector>
+#include <typeinfo>
+#include <utility>
 
+static const char* whichfile[] = { "stdin", "stdout", "stderr" };
 static std::string empty;
 static LLProcess::Status interpret_status(int status);
 
-/// Need an exception to avoid constructing an invalid LLProcess object, but
-/// internal use only
-struct LLProcessError: public std::runtime_error
-{
-	LLProcessError(const std::string& msg): std::runtime_error(msg) {}
-};
-
 /**
  * Ref-counted "mainloop" listener. As long as there are still outstanding
  * LLProcess objects, keep listening on "mainloop" so we can keep polling APR
@@ -117,6 +119,154 @@ private:
 };
 static LLProcessListener sProcessListener;
 
+LLProcess::BasePipe::~BasePipe() {}
+
+class WritePipeImpl: public LLProcess::WritePipe
+{
+public:
+	WritePipeImpl(const std::string& desc, apr_file_t* pipe):
+		mDesc(desc),
+		mPipe(pipe),
+		// Essential to initialize our std::ostream with our special streambuf!
+		mStream(&mStreambuf)
+	{
+		mConnection = LLEventPumps::instance().obtain("mainloop")
+			.listen(LLEventPump::inventName("WritePipe"),
+					boost::bind(&WritePipeImpl::tick, this, _1));
+	}
+
+	virtual std::ostream& get_ostream() { return mStream; }
+
+	bool tick(const LLSD&)
+	{
+		// If there's anything to send, try to send it.
+		if (mStreambuf.size())
+		{
+			// Copy data out from mStreambuf to a flat, contiguous buffer to
+			// write -- but only up to a certain size.
+			std::streamsize total(mStreambuf.size());
+			std::streamsize bufsize((std::min)(4096, total));
+			boost::asio::streambuf::const_buffers_type bufs = mStreambuf.data();
+			std::vector<char> buffer(
+				boost::asio::buffers_begin(bufs),
+				boost::asio::buffers_begin(bufs) + bufsize);
+			apr_size_t written(bufsize);
+			ll_apr_warn_status(apr_file_write(mPipe, &buffer[0], &written));
+			// 'written' is modified to reflect the number of bytes actually
+			// written. Since they've been sent, remove them from the
+			// streambuf so we don't keep trying to send them. This could be
+			// anywhere from 0 up to mStreambuf.size(); anything we haven't
+			// yet sent, we'll try again next tick() call.
+			mStreambuf.consume(written);
+			LL_DEBUGS("LLProcess") << "wrote " << written << " of " << bufsize
+								   << " bytes to " << mDesc
+								   << " (original " << total << "), "
+								   << mStreambuf.size() << " remaining" << LL_ENDL;
+		}
+		return false;
+	}
+
+private:
+	std::string mDesc;
+	apr_file_t* mPipe;
+	LLTempBoundListener mConnection;
+	boost::asio::streambuf mStreambuf;
+	std::ostream mStream;
+};
+
+class ReadPipeImpl: public LLProcess::ReadPipe
+{
+public:
+	ReadPipeImpl(const std::string& desc, apr_file_t* pipe):
+		mDesc(desc),
+		mPipe(pipe),
+		// Essential to initialize our std::istream with our special streambuf!
+		mStream(&mStreambuf),
+		mPump("ReadPipe"),
+		// use funky syntax to call max() to avoid blighted max() macros
+		mLimit((std::numeric_limits<size_t>::max)())
+	{
+		mConnection = LLEventPumps::instance().obtain("mainloop")
+			.listen(LLEventPump::inventName("ReadPipe"),
+					boost::bind(&ReadPipeImpl::tick, this, _1));
+	}
+
+	// Much of the implementation is simply connecting the abstract virtual
+	// methods with implementation data concealed from the base class.
+	virtual std::istream& get_istream() { return mStream; }
+	virtual LLEventPump& getPump() { return mPump; }
+	virtual void setLimit(size_t limit) { mLimit = limit; }
+	virtual size_t getLimit() const { return mLimit; }
+
+private:
+	bool tick(const LLSD&)
+	{
+		// Allocate a buffer and try, every time, to read into it.
+		std::vector<char> buffer(4096);
+		apr_size_t gotten(buffer.size());
+		apr_status_t err = apr_file_read(mPipe, &buffer[0], &gotten);
+		if (err == APR_EOF)
+		{
+			// Handle EOF specially: it's part of normal-case processing.
+			LL_DEBUGS("LLProcess") << "EOF on " << mDesc << LL_ENDL;
+			// We won't need any more tick() calls.
+			mConnection.disconnect();
+		}
+		else if (! ll_apr_warn_status(err)) // validate anything but EOF
+		{
+			// 'gotten' was modified to reflect the number of bytes actually
+			// received. If nonzero, add them to the streambuf and notify
+			// interested parties.
+			if (gotten)
+			{
+				boost::asio::streambuf::mutable_buffers_type mbufs = mStreambuf.prepare(gotten);
+				std::copy(buffer.begin(), buffer.begin() + gotten,
+						  boost::asio::buffers_begin(mbufs));
+				// Don't forget to "commit" the data! The sequence (prepare(),
+				// commit()) is obviously intended to allow us to allocate
+				// buffer space, then read directly into some portion of it,
+				// then commit only as much as we managed to obtain. But the
+				// only official (documented) way I can find to populate a
+				// mutable_buffers_type is to use buffers_begin(). It Would Be
+				// Nice if we were permitted to directly read into
+				// mutable_buffers_type (not to mention writing directly from
+				// const_buffers_type in WritePipeImpl; APR even supports an
+				// apr_file_writev() function for writing from discontiguous
+				// buffers) -- but as of 2012-02-14, this copying appears to
+				// be the safest tactic.
+				mStreambuf.commit(gotten);
+				LL_DEBUGS("LLProcess") << "read " << gotten << " of " << buffer.size()
+									   << " bytes from " << mDesc << ", new total "
+									   << mStreambuf.size() << LL_ENDL;
+
+				// Now that we've received new data, publish it on our
+				// LLEventPump as advertised. Constrain it by mLimit.
+				std::streamsize datasize((std::min)(mLimit, mStreambuf.size()));
+				boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
+				mPump.post(LLSDMap("data", LLSD::String(
+									   boost::asio::buffers_begin(cbufs),
+									   boost::asio::buffers_begin(cbufs) + datasize)));
+			}
+		}
+		return false;
+	}
+
+	std::string mDesc;
+	apr_file_t* mPipe;
+	LLTempBoundListener mConnection;
+	boost::asio::streambuf mStreambuf;
+	std::istream mStream;
+	LLEventStream mPump;
+	size_t mLimit;
+};
+
+/// Need an exception to avoid constructing an invalid LLProcess object, but
+/// internal use only
+struct LLProcessError: public std::runtime_error
+{
+	LLProcessError(const std::string& msg): std::runtime_error(msg) {}
+};
+
 LLProcessPtr LLProcess::create(const LLSDOrParams& params)
 {
 	try
@@ -134,12 +284,23 @@ LLProcessPtr LLProcess::create(const LLSDOrParams& params)
 /// throw LLProcessError mentioning the function call that produced that
 /// result.
 #define chkapr(func)                            \
-    if (ll_apr_warn_status(func))               \
-        throw LLProcessError(#func " failed")
+	if (ll_apr_warn_status(func))				\
+		throw LLProcessError(#func " failed")
 
 LLProcess::LLProcess(const LLSDOrParams& params):
-	mAutokill(params.autokill)
+	mAutokill(params.autokill),
+	mPipes(NSLOTS)
 {
+	// Hmm, when you construct a ptr_vector with a size, it merely reserves
+	// space, it doesn't actually make it that big. Explicitly make it bigger.
+	// Because of ptr_vector's odd semantics, have to push_back(0) the right
+	// number of times! resize() wants to default-construct new BasePipe
+	// instances, which fails because it's pure virtual. But because of the
+	// constructor call, these push_back() calls should require no new
+	// allocation.
+	for (size_t i = 0; i < mPipes.capacity(); ++i)
+		mPipes.push_back(0);
+
 	if (! params.validateBlock(true))
 	{
 		throw LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
@@ -154,16 +315,46 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 	// apr_procattr_io_set() alternatives: inherit the viewer's own stdxxx
 	// handle (APR_NO_PIPE, e.g. for stdout, stderr), or create a pipe that's
 	// blocking on the child end but nonblocking at the viewer end
-	// (APR_CHILD_BLOCK). The viewer can't block for anything: the parent end
-	// MUST be nonblocking. As the APR documentation itself points out, it
-	// makes very little sense to set nonblocking I/O for the child end of a
-	// pipe: only a specially-written child could deal with that.
+	// (APR_CHILD_BLOCK).
 	// Other major options could include explicitly creating a single APR pipe
 	// and passing it as both stdout and stderr (apr_procattr_child_out_set(),
 	// apr_procattr_child_err_set()), or accepting a filename, opening it and
 	// passing that apr_file_t (simple <, >, 2> redirect emulation).
-//	chkapr(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK));
-	chkapr(apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE, APR_NO_PIPE));
+	std::vector<FileParam> fparams(params.files.begin(), params.files.end());
+	// By default, pass APR_NO_PIPE for each slot.
+	std::vector<apr_int32_t> select(LL_ARRAY_SIZE(whichfile), APR_NO_PIPE);
+	for (size_t i = 0; i < (std::min)(LL_ARRAY_SIZE(whichfile), fparams.size()); ++i)
+	{
+		if (std::string(fparams[i].type).empty()) // inherit our file descriptor
+		{
+			select[i] = APR_NO_PIPE;
+		}
+		else if (std::string(fparams[i].type) == "pipe") // anonymous pipe
+		{
+			if (! std::string(fparams[i].name).empty())
+			{
+				LL_WARNS("LLProcess") << "For " << std::string(params.executable)
+									  << ": internal names for reusing pipes ('"
+									  << std::string(fparams[i].name) << "' for " << whichfile[i]
+									  << ") are not yet supported -- creating distinct pipe"
+									  << LL_ENDL;
+			}
+			// The viewer can't block for anything: the parent end MUST be
+			// nonblocking. As the APR documentation itself points out, it
+			// makes very little sense to set nonblocking I/O for the child
+			// end of a pipe: only a specially-written child could deal with
+			// that.
+			select[i] = APR_CHILD_BLOCK;
+		}
+		else
+		{
+			throw LLProcessError(STRINGIZE("For " << std::string(params.executable)
+										   << ": unsupported FileParam for " << whichfile[i]
+										   << ": type='" << std::string(fparams[i].type)
+										   << "', name='" << std::string(fparams[i].name) << "'"));
+		}
+	}
+	chkapr(apr_procattr_io_set(procattr, select[STDIN], select[STDOUT], select[STDERR]));
 
 	// Thumbs down on implicitly invoking the shell to invoke the child. From
 	// our point of view, the other major alternative to APR_PROGRAM_PATH
@@ -251,6 +442,27 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 		// On Windows, associate the new child process with our Job Object.
 		autokill();
 	}
+
+	// Instantiate the proper pipe I/O machinery
+	// want to be able to point to apr_proc_t::in, out, err by index
+	typedef apr_file_t* apr_proc_t::*apr_proc_file_ptr;
+	static apr_proc_file_ptr members[] =
+		{ &apr_proc_t::in, &apr_proc_t::out, &apr_proc_t::err };
+	for (size_t i = 0; i < NSLOTS; ++i)
+	{
+		if (select[i] != APR_CHILD_BLOCK)
+			continue;
+		if (i == STDIN)
+		{
+			mPipes.replace(i, new WritePipeImpl(whichfile[i], mProcess.*(members[i])));
+		}
+		else
+		{
+			mPipes.replace(i, new ReadPipeImpl(whichfile[i], mProcess.*(members[i])));
+		}
+		LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name()
+							   << "('" << whichfile[i] << "')" << LL_ENDL;
+	}
 }
 
 LLProcess::~LLProcess()
@@ -428,6 +640,83 @@ LLProcess::handle LLProcess::getProcessHandle() const
 #endif
 }
 
+std::string LLProcess::getPipeName(FILESLOT)
+{
+	// LLProcess::FileParam::type "npipe" is not yet implemented
+	return "";
+}
+
+template<class PIPETYPE>
+PIPETYPE* LLProcess::getPipePtr(std::string& error, FILESLOT slot)
+{
+    if (slot >= NSLOTS)
+    {
+        error = STRINGIZE(mDesc << " has no slot " << slot);
+        return NULL;
+    }
+    if (mPipes.is_null(slot))
+    {
+        error = STRINGIZE(mDesc << ' ' << whichfile[slot] << " not a monitored pipe");
+        return NULL;
+    }
+    // Make sure we dynamic_cast in pointer domain so we can test, rather than
+    // accepting runtime's exception.
+    PIPETYPE* ppipe = dynamic_cast<PIPETYPE*>(&mPipes[slot]);
+    if (! ppipe)
+    {
+        error = STRINGIZE(mDesc << ' ' << whichfile[slot] << " not a " << typeid(PIPETYPE).name());
+        return NULL;
+    }
+
+    error.clear();
+    return ppipe;
+}
+
+template <class PIPETYPE>
+PIPETYPE& LLProcess::getPipe(FILESLOT slot)
+{
+    std::string error;
+    PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
+    if (! wp)
+    {
+        throw NoPipe(error);
+    }
+    return *wp;
+}
+
+template <class PIPETYPE>
+boost::optional<PIPETYPE&> LLProcess::getOptPipe(FILESLOT slot)
+{
+    std::string error;
+    PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
+    if (! wp)
+    {
+        LL_DEBUGS("LLProcess") << error << LL_ENDL;
+        return boost::optional<PIPETYPE&>();
+    }
+    return *wp;
+}
+
+LLProcess::WritePipe& LLProcess::getWritePipe(FILESLOT slot)
+{
+    return getPipe<WritePipe>(slot);
+}
+
+boost::optional<LLProcess::WritePipe&> LLProcess::getOptWritePipe(FILESLOT slot)
+{
+    return getOptPipe<WritePipe>(slot);
+}
+
+LLProcess::ReadPipe& LLProcess::getReadPipe(FILESLOT slot)
+{
+    return getPipe<ReadPipe>(slot);
+}
+
+boost::optional<LLProcess::ReadPipe&> LLProcess::getOptReadPipe(FILESLOT slot)
+{
+    return getOptPipe<ReadPipe>(slot);
+}
+
 std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
 {
 	std::string cwd(params.cwd);
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index b95ae55701..448a88f4c0 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -31,8 +31,11 @@
 #include "llsdparam.h"
 #include "apr_thread_proc.h"
 #include <boost/shared_ptr.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/optional.hpp>
 #include <boost/noncopyable.hpp>
 #include <iosfwd>                   // std::ostream
+#include <stdexcept>
 
 #if LL_WINDOWS
 #define WIN32_LEAN_AND_MEAN
@@ -43,6 +46,8 @@
 #endif
 #endif
 
+class LLEventPump;
+
 class LLProcess;
 /// LLProcess instances are created on the heap by static factory methods and
 /// managed by ref-counted pointers.
@@ -64,6 +69,87 @@ class LL_COMMON_API LLProcess: public boost::noncopyable
 {
 	LOG_CLASS(LLProcess);
 public:
+	/**
+	 * Specify what to pass for each of child stdin, stdout, stderr.
+	 * @see LLProcess::Params::files.
+	 */
+	struct FileParam: public LLInitParam::Block<FileParam>
+	{
+		/**
+		 * type of file handle to pass to child process
+		 *
+		 * - "" (default): let the child inherit the same file handle used by
+		 *   this process. For instance, if passed as stdout, child stdout
+		 *   will be interleaved with stdout from this process. In this case,
+		 *   @a name is moot and should be left "".
+		 *
+		 * - "file": open an OS filesystem file with the specified @a name.
+		 *   <i>Not yet implemented.</i>
+		 *
+		 * - "pipe" or "tpipe" or "npipe": depends on @a name
+		 *
+		 *   - @a name.empty(): construct an OS pipe used only for this slot
+		 *     of the forthcoming child process.
+		 *
+		 *   - ! @a name.empty(): in a global registry, find or create (using
+		 *     the specified @a name) an OS pipe. The point of the (purely
+		 *     internal) @a name is that passing the same @a name in more than
+		 *     one slot for a given LLProcess -- or for slots in different
+		 *     LLProcess instances -- means the same pipe. For example, you
+		 *     might pass the same @a name value as both stdout and stderr to
+		 *     make the child process produce both on the same actual pipe. Or
+		 *     you might pass the same @a name as the stdout for one LLProcess
+		 *     and the stdin for another to connect the two child processes.
+		 *     Use LLProcess::getPipeName() to generate a unique name
+		 *     guaranteed not to already exist in the registry. <i>Not yet
+		 *     implemented.</i>
+		 *
+		 *   The difference between "pipe", "tpipe" and "npipe" is as follows.
+		 *
+		 *   - "pipe": direct LLProcess to monitor the parent end of the pipe,
+		 *     pumping nonblocking I/O every frame. The expectation (at least
+		 *     for stdout or stderr) is that the caller will listen for
+		 *     incoming data and consume it as it arrives. It's important not
+		 *     to neglect such a pipe, because it's buffered in viewer memory.
+		 *     If you suspect the child may produce a great volume of output
+		 *     between viewer frames, consider directing the child to write to
+		 *     a filesystem file instead, then read the file later.
+		 *
+		 *   - "tpipe": do not engage LLProcess machinery to monitor the
+		 *     parent end of the pipe. A "tpipe" is used only to connect
+		 *     different child processes. As such, it makes little sense to
+		 *     pass an empty @a name. <i>Not yet implemented.</i>
+		 *
+		 *   - "npipe": like "tpipe", but use an OS named pipe with a
+		 *     generated name. Note that @a name is the @em internal name of
+		 *     the pipe in our global registry -- it doesn't necessarily have
+		 *     anything to do with the pipe's name in the OS filesystem. Use
+		 *     LLProcess::getPipeName() to obtain the named pipe's OS
+		 *     filesystem name, e.g. to pass it as the @a name to another
+		 *     LLProcess instance using @a type "file". This supports usage
+		 *     like bash's &lt;(subcommand...) or &gt;(subcommand...)
+		 *     constructs. <i>Not yet implemented.</i>
+		 *
+		 * In all cases the open mode (read, write) is determined by the child
+		 * slot you're filling. Child stdin means select the "read" end of a
+		 * pipe, or open a filesystem file for reading; child stdout or stderr
+		 * means select the "write" end of a pipe, or open a filesystem file
+		 * for writing.
+		 *
+		 * Confusion such as passing the same pipe as the stdin of two
+		 * processes (rather than stdout for one and stdin for the other) is
+		 * explicitly permitted: it's up to the caller to construct meaningful
+		 * LLProcess pipe graphs.
+		 */
+		Optional<std::string> type;
+		Optional<std::string> name;
+
+		FileParam(const std::string& tp="", const std::string& nm=""):
+			type("type", tp),
+			name("name", nm)
+		{}
+	};
+
 	/// Param block definition
 	struct Params: public LLInitParam::Block<Params>
 	{
@@ -71,7 +157,8 @@ public:
 			executable("executable"),
 			args("args"),
 			cwd("cwd"),
-			autokill("autokill", true)
+			autokill("autokill", true),
+			files("files")
 		{}
 
 		/// pathname of executable
@@ -87,19 +174,22 @@ public:
 		Optional<std::string> cwd;
 		/// implicitly kill process on destruction of LLProcess object
 		Optional<bool> autokill;
+		/**
+		 * Up to three FileParam items: for child stdin, stdout, stderr.
+		 * Passing two FileParam entries means default treatment for stderr,
+		 * and so forth.
+		 *
+		 * @note While it's theoretically plausible to pass additional open
+		 * file handles to a child specifically written to expect them, our
+		 * underlying implementation library doesn't support that.
+		 */
+		Multiple<FileParam> files;
 	};
 	typedef LLSDParamAdapter<Params> LLSDOrParams;
 
 	/**
 	 * Factory accepting either plain LLSD::Map or Params block.
 	 * MAY RETURN DEFAULT-CONSTRUCTED LLProcessPtr if params invalid!
-	 *
-	 * Redundant with Params definition above?
-	 *
-	 * executable (required, string):				executable pathname
-	 * args		  (optional, string array):			extra command-line arguments
-	 * cwd		  (optional, string, dft no chdir): change to this directory before executing
-	 * autokill	  (optional, bool, dft true):		implicit kill() on ~LLProcess
 	 */
 	static LLProcessPtr create(const LLSDOrParams& params);
 	virtual ~LLProcess();
@@ -190,6 +280,125 @@ public:
 	 */
 	static handle isRunning(handle, const std::string& desc="");
 
+	/// Provide symbolic access to child's file slots
+	enum FILESLOT { STDIN=0, STDOUT=1, STDERR=2, NSLOTS=3 };
+
+	/**
+	 * For a pipe constructed with @a type "npipe", obtain the generated OS
+	 * filesystem name for the specified pipe. Otherwise returns the empty
+	 * string. @see LLProcess::FileParam::type
+	 */
+	std::string getPipeName(FILESLOT);
+
+	/// base of ReadPipe, WritePipe
+	class BasePipe
+	{
+	public:
+		virtual ~BasePipe() = 0;
+	};
+
+	/// As returned by getWritePipe() or getOptWritePipe()
+	class WritePipe: public BasePipe
+	{
+	public:
+		/**
+		 * Get ostream& on which to write to child's stdin.
+		 *
+		 * @usage
+		 * @code
+		 * myProcess->getWritePipe().get_ostream() << "Hello, child!" << std::endl;
+		 * @endcode
+		 */
+		virtual std::ostream& get_ostream() = 0;
+	};
+
+	/// As returned by getReadPipe() or getOptReadPipe()
+	class ReadPipe: public BasePipe
+	{
+	public:
+		/**
+		 * Get istream& on which to read from child's stdout or stderr.
+		 *
+		 * @usage
+		 * @code
+		 * std::string stuff;
+		 * myProcess->getReadPipe().get_istream() >> stuff;
+		 * @endcode
+		 *
+		 * You should be sure in advance that the ReadPipe in question can
+		 * fill the request. @see getPump()
+		 */
+		virtual std::istream& get_istream() = 0;
+
+		/**
+		 * Get LLEventPump& on which to listen for incoming data. The posted
+		 * LLSD::Map event will contain a key "data" whose value is an
+		 * LLSD::String containing (part of) the data accumulated in the
+		 * buffer.
+		 *
+		 * If the child sends "abc", and this ReadPipe posts "data"="abc", but
+		 * you don't consume it by reading the std::istream returned by
+		 * get_istream(), and the child next sends "def", ReadPipe will post
+		 * "data"="abcdef".
+		 */
+		virtual LLEventPump& getPump() = 0;
+
+		/**
+		 * Set maximum length of buffer data that will be posted in the LLSD
+		 * announcing arrival of new data from the child. If you call
+		 * setLimit(5), and the child sends "abcdef", the LLSD event will
+		 * contain "data"="abcde". However, you may still read the entire
+		 * "abcdef" from get_istream(): this limit affects only the size of
+		 * the data posted with the LLSD event. If you don't call this method,
+		 * all pending data will be posted.
+		 */
+		virtual void setLimit(size_t limit) = 0;
+
+		/**
+		 * Query the current setLimit() limit.
+		 */
+		virtual size_t getLimit() const = 0;
+	};
+
+	/// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to
+	/// create a pipe at the corresponding FILESLOT.
+	struct NoPipe: public std::runtime_error
+	{
+		NoPipe(const std::string& what): std::runtime_error(what) {}
+	};
+
+	/**
+	 * Get a reference to the (only) WritePipe for this LLProcess. @a slot, if
+	 * specified, must be STDIN. Throws NoPipe if you did not request a "pipe"
+	 * for child stdin. Use this method when you know how you created the
+	 * LLProcess in hand.
+	 */
+	WritePipe& getWritePipe(FILESLOT slot=STDIN);
+
+	/**
+	 * Get a boost::optional<WritePipe&> to the (only) WritePipe for this
+	 * LLProcess. @a slot, if specified, must be STDIN. The return value is
+	 * empty if you did not request a "pipe" for child stdin. Use this method
+	 * for inspecting an LLProcess you did not create.
+	 */
+	boost::optional<WritePipe&> getOptWritePipe(FILESLOT slot=STDIN);
+
+	/**
+	 * Get a reference to one of the ReadPipes for this LLProcess. @a slot, if
+	 * specified, must be STDOUT or STDERR. Throws NoPipe if you did not
+	 * request a "pipe" for child stdout or stderr. Use this method when you
+	 * know how you created the LLProcess in hand.
+	 */
+	ReadPipe& getReadPipe(FILESLOT slot);
+
+	/**
+	 * Get a boost::optional<ReadPipe&> to one of the ReadPipes for this
+	 * LLProcess. @a slot, if specified, must be STDOUT or STDERR. The return
+	 * value is empty if you did not request a "pipe" for child stdout or
+	 * stderr. Use this method for inspecting an LLProcess you did not create.
+	 */
+	boost::optional<ReadPipe&> getOptReadPipe(FILESLOT slot);
+
 private:
 	/// constructor is private: use create() instead
 	LLProcess(const LLSDOrParams& params);
@@ -198,11 +407,21 @@ private:
 	static void status_callback(int reason, void* data, int status);
 	// Object-oriented callback
 	void handle_status(int reason, int status);
+	// implementation for get[Opt][Read|Write]Pipe()
+	template <class PIPETYPE>
+	PIPETYPE& getPipe(FILESLOT slot);
+	template <class PIPETYPE>
+	boost::optional<PIPETYPE&> getOptPipe(FILESLOT slot);
+	template <class PIPETYPE>
+	PIPETYPE* getPipePtr(std::string& error, FILESLOT slot);
 
 	std::string mDesc;
 	apr_proc_t mProcess;
 	bool mAutokill;
 	Status mStatus;
+	// explicitly want this ptr_vector to be able to store NULLs
+	typedef boost::ptr_vector< boost::nullable<BasePipe> > PipeVector;
+	PipeVector mPipes;
 };
 
 /// for logging
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 8c21be196b..d4e9977e63 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -34,6 +34,7 @@
 #include "stringize.h"
 #include "llsdutil.h"
 #include "llevents.h"
+#include "llerrorcontrol.h"
 
 #if defined(LL_WINDOWS)
 #define sleep(secs) _sleep((secs) * 1000)
@@ -92,12 +93,18 @@ static std::string readfile(const std::string& pathname, const std::string& desc
 /// Looping on LLProcess::isRunning() must now be accompanied by pumping
 /// "mainloop" -- otherwise the status won't update and you get an infinite
 /// loop.
+void yield(int seconds=1)
+{
+    // This function simulates waiting for another viewer frame
+    sleep(seconds);
+    LLEventPumps::instance().obtain("mainloop").post(LLSD());
+}
+
 void waitfor(LLProcess& proc)
 {
     while (proc.isRunning())
     {
-        sleep(1);
-        LLEventPumps::instance().obtain("mainloop").post(LLSD());
+        yield();
     }
 }
 
@@ -105,8 +112,7 @@ void waitfor(LLProcess::handle h, const std::string& desc)
 {
     while (LLProcess::isRunning(h, desc))
     {
-        sleep(1);
-        LLEventPumps::instance().obtain("mainloop").post(LLSD());
+        yield();
     }
 }
 
@@ -219,6 +225,68 @@ private:
     std::string mPath;
 };
 
+// statically reference the function in test.cpp... it's short, we could
+// replicate, but better to reuse
+extern void wouldHaveCrashed(const std::string& message);
+
+/**
+ * Capture log messages. This is adapted (simplified) from the one in
+ * llerror_test.cpp. Sigh, should've broken that out into a separate header
+ * file, but time for this project is short...
+ */
+class TestRecorder : public LLError::Recorder
+{
+public:
+    TestRecorder():
+        // Mostly what we're trying to accomplish by saving and resetting
+        // LLError::Settings is to bypass the default RecordToStderr and
+        // RecordToWinDebug Recorders. As these are visible only inside
+        // llerror.cpp, we can't just call LLError::removeRecorder() with
+        // each. For certain tests we need to produce, capture and examine
+        // DEBUG log messages -- but we don't want to spam the user's console
+        // with that output. If it turns out that saveAndResetSettings() has
+        // some bad effect, give up and just let the DEBUG level log messages
+        // display.
+        mOldSettings(LLError::saveAndResetSettings())
+    {
+        LLError::setFatalFunction(wouldHaveCrashed);
+        LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+        LLError::addRecorder(this);
+    }
+
+    ~TestRecorder()
+    {
+        LLError::removeRecorder(this);
+        LLError::restoreSettings(mOldSettings);
+    }
+
+    void recordMessage(LLError::ELevel level,
+                       const std::string& message)
+    {
+        mMessages.push_back(message);
+    }
+
+    /// Don't assume the message we want is necessarily the LAST log message
+    /// emitted by the underlying code; search backwards through all messages
+    /// for the sought string.
+    std::string messageWith(const std::string& search)
+    {
+        for (std::list<std::string>::const_reverse_iterator rmi(mMessages.rbegin()),
+                 rmend(mMessages.rend());
+             rmi != rmend; ++rmi)
+        {
+            if (rmi->find(search) != std::string::npos)
+                return *rmi;
+        }
+        // failed to find any such message
+        return std::string();
+    }
+
+    typedef std::list<std::string> MessageList;
+    MessageList mMessages;
+    LLError::Settings* mOldSettings;
+};
+
 /*****************************************************************************
 *   TUT
 *****************************************************************************/
@@ -602,9 +670,19 @@ namespace tut
         set_test_name("syntax_error:");
         PythonProcessLauncher py("syntax_error:",
                                  "syntax_error:\n");
+        py.mParams.files.add(LLProcess::FileParam()); // inherit stdin
+        py.mParams.files.add(LLProcess::FileParam()); // inherit stdout
+        py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stderr
         py.run();
         ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED);
         ensure_equals("Status.mData",  py.mPy->getStatus().mData,  1);
+        std::istream& rpipe(py.mPy->getReadPipe(LLProcess::STDERR).get_istream());
+        std::vector<char> buffer(4096);
+        rpipe.read(&buffer[0], buffer.size());
+        std::streamsize got(rpipe.gcount());
+        ensure("Nothing read from stderr pipe", got);
+        std::string data(&buffer[0], got);
+        ensure("Didn't find 'SyntaxError:'", data.find("\nSyntaxError:") != std::string::npos);
     }
 
     template<> template<>
@@ -629,7 +707,7 @@ namespace tut
         int i = 0, timeout = 60;
         for ( ; i < timeout; ++i)
         {
-            sleep(1);
+            yield();
             if (readfile(out.getName(), "from kill() script") == "ok")
                 break;
         }
@@ -678,7 +756,7 @@ namespace tut
             int i = 0, timeout = 60;
             for ( ; i < timeout; ++i)
             {
-                sleep(1);
+                yield();
                 if (readfile(out.getName(), "from kill() script") == "ok")
                     break;
             }
@@ -733,7 +811,7 @@ namespace tut
             int i = 0, timeout = 60;
             for ( ; i < timeout; ++i)
             {
-                sleep(1);
+                yield();
                 if (readfile(from.getName(), "from autokill script") == "ok")
                     break;
             }
@@ -742,7 +820,7 @@ namespace tut
             // Now destroy the LLProcess, which should NOT kill the child!
         }
         // If the destructor killed the child anyway, give it time to die
-        sleep(2);
+        yield(2);
         // How do we know it's not terminated? By making it respond to
         // a specific stimulus in a specific way.
         {
@@ -755,4 +833,81 @@ namespace tut
         // script could not have written 'ack' as we expect.
         ensure_equals("autokill script output", readfile(from.getName()), "ack");
     }
+
+    template<> template<>
+    void object::test<10>()
+    {
+        set_test_name("'bogus' test");
+        TestRecorder recorder;
+        PythonProcessLauncher py("'bogus' test",
+                                 "print 'Hello world'\n");
+        py.mParams.files.add(LLProcess::FileParam("bogus"));
+        py.mPy = LLProcess::create(py.mParams);
+        ensure("should have rejected 'bogus'", ! py.mPy);
+        std::string message(recorder.messageWith("bogus"));
+        ensure("did not log 'bogus' type", ! message.empty());
+        ensure_contains("did not name 'stdin'", message, "stdin");
+    }
+
+    template<> template<>
+    void object::test<11>()
+    {
+        set_test_name("'file' test");
+        // Replace this test with one or more real 'file' tests when we
+        // implement 'file' support
+        PythonProcessLauncher py("'file' test",
+                                 "print 'Hello world'\n");
+        py.mParams.files.add(LLProcess::FileParam());
+        py.mParams.files.add(LLProcess::FileParam("file"));
+        py.mPy = LLProcess::create(py.mParams);
+        ensure("should have rejected 'file'", ! py.mPy);
+    }
+
+    template<> template<>
+    void object::test<12>()
+    {
+        set_test_name("'tpipe' test");
+        // Replace this test with one or more real 'tpipe' tests when we
+        // implement 'tpipe' support
+        TestRecorder recorder;
+        PythonProcessLauncher py("'tpipe' test",
+                                 "print 'Hello world'\n");
+        py.mParams.files.add(LLProcess::FileParam());
+        py.mParams.files.add(LLProcess::FileParam("tpipe"));
+        py.mPy = LLProcess::create(py.mParams);
+        ensure("should have rejected 'tpipe'", ! py.mPy);
+        std::string message(recorder.messageWith("tpipe"));
+        ensure("did not log 'tpipe' type", ! message.empty());
+        ensure_contains("did not name 'stdout'", message, "stdout");
+    }
+
+    template<> template<>
+    void object::test<13>()
+    {
+        set_test_name("'npipe' test");
+        // Replace this test with one or more real 'npipe' tests when we
+        // implement 'npipe' support
+        TestRecorder recorder;
+        PythonProcessLauncher py("'npipe' test",
+                                 "print 'Hello world'\n");
+        py.mParams.files.add(LLProcess::FileParam());
+        py.mParams.files.add(LLProcess::FileParam());
+        py.mParams.files.add(LLProcess::FileParam("npipe"));
+        py.mPy = LLProcess::create(py.mParams);
+        ensure("should have rejected 'npipe'", ! py.mPy);
+        std::string message(recorder.messageWith("npipe"));
+        ensure("did not log 'npipe' type", ! message.empty());
+        ensure_contains("did not name 'stderr'", message, "stderr");
+    }
+
+    // TODO:
+    // test "pipe" with nonempty name (should log & continue)
+    // test pipe for just stderr (tests for get[Opt]ReadPipe(), get[Opt]WritePipe())
+    // test pipe for stdin, stdout (etc.)
+    // test getWritePipe().get_ostream(), getReadPipe().get_istream()
+    // test listening on getReadPipe().getPump(), disconnecting
+    // test setLimit(), getLimit()
+    // test EOF -- check logging
+    // test get(Read|Write)Pipe(3), unmonitored slot, getReadPipe(1), getWritePipe(0)
+
 } // namespace tut
-- 
cgit v1.2.3


From c6ccdb5b5088f3ab24bb89d8c56049c7a17a663e Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 15 Feb 2012 12:11:38 -0500
Subject: Add tests for LLProcess::get[Opt][Read|Write]Pipe() validations.

---
 indra/llcommon/tests/llprocess_test.cpp | 90 +++++++++++++++++++++++++++++++--
 1 file changed, 87 insertions(+), 3 deletions(-)

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index d4e9977e63..06f9f3827f 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -900,14 +900,98 @@ namespace tut
         ensure_contains("did not name 'stderr'", message, "stderr");
     }
 
+    template<> template<>
+    void object::test<14>()
+    {
+        set_test_name("internal pipe name warning");
+        TestRecorder recorder;
+        PythonProcessLauncher py("pipe warning",
+                                 "import sys\n"
+                                 "sys.exit(7)\n");
+        py.mParams.files.add(LLProcess::FileParam("pipe", "somename"));
+        py.run();                   // verify that it did launch anyway
+        ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED);
+        ensure_equals("Status.mData",  py.mPy->getStatus().mData,  7);
+        std::string message(recorder.messageWith("not yet supported"));
+        ensure("did not log pipe name warning", ! message.empty());
+        ensure_contains("log message did not mention internal pipe name",
+                        message, "somename");
+    }
+
+#define TEST_getPipe(PROCESS, GETPIPE, GETOPTPIPE, VALID, NOPIPE, BADPIPE) \
+    do                                                                  \
+    {                                                                   \
+        std::string threw;                                              \
+        /* Both the following calls should work. */                     \
+        (PROCESS).GETPIPE(VALID);                                       \
+        ensure(#GETOPTPIPE "(" #VALID ") failed", (PROCESS).GETOPTPIPE(VALID)); \
+        /* pass obviously bogus PIPESLOT */                             \
+        CATCH_IN(threw, LLProcess::NoPipe, (PROCESS).GETPIPE(LLProcess::FILESLOT(4))); \
+        ensure_contains("didn't reject bad slot", threw, "no slot");    \
+        ensure_contains("didn't mention bad slot num", threw, "4");     \
+        EXPECT_FAIL_WITH_LOG(threw, (PROCESS).GETOPTPIPE(LLProcess::FILESLOT(4))); \
+        /* pass NOPIPE */                                               \
+        CATCH_IN(threw, LLProcess::NoPipe, (PROCESS).GETPIPE(NOPIPE));  \
+        ensure_contains("didn't reject non-pipe", threw, "not a monitored"); \
+        EXPECT_FAIL_WITH_LOG(threw, (PROCESS).GETOPTPIPE(NOPIPE));      \
+        /* pass BADPIPE: FILESLOT isn't empty but wrong direction */    \
+        CATCH_IN(threw, LLProcess::NoPipe, (PROCESS).GETPIPE(BADPIPE)); \
+        /* sneaky: GETPIPE is getReadPipe or getWritePipe */            \
+        /* so skip "get" to obtain ReadPipe or WritePipe  :-P  */       \
+        ensure_contains("didn't reject wrong pipe", threw, (#GETPIPE)+3); \
+        EXPECT_FAIL_WITH_LOG(threw, (PROCESS).GETOPTPIPE(BADPIPE));     \
+    } while (0)
+
+/// For expecting exceptions. Execute CODE, catch EXCEPTION, store its what()
+/// in std::string THREW, ensure it's not empty (i.e. EXCEPTION did happen).
+#define CATCH_IN(THREW, EXCEPTION, CODE)                                \
+    do                                                                  \
+    {                                                                   \
+        (THREW).clear();                                                \
+        try                                                             \
+        {                                                               \
+            CODE;                                                       \
+        }                                                               \
+        catch (const EXCEPTION& e)                                      \
+        {                                                               \
+            (THREW) = e.what();                                         \
+        }                                                               \
+        ensure("failed to throw " #EXCEPTION ": " #CODE, ! (THREW).empty()); \
+    } while (0)
+
+#define EXPECT_FAIL_WITH_LOG(EXPECT, CODE)                              \
+    do                                                                  \
+    {                                                                   \
+        TestRecorder recorder;                                          \
+        ensure(#CODE " succeeded", ! (CODE));                           \
+        ensure("wrong log message", ! recorder.messageWith(EXPECT).empty()); \
+    } while (0)
+
+    template<> template<>
+    void object::test<15>()
+    {
+        set_test_name("get*Pipe() validation");
+        PythonProcessLauncher py("just stderr",
+                                 "print 'this output is expected'\n");
+        py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for  stdin
+        py.mParams.files.add(LLProcess::FileParam());       // inherit stdout
+        py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stderr
+        py.run();
+        TEST_getPipe(*py.mPy, getWritePipe, getOptWritePipe,
+                     LLProcess::STDIN,   // VALID
+                     LLProcess::STDOUT,  // NOPIPE
+                     LLProcess::STDERR); // BADPIPE
+        TEST_getPipe(*py.mPy, getReadPipe,  getOptReadPipe,
+                     LLProcess::STDERR,  // VALID
+                     LLProcess::STDOUT,  // NOPIPE
+                     LLProcess::STDIN);  // BADPIPE
+    }
+
     // TODO:
-    // test "pipe" with nonempty name (should log & continue)
-    // test pipe for just stderr (tests for get[Opt]ReadPipe(), get[Opt]WritePipe())
     // test pipe for stdin, stdout (etc.)
     // test getWritePipe().get_ostream(), getReadPipe().get_istream()
     // test listening on getReadPipe().getPump(), disconnecting
     // test setLimit(), getLimit()
     // test EOF -- check logging
-    // test get(Read|Write)Pipe(3), unmonitored slot, getReadPipe(1), getWritePipe(0)
 
 } // namespace tut
-- 
cgit v1.2.3


From 10ab4adc86207f86df30ab23d8858c23e7f550ea Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 15 Feb 2012 13:44:43 -0500
Subject: Fix llprocess_test.cpp's exception catching for Linux. In the course
 of re-enabling the indra/test tests last year, Log generalized a workaround
 I'd introduced in llsdmessage_test.cpp. In Linux viewer land, a test program
 trying to catch an expected exception can't seem to catch it by its specific
 class (across the libllcommon.so boundary), but must instead catch
 std::runtime_error and validate the typeid().name() string. Log added a macro
 for this idiom in llevents_tut.cpp. Generalize that macro further for
 normal-case processing as well, move it to a header file of its own and use
 it in all known places -- plus the new exception-catching tests in
 llprocess_test.cpp.

---
 indra/llcommon/tests/llprocess_test.cpp    |  6 +--
 indra/llmessage/tests/llsdmessage_test.cpp | 36 ++-----------
 indra/test/catch_and_store_what_in.h       | 86 ++++++++++++++++++++++++++++++
 indra/test/llevents_tut.cpp                | 69 +++---------------------
 4 files changed, 98 insertions(+), 99 deletions(-)
 create mode 100644 indra/test/catch_and_store_what_in.h

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 06f9f3827f..a901c577d6 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -31,6 +31,7 @@
 #include "../test/lltut.h"
 #include "../test/manageapr.h"
 #include "../test/namedtempfile.h"
+#include "../test/catch_and_store_what_in.h"
 #include "stringize.h"
 #include "llsdutil.h"
 #include "llevents.h"
@@ -952,10 +953,7 @@ namespace tut
         {                                                               \
             CODE;                                                       \
         }                                                               \
-        catch (const EXCEPTION& e)                                      \
-        {                                                               \
-            (THREW) = e.what();                                         \
-        }                                                               \
+        CATCH_AND_STORE_WHAT_IN(THREW, EXCEPTION)                       \
         ensure("failed to throw " #EXCEPTION ": " #CODE, ! (THREW).empty()); \
     } while (0)
 
diff --git a/indra/llmessage/tests/llsdmessage_test.cpp b/indra/llmessage/tests/llsdmessage_test.cpp
index 0f2c069303..6871ac0d52 100644
--- a/indra/llmessage/tests/llsdmessage_test.cpp
+++ b/indra/llmessage/tests/llsdmessage_test.cpp
@@ -42,6 +42,7 @@
 // external library headers
 // other Linden headers
 #include "../test/lltut.h"
+#include "../test/catch_and_store_what_in.h"
 #include "llsdserialize.h"
 #include "llevents.h"
 #include "stringize.h"
@@ -72,43 +73,14 @@ namespace tut
     template<> template<>
     void llsdmessage_object::test<1>()
     {
-        bool threw = false;
+        std::string threw;
         // This should fail...
         try
         {
             LLSDMessage localListener;
         }
-        catch (const LLEventPump::DupPumpName&)
-        {
-            threw = true;
-        }
-        catch (const std::runtime_error& ex)
-        {
-            // This clause is because on Linux, on the viewer side, for this
-            // one test program (though not others!), the
-            // LLEventPump::DupPumpName exception isn't caught by the clause
-            // above. Warn the user...
-            std::cerr << "Failed to catch " << typeid(ex).name() << std::endl;
-            // But if the expected exception was thrown, allow the test to
-            // succeed anyway. Not sure how else to handle this odd case.
-            if (std::string(typeid(ex).name()) == typeid(LLEventPump::DupPumpName).name())
-            {
-                threw = true;
-            }
-            else
-            {
-                // We don't even recognize this exception. Let it propagate
-                // out to TUT to fail the test.
-                throw;
-            }
-        }
-        catch (...)
-        {
-            std::cerr << "Utterly failed to catch expected exception!" << std::endl;
-            // This case is full of fail. We HAVE to address it.
-            throw;
-        }
-        ensure("second LLSDMessage should throw", threw);
+        CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName)
+        ensure("second LLSDMessage should throw", ! threw.empty());
     }
 
     template<> template<>
diff --git a/indra/test/catch_and_store_what_in.h b/indra/test/catch_and_store_what_in.h
new file mode 100644
index 0000000000..59f8cc0085
--- /dev/null
+++ b/indra/test/catch_and_store_what_in.h
@@ -0,0 +1,86 @@
+/**
+ * @file   catch_and_store_what_in.h
+ * @author Nat Goodspeed
+ * @date   2012-02-15
+ * @brief  CATCH_AND_STORE_WHAT_IN() macro
+ * 
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Copyright (c) 2012, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_CATCH_AND_STORE_WHAT_IN_H)
+#define LL_CATCH_AND_STORE_WHAT_IN_H
+
+/**
+ * Idiom useful for test programs: catch an expected exception, store its
+ * what() string in a specified std::string variable. From there the caller
+ * can do things like:
+ * @code
+ * ensure("expected exception not thrown", ! string.empty());
+ * @endcode
+ * or
+ * @code
+ * ensure_contains("exception doesn't mention blah", string, "blah");
+ * @endcode
+ * etc.
+ *
+ * The trouble is that when linking to a dynamic libllcommon.so on Linux, we
+ * generally fail to catch the specific exception. Oddly, we can catch it as
+ * std::runtime_error and validate its typeid().name(), so we do -- but that's
+ * a lot of boilerplate per test. Encapsulate with this macro. Usage:
+ *
+ * @code
+ * std::string threw;
+ * try
+ * {
+ *     some_call_that_should_throw_Foo();
+ * }
+ * CATCH_AND_STORE_WHAT_IN(threw, Foo)
+ * ensure("some_call_that_should_throw_Foo() didn't throw", ! threw.empty());
+ * @endcode
+ */
+#define CATCH_AND_STORE_WHAT_IN(THREW, EXCEPTION)	\
+catch (const EXCEPTION& ex)							\
+{													\
+	(THREW) = ex.what();							\
+}													\
+CATCH_MISSED_LINUX_EXCEPTION(THREW, EXCEPTION)
+
+#ifndef LL_LINUX
+#define CATCH_MISSED_LINUX_EXCEPTION(THREW, EXCEPTION)					\
+	/* only needed on Linux */
+#else // LL_LINUX
+
+#define CATCH_MISSED_LINUX_EXCEPTION(THREW, EXCEPTION)					\
+catch (const std::runtime_error& ex)									\
+{																		\
+	/* This clause is needed on Linux, on the viewer side, because	*/	\
+	/* the exception isn't caught by catch (const EXCEPTION&).		*/	\
+	/* But if the expected exception was thrown, allow the test to	*/	\
+	/* succeed anyway. Not sure how else to handle this odd case.	*/	\
+	if (std::string(typeid(ex).name()) == typeid(EXCEPTION).name())		\
+	{																	\
+		/* std::cerr << "Caught " << typeid(ex).name() */				\
+		/*			 << " with Linux workaround" << std::endl; */		\
+		(THREW) = ex.what();											\
+		/*std::cout << ex.what() << std::endl;*/						\
+	}																	\
+	else																\
+	{																	\
+		/* We don't even recognize this exception. Let it propagate	*/	\
+		/* out to TUT to fail the test.								*/	\
+		throw;															\
+	}																	\
+}																		\
+catch (...)																\
+{																		\
+	std::cerr << "Failed to catch expected exception "					\
+			  << #EXCEPTION << "!" << std::endl;						\
+	/* This indicates a problem in the test that should be addressed. */ \
+	throw;																\
+}
+
+#endif // LL_LINUX
+
+#endif /* ! defined(LL_CATCH_AND_STORE_WHAT_IN_H) */
diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp
index 4699bb1827..ca4c74099f 100644
--- a/indra/test/llevents_tut.cpp
+++ b/indra/test/llevents_tut.cpp
@@ -49,46 +49,12 @@
 #include <boost/assign/list_of.hpp>
 // other Linden headers
 #include "lltut.h"
+#include "catch_and_store_what_in.h"
 #include "stringize.h"
 #include "tests/listener.h"
 
 using boost::assign::list_of;
 
-#ifdef LL_LINUX
-#define CATCH_MISSED_LINUX_EXCEPTION(exception, threw)										\
-catch (const std::runtime_error& ex)														\
-{																							\
-	/* This clause is needed on Linux, on the viewer side, because the	*/					\
-	/* exception isn't caught by the clause above. Warn the user...		*/					\
-	std::cerr << "Failed to catch " << typeid(ex).name() << std::endl;						\
-	/* But if the expected exception was thrown, allow the test to		*/					\
-	/* succeed anyway. Not sure how else to handle this odd case.		*/					\
-	/* This approach is also used in llsdmessage_test.cpp. 				*/					\
-	if (std::string(typeid(ex).name()) == typeid(exception).name())							\
-	{																						\
-		threw = ex.what();																	\
-		/*std::cout << ex.what() << std::endl;*/											\
-	}																						\
-	else																					\
-	{																						\
-		/* We don't even recognize this exception. Let it propagate		*/					\
-		/* out to TUT to fail the test.									*/					\
-		throw;																				\
-	}																						\
-}																							\
-catch (...)																					\
-{																							\
-	std::cerr << "Utterly failed to catch expected exception " << #exception << "!" <<		\
-	std::endl;																				\
-	/* This indicates a problem in the test that should be addressed.   */					\
-	throw;																					\
-}
-
-#else // LL_LINUX
-#define CATCH_MISSED_LINUX_EXCEPTION(exception, threw)										\
-	/* Not needed on other platforms */
-#endif // LL_LINUX
-
 template<typename T>
 T make(const T& value)
 {
@@ -178,11 +144,7 @@ void events_object::test<1>()
 		per_frame.listen(listener0.getName(), // note bug, dup name
 						 boost::bind(&Listener::call, boost::ref(listener1), _1));
 	}
-	catch (const LLEventPump::DupListenerName& e)
-	{
-		threw = e.what();
-	}
-	CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::DupListenerName, threw)
+	CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupListenerName)
 	ensure_equals(threw,
 				  std::string("DupListenerName: "
 							  "Attempt to register duplicate listener name '") +
@@ -388,12 +350,7 @@ void events_object::test<7>()
 					  // after "Mary" and "checked" -- whoops!
 			 		  make<NameList>(list_of("Mary")("checked")));
 	}
-	catch (const LLEventPump::Cycle& e)
-	{
-		threw = e.what();
-		// std::cout << "Caught: " << e.what() << '\n';
-	}
-	CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::Cycle, threw)
+	CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::Cycle)
 	// Obviously the specific wording of the exception text can
 	// change; go ahead and change the test to match.
 	// Establish that it contains:
@@ -426,12 +383,7 @@ void events_object::test<7>()
 					  make<NameList>(list_of("shoelaces")),
 					  make<NameList>(list_of("yellow")));
 	}
-	catch (const LLEventPump::OrderChange& e)
-	{
-		threw = e.what();
-		// std::cout << "Caught: " << e.what() << '\n';
-	}
-	CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::OrderChange, threw)
+	CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::OrderChange)
 	// Same remarks about the specific wording of the exception. Just
 	// ensure that it contains enough information to clarify the
 	// problem and what must be done to resolve it.
@@ -459,12 +411,7 @@ void events_object::test<8>()
 			// then another with a duplicate name.
 			LLEventStream bob2("bob");
 		}
-		catch (const LLEventPump::DupPumpName& e)
-		{
-			threw = e.what();
-			// std::cout << "Caught: " << e.what() << '\n';
-		}
-		CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::DupPumpName, threw)
+		CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName)
 		ensure("Caught DupPumpName", !threw.empty());
 	} 	// delete first 'bob'
 	LLEventStream bob("bob"); 		// should work, previous one unregistered
@@ -505,11 +452,7 @@ void events_object::test<9>()
 		LLListenerOrPumpName empty;
 		empty(17);
 	}
-	catch (const LLListenerOrPumpName::Empty& e)
-	{
-		threw = e.what();
-	}
-	CATCH_MISSED_LINUX_EXCEPTION(LLListenerOrPumpName::Empty, threw)
+	CATCH_AND_STORE_WHAT_IN(threw, LLListenerOrPumpName::Empty)
 
 	ensure("threw Empty", !threw.empty());
 }
-- 
cgit v1.2.3


From 9b02f483ffe6f313ec86af3f29fa858fa0cb22e4 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 15 Feb 2012 14:04:46 -0500
Subject: VS2010 doesn't know how to compute min(4096, size_t)  :-P

---
 indra/llcommon/llprocess.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 55eb7e69d3..d7c297b952 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -144,8 +144,8 @@ public:
 		{
 			// Copy data out from mStreambuf to a flat, contiguous buffer to
 			// write -- but only up to a certain size.
-			std::streamsize total(mStreambuf.size());
-			std::streamsize bufsize((std::min)(4096, total));
+			std::size_t total(mStreambuf.size());
+			std::size_t bufsize((std::min)(std::size_t(4096), total));
 			boost::asio::streambuf::const_buffers_type bufs = mStreambuf.data();
 			std::vector<char> buffer(
 				boost::asio::buffers_begin(bufs),
@@ -241,7 +241,7 @@ private:
 
 				// Now that we've received new data, publish it on our
 				// LLEventPump as advertised. Constrain it by mLimit.
-				std::streamsize datasize((std::min)(mLimit, mStreambuf.size()));
+				std::size_t datasize((std::min)(mLimit, mStreambuf.size()));
 				boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
 				mPump.post(LLSDMap("data", LLSD::String(
 									   boost::asio::buffers_begin(cbufs),
-- 
cgit v1.2.3


From 56d931216e67a3e59199669bba022c65a9617bb5 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 15 Feb 2012 15:47:03 -0500
Subject: Add LLProcess::ReadPipe::size(), peek(), contains(). Also add "len"
 key to event data on LLProcess::getPump(). If you've used setLimit(),
 event["data"].length() may not reflect the length of the accumulated data in
 the ReadPipe. Add unit test with stdin/stdout handshake with child process.

---
 indra/llcommon/llprocess.cpp            | 31 +++++++++++++++++++-----
 indra/llcommon/llprocess.h              | 25 +++++++++++++++++++
 indra/llcommon/tests/llprocess_test.cpp | 43 +++++++++++++++++++++++++++++++--
 3 files changed, 91 insertions(+), 8 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index d7c297b952..1481bf571f 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -197,6 +197,25 @@ public:
 	virtual LLEventPump& getPump() { return mPump; }
 	virtual void setLimit(size_t limit) { mLimit = limit; }
 	virtual size_t getLimit() const { return mLimit; }
+    virtual std::size_t size() { return mStreambuf.size(); }
+
+	virtual std::string peek(std::size_t offset=0,
+							 std::size_t len=(std::numeric_limits<std::size_t>::max)())
+	{
+		// Constrain caller's offset and len to overlap actual buffer content.
+		std::size_t real_offset = (std::min)(mStreambuf.size(), offset);
+		std::size_t real_end	= (std::min)(mStreambuf.size(), real_offset + len);
+		boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
+		return std::string(boost::asio::buffers_begin(cbufs) + real_offset,
+						   boost::asio::buffers_begin(cbufs) + real_end);
+	}
+
+	virtual bool contains(const std::string& seek, std::size_t offset=0)
+	{
+		// There may be a more efficient way to search mStreambuf contents,
+		// but this is far the easiest...
+		return peek(offset).find(seek) != std::string::npos;
+	}
 
 private:
 	bool tick(const LLSD&)
@@ -240,12 +259,13 @@ private:
 									   << mStreambuf.size() << LL_ENDL;
 
 				// Now that we've received new data, publish it on our
-				// LLEventPump as advertised. Constrain it by mLimit.
+				// LLEventPump as advertised. Constrain it by mLimit. But show
+				// listener the actual accumulated buffer size, regardless of
+				// mLimit.
 				std::size_t datasize((std::min)(mLimit, mStreambuf.size()));
-				boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
-				mPump.post(LLSDMap("data", LLSD::String(
-									   boost::asio::buffers_begin(cbufs),
-									   boost::asio::buffers_begin(cbufs) + datasize)));
+				mPump.post(LLSDMap
+						   ("data", peek(0, datasize))
+						   ("len", LLSD::Integer(mStreambuf.size())));
 			}
 		}
 		return false;
@@ -985,5 +1005,4 @@ void LLProcess::reap(void)
 	}
 }
 |*==========================================================================*/
-
 #endif  // Posix
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 448a88f4c0..bf0517600d 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -330,6 +330,31 @@ public:
 		 */
 		virtual std::istream& get_istream() = 0;
 
+		/**
+		 * Get accumulated buffer length.
+		 * Often we need to refrain from actually reading the std::istream
+		 * returned by get_istream() until we've accumulated enough data to
+		 * make it worthwhile. For instance, if we're expecting a number from
+		 * the child, but the child happens to flush "12" before emitting
+		 * "3\n", get_istream() >> myint could return 12 rather than 123!
+		 */
+		virtual std::size_t size() = 0;
+
+		/**
+		 * Peek at accumulated buffer data without consuming it. Optional
+		 * parameters give you substr() functionality.
+		 *
+		 * @note You can discard buffer data using get_istream().ignore(n).
+		 */
+		virtual std::string peek(std::size_t offset=0,
+								 std::size_t len=(std::numeric_limits<std::size_t>::max)()) = 0;
+
+		/**
+		 * Search accumulated buffer data without retrieving it. Optional
+		 * offset allows you to start at specified position.
+		 */
+		virtual bool contains(const std::string& seek, std::size_t offset=0) = 0;
+
 		/**
 		 * Get LLEventPump& on which to listen for incoming data. The posted
 		 * LLSD::Map event will contain a key "data" whose value is an
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index a901c577d6..2db17cae97 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -919,6 +919,7 @@ namespace tut
                         message, "somename");
     }
 
+    /*-------------- support for "get*Pipe() validation" test --------------*/
 #define TEST_getPipe(PROCESS, GETPIPE, GETOPTPIPE, VALID, NOPIPE, BADPIPE) \
     do                                                                  \
     {                                                                   \
@@ -985,11 +986,49 @@ namespace tut
                      LLProcess::STDIN);  // BADPIPE
     }
 
+    template<> template<>
+    void object::test<16>()
+    {
+        set_test_name("talk to stdin/stdout");
+        PythonProcessLauncher py("stdin/stdout",
+                                 "import sys, time\n"
+                                 "print 'ok'\n"
+                                 "sys.stdout.flush()\n"
+                                 "# wait for 'go' from test program\n"
+                                 "go = sys.stdin.readline()\n"
+                                 "if go != 'go\\n':\n"
+                                 "    sys.exit('expected \"go\", saw %r' % go)\n"
+                                 "print 'ack'\n");
+        py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin
+        py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
+        py.mPy = LLProcess::create(py.mParams);
+        ensure("couldn't launch stdin/stdout script", py.mPy);
+        LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT));
+        int i, timeout = 60;
+        for (i = 0; i < timeout && py.mPy->isRunning() && childout.size() < 3; ++i)
+        {
+            yield();
+        }
+        ensure("script never started", i < timeout);
+        std::string line;
+        std::getline(childout.get_istream(), line);
+        ensure_equals("bad wakeup from stdin/stdout script", line, "ok");
+        py.mPy->getWritePipe().get_ostream() << "go" << std::endl;
+        for (i = 0; i < timeout && py.mPy->isRunning() && ! childout.contains("\n"); ++i)
+        {
+            yield();
+        }
+        ensure("script never replied", childout.contains("\n"));
+        std::getline(childout.get_istream(), line);
+        ensure_equals("child didn't ack", line, "ack");
+        ensure_equals("bad child termination", py.mPy->getStatus().mState, LLProcess::EXITED);
+        ensure_equals("bad child exit code",   py.mPy->getStatus().mData,  0);
+    }
+
     // TODO:
-    // test pipe for stdin, stdout (etc.)
-    // test getWritePipe().get_ostream(), getReadPipe().get_istream()
     // test listening on getReadPipe().getPump(), disconnecting
     // test setLimit(), getLimit()
     // test EOF -- check logging
+    // test peek() with substr
 
 } // namespace tut
-- 
cgit v1.2.3


From fc6d70db8771320f3b1136e76383fc85ddf1b6b2 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 15 Feb 2012 20:57:25 -0500
Subject: Don't be confused by "\r\n" line endings on pipe on Windows. These
 are all very well when we just want to dump the output to a log, or whatever,
 but in a unit-test context it matters for comparison.

---
 indra/llcommon/tests/llprocess_test.cpp | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 2db17cae97..6d6b888471 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -288,6 +288,22 @@ public:
     LLError::Settings* mOldSettings;
 };
 
+std::string getline(std::istream& in)
+{
+    std::string line;
+    std::getline(in, line);
+    // Blur the distinction between "\r\n" and plain "\n". std::getline() will
+    // have eaten the "\n", but we could still end up with a trailing "\r".
+    std::string::size_type lastpos = line.find_last_not_of("\r");
+    if (lastpos != std::string::npos)
+    {
+        // Found at least one character that's not a trailing '\r'. SKIP OVER
+        // IT and then erase the rest of the line.
+        line.erase(lastpos+1);
+    }
+    return line;
+}
+
 /*****************************************************************************
 *   TUT
 *****************************************************************************/
@@ -1010,17 +1026,15 @@ namespace tut
             yield();
         }
         ensure("script never started", i < timeout);
-        std::string line;
-        std::getline(childout.get_istream(), line);
-        ensure_equals("bad wakeup from stdin/stdout script", line, "ok");
+        ensure_equals("bad wakeup from stdin/stdout script",
+                      getline(childout.get_istream()), "ok");
         py.mPy->getWritePipe().get_ostream() << "go" << std::endl;
         for (i = 0; i < timeout && py.mPy->isRunning() && ! childout.contains("\n"); ++i)
         {
             yield();
         }
         ensure("script never replied", childout.contains("\n"));
-        std::getline(childout.get_istream(), line);
-        ensure_equals("child didn't ack", line, "ack");
+        ensure_equals("child didn't ack", getline(childout.get_istream()), "ack");
         ensure_equals("bad child termination", py.mPy->getStatus().mState, LLProcess::EXITED);
         ensure_equals("bad child exit code",   py.mPy->getStatus().mData,  0);
     }
-- 
cgit v1.2.3


From 85057908c3f7e48f1dc086ea1c82e672674b2596 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 15 Feb 2012 21:55:53 -0500
Subject: Add unit test for listening on LLProcess::ReadPipe::getPump().

---
 indra/llcommon/tests/llprocess_test.cpp | 89 ++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 6d6b888471..31bc833a1d 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -1028,6 +1028,7 @@ namespace tut
         ensure("script never started", i < timeout);
         ensure_equals("bad wakeup from stdin/stdout script",
                       getline(childout.get_istream()), "ok");
+        // important to get the implicit flush from std::endl
         py.mPy->getWritePipe().get_ostream() << "go" << std::endl;
         for (i = 0; i < timeout && py.mPy->isRunning() && ! childout.contains("\n"); ++i)
         {
@@ -1039,8 +1040,94 @@ namespace tut
         ensure_equals("bad child exit code",   py.mPy->getStatus().mData,  0);
     }
 
+    struct EventListener: public boost::noncopyable
+    {
+        EventListener(LLEventPump& pump)
+        {
+            mConnection = 
+                pump.listen("EventListener", boost::bind(&EventListener::tick, this, _1));
+        }
+
+        bool tick(const LLSD& data)
+        {
+            mHistory.push_back(data);
+            return false;
+        }
+
+        std::list<LLSD> mHistory;
+        LLTempBoundListener mConnection;
+    };
+
+    static bool ack(std::ostream& out, const LLSD& data)
+    {
+        out << "continue" << std::endl;
+        return false;
+    }
+
+    template<> template<>
+    void object::test<17>()
+    {
+        set_test_name("listen for ReadPipe events");
+        PythonProcessLauncher py("ReadPipe listener",
+                                 "import sys\n"
+                                 "sys.stdout.write('abc')\n"
+                                 "sys.stdout.flush()\n"
+                                 "sys.stdin.readline()\n"
+                                 "sys.stdout.write('def')\n"
+                                 "sys.stdout.flush()\n"
+                                 "sys.stdin.readline()\n"
+                                 "sys.stdout.write('ghi\\n')\n"
+                                 "sys.stdout.flush()\n"
+                                 "sys.stdin.readline()\n"
+                                 "sys.stdout.write('second line\\n')\n");
+        py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin
+        py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
+        py.mPy = LLProcess::create(py.mParams);
+        ensure("couldn't launch ReadPipe listener script", py.mPy);
+        std::ostream& childin(py.mPy->getWritePipe(LLProcess::STDIN).get_ostream());
+        LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT));
+        // listen for incoming data on childout
+        EventListener listener(childout.getPump());
+        // also listen with a function that prompts the child to continue
+        // every time we see output
+        LLTempBoundListener connection(
+            childout.getPump().listen("ack", boost::bind(ack, boost::ref(childin), _1)));
+        int i, timeout = 60;
+        // wait through stuttering first line
+        for (i = 0; i < timeout && py.mPy->isRunning() && ! childout.contains("\n"); ++i)
+        {
+            yield();
+        }
+        ensure("couldn't get first line", i < timeout);
+        // disconnect from listener
+        listener.mConnection.disconnect();
+        // finish out the run
+        for (i = 0; i < timeout && py.mPy->isRunning(); ++i)
+        {
+            yield();
+        }
+        ensure("child took too long to terminate", i < timeout);
+        // now verify history
+        std::list<LLSD>::const_iterator li(listener.mHistory.begin()),
+                                        lend(listener.mHistory.end());
+        ensure("no events", li != lend);
+        ensure_equals("history[0]", (*li)["data"].asString(), "abc");
+        ensure_equals("history[0] len", (*li)["len"].asInteger(), 3);
+        ++li;
+        ensure("only 1 event", li != lend);
+        ensure_equals("history[1]", (*li)["data"].asString(), "abcdef");
+        ensure_equals("history[0] len", (*li)["len"].asInteger(), 6);
+        ++li;
+        ensure("only 2 events", li != lend);
+        ensure_equals("history[2]", (*li)["data"].asString(), "abcdefghi" EOL);
+        ensure_equals("history[0] len", (*li)["len"].asInteger(), 9 + sizeof(EOL) - 1);
+        ++li;
+        // We DO NOT expect a whole new event for the second line because we
+        // disconnected.
+        ensure("more than 3 events", li == lend);
+    }
+
     // TODO:
-    // test listening on getReadPipe().getPump(), disconnecting
     // test setLimit(), getLimit()
     // test EOF -- check logging
     // test peek() with substr
-- 
cgit v1.2.3


From e92c3113545dd60fb76e115da201163e340c730c Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 16 Feb 2012 16:05:04 -0500
Subject: Add LLProcess::ReadPipe::find() methods, with corresponding npos. If
 it's useful to have contains() to tell you whether incoming data contains a
 particular substring, and if it's useful for contains() and peek() to accept
 an offset within that data, then it's useful to allow you to get the offset
 of a desired substring within that data. But of course a find() returning
 offset needs something like std::string::npos for "not found"; borrow that
 convention. Support both find(const std::string&) and find(char); the latter
 permits a more efficient implementation. In fact, make find(string) recognize
 a string of length 1 and leverage the find(char) implementation. Given that,
 reimplement contains(mumble) as shorthand for find(mumble) != npos. Implement
 find() overloads using std::search() and std::find() on
 boost::asio::streambuf character iterators, rather than copying to
 std::string and then using string search like previous contains()
 implementation. Reimplement WritePipeImpl::tick() and ReadPipeImpl::tick() to
 write/read directly from/to boost::asio::streambuf data, instead of copying
 to/from a temporary flat buffer. As long as ReadPipeImpl::tick() keeps
 successfully filling buffers, keep reading. Previous implementation would
 only handle a long child write over successive tick() calls. Stop on read
 error or when we come up short.

---
 indra/llcommon/llprocess.cpp            | 259 ++++++++++++++++++++++----------
 indra/llcommon/llprocess.h              |  37 ++++-
 indra/llcommon/tests/llprocess_test.cpp |   2 +
 3 files changed, 210 insertions(+), 88 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 1481bf571f..aa22b3f805 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -120,9 +120,12 @@ private:
 static LLProcessListener sProcessListener;
 
 LLProcess::BasePipe::~BasePipe() {}
+const LLProcess::BasePipe::size_type
+	  LLProcess::BasePipe::npos((std::numeric_limits<LLProcess::BasePipe::size_type>::max)());
 
 class WritePipeImpl: public LLProcess::WritePipe
 {
+    LOG_CLASS(WritePipeImpl);
 public:
 	WritePipeImpl(const std::string& desc, apr_file_t* pipe):
 		mDesc(desc),
@@ -139,30 +142,53 @@ public:
 
 	bool tick(const LLSD&)
 	{
+		typedef boost::asio::streambuf::const_buffers_type const_buffer_sequence;
 		// If there's anything to send, try to send it.
-		if (mStreambuf.size())
+		std::size_t total(mStreambuf.size()), consumed(0);
+		if (total)
 		{
-			// Copy data out from mStreambuf to a flat, contiguous buffer to
-			// write -- but only up to a certain size.
-			std::size_t total(mStreambuf.size());
-			std::size_t bufsize((std::min)(std::size_t(4096), total));
-			boost::asio::streambuf::const_buffers_type bufs = mStreambuf.data();
-			std::vector<char> buffer(
-				boost::asio::buffers_begin(bufs),
-				boost::asio::buffers_begin(bufs) + bufsize);
-			apr_size_t written(bufsize);
-			ll_apr_warn_status(apr_file_write(mPipe, &buffer[0], &written));
-			// 'written' is modified to reflect the number of bytes actually
-			// written. Since they've been sent, remove them from the
+			const_buffer_sequence bufs = mStreambuf.data();
+			// In general, our streambuf might contain a number of different
+			// physical buffers; iterate over those.
+			for (const_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end());
+				 bufi != bufend; ++bufi)
+			{
+				// http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents
+				std::size_t towrite(boost::asio::buffer_size(*bufi));
+				apr_size_t written(towrite);
+				apr_status_t err = apr_file_write(mPipe,
+												  boost::asio::buffer_cast<const void*>(*bufi),
+												  &written);
+				// EAGAIN is exactly what we want from a nonblocking pipe.
+				// Rather than waiting for data, it should return immediately.
+				if (! (err == APR_SUCCESS || APR_STATUS_IS_EAGAIN(err)))
+				{
+					LL_WARNS("LLProcess") << "apr_file_write(" << towrite << ") on " << mDesc
+										  << " got " << err << ":" << LL_ENDL;
+					ll_apr_warn_status(err);
+				}
+
+				// 'written' is modified to reflect the number of bytes actually
+				// written. Make sure we consume those later. (Don't consume them
+				// now, that would invalidate the buffer iterator sequence!)
+				consumed += written;
+				LL_DEBUGS("LLProcess") << "wrote " << written << " of " << towrite
+									   << " bytes to " << mDesc
+									   << " (original " << total << ")" << LL_ENDL;
+
+				// The parent end of this pipe is nonblocking. If we weren't able
+				// to write everything we wanted, don't keep banging on it -- that
+				// won't change until the child reads some. Wait for next tick().
+				if (written < towrite)
+					break;
+			}
+			// In all, we managed to write 'consumed' bytes. Remove them from the
 			// streambuf so we don't keep trying to send them. This could be
-			// anywhere from 0 up to mStreambuf.size(); anything we haven't
-			// yet sent, we'll try again next tick() call.
-			mStreambuf.consume(written);
-			LL_DEBUGS("LLProcess") << "wrote " << written << " of " << bufsize
-								   << " bytes to " << mDesc
-								   << " (original " << total << "), "
-								   << mStreambuf.size() << " remaining" << LL_ENDL;
+			// anywhere from 0 up to mStreambuf.size(); anything we haven't yet
+			// sent, we'll try again later.
+			mStreambuf.consume(consumed);
 		}
+
 		return false;
 	}
 
@@ -176,6 +202,7 @@ private:
 
 class ReadPipeImpl: public LLProcess::ReadPipe
 {
+    LOG_CLASS(ReadPipeImpl);
 public:
 	ReadPipeImpl(const std::string& desc, apr_file_t* pipe):
 		mDesc(desc),
@@ -184,7 +211,7 @@ public:
 		mStream(&mStreambuf),
 		mPump("ReadPipe"),
 		// use funky syntax to call max() to avoid blighted max() macros
-		mLimit((std::numeric_limits<size_t>::max)())
+		mLimit(npos)
 	{
 		mConnection = LLEventPumps::instance().obtain("mainloop")
 			.listen(LLEventPump::inventName("ReadPipe"),
@@ -195,79 +222,149 @@ public:
 	// methods with implementation data concealed from the base class.
 	virtual std::istream& get_istream() { return mStream; }
 	virtual LLEventPump& getPump() { return mPump; }
-	virtual void setLimit(size_t limit) { mLimit = limit; }
-	virtual size_t getLimit() const { return mLimit; }
-    virtual std::size_t size() { return mStreambuf.size(); }
+	virtual void setLimit(size_type limit) { mLimit = limit; }
+	virtual size_type getLimit() const { return mLimit; }
+	virtual size_type size() const { return mStreambuf.size(); }
 
-	virtual std::string peek(std::size_t offset=0,
-							 std::size_t len=(std::numeric_limits<std::size_t>::max)())
+	virtual std::string peek(size_type offset=0, size_type len=npos) const
 	{
 		// Constrain caller's offset and len to overlap actual buffer content.
-		std::size_t real_offset = (std::min)(mStreambuf.size(), offset);
-		std::size_t real_end	= (std::min)(mStreambuf.size(), real_offset + len);
+		std::size_t real_offset = (std::min)(mStreambuf.size(), std::size_t(offset));
+		std::size_t real_end	= (std::min)(mStreambuf.size(), std::size_t(real_offset + len));
 		boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
 		return std::string(boost::asio::buffers_begin(cbufs) + real_offset,
 						   boost::asio::buffers_begin(cbufs) + real_end);
 	}
 
-	virtual bool contains(const std::string& seek, std::size_t offset=0)
+	virtual size_type find(const std::string& seek, size_type offset=0) const
 	{
-		// There may be a more efficient way to search mStreambuf contents,
-		// but this is far the easiest...
-		return peek(offset).find(seek) != std::string::npos;
+		// If we're passing a string of length 1, use find(char), which can
+		// use an O(n) std::find() rather than the O(n^2) std::search().
+		if (seek.length() == 1)
+		{
+			return find(seek[0], offset);
+		}
+
+		// If offset is beyond the whole buffer, can't even construct a valid
+		// iterator range; can't possibly find the string we seek.
+		if (offset > mStreambuf.size())
+		{
+			return npos;
+		}
+
+		boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
+		boost::asio::buffers_iterator<boost::asio::streambuf::const_buffers_type>
+			begin(boost::asio::buffers_begin(cbufs)),
+			end	 (boost::asio::buffers_end(cbufs)),
+			found(std::search(begin + offset, end, seek.begin(), seek.end()));
+		return (found == end)? npos : (found - begin);
 	}
 
-private:
-	bool tick(const LLSD&)
+	virtual size_type find(char seek, size_type offset=0) const
 	{
-		// Allocate a buffer and try, every time, to read into it.
-		std::vector<char> buffer(4096);
-		apr_size_t gotten(buffer.size());
-		apr_status_t err = apr_file_read(mPipe, &buffer[0], &gotten);
-		if (err == APR_EOF)
+		// If offset is beyond the whole buffer, can't even construct a valid
+		// iterator range; can't possibly find the char we seek.
+		if (offset > mStreambuf.size())
 		{
-			// Handle EOF specially: it's part of normal-case processing.
-			LL_DEBUGS("LLProcess") << "EOF on " << mDesc << LL_ENDL;
-			// We won't need any more tick() calls.
-			mConnection.disconnect();
+			return npos;
 		}
-		else if (! ll_apr_warn_status(err)) // validate anything but EOF
+
+		boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
+		boost::asio::buffers_iterator<boost::asio::streambuf::const_buffers_type>
+			begin(boost::asio::buffers_begin(cbufs)),
+			end	 (boost::asio::buffers_end(cbufs)),
+			found(std::find(begin + offset, end, seek));
+		return (found == end)? npos : (found - begin);
+	}
+
+private:
+	bool tick(const LLSD&)
+	{
+		typedef boost::asio::streambuf::mutable_buffers_type mutable_buffer_sequence;
+		// Try, every time, to read into our streambuf. In fact, we have no
+		// idea how much data the child might be trying to send: keep trying
+		// until we're convinced we've temporarily exhausted the pipe.
+		bool exhausted = false;
+		std::size_t committed(0);
+		do
 		{
-			// 'gotten' was modified to reflect the number of bytes actually
-			// received. If nonzero, add them to the streambuf and notify
-			// interested parties.
-			if (gotten)
+			// attempt to read an arbitrary size
+			mutable_buffer_sequence bufs = mStreambuf.prepare(4096);
+			// In general, the mutable_buffer_sequence returned by prepare() might
+			// contain a number of different physical buffers; iterate over those.
+			std::size_t tocommit(0);
+			for (mutable_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end());
+				 bufi != bufend; ++bufi)
 			{
-				boost::asio::streambuf::mutable_buffers_type mbufs = mStreambuf.prepare(gotten);
-				std::copy(buffer.begin(), buffer.begin() + gotten,
-						  boost::asio::buffers_begin(mbufs));
-				// Don't forget to "commit" the data! The sequence (prepare(),
-				// commit()) is obviously intended to allow us to allocate
-				// buffer space, then read directly into some portion of it,
-				// then commit only as much as we managed to obtain. But the
-				// only official (documented) way I can find to populate a
-				// mutable_buffers_type is to use buffers_begin(). It Would Be
-				// Nice if we were permitted to directly read into
-				// mutable_buffers_type (not to mention writing directly from
-				// const_buffers_type in WritePipeImpl; APR even supports an
-				// apr_file_writev() function for writing from discontiguous
-				// buffers) -- but as of 2012-02-14, this copying appears to
-				// be the safest tactic.
-				mStreambuf.commit(gotten);
-				LL_DEBUGS("LLProcess") << "read " << gotten << " of " << buffer.size()
-									   << " bytes from " << mDesc << ", new total "
-									   << mStreambuf.size() << LL_ENDL;
-
-				// Now that we've received new data, publish it on our
-				// LLEventPump as advertised. Constrain it by mLimit. But show
-				// listener the actual accumulated buffer size, regardless of
-				// mLimit.
-				std::size_t datasize((std::min)(mLimit, mStreambuf.size()));
-				mPump.post(LLSDMap
-						   ("data", peek(0, datasize))
-						   ("len", LLSD::Integer(mStreambuf.size())));
+				// http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents
+				std::size_t toread(boost::asio::buffer_size(*bufi));
+				apr_size_t gotten(toread);
+				apr_status_t err = apr_file_read(mPipe,
+												 boost::asio::buffer_cast<void*>(*bufi),
+												 &gotten);
+				// EAGAIN is exactly what we want from a nonblocking pipe.
+				// Rather than waiting for data, it should return immediately.
+				if (! (err == APR_SUCCESS || APR_STATUS_IS_EAGAIN(err)))
+				{
+					// Handle EOF specially: it's part of normal-case processing.
+					if (err == APR_EOF)
+					{
+						LL_DEBUGS("LLProcess") << "EOF on " << mDesc << LL_ENDL;
+					}
+					else
+					{
+						LL_WARNS("LLProcess") << "apr_file_read(" << toread << ") on " << mDesc
+											  << " got " << err << ":" << LL_ENDL;
+						ll_apr_warn_status(err);
+					}
+					// Either way, though, we won't need any more tick() calls.
+					mConnection.disconnect();
+					exhausted = true; // also break outer retry loop
+					break;
+				}
+
+				// 'gotten' was modified to reflect the number of bytes actually
+				// received. Make sure we commit those later. (Don't commit them
+				// now, that would invalidate the buffer iterator sequence!)
+				tocommit += gotten;
+				LL_DEBUGS("LLProcess") << "read " << gotten << " of " << toread
+									   << " bytes from " << mDesc << LL_ENDL;
+
+				// The parent end of this pipe is nonblocking. If we weren't even
+				// able to fill this buffer, don't loop to try to fill the next --
+				// that won't change until the child writes more. Wait for next
+				// tick().
+				if (gotten < toread)
+				{
+					// break outer retry loop too
+					exhausted = true;
+					break;
+				}
 			}
+
+			// Don't forget to "commit" the data!
+			mStreambuf.commit(tocommit);
+			committed += tocommit;
+
+			// 'exhausted' is set when we can't fill any one buffer of the
+			// mutable_buffer_sequence established by the current prepare()
+			// call -- whether due to error or not enough bytes. That is,
+			// 'exhausted' is still false when we've filled every physical
+			// buffer in the mutable_buffer_sequence. In that case, for all we
+			// know, the child might have still more data pending -- go for it!
+		} while (! exhausted);
+
+		if (committed)
+		{
+			// If we actually received new data, publish it on our LLEventPump
+			// as advertised. Constrain it by mLimit. But show listener the
+			// actual accumulated buffer size, regardless of mLimit.
+			size_type datasize((std::min)(mLimit, size_type(mStreambuf.size())));
+			mPump.post(LLSDMap
+					   ("data", peek(0, datasize))
+					   ("len", LLSD::Integer(mStreambuf.size())));
 		}
+
 		return false;
 	}
 
@@ -277,7 +374,7 @@ private:
 	boost::asio::streambuf mStreambuf;
 	std::istream mStream;
 	LLEventStream mPump;
-	size_t mLimit;
+	size_type mLimit;
 };
 
 /// Need an exception to avoid constructing an invalid LLProcess object, but
@@ -472,16 +569,18 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 	{
 		if (select[i] != APR_CHILD_BLOCK)
 			continue;
+		std::string desc(STRINGIZE(mDesc << ' ' << whichfile[i]));
+		apr_file_t* pipe(mProcess.*(members[i]));
 		if (i == STDIN)
 		{
-			mPipes.replace(i, new WritePipeImpl(whichfile[i], mProcess.*(members[i])));
+			mPipes.replace(i, new WritePipeImpl(desc, pipe));
 		}
 		else
 		{
-			mPipes.replace(i, new ReadPipeImpl(whichfile[i], mProcess.*(members[i])));
+			mPipes.replace(i, new ReadPipeImpl(desc, pipe));
 		}
 		LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name()
-							   << "('" << whichfile[i] << "')" << LL_ENDL;
+							   << "('" << desc << "')" << LL_ENDL;
 	}
 }
 
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index bf0517600d..2c6951b562 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -295,6 +295,9 @@ public:
 	{
 	public:
 		virtual ~BasePipe() = 0;
+
+		typedef std::size_t size_type;
+		static const size_type npos;
 	};
 
 	/// As returned by getWritePipe() or getOptWritePipe()
@@ -338,7 +341,7 @@ public:
 		 * the child, but the child happens to flush "12" before emitting
 		 * "3\n", get_istream() >> myint could return 12 rather than 123!
 		 */
-		virtual std::size_t size() = 0;
+		virtual size_type size() const = 0;
 
 		/**
 		 * Peek at accumulated buffer data without consuming it. Optional
@@ -346,14 +349,32 @@ public:
 		 *
 		 * @note You can discard buffer data using get_istream().ignore(n).
 		 */
-		virtual std::string peek(std::size_t offset=0,
-								 std::size_t len=(std::numeric_limits<std::size_t>::max)()) = 0;
+		virtual std::string peek(size_type offset=0, size_type len=npos) const = 0;
+
+		/**
+		 * Detect presence of a substring (or char) in accumulated buffer data
+		 * without retrieving it. Optional offset allows you to search from
+		 * specified position.
+		 */
+		template <typename SEEK>
+		bool contains(SEEK seek, size_type offset=0) const
+		{ return find(seek, offset) != npos; }
+
+		/**
+		 * Search for a substring in accumulated buffer data without
+		 * retrieving it. Returns size_type position at which found, or npos
+		 * meaning not found. Optional offset allows you to search from
+		 * specified position.
+		 */
+		virtual size_type find(const std::string& seek, size_type offset=0) const = 0;
 
 		/**
-		 * Search accumulated buffer data without retrieving it. Optional
-		 * offset allows you to start at specified position.
+		 * Search for a char in accumulated buffer data without retrieving it.
+		 * Returns size_type position at which found, or npos meaning not
+		 * found. Optional offset allows you to search from specified
+		 * position.
 		 */
-		virtual bool contains(const std::string& seek, std::size_t offset=0) = 0;
+		virtual size_type find(char seek, size_type offset=0) const = 0;
 
 		/**
 		 * Get LLEventPump& on which to listen for incoming data. The posted
@@ -377,12 +398,12 @@ public:
 		 * the data posted with the LLSD event. If you don't call this method,
 		 * all pending data will be posted.
 		 */
-		virtual void setLimit(size_t limit) = 0;
+		virtual void setLimit(size_type limit) = 0;
 
 		/**
 		 * Query the current setLimit() limit.
 		 */
-		virtual size_t getLimit() const = 0;
+		virtual size_type getLimit() const = 0;
 	};
 
 	/// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 31bc833a1d..d7bda34923 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -1131,5 +1131,7 @@ namespace tut
     // test setLimit(), getLimit()
     // test EOF -- check logging
     // test peek() with substr
+    // test contains(char)
+    // test find(string, offset), find(char, offset), offset <, =, > size()
 
 } // namespace tut
-- 
cgit v1.2.3


From 4ecf9d6a2d981ef27c7b5bddc4807c67d12d5984 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 16 Feb 2012 16:40:14 -0500
Subject: Add unit test for LLProcess::ReadPipe::setLimit().

---
 indra/llcommon/tests/llprocess_test.cpp | 62 +++++++++++++++++++++++----------
 1 file changed, 44 insertions(+), 18 deletions(-)

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index d7bda34923..29233d4415 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -140,11 +140,17 @@ struct PythonProcessLauncher
         mParams.args.add(mScript.getName());
     }
 
-    /// Run Python script and wait for it to complete.
-    void run()
+    /// Launch Python script; verify that it launched
+    void launch()
     {
         mPy = LLProcess::create(mParams);
         tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), mPy);
+    }
+
+    /// Run Python script and wait for it to complete.
+    void run()
+    {
+        launch();
         // One of the irritating things about LLProcess is that
         // there's no API to wait for the child to terminate -- but given
         // its use in our graphics-intensive interactive viewer, it's
@@ -718,8 +724,7 @@ namespace tut
                                  "    f.write('bad')\n");
         NamedTempFile out("out", "not started");
         py.mParams.args.add(out.getName());
-        py.mPy = LLProcess::create(py.mParams);
-        ensure("couldn't launch kill() script", py.mPy);
+        py.launch();
         // Wait for the script to wake up and do its first write
         int i = 0, timeout = 60;
         for ( ; i < timeout; ++i)
@@ -765,8 +770,7 @@ namespace tut
                                      "with open(sys.argv[1], 'w') as f:\n"
                                      "    f.write('bad')\n");
             py.mParams.args.add(out.getName());
-            py.mPy = LLProcess::create(py.mParams);
-            ensure("couldn't launch kill() script", py.mPy);
+            py.launch();
             // Capture handle for later
             phandle = py.mPy->getProcessHandle();
             // Wait for the script to wake up and do its first write
@@ -820,8 +824,7 @@ namespace tut
             py.mParams.args.add(from.getName());
             py.mParams.args.add(to.getName());
             py.mParams.autokill = false;
-            py.mPy = LLProcess::create(py.mParams);
-            ensure("couldn't launch kill() script", py.mPy);
+            py.launch();
             // Capture handle for later
             phandle = py.mPy->getProcessHandle();
             // Wait for the script to wake up and do its first write
@@ -1017,8 +1020,7 @@ namespace tut
                                  "print 'ack'\n");
         py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin
         py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
-        py.mPy = LLProcess::create(py.mParams);
-        ensure("couldn't launch stdin/stdout script", py.mPy);
+        py.launch();
         LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT));
         int i, timeout = 60;
         for (i = 0; i < timeout && py.mPy->isRunning() && childout.size() < 3; ++i)
@@ -1082,8 +1084,7 @@ namespace tut
                                  "sys.stdout.write('second line\\n')\n");
         py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin
         py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
-        py.mPy = LLProcess::create(py.mParams);
-        ensure("couldn't launch ReadPipe listener script", py.mPy);
+        py.launch();
         std::ostream& childin(py.mPy->getWritePipe(LLProcess::STDIN).get_ostream());
         LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT));
         // listen for incoming data on childout
@@ -1102,11 +1103,7 @@ namespace tut
         // disconnect from listener
         listener.mConnection.disconnect();
         // finish out the run
-        for (i = 0; i < timeout && py.mPy->isRunning(); ++i)
-        {
-            yield();
-        }
-        ensure("child took too long to terminate", i < timeout);
+        waitfor(*py.mPy);
         // now verify history
         std::list<LLSD>::const_iterator li(listener.mHistory.begin()),
                                         lend(listener.mHistory.end());
@@ -1127,8 +1124,37 @@ namespace tut
         ensure("more than 3 events", li == lend);
     }
 
+    template<> template<>
+    void object::test<18>()
+    {
+        set_test_name("setLimit()");
+        PythonProcessLauncher py("setLimit()",
+                                 "import sys\n"
+                                 "print sys.argv[1]\n");
+        std::string abc("abcdefghijklmnopqrstuvwxyz");
+        py.mParams.args.add(abc);
+        py.mParams.files.add(LLProcess::FileParam()); // stdin
+        py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
+        py.launch();
+        LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT));
+        // listen for incoming data on childout
+        EventListener listener(childout.getPump());
+        // but set limit
+        childout.setLimit(10);
+        ensure_equals("getLimit() after setlimit(10)", childout.getLimit(), 10);
+        // okay, pump I/O to pick up output from child
+        waitfor(*py.mPy);
+        ensure("no events", ! listener.mHistory.empty());
+        // For all we know, that data could have arrived in several different
+        // bursts... probably not, but anyway, only check the last one.
+        ensure_equals("event[\"len\"]",
+                      listener.mHistory.back()["len"].asInteger(),
+                      abc.length() + sizeof(EOL) - 1);
+        ensure_equals("length of setLimit(10) data",
+                      listener.mHistory.back()["data"].asString().length(), 10);
+    }
+
     // TODO:
-    // test setLimit(), getLimit()
     // test EOF -- check logging
     // test peek() with substr
     // test contains(char)
-- 
cgit v1.2.3


From a06ba836c76ea8b35aeca9d09bd7d3b043a4c962 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 16 Feb 2012 17:35:34 -0500
Subject: Fix bug in LLProcess::ReadPipe::peek() substring computation. Add
 unit tests for peek() with substring args, reimplemented contains(), various
 forms of find(). (yay unit tests)

---
 indra/llcommon/llprocess.cpp            |  3 +-
 indra/llcommon/tests/llprocess_test.cpp | 61 +++++++++++++++++++++++++++++----
 2 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index aa22b3f805..add1649ba5 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -230,7 +230,8 @@ public:
 	{
 		// Constrain caller's offset and len to overlap actual buffer content.
 		std::size_t real_offset = (std::min)(mStreambuf.size(), std::size_t(offset));
-		std::size_t real_end	= (std::min)(mStreambuf.size(), std::size_t(real_offset + len));
+		size_type	want_end	= (len == npos)? npos : (real_offset + len);
+		std::size_t real_end	= (std::min)(mStreambuf.size(), std::size_t(want_end));
 		boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
 		return std::string(boost::asio::buffers_begin(cbufs) + real_offset,
 						   boost::asio::buffers_begin(cbufs) + real_end);
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 29233d4415..e5d873c8ee 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -1130,7 +1130,7 @@ namespace tut
         set_test_name("setLimit()");
         PythonProcessLauncher py("setLimit()",
                                  "import sys\n"
-                                 "print sys.argv[1]\n");
+                                 "sys.stdout.write(sys.argv[1])\n");
         std::string abc("abcdefghijklmnopqrstuvwxyz");
         py.mParams.args.add(abc);
         py.mParams.files.add(LLProcess::FileParam()); // stdin
@@ -1148,16 +1148,65 @@ namespace tut
         // For all we know, that data could have arrived in several different
         // bursts... probably not, but anyway, only check the last one.
         ensure_equals("event[\"len\"]",
-                      listener.mHistory.back()["len"].asInteger(),
-                      abc.length() + sizeof(EOL) - 1);
+                      listener.mHistory.back()["len"].asInteger(), abc.length());
         ensure_equals("length of setLimit(10) data",
                       listener.mHistory.back()["data"].asString().length(), 10);
     }
 
+    template<> template<>
+    void object::test<19>()
+    {
+        set_test_name("peek() ReadPipe data");
+        PythonProcessLauncher py("peek() ReadPipe",
+                                 "import sys\n"
+                                 "sys.stdout.write(sys.argv[1])\n");
+        std::string abc("abcdefghijklmnopqrstuvwxyz");
+        py.mParams.args.add(abc);
+        py.mParams.files.add(LLProcess::FileParam()); // stdin
+        py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
+        py.launch();
+        LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT));
+        // okay, pump I/O to pick up output from child
+        waitfor(*py.mPy);
+        // peek() with substr args
+        ensure_equals("peek()", childout.peek(), abc);
+        ensure_equals("peek(23)", childout.peek(23), abc.substr(23));
+        ensure_equals("peek(5, 3)", childout.peek(5, 3), abc.substr(5, 3));
+        ensure_equals("peek(27, 2)", childout.peek(27, 2), "");
+        ensure_equals("peek(23, 5)", childout.peek(23, 5), "xyz");
+        // contains() -- we don't exercise as thoroughly as find() because the
+        // contains() implementation is trivially (and visibly) based on find()
+        ensure("contains(\":\")", ! childout.contains(":"));
+        ensure("contains(':')",   ! childout.contains(':'));
+        ensure("contains(\"d\")", childout.contains("d"));
+        ensure("contains('d')",   childout.contains("d"));
+        ensure("contains(\"klm\")", childout.contains("klm"));
+        ensure("contains(\"klx\")", ! childout.contains("klx"));
+        // find()
+        ensure("find(\":\")", childout.find(":") == LLProcess::ReadPipe::npos);
+        ensure("find(':')",   childout.find(':') == LLProcess::ReadPipe::npos);
+        ensure_equals("find(\"d\")", childout.find("d"), 3);
+        ensure_equals("find('d')",   childout.find("d"), 3);
+        ensure_equals("find(\"d\", 3)", childout.find("d", 3), 3);
+        ensure_equals("find('d', 3)",   childout.find("d", 3), 3);
+        ensure("find(\"d\", 4)", childout.find("d", 4) == LLProcess::ReadPipe::npos);
+        ensure("find('d', 4)",   childout.find('d', 4) == LLProcess::ReadPipe::npos);
+        // The case of offset == end and offset > end are different. In the
+        // first case, we can form a valid (albeit empty) iterator range and
+        // search that. In the second, guard logic in the implementation must
+        // realize we can't form a valid iterator range.
+        ensure("find(\"d\", 26)", childout.find("d", 26) == LLProcess::ReadPipe::npos);
+        ensure("find('d', 26)",   childout.find('d', 26) == LLProcess::ReadPipe::npos);
+        ensure("find(\"d\", 27)", childout.find("d", 27) == LLProcess::ReadPipe::npos);
+        ensure("find('d', 27)",   childout.find('d', 27) == LLProcess::ReadPipe::npos);
+        ensure_equals("find(\"ghi\")", childout.find("ghi"), 6);
+        ensure_equals("find(\"ghi\", 6)", childout.find("ghi"), 6);
+        ensure("find(\"ghi\", 7)", childout.find("ghi", 7) == LLProcess::ReadPipe::npos);
+        ensure("find(\"ghi\", 26)", childout.find("ghi", 26) == LLProcess::ReadPipe::npos);
+        ensure("find(\"ghi\", 27)", childout.find("ghi", 27) == LLProcess::ReadPipe::npos);
+    }
+
     // TODO:
     // test EOF -- check logging
-    // test peek() with substr
-    // test contains(char)
-    // test find(string, offset), find(char, offset), offset <, =, > size()
 
 } // namespace tut
-- 
cgit v1.2.3


From d6ed77a598a0009d386ce3cd6c49d0f1c4b422e8 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 16 Feb 2012 17:39:56 -0500
Subject: Attempt to fix Windows link error for LLProcess::BasePipe::npos.

---
 indra/llcommon/llprocess.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 2c6951b562..06be0954c0 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -291,7 +291,7 @@ public:
 	std::string getPipeName(FILESLOT);
 
 	/// base of ReadPipe, WritePipe
-	class BasePipe
+	class LL_COMMON_API BasePipe
 	{
 	public:
 		virtual ~BasePipe() = 0;
-- 
cgit v1.2.3


From f52cf4be7003f18813da31b25d204f10eb36db17 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 16 Feb 2012 21:10:06 -0500
Subject: Fix typos in a few LLProcess::ReadPipe::find() unit tests. The typos
 didn't make for invalid tests, but they made a few tests redundant while
 leaving other (subtly different) cases untested.

---
 indra/llcommon/tests/llprocess_test.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index e5d873c8ee..c67605cc0b 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -1179,16 +1179,16 @@ namespace tut
         ensure("contains(\":\")", ! childout.contains(":"));
         ensure("contains(':')",   ! childout.contains(':'));
         ensure("contains(\"d\")", childout.contains("d"));
-        ensure("contains('d')",   childout.contains("d"));
+        ensure("contains('d')",   childout.contains('d'));
         ensure("contains(\"klm\")", childout.contains("klm"));
         ensure("contains(\"klx\")", ! childout.contains("klx"));
         // find()
         ensure("find(\":\")", childout.find(":") == LLProcess::ReadPipe::npos);
         ensure("find(':')",   childout.find(':') == LLProcess::ReadPipe::npos);
         ensure_equals("find(\"d\")", childout.find("d"), 3);
-        ensure_equals("find('d')",   childout.find("d"), 3);
+        ensure_equals("find('d')",   childout.find('d'), 3);
         ensure_equals("find(\"d\", 3)", childout.find("d", 3), 3);
-        ensure_equals("find('d', 3)",   childout.find("d", 3), 3);
+        ensure_equals("find('d', 3)",   childout.find('d', 3), 3);
         ensure("find(\"d\", 4)", childout.find("d", 4) == LLProcess::ReadPipe::npos);
         ensure("find('d', 4)",   childout.find('d', 4) == LLProcess::ReadPipe::npos);
         // The case of offset == end and offset > end are different. In the
-- 
cgit v1.2.3


From e98438bda70f92c1caa0621b7e467b72c7e484ad Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 18 Feb 2012 12:00:13 -0500
Subject: Fix subtle bug in ReadPipeImpl: wouldn't tolerate multiple instances.
 That is, trying to instantiate a ReadPipeImpl while another already existed
 would throw an LLEventPump::DupPumpName exception. Fortunately this behavior
 is easily bypassed.

---
 indra/llcommon/llprocess.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index add1649ba5..d6a5a18565 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -209,7 +209,7 @@ public:
 		mPipe(pipe),
 		// Essential to initialize our std::istream with our special streambuf!
 		mStream(&mStreambuf),
-		mPump("ReadPipe"),
+		mPump("ReadPipe", true),    // tweak name as needed to avoid collisions
 		// use funky syntax to call max() to avoid blighted max() macros
 		mLimit(npos)
 	{
-- 
cgit v1.2.3


From 8b5d5f9652499103b966524e1c0ceef869e29eeb Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 20 Feb 2012 12:40:38 -0500
Subject: Make LLProcess post termination event to specified pump if desired.
 This way a caller need not spin on isRunning(); we can just listen for the
 requested termination event. Post a similar event containing error message if
 for any reason LLProcess::create() failed to launch the child. Add unit tests
 for both cases.

---
 indra/llcommon/llprocess.cpp            | 118 ++++++++++++++++++++------------
 indra/llcommon/llprocess.h              |  18 ++++-
 indra/llcommon/tests/llprocess_test.cpp |  59 ++++++++++++++++
 3 files changed, 151 insertions(+), 44 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index d6a5a18565..9799ed1938 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -125,7 +125,7 @@ const LLProcess::BasePipe::size_type
 
 class WritePipeImpl: public LLProcess::WritePipe
 {
-    LOG_CLASS(WritePipeImpl);
+	LOG_CLASS(WritePipeImpl);
 public:
 	WritePipeImpl(const std::string& desc, apr_file_t* pipe):
 		mDesc(desc),
@@ -202,7 +202,7 @@ private:
 
 class ReadPipeImpl: public LLProcess::ReadPipe
 {
-    LOG_CLASS(ReadPipeImpl);
+	LOG_CLASS(ReadPipeImpl);
 public:
 	ReadPipeImpl(const std::string& desc, apr_file_t* pipe):
 		mDesc(desc),
@@ -394,6 +394,23 @@ LLProcessPtr LLProcess::create(const LLSDOrParams& params)
 	catch (const LLProcessError& e)
 	{
 		LL_WARNS("LLProcess") << e.what() << LL_ENDL;
+
+		// If caller is requesting an event on process termination, send one
+		// indicating bad launch. This may prevent someone waiting forever for
+		// a termination post that can't arrive because the child never
+		// started.
+		if (! std::string(params.postend).empty())
+		{
+			LLEventPumps::instance().obtain(params.postend)
+				.post(LLSDMap
+					  // no "id"
+					  ("desc", std::string(params.executable))
+					  ("state", LLProcess::UNSTARTED)
+					  // no "data"
+					  ("string", e.what())
+					 );
+		}
+
 		return LLProcessPtr();
 	}
 }
@@ -425,6 +442,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 									   << LLSDNotationStreamer(params)));
 	}
 
+	mPostend = params.postend;
+
 	apr_procattr_t *procattr = NULL;
 	chkapr(apr_procattr_create(&procattr, gAPRPoolp));
 
@@ -744,6 +763,19 @@ void LLProcess::handle_status(int reason, int status)
 	// hand.
 	mStatus = interpret_status(status);
 	LL_INFOS("LLProcess") << getStatusString() << LL_ENDL;
+
+	// If caller requested notification on child termination, send it.
+	if (! mPostend.empty())
+	{
+		LLEventPumps::instance().obtain(mPostend)
+			.post(LLSDMap
+				  ("id",     getProcessID())
+				  ("desc",   mDesc)
+				  ("state",  mStatus.mState)
+				  ("data",   mStatus.mData)
+				  ("string", getStatusString())
+				 );
+	}
 }
 
 LLProcess::id LLProcess::getProcessID() const
@@ -769,72 +801,72 @@ std::string LLProcess::getPipeName(FILESLOT)
 template<class PIPETYPE>
 PIPETYPE* LLProcess::getPipePtr(std::string& error, FILESLOT slot)
 {
-    if (slot >= NSLOTS)
-    {
-        error = STRINGIZE(mDesc << " has no slot " << slot);
-        return NULL;
-    }
-    if (mPipes.is_null(slot))
-    {
-        error = STRINGIZE(mDesc << ' ' << whichfile[slot] << " not a monitored pipe");
-        return NULL;
-    }
-    // Make sure we dynamic_cast in pointer domain so we can test, rather than
-    // accepting runtime's exception.
-    PIPETYPE* ppipe = dynamic_cast<PIPETYPE*>(&mPipes[slot]);
-    if (! ppipe)
-    {
-        error = STRINGIZE(mDesc << ' ' << whichfile[slot] << " not a " << typeid(PIPETYPE).name());
-        return NULL;
-    }
-
-    error.clear();
-    return ppipe;
+	if (slot >= NSLOTS)
+	{
+		error = STRINGIZE(mDesc << " has no slot " << slot);
+		return NULL;
+	}
+	if (mPipes.is_null(slot))
+	{
+		error = STRINGIZE(mDesc << ' ' << whichfile[slot] << " not a monitored pipe");
+		return NULL;
+	}
+	// Make sure we dynamic_cast in pointer domain so we can test, rather than
+	// accepting runtime's exception.
+	PIPETYPE* ppipe = dynamic_cast<PIPETYPE*>(&mPipes[slot]);
+	if (! ppipe)
+	{
+		error = STRINGIZE(mDesc << ' ' << whichfile[slot] << " not a " << typeid(PIPETYPE).name());
+		return NULL;
+	}
+
+	error.clear();
+	return ppipe;
 }
 
 template <class PIPETYPE>
 PIPETYPE& LLProcess::getPipe(FILESLOT slot)
 {
-    std::string error;
-    PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
-    if (! wp)
-    {
-        throw NoPipe(error);
-    }
-    return *wp;
+	std::string error;
+	PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
+	if (! wp)
+	{
+		throw NoPipe(error);
+	}
+	return *wp;
 }
 
 template <class PIPETYPE>
 boost::optional<PIPETYPE&> LLProcess::getOptPipe(FILESLOT slot)
 {
-    std::string error;
-    PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
-    if (! wp)
-    {
-        LL_DEBUGS("LLProcess") << error << LL_ENDL;
-        return boost::optional<PIPETYPE&>();
-    }
-    return *wp;
+	std::string error;
+	PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
+	if (! wp)
+	{
+		LL_DEBUGS("LLProcess") << error << LL_ENDL;
+		return boost::optional<PIPETYPE&>();
+	}
+	return *wp;
 }
 
 LLProcess::WritePipe& LLProcess::getWritePipe(FILESLOT slot)
 {
-    return getPipe<WritePipe>(slot);
+	return getPipe<WritePipe>(slot);
 }
 
 boost::optional<LLProcess::WritePipe&> LLProcess::getOptWritePipe(FILESLOT slot)
 {
-    return getOptPipe<WritePipe>(slot);
+	return getOptPipe<WritePipe>(slot);
 }
 
 LLProcess::ReadPipe& LLProcess::getReadPipe(FILESLOT slot)
 {
-    return getPipe<ReadPipe>(slot);
+	return getPipe<ReadPipe>(slot);
 }
 
 boost::optional<LLProcess::ReadPipe&> LLProcess::getOptReadPipe(FILESLOT slot)
 {
-    return getOptPipe<ReadPipe>(slot);
+	return getOptPipe<ReadPipe>(slot);
 }
 
 std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
@@ -932,7 +964,7 @@ static std::string WindowsErrorString(const std::string& operation)
 					   NULL)
 		!= 0) 
 	{
-        // convert from wide-char string to multi-byte string
+		// convert from wide-char string to multi-byte string
 		char message[256];
 		wcstombs(message, error_str, sizeof(message));
 		message[sizeof(message)-1] = 0;
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 06be0954c0..96a3dce5b3 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -158,7 +158,8 @@ public:
 			args("args"),
 			cwd("cwd"),
 			autokill("autokill", true),
-			files("files")
+			files("files"),
+			postend("postend")
 		{}
 
 		/// pathname of executable
@@ -184,6 +185,20 @@ public:
 		 * underlying implementation library doesn't support that.
 		 */
 		Multiple<FileParam> files;
+		/**
+		 * On child-process termination, if this LLProcess object still
+		 * exists, post LLSD event to LLEventPump with specified name (default
+		 * no event). Event contains at least:
+		 *
+		 * - "id" as obtained from getProcessID()
+		 * - "desc" short string description of child (executable + pid)
+		 * - "state" @c state enum value, from Status.mState
+		 * - "data"	 if "state" is EXITED, exit code; if KILLED, on Posix,
+		 *   signal number
+		 * - "string" English text describing "state" and "data" (e.g. "exited
+		 *   with code 0")
+		 */
+		Optional<std::string> postend;
 	};
 	typedef LLSDParamAdapter<Params> LLSDOrParams;
 
@@ -462,6 +477,7 @@ private:
 	PIPETYPE* getPipePtr(std::string& error, FILESLOT slot);
 
 	std::string mDesc;
+	std::string mPostend;
 	apr_proc_t mProcess;
 	bool mAutokill;
 	Status mStatus;
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index c67605cc0b..1a755c283c 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -1206,6 +1206,65 @@ namespace tut
         ensure("find(\"ghi\", 27)", childout.find("ghi", 27) == LLProcess::ReadPipe::npos);
     }
 
+    template<> template<>
+    void object::test<20>()
+    {
+        set_test_name("good postend");
+        PythonProcessLauncher py("postend",
+                                 "import sys\n"
+                                 "sys.exit(35)\n");
+        std::string pumpname("postend");
+        EventListener listener(LLEventPumps::instance().obtain(pumpname));
+        py.mParams.postend = pumpname;
+        py.launch();
+        LLProcess::id childid(py.mPy->getProcessID());
+        // Don't use waitfor(), which calls isRunning(); instead wait for an
+        // event on pumpname.
+        int i, timeout = 60;
+        for (i = 0; i < timeout && listener.mHistory.empty(); ++i)
+        {
+            yield();
+        }
+        ensure("no postend event", i < timeout);
+        ensure_equals("number of postend events", listener.mHistory.size(), 1);
+        LLSD postend(listener.mHistory.front());
+        ensure_equals("id",    postend["id"].asInteger(), childid);
+        ensure("desc empty", ! postend["desc"].asString().empty());
+        ensure_equals("state", postend["state"].asInteger(), LLProcess::EXITED);
+        ensure_equals("data",  postend["data"].asInteger(),  35);
+        std::string str(postend["string"]);
+        ensure_contains("string", str, "exited");
+        ensure_contains("string", str, "35");
+    }
+
+    template<> template<>
+    void object::test<21>()
+    {
+        set_test_name("bad postend");
+        std::string pumpname("postend");
+        EventListener listener(LLEventPumps::instance().obtain(pumpname));
+        LLProcess::Params params;
+        params.postend = pumpname;
+        LLProcessPtr child = LLProcess::create(params);
+        ensure("shouldn't have launched", ! child);
+        ensure_equals("number of postend events", listener.mHistory.size(), 1);
+        LLSD postend(listener.mHistory.front());
+        ensure("has id", ! postend.has("id"));
+        // Ha ha, in this case the implementation normally sets "desc" to
+        // params.executable. But as the nature of the problem is that
+        // params.executable is empty, expecting "desc" to be nonempty is a
+        // bit unreasonable!
+        //ensure("desc empty", ! postend["desc"].asString().empty());
+        ensure_equals("state", postend["state"].asInteger(), LLProcess::UNSTARTED);
+        ensure("has data", ! postend.has("data"));
+        std::string error(postend["string"]);
+        // All we get from canned parameter validation is a bool, so the
+        // "validation failed" message we ourselves generate can't mention
+        // "executable" by name. Just check that it's nonempty.
+        //ensure_contains("error", error, "executable");
+        ensure("string", ! error.empty());
+    }
+
     // TODO:
     // test EOF -- check logging
 
-- 
cgit v1.2.3


From 999484a60896b11df1af9a44e58ccae6fa6ecbed Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 20 Feb 2012 14:22:32 -0500
Subject: Let LLProcess consumer specify desired description for logging. If
 caller runs (e.g.) a Python script, it's not very helpful to a human log
 reader to keep seeing LLProcess instances logged as /pathname/to/python
 (pid). If caller is aware, the code can at least use the script name as the
 desc -- or maybe even a hint as to the script's purpose. If caller doesn't
 explicitly pass a desc, at least shorten to just the basename of the
 executable.

---
 indra/llcommon/llprocess.cpp            | 30 +++++++++++++++++++++++++++---
 indra/llcommon/llprocess.h              | 10 +++++++++-
 indra/llcommon/tests/llprocess_test.cpp |  8 +++-----
 3 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 9799ed1938..b4c6a647d7 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -50,6 +50,7 @@
 static const char* whichfile[] = { "stdin", "stdout", "stderr" };
 static std::string empty;
 static LLProcess::Status interpret_status(int status);
+static std::string getDesc(const LLProcess::Params& params);
 
 /**
  * Ref-counted "mainloop" listener. As long as there are still outstanding
@@ -404,7 +405,7 @@ LLProcessPtr LLProcess::create(const LLSDOrParams& params)
 			LLEventPumps::instance().obtain(params.postend)
 				.post(LLSDMap
 					  // no "id"
-					  ("desc", std::string(params.executable))
+					  ("desc", getDesc(params))
 					  ("state", LLProcess::UNSTARTED)
 					  // no "data"
 					  ("string", e.what())
@@ -561,8 +562,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 	sProcessListener.addPoll(*this);
 	mStatus.mState = RUNNING;
 
-	mDesc = STRINGIZE(LLStringUtil::quote(params.executable) << " (" << mProcess.pid << ')');
-	LL_INFOS("LLProcess") << "Launched " << params << " (" << mProcess.pid << ")" << LL_ENDL;
+	mDesc = STRINGIZE(getDesc(params) << " (" << mProcess.pid << ')');
+	LL_INFOS("LLProcess") << mDesc << ": launched " << params << LL_ENDL;
 
 	// Unless caller explicitly turned off autokill (child should persist),
 	// take steps to terminate the child. This is all suspenders-and-belt: in
@@ -604,6 +605,29 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 	}
 }
 
+// Helper to obtain a description string, given a Params block
+static std::string getDesc(const LLProcess::Params& params)
+{
+	// If caller specified a description string, by all means use it.
+	std::string desc(params.desc);
+	if (! desc.empty())
+		return desc;
+
+	// Caller didn't say. Use the executable name -- but use just the filename
+	// part. On Mac, for instance, full pathnames get cumbersome.
+	// If there are Linden utility functions to manipulate pathnames, I
+	// haven't found them -- and for this usage, Boost.Filesystem seems kind
+	// of heavyweight.
+	std::string executable(params.executable);
+	std::string::size_type delim = executable.find_last_of("\\/");
+	// If executable contains no pathname delimiters, return the whole thing.
+	if (delim == std::string::npos)
+		return executable;
+
+	// Return just the part beyond the last delimiter.
+	return executable.substr(delim + 1);
+}
+
 LLProcess::~LLProcess()
 {
 	// Only in state RUNNING are we registered for callback. In UNSTARTED we
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 96a3dce5b3..d005847e18 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -159,7 +159,8 @@ public:
 			cwd("cwd"),
 			autokill("autokill", true),
 			files("files"),
-			postend("postend")
+			postend("postend"),
+			desc("desc")
 		{}
 
 		/// pathname of executable
@@ -199,6 +200,13 @@ public:
 		 *   with code 0")
 		 */
 		Optional<std::string> postend;
+		/**
+		 * Description of child process for logging purposes. It need not be
+		 * unique; the logged description string will contain the PID as well.
+		 * If this is omitted, a description will be derived from the
+		 * executable name.
+		 */
+		Optional<std::string> desc;
 	};
 	typedef LLSDParamAdapter<Params> LLSDOrParams;
 
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 1a755c283c..fe599e7892 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -136,6 +136,7 @@ struct PythonProcessLauncher
         const char* PYTHON(getenv("PYTHON"));
         tut::ensure("Set $PYTHON to the Python interpreter", PYTHON);
 
+        mParams.desc = desc + " script";
         mParams.executable = PYTHON;
         mParams.args.add(mScript.getName());
     }
@@ -1244,17 +1245,14 @@ namespace tut
         std::string pumpname("postend");
         EventListener listener(LLEventPumps::instance().obtain(pumpname));
         LLProcess::Params params;
+        params.desc = "bad postend";
         params.postend = pumpname;
         LLProcessPtr child = LLProcess::create(params);
         ensure("shouldn't have launched", ! child);
         ensure_equals("number of postend events", listener.mHistory.size(), 1);
         LLSD postend(listener.mHistory.front());
         ensure("has id", ! postend.has("id"));
-        // Ha ha, in this case the implementation normally sets "desc" to
-        // params.executable. But as the nature of the problem is that
-        // params.executable is empty, expecting "desc" to be nonempty is a
-        // bit unreasonable!
-        //ensure("desc empty", ! postend["desc"].asString().empty());
+        ensure_equals("desc", postend["desc"].asString(), std::string(params.desc));
         ensure_equals("state", postend["state"].asInteger(), LLProcess::UNSTARTED);
         ensure("has data", ! postend.has("data"));
         std::string error(postend["string"]);
-- 
cgit v1.2.3


From 14ddc6474a0ae83db8d034b00138289fb15e41b7 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 23 Feb 2012 13:41:26 -0500
Subject: Tighten up LLProcess pipe support, per Richard's code review. Clarify
 wording in some of the doc comments; be a bit more explicit about some of the
 parameter fields. Make some query methods 'const'. Change default
 LLProcess::ReadPipe::getLimit() value to 0: don't post any incoming data with
 notification event unless caller requests it. But do post pertinent FILESLOT
 in case caller reuses same listener for both stdout and stderr. Use more
 idiomatic, readable syntax for accessing LLProcess::Params data.

---
 indra/llcommon/llprocess.cpp            | 119 +++++++++++++++++++-------------
 indra/llcommon/llprocess.h              |  63 +++++++++++------
 indra/llcommon/tests/llprocess_test.cpp |   4 +-
 3 files changed, 116 insertions(+), 70 deletions(-)

diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index b4c6a647d7..3b17b819bd 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -47,11 +47,18 @@
 #include <typeinfo>
 #include <utility>
 
-static const char* whichfile[] = { "stdin", "stdout", "stderr" };
+static const char* whichfile_[] = { "stdin", "stdout", "stderr" };
 static std::string empty;
 static LLProcess::Status interpret_status(int status);
 static std::string getDesc(const LLProcess::Params& params);
 
+static std::string whichfile(LLProcess::FILESLOT index)
+{
+	if (index < LL_ARRAY_SIZE(whichfile_))
+		return whichfile_[index];
+	return STRINGIZE("file slot " << index);
+}
+
 /**
  * Ref-counted "mainloop" listener. As long as there are still outstanding
  * LLProcess objects, keep listening on "mainloop" so we can keep polling APR
@@ -122,6 +129,7 @@ static LLProcessListener sProcessListener;
 
 LLProcess::BasePipe::~BasePipe() {}
 const LLProcess::BasePipe::size_type
+	  // use funky syntax to call max() to avoid blighted max() macros
 	  LLProcess::BasePipe::npos((std::numeric_limits<LLProcess::BasePipe::size_type>::max)());
 
 class WritePipeImpl: public LLProcess::WritePipe
@@ -205,14 +213,14 @@ class ReadPipeImpl: public LLProcess::ReadPipe
 {
 	LOG_CLASS(ReadPipeImpl);
 public:
-	ReadPipeImpl(const std::string& desc, apr_file_t* pipe):
+	ReadPipeImpl(const std::string& desc, apr_file_t* pipe, LLProcess::FILESLOT index):
 		mDesc(desc),
 		mPipe(pipe),
+		mIndex(index),
 		// Essential to initialize our std::istream with our special streambuf!
 		mStream(&mStreambuf),
 		mPump("ReadPipe", true),    // tweak name as needed to avoid collisions
-		// use funky syntax to call max() to avoid blighted max() macros
-		mLimit(npos)
+		mLimit(0)
 	{
 		mConnection = LLEventPumps::instance().obtain("mainloop")
 			.listen(LLEventPump::inventName("ReadPipe"),
@@ -364,7 +372,10 @@ private:
 			size_type datasize((std::min)(mLimit, size_type(mStreambuf.size())));
 			mPump.post(LLSDMap
 					   ("data", peek(0, datasize))
-					   ("len", LLSD::Integer(mStreambuf.size())));
+					   ("len", LLSD::Integer(mStreambuf.size()))
+					   ("index", LLSD::Integer(mIndex))
+					   ("name", whichfile(mIndex))
+					   ("desc", mDesc));
 		}
 
 		return false;
@@ -372,6 +383,7 @@ private:
 
 	std::string mDesc;
 	apr_file_t* mPipe;
+	LLProcess::FILESLOT mIndex;
 	LLTempBoundListener mConnection;
 	boost::asio::streambuf mStreambuf;
 	std::istream mStream;
@@ -400,7 +412,7 @@ LLProcessPtr LLProcess::create(const LLSDOrParams& params)
 		// indicating bad launch. This may prevent someone waiting forever for
 		// a termination post that can't arrive because the child never
 		// started.
-		if (! std::string(params.postend).empty())
+		if (params.postend.isProvided())
 		{
 			LLEventPumps::instance().obtain(params.postend)
 				.post(LLSDMap
@@ -458,22 +470,24 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 	// and passing it as both stdout and stderr (apr_procattr_child_out_set(),
 	// apr_procattr_child_err_set()), or accepting a filename, opening it and
 	// passing that apr_file_t (simple <, >, 2> redirect emulation).
-	std::vector<FileParam> fparams(params.files.begin(), params.files.end());
-	// By default, pass APR_NO_PIPE for each slot.
-	std::vector<apr_int32_t> select(LL_ARRAY_SIZE(whichfile), APR_NO_PIPE);
-	for (size_t i = 0; i < (std::min)(LL_ARRAY_SIZE(whichfile), fparams.size()); ++i)
+	std::vector<apr_int32_t> select;
+	BOOST_FOREACH(const FileParam& fparam, params.files)
 	{
-		if (std::string(fparams[i].type).empty()) // inherit our file descriptor
+		// Every iteration, we're going to append an item to 'select'. At the
+		// top of the loop, its size() is, in effect, an index. Use that to
+		// pick a string description for messages.
+		std::string which(whichfile(FILESLOT(select.size())));
+		if (fparam.type().empty())  // inherit our file descriptor
 		{
-			select[i] = APR_NO_PIPE;
+			select.push_back(APR_NO_PIPE);
 		}
-		else if (std::string(fparams[i].type) == "pipe") // anonymous pipe
+		else if (fparam.type() == "pipe") // anonymous pipe
 		{
-			if (! std::string(fparams[i].name).empty())
+			if (! fparam.name().empty())
 			{
-				LL_WARNS("LLProcess") << "For " << std::string(params.executable)
+				LL_WARNS("LLProcess") << "For " << params.executable()
 									  << ": internal names for reusing pipes ('"
-									  << std::string(fparams[i].name) << "' for " << whichfile[i]
+									  << fparam.name() << "' for " << which
 									  << ") are not yet supported -- creating distinct pipe"
 									  << LL_ENDL;
 			}
@@ -482,16 +496,21 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 			// makes very little sense to set nonblocking I/O for the child
 			// end of a pipe: only a specially-written child could deal with
 			// that.
-			select[i] = APR_CHILD_BLOCK;
+			select.push_back(APR_CHILD_BLOCK);
 		}
 		else
 		{
-			throw LLProcessError(STRINGIZE("For " << std::string(params.executable)
-										   << ": unsupported FileParam for " << whichfile[i]
-										   << ": type='" << std::string(fparams[i].type)
-										   << "', name='" << std::string(fparams[i].name) << "'"));
+			throw LLProcessError(STRINGIZE("For " << params.executable()
+										   << ": unsupported FileParam for " << which
+										   << ": type='" << fparam.type()
+										   << "', name='" << fparam.name() << "'"));
 		}
 	}
+	// By default, pass APR_NO_PIPE for unspecified slots.
+	while (select.size() < NSLOTS)
+	{
+		select.push_back(APR_NO_PIPE);
+	}
 	chkapr(apr_procattr_io_set(procattr, select[STDIN], select[STDOUT], select[STDERR]));
 
 	// Thumbs down on implicitly invoking the shell to invoke the child. From
@@ -527,24 +546,32 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 #endif
 	}
 
-	// Have to instantiate named std::strings for string params items so their
-	// c_str() values persist.
-	std::string cwd(params.cwd);
-	if (! cwd.empty())
+	// In preparation for calling apr_proc_create(), we collect a number of
+	// const char* pointers obtained from std::string::c_str(). Turns out
+	// LLInitParam::Block's helpers Optional, Mandatory, Multiple et al.
+	// guarantee that converting to the wrapped type (std::string in our
+	// case), e.g. by calling operator(), returns a reference to *the same
+	// instance* of the wrapped type that's stored in our Block subclass.
+	// That's important! We know 'params' persists throughout this method
+	// call; but without that guarantee, we'd have to assume that converting
+	// one of its members to std::string might return a different (temp)
+	// instance. Capturing the c_str() from a temporary std::string is Bad Bad
+	// Bad. But armed with this knowledge, when you see params.cwd().c_str(),
+	// grit your teeth and smile and carry on.
+
+	if (params.cwd.isProvided())
 	{
-		chkapr(apr_procattr_dir_set(procattr, cwd.c_str()));
+		chkapr(apr_procattr_dir_set(procattr, params.cwd().c_str()));
 	}
 
 	// create an argv vector for the child process
 	std::vector<const char*> argv;
 
-	// add the executable path
-	std::string executable(params.executable);
-	argv.push_back(executable.c_str());
+	// Add the executable path. See above remarks about c_str().
+	argv.push_back(params.executable().c_str());
 
-	// and any arguments
-	std::vector<std::string> args(params.args.begin(), params.args.end());
-	BOOST_FOREACH(const std::string& arg, args)
+	// Add arguments. See above remarks about c_str().
+	BOOST_FOREACH(const std::string& arg, params.args)
 	{
 		argv.push_back(arg.c_str());
 	}
@@ -590,7 +617,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 	{
 		if (select[i] != APR_CHILD_BLOCK)
 			continue;
-		std::string desc(STRINGIZE(mDesc << ' ' << whichfile[i]));
+		std::string desc(STRINGIZE(mDesc << ' ' << whichfile(FILESLOT(i))));
 		apr_file_t* pipe(mProcess.*(members[i]));
 		if (i == STDIN)
 		{
@@ -598,7 +625,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 		}
 		else
 		{
-			mPipes.replace(i, new ReadPipeImpl(desc, pipe));
+			mPipes.replace(i, new ReadPipeImpl(desc, pipe, FILESLOT(i)));
 		}
 		LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name()
 							   << "('" << desc << "')" << LL_ENDL;
@@ -609,9 +636,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 static std::string getDesc(const LLProcess::Params& params)
 {
 	// If caller specified a description string, by all means use it.
-	std::string desc(params.desc);
-	if (! desc.empty())
-		return desc;
+	if (params.desc.isProvided())
+		return params.desc;
 
 	// Caller didn't say. Use the executable name -- but use just the filename
 	// part. On Mac, for instance, full pathnames get cumbersome.
@@ -670,22 +696,22 @@ bool LLProcess::kill(const std::string& who)
 	return ! isRunning();
 }
 
-bool LLProcess::isRunning(void)
+bool LLProcess::isRunning() const
 {
 	return getStatus().mState == RUNNING;
 }
 
-LLProcess::Status LLProcess::getStatus()
+LLProcess::Status LLProcess::getStatus() const
 {
 	return mStatus;
 }
 
-std::string LLProcess::getStatusString()
+std::string LLProcess::getStatusString() const
 {
 	return getStatusString(getStatus());
 }
 
-std::string LLProcess::getStatusString(const Status& status)
+std::string LLProcess::getStatusString(const Status& status) const
 {
 	return getStatusString(mDesc, status);
 }
@@ -816,7 +842,7 @@ LLProcess::handle LLProcess::getProcessHandle() const
 #endif
 }
 
-std::string LLProcess::getPipeName(FILESLOT)
+std::string LLProcess::getPipeName(FILESLOT) const
 {
 	// LLProcess::FileParam::type "npipe" is not yet implemented
 	return "";
@@ -832,7 +858,7 @@ PIPETYPE* LLProcess::getPipePtr(std::string& error, FILESLOT slot)
 	}
 	if (mPipes.is_null(slot))
 	{
-		error = STRINGIZE(mDesc << ' ' << whichfile[slot] << " not a monitored pipe");
+		error = STRINGIZE(mDesc << ' ' << whichfile(slot) << " not a monitored pipe");
 		return NULL;
 	}
 	// Make sure we dynamic_cast in pointer domain so we can test, rather than
@@ -840,7 +866,7 @@ PIPETYPE* LLProcess::getPipePtr(std::string& error, FILESLOT slot)
 	PIPETYPE* ppipe = dynamic_cast<PIPETYPE*>(&mPipes[slot]);
 	if (! ppipe)
 	{
-		error = STRINGIZE(mDesc << ' ' << whichfile[slot] << " not a " << typeid(PIPETYPE).name());
+		error = STRINGIZE(mDesc << ' ' << whichfile(slot) << " not a " << typeid(PIPETYPE).name());
 		return NULL;
 	}
 
@@ -895,10 +921,9 @@ boost::optional<LLProcess::ReadPipe&> LLProcess::getOptReadPipe(FILESLOT slot)
 
 std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
 {
-	std::string cwd(params.cwd);
-	if (! cwd.empty())
+	if (params.cwd.isProvided())
 	{
-		out << "cd " << LLStringUtil::quote(cwd) << ": ";
+		out << "cd " << LLStringUtil::quote(params.cwd) << ": ";
 	}
 	out << LLStringUtil::quote(params.executable);
 	BOOST_FOREACH(const std::string& arg, params.args)
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index d005847e18..637b7e2f9c 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -58,12 +58,16 @@ typedef boost::shared_ptr<LLProcess> LLProcessPtr;
  * arguments. It also keeps track of whether the process is still running, and
  * can kill it if required.
  *
+ * In discussing LLProcess, we use the term "parent" to refer to this process
+ * (the process invoking LLProcess), versus "child" to refer to the process
+ * spawned by LLProcess.
+ *
  * LLProcess relies on periodic post() calls on the "mainloop" LLEventPump: an
- * LLProcess object's Status won't update until the next "mainloop" tick. The
- * viewer's main loop already posts to that LLEventPump once per iteration
- * (hence the name). See indra/llcommon/tests/llprocess_test.cpp for an
- * example of waiting for child-process termination in a standalone test
- * context.
+ * LLProcess object's Status won't update until the next "mainloop" tick. For
+ * instance, the Second Life viewer's main loop already posts to an
+ * LLEventPump by that name once per iteration. See
+ * indra/llcommon/tests/llprocess_test.cpp for an example of waiting for
+ * child-process termination in a standalone test context.
  */
 class LL_COMMON_API LLProcess: public boost::noncopyable
 {
@@ -110,10 +114,10 @@ public:
 		 *     pumping nonblocking I/O every frame. The expectation (at least
 		 *     for stdout or stderr) is that the caller will listen for
 		 *     incoming data and consume it as it arrives. It's important not
-		 *     to neglect such a pipe, because it's buffered in viewer memory.
-		 *     If you suspect the child may produce a great volume of output
-		 *     between viewer frames, consider directing the child to write to
-		 *     a filesystem file instead, then read the file later.
+		 *     to neglect such a pipe, because it's buffered in memory. If you
+		 *     suspect the child may produce a great volume of output between
+		 *     frames, consider directing the child to write to a filesystem
+		 *     file instead, then read the file later.
 		 *
 		 *   - "tpipe": do not engage LLProcess machinery to monitor the
 		 *     parent end of the pipe. A "tpipe" is used only to connect
@@ -145,9 +149,14 @@ public:
 		Optional<std::string> name;
 
 		FileParam(const std::string& tp="", const std::string& nm=""):
-			type("type", tp),
-			name("name", nm)
-		{}
+			type("type"),
+			name("name")
+		{
+			// If caller wants to specify values, use explicit assignment to
+			// set them rather than initialization.
+			if (! tp.empty()) type = tp;
+			if (! nm.empty()) name = nm;
+        }
 	};
 
 	/// Param block definition
@@ -175,17 +184,28 @@ public:
 		/// current working directory, if need it changed
 		Optional<std::string> cwd;
 		/// implicitly kill process on destruction of LLProcess object
+		/// (default true)
 		Optional<bool> autokill;
 		/**
 		 * Up to three FileParam items: for child stdin, stdout, stderr.
 		 * Passing two FileParam entries means default treatment for stderr,
 		 * and so forth.
 		 *
+		 * @note LLInitParam::Block permits usage like this:
+		 * @code
+		 * LLProcess::Params params;
+		 * ...
+		 * params.files
+		 *     .add(LLProcess::FileParam()) // stdin
+		 *     .add(LLProcess::FileParam().type("pipe") // stdout
+		 *     .add(LLProcess::FileParam().type("file").name("error.log"));
+		 * @endcode
+		 *
 		 * @note While it's theoretically plausible to pass additional open
 		 * file handles to a child specifically written to expect them, our
-		 * underlying implementation library doesn't support that.
+		 * underlying implementation doesn't yet support that.
 		 */
-		Multiple<FileParam> files;
+		Multiple<FileParam, AtMost<3> > files;
 		/**
 		 * On child-process termination, if this LLProcess object still
 		 * exists, post LLSD event to LLEventPump with specified name (default
@@ -217,9 +237,8 @@ public:
 	static LLProcessPtr create(const LLSDOrParams& params);
 	virtual ~LLProcess();
 
-	// isRunning() isn't const because, when child terminates, it sets stored
-	// Status
-	bool isRunning(void);
+	/// Is child process still running?
+	bool isRunning() const;
 
 	/**
 	 * State of child process
@@ -252,11 +271,11 @@ public:
 	};
 
 	/// Status query
-	Status getStatus();
+	Status getStatus() const;
 	/// English Status string query, for logging etc.
-	std::string getStatusString();
+	std::string getStatusString() const;
 	/// English Status string query for previously-captured Status
-	std::string getStatusString(const Status& status);
+	std::string getStatusString(const Status& status) const;
 	/// static English Status string query
 	static std::string getStatusString(const std::string& desc, const Status& status);
 
@@ -311,7 +330,7 @@ public:
 	 * filesystem name for the specified pipe. Otherwise returns the empty
 	 * string. @see LLProcess::FileParam::type
 	 */
-	std::string getPipeName(FILESLOT);
+	std::string getPipeName(FILESLOT) const;
 
 	/// base of ReadPipe, WritePipe
 	class LL_COMMON_API BasePipe
@@ -419,7 +438,7 @@ public:
 		 * contain "data"="abcde". However, you may still read the entire
 		 * "abcdef" from get_istream(): this limit affects only the size of
 		 * the data posted with the LLSD event. If you don't call this method,
-		 * all pending data will be posted.
+		 * @em no data will be posted: the default is 0 bytes.
 		 */
 		virtual void setLimit(size_type limit) = 0;
 
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index fe599e7892..d7feddd26b 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -696,7 +696,7 @@ namespace tut
                                  "syntax_error:\n");
         py.mParams.files.add(LLProcess::FileParam()); // inherit stdin
         py.mParams.files.add(LLProcess::FileParam()); // inherit stdout
-        py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stderr
+        py.mParams.files.add(LLProcess::FileParam().type("pipe")); // pipe for stderr
         py.run();
         ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED);
         ensure_equals("Status.mData",  py.mPy->getStatus().mData,  1);
@@ -1088,6 +1088,8 @@ namespace tut
         py.launch();
         std::ostream& childin(py.mPy->getWritePipe(LLProcess::STDIN).get_ostream());
         LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT));
+        // lift the default limit; allow event to carry (some of) the actual data
+        childout.setLimit(20);
         // listen for incoming data on childout
         EventListener listener(childout.getPump());
         // also listen with a function that prompts the child to continue
-- 
cgit v1.2.3


From 025329b6a2ecb8ddee3022d6a73344f862f0d326 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 24 Feb 2012 15:06:44 -0500
Subject: Add LLStringUtil::getTokens() overload handling quoted substrings. We
 didn't have any tokenizer suitable for scanning something like a bash command
 line. We do have a couple hacks, e.g. LLExternalEditor::tokenize() and
 LLCommandLineParser::parseCommandLineString(). Both try to work around
 boost::tokenizer limitations; but existing boost::tokenizer support just
 doesn't address this case. Neither of the above is available as a general
 scanner anyway, and parseCommandLineString() fails outright when passed "".
 New getTokens() also distinguishes between "drop delimiters" (e.g. space,
 return, newline) to be discarded from the token stream, versus "keep
 delimiters" (e.g. "+-*/") to be returned as tokens in their own right.
 There's an overload that honors escapes and a more efficient one that
 doesn't; each has a convenience overload that returns the scanned string
 vector rather than requiring a separate declaration. Tweak and comment older
 getTokens() implementation. Add unit tests for both old and new getTokens()
 implementations. Break out StringVec and std::ostream << StringVec from
 indra/llcommon/tests/listener.h to StringVec.h: that's coming in handy for a
 number of different TUT test sources.

---
 indra/llcommon/llstring.cpp            |  16 +-
 indra/llcommon/llstring.h              | 355 ++++++++++++++++++++++++++++++++-
 indra/llcommon/tests/StringVec.h       |  37 ++++
 indra/llcommon/tests/listener.h        |  21 +-
 indra/llcommon/tests/llstring_test.cpp | 115 +++++++++++
 5 files changed, 517 insertions(+), 27 deletions(-)
 create mode 100644 indra/llcommon/tests/StringVec.h

diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index e7fe656808..fa0eb9f72c 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -912,22 +912,24 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions);
 template<> 
 void LLStringUtil::getTokens(const std::string& instr, std::vector<std::string >& tokens, const std::string& delims)
 {
-	std::string currToken;
-	std::string::size_type begIdx, endIdx;
-
-	begIdx = instr.find_first_not_of (delims);
-	while (begIdx != std::string::npos)
+	// Starting at offset 0, scan forward for the next non-delimiter. We're
+	// done when the only characters left in 'instr' are delimiters.
+	for (std::string::size_type begIdx, endIdx = 0;
+		 (begIdx = instr.find_first_not_of (delims, endIdx)) != std::string::npos; )
 	{
+		// Found a non-delimiter. After that, find the next delimiter.
 		endIdx = instr.find_first_of (delims, begIdx);
 		if (endIdx == std::string::npos)
 		{
+			// No more delimiters: this token extends to the end of the string.
 			endIdx = instr.length();
 		}
 
-		currToken = instr.substr(begIdx, endIdx - begIdx);
+		// extract the token between begIdx and endIdx; substr() needs length
+		std::string currToken(instr.substr(begIdx, endIdx - begIdx));
 		LLStringUtil::trim (currToken);
 		tokens.push_back(currToken);
-		begIdx = instr.find_first_not_of (delims, endIdx);
+		// next scan past delimiters starts at endIdx
 	}
 }
 
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 7b24b5e279..e4ae54cec5 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -40,6 +40,7 @@
 #endif
 
 #include <string.h>
+#include <boost/scoped_ptr.hpp>
 
 #if LL_SOLARIS
 // stricmp and strnicmp do not exist on Solaris:
@@ -247,7 +248,38 @@ public:
 	static const string_type null;
 	
 	typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
-	LL_COMMON_API static void getTokens(const string_type& instr, std::vector<string_type >& tokens, const string_type& delims);
+	/// considers any sequence of delims as a single field separator
+	LL_COMMON_API static void getTokens(const string_type& instr,
+										std::vector<string_type >& tokens,
+										const string_type& delims);
+	/// like simple scan overload, but returns scanned vector
+	LL_COMMON_API static std::vector<string_type> getTokens(const string_type& instr,
+															const string_type& delims);
+	/// add support for keep_delims and quotes (either could be empty string)
+	LL_COMMON_API static void getTokens(const string_type& instr,
+										std::vector<string_type>& tokens,
+										const string_type& drop_delims,
+										const string_type& keep_delims,
+										const string_type& quotes=string_type());
+	/// like keep_delims-and-quotes overload, but returns scanned vector
+	LL_COMMON_API static std::vector<string_type> getTokens(const string_type& instr,
+															const string_type& drop_delims,
+															const string_type& keep_delims,
+															const string_type& quotes=string_type());
+	/// add support for escapes (could be empty string)
+	LL_COMMON_API static void getTokens(const string_type& instr,
+										std::vector<string_type>& tokens,
+										const string_type& drop_delims,
+										const string_type& keep_delims,
+										const string_type& quotes,
+										const string_type& escapes);
+	/// like escapes overload, but returns scanned vector
+	LL_COMMON_API static std::vector<string_type> getTokens(const string_type& instr,
+															const string_type& drop_delims,
+															const string_type& keep_delims,
+															const string_type& quotes,
+															const string_type& escapes);
+
 	LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals);
 	LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch);
 	LL_COMMON_API static S32 format(string_type& s, const format_map_t& substitutions);
@@ -262,6 +294,11 @@ public:
 		return !string.empty() && (0 <= i) && (i <= string.size());
 	}
 
+	static bool contains(const string_type& string, T c, size_type i=0)
+	{
+		return string.find(c, i) != string_type::npos;
+	}
+
 	static void	trimHead(string_type& string);
 	static void	trimTail(string_type& string);
 	static void	trim(string_type& string)	{ trimHead(string); trimTail(string); }
@@ -650,10 +687,324 @@ namespace LLStringFn
 ////////////////////////////////////////////////////////////
 // NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp.
 // There is no LLWStringUtil::format implementation currently.
-// Calling thse for anything other than LLStringUtil will produce link errors.
+// Calling these for anything other than LLStringUtil will produce link errors.
 
 ////////////////////////////////////////////////////////////
 
+// static
+template <class T>
+std::vector<typename LLStringUtilBase<T>::string_type>
+LLStringUtilBase<T>::getTokens(const string_type& instr, const string_type& delims)
+{
+	std::vector<string_type> tokens;
+	getTokens(instr, tokens, delims);
+	return tokens;
+}
+
+// static
+template <class T>
+std::vector<typename LLStringUtilBase<T>::string_type>
+LLStringUtilBase<T>::getTokens(const string_type& instr,
+							   const string_type& drop_delims,
+							   const string_type& keep_delims,
+							   const string_type& quotes)
+{
+	std::vector<string_type> tokens;
+	getTokens(instr, tokens, drop_delims, keep_delims, quotes);
+	return tokens;
+}
+
+// static
+template <class T>
+std::vector<typename LLStringUtilBase<T>::string_type>
+LLStringUtilBase<T>::getTokens(const string_type& instr,
+							   const string_type& drop_delims,
+							   const string_type& keep_delims,
+							   const string_type& quotes,
+							   const string_type& escapes)
+{
+	std::vector<string_type> tokens;
+	getTokens(instr, tokens, drop_delims, keep_delims, quotes, escapes);
+	return tokens;
+}
+
+namespace LLStringUtilBaseImpl
+{
+
+/**
+ * Input string scanner helper for getTokens(), or really any other
+ * character-parsing routine that may have to deal with escape characters.
+ * This implementation defines the concept (also an interface, should you
+ * choose to implement the concept by subclassing) and provides trivial
+ * implementations for a string @em without escape processing.
+ */
+template <class T>
+struct InString
+{
+	typedef std::basic_string<T> string_type;
+	typedef typename string_type::const_iterator const_iterator;
+
+	InString(const_iterator b, const_iterator e):
+		iter(b),
+		end(e)
+	{}
+
+	bool done() const { return iter == end; }
+	/// Is the current character (*iter) escaped? This implementation can
+	/// answer trivially because it doesn't support escapes.
+	virtual bool escaped() const { return false; }
+	/// Obtain the current character and advance @c iter.
+	virtual T next() { return *iter++; }
+	/// Does the current character match specified character?
+	virtual bool is(T ch) const { return (! done()) && *iter == ch; }
+	/// Is the current character any one of the specified characters?
+	virtual bool oneof(const string_type& delims) const
+	{
+		return (! done()) && LLStringUtilBase<T>::contains(delims, *iter);
+	}
+
+	/**
+	 * Scan forward from @from until either @a delim or end. This is primarily
+	 * useful for processing quoted substrings.
+	 *
+	 * If we do see @a delim, append everything from @from until (excluding)
+	 * @a delim to @a into, advance @c iter to skip @a delim, and return @c
+	 * true.
+	 *
+	 * If we do not see @a delim, do not alter @a into or @c iter and return
+	 * @c false. Do not pass GO, do not collect $200.
+	 *
+	 * @note The @c false case described above implements normal getTokens()
+	 * treatment of an unmatched open quote: treat the quote character as if
+	 * escaped, that is, simply collect it as part of the current token. Other
+	 * plausible behaviors directly affect the way getTokens() deals with an
+	 * unmatched quote: e.g. throwing an exception to treat it as an error, or
+	 * assuming a close quote beyond end of string (in which case return @c
+	 * true).
+	 */
+	virtual bool collect_until(string_type& into, const_iterator from, T delim)
+	{
+		const_iterator found = std::find(from, end, delim);
+		// If we didn't find delim, change nothing, just tell caller.
+		if (found == end)
+			return false;
+		// Found delim! Append everything between from and found.
+		into.append(from, found);
+		// advance past delim in input
+		iter = found + 1;
+		return true;
+	}
+
+	const_iterator iter, end;
+};
+
+/// InString subclass that handles escape characters
+template <class T>
+class InEscString: public InString<T>
+{
+public:
+	typedef InString<T> super;
+	typedef typename super::string_type string_type;
+	typedef typename super::const_iterator const_iterator;
+	using super::done;
+	using super::iter;
+	using super::end;
+
+	InEscString(const_iterator b, const_iterator e, const string_type& escapes_):
+		super(b, e),
+		escapes(escapes_)
+	{
+		// Even though we've already initialized 'iter' via our base-class
+		// constructor, set it again to check for initial escape char.
+		setiter(b);
+	}
+
+	/// This implementation uses the answer cached by setiter().
+	virtual bool escaped() const { return isesc; }
+	virtual T next()
+	{
+		// If we're looking at the escape character of an escape sequence,
+		// skip that character. This is the one time we can modify 'iter'
+		// without using setiter: for this one case we DO NOT CARE if the
+		// escaped character is itself an escape.
+		if (isesc)
+			++iter;
+		// If we were looking at an escape character, this is the escaped
+		// character; otherwise it's just the next character.
+		T result(*iter);
+		// Advance iter, checking for escape sequence.
+		setiter(iter + 1);
+		return result;
+	}
+
+	virtual bool is(T ch) const
+	{
+		// Like base-class is(), except that an escaped character matches
+		// nothing.
+		return (! done()) && (! isesc) && *iter == ch;
+	}
+
+	virtual bool oneof(const string_type& delims) const
+	{
+		// Like base-class oneof(), except that an escaped character matches
+		// nothing.
+		return (! done()) && (! isesc) && LLStringUtilBase<T>::contains(delims, *iter);
+	}
+
+	virtual bool collect_until(string_type& into, const_iterator from, T delim)
+	{
+		// Deal with escapes in the characters we collect; that is, an escaped
+		// character must become just that character without the preceding
+		// escape. Collect characters in a separate string rather than
+		// directly appending to 'into' in case we do not find delim, in which
+		// case we're supposed to leave 'into' unmodified.
+		string_type collected;
+		// For scanning purposes, we're going to work directly with 'iter'.
+		// Save its current value in case we fail to see delim.
+		const_iterator save_iter(iter);
+		// Okay, set 'iter', checking for escape.
+		setiter(from);
+		while (! done())
+		{
+			// If we see an unescaped delim, stop and report success.
+			if ((! isesc) && *iter == delim)
+			{
+				// Append collected chars to 'into'.
+				into.append(collected);
+				// Don't forget to advance 'iter' past delim.
+				setiter(iter + 1);
+				return true;
+			}
+			// We're not at end, and either we're not looking at delim or it's
+			// escaped. Collect this character and keep going.
+			collected.push_back(next());
+		}
+		// Here we hit 'end' without ever seeing delim. Restore iter and tell
+		// caller.
+		setiter(save_iter);
+		return false;
+	}
+
+private:
+	void setiter(const_iterator i)
+	{
+		iter = i;
+
+		// Every time we change 'iter', set 'isesc' to be able to repetitively
+		// answer escaped() without having to rescan 'escapes'. isesc caches
+		// contains(escapes, *iter).
+
+		// We're looking at an escaped char if we're not already at end (that
+		// is, *iter is even meaningful); if *iter is in fact one of the
+		// specified escape characters; and if there's one more character
+		// following it. That is, if an escape character is the very last
+		// character of the input string, it loses its special meaning.
+		isesc = (! done()) &&
+				LLStringUtilBase<T>::contains(escapes, *iter) &&
+				(iter+1) != end;
+	}
+
+	const string_type escapes;
+	bool isesc;
+};
+
+/// getTokens() implementation based on InString concept
+template <typename INSTRING, typename string_type>
+void getTokens(INSTRING& instr, std::vector<string_type>& tokens,
+			   const string_type& drop_delims, const string_type& keep_delims,
+			   const string_type& quotes)
+{
+	// There are times when we want to match either drop_delims or
+	// keep_delims. Concatenate them up front to speed things up.
+	string_type all_delims(drop_delims + keep_delims);
+	// no tokens yet
+	tokens.clear();
+
+	// try for another token
+	while (! instr.done())
+	{
+		// scan past any drop_delims
+		while (instr.oneof(drop_delims))
+		{
+			// skip this drop_delim
+			instr.next();
+			// but if that was the end of the string, done
+			if (instr.done())
+				return;
+		}
+		// found the start of another token: make a slot for it
+		tokens.push_back(string_type());
+		if (instr.oneof(keep_delims))
+		{
+			// *iter is a keep_delim, a token of exactly 1 character. Append
+			// that character to the new token and proceed.
+			tokens.back().push_back(instr.next());
+			continue;
+		}
+		// Here we have a non-delimiter token, which might consist of a mix of
+		// quoted and unquoted parts. Use bash rules for quoting: you can
+		// embed a quoted substring in the midst of an unquoted token (e.g.
+		// ~/"sub dir"/myfile.txt); you can ram two quoted substrings together
+		// to make a single token (e.g. 'He said, "'"Don't."'"'). We diverge
+		// from bash in that bash considers an unmatched quote an error. Our
+		// param signature doesn't allow for errors, so just pretend it's not
+		// a quote and embed it.
+		// At this level, keep scanning until we hit the next delimiter of
+		// either type (drop_delims or keep_delims).
+		while (! instr.oneof(all_delims))
+		{
+			// If we're looking at an open quote, search forward for
+			// a close quote, collecting characters along the way.
+			if (instr.oneof(quotes) &&
+				instr.collect_until(tokens.back(), instr.iter+1, *instr.iter))
+			{
+				// collect_until is cleverly designed to do exactly what we
+				// need here. No further action needed if it returns true.
+			}
+			else
+			{
+				// Either *iter isn't a quote, or there's no matching close
+				// quote: in other words, just an ordinary char. Append it to
+				// current token.
+				tokens.back().push_back(instr.next());
+			}
+			// having scanned that segment of this token, if we've reached the
+			// end of the string, we're done
+			if (instr.done())
+				return;
+		}
+	}
+}
+
+} // namespace LLStringUtilBaseImpl
+
+// static
+template <class T>
+void LLStringUtilBase<T>::getTokens(const string_type& string, std::vector<string_type>& tokens,
+									const string_type& drop_delims, const string_type& keep_delims,
+									const string_type& quotes)
+{
+	// Because this overload doesn't support escapes, use simple InString to
+	// manage input range.
+	LLStringUtilBaseImpl::InString<T> instring(string.begin(), string.end());
+	LLStringUtilBaseImpl::getTokens(instring, tokens, drop_delims, keep_delims, quotes);
+}
+
+// static
+template <class T>
+void LLStringUtilBase<T>::getTokens(const string_type& string, std::vector<string_type>& tokens,
+									const string_type& drop_delims, const string_type& keep_delims,
+									const string_type& quotes, const string_type& escapes)
+{
+	// This overload must deal with escapes. Delegate that to InEscString
+	// (unless there ARE no escapes).
+	boost::scoped_ptr< LLStringUtilBaseImpl::InString<T> > instrp;
+	if (escapes.empty())
+		instrp.reset(new LLStringUtilBaseImpl::InString<T>(string.begin(), string.end()));
+	else
+		instrp.reset(new LLStringUtilBaseImpl::InEscString<T>(string.begin(), string.end(), escapes));
+	LLStringUtilBaseImpl::getTokens(*instrp, tokens, drop_delims, keep_delims, quotes);
+}
 
 // static
 template<class T> 
diff --git a/indra/llcommon/tests/StringVec.h b/indra/llcommon/tests/StringVec.h
new file mode 100644
index 0000000000..a380b00a05
--- /dev/null
+++ b/indra/llcommon/tests/StringVec.h
@@ -0,0 +1,37 @@
+/**
+ * @file   StringVec.h
+ * @author Nat Goodspeed
+ * @date   2012-02-24
+ * @brief  Extend TUT ensure_equals() to handle std::vector<std::string>
+ * 
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Copyright (c) 2012, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_STRINGVEC_H)
+#define LL_STRINGVEC_H
+
+#include <vector>
+#include <string>
+#include <iostream>
+
+typedef std::vector<std::string> StringVec;
+
+std::ostream& operator<<(std::ostream& out, const StringVec& strings)
+{
+    out << '(';
+    StringVec::const_iterator begin(strings.begin()), end(strings.end());
+    if (begin != end)
+    {
+        out << '"' << *begin << '"';
+        while (++begin != end)
+        {
+            out << ", \"" << *begin << '"';
+        }
+    }
+    out << ')';
+    return out;
+}
+
+#endif /* ! defined(LL_STRINGVEC_H) */
diff --git a/indra/llcommon/tests/listener.h b/indra/llcommon/tests/listener.h
index dcdb2412be..9c5c18a150 100644
--- a/indra/llcommon/tests/listener.h
+++ b/indra/llcommon/tests/listener.h
@@ -30,6 +30,8 @@
 #define LL_LISTENER_H
 
 #include "llsd.h"
+#include "llevents.h"
+#include "tests/StringVec.h"
 #include <iostream>
 
 /*****************************************************************************
@@ -133,24 +135,7 @@ struct Collect
         return false;
     }
     void clear() { result.clear(); }
-    typedef std::vector<std::string> StringList;
-    StringList result;
+    StringVec result;
 };
 
-std::ostream& operator<<(std::ostream& out, const Collect::StringList& strings)
-{
-    out << '(';
-    Collect::StringList::const_iterator begin(strings.begin()), end(strings.end());
-    if (begin != end)
-    {
-        out << '"' << *begin << '"';
-        while (++begin != end)
-        {
-            out << ", \"" << *begin << '"';
-        }
-    }
-    out << ')';
-    return out;
-}
-
 #endif /* ! defined(LL_LISTENER_H) */
diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp
index 6a1cbf652a..821deeac21 100644
--- a/indra/llcommon/tests/llstring_test.cpp
+++ b/indra/llcommon/tests/llstring_test.cpp
@@ -29,7 +29,11 @@
 #include "linden_common.h"
 #include "../test/lltut.h"
 
+#include <boost/assign/list_of.hpp>
 #include "../llstring.h"
+#include "StringVec.h"
+
+using boost::assign::list_of;
 
 namespace tut
 {
@@ -750,4 +754,115 @@ namespace tut
 		ensure("empty substr.", !LLStringUtil::endsWith(empty, value));
 		ensure("empty everything.", !LLStringUtil::endsWith(empty, empty));
 	}
+
+	template<> template<>
+	void string_index_object_t::test<41>()
+	{
+		set_test_name("getTokens(\"delims\")");
+		ensure_equals("empty string", LLStringUtil::getTokens("", " "), StringVec());
+		ensure_equals("only delims",
+					  LLStringUtil::getTokens("   \r\n   ", " \r\n"), StringVec());
+		ensure_equals("sequence of delims",
+					  LLStringUtil::getTokens(",,, one ,,,", ","), list_of("one"));
+		// nat considers this a dubious implementation side effect, but I'd
+		// hate to change it now...
+		ensure_equals("noncontiguous tokens",
+					  LLStringUtil::getTokens(", ,, , one ,,,", ","), list_of("")("")("one"));
+		ensure_equals("space-padded tokens",
+					  LLStringUtil::getTokens(",    one  ,  two  ,", ","), list_of("one")("two"));
+		ensure_equals("no delims", LLStringUtil::getTokens("one", ","), list_of("one"));
+	}
+
+	// Shorthand for verifying that getTokens() behaves the same when you
+	// don't pass a string of escape characters, when you pass an empty string
+	// (different overloads), and when you pass a string of characters that
+	// aren't actually present.
+	void ensure_getTokens(const std::string& desc,
+						  const std::string& string,
+						  const std::string& drop_delims,
+						  const std::string& keep_delims,
+						  const std::string& quotes,
+						  const std::vector<std::string>& expect)
+	{
+		ensure_equals(desc + " - no esc",
+					  LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes),
+					  expect);
+		ensure_equals(desc + " - empty esc",
+					  LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes, ""),
+					  expect);
+		ensure_equals(desc + " - unused esc",
+					  LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes, "!"),
+					  expect);
+	}
+
+	void ensure_getTokens(const std::string& desc,
+						  const std::string& string,
+						  const std::string& drop_delims,
+						  const std::string& keep_delims,
+						  const std::vector<std::string>& expect)
+	{
+		ensure_getTokens(desc, string, drop_delims, keep_delims, "", expect);
+	}
+
+	template<> template<>
+	void string_index_object_t::test<42>()
+	{
+		set_test_name("getTokens(\"delims\", etc.)");
+		// Signatures to test in this method:
+		// getTokens(string, drop_delims, keep_delims [, quotes [, escapes]])
+		// If you omit keep_delims, you get the older function (test above).
+
+		// cases like the getTokens(string, delims) tests above
+		ensure_getTokens("empty string", "", " ", "", StringVec());
+		ensure_getTokens("only delims",
+						 "   \r\n   ", " \r\n", "", StringVec());
+		ensure_getTokens("sequence of delims",
+						 ",,, one ,,,", ", ", "", list_of("one"));
+		// Note contrast with the case in the previous method
+		ensure_getTokens("noncontiguous tokens",
+						 ", ,, , one ,,,", ", ", "", list_of("one"));
+		ensure_getTokens("space-padded tokens",
+						 ",    one  ,  two  ,", ", ", "",
+                         list_of("one")("two"));
+		ensure_getTokens("no delims", "one", ",", "", list_of("one"));
+
+		// drop_delims vs. keep_delims
+		ensure_getTokens("arithmetic",
+						 " ab+def  / xx*  yy ", " ", "+-*/",
+						 list_of("ab")("+")("def")("/")("xx")("*")("yy"));
+
+		// quotes
+		ensure_getTokens("no quotes",
+						 "She said, \"Don't go.\"", " ", ",", "",
+						 list_of("She")("said")(",")("\"Don't")("go.\""));
+		ensure_getTokens("quotes",
+						 "She said, \"Don't go.\"", " ", ",", "\"",
+						 list_of("She")("said")(",")("Don't go."));
+		ensure_getTokens("quotes and delims",
+						 "run c:/'Documents and Settings'/someone", " ", "", "'",
+						 list_of("run")("c:/Documents and Settings/someone"));
+		ensure_getTokens("unmatched quote",
+						 "baby don't leave", " ", "", "'",
+						 list_of("baby")("don't")("leave"));
+		ensure_getTokens("adjacent quoted",
+						 "abc'def \"ghi'\"jkl' mno\"pqr", " ", "", "\"'",
+						 list_of("abcdef \"ghijkl' mnopqr"));
+
+		// escapes
+		// Don't use backslash as an escape for these tests -- you'll go nuts
+		// between the C++ string scanner and getTokens() escapes. Test with
+		// something else!
+		ensure_equals("escaped delims",
+					  LLStringUtil::getTokens("^ a - dog^-gone^ phrase", " ", "-", "", "^"),
+					  list_of(" a")("-")("dog-gone phrase"));
+		ensure_equals("escaped quotes",
+					  LLStringUtil::getTokens("say: 'this isn^'t w^orking'.", " ", "", "'", "^"),
+					  list_of("say:")("this isn't working."));
+		ensure_equals("escaped escape",
+					  LLStringUtil::getTokens("want x^^2", " ", "", "", "^"),
+					  list_of("want")("x^2"));
+		ensure_equals("escape at end",
+					  LLStringUtil::getTokens("it's^ up there^", " ", "", "'", "^"),
+					  list_of("it's up")("there^"));
+    }
 }
-- 
cgit v1.2.3


From 5adc39753b9392050d961eb01edb31f8a6fbb05d Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 24 Feb 2012 16:02:39 -0500
Subject: Update llevents_tut.cpp to use StringVec, not local StringList.

---
 indra/test/llevents_tut.cpp | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp
index ca4c74099f..a9114075fc 100644
--- a/indra/test/llevents_tut.cpp
+++ b/indra/test/llevents_tut.cpp
@@ -316,7 +316,6 @@ void events_object::test<7>()
 {
 	set_test_name("listener dependency order");
 	typedef LLEventPump::NameList NameList;
-	typedef Collect::StringList StringList;
 	LLEventPump& button(pumps.obtain("button"));
 	Collect collector;
 	button.listen("Mary",
@@ -330,7 +329,7 @@ void events_object::test<7>()
 	button.listen("spot",
 				  boost::bind(&Collect::add, boost::ref(collector), "spot", _1));
 	button.post(1);
-	ensure_equals(collector.result, make<StringList>(list_of("spot")("checked")("Mary")));
+	ensure_equals(collector.result, make<StringVec>(list_of("spot")("checked")("Mary")));
 	collector.clear();
 	button.stopListening("Mary");
 	button.listen("Mary",
@@ -339,7 +338,7 @@ void events_object::test<7>()
 			// now "Mary" must come before "spot"
 			make<NameList>(list_of("spot")));
 	button.post(2);
-	ensure_equals(collector.result, make<StringList>(list_of("Mary")("spot")("checked")));
+	ensure_equals(collector.result, make<StringVec>(list_of("Mary")("spot")("checked")));
 	collector.clear();
 	button.stopListening("spot");
 	std::string threw;
@@ -373,7 +372,7 @@ void events_object::test<7>()
 				  boost::bind(&Collect::add, boost::ref(collector), "shoelaces", _1),
 				  make<NameList>(list_of("checked")));
 	button.post(3);
-	ensure_equals(collector.result, make<StringList>(list_of("Mary")("checked")("yellow")("shoelaces")));
+	ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces")));
 	collector.clear();
 	threw.clear();
 	try
@@ -395,7 +394,7 @@ void events_object::test<7>()
 	ensure_contains("old order", threw, "was: Mary, checked, yellow, shoelaces");
 	ensure_contains("new order", threw, "now: Mary, checked, shoelaces, of, yellow");
 	button.post(4);
-	ensure_equals(collector.result, make<StringList>(list_of("Mary")("checked")("yellow")("shoelaces")));
+	ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces")));
 }
 
 template<> template<>
-- 
cgit v1.2.3


From 4edf93d6d991af3f1aa0aba764388ad52ab1464b Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 24 Feb 2012 16:50:47 -0500
Subject: "Then there's Windows..." Fix llstring.h to build there too.

---
 indra/llcommon/llstring.h | 45 +++++++++++++++++++++++----------------------
 1 file changed, 23 insertions(+), 22 deletions(-)

diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index e4ae54cec5..5085d32f7f 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -253,32 +253,32 @@ public:
 										std::vector<string_type >& tokens,
 										const string_type& delims);
 	/// like simple scan overload, but returns scanned vector
-	LL_COMMON_API static std::vector<string_type> getTokens(const string_type& instr,
-															const string_type& delims);
+	static std::vector<string_type> getTokens(const string_type& instr,
+											  const string_type& delims);
 	/// add support for keep_delims and quotes (either could be empty string)
-	LL_COMMON_API static void getTokens(const string_type& instr,
-										std::vector<string_type>& tokens,
-										const string_type& drop_delims,
-										const string_type& keep_delims,
-										const string_type& quotes=string_type());
+	static void getTokens(const string_type& instr,
+						  std::vector<string_type>& tokens,
+						  const string_type& drop_delims,
+						  const string_type& keep_delims,
+						  const string_type& quotes=string_type());
 	/// like keep_delims-and-quotes overload, but returns scanned vector
-	LL_COMMON_API static std::vector<string_type> getTokens(const string_type& instr,
-															const string_type& drop_delims,
-															const string_type& keep_delims,
-															const string_type& quotes=string_type());
+	static std::vector<string_type> getTokens(const string_type& instr,
+											  const string_type& drop_delims,
+											  const string_type& keep_delims,
+											  const string_type& quotes=string_type());
 	/// add support for escapes (could be empty string)
-	LL_COMMON_API static void getTokens(const string_type& instr,
-										std::vector<string_type>& tokens,
-										const string_type& drop_delims,
-										const string_type& keep_delims,
-										const string_type& quotes,
-										const string_type& escapes);
+	static void getTokens(const string_type& instr,
+						  std::vector<string_type>& tokens,
+						  const string_type& drop_delims,
+						  const string_type& keep_delims,
+						  const string_type& quotes,
+						  const string_type& escapes);
 	/// like escapes overload, but returns scanned vector
-	LL_COMMON_API static std::vector<string_type> getTokens(const string_type& instr,
-															const string_type& drop_delims,
-															const string_type& keep_delims,
-															const string_type& quotes,
-															const string_type& escapes);
+	static std::vector<string_type> getTokens(const string_type& instr,
+											  const string_type& drop_delims,
+											  const string_type& keep_delims,
+											  const string_type& quotes,
+											  const string_type& escapes);
 
 	LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals);
 	LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch);
@@ -748,6 +748,7 @@ struct InString
 		iter(b),
 		end(e)
 	{}
+	virtual ~InString() {}
 
 	bool done() const { return iter == end; }
 	/// Is the current character (*iter) escaped? This implementation can
-- 
cgit v1.2.3


From d2faf5d25a0f6cc3ccaaf450fe6d3585fef058b7 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 24 Feb 2012 17:14:07 -0500
Subject: Get rid of indra/llcommon/tests/setpython.py. run_build_test.py
 already has the capability to set environment variables, and we may as well
 direct it to set PYTHON to the running Python interpreter. That completely
 eliminates one level of process wrapper.

---
 indra/cmake/LLTestCommand.cmake   |  3 +++
 indra/llcommon/CMakeLists.txt     |  6 ++----
 indra/llcommon/tests/setpython.py | 19 -------------------
 3 files changed, 5 insertions(+), 23 deletions(-)
 delete mode 100644 indra/llcommon/tests/setpython.py

diff --git a/indra/cmake/LLTestCommand.cmake b/indra/cmake/LLTestCommand.cmake
index b5a0580a90..f75c23a5de 100644
--- a/indra/cmake/LLTestCommand.cmake
+++ b/indra/cmake/LLTestCommand.cmake
@@ -9,6 +9,9 @@ MACRO(LL_TEST_COMMAND OUTVAR LD_LIBRARY_PATH)
   FOREACH(dir ${LD_LIBRARY_PATH})
     LIST(APPEND value "-l${dir}")
   ENDFOREACH(dir)
+  # Enough different tests want to be able to find CMake's PYTHON_EXECUTABLE
+  # that we should just pop it into the environment for everybody.
+  LIST(APPEND value "-DPYTHON=${PYTHON_EXECUTABLE}")
   LIST(APPEND value ${ARGN})
   SET(${OUTVAR} ${value})
 ##IF(LL_TEST_VERBOSE)
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 3255e28e8e..1cab648cfa 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -324,8 +324,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}"
-                          "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
+  LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")                          
   LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
@@ -333,8 +332,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}"
-                          "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
+  LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
 
   # *TODO - reenable these once tcmalloc libs no longer break the build.
diff --git a/indra/llcommon/tests/setpython.py b/indra/llcommon/tests/setpython.py
deleted file mode 100644
index df7b90428e..0000000000
--- a/indra/llcommon/tests/setpython.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-"""\
-@file   setpython.py
-@author Nat Goodspeed
-@date   2011-07-13
-@brief  Set PYTHON environment variable for tests that care.
-
-$LicenseInfo:firstyear=2011&license=viewerlgpl$
-Copyright (c) 2011, Linden Research, Inc.
-$/LicenseInfo$
-"""
-
-import os
-import sys
-import subprocess
-
-if __name__ == "__main__":
-    os.environ["PYTHON"] = sys.executable
-    sys.exit(subprocess.call(sys.argv[1:]))
-- 
cgit v1.2.3


From bf7c215692435ceb85d8991a9337933688dc0cf0 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sun, 26 Feb 2012 07:17:08 -0500
Subject: Add LLStringUtil::getTokens() test for quoted empty string. This is
 an important differentiator between getTokens() and the present
 LLCommandLineParser::parseCommandLineString() logic: you cannot currently
 --set SomeVar to an empty string value because parseCommandLineString()
 discards empty strings.

---
 indra/llcommon/tests/llstring_test.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp
index 821deeac21..93d3968dbf 100644
--- a/indra/llcommon/tests/llstring_test.cpp
+++ b/indra/llcommon/tests/llstring_test.cpp
@@ -847,6 +847,9 @@ namespace tut
 		ensure_getTokens("adjacent quoted",
 						 "abc'def \"ghi'\"jkl' mno\"pqr", " ", "", "\"'",
 						 list_of("abcdef \"ghijkl' mnopqr"));
+		ensure_getTokens("quoted empty string",
+						 "--set SomeVar ''", " ", "", "'",
+						 list_of("--set")("SomeVar")(""));
 
 		// escapes
 		// Don't use backslash as an escape for these tests -- you'll go nuts
-- 
cgit v1.2.3


From 4a7848148e886676dd24bfcf4f50db06bffb28da Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sun, 26 Feb 2012 07:21:51 -0500
Subject: Add TODOs for getTokens() to known places that scan command lines.
 Lacking time to properly test new LLStringUtil::getTokens() against the
 present (different!) command-line scanners in LLExternalEditor::tokenize()
 and LLCommandLineParser::parseCommandLineString(), just annotate as future
 work the goal of unifying them... SIGH.

---
 indra/newview/llcommandlineparser.cpp | 9 +++++++++
 indra/newview/llexternaleditor.cpp    | 6 ++++++
 2 files changed, 15 insertions(+)

diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp
index 65c61c4a8b..17d403bbe1 100644
--- a/indra/newview/llcommandlineparser.cpp
+++ b/indra/newview/llcommandlineparser.cpp
@@ -342,6 +342,15 @@ bool LLCommandLineParser::parseCommandLine(int argc, char **argv)
     return parseAndStoreResults(clp);
 }
 
+// TODO:
+// - Break out this funky parsing logic into separate method
+// - Unit-test it with tests like LLStringUtil::getTokens() (the command-line
+//   overload that supports quoted tokens)
+// - Unless this logic offers significant semantic benefits, replace it with
+//   LLStringUtil::getTokens(). This would fix a known bug: you cannot --set a
+//   string-valued variable to the empty string, because empty strings are
+//   eliminated below.
+
 bool LLCommandLineParser::parseCommandLineString(const std::string& str)
 {
     // Split the string content into tokens
diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp
index db482f023e..9480e54809 100644
--- a/indra/newview/llexternaleditor.cpp
+++ b/indra/newview/llexternaleditor.cpp
@@ -119,6 +119,12 @@ std::string LLExternalEditor::getErrorMessage(EErrorCode code)
 	return LLTrans::getString("Unknown");
 }
 
+// TODO:
+// - Unit-test this with tests like LLStringUtil::getTokens() (the
+//   command-line overload that supports quoted tokens)
+// - Unless there are significant semantic differences, eliminate this method
+//   and use LLStringUtil::getTokens() instead.
+
 // static
 size_t LLExternalEditor::tokenize(string_vec_t& tokens, const std::string& str)
 {
-- 
cgit v1.2.3


From c0318d1bf988217e1fbb0593d03c4f0235a13ea3 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 27 Feb 2012 11:50:47 -0500
Subject: Make LLInstanceTracker<T, T*>::getInstance(T*) validate passed T*.
 For the T* specialization (no string, or whatever, key), the original
 getInstance() method simply returned the passed-in T* value. It was defined,
 as the comments noted, for completeness of the analogy with the keyed
 LLInstanceTracker specialization. It turns out, though, that getInstance(T*)
 can still be useful to ask whether the T* you have in hand still references a
 valid T instance. Support that usage.

---
 indra/llcommon/llinstancetracker.h              | 21 +++++++++++++++++----
 indra/llcommon/tests/llinstancetracker_test.cpp |  7 ++++++-
 2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 34d841a4e0..403df08990 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -167,8 +167,9 @@ public:
 
 	static T* getInstance(const KEY& k)
 	{
-		typename InstanceMap::const_iterator found = getMap_().find(k);
-		return (found == getMap_().end()) ? NULL : found->second;
+		const InstanceMap& map(getMap_());
+		typename InstanceMap::const_iterator found = map.find(k);
+		return (found == map.end()) ? NULL : found->second;
 	}
 
 	static instance_iter beginInstances() 
@@ -239,8 +240,20 @@ class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
 
 public:
 
-	/// for completeness of analogy with the generic implementation
-	static T* getInstance(T* k) { return k; }
+	/**
+	 * Does a particular instance still exist? Of course, if you already have
+	 * a T* in hand, you need not call getInstance() to @em locate the
+	 * instance -- unlike the case where getInstance() accepts some kind of
+	 * key. Nonetheless this method is still useful to @em validate a
+	 * particular T*, since each instance's destructor removes itself from the
+	 * underlying set.
+	 */
+	static T* getInstance(T* k)
+	{
+		const InstanceSet& set(getSet_());
+		typename InstanceSet::const_iterator found = set.find(k);
+		return (found == set.end())? NULL : *found;
+	}
 	static S32 instanceCount() { return getSet_().size(); }
 
 	class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag>
diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp
index b34d1c5fd3..294e21bac5 100644
--- a/indra/llcommon/tests/llinstancetracker_test.cpp
+++ b/indra/llcommon/tests/llinstancetracker_test.cpp
@@ -95,6 +95,7 @@ namespace tut
     void object::test<2>()
     {
         ensure_equals(Unkeyed::instanceCount(), 0);
+        Unkeyed* dangling = NULL;
         {
             Unkeyed one;
             ensure_equals(Unkeyed::instanceCount(), 1);
@@ -107,7 +108,11 @@ namespace tut
                 ensure_equals(found, two.get());
             }
             ensure_equals(Unkeyed::instanceCount(), 1);
-        }
+            // store an unwise pointer to a temp Unkeyed instance
+            dangling = &one;
+        } // make that instance vanish
+        // check the now-invalid pointer to the destroyed instance
+        ensure("getInstance(T*) failed to track destruction", ! Unkeyed::getInstance(dangling));
         ensure_equals(Unkeyed::instanceCount(), 0);
     }
 
-- 
cgit v1.2.3