diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt
index d39055e118c3d8262cd867a16c0d1403db437db6..88564c60853cb4c17919541105ca46b5ba49ea38 100644
--- a/indra/integration_tests/llui_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llui_libtest/CMakeLists.txt
@@ -1,5 +1,7 @@
 # -*- cmake -*-
 
+# Only set this up for viewer builds, because the llui library is most closely
+# related to the viewer
 if (VIEWER)
 
 project (llui_libtest)
@@ -91,8 +93,9 @@ if (WINDOWS)
         )
 endif (WINDOWS)
 
-    # Ensure people working on the viewer don't break this library
-    # *NOTE: This could be removed, or only built by Parabuild, if the build
-    # and link times become too long. JC
-    add_dependencies(viewer llui_libtest)
+# Ensure people working on the viewer don't break this library
+# *NOTE: This could be removed, or only built by Parabuild, if the build
+# and link times become too long. JC
+add_dependencies(viewer llui_libtest)
+
 endif (VIEWER)
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 6715b6722d33f3769ad8b10b26685766a3d081a5..e4102a622d8361ced6f72b91ff8fa2f9fbb4bbca 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -46,7 +46,8 @@ struct AssetEntry : public LLDictionaryEntry
 			   const char *type_name, // 8 character limit!
 			   const char *human_name,
 			   const char *category_name, // used by llinventorymodel when creating new categories
-			   EDragAndDropType dad_type);
+			   EDragAndDropType dad_type,
+			   bool can_link);
 
 	// limited to 8 characters
 	const char *mTypeName;
@@ -55,6 +56,7 @@ struct AssetEntry : public LLDictionaryEntry
 	const char *mHumanName;
 	const char *mCategoryName;
 	EDragAndDropType mDadType;
+	bool mCanLink;
 };
 
 class LLAssetDictionary : public LLSingleton<LLAssetDictionary>,
@@ -66,44 +68,49 @@ class LLAssetDictionary : public LLSingleton<LLAssetDictionary>,
 
 LLAssetDictionary::LLAssetDictionary()
 {
-	addEntry(LLAssetType::AT_TEXTURE, 			new AssetEntry("TEXTURE",			"texture",	"texture",			"Textures", 		DAD_TEXTURE));
-	addEntry(LLAssetType::AT_SOUND, 			new AssetEntry("SOUND",				"sound",	"sound",			"Sounds", 			DAD_SOUND));
-	addEntry(LLAssetType::AT_CALLINGCARD, 		new AssetEntry("CALLINGCARD",		"callcard",	"calling card",		"Calling Cards", 	DAD_CALLINGCARD));
-	addEntry(LLAssetType::AT_LANDMARK, 			new AssetEntry("LANDMARK",			"landmark",	"landmark",			"Landmarks", 		DAD_LANDMARK));
-	addEntry(LLAssetType::AT_SCRIPT, 			new AssetEntry("SCRIPT",			"script",	"legacy script",	"Scripts", 			DAD_NONE));
-	addEntry(LLAssetType::AT_CLOTHING, 			new AssetEntry("CLOTHING",			"clothing",	"clothing",			"Clothing", 		DAD_CLOTHING));
-	addEntry(LLAssetType::AT_OBJECT, 			new AssetEntry("OBJECT",			"object",	"object",			"Objects", 			DAD_OBJECT));
-	addEntry(LLAssetType::AT_NOTECARD, 			new AssetEntry("NOTECARD",			"notecard",	"note card",		"Notecards", 		DAD_NOTECARD));
-	addEntry(LLAssetType::AT_CATEGORY, 			new AssetEntry("CATEGORY",			"category",	"folder",			"New Folder", 		DAD_CATEGORY));
-	addEntry(LLAssetType::AT_ROOT_CATEGORY, 	new AssetEntry("ROOT_CATEGORY",		"root",		"root",				"Inventory", 		DAD_ROOT_CATEGORY));
-	addEntry(LLAssetType::AT_LSL_TEXT, 			new AssetEntry("LSL_TEXT",			"lsltext",	"lsl2 script",		"Scripts", 			DAD_SCRIPT));
-	addEntry(LLAssetType::AT_LSL_BYTECODE, 		new AssetEntry("LSL_BYTECODE",		"lslbyte",	"lsl bytecode",		"Scripts", 			DAD_NONE));
-	addEntry(LLAssetType::AT_TEXTURE_TGA, 		new AssetEntry("TEXTURE_TGA",		"txtr_tga",	"tga texture",		"Uncompressed Images", DAD_NONE));
-	addEntry(LLAssetType::AT_BODYPART, 			new AssetEntry("BODYPART",			"bodypart",	"body part",		"Body Parts", 		DAD_BODYPART));
-	addEntry(LLAssetType::AT_TRASH, 			new AssetEntry("TRASH",				"trash",	"trash",			"Trash", 			DAD_NONE));
-	addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot",	"snapshot",			"Photo Album", 		DAD_NONE));
-	addEntry(LLAssetType::AT_LOST_AND_FOUND, 	new AssetEntry("LOST_AND_FOUND", 	"lstndfnd",	"lost and found",	"Lost And Found", 	DAD_NONE));
-	addEntry(LLAssetType::AT_SOUND_WAV, 		new AssetEntry("SOUND_WAV",			"snd_wav",	"sound",			"Uncompressed Sounds", DAD_NONE));
-	addEntry(LLAssetType::AT_IMAGE_TGA, 		new AssetEntry("IMAGE_TGA",			"img_tga",	"targa image",		"Uncompressed Images", DAD_NONE));
-	addEntry(LLAssetType::AT_IMAGE_JPEG, 		new AssetEntry("IMAGE_JPEG",		"jpeg",		"jpeg image",		"Uncompressed Images", DAD_NONE));
-	addEntry(LLAssetType::AT_ANIMATION, 		new AssetEntry("ANIMATION",			"animatn",	"animation",		"Animations", 		DAD_ANIMATION));
-	addEntry(LLAssetType::AT_GESTURE, 			new AssetEntry("GESTURE",			"gesture",	"gesture",			"Gestures", 		DAD_GESTURE));
-	addEntry(LLAssetType::AT_SIMSTATE, 			new AssetEntry("SIMSTATE",			"simstate",	"simstate",			"New Folder", 		DAD_NONE));
-	addEntry(LLAssetType::AT_LINK, 				new AssetEntry("LINK",				"link",		"symbolic  link",	"New Folder", 		DAD_NONE));
-	addEntry(LLAssetType::AT_FAVORITE, 			new AssetEntry("FAVORITE",			"favorite",	"favorite",			"favorite", 		DAD_NONE));
-	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		"New Folder", 		DAD_NONE));
+	addEntry(LLAssetType::AT_TEXTURE, 			new AssetEntry("TEXTURE",			"texture",	"texture",			"Textures", 		DAD_TEXTURE,	FALSE));
+	addEntry(LLAssetType::AT_SOUND, 			new AssetEntry("SOUND",				"sound",	"sound",			"Sounds", 			DAD_SOUND,		FALSE));
+	addEntry(LLAssetType::AT_CALLINGCARD, 		new AssetEntry("CALLINGCARD",		"callcard",	"calling card",		"Calling Cards", 	DAD_CALLINGCARD, FALSE));
+	addEntry(LLAssetType::AT_LANDMARK, 			new AssetEntry("LANDMARK",			"landmark",	"landmark",			"Landmarks", 		DAD_LANDMARK,	FALSE));
+	addEntry(LLAssetType::AT_SCRIPT, 			new AssetEntry("SCRIPT",			"script",	"legacy script",	"Scripts", 			DAD_NONE,		FALSE));
+	addEntry(LLAssetType::AT_CLOTHING, 			new AssetEntry("CLOTHING",			"clothing",	"clothing",			"Clothing", 		DAD_CLOTHING,	TRUE));
+	addEntry(LLAssetType::AT_OBJECT, 			new AssetEntry("OBJECT",			"object",	"object",			"Objects", 			DAD_OBJECT,		TRUE));
+	addEntry(LLAssetType::AT_NOTECARD, 			new AssetEntry("NOTECARD",			"notecard",	"note card",		"Notecards", 		DAD_NOTECARD,	FALSE));
+	addEntry(LLAssetType::AT_CATEGORY, 			new AssetEntry("CATEGORY",			"category",	"folder",			"New Folder", 		DAD_CATEGORY,	TRUE));
+	addEntry(LLAssetType::AT_ROOT_CATEGORY, 	new AssetEntry("ROOT_CATEGORY",		"root",		"root",				"Inventory", 		DAD_ROOT_CATEGORY, TRUE));
+	addEntry(LLAssetType::AT_LSL_TEXT, 			new AssetEntry("LSL_TEXT",			"lsltext",	"lsl2 script",		"Scripts", 			DAD_SCRIPT,		FALSE));
+	addEntry(LLAssetType::AT_LSL_BYTECODE, 		new AssetEntry("LSL_BYTECODE",		"lslbyte",	"lsl bytecode",		"Scripts", 			DAD_NONE,		FALSE));
+	addEntry(LLAssetType::AT_TEXTURE_TGA, 		new AssetEntry("TEXTURE_TGA",		"txtr_tga",	"tga texture",		"Uncompressed Images", DAD_NONE,	FALSE));
+	addEntry(LLAssetType::AT_BODYPART, 			new AssetEntry("BODYPART",			"bodypart",	"body part",		"Body Parts", 		DAD_BODYPART,	TRUE));
+	addEntry(LLAssetType::AT_TRASH, 			new AssetEntry("TRASH",				"trash",	"trash",			"Trash", 			DAD_NONE,		FALSE));
+	addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot",	"snapshot",			"Photo Album", 		DAD_NONE,		FALSE));
+	addEntry(LLAssetType::AT_LOST_AND_FOUND, 	new AssetEntry("LOST_AND_FOUND", 	"lstndfnd",	"lost and found",	"Lost And Found", 	DAD_NONE,		FALSE));
+	addEntry(LLAssetType::AT_SOUND_WAV, 		new AssetEntry("SOUND_WAV",			"snd_wav",	"sound",			"Uncompressed SoundS", DAD_NONE,	FALSE));
+	addEntry(LLAssetType::AT_IMAGE_TGA, 		new AssetEntry("IMAGE_TGA",			"img_tga",	"targa image",		"Uncompressed Images", DAD_NONE,	FALSE));
+	addEntry(LLAssetType::AT_IMAGE_JPEG, 		new AssetEntry("IMAGE_JPEG",		"jpeg",		"jpeg image",		"Uncompressed Images", DAD_NONE,	FALSE));
+	addEntry(LLAssetType::AT_ANIMATION, 		new AssetEntry("ANIMATION",			"animatn",	"animation",		"Animations", 		DAD_ANIMATION,	FALSE));
+	addEntry(LLAssetType::AT_GESTURE, 			new AssetEntry("GESTURE",			"gesture",	"gesture",			"Gestures", 		DAD_GESTURE,	FALSE));
+	addEntry(LLAssetType::AT_SIMSTATE, 			new AssetEntry("SIMSTATE",			"simstate",	"simstate",			"New Folder", 		DAD_NONE,		FALSE));
+	addEntry(LLAssetType::AT_FAVORITE, 			new AssetEntry("FAVORITE",			"favorite",	"favorite",			"favorite", 		DAD_NONE,		FALSE));
+
+	addEntry(LLAssetType::AT_LINK, 				new AssetEntry("LINK",				"link",		"symbolic link",	"New Folder", 		DAD_NONE,		FALSE));
+	addEntry(LLAssetType::AT_LINK_FOLDER, 		new AssetEntry("FOLDER_LINK",		"link_f", "symbolic folder link", "New Folder", DAD_NONE,		FALSE));
+
+	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		"New Folder", 		DAD_NONE,		FALSE));
 };
 
 AssetEntry::AssetEntry(const char *desc_name,
 					   const char *type_name,
 					   const char *human_name,
 					   const char *category_name,
-					   EDragAndDropType dad_type) :
+					   EDragAndDropType dad_type,
+					   bool can_link) :
 	LLDictionaryEntry(desc_name),
 	mTypeName(type_name),
 	mHumanName(human_name),
 	mCategoryName(category_name),
-	mDadType(dad_type)
+	mDadType(dad_type),
+	mCanLink(can_link)
 {
 	llassert(strlen(mTypeName) <= 8);
 }
@@ -231,6 +238,29 @@ EDragAndDropType LLAssetType::lookupDragAndDropType(EType asset_type)
 		return DAD_NONE;
 }
 
+// static
+bool LLAssetType::lookupCanLink(EType asset_type)
+{
+	const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+	const AssetEntry *entry = dict->lookup(asset_type);
+	if (entry)
+	{
+		return entry->mCanLink;
+	}
+	return false;
+}
+
+// static
+// Not adding this to dictionary since we probably will only have these two types
+bool LLAssetType::lookupIsLinkType(EType asset_type)
+{
+	if (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER)
+	{
+		return true;
+	}
+	return false;
+}
+
 // static. Generate a good default description
 void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type,
 										 std::string& description)
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 2f5403168810cd3045587e15f90b01f955d5587e..353bd57bb9bc5dd937a75aada2e93eb72b2cc41f 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -125,23 +125,25 @@ class LLAssetType
 
 		AT_SIMSTATE = 22,
 			// Simstate file.
-			
-		AT_LINK = 23,
-			// Inventory symbolic link
-			
-		AT_FAVORITE = 24,
+	
+		AT_FAVORITE = 23,
 			// favorite items
 
-		// +*********************************************+
-		// |  TO ADD AN ELEMENT TO THIS ENUM:            |
-			// +************************************************+
-		// | 1. INSERT BEFORE AT_COUNT                   |
-		// | 2. INCREMENT AT_COUNT BY 1                  |
-		// | 3. ADD TO LLAssetType::mAssetTypeNames      |
-		// | 4. ADD TO LLAssetType::mAssetTypeHumanNames |
-		// +*********************************************+
+		AT_LINK = 24,
+			// Inventory symbolic link
+
+		AT_LINK_FOLDER = 25,
+			// Inventory folder link
 
-		AT_COUNT = 25,
+		AT_COUNT = 26,
+
+			// +************************************************+
+			// |  TO ADD AN ELEMENT TO THIS ENUM:               |
+			// +************************************************+
+			// | 1. INSERT BEFORE AT_COUNT                      |
+			// | 2. INCREMENT AT_COUNT BY 1                     |
+			// | 3. ADD TO LLAssetDictionary in llassettype.cpp |
+			// +************************************************+
 
 		AT_NONE = -1
 	};
@@ -166,6 +168,8 @@ class LLAssetType
 	static EType 				getType(const std::string& desc_name);
 	static const std::string&	getDesc(EType asset_type);
 	static EDragAndDropType   	lookupDragAndDropType(EType asset_type);
+	static bool 				lookupCanLink(EType asset_type);
+	static bool 				lookupIsLinkType(EType asset_type);
 
 	/* TODO: Change return types from "const char *" to "const std::string &".
 	This is fairly straightforward, but requires changing some calls to use .c_str().
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index adc80b2ed370d083c71e482f613ee153e32af90a..597e19e7eadfa6f148ff172e810b5df6736183c9 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -126,6 +126,20 @@ const std::string& LLInventoryObject::getName() const
 	return mName;
 }
 
+// To bypass linked items, since llviewerinventory's getType
+// will return the linked-to item's type instead of this object's type.
+LLAssetType::EType LLInventoryObject::getActualType() const
+{
+	return mType;
+}
+
+// See LLInventoryItem override.
+// virtual
+const LLUUID& LLInventoryObject::getLinkedUUID() const
+{
+	return mUUID;
+}
+
 LLAssetType::EType LLInventoryObject::getType() const
 {
 	return mType;
@@ -333,6 +347,19 @@ void LLInventoryItem::copyItem(const LLInventoryItem* other)
 	mCreationDate = other->mCreationDate;
 }
 
+// If this is a linked item, then the UUID of the base object is
+// this item's assetID.
+// virtual
+const LLUUID& LLInventoryItem::getLinkedUUID() const
+{
+	if (LLAssetType::lookupIsLinkType(getActualType()))
+	{
+		return mAssetUUID;
+	}
+
+	return LLInventoryObject::getLinkedUUID();
+}
+
 const LLPermissions& LLInventoryItem::getPermissions() const
 {
 	return mPermissions;
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 3f79cedc232783ab33b1ec6b61346e05c10253a5..ce64317f488db42f9f46adb22067034d15e2d4d5 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -92,9 +92,12 @@ class LLInventoryObject : public LLRefCount
 	// accessors
 	virtual const LLUUID& getUUID() const;
 	const LLUUID& getParentUUID() const;
+	virtual const LLUUID& getLinkedUUID() const; // get the inventoryID that this item points to, else this item's inventoryID
+
 	virtual const std::string& getName() const;
 	virtual LLAssetType::EType getType() const;
-	LLAssetType::EType getActualType() const { return mType; }
+	LLAssetType::EType getActualType() const; // bypasses indirection for linked items
+
 	// mutators - will not call updateServer();
 	void setUUID(const LLUUID& new_uuid);
 	void rename(const std::string& new_name);
@@ -240,15 +243,16 @@ class LLInventoryItem : public LLInventoryObject
 	void generateUUID() { mUUID.generate(); }
 	
 	// accessors
-	const LLPermissions& getPermissions() const;
-	const LLUUID& getCreatorUUID() const;
+	virtual const LLUUID& getLinkedUUID() const;
+	virtual const LLPermissions& getPermissions() const;
+	virtual const LLUUID& getCreatorUUID() const;
 	virtual const LLUUID& getAssetUUID() const;
-	const std::string& getDescription() const;
-	const LLSaleInfo& getSaleInfo() const;
-	LLInventoryType::EType getInventoryType() const;
-	U32 getFlags() const;
-	time_t getCreationDate() const;
-	U32 getCRC32() const; // really more of a checksum.
+	virtual const std::string& getDescription() const;
+	virtual const LLSaleInfo& getSaleInfo() const;
+	virtual LLInventoryType::EType getInventoryType() const;
+	virtual U32 getFlags() const;
+	virtual time_t getCreationDate() const;
+	virtual U32 getCRC32() const; // really more of a checksum.
 	
 	// mutators - will not call updateServer(), and will never fail
 	// (though it may correct to sane values)
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index ff9c6989437c86e1df756234c02933e488a9b036..2dc229226f14776279b2aa20222e0237461614fd 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -113,8 +113,10 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
 	LLInventoryType::IT_NONE,			// AT_IMAGE_JPEG
 	LLInventoryType::IT_ANIMATION,		// AT_ANIMATION
 	LLInventoryType::IT_GESTURE,		// AT_GESTURE
-	LLInventoryType::IT_NONE,			// AT_LINK
+	LLInventoryType::IT_NONE,			// AT_SIMSTATE
 	LLInventoryType::IT_FAVORITE,		// AT_FAVORITE
+	LLInventoryType::IT_NONE,			// AT_LINK
+	LLInventoryType::IT_NONE,			// AT_LINK_FOLDER
 };
 
 InventoryEntry::InventoryEntry(const std::string &name,
diff --git a/indra/llmath/xform.h b/indra/llmath/xform.h
index d3be28f41d88adab91853139ca79017e587ea48c..5b7b1900bcb58cc79a09cf5254d5604eb18fa41f 100644
--- a/indra/llmath/xform.h
+++ b/indra/llmath/xform.h
@@ -173,7 +173,7 @@ BOOL LLXform::setParent(LLXform* parent)
 		{
 			if (cur_par == this)
 			{
-				llwarns << "LLXform::setParent Creating loop when setting parent!" << llendl;
+				//llwarns << "LLXform::setParent Creating loop when setting parent!" << llendl;
 				return FALSE;
 			}
 			cur_par = cur_par->mParent;
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index 059c1bdfa1b8f82f4bd73186d1da0f9c12804969..c715e16e34c829598f62d2dae5939862df51b144 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -264,17 +264,17 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type)
 	bool rv = false;
 	switch(type)
 	{
-	case LLAssetType::AT_SOUND:
-	case LLAssetType::AT_LANDMARK:
-	case LLAssetType::AT_CLOTHING:
-	case LLAssetType::AT_BODYPART:
-	case LLAssetType::AT_ANIMATION:
-	case LLAssetType::AT_GESTURE:
-	case LLAssetType::AT_FAVORITE:
-		rv = true;
-		break;
-	default:
-		break;
+		case LLAssetType::AT_SOUND:
+		case LLAssetType::AT_LANDMARK:
+		case LLAssetType::AT_CLOTHING:
+		case LLAssetType::AT_BODYPART:
+		case LLAssetType::AT_ANIMATION:
+		case LLAssetType::AT_GESTURE:
+		case LLAssetType::AT_FAVORITE:
+			rv = true;
+			break;
+		default:
+			break;
 	}
 	return rv;
 }
@@ -285,15 +285,17 @@ bool is_asset_id_knowable(LLAssetType::EType type)
 	bool rv = false;
 	switch(type)
 	{
-	case LLAssetType::AT_TEXTURE:
-	case LLAssetType::AT_SOUND:
-	case LLAssetType::AT_LANDMARK:
-	case LLAssetType::AT_CLOTHING:
-	case LLAssetType::AT_NOTECARD:
-	case LLAssetType::AT_BODYPART:
-	case LLAssetType::AT_ANIMATION:
-	case LLAssetType::AT_GESTURE:
-	case LLAssetType::AT_FAVORITE:
+		case LLAssetType::AT_TEXTURE:
+		case LLAssetType::AT_SOUND:
+		case LLAssetType::AT_LANDMARK:
+		case LLAssetType::AT_CLOTHING:
+		case LLAssetType::AT_NOTECARD:
+		case LLAssetType::AT_BODYPART:
+		case LLAssetType::AT_ANIMATION:
+		case LLAssetType::AT_GESTURE:
+		case LLAssetType::AT_FAVORITE:
+		case LLAssetType::AT_LINK:
+		case LLAssetType::AT_LINK_FOLDER:
 		rv = true;
 		break;
 	default:
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 4e657067cd8d3354d71e028456542c849d581d10..9e3986f257631c17d7895b7163788bec925111ca 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -174,6 +174,7 @@ char* _PREHASH_UpdateInventoryItem = LLMessageStringTable::getInstance()->getStr
 char* _PREHASH_UpdateCreateInventoryItem = LLMessageStringTable::getInstance()->getString("UpdateCreateInventoryItem");
 char* _PREHASH_MoveInventoryItem = LLMessageStringTable::getInstance()->getString("MoveInventoryItem");
 char* _PREHASH_CopyInventoryItem = LLMessageStringTable::getInstance()->getString("CopyInventoryItem");
+char* _PREHASH_LinkInventoryItem = LLMessageStringTable::getInstance()->getString("LinkInventoryItem");
 char* _PREHASH_RemoveInventoryItem = LLMessageStringTable::getInstance()->getString("RemoveInventoryItem");
 char* _PREHASH_CreateInventoryItem = LLMessageStringTable::getInstance()->getString("CreateInventoryItem");
 char* _PREHASH_PathTwistBegin = LLMessageStringTable::getInstance()->getString("PathTwistBegin");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index f8ef61040839daefcac02df40298618c20bdb104..e73ec3e5e1948c2d482f19ba059287a526d2994d 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -174,6 +174,7 @@ extern char * _PREHASH_UpdateInventoryItem;
 extern char * _PREHASH_UpdateCreateInventoryItem;
 extern char * _PREHASH_MoveInventoryItem;
 extern char * _PREHASH_CopyInventoryItem;
+extern char * _PREHASH_LinkInventoryItem;
 extern char * _PREHASH_RemoveInventoryItem;
 extern char * _PREHASH_CreateInventoryItem;
 extern char * _PREHASH_PathTwistBegin;
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 452f18b40ba50645641a14f35b627529525d1f9b..50fee41029437007732ea11a8931125553d93d5f 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -160,6 +160,12 @@ class LLNotificationHistoryChannel : public LLNotificationChannel
 
 bool filterIgnoredNotifications(LLNotificationPtr notification)
 {
+	// filter everything if we are to ignore ALL
+	if(LLNotifications::instance().getIgnoreAllNotifications())
+	{
+		return false;
+	}
+
 	LLNotificationFormPtr form = notification->getForm();
 	// Check to see if the user wants to ignore this alert
 	if (form->getIgnoreType() != LLNotificationForm::IGNORE_NO)
@@ -231,7 +237,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodeP
 		LLSD item_entry;
 		std::string element_name = child->getName()->mString;
 
-		if (element_name == "ignore")
+		if (element_name == "ignore" )
 		{
 			bool save_option = false;
 			child->getAttribute_bool("save_option", save_option);
@@ -925,7 +931,8 @@ std::string LLNotificationChannel::summarize()
 // LLNotifications implementation
 // ---
 LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything,
-															   LLNotificationComparators::orderByUUID())
+															   LLNotificationComparators::orderByUUID()),
+									mIgnoreAllNotifications(false)
 {
 	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
 }
@@ -1473,6 +1480,14 @@ std::string LLNotifications::getGlobalString(const std::string& key) const
 	}
 }
 
+void LLNotifications::setIgnoreAllNotifications(bool setting)
+{
+	mIgnoreAllNotifications = setting; 
+}
+bool LLNotifications::getIgnoreAllNotifications()
+{
+	return mIgnoreAllNotifications; 
+}
 													
 // ---
 // END OF LLNotifications implementation
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index b749724b4e93e64ae67c7a23c574d813873c4dc0..512886790cab1f42a9fa0045465e243b4df00853 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -870,6 +870,9 @@ class LLNotifications :
 	
 	std::string getGlobalString(const std::string& key) const;
 
+	void setIgnoreAllNotifications(bool ignore);
+	bool getIgnoreAllNotifications();
+
 private:
 	// we're a singleton, so we don't have a public constructor
 	LLNotifications();
@@ -898,6 +901,8 @@ class LLNotifications :
 	
 	typedef std::map<std::string, std::string> GlobalStringMap;
 	GlobalStringMap mGlobalStrings;
+
+	bool mIgnoreAllNotifications;
 };
 
 
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index f5d06b725871c4983df821d3f1319ddb6801107c..b80080e458f949933560202379352b2e307b19c5 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -35,6 +35,7 @@ include_directories(
 set(llwindow_SOURCE_FILES
     llkeyboard.cpp
     llwindowheadless.cpp
+    llwindowcallbacks.cpp
     )
 
 set(llwindow_HEADER_FILES
@@ -42,27 +43,28 @@ set(llwindow_HEADER_FILES
 
     llkeyboard.h
     llwindowheadless.h
+    llwindowcallbacks.h
     )
 
 set(viewer_SOURCE_FILES
     llwindow.cpp
     llmousehandler.cpp
-    llwindowcallbacks.cpp
     )
 
 set(viewer_HEADER_FILES
     llwindow.h
-    llwindowcallbacks.h
     llpreeditor.h
     llmousehandler.h
     )
 
 # Libraries on which this library depends, needed for Linux builds
 # Sort by high-level to low-level
-set(llwindow_LINK_LIBRARIES
-    ${UI_LIBRARIES}     # for GTK
-    ${SDL_LIBRARY}
-    )
+if (NOT LINUX OR VIEWER)
+  set(llwindow_LINK_LIBRARIES
+      ${UI_LIBRARIES}     # for GTK
+      ${SDL_LIBRARY}
+      )
+endif (VIEWER)
 
 if (DARWIN)
   list(APPEND llwindow_SOURCE_FILES
@@ -85,7 +87,7 @@ if (DARWIN)
       )
 endif (DARWIN)
 
-if (LINUX)
+if (LINUX AND VIEWER)
   list(APPEND viewer_SOURCE_FILES 
        llkeyboardsdl.cpp 
        llwindowsdl.cpp
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 783a886fdd325e0c654afbaac2a82ee3bf10fddc..5f143431deb6c77a5962ffa8c8f5bfc0fd28bb1b 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -146,6 +146,14 @@
       <string>ReplaySession</string>
     </map>
 
+    <key>nonotifications</key>
+    <map>
+      <key>desc</key>
+      <string>User will not get any notifications. NOTE: All notifications that occur will get added to ignore file for future runs.</string>
+      <key>map-to</key>
+      <string>IgnoreAllNotifications</string>      
+    </map>    
+
     <key>rotate</key>
     <map>
       <key>map-to</key>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 5ad49774a9ef6b206ea87b775dce852e52435eb6..afa7f707f17e656a0190ac0e5923105b841931a9 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -3560,6 +3560,17 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>IgnoreAllNotifications</key>
+    <map>
+      <key>Comment</key>
+      <string>Ignore all notifications so we never need user input on them.</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>  
     <key>IgnorePixelDepth</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index a70d31431fe7fb32cb2d33b12740b9f0042cff03..a8094a5850d3123954cdf77cba300c83636c6d06 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -64,6 +64,9 @@
 #include "llmorphview.h"
 #include "llmoveview.h"
 #include "llparcel.h"
+#include "llquantize.h"
+#include "llrand.h"
+#include "llregionhandle.h"
 #include "llsdutil.h"
 #include "llselectmgr.h"
 #include "llsky.h"
@@ -71,6 +74,7 @@
 #include "llsmoothstep.h"
 #include "llsidetray.h"
 #include "llstatusbar.h"
+#include "llteleportflags.h"
 #include "llteleporthistory.h"
 #include "lltool.h"
 #include "lltoolcomp.h"
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 1c756b1441fe2731e9d4754432a1ffe54696aef4..1da54ad08c5b18f6dcce1d7a6a707391e8ce21b6 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -626,9 +626,24 @@ const LLUUID& LLAgentWearables::getWearableItem(EWearableType type, U32 index) c
 }
 
 
-BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const
+// Warning: include_linked_items = TRUE makes this operation expensive.
+BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id, BOOL include_linked_items) const
 {
-	return (getWearableFromWearableItem(item_id) != NULL);
+	if (getWearableFromWearableItem(item_id) != NULL) return TRUE;
+	if (include_linked_items)
+	{
+		LLInventoryModel::item_array_t item_array;
+		gInventory.collectLinkedItems(item_id, item_array);
+		for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
+			 iter != item_array.end();
+			 iter++)
+		{
+			LLViewerInventoryItem *linked_item = (*iter);
+			const LLUUID &item_id = linked_item->getUUID();
+			if (getWearableFromWearableItem(item_id) != NULL) return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 // MULTI-WEARABLE: update for multiple
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 98f49203d3d30b559ca6d4aa0cc67aeaca3a82e8..31d6e3006934b10c770707c7a9502c8e90937d55 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -63,7 +63,7 @@ class LLAgentWearables
 	// Queries
 	//--------------------------------------------------------------------
 public:
-	BOOL			isWearingItem(const LLUUID& item_id) const;
+	BOOL			isWearingItem(const LLUUID& item_id, const BOOL include_linked_items = FALSE) const;
 	BOOL			isWearableModifiable(EWearableType type, U32 index /*= 0*/) const;
 	BOOL			isWearableCopyable(EWearableType type, U32 index /*= 0*/) const;
 	BOOL			areWearablesLoaded() const { return mWearablesLoaded; } 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index ff5ddbfcfb0839f900a7a4a639afe29a32de26e9..f9e6db52c33fef1e4306a656c4028ecc3b9edce6 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -641,6 +641,11 @@ bool LLAppViewer::init()
 	// Get the single value from the crash settings file, if it exists
 	std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
 	gCrashSettings.loadFromFile(crash_settings_filename);
+	if(gSavedSettings.getBOOL("IgnoreAllNotifications"))
+	{
+		gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, CRASH_BEHAVIOR_ALWAYS_SEND);
+		gCrashSettings.saveToFile(crash_settings_filename, FALSE);
+	}
 
 	/////////////////////////////////////////////////
 	// OS-specific login dialogs
@@ -1971,6 +1976,11 @@ bool LLAppViewer::initConfiguration()
 	{
 		LLAgentPilot::sReplaySession = TRUE;
 	}
+
+	if (clp.hasOption("nonotifications"))
+	{
+		gSavedSettings.setBOOL("IgnoreAllNotifications", TRUE);
+	}
 	
 	if (clp.hasOption("debugsession"))
 	{
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index b23bd8cc81f97b14d3a149930058fdefefc90ec5..540c8785431ed074a4ffc667b4c34f113539fa27 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -33,14 +33,19 @@
 #ifndef LL_LLAPPVIEWER_H
 #define LL_LLAPPVIEWER_H
 
+#include "llallocator.h"
 #include "llcontrol.h"
+#include "llsys.h"			// for LLOSInfo
 
+class LLCommandLineParser;
+class LLFrameTimer;
+class LLPumpIO;
 class LLTextureCache;
-class LLWorkerThread;
 class LLTextureFetch;
+class LLTimer;
+class LLVFS;
 class LLWatchdogTimeout;
-class LLCommandLineParser;
-class LLAllocator;
+class LLWorkerThread;
 
 
 
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index 4cd9647603fcde5c7d321fb7d9e092c06fd37ee1..1379073bba69b48467848be53b3648bce8834971 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -58,11 +58,13 @@
 #include "lltexlayer.h"
 
 // library includes
+#include "lldir.h"
 #include "lleconomy.h"
 #include "llfloaterreg.h"
 #include "llfocusmgr.h"
 #include "llscrolllistctrl.h"
 #include "llsdserialize.h"
+#include "llvfs.h"
 
 // When uploading multiple files, don't display any of them when uploading more than this number.
 static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5;
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index 807f2f035cf3a8784c85b127608b381ec9a278bf..3cd612673928f886b48bf0d90f8d6c28a02fdef5 100644
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -41,6 +41,8 @@
 #include "llmenugl.h"
 #include "lluictrlfactory.h"
 
+#include "llcachename.h"
+
 #define MENU_ITEM_VIEW_PROFILE 0
 #define MENU_ITEM_SEND_IM 1
 
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
index 4d50541d9a6da4ec74bcdb442f3b196f6a26af18..2e10dea834552ae435d6e1ed286c9b88827aeb9b 100644
--- a/indra/newview/llavatarpropertiesprocessor.h
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -34,6 +34,8 @@
 #define LL_LLAVATARPROPERTIESPROCESSOR_H
 
 #include "lluuid.h"
+#include "llsingleton.h"
+#include "v3dmath.h"	// LLVector3d
 #include <map>
 
 /*
diff --git a/indra/newview/llcapabilitylistener.cpp b/indra/newview/llcapabilitylistener.cpp
index 0a41ad614e516e794d31da68943d31a8356ed52f..785a647fa2901e099b4cfc926164167a0a5e8812 100644
--- a/indra/newview/llcapabilitylistener.cpp
+++ b/indra/newview/llcapabilitylistener.cpp
@@ -21,6 +21,7 @@
 // other Linden headers
 #include "stringize.h"
 #include "llcapabilityprovider.h"
+#include "message.h"
 
 class LLCapabilityListener::CapabilityMappers: public LLSingleton<LLCapabilityListener::CapabilityMappers>
 {
diff --git a/indra/newview/llcapabilitylistener.h b/indra/newview/llcapabilitylistener.h
index 061227e04d6056d678b10d68a601aeb4f7ede42e..ce16b7da5daa7be22354392c815d92f54f3b0209 100644
--- a/indra/newview/llcapabilitylistener.h
+++ b/indra/newview/llcapabilitylistener.h
@@ -17,6 +17,7 @@
 #include "llerror.h"                // LOG_CLASS()
 
 class LLCapabilityProvider;
+class LLMessageSystem;
 class LLSD;
 
 class LLCapabilityListener
diff --git a/indra/newview/llcaphttpsender.cpp b/indra/newview/llcaphttpsender.cpp
index 1127f43424fc5ec04190eec39fa31ebfe08142df..b44e1f11fac65dc2a056d6aadaf686406ded086b 100644
--- a/indra/newview/llcaphttpsender.cpp
+++ b/indra/newview/llcaphttpsender.cpp
@@ -32,9 +32,10 @@
 
 #include "llviewerprecompiledheaders.h"
 
-#include "linden_common.h"
 #include "llcaphttpsender.h"
 
+#include "llhost.h"
+
 LLCapHTTPSender::LLCapHTTPSender(const std::string& cap) :
 	mCap(cap)
 {
diff --git a/indra/newview/llcloud.cpp b/indra/newview/llcloud.cpp
index 0099817de478cdab3d9783348a93d8091cb0aed3..af6f4e3286f4e8723ab8cdaf4deca4454cab8d3d 100644
--- a/indra/newview/llcloud.cpp
+++ b/indra/newview/llcloud.cpp
@@ -37,6 +37,7 @@
 #include "v3math.h"
 #include "v4math.h"
 #include "llquaternion.h"
+#include "llrand.h"
 #include "v4color.h"
 
 #include "llwind.h"
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index 096777ddd47caa56943647acd4c08580f48a6b6e..9d3b92d93742a46992564236ee037b5f3a2dc82b 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -56,10 +56,12 @@
 #include "llviewerobject.h"
 #include "llviewerregion.h"
 #include "llresmgr.h"
+
 #include "llbutton.h"
 #include "lldir.h"
 #include "llfloaterchat.h"
 #include "llviewerstats.h"
+#include "llvfile.h"
 #include "lluictrlfactory.h"
 #include "lltrans.h"
 
diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h
index 5a20eaef9bb8955abd8991e5fee4f2e8c652d5d4..22e5a4819d79a46f5afd9abd0a9911f6e3d3577b 100644
--- a/indra/newview/lldynamictexture.h
+++ b/indra/newview/lldynamictexture.h
@@ -33,6 +33,7 @@
 #ifndef LL_LLDYNAMICTEXTURE_H
 #define LL_LLDYNAMICTEXTURE_H
 
+#include "llcamera.h"
 #include "llgl.h"
 #include "llcoord.h"
 #include "llimagegl.h"
diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h
index 12e4b49d57c63ccd2a0fad59beb29af939d84a48..f2465a361e9f9a622b83de804238ee7c35132bcd 100644
--- a/indra/newview/lleventpoll.h
+++ b/indra/newview/lleventpoll.h
@@ -35,6 +35,9 @@
 
 #include "llhttpclient.h"
 
+class LLHost;
+
+
 class LLEventPoll
 	///< implements the viewer side of server-to-viewer pushed events.
 {
diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h
index 537bf0c6a444d10fa4f29e6fdff85b1fd4ef18cf..383963a41d8693b92c19a147c3dd57ea3a1730bb 100644
--- a/indra/newview/llfeaturemanager.h
+++ b/indra/newview/llfeaturemanager.h
@@ -35,6 +35,7 @@
 
 #include "stdtypes.h"
 
+#include "llsingleton.h"
 #include "llstring.h"
 #include <map>
 
diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp
index 5a8afc227787fa1715035a91fbdfcf82b7a64e98..dc72b66949b9179efc8369669000e84689c0023e 100644
--- a/indra/newview/llfloaterproperties.cpp
+++ b/indra/newview/llfloaterproperties.cpp
@@ -305,10 +305,11 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
 	BOOL is_complete = i->isComplete();
 
 	const LLPermissions& perm = item->getPermissions();
-	BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm, 
-												GP_OBJECT_MANIPULATE);
-	BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm, 
-												GP_OBJECT_SET_SALE);
+	const BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm, 
+															GP_OBJECT_MANIPULATE);
+	const BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm, 
+													  GP_OBJECT_SET_SALE);
+	const BOOL is_link = LLAssetType::lookupIsLinkType(i->getActualType());
 
 	// You need permission to modify the object to modify an inventory
 	// item in it.
@@ -491,7 +492,12 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
 	/////////////
 
 	// Check for ability to change values.
-	if (is_obj_modify && can_agent_manipulate)
+	if (is_link)
+	{
+		childSetEnabled("CheckShareWithGroup",FALSE);
+		childSetEnabled("CheckEveryoneCopy",FALSE);
+	}
+	else if (is_obj_modify && can_agent_manipulate)
 	{
 		childSetEnabled("CheckShareWithGroup",TRUE);
 		childSetEnabled("CheckEveryoneCopy",(owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER));
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 251539088be6e50a8fce128f3d968ae29b9f7f29..2fe817625a1ce7498b129e8953372223d59b712c 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -57,6 +57,7 @@
 #include "llslurl.h"
 #include "lltextbox.h"
 #include "lltracker.h"
+#include "llviewerinventory.h"	// LLViewerInventoryItem
 #include "llviewermenu.h"
 #include "llviewerregion.h"
 #include "llviewerstats.h"
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 9d91f0d64ec4ab437839dbb05514bc23662bd058..3386a7fb0e03aa8b048c76f88337ae6467099bb0 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -103,6 +103,7 @@ class LLFolderViewEventListener
 	virtual void cutToClipboard() = 0;
 	virtual BOOL isClipboardPasteable() const = 0;
 	virtual void pasteFromClipboard() = 0;
+	virtual void pasteLinkFromClipboard() = 0;
 	virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
 	virtual BOOL isUpToDate() const = 0;
 	virtual BOOL hasChildren() const = 0;
diff --git a/indra/newview/llhudeffectpointat.h b/indra/newview/llhudeffectpointat.h
index 81db3da1c78188136ad6f3246236e92dce352645..278c69fe2bff6e71f5b066b00988c6e15ee7f017 100644
--- a/indra/newview/llhudeffectpointat.h
+++ b/indra/newview/llhudeffectpointat.h
@@ -33,6 +33,7 @@
 #ifndef LL_LLHUDEFFECTPOINTAT_H
 #define LL_LLHUDEFFECTPOINTAT_H
 
+#include "llframetimer.h"
 #include "llhudeffect.h"
 
 class LLViewerObject;
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 469f6ec21db06b73f4cf15bab7e79af8736df3d8..37dcd1593fe475e0504024ab798ab92c8ab13464 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -33,6 +33,7 @@
 #ifndef LL_LLIMVIEW_H
 #define LL_LLIMVIEW_H
 
+#include "lldarray.h"
 #include "llmodaldialog.h"
 #include "llinstantmessage.h"
 #include "lluuid.h"
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 540cefbc46019a67f37d63915ec55829d1f8e72e..af653238d35c7959df72ab6186e46ce2892cb0be 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -202,6 +202,38 @@ BOOL LLInvFVBridge::isItemRemovable()
 	return FALSE;
 }
 
+// Sends an update to all link items that point to the base item.
+void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name)
+{
+	LLInventoryModel* model = getInventoryModel();
+	if(!model) return;
+
+	LLInventoryItem* itemp = model->getItem(mUUID);
+	if (!itemp) return;
+
+	if (LLAssetType::lookupIsLinkType(itemp->getActualType()))
+	{
+		return;
+	}
+	
+	LLInventoryModel::item_array_t item_array;
+	model->collectLinkedItems(item_id, item_array);
+	for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
+		 iter != item_array.end();
+		 iter++)
+	{
+		LLViewerInventoryItem *linked_item = (*iter);
+		if (linked_item->getUUID() == item_id) continue;
+		
+		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item);
+		new_item->rename(new_name);
+		new_item->updateServer(FALSE);
+		model->updateItem(new_item);
+		// model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
+	}
+	model->notifyObservers();
+}
+
 // Can be moved to another folder
 BOOL LLInvFVBridge::isItemMovable()
 {
@@ -370,15 +402,71 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
 
 BOOL LLInvFVBridge::isClipboardPasteable() const
 {
+	if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+	{
+		return FALSE;
+	}
 	LLInventoryModel* model = getInventoryModel();
-	if(!model) return FALSE;
-	BOOL is_agent_inventory = model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID());
+	if (!model)
+	{
+		return FALSE;
+	}
+
+	const LLUUID &agent_id = gAgent.getID();
 
-	if(LLInventoryClipboard::instance().hasContents() && is_agent_inventory)
+	LLDynamicArray<LLUUID> objects;
+	LLInventoryClipboard::instance().retrieve(objects);
+	S32 count = objects.count();
+	for(S32 i = 0; i < count; i++)
 	{
-		return TRUE;
+		const LLUUID &item_id = objects.get(i);
+
+		// Can't paste folders
+		const LLInventoryCategory *cat = model->getCategory(item_id);
+		if (cat)
+		{
+			return FALSE;
+		}
+
+		const LLInventoryItem *item = model->getItem(item_id);
+		if (item)
+		{
+			if (!item->getPermissions().allowCopyBy(agent_id))
+			{
+				return FALSE;
+			}
+		}
 	}
-	return FALSE;
+	return TRUE;
+}
+
+BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
+{
+	if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+	{
+		return FALSE;
+	}
+	LLInventoryModel* model = getInventoryModel();
+	if (!model)
+	{
+		return FALSE;
+	}
+
+	LLDynamicArray<LLUUID> objects;
+	LLInventoryClipboard::instance().retrieve(objects);
+	S32 count = objects.count();
+	for(S32 i = 0; i < count; i++)
+	{
+		LLInventoryItem *item = model->getItem(objects.get(i));
+		if (item)
+		{
+			if (!LLAssetType::lookupCanLink(item->getActualType()))
+			{
+				return FALSE;
+			}
+		}
+	}
+	return TRUE;
 }
 
 void hideContextEntries(LLMenuGL& menu, 
@@ -461,6 +549,11 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 		disabled_items.push_back(std::string("Paste"));
 	}
 
+	items.push_back(std::string("Paste As Link"));
+	if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
+	{
+		disabled_items.push_back(std::string("Paste As Link"));
+	}
 	items.push_back(std::string("Paste Separator"));
 
 	items.push_back(std::string("Delete"));
@@ -544,10 +637,25 @@ BOOL LLInvFVBridge::isInTrash() const
 {
 	LLInventoryModel* model = getInventoryModel();
 	if(!model) return FALSE;
-	LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+	const LLUUID& trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
 	return model->isObjectDescendentOf(mUUID, trash_id);
 }
 
+BOOL LLInvFVBridge::isLinkedObjectInTrash() const
+{
+	if (isInTrash()) return TRUE;
+
+	LLInventoryModel* model = getInventoryModel();
+	if(!model) return FALSE;
+	LLInventoryObject *obj = model->getObject(mUUID);
+	if (obj && LLAssetType::lookupIsLinkType(obj->getActualType()))
+	{
+		const LLUUID& trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+		return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
+	}
+	return FALSE;
+}
+
 BOOL LLInvFVBridge::isAgentInventory() const
 {
 	LLInventoryModel* model = getInventoryModel();
@@ -627,108 +735,106 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
 	LLInvFVBridge* new_listener = NULL;
 	switch(asset_type)
 	{
-	case LLAssetType::AT_TEXTURE:
-		if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLTextureBridge(inventory, uuid, inv_type);
-		break;
+		case LLAssetType::AT_TEXTURE:
+			if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLTextureBridge(inventory, uuid, inv_type);
+			break;
 
-	case LLAssetType::AT_SOUND:
-		if(!(inv_type == LLInventoryType::IT_SOUND))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLSoundBridge(inventory, uuid);
-		break;
+		case LLAssetType::AT_SOUND:
+			if(!(inv_type == LLInventoryType::IT_SOUND))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLSoundBridge(inventory, uuid);
+			break;
 
-	case LLAssetType::AT_LANDMARK:
-		if(!(inv_type == LLInventoryType::IT_LANDMARK))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLLandmarkBridge(inventory, uuid, flags);
-		break;
+		case LLAssetType::AT_LANDMARK:
+			if(!(inv_type == LLInventoryType::IT_LANDMARK))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLLandmarkBridge(inventory, uuid, flags);
+			break;
 		
-	case LLAssetType::AT_CALLINGCARD:
-		if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLCallingCardBridge(inventory, uuid);
-		break;
-
-	case LLAssetType::AT_SCRIPT:
-		if(!(inv_type == LLInventoryType::IT_LSL))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLScriptBridge(inventory, uuid);
-		break;
-
-	case LLAssetType::AT_OBJECT:
-		if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
-		break;
+		case LLAssetType::AT_CALLINGCARD:
+			if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLCallingCardBridge(inventory, uuid);
+			break;
 
-	case LLAssetType::AT_NOTECARD:
-		if(!(inv_type == LLInventoryType::IT_NOTECARD))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLNotecardBridge(inventory, uuid);
-		break;
+		case LLAssetType::AT_SCRIPT:
+			if(!(inv_type == LLInventoryType::IT_LSL))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLScriptBridge(inventory, uuid);
+			break;
 
-	case LLAssetType::AT_ANIMATION:
-		if(!(inv_type == LLInventoryType::IT_ANIMATION))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLAnimationBridge(inventory, uuid);
-		break;
+		case LLAssetType::AT_OBJECT:
+			if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
+			break;
 
-	case LLAssetType::AT_GESTURE:
-		if(!(inv_type == LLInventoryType::IT_GESTURE))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLGestureBridge(inventory, uuid);
-		break;
+		case LLAssetType::AT_NOTECARD:
+			if(!(inv_type == LLInventoryType::IT_NOTECARD))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLNotecardBridge(inventory, uuid);
+			break;
 
-	case LLAssetType::AT_LSL_TEXT:
-		if(!(inv_type == LLInventoryType::IT_LSL))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLLSLTextBridge(inventory, uuid);
-		break;
+		case LLAssetType::AT_ANIMATION:
+			if(!(inv_type == LLInventoryType::IT_ANIMATION))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLAnimationBridge(inventory, uuid);
+			break;
 
-	case LLAssetType::AT_CLOTHING:
-	case LLAssetType::AT_BODYPART:
-		if(!(inv_type == LLInventoryType::IT_WEARABLE))
-		{
-			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
-		}
-		new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
-		break;
+		case LLAssetType::AT_GESTURE:
+			if(!(inv_type == LLInventoryType::IT_GESTURE))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLGestureBridge(inventory, uuid);
+			break;
 
-	case LLAssetType::AT_CATEGORY:
-	case LLAssetType::AT_ROOT_CATEGORY:
-		new_listener = new LLFolderBridge(inventory, uuid);
-		break;
+		case LLAssetType::AT_LSL_TEXT:
+			if(!(inv_type == LLInventoryType::IT_LSL))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLLSLTextBridge(inventory, uuid);
+			break;
 
-	case LLAssetType::AT_FAVORITE:
-		new_listener = new LLFolderBridge(inventory, uuid);
-		break;
-		
-	default:
-		llinfos << "Unhandled asset type (llassetstorage.h): "
-				<< (S32)asset_type << llendl;
-		break;
+		case LLAssetType::AT_CLOTHING:
+		case LLAssetType::AT_BODYPART:
+			if(!(inv_type == LLInventoryType::IT_WEARABLE))
+			{
+				llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+			}
+			new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
+			break;
+		case LLAssetType::AT_CATEGORY:
+		case LLAssetType::AT_ROOT_CATEGORY:
+			new_listener = new LLFolderBridge(inventory, uuid);
+			break;
+		case LLAssetType::AT_LINK:
+			// Only should happen for broken links.
+			new_listener = new LLLinkItemBridge(inventory, uuid);
+			break;
+		default:
+			llinfos << "Unhandled asset type (llassetstorage.h): "
+					<< (S32)asset_type << llendl;
+			break;
 	}
 
 	if (new_listener)
@@ -739,6 +845,22 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
 	return new_listener;
 }
 
+void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
+{
+	LLInventoryCategory* cat = model->getCategory(uuid);
+	if (cat)
+	{
+		model->purgeDescendentsOf(uuid);
+		model->notifyObservers();
+	}
+	LLInventoryObject* obj = model->getObject(uuid);
+	if (obj)
+	{
+		model->purgeObject(uuid);
+		model->notifyObservers();
+	}
+}
+
 // +=================================================+
 // |        LLItemBridge                             |
 // +=================================================+
@@ -748,32 +870,27 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model,
 	if ("open" == action)
 	{
 		openItem();
+		return;
 	}
 	else if ("properties" == action)
 	{
 		showProperties();
+		return;
 	}
 	else if ("purge" == action)
 	{
-		LLInventoryCategory* cat = model->getCategory(mUUID);
-		if(cat)
-		{
-			model->purgeDescendentsOf(mUUID);
-		}
-		LLInventoryObject* obj = model->getObject(mUUID);
-		if(!obj) return;
-		obj->removeFromServer();
-		LLPreview::hide(mUUID);
-		model->deleteObject(mUUID);
-		model->notifyObservers();
+		purgeItem(model, mUUID);
+		return;
 	}
 	else if ("restoreToWorld" == action)
 	{
 		restoreToWorld();
+		return;
 	}
 	else if ("restore" == action)
 	{
 		restoreItem();
+		return;
 	}
 	else if ("copy_uuid" == action)
 	{
@@ -804,6 +921,18 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model,
 		folder_view_itemp->getListener()->pasteFromClipboard();
 		return;
 	}
+	else if ("paste_link" == action)
+	{
+		// Single item only
+		LLInventoryItem* itemp = model->getItem(mUUID);
+		if (!itemp) return;
+
+		LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+		if (!folder_view_itemp) return;
+
+		folder_view_itemp->getListener()->pasteLinkFromClipboard();
+		return;
+	}
 }
 
 void LLItemBridge::selectItem()
@@ -913,6 +1042,24 @@ void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
 	}
 }
 
+LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
+{ 
+	U8 font = LLFontGL::NORMAL;
+	
+	if( gAgentWearables.isWearingItem( mUUID ) )
+	{
+		// llinfos << "BOLD" << llendl;
+		font |= LLFontGL::BOLD;
+	}
+
+	const LLViewerInventoryItem* item = getItem();
+	if (LLAssetType::lookupIsLinkType(item->getActualType()))
+	{
+		font |= LLFontGL::ITALIC;
+	}
+	return (LLFontGL::StyleFlags)font;
+}
+
 std::string LLItemBridge::getLabelSuffix() const
 {
 	// assume that this won't be called before string table is loaded
@@ -932,8 +1079,12 @@ std::string LLItemBridge::getLabelSuffix() const
 			BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
 			BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
 																gAgent.getID());
+			BOOL link = (item->getActualType() == LLAssetType::AT_LINK);
 
 			const char* EMPTY = "";
+			const char* LINK = " (link)"; // *TODO: Seraph translate
+			if (link) return LINK;
+
 			const char* scopy;
 			if(copy) scopy = EMPTY;
 			else scopy = NO_COPY;
@@ -986,6 +1137,8 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)
 		buildDisplayName(new_item, mDisplayName);
 		new_item->updateServer(FALSE);
 		model->updateItem(new_item);
+		renameLinkedItems(item->getUUID(),new_name);
+
 		model->notifyObservers();
 	}
 	// return FALSE because we either notified observers (& therefore
@@ -1034,13 +1187,19 @@ BOOL LLItemBridge::isItemCopyable() const
 			return FALSE;
 		}
 
-		if( avatarp->isWearingAttachment( mUUID ) )
+		if( avatarp->isWearingAttachment( mUUID, TRUE ) )
 		{
 			return FALSE;
 		}
-			
-
-		return (item->getPermissions().allowCopyBy(gAgent.getID()));
+		
+		// All items can be copied, not all can be pasted.
+		// The only time an item can't be copied is if it's a link 
+		// return (item->getPermissions().allowCopyBy(gAgent.getID()));
+		if (item->getActualType() == LLAssetType::AT_LINK)
+		{
+			return FALSE;
+		}
+		return TRUE;
 	}
 	return FALSE;
 }
@@ -1152,7 +1311,7 @@ BOOL LLFolderBridge::isItemRemovable()
 		if( (item->getType() == LLAssetType::AT_CLOTHING) ||
 			(item->getType() == LLAssetType::AT_BODYPART) )
 		{
-			if( gAgentWearables.isWearingItem( item->getUUID() ) )
+			if( gAgentWearables.isWearingItem( item->getUUID(), TRUE ) )
 			{
 				return FALSE;
 			}
@@ -1160,7 +1319,7 @@ BOOL LLFolderBridge::isItemRemovable()
 		else
 		if( item->getType() == LLAssetType::AT_OBJECT )
 		{
-			if( avatar->isWearingAttachment( item->getUUID() ) )
+			if( avatar->isWearingAttachment( item->getUUID(), TRUE ) )
 			{
 				return FALSE;
 			}
@@ -1183,6 +1342,21 @@ BOOL LLFolderBridge::isUpToDate() const
 	return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
 }
 
+BOOL LLFolderBridge::isItemCopyable() const
+{
+	return TRUE;
+}
+
+BOOL LLFolderBridge::copyToClipboard() const
+{
+	if(isItemCopyable())
+	{
+		LLInventoryClipboard::instance().add(mUUID);
+		return TRUE;
+	}
+	return FALSE;
+}
+
 BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 											BOOL drop)
 {
@@ -1620,22 +1794,37 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
 	if ("open" == action)
 	{
 		openItem();
+		return;
 	}
 	else if ("paste" == action)
 	{
 		pasteFromClipboard();
+		return;
+	}
+	else if ("paste_link" == action)
+	{
+		pasteLinkFromClipboard();
+		return;
 	}
 	else if ("properties" == action)
 	{
 		showProperties();
+		return;
 	}
 	else if ("replaceoutfit" == action)
 	{
 		modifyOutfit(FALSE);
+		return;
 	}
 	else if ("addtooutfit" == action)
 	{
 		modifyOutfit(TRUE);
+		return;
+	}
+	else if ("copy" == action)
+	{
+		copyToClipboard();
+		return;
 	}
 	else if ("removefromoutfit" == action)
 	{
@@ -1645,25 +1834,17 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
 		if(!cat) return;
 		
 		remove_inventory_category_from_avatar ( cat );
+		return;
 	}	
 	else if ("purge" == action)
 	{		
-		LLViewerInventoryCategory* cat;
-		cat = (LLViewerInventoryCategory*)getCategory();
-
-		if(cat)
-		{
-			model->purgeDescendentsOf(mUUID);
-		}
-		LLInventoryObject* obj = model->getObject(mUUID);
-		if(!obj) return;
-		obj->removeFromServer();
-		model->deleteObject(mUUID);
-		model->notifyObservers();
+		purgeItem(model, mUUID);
+		return;
 	}
 	else if ("restore" == action)
 	{
 		restoreItem();
+		return;
 	}
 }
 
@@ -1723,59 +1904,59 @@ LLUIImagePtr LLFolderBridge::getIcon() const
 	}
 	switch(preferred_type)
 	{
-	case LLAssetType::AT_TEXTURE:
-		control = "inv_folder_texture.tga";
-		break;
-	case LLAssetType::AT_SOUND:
-		control = "inv_folder_sound.tga";
-		break;
-	case LLAssetType::AT_CALLINGCARD:
-		control = "inv_folder_callingcard.tga";
-		break;
-	case LLAssetType::AT_LANDMARK:
-		control = "inv_folder_landmark.tga";
-		break;
-	case LLAssetType::AT_SCRIPT:
-	case LLAssetType::AT_LSL_TEXT:
-		control = "inv_folder_script.tga";
-		break;
-	case LLAssetType::AT_OBJECT:
-		control = "inv_folder_object.tga";
-		break;
-	case LLAssetType::AT_NOTECARD:
-		control = "inv_folder_notecard.tga";
-		break;
-	case LLAssetType::AT_CATEGORY:
-		control = "inv_folder_plain_closed.tga";
-		break;
-	case LLAssetType::AT_CLOTHING:
-		control = "inv_folder_clothing.tga";
-		break;
-	case LLAssetType::AT_BODYPART:
-		control = "inv_folder_bodypart.tga";
-		break;
-	case LLAssetType::AT_TRASH:
-		control = "inv_folder_trash.tga";
-		break;
-	case LLAssetType::AT_SNAPSHOT_CATEGORY:
-		control = "inv_folder_snapshot.tga";
-		break;
-	case LLAssetType::AT_LOST_AND_FOUND:
-		control = "inv_folder_lostandfound.tga";
-		break;
-	case LLAssetType::AT_ANIMATION:
-		control = "inv_folder_animation.tga";
-		break;
-	case LLAssetType::AT_GESTURE:
-		control = "inv_folder_gesture.tga";
-		break;
-	case LLAssetType::AT_FAVORITE:
-		//TODO - need icon
-		control = "inv_folder_plain_closed.tga";
-		break;
-	default:
-		control = "inv_folder_plain_closed.tga";
-		break;
+		case LLAssetType::AT_TEXTURE:
+			control = "inv_folder_texture.tga";
+			break;
+		case LLAssetType::AT_SOUND:
+			control = "inv_folder_sound.tga";
+			break;
+		case LLAssetType::AT_CALLINGCARD:
+			control = "inv_folder_callingcard.tga";
+			break;
+		case LLAssetType::AT_LANDMARK:
+			control = "inv_folder_landmark.tga";
+			break;
+		case LLAssetType::AT_SCRIPT:
+		case LLAssetType::AT_LSL_TEXT:
+			control = "inv_folder_script.tga";
+			break;
+		case LLAssetType::AT_OBJECT:
+			control = "inv_folder_object.tga";
+			break;
+		case LLAssetType::AT_NOTECARD:
+			control = "inv_folder_notecard.tga";
+			break;
+		case LLAssetType::AT_CATEGORY:
+			control = "inv_folder_plain_closed.tga";
+			break;
+		case LLAssetType::AT_CLOTHING:
+			control = "inv_folder_clothing.tga";
+			break;
+		case LLAssetType::AT_BODYPART:
+			control = "inv_folder_bodypart.tga";
+			break;
+		case LLAssetType::AT_TRASH:
+			control = "inv_folder_trash.tga";
+			break;
+		case LLAssetType::AT_SNAPSHOT_CATEGORY:
+			control = "inv_folder_snapshot.tga";
+			break;
+		case LLAssetType::AT_LOST_AND_FOUND:
+			control = "inv_folder_lostandfound.tga";
+			break;
+		case LLAssetType::AT_ANIMATION:
+			control = "inv_folder_animation.tga";
+			break;
+		case LLAssetType::AT_GESTURE:
+			control = "inv_folder_gesture.tga";
+			break;
+		case LLAssetType::AT_FAVORITE:
+			//TODO - need icon
+			control = "inv_folder_plain_closed.tga";
+			break;
+		default:
+			control = "inv_folder_plain_closed.tga";
+			break;
 	}
 	return LLUI::getUIImage(control);
 }
@@ -1794,6 +1975,8 @@ BOOL LLFolderBridge::renameItem(const std::string& new_name)
 		new_cat->rename(new_name);
 		new_cat->updateServer(FALSE);
 		model->updateCategory(new_cat);
+		renameLinkedItems(cat->getUUID(),new_name);
+
 		model->notifyObservers();
 	}
 	// return FALSE because we either notified observers (& therefore
@@ -1842,15 +2025,6 @@ BOOL LLFolderBridge::removeItem()
 	return TRUE;
 }
 
-BOOL LLFolderBridge::isClipboardPasteable() const
-{
-	if(LLInventoryClipboard::instance().hasContents() && isAgentInventory())
-	{
-		return TRUE;
-	}
-	return FALSE;
-}
-
 void LLFolderBridge::pasteFromClipboard()
 {
 	LLInventoryModel* model = getInventoryModel();
@@ -1878,6 +2052,33 @@ void LLFolderBridge::pasteFromClipboard()
 	}
 }
 
+void LLFolderBridge::pasteLinkFromClipboard()
+{
+	LLInventoryModel* model = getInventoryModel();
+	if(model)
+	{
+		LLInventoryItem* item = NULL;
+		LLDynamicArray<LLUUID> objects;
+		LLInventoryClipboard::instance().retrieve(objects);
+		S32 count = objects.count();
+		LLUUID parent_id(mUUID);
+		for(S32 i = 0; i < count; i++)
+		{
+			item = model->getItem(objects.get(i));
+			if (item)
+			{
+				link_inventory_item(
+					gAgent.getID(),
+					item->getUUID(),
+					parent_id,
+					item->getName(),
+					LLAssetType::AT_LINK,
+					LLPointer<LLInventoryCallback>(NULL));
+			}
+		}
+	}
+}
+
 void LLFolderBridge::staticFolderOptionsMenu()
 {
 	if (!sSelf) return;
@@ -1948,6 +2149,9 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv
 // Flags unused
 void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 {
+	mItems.clear();
+	mDisabledItems.clear();
+
 	lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
 //	std::vector<std::string> disabled_items;
 	LLInventoryModel* model = getInventoryModel();
@@ -3116,7 +3320,7 @@ BOOL LLObjectBridge::isItemRemovable()
 {
 	LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
 	if(!avatar) return FALSE;
-	if(avatar->isWearingAttachment(mUUID)) return FALSE;
+	if(avatar->isWearingAttachment(mUUID, TRUE)) return FALSE;
 	return LLInvFVBridge::isItemRemovable();
 }
 
@@ -3125,6 +3329,17 @@ LLUIImagePtr LLObjectBridge::getIcon() const
 	return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
 }
 
+LLInventoryObject* LLObjectBridge::getObject() const
+{
+	LLInventoryObject* object = NULL;
+	LLInventoryModel* model = getInventoryModel();
+	if(model)
+	{
+		object = (LLInventoryObject*)model->getObject(mUUID);
+	}
+	return object;
+}
+
 // virtual
 void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
 {
@@ -3194,15 +3409,21 @@ void LLObjectBridge::openItem()
 
 LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
 { 
+	U8 font = LLFontGL::NORMAL;
+
 	LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
 	if( avatar && avatar->isWearingAttachment( mUUID ) )
 	{
-		return LLFontGL::BOLD;
+		font |= LLFontGL::BOLD;
 	}
-	else
+
+	LLInventoryItem* item = getItem();
+	if (item->getActualType() == LLAssetType::AT_LINK)
 	{
-		return LLFontGL::NORMAL;
+		font |= LLFontGL::ITALIC;
 	}
+	
+	return (LLFontGL::StyleFlags)font;
 }
 
 std::string LLObjectBridge::getLabelSuffix() const
@@ -3223,7 +3444,7 @@ std::string LLObjectBridge::getLabelSuffix() const
 void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
 {
 	LLSD payload;
-	payload["item_id"] = item->getUUID();
+	payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link.
 
 	S32 attach_pt = 0;
 	if (gAgent.getAvatarObject() && attachment)
@@ -3315,7 +3536,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 				items.push_back(std::string("Detach From Yourself"));
 			}
 			else
-			if( !isInTrash() )
+			if( !isInTrash() && !isLinkedObjectInTrash() )
 			{
 				items.push_back(std::string("Attach Separator"));
 				items.push_back(std::string("Object Wear"));
@@ -3381,6 +3602,8 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
 		buildDisplayName(new_item, mDisplayName);
 		new_item->updateServer(FALSE);
 		model->updateItem(new_item);
+		renameLinkedItems(item->getUUID(),new_name);
+
 		model->notifyObservers();
 
 		LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
@@ -4141,23 +4364,10 @@ BOOL LLWearableBridge::renameItem(const std::string& new_name)
 
 BOOL LLWearableBridge::isItemRemovable()
 {
-	if(gAgentWearables.isWearingItem(mUUID)) return FALSE;
+	if (gAgentWearables.isWearingItem(mUUID, TRUE)) return FALSE;
 	return LLInvFVBridge::isItemRemovable();
 }
 
-LLFontGL::StyleFlags LLWearableBridge::getLabelStyle() const
-{ 
-	if( gAgentWearables.isWearingItem( mUUID ) )
-	{
-		// llinfos << "BOLD" << llendl;
-		return LLFontGL::BOLD;
-	}
-	else
-	{
-		return LLFontGL::NORMAL;
-	}
-}
-
 std::string LLWearableBridge::getLabelSuffix() const
 {
 	if( gAgentWearables.isWearingItem( mUUID ) )
@@ -4300,6 +4510,13 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 		{
 			disabled_items.push_back(std::string("Wearable Edit"));
 		}
+		// Don't allow items to be worn if their baseobj is in the trash.
+		if (isLinkedObjectInTrash())
+		{
+			disabled_items.push_back(std::string("Wearable Wear"));
+			disabled_items.push_back(std::string("Wearable Add"));
+			disabled_items.push_back(std::string("Wearable Edit"));
+		}
 
 		if( item && (item->getType() == LLAssetType::AT_CLOTHING) )
 		{
@@ -4534,9 +4751,8 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
 	delete item_id;
 }
 
-
 LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
-									   const LLUUID& uuid,LLInventoryModel* model)
+													   const LLUUID& uuid,LLInventoryModel* model)
 {
 	LLInvFVBridgeAction* action = NULL;
 	switch(asset_type)
@@ -4819,3 +5035,44 @@ void	LLWearableBridgeAction::doIt()
 
 	LLInvFVBridgeAction::doIt();
 }
+
+// +=================================================+
+// |        LLLinkItemBridge                         |
+// +=================================================+
+// For broken links
+
+std::string LLLinkItemBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkItemBridge::getIcon() const
+{
+	return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);
+}
+
+void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+	// *TODO: Translate
+	lldebugs << "LLLink::buildContextMenu()" << llendl;
+	std::vector<std::string> items;
+	std::vector<std::string> disabled_items;
+
+	if(isInTrash())
+	{
+		items.push_back(std::string("Purge Item"));
+		if (!isItemRemovable())
+		{
+			disabled_items.push_back(std::string("Purge Item"));
+		}
+
+		items.push_back(std::string("Restore Item"));
+	}
+	else
+	{	
+		items.push_back(std::string("Delete"));
+		if (!isItemRemovable())
+		{
+			disabled_items.push_back(std::string("Delete"));
+		}
+	}
+	hideContextEntries(menu, items, disabled_items);
+}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 3958f7e9c208e910d7c345f7bf1cd3fcd6ca4ba6..016eb701d673aa2b379618ac1a9213608b04f328 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -167,7 +167,9 @@ class LLInvFVBridge : public LLFolderViewEventListener
 	virtual BOOL copyToClipboard() const { return FALSE; }
 	virtual void cutToClipboard() {}
 	virtual BOOL isClipboardPasteable() const;
+	virtual BOOL isClipboardPasteableAsLink() const;
 	virtual void pasteFromClipboard() {}
+	virtual void pasteLinkFromClipboard() {}
 	void getClipboardEntries(bool show_asset_id, std::vector<std::string> &items, 
 		std::vector<std::string> &disabled_items, U32 flags);
 	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
@@ -191,6 +193,8 @@ class LLInvFVBridge : public LLFolderViewEventListener
 	LLInventoryModel* getInventoryModel() const;
 	
 	BOOL isInTrash() const;
+	BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?
+
 	// return true if the item is in agent inventory. if false, it
 	// must be lost or in the inventory library.
 	BOOL isAgentInventory() const;
@@ -204,11 +208,13 @@ class LLInvFVBridge : public LLFolderViewEventListener
 									 const LLUUID& new_parent,
 									 BOOL restamp);
 	void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch);
-	
+	void renameLinkedItems(const LLUUID &item_id, const std::string& new_name);
+
 protected:
 	LLHandle<LLPanel> mInventoryPanel;
-	LLUUID mUUID;	// item id
+	const LLUUID mUUID;	// item id
 	LLInventoryType::EType mInvType;
+	void purgeItem(LLInventoryModel *model, const LLUUID &uuid);
 };
 
 
@@ -227,6 +233,7 @@ class LLItemBridge : public LLInvFVBridge
 	virtual LLUIImagePtr getIcon() const;
 	virtual const std::string& getDisplayName() const;
 	virtual std::string getLabelSuffix() const;
+	virtual LLFontGL::StyleFlags getLabelStyle() const;
 	virtual PermissionMask getPermissionMask() const;
 	virtual time_t getCreationDate() const;
 	virtual BOOL isItemRenameable() const;
@@ -267,8 +274,8 @@ class LLFolderBridge : public LLInvFVBridge
 	virtual LLUIImagePtr getIcon() const;
 	virtual BOOL renameItem(const std::string& new_name);
 	virtual BOOL removeItem();
-	virtual BOOL isClipboardPasteable() const;
 	virtual void pasteFromClipboard();
+	virtual void pasteLinkFromClipboard();
 	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
 	virtual BOOL hasChildren() const;
 	virtual BOOL dragOrDrop(MASK mask, BOOL drop,
@@ -278,7 +285,9 @@ class LLFolderBridge : public LLInvFVBridge
 	virtual BOOL isItemRemovable();
 	virtual BOOL isItemMovable();
 	virtual BOOL isUpToDate() const;
-
+	virtual BOOL isItemCopyable() const;
+	virtual BOOL copyToClipboard() const;
+	
 	static void createWearable(LLFolderBridge* bridge, EWearableType type);
 	static void createWearable(LLUUID parent_folder_id, EWearableType type);
 
@@ -489,6 +498,8 @@ class LLObjectBridge : public LLItemBridge
 	virtual BOOL			isItemRemovable();
 	virtual BOOL renameItem(const std::string& new_name);
 
+	LLInventoryObject* getObject() const;
+
 protected:
 	LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) :
 		LLItemBridge(inventory, uuid), mInvType(type)
@@ -527,7 +538,6 @@ class LLWearableBridge : public LLItemBridge
 	virtual void	performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
 	virtual void	openItem();
 	virtual void	buildContextMenu(LLMenuGL& menu, U32 flags);
-	virtual LLFontGL::StyleFlags getLabelStyle() const;
 	virtual std::string getLabelSuffix() const;
 	virtual BOOL	isItemRemovable();
 	virtual BOOL renameItem(const std::string& new_name);
@@ -562,8 +572,25 @@ class LLWearableBridge : public LLItemBridge
 	EWearableType  mWearableType;
 };
 
+class LLLinkItemBridge : public LLItemBridge
+{
+	friend class LLInvFVBridge;
+public:
+	virtual const std::string& getPrefix() { return sPrefix; }
+
+	virtual LLUIImagePtr getIcon() const;
+	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+
+protected:
+	LLLinkItemBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
+		LLItemBridge(inventory, uuid) {}
+
+protected:
+	static std::string sPrefix;
+};
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInvFVBridgeAction (& it's derived classes)
+// Class LLInvFVBridgeAction (& its derived classes)
 //
 // This is an implementation class to be able to 
 // perform action to view inventory items.
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 3ee529aedfbc1324bfa930459334258c3ffee55a..665ad5b1a280d255afbe194fd3ecdb3a21508b0c 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -464,6 +464,18 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
 	}
 }
 
+void LLInventoryModel::collectLinkedItems(const LLUUID& id,
+										  item_array_t& items)
+{
+	LLInventoryModel::cat_array_t cat_array;
+	LLLinkedItemIDMatches is_linked_item_match(id);
+	collectDescendentsIf(gAgent.getInventoryRootID(),
+						 cat_array,
+						 items,
+						 LLInventoryModel::INCLUDE_TRASH,
+						 is_linked_item_match);
+}
+
 // Generates a string containing the path to the item specified by
 // item_id.
 void LLInventoryModel::appendPath(const LLUUID& id, std::string& path)
@@ -747,6 +759,7 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id)
 // Delete a particular inventory object by ID.
 void LLInventoryModel::deleteObject(const LLUUID& id)
 {
+	purgeLinkedObjects(id);
 	lldebugs << "LLInventoryModel::deleteObject()" << llendl;
 	LLPointer<LLInventoryObject> obj = getObject(id);
 	if(obj)
@@ -786,6 +799,42 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
 	}
 }
 
+// Delete a particular inventory item by ID, and remove it from the server.
+void LLInventoryModel::purgeObject(const LLUUID &id)
+{
+	lldebugs << "LLInventoryModel::purgeObject()" << llendl;
+	LLPointer<LLInventoryObject> obj = getObject(id);
+	if(obj)
+	{
+		obj->removeFromServer();
+		LLPreview::hide(id);
+		deleteObject(id);
+	}
+}
+
+void LLInventoryModel::purgeLinkedObjects(const LLUUID &id)
+{
+	LLInventoryItem* itemp = getItem(id);
+	if (!itemp) return;
+
+	if (LLAssetType::lookupIsLinkType(itemp->getActualType()))
+	{
+		return;
+	}
+
+	LLInventoryModel::item_array_t item_array;
+	collectLinkedItems(id, item_array);
+	
+	for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
+		 iter != item_array.end();
+		 iter++)
+	{
+		LLViewerInventoryItem *linked_item = (*iter);
+		if (linked_item->getUUID() == id) continue;
+		purgeObject(linked_item->getUUID());
+	}
+}
+
 // This is a method which collects the descendents of the id
 // provided. If the category is not found, no action is
 // taken. This method goes through the long winded process of
@@ -3906,11 +3955,20 @@ void LLInventoryTransactionObserver::changed(U32 mask)
 ///----------------------------------------------------------------------------
 /// LLAssetIDMatches 
 ///----------------------------------------------------------------------------
-bool LLAssetIDMatches ::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+bool LLAssetIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 {
 	return (item && item->getAssetUUID() == mAssetID);
 }
 
+///----------------------------------------------------------------------------
+/// LLLinkedItemIDMatches 
+///----------------------------------------------------------------------------
+bool LLLinkedItemIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+{
+	return (item && 
+			(LLAssetType::lookupIsLinkType(item->getActualType())) &&
+			(item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
+}
 
 ///----------------------------------------------------------------------------
 /// Local function definitions
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 0ba64d20e4a24f9273bf954c9aa506b768d5a5d7..8dc3c1605fa5175730c4b7f815c55c291c171a09 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -35,6 +35,8 @@
 
 #include "llassettype.h"
 #include "lldarray.h"
+#include "llframetimer.h"
+#include "llhttpclient.h"
 #include "lluuid.h"
 #include "llpermissionsflags.h"
 #include "llstring.h"
@@ -111,7 +113,7 @@ class LLInventoryModel
 	LLInventoryModel();
 	~LLInventoryModel();
 
-	class fetchInventoryResponder: public LLHTTPClient::Responder
+	class fetchInventoryResponder : public LLHTTPClient::Responder
 	{
 	public:
 		fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
@@ -167,7 +169,7 @@ class LLInventoryModel
 									item_array_t*& items);
 	void unlockDirectDescendentArrays(const LLUUID& cat_id);
 	
-	// Starting with the object specified, add it's descendents to the
+	// Starting with the object specified, add its descendents to the
 	// array provided, but do not add the inventory object specified
 	// by id. There is no guaranteed order. Neither array will be
 	// erased before adding objects to it. Do not store a copy of the
@@ -185,6 +187,11 @@ class LLInventoryModel
 							  BOOL include_trash,
 							  LLInventoryCollectFunctor& add);
 
+	// Collect all items in inventory that are linked to item_id.
+	// Assumes item_id is itself not a linked item.
+	void collectLinkedItems(const LLUUID& item_id,
+							item_array_t& items);
+	
 	// This method will return false if this inventory model is in an usabel state.
 	// The inventory model usage is sensitive to the initial construction of the 
 	// model. 
@@ -225,8 +232,13 @@ class LLInventoryModel
 	// delete a particular inventory object by ID. This will purge one
 	// object from the internal data structures maintaining a
 	// cosistent internal state. No cache accounting, observer
-	// notification, or server update is performed.
+	// notification, or server update is performed.  Purges linked items.
 	void deleteObject(const LLUUID& id);
+	
+	// delete a particular inventory object by ID, and delete it from
+	// the server.  Also purges linked items via purgeLinkedObjects.
+	void purgeObject(const LLUUID& id);
+	void purgeLinkedObjects(const LLUUID& id);
 
 	// This is a method which collects the descendents of the id
 	// provided. If the category is not found, no action is
@@ -526,6 +538,22 @@ class LLAssetIDMatches : public LLInventoryCollectFunctor
 	LLUUID mAssetID;
 };
 
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLLinkedItemIDMatches
+//
+// This functor finds inventory items linked to the specific inventory id.
+// Assumes the inventory id is itself not a linked item.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLLinkedItemIDMatches : public LLInventoryCollectFunctor
+{
+public:
+	LLLinkedItemIDMatches(const LLUUID& item_id) : mBaseItemID(item_id) {}
+	virtual ~LLLinkedItemIDMatches() {}
+	bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+	
+protected:
+	LLUUID mBaseItemID;
+};
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLIsType
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index 64713108aff4c4e0671848f4d692e17a49bd00c4..676943ff87400cbee8fd4aff6ed8d0ecd21bdc61 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -61,6 +61,7 @@
 LLPreview::LLPreview(const LLSD& key)
 :	LLFloater(key),
 	mItemUUID(key.asUUID()),
+	mObjectUUID(),			// set later by setObjectID()
 	mCopyToInvBtn( NULL ),
 	mForceClose(FALSE),
 	mUserResized(FALSE),
@@ -194,6 +195,13 @@ void LLPreview::changed(U32 mask)
 	mDirty = TRUE;
 }
 
+void LLPreview::setNotecardInfo(const LLUUID& notecard_inv_id, 
+								const LLUUID& object_id)
+{
+	mNotecardInventoryID = notecard_inv_id;
+	mNotecardObjectID = object_id;
+}
+
 void LLPreview::draw()
 {
 	LLFloater::draw();
@@ -338,6 +346,12 @@ void LLPreview::onOpen(const LLSD& key)
 	}
 }
 
+void LLPreview::setAuxItem( const LLInventoryItem* item )
+{
+	if ( mAuxItem ) 
+		mAuxItem->copyItem(item);
+}
+
 // static
 void LLPreview::onBtnCopyToInv(void* userdata)
 {
@@ -349,7 +363,7 @@ void LLPreview::onBtnCopyToInv(void* userdata)
 		// Copy to inventory
 		if (self->mNotecardInventoryID.notNull())
 		{
-			copy_inventory_from_notecard(self->mObjectID,
+			copy_inventory_from_notecard(self->mNotecardObjectID,
 				self->mNotecardInventoryID, item);
 		}
 		else
diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h
index f6042f065bb3bbefb20be232982271913178b7f7..c5f2bfcf47f4febeb6a51bbb9affb3a2b0143cef 100644
--- a/indra/newview/llpreview.h
+++ b/indra/newview/llpreview.h
@@ -35,13 +35,12 @@
 
 #include "llmultifloater.h"
 #include "llresizehandle.h"
-#include "llmap.h"
+#include "llpointer.h"
 #include "lluuid.h"
-#include "llviewerinventory.h"
-#include "lltabcontainer.h"
-#include "llinventorymodel.h"
+#include "llinventorymodel.h"	// LLInventoryObserver
 #include <map>
 
+class LLInventoryItem;
 class LLLineEditor;
 class LLRadioGroup;
 class LLPreview;
@@ -88,11 +87,7 @@ class LLPreview : public LLFloater, LLInventoryObserver
 	virtual BOOL handleHover(S32 x, S32 y, MASK mask);
 	virtual void onOpen(const LLSD& key);
 	
-	void setAuxItem( const LLInventoryItem* item )
-	{
-		if ( mAuxItem ) 
-			mAuxItem->copyItem(item);
-	}
+	void setAuxItem( const LLInventoryItem* item );
 
 	static void			onBtnCopyToInv(void* userdata);
 
@@ -107,11 +102,12 @@ class LLPreview : public LLFloater, LLInventoryObserver
 	virtual EAssetStatus getAssetStatus() { return mAssetStatus;}
 
 	static LLPreview* getFirstPreviewForSource(const LLUUID& source_id);
-	void setNotecardInfo(const LLUUID& notecard_inv_id, const LLUUID& object_id)
-	{ mNotecardInventoryID = notecard_inv_id; mObjectID = object_id; }
+
+	// Why is this at the LLPreview level?  JC
+	void setNotecardInfo(const LLUUID& notecard_inv_id, const LLUUID& object_id);
 
 	// llview
-	virtual void draw();
+	/*virtual*/ void draw();
 	void refreshFromItem();
 	
 protected:
@@ -129,7 +125,7 @@ class LLPreview : public LLFloater, LLInventoryObserver
 protected:
 	LLUUID mItemUUID;
 
-	// mObjectID will have a value if it is associated with a task in
+	// mObjectUUID will have a value if it is associated with a task in
 	// the world, and will be == LLUUID::null if it's in the agent
 	// inventory.
 	LLUUID mObjectUUID;
@@ -152,7 +148,9 @@ class LLPreview : public LLFloater, LLInventoryObserver
 	EAssetStatus mAssetStatus;
 
 	LLUUID mNotecardInventoryID;
-	LLUUID mObjectID;
+	// I am unsure if this is always the same as mObjectUUID, or why it exists
+	// at the LLPreview level.  JC 2009-06-24
+	LLUUID mNotecardObjectID;
 };
 
 
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 9de2f38afffd96bb7c24ff67cc46a80786f90c83..7c50bc59771dcc8d93211362938bf4fa55545eaf 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1424,7 +1424,7 @@ void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id,
 												  bool is_script_running)
 {
 	lldebugs << "LSL Bytecode saved" << llendl;
-	mScriptEd->mErrorList->setCommentText(LLTrans::getString("Compilesuccessful"));
+	mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful"));
 	mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete"));
 	closeIfNeeded();
 }
@@ -1441,6 +1441,7 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors)
 		std::string error_message = line->asString();
 		LLStringUtil::stripNonprintable(error_message);
 		row["columns"][0]["value"] = error_message;
+		// *TODO: change to "MONOSPACE" and change llfontgl.cpp?
 		row["columns"][0]["font"] = "OCRA";
 		mScriptEd->mErrorList->addElement(row);
 	}
@@ -1767,7 +1768,7 @@ void LLLiveLSLEditor::onSearchReplace(void* userdata)
 struct LLLiveLSLSaveData
 {
 	LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, BOOL active);
-	LLUUID mObjectID;
+	LLUUID mSaveObjectID;
 	LLPointer<LLViewerInventoryItem> mItem;
 	BOOL mActive;
 };
@@ -1775,7 +1776,7 @@ struct LLLiveLSLSaveData
 LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
 									 const LLViewerInventoryItem* item,
 									 BOOL active) :
-	mObjectID(id),
+	mSaveObjectID(id),
 	mActive(active)
 {
 	llassert(item);
@@ -1785,7 +1786,7 @@ LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
 void LLLiveLSLEditor::saveIfNeeded()
 {
 	llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl;
-	LLViewerObject* object = gObjectList.findObject(mObjectID);
+	LLViewerObject* object = gObjectList.findObject(mObjectUUID);
 	if(!object)
 	{
 		LLNotifications::instance().add("SaveScriptFailObjectNotFound");
@@ -1865,7 +1866,7 @@ void LLLiveLSLEditor::saveIfNeeded()
 	BOOL is_running = getChild<LLCheckBoxCtrl>( "running")->get();
 	if (!url.empty())
 	{
-		uploadAssetViaCaps(url, filename, mObjectID, mItemUUID, is_running);
+		uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running);
 	}
 	else if (gAssetStorage)
 	{
@@ -1894,7 +1895,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename,
 										const LLTransactionID& tid,
 										BOOL is_running)
 {
-	LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectID,
+	LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectUUID,
 													mItem,
 													is_running);
 	gAssetStorage->storeAssetData(filename, tid,
@@ -1965,7 +1966,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename,
 			getWindow()->incBusyCount();
 			mPendingUploads++;
 			LLLiveLSLSaveData* data = NULL;
-			data = new LLLiveLSLSaveData(mObjectID,
+			data = new LLLiveLSLSaveData(mObjectUUID,
 										 mItem,
 										 is_running);
 			gAssetStorage->storeAssetData(dst_filename,
@@ -2001,7 +2002,7 @@ void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_da
 	}
 	else
 	{
-		LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", data->mItem->getUUID()); //  ^ data->mObjectID
+		LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", data->mItem->getUUID()); //  ^ data->mSaveObjectID
 		if (self)
 		{
 			self->getWindow()->decBusyCount();
@@ -2026,7 +2027,7 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use
 	if(0 ==status)
 	{
 		llinfos << "LSL Bytecode saved" << llendl;
-		LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", data->mItem->getUUID()); //  ^ data->mObjectID
+		LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", data->mItem->getUUID()); //  ^ data->mSaveObjectID
 		if (self)
 		{
 			// Tell the user that the compile worked.
@@ -2040,7 +2041,7 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use
 				self->closeFloater();
 			}
 		}
-		LLViewerObject* object = gObjectList.findObject(data->mObjectID);
+		LLViewerObject* object = gObjectList.findObject(data->mSaveObjectID);
 		if(object)
 		{
 			object->saveScript(data->mItem, data->mActive, false);
@@ -2122,7 +2123,7 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
 void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata)
 {
 	LLLiveLSLEditor* self = static_cast<LLLiveLSLEditor*>(userdata);
-	self->mMonoCheckbox->setEnabled(have_script_upload_cap(self->mObjectID));
+	self->mMonoCheckbox->setEnabled(have_script_upload_cap(self->mObjectUUID));
 	self->mScriptEd->enableSave(self->getIsModifiable());
 }
 
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 9615d00200854256e827d6e294ed03b355c6b0f0..b99dd395847de4c86326d6b8c0b0d1a6f53f1a30 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -34,8 +34,9 @@
 #define LL_LLVIEWERCAMERA_H
 
 #include "llcamera.h"
-#include "lltimer.h"
+#include "llsingleton.h"
 #include "llstat.h"
+#include "lltimer.h"
 #include "m4math.h"
 
 class LLCoordGL;
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 45d24ee7e83c29b819770b3d450a394c320d13d4..2c79e67ebcd5f9923074bb2a0869f8269e927bc5 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -244,8 +244,7 @@ BOOL LLViewerInventoryItem::unpackMessage(LLSD item)
 }
 
 // virtual
-BOOL LLViewerInventoryItem::unpackMessage(
-	LLMessageSystem* msg, const char* block, S32 block_num)
+BOOL LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
 {
 	BOOL rv = LLInventoryItem::unpackMessage(msg, block, block_num);
 	mIsComplete = TRUE;
@@ -742,6 +741,32 @@ void copy_inventory_item(
 	gAgent.sendReliableMessage();
 }
 
+void link_inventory_item(
+	const LLUUID& agent_id,
+	const LLUUID& item_id,
+	const LLUUID& parent_id,
+	const std::string& new_name,
+	const LLAssetType::EType asset_type,
+	LLPointer<LLInventoryCallback> cb)
+{
+	LLMessageSystem* msg = gMessageSystem;
+	msg->newMessageFast(_PREHASH_LinkInventoryItem);
+	msg->nextBlockFast(_PREHASH_AgentData);
+	{
+		msg->addUUIDFast(_PREHASH_AgentID, agent_id);
+		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+	}
+	msg->nextBlockFast(_PREHASH_InventoryData);
+	{
+		msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
+		msg->addUUIDFast(_PREHASH_FolderID, parent_id);
+		msg->addUUIDFast(_PREHASH_OldItemID, item_id);
+		msg->addStringFast(_PREHASH_Name, new_name);
+		msg->addU8Fast(_PREHASH_AssetType, asset_type);
+	}
+	gAgent.sendReliableMessage();
+}
+
 void move_inventory_item(
 	const LLUUID& agent_id,
 	const LLUUID& session_id,
@@ -948,26 +973,19 @@ void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, co
 
 LLAssetType::EType LLViewerInventoryItem::getType() const
 {
-	if (mType == LLAssetType::AT_LINK)
+	if (const LLViewerInventoryItem *linked_item = getLinkedItem())
 	{
-		LLInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
-		if (linked_item)
-		{
-			return linked_item->getType();
-		}
+		return linked_item->getType();
 	}
+	
 	return LLInventoryItem::getType();
 }
 
 const LLUUID& LLViewerInventoryItem::getAssetUUID() const
 {
-	if (mType == LLAssetType::AT_LINK)
+	if (const LLViewerInventoryItem *linked_item = getLinkedItem())
 	{
-		LLInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
-		if (linked_item)
-		{
-			return linked_item->getAssetUUID();
-		}
+		return linked_item->getAssetUUID();
 	}
 
 	return LLInventoryItem::getAssetUUID();
@@ -975,11 +993,96 @@ const LLUUID& LLViewerInventoryItem::getAssetUUID() const
 
 const std::string& LLViewerInventoryItem::getName() const
 {
-	if (mType == LLAssetType::AT_LINK)
+	if (const LLViewerInventoryItem *linked_item = getLinkedItem())
 	{
-		return LLInventoryItem::getName(); //+" link";
+		return linked_item->getName();
 	}
 
 	return LLInventoryItem::getName();
 }
 
+const LLPermissions& LLViewerInventoryItem::getPermissions() const
+{
+	// Use the actual permissions of the symlink, not its parent.
+	return LLInventoryItem::getPermissions();	
+}
+
+const LLUUID& LLViewerInventoryItem::getCreatorUUID() const
+{
+	if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+	{
+		return linked_item->getCreatorUUID();
+	}
+
+	return LLInventoryItem::getCreatorUUID();
+}
+
+const std::string& LLViewerInventoryItem::getDescription() const
+{
+	if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+	{
+		return linked_item->getDescription();
+	}
+
+	return LLInventoryItem::getDescription();
+}
+
+const LLSaleInfo& LLViewerInventoryItem::getSaleInfo() const
+{	
+	if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+	{
+		return linked_item->getSaleInfo();
+	}
+
+	return LLInventoryItem::getSaleInfo();
+}
+
+LLInventoryType::EType LLViewerInventoryItem::getInventoryType() const
+{
+	if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+	{
+		return linked_item->getInventoryType();
+	}
+
+	return LLInventoryItem::getInventoryType();
+}
+
+U32 LLViewerInventoryItem::getFlags() const
+{
+	if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+	{
+		return linked_item->getFlags();
+	}
+
+	return LLInventoryItem::getFlags();
+}
+
+time_t LLViewerInventoryItem::getCreationDate() const
+{
+	return LLInventoryItem::getCreationDate();
+}
+
+U32 LLViewerInventoryItem::getCRC32() const
+{
+	return LLInventoryItem::getCRC32();	
+}
+
+const LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const
+{
+	if (mType == LLAssetType::AT_LINK)
+	{
+		const LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
+		return linked_item;
+	}
+	return NULL;
+}
+
+const LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
+{
+	if (mType == LLAssetType::AT_LINK_FOLDER)
+	{
+		const LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID);
+		return linked_category;
+	}
+	return NULL;
+}
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 8318931dde1bad52b5aa6a345bc3ce8a7ad38ad2..7084c9f37ae5cbf17437651ddeb3e5e065467c8b 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -39,6 +39,7 @@
 
 class LLFolderView;
 class LLFolderBridge;
+class LLViewerInventoryCategory;
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLViewerInventoryItem
@@ -59,7 +60,15 @@ class LLViewerInventoryItem : public LLInventoryItem
 	virtual LLAssetType::EType getType() const;
 	virtual const LLUUID& getAssetUUID() const;
 	virtual const std::string& getName() const;
-	
+	virtual const LLPermissions& getPermissions() const;
+	virtual const LLUUID& getCreatorUUID() const;
+	virtual const std::string& getDescription() const;
+	virtual const LLSaleInfo& getSaleInfo() const;
+	virtual LLInventoryType::EType getInventoryType() const;
+	virtual U32 getFlags() const;
+	virtual time_t getCreationDate() const;
+	virtual U32 getCRC32() const; // really more of a checksum.
+
 	// construct a complete viewer inventory item
 	LLViewerInventoryItem(const LLUUID& uuid, const LLUUID& parent_uuid,
 						  const LLPermissions& permissions,
@@ -133,6 +142,9 @@ class LLViewerInventoryItem : public LLInventoryItem
 	LLTransactionID getTransactionID() const { return mTransactionID; }
 	
 protected:
+	const LLViewerInventoryItem *getLinkedItem() const;
+	const LLViewerInventoryCategory *getLinkedCategory() const;
+
 	BOOL mIsComplete;
 	LLTransactionID mTransactionID;
 };
@@ -279,6 +291,14 @@ void copy_inventory_item(
 	const std::string& new_name,
 	LLPointer<LLInventoryCallback> cb);
 
+void link_inventory_item(
+	const LLUUID& agent_id,
+	const LLUUID& item_id,
+	const LLUUID& parent_id,
+	const std::string& new_name,
+	const LLAssetType::EType asset_type,
+	LLPointer<LLInventoryCallback> cb);
+
 void move_inventory_item(
 	const LLUUID& agent_id,
 	const LLUUID& session_id,
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index 90a54e2b9cf3c830b80c5821fc3b19b8025d9f96..c15e5df675a717ccc06bf0c4477d6e553babdc21 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -34,6 +34,7 @@
 #define LL_LLVIEWERMESSAGE_H
 
 #include "llinstantmessage.h"
+#include "llpointer.h"
 #include "lltransactiontypes.h"
 #include "lluuid.h"
 #include "stdenums.h"
@@ -42,10 +43,11 @@
 // Forward declarations
 //
 class LLColor4;
-class LLViewerObject;
 class LLInventoryObject;
 class LLInventoryItem;
+class LLMeanCollisionData;
 class LLMessageSystem;
+class LLViewerObject;
 class LLViewerRegion;
 
 //
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index dc4f2b2990e917f033d30bd09390b9e82102d0b2..a96ccfd84894a2fd9793cdc60fe37c49c68b403b 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -512,15 +512,24 @@ BOOL LLViewerObject::isOverGroupOwnedLand() const
 		&& mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion());
 }
 
-void LLViewerObject::setParent(LLViewerObject* parent)
+BOOL LLViewerObject::setParent(LLViewerObject* parent)
 {
-	LLPrimitive::setParent(parent);
+	if(mParent != parent)
+	{
+		LLViewerObject* old_parent = (LLViewerObject*)mParent ;		
+		BOOL ret = LLPrimitive::setParent(parent);
+		if(ret && old_parent && parent)
+		{
+			old_parent->removeChild(this) ;
+		}
+		return ret ;
+	}
+
+	return FALSE ;
 }
 
 void LLViewerObject::addChild(LLViewerObject *childp)
 {
-	BOOL result = TRUE;
-	
 	for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
 	{
 		if (*i == childp)
@@ -535,18 +544,9 @@ void LLViewerObject::addChild(LLViewerObject *childp)
 		childp->mbCanSelect = mbCanSelect;
 	}
 
-	childp->setParent(this);
-	mChildList.push_back(childp);
-
-	if (!result) 
+	if(childp->setParent(this))
 	{
-		llwarns << "Failed to attach child " << childp->getID() << " to object " << getID() << llendl;
-		removeChild(childp);
-		if (mJointInfo)
-		{
-			delete mJointInfo;
-			mJointInfo = NULL;
-		}
+		mChildList.push_back(childp);
 	}
 }
 
@@ -562,7 +562,11 @@ void LLViewerObject::removeChild(LLViewerObject *childp)
 			}
 
 			mChildList.erase(i);
-			childp->setParent(NULL);			
+
+			if(childp->getParent() == this)
+			{
+				childp->setParent(NULL);			
+			}
 			break;
 		}
 	}
@@ -644,11 +648,14 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
 		return FALSE;
 	}
 
+	BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
+	if(!ret)
+	{
+		return FALSE ;
+	}
 	LLDrawable* old_parent = mDrawable->mParent;
-
 	mDrawable->mParent = parentp; 
-	
-	BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
+		
 	gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
 	if(	old_parent != parentp &&
 		old_parent || (parentp && parentp->isActive()))
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 21a99c58d9e58debd3f8a1e77b16fb6bc50622d5..2b2c2d5a95d57de9a60bbe2ed972947de0a02f9a 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -64,6 +64,7 @@ class LLWorld;
 class LLNameValue;
 class LLNetMap;
 class LLMessageSystem;
+class LLPartSysData;
 class LLPrimitive;
 class LLPipeline;
 class LLTextureEntry;
@@ -236,7 +237,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount
 	BOOL isProbablyModifiable() const;
 	*/
 
-	virtual void setParent(LLViewerObject* parent);
+	virtual BOOL setParent(LLViewerObject* parent);
 	virtual void addChild(LLViewerObject *childp);
 	virtual void removeChild(LLViewerObject *childp);
 	const_child_list_t& getChildren() const { 	return mChildList; }
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 0f906a4d7f9c125f494e42a7ada2aaf037c5cfbf..ace5c5038e7d39d16d32f0b137eaaf86dd3391f7 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -39,11 +39,13 @@
 // common includes
 #include "llstat.h"
 #include "lldarrayptr.h"
+#include "llmap.h"			// *TODO: switch to std::map
 #include "llstring.h"
 
 // project includes
 #include "llviewerobject.h"
 
+class LLCamera;
 class LLNetMap;
 class LLDebugBeacon;
 
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 35f374a4c8f4d777948e76a52bbb7072b0b1e800..49d0900f2ace9f36b6f4d30bb204ed29faff3f9e 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -51,6 +51,7 @@
 #include "llweb.h"
 #include "llcapabilityprovider.h"
 #include "llcapabilitylistener.h"
+#include "m4math.h"					// LLMatrix4
 
 // Surface id's
 #define LAND  1
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index fb501b023f6d46b3745957eca842e6a062675130..5c9f8af2169930c76a8eda5069c2098c6efa72cc 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1269,6 +1269,8 @@ LLViewerWindow::LLViewerWindow(
 
 	LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert);
 	LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert);
+	LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));
+	llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl;
 
 	// Default to application directory.
 	LLViewerWindow::sSnapshotBaseName = "Snapshot";
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 176f8fb37bae65f2c94d454ff5137c3c13b8a95d..c2b54ec9c6c363dc4f7ace3023ad7e3d3d6f1fe6 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5315,12 +5315,13 @@ void LLVOAvatar::hideSkirt()
 	mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE);
 }
 
-void LLVOAvatar::setParent(LLViewerObject* parent)
+BOOL LLVOAvatar::setParent(LLViewerObject* parent)
 {
+	BOOL ret ;
 	if (parent == NULL)
 	{
 		getOffObject();
-		LLViewerObject::setParent(parent);
+		ret = LLViewerObject::setParent(parent);
 		if (isSelf())
 		{
 			gAgent.resetCamera();
@@ -5328,9 +5329,13 @@ void LLVOAvatar::setParent(LLViewerObject* parent)
 	}
 	else
 	{
-		LLViewerObject::setParent(parent);
-		sitOnObject(parent);
+		ret = LLViewerObject::setParent(parent);
+		if(ret)
+		{
+			sitOnObject(parent);
+		}
 	}
+	return ret ;
 }
 
 void LLVOAvatar::addChild(LLViewerObject *childp)
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 301c032b25453cbe110e14fb19ccf786ed054140..b22c0deb3378a8820f766f2c10ef240b58d38659 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -39,6 +39,7 @@
 #include <string>
 #include <vector>
 
+#include "imageids.h"			// IMG_INVISIBLE
 #include "llchat.h"
 #include "lldrawpoolalpha.h"
 #include "llviewerobject.h"
@@ -49,6 +50,7 @@
 #include "llvoavatardefines.h"
 #include "lltexglobalcolor.h"
 #include "lldriverparam.h"
+#include "material_codes.h"		// LL_MCODE_END
 
 extern const LLUUID ANIM_AGENT_BODY_NOISE;
 extern const LLUUID ANIM_AGENT_BREATHE_ROT;
@@ -774,7 +776,7 @@ class LLVOAvatar :
  **/
 
 public:
-	virtual void 	setParent(LLViewerObject* parent);
+	virtual BOOL 	setParent(LLViewerObject* parent);
 	virtual void 	addChild(LLViewerObject *childp);
 	virtual void 	removeChild(LLViewerObject *childp);
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index d629767bbe9497f53bd8ca24ef319d35bf304c03..e7d7d74f62b4b0fcd2aa6ce4c3533ac5fdd9cdca 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -907,18 +907,43 @@ void LLVOAvatarSelf::wearableUpdated( EWearableType type )
 //-----------------------------------------------------------------------------
 // isWearingAttachment()
 //-----------------------------------------------------------------------------
-BOOL LLVOAvatarSelf::isWearingAttachment( const LLUUID& inv_item_id )
+// Warning: include_linked_items = TRUE makes this operation expensive.
+BOOL LLVOAvatarSelf::isWearingAttachment( const LLUUID& inv_item_id , BOOL include_linked_items ) const
 {
-	for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
+	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); 
 		 iter != mAttachmentPoints.end(); )
 	{
-		attachment_map_t::iterator curiter = iter++;
-		LLViewerJointAttachment* attachment = curiter->second;
+		attachment_map_t::const_iterator curiter = iter++;
+		const LLViewerJointAttachment* attachment = curiter->second;
 		if( attachment->getItemID() == inv_item_id )
 		{
 			return TRUE;
 		}
 	}
+
+	if (include_linked_items)
+	{
+		LLInventoryModel::item_array_t item_array;
+		gInventory.collectLinkedItems(inv_item_id, item_array);
+		for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
+			 iter != item_array.end();
+			 iter++)
+		{
+			const LLViewerInventoryItem *linked_item = (*iter);
+			const LLUUID &item_id = linked_item->getUUID();
+			for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); 
+				 iter != mAttachmentPoints.end(); )
+			{
+				attachment_map_t::const_iterator curiter = iter++;
+				const LLViewerJointAttachment* attachment = curiter->second;
+				if( attachment->getItemID() == item_id )
+				{
+					return TRUE;
+				}
+			}
+		}
+	}
+
 	return FALSE;
 }
 
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 431c814382b8ec8d3f299fb478992218e5dd07b9..02a77cba908b36ec1e07a7a87e8a986793814a1b 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -267,7 +267,7 @@ class LLVOAvatarSelf :
 	//--------------------------------------------------------------------
 public:
 	void 				updateAttachmentVisibility(U32 camera_mode);
-	BOOL 				isWearingAttachment(const LLUUID& inv_item_id);
+	BOOL 				isWearingAttachment(const LLUUID& inv_item_id, BOOL include_linked_items = FALSE) const;
 	LLViewerObject* 	getWornAttachment(const LLUUID& inv_item_id ) const;
 	const std::string   getAttachedPointName(const LLUUID& inv_item_id) const;
 	/*virtual*/ LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 1066ac73f13992f3e4c797a2589e81675d934443..8b3bbb68bb218ef1ff164199bbcc90f5dc101bc7 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -43,6 +43,7 @@ class LLVivoxProtocolParser;
 #include "llframetimer.h"
 #include "llviewerregion.h"
 #include "llcallingcard.h"   // for LLFriendObserver
+#include "m3math.h"			// LLMatrix3
 
 class LLVoiceClientParticipantObserver
 {
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index aff8fe8f1d77e5d3ebf32eabd305cc4d10f98a60..f31f09f60e8a24a84f863c6b873a70fa8fef06d9 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -934,17 +934,20 @@ void LLVOVolume::updateFaceFlags()
 	}
 }
 
-void LLVOVolume::setParent(LLViewerObject* parent)
+BOOL LLVOVolume::setParent(LLViewerObject* parent)
 {
+	BOOL ret = FALSE ;
 	if (parent != getParent())
 	{
-		LLViewerObject::setParent(parent);
-		if (mDrawable)
+		ret = LLViewerObject::setParent(parent);
+		if (ret && mDrawable)
 		{
 			gPipeline.markMoved(mDrawable);
 			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
 		}
 	}
+
+	return ret ;
 }
 
 // NOTE: regenFaces() MUST be followed by genTriangles()!
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 9b4e715194448c639b7cae901874e804ed517065..5d7b373b3cfd8e6c4b4e6fb8a220b980c1d84b62 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -37,6 +37,8 @@
 #include "llviewerimage.h"
 #include "llframetimer.h"
 #include "llapr.h"
+#include "m3math.h"		// LLMatrix3
+#include "m4math.h"		// LLMatrix4
 #include <map>
 
 class LLViewerTextureAnim;
@@ -105,7 +107,7 @@ class LLVOVolume : public LLViewerObject
 	/*virtual*/ BOOL	isHUDAttachment() const;
 
 				void	generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
-	/*virtual*/	void	setParent(LLViewerObject* parent);
+	/*virtual*/	BOOL	setParent(LLViewerObject* parent);
 				S32		getLOD() const							{ return mLOD; }
 	const LLVector3		getPivotPositionAgent() const;
 	const LLMatrix4&	getRelativeXform() const				{ return mRelativeXform; }
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index 92de94636bf659b957c5cc1e43f4477c0f589fb9..1275312676d93cfc3e3bcce17f79329768efb417 100644
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -77,14 +77,17 @@ LLWearableList::~LLWearableList()
 void LLWearableList::getAsset(const LLAssetID& _assetID, const std::string& wearable_name, LLAssetType::EType asset_type, void(*asset_arrived_callback)(LLWearable*, void* userdata), void* userdata)
 {
 	LLAssetID assetID = _assetID;
-	if (asset_type == LLAssetType::AT_LINK)
+
+	// A bit of a hack since wearables database doesn't contain asset types...
+	// Perform indirection in case this assetID is in fact a link.  This only works
+	// because of the assumption that all assetIDs and itemIDs are unique (i.e.
+	// no assetID is also used as an itemID elsewhere); therefore if the assetID
+	// exists as an itemID in the user's inventory, then this must be a link.
+	const LLInventoryItem *linked_item = gInventory.getItem(_assetID);
+	if (linked_item)
 	{
-		LLInventoryItem *linked_item = gInventory.getItem(_assetID);
-		if (linked_item)
-		{
-			assetID = linked_item->getAssetUUID();
-			asset_type = linked_item->getType();
-		}
+		assetID = linked_item->getAssetUUID();
+		asset_type = linked_item->getType();
 	}
 	llassert( (asset_type == LLAssetType::AT_CLOTHING) || (asset_type == LLAssetType::AT_BODYPART) );
 	LLWearable* instance = get_if_there(mList, assetID, (LLWearable*)NULL );
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index c017e9b64f9fcfee289e74bc1709d0f54d4dc683..5358fce766491e384eadf49b862ae90f95950d1d 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -33,6 +33,7 @@
 #ifndef LL_PIPELINE_H
 #define LL_PIPELINE_H
 
+#include "llcamera.h"
 #include "llerror.h"
 #include "lldarrayptr.h"
 #include "lldqueueptr.h"
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index f4fd6b01b4fa12341a2f8c52f7ca518b8744f471..afac4a4051c955223e4059bdd65fc6d4102b7fa2 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -1,32 +1,32 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater 
- background_opaque="false"
- background_visible="true" 
- bevel_style="in"
- bg_alpha_color="0.3 0.3 0.3 1.0"
- height="300"
- layout="topleft"
- name="nearby_chat"
- save_rect="true"
- title="Nearby Chat"
- width="320">
-	<panel top="20" width="320" height="30" background_visible="true" background_opaque="false" bg_alpha_color="0.0 0.0 0.0 1.0" name="chat_caption">
-    	<text
-        	width="140" left="25" height="20" follows="left|right|top"
-        	font="SansSerifBigBold" text_color="white" word_wrap="true"
-        	mouse_opaque="true" name="sender_name" >NEARBY CHAT  </text>
-    	<icon top="5" left="250"
-      			width="20" height="20" follows="top|right"
-		      	color="1 1 1 1" enabled="true" image_name="icn_voice-groupfocus.tga"
-      			mouse_opaque="true" name="nearby_speakers_btn"/>
-    	<icon top="5" left="275"
-      		width="20" height="20" follows="top|right"
-      		color="1 1 1 1" enabled="true" image_name="inv_item_landmark_visited.tga"
-      		mouse_opaque="true" name="tearoff_btn"/>
-    	<icon top="5" left="300"
-      		width="15" height="15" follows="top|right"
-      		color="1 1 1 1" enabled="true" image_name="closebox.tga"
-      		name="close_btn"/>
-	</panel>
-  <chat_history_view bottom="0" width="250" height="320" follows="left|right|top|bottom" name="chat_scroll" />
-</floater>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater 
+ background_opaque="false"
+ background_visible="true" 
+ bevel_style="in"
+ bg_alpha_color="0.3 0.3 0.3 1.0"
+ height="300"
+ layout="topleft"
+ name="nearby_chat"
+ save_rect="true"
+ title="Nearby Chat"
+ width="320">
+	<panel top="20" width="320" height="30" background_visible="true" background_opaque="false" bg_alpha_color="0.0 0.0 0.0 1.0" name="chat_caption">
+    	<text
+        	width="140" left="25" height="20" follows="left|right|top"
+        	font="SansSerifBigBold" text_color="white" word_wrap="true"
+        	mouse_opaque="true" name="sender_name" >NEARBY CHAT  </text>
+    	<icon top="5" left="250"
+      			width="20" height="20" follows="top|right"
+		      	color="1 1 1 1" enabled="true" image_name="icn_voice-groupfocus.tga"
+      			mouse_opaque="true" name="nearby_speakers_btn"/>
+    	<icon top="5" left="275"
+      		width="20" height="20" follows="top|right"
+      		color="1 1 1 1" enabled="true" image_name="inv_item_landmark_visited.tga"
+      		mouse_opaque="true" name="tearoff_btn"/>
+    	<icon top="5" left="300"
+      		width="15" height="15" follows="top|right"
+      		color="1 1 1 1" enabled="true" image_name="closebox.tga"
+      		name="close_btn"/>
+	</panel>
+  <chat_history_view bottom="0" width="250" height="320" follows="left|right|top|bottom" name="chat_scroll" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_combobox.xml b/indra/newview/skins/default/xui/en/floater_test_combobox.xml
index 9e1253ec565503886364f1fbf77d9b63315892da..4bc1b8b6442c7781183c8d7c45684303f4d7f750 100644
--- a/indra/newview/skins/default/xui/en/floater_test_combobox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_combobox.xml
@@ -1,143 +1,143 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- can_resize="true"
- height="400"
- layout="topleft"
- name="floater_test_combobox"
- width="400">
-    <text
-     type="string"
-     length="1"
-     height="16"
-     layout="topleft"
-     left="10"
-     top="24"
-     width="200">
-        Real world usage (login location):
-    </text>
-    <combo_box
-     allow_text_entry="true"
-     control_name="LoginLocation"
-     follows="left|bottom"
-     height="18"
-     layout="topleft"
-     left_delta="0"
-     max_chars="128"
-     name="start_location_combo"
-     top_pad="2"
-     width="155">
-        <combo_box.item
-         label="My Last Location"
-         value="last" />
-        <combo_box.item
-         label="My Home"
-         value="home" />
-        <combo_box.item
-         label="&lt;Type region name&gt;"
-         value="" />
-    </combo_box>
-    <text
-     type="string"
-     length="1"
-     height="16"
-     layout="topleft"
-     left_delta="0"
-     top_pad="24"
-     width="200">
-        Minimal combobox:
-    </text>
-    <combo_box
-     height="18"
-     layout="topleft"
-     left_delta="0"
-     name="minimal_combo"
-     top_pad="2"
-     width="150">
-        <combo_box.item
-         label="First Item"
-         value="first" />
-        <combo_box.item
-         label="Second Item"
-         value="second" />
-    </combo_box>
-    <text
-     type="string"
-     length="1"
-     height="16"
-     layout="topleft"
-     left_delta="0"
-     top_pad="24"
-     width="200">
-        Allow text input:
-    </text>
-    <combo_box
-     allow_text_entry="true"
-     height="18"
-     layout="topleft"
-     left_delta="0"
-     name="text_entry_combo"
-     top_pad="2"
-     width="150">
-        <combo_box.item
-         label="First Item"
-         value="first" />
-        <combo_box.item
-         label="Second Item"
-         value="second" />
-    </combo_box>
-    <text
-     type="string"
-     length="1"
-     height="16"
-     layout="topleft"
-     left_delta="0"
-     top_pad="24"
-     width="200">
-        Allow text input, default to second item:
-    </text>
-    <combo_box
-     allow_text_entry="true"
-     height="18"
-     initial_value="second"
-     layout="topleft"
-     left_delta="0"
-     name="text_entry_combo"
-     top_pad="2"
-     width="150">
-        <combo_box.item
-         label="First Item"
-         value="first" />
-        <combo_box.item
-         label="Second Item"
-         value="second" />
-    </combo_box>
-    <text
-     type="string"
-     length="1"
-     height="16"
-     layout="topleft"
-     left_delta="0"
-     top_pad="24"
-     width="200">
-        Two character max input:
-    </text>
-    <combo_box
-     allow_text_entry="true"
-     height="16"
-     layout="topleft"
-     left_delta="0"
-     max_chars="2"
-     name="state_combo"
-     top_pad="4"
-     width="150">
-        <combo_box.item
-         label="CA"
-         value="ca" />
-        <combo_box.item
-         label="NY"
-         value="ny" />
-        <combo_box.item
-         label="TX"
-         value="tx" />
-    </combo_box>
-</floater>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ name="floater_test_combobox"
+ width="400">
+    <text
+     type="string"
+     length="1"
+     height="16"
+     layout="topleft"
+     left="10"
+     top="24"
+     width="200">
+        Real world usage (login location):
+    </text>
+    <combo_box
+     allow_text_entry="true"
+     control_name="LoginLocation"
+     follows="left|bottom"
+     height="18"
+     layout="topleft"
+     left_delta="0"
+     max_chars="128"
+     name="start_location_combo"
+     top_pad="2"
+     width="155">
+        <combo_box.item
+         label="My Last Location"
+         value="last" />
+        <combo_box.item
+         label="My Home"
+         value="home" />
+        <combo_box.item
+         label="&lt;Type region name&gt;"
+         value="" />
+    </combo_box>
+    <text
+     type="string"
+     length="1"
+     height="16"
+     layout="topleft"
+     left_delta="0"
+     top_pad="24"
+     width="200">
+        Minimal combobox:
+    </text>
+    <combo_box
+     height="18"
+     layout="topleft"
+     left_delta="0"
+     name="minimal_combo"
+     top_pad="2"
+     width="150">
+        <combo_box.item
+         label="First Item"
+         value="first" />
+        <combo_box.item
+         label="Second Item"
+         value="second" />
+    </combo_box>
+    <text
+     type="string"
+     length="1"
+     height="16"
+     layout="topleft"
+     left_delta="0"
+     top_pad="24"
+     width="200">
+        Allow text input:
+    </text>
+    <combo_box
+     allow_text_entry="true"
+     height="18"
+     layout="topleft"
+     left_delta="0"
+     name="text_entry_combo"
+     top_pad="2"
+     width="150">
+        <combo_box.item
+         label="First Item"
+         value="first" />
+        <combo_box.item
+         label="Second Item"
+         value="second" />
+    </combo_box>
+    <text
+     type="string"
+     length="1"
+     height="16"
+     layout="topleft"
+     left_delta="0"
+     top_pad="24"
+     width="200">
+        Allow text input, default to second item:
+    </text>
+    <combo_box
+     allow_text_entry="true"
+     height="18"
+     initial_value="second"
+     layout="topleft"
+     left_delta="0"
+     name="text_entry_combo"
+     top_pad="2"
+     width="150">
+        <combo_box.item
+         label="First Item"
+         value="first" />
+        <combo_box.item
+         label="Second Item"
+         value="second" />
+    </combo_box>
+    <text
+     type="string"
+     length="1"
+     height="16"
+     layout="topleft"
+     left_delta="0"
+     top_pad="24"
+     width="200">
+        Two character max input:
+    </text>
+    <combo_box
+     allow_text_entry="true"
+     height="16"
+     layout="topleft"
+     left_delta="0"
+     max_chars="2"
+     name="state_combo"
+     top_pad="4"
+     width="150">
+        <combo_box.item
+         label="CA"
+         value="ca" />
+        <combo_box.item
+         label="NY"
+         value="ny" />
+        <combo_box.item
+         label="TX"
+         value="tx" />
+    </combo_box>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 808618ba9685fc55c0faa80f1cfda64651697ca1..6f2fd5e5e5ee29b7b6551b1fa6d6279ab852cb5b 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -320,6 +320,14 @@
          function="Inventory.DoToSelected"
          parameter="paste" />
     </menu_item_call>
+    <menu_item_call
+     label="Paste As Link"
+     layout="topleft"
+     name="Paste As Link">
+        <menu_item_call.on_click
+         function="Inventory.DoToSelected"
+         parameter="paste_link" />
+    </menu_item_call>
     <menu_item_separator
      layout="topleft" />
     <menu_item_call
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 5a452bd70629aef044aa589ac6b4ae1c2e8d6009..f059f4f3c141de0b8a09e9c253f91685b93fb5e1 100644
--- a/indra/newview/skins/default/xui/en/panel_script_ed.xml
+++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml
@@ -1,190 +1,190 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel
- bevel_style="none"
- border_style="line"
- bottom="550"
- follows="left|top|right|bottom"
- height="508"
- layout="topleft"
- left="0"
- name="script panel"
- width="500">
-    <panel.string
-     name="loading">
-        Loading...
-    </panel.string>
-    <panel.string
-     name="can_not_view">
-        You are not allowed to view this script.
-    </panel.string>
-    <panel.string
-     name="public_objects_can_not_run">
-        Public Objects cannot run scripts
-    </panel.string>
-    <panel.string
-     name="script_running">
-        Running
-    </panel.string>
-    <panel.string
-     name="Title">
-        Script: [NAME]
-    </panel.string>
-    <text_editor
-     type="string"
-     length="1"
-     bevel_style="none"
-     border_style="line"
-     bottom="393"
-     follows="left|top|right|bottom"
-     font="Monospace"
-     height="376"
-     ignore_tab="false"
-     layout="topleft"
-     left="4"
-     max_length="65536"
-     name="Script Editor"
-     width="492"
-     word_wrap="true">
-        Loading...
-    </text_editor>
-    <button
-     bottom="499"
-     follows="right|bottom"
-     height="20"
-     label="Save"
-     label_selected="Save"
-     layout="topleft"
-     left="360"
-     name="Save_btn"
-     width="128" />
-    <scroll_list
-     bottom="457"
-     follows="left|right|bottom"
-     height="60"
-     layout="topleft"
-     left="4"
-     name="lsl errors"
-     width="492" />
-    <combo_box
-     bottom="499"
-     follows="left|bottom"
-     height="20"
-     label="Insert..."
-     layout="topleft"
-     left="12"
-     name="Insert..."
-     width="128" />
-    <text
-     bottom="473"
-     follows="left|bottom"
-     height="12"
-     layout="topleft"
-     left="12"
-     name="line_col"
-     width="128" />
-    <menu_bar
-     bg_visible="false"
-     bottom="18"
-     follows="left|top|right"
-     height="18"
-     layout="topleft"
-     left="8"
-     mouse_opaque="false"
-     name="script_menu"
-     width="476">
-        <menu
-         bottom="18"
-         height="62"
-         label="File"
-         layout="topleft"
-         left="0"
-         mouse_opaque="false"
-         name="File"
-         width="138">
-            <menu_item_call
-             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>
-        <menu
-         bottom="-647"
-         height="198"
-         label="Edit"
-         layout="topleft"
-         left="222"
-         mouse_opaque="false"
-         name="Edit"
-         width="139">
-            <menu_item_call
-             enabled="false"
-             label="Undo"
-             layout="topleft"
-             name="Undo" />
-            <menu_item_call
-             enabled="false"
-             label="Redo"
-             layout="topleft"
-             name="Redo" />
-            <menu_item_separator
-             layout="topleft" />
-            <menu_item_call
-             enabled="false"
-             label="Cut"
-             layout="topleft"
-             name="Cut" />
-            <menu_item_call
-             enabled="false"
-             label="Copy"
-             layout="topleft"
-             name="Copy" />
-            <menu_item_call
-             enabled="false"
-             label="Paste"
-             layout="topleft"
-             name="Paste" />
-            <menu_item_separator
-             layout="topleft"
-             name="separator2" />
-            <menu_item_call
-             label="Select All"
-             layout="topleft"
-             name="Select All" />
-            <menu_item_call
-             enabled="false"
-             label="Deselect"
-             layout="topleft"
-             name="Deselect" />
-            <menu_item_separator
-             layout="topleft"
-             name="separator3" />
-            <menu_item_call
-             label="Search / Replace..."
-             layout="topleft"
-             name="Search / Replace..." />
-        </menu>
-        <menu
-         bottom="18"
-         height="34"
-         label="Help"
-         layout="topleft"
-         left="0"
-         mouse_opaque="false"
-         name="Help"
-         width="112">
-            <menu_item_call
-             label="Help..."
-             layout="topleft"
-             name="Help..." />
-            <menu_item_call
-             label="LSL Wiki Help..."
-             layout="topleft"
-             name="LSL Wiki Help..." />
-        </menu>
-    </menu_bar>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ bevel_style="none"
+ border_style="line"
+ bottom="550"
+ follows="left|top|right|bottom"
+ height="508"
+ layout="topleft"
+ left="0"
+ name="script panel"
+ width="500">
+    <panel.string
+     name="loading">
+        Loading...
+    </panel.string>
+    <panel.string
+     name="can_not_view">
+        You are not allowed to view this script.
+    </panel.string>
+    <panel.string
+     name="public_objects_can_not_run">
+        Public Objects cannot run scripts
+    </panel.string>
+    <panel.string
+     name="script_running">
+        Running
+    </panel.string>
+    <panel.string
+     name="Title">
+        Script: [NAME]
+    </panel.string>
+    <text_editor
+     type="string"
+     length="1"
+     bevel_style="none"
+     border_style="line"
+     bottom="393"
+     follows="left|top|right|bottom"
+     font="Monospace"
+     height="376"
+     ignore_tab="false"
+     layout="topleft"
+     left="4"
+     max_length="65536"
+     name="Script Editor"
+     width="492"
+     word_wrap="true">
+        Loading...
+    </text_editor>
+    <button
+     bottom="499"
+     follows="right|bottom"
+     height="20"
+     label="Save"
+     label_selected="Save"
+     layout="topleft"
+     left="360"
+     name="Save_btn"
+     width="128" />
+    <scroll_list
+     bottom="457"
+     follows="left|right|bottom"
+     height="60"
+     layout="topleft"
+     left="4"
+     name="lsl errors"
+     width="492" />
+    <combo_box
+     bottom="499"
+     follows="left|bottom"
+     height="20"
+     label="Insert..."
+     layout="topleft"
+     left="12"
+     name="Insert..."
+     width="128" />
+    <text
+     bottom="473"
+     follows="left|bottom"
+     height="12"
+     layout="topleft"
+     left="12"
+     name="line_col"
+     width="128" />
+    <menu_bar
+     bg_visible="false"
+     bottom="18"
+     follows="left|top|right"
+     height="18"
+     layout="topleft"
+     left="8"
+     mouse_opaque="false"
+     name="script_menu"
+     width="476">
+        <menu
+         bottom="18"
+         height="62"
+         label="File"
+         layout="topleft"
+         left="0"
+         mouse_opaque="false"
+         name="File"
+         width="138">
+            <menu_item_call
+             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>
+        <menu
+         bottom="-647"
+         height="198"
+         label="Edit"
+         layout="topleft"
+         left="222"
+         mouse_opaque="false"
+         name="Edit"
+         width="139">
+            <menu_item_call
+             enabled="false"
+             label="Undo"
+             layout="topleft"
+             name="Undo" />
+            <menu_item_call
+             enabled="false"
+             label="Redo"
+             layout="topleft"
+             name="Redo" />
+            <menu_item_separator
+             layout="topleft" />
+            <menu_item_call
+             enabled="false"
+             label="Cut"
+             layout="topleft"
+             name="Cut" />
+            <menu_item_call
+             enabled="false"
+             label="Copy"
+             layout="topleft"
+             name="Copy" />
+            <menu_item_call
+             enabled="false"
+             label="Paste"
+             layout="topleft"
+             name="Paste" />
+            <menu_item_separator
+             layout="topleft"
+             name="separator2" />
+            <menu_item_call
+             label="Select All"
+             layout="topleft"
+             name="Select All" />
+            <menu_item_call
+             enabled="false"
+             label="Deselect"
+             layout="topleft"
+             name="Deselect" />
+            <menu_item_separator
+             layout="topleft"
+             name="separator3" />
+            <menu_item_call
+             label="Search / Replace..."
+             layout="topleft"
+             name="Search / Replace..." />
+        </menu>
+        <menu
+         bottom="18"
+         height="34"
+         label="Help"
+         layout="topleft"
+         left="0"
+         mouse_opaque="false"
+         name="Help"
+         width="112">
+            <menu_item_call
+             label="Help..."
+             layout="topleft"
+             name="Help..." />
+            <menu_item_call
+             label="LSL Wiki Help..."
+             layout="topleft"
+             name="LSL Wiki Help..." />
+        </menu>
+    </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml
index e447e541e0ba6da664a66da09c527f769b5e9817..4ae90380f8786ff3351e83bd090abe470dd10898 100644
--- a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml
+++ b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel name="sidetray_tab_panel"
        bottom="0" height="25" left="0" background_visible="false"
        bg_visible="false" border="false" border_visible="false"
@@ -12,4 +12,4 @@
                name="sidetray_tab_title" width="100">
         Side Panel
     </text>
-</panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
index 8f6a2d7648c3b18abf1263ef5b869a9550782d02..b7ce812dc8322291660ce2eedc36a6b33094495e 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel name="Teleport History" bottom="0" height="326" left="0" width="380"
      border="true" follows="left|top|right|bottom">
 	<scroll_list bottom="0" can_resize="true" column_padding="0" draw_heading="true"
@@ -9,4 +9,4 @@
 		<column dynamicwidth="true" label="Region" name="region" />
 		<column name="index" width="0" />
 	</scroll_list>
-</panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_world_map.xml b/indra/newview/skins/default/xui/en/panel_world_map.xml
index 532f487780c52525dd0c39b6a366282522dafbe5..ee355fa95c82ee09573a8fcc2f1f547a2fda388f 100644
--- a/indra/newview/skins/default/xui/en/panel_world_map.xml
+++ b/indra/newview/skins/default/xui/en/panel_world_map.xml
@@ -1,128 +1,128 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel
- follows="left|top|right|bottom"
- height="300"
- layout="topleft"
- name="world_map"
- width="400">
-    <panel.string
-     name="Loading">
-        Loading...
-    </panel.string>
-    <panel.string
-     name="InvalidLocation">
-        Invalid Location
-    </panel.string>
-    <panel.string
-     name="world_map_north">
-        N
-    </panel.string>
-    <panel.string
-     name="world_map_east">
-        E
-    </panel.string>
-    <panel.string
-     name="world_map_west">
-        W
-    </panel.string>
-    <panel.string
-     name="world_map_south">
-        S
-    </panel.string>
-    <panel.string
-     name="world_map_southeast">
-        SE
-    </panel.string>
-    <panel.string
-     name="world_map_northeast">
-        NE
-    </panel.string>
-    <panel.string
-     name="world_map_southwest">
-        SW
-    </panel.string>
-    <panel.string
-     name="world_map_northwest">
-        NW
-    </panel.string>
-    <text
-     type="string"
-     length="1"
-     label="N"
-     layout="topleft"
-     name="floater_map_north"
-     text="N"
-     text_color="1 1 1 0.7">
-        N
-    </text>
-    <text
-     type="string"
-     length="1"
-     label="E"
-     layout="topleft"
-     name="floater_map_east"
-     text="E"
-     text_color="1 1 1 0.7">
-        E
-    </text>
-    <text
-     type="string"
-     length="1"
-     label="W"
-     layout="topleft"
-     name="floater_map_west"
-     text="W"
-     text_color="1 1 1 0.7">
-        W
-    </text>
-    <text
-     type="string"
-     length="1"
-     label="S"
-     layout="topleft"
-     name="floater_map_south"
-     text="S"
-     text_color="1 1 1 0.7">
-        S
-    </text>
-    <text
-     type="string"
-     length="1"
-     label="SE"
-     layout="topleft"
-     name="floater_map_southeast"
-     text="SE"
-     text_color="1 1 1 0.7">
-        SE
-    </text>
-    <text
-     type="string"
-     length="1"
-     label="NE"
-     layout="topleft"
-     name="floater_map_northeast"
-     text="NE"
-     text_color="1 1 1 0.7">
-        NE
-    </text>
-    <text
-     type="string"
-     length="1"
-     label="SW"
-     layout="topleft"
-     name="floater_map_southwest"
-     text="SW"
-     text_color="1 1 1 0.7">
-        SW
-    </text>
-    <text
-     type="string"
-     length="1"
-     label="NW"
-     layout="topleft"
-     name="floater_map_northwest"
-     text="NW"
-     text_color="1 1 1 0.7">
-        NW
-    </text>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|top|right|bottom"
+ height="300"
+ layout="topleft"
+ name="world_map"
+ width="400">
+    <panel.string
+     name="Loading">
+        Loading...
+    </panel.string>
+    <panel.string
+     name="InvalidLocation">
+        Invalid Location
+    </panel.string>
+    <panel.string
+     name="world_map_north">
+        N
+    </panel.string>
+    <panel.string
+     name="world_map_east">
+        E
+    </panel.string>
+    <panel.string
+     name="world_map_west">
+        W
+    </panel.string>
+    <panel.string
+     name="world_map_south">
+        S
+    </panel.string>
+    <panel.string
+     name="world_map_southeast">
+        SE
+    </panel.string>
+    <panel.string
+     name="world_map_northeast">
+        NE
+    </panel.string>
+    <panel.string
+     name="world_map_southwest">
+        SW
+    </panel.string>
+    <panel.string
+     name="world_map_northwest">
+        NW
+    </panel.string>
+    <text
+     type="string"
+     length="1"
+     label="N"
+     layout="topleft"
+     name="floater_map_north"
+     text="N"
+     text_color="1 1 1 0.7">
+        N
+    </text>
+    <text
+     type="string"
+     length="1"
+     label="E"
+     layout="topleft"
+     name="floater_map_east"
+     text="E"
+     text_color="1 1 1 0.7">
+        E
+    </text>
+    <text
+     type="string"
+     length="1"
+     label="W"
+     layout="topleft"
+     name="floater_map_west"
+     text="W"
+     text_color="1 1 1 0.7">
+        W
+    </text>
+    <text
+     type="string"
+     length="1"
+     label="S"
+     layout="topleft"
+     name="floater_map_south"
+     text="S"
+     text_color="1 1 1 0.7">
+        S
+    </text>
+    <text
+     type="string"
+     length="1"
+     label="SE"
+     layout="topleft"
+     name="floater_map_southeast"
+     text="SE"
+     text_color="1 1 1 0.7">
+        SE
+    </text>
+    <text
+     type="string"
+     length="1"
+     label="NE"
+     layout="topleft"
+     name="floater_map_northeast"
+     text="NE"
+     text_color="1 1 1 0.7">
+        NE
+    </text>
+    <text
+     type="string"
+     length="1"
+     label="SW"
+     layout="topleft"
+     name="floater_map_southwest"
+     text="SW"
+     text_color="1 1 1 0.7">
+        SW
+    </text>
+    <text
+     type="string"
+     length="1"
+     label="NW"
+     layout="topleft"
+     name="floater_map_northwest"
+     text="NW"
+     text_color="1 1 1 0.7">
+        NW
+    </text>
+</panel>
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 23efd65c45e71e62ad41ec9a580ed2a7b8643354..67233cbda063b55ca7976d68a18ac40d4ebe1e5c 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -8945,3 +8945,21 @@ version 2.0
 		{	CRC				U32	}
 	}
 }
+
+{
+	LinkInventoryItem	Low	426 NotTrusted	Zerocoded
+	{
+		AgentData		Single
+		{	AgentID		LLUUID	}
+		{	SessionID	LLUUID	}
+	}
+	{
+		InventoryData		Variable
+		{	CallbackID	U32			} // Async Response
+		{	FolderID		LLUUID	}
+		{	OldItemID		LLUUID	}
+		{	Name			Variable	1	}
+		{	AssetType		U8		}
+	}
+}
+