diff --git a/.hgignore b/.hgignore
new file mode 100644
index 0000000000000000000000000000000000000000..454be00dbffc27a0c6969fb3561556f08d5c1d96
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,50 @@
+syntax: glob
+
+# WinMerge temp files
+*.bak
+# Compiled python bytecode
+*.pyc
+# Emacs temp files
+*~
+.*.swp
+LICENSES
+indra/.distcc
+indra/build-darwin-*
+indra/build-vc[0-9]*
+indra/lib/mono/1.0/*.dll
+indra/lib/mono/indra/*.dll
+indra/lib/mono/indra/*.exe
+indra/lib/mono/indra/*.pdb
+indra/lib/python/eventlet/
+indra/llwindow/glh/glh_linear.h
+indra/newview/app_settings/mozilla
+indra/newview/app_settings/mozilla-runtime-*
+indra/newview/app_settings/mozilla_debug
+indra/newview/app_settings/static_*.db2
+indra/newview/browser_profile
+indra/newview/character
+indra/newview/fmod.dll
+indra/newview/mozilla-theme
+indra/newview/mozilla-universal-darwin.tgz
+indra/newview/res-sdl
+indra/newview/skins
+indra/newview/vivox-runtime
+indra/server-linux-*
+indra/test/linden_file.dat
+indra/test_apps/llmediatest/dependencies/i686-win32
+indra/test_apps/terrain_mule/*.dll
+indra/viewer-linux-*
+indra/web/doc/asset-upload/plugins/lsl_compiler/lslc
+indra/web/doc/asset-upload/plugins/verify-notecard
+indra/web/doc/asset-upload/plugins/verify-texture
+installed.xml
+libraries
+tarfile_tmp
+^indra/lib/python/mulib.*
+^web/locale.*
+^web/secondlife.com.*
+^web/config.*
+^indra/web/dataservice/locale.*
+^indra/web/dataservice/lib/shared/vault.*
+^indra/web/dataservice/vendor.*
+glob:indra/newview/dbghelp.dll
diff --git a/etc/message.xml b/etc/message.xml
index d2ba9843e4f9fe31198e19f54249b2f4cef9b40d..da08e12aa1bb84a4615fb96994ef49c92b312962 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -669,11 +669,14 @@
 			<key>FetchLib</key>
 			<boolean>true</boolean>
 
-            <key>ObjectMedia</key>
-            <boolean>false</boolean>
+			<key>UploadBakedTexture</key>
+			<boolean>true</boolean>
+			
+			<key>ObjectMedia</key>
+            		<boolean>false</boolean>
                   
-            <key>ObjectMediaNavigate</key>
-            <boolean>false</boolean>
+            		<key>ObjectMediaNavigate</key>
+            		<boolean>false</boolean>
                   
       </map>
 
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 9418dbf271fb21563c5bb3438c62e5ce2c27b6cf..261c0b17e2361a9ac700336e2273322d13441aea 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -66,6 +66,7 @@ if (VIEWER)
   add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
   add_subdirectory(${LIBS_OPEN_PREFIX}llui)
   add_subdirectory(${LIBS_OPEN_PREFIX}llxuixml)
+  add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
 
   # viewer media plugins
   add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 3bd10ea9ee91f475153244af235a4b149b5b70c7..e7afe0ecba8a46e9f1fccdb1fefcd5df7a93e564 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -183,11 +183,17 @@ endif (LINUX)
 
 
 if (DARWIN)
-  add_definitions(-DLL_DARWIN=1)
+  # NOTE (per http://lists.apple.com/archives/darwin-dev/2008/Jan/msg00232.html):
+  # > Why the bus error? What am I doing wrong? 
+  # This is a known issue where getcontext(3) is writing past the end of the
+  # ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ).
+  # As a workaround, define _XOPEN_SOURCE before including ucontext.h.
+  add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE)
   set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
   set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-branch")
+  set(DARWIN_extra_cstar_flags "-mlong-branch")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags}")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}  ${DARWIN_extra_cstar_flags}")
   # NOTE: it's critical that the optimization flag is put in front.
   # NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
   set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
@@ -196,13 +202,13 @@ endif (DARWIN)
 
 
 if (LINUX OR DARWIN)
-  set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor")
+  set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")
 
   if (NOT GCC_DISABLE_FATAL_WARNINGS)
     set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
   endif (NOT GCC_DISABLE_FATAL_WARNINGS)
 
-  set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder")
+  set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual")
 
   set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}")
   set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}")
diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake
index 0755aeee035d00bb135ad1c47172d964c29ab9d4..f4706dd4f2713ddb1e410da8d76342a13726ecd8 100644
--- a/indra/cmake/APR.cmake
+++ b/indra/cmake/APR.cmake
@@ -13,26 +13,38 @@ if (STANDALONE)
 else (STANDALONE)
   use_prebuilt_binary(apr_suite)
   if (WINDOWS)
+    if (LLCOMMON_LINK_SHARED)
+      set(APR_selector "lib")
+    else (LLCOMMON_LINK_SHARED)
+      set(APR_selector "")
+    endif (LLCOMMON_LINK_SHARED)
     set(APR_LIBRARIES 
-      debug ${ARCH_PREBUILT_DIRS_DEBUG}/apr-1.lib
-      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/apr-1.lib
+      debug ${ARCH_PREBUILT_DIRS_DEBUG}/${APR_selector}apr-1.lib
+      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}apr-1.lib
       )
     set(APRICONV_LIBRARIES 
-      debug ${ARCH_PREBUILT_DIRS_DEBUG}/apriconv-1.lib
-      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/apriconv-1.lib
+      debug ${ARCH_PREBUILT_DIRS_DEBUG}/${APR_selector}apriconv-1.lib
+      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}apriconv-1.lib
       )
     set(APRUTIL_LIBRARIES 
-      debug ${ARCH_PREBUILT_DIRS_DEBUG}/aprutil-1.lib ${APRICONV_LIBRARIES}
-      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/aprutil-1.lib ${APRICONV_LIBRARIES}
+      debug ${ARCH_PREBUILT_DIRS_DEBUG}/${APR_selector}aprutil-1.lib ${APRICONV_LIBRARIES}
+      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}aprutil-1.lib ${APRICONV_LIBRARIES}
       )
   elseif (DARWIN)
+    if (LLCOMMON_LINK_SHARED)
+      set(APR_selector     "0.3.7.dylib")
+      set(APRUTIL_selector "0.3.8.dylib")
+    else (LLCOMMON_LINK_SHARED)
+      set(APR_selector     "a")
+      set(APRUTIL_selector "a")
+    endif (LLCOMMON_LINK_SHARED)
     set(APR_LIBRARIES 
-      debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.a
-      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.a
+      debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.${APR_selector}
+      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.${APR_selector}
       )
     set(APRUTIL_LIBRARIES 
-      debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.a
-      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.a
+      debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.${APRUTIL_selector}
+      optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.${APRUTIL_selector}
       )
     set(APRICONV_LIBRARIES iconv)
   else (WINDOWS)
diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake
index 0578ae95ffa7edc027d74c6ef0bab0ba48b0ee3d..efe9ad74d3fe5b11ecf5e3634bd916fbb946a660 100644
--- a/indra/cmake/Boost.cmake
+++ b/indra/cmake/Boost.cmake
@@ -15,7 +15,7 @@ else (STANDALONE)
   set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
 
   if (WINDOWS)
-    set(BOOST_VERSION 1_34_1)
+    set(BOOST_VERSION 1_39)
     if (MSVC71)
       set(BOOST_PROGRAM_OPTIONS_LIBRARY 
           optimized libboost_program_options-vc71-mt-s-${BOOST_VERSION}
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 3ce393b659174a57f736aae1d2f00a0ea84945d1..4563b59ad2b5d1fff9e92af864fbae909742ce8b 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -53,6 +53,7 @@ set(cmake_SOURCE_FILES
     LLPrimitive.cmake
     LLRender.cmake
     LLScene.cmake
+    LLTestCommand.cmake
     LLUI.cmake
     LLVFS.cmake
     LLWindow.cmake
@@ -69,7 +70,6 @@ set(cmake_SOURCE_FILES
     PNG.cmake
     Python.cmake
     Prebuilt.cmake
-    RunBuildTest.cmake
     TemplateCheck.cmake
     Tut.cmake
     UI.cmake
diff --git a/indra/cmake/DeploySharedLibs.cmake b/indra/cmake/DeploySharedLibs.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a7e772bd7501e3d67c9fb58b779bfc57be88f137
--- /dev/null
+++ b/indra/cmake/DeploySharedLibs.cmake
@@ -0,0 +1,67 @@
+# DeploySharedLibs.cmake
+# This is a script to be run at build time! Its not part of the cmake configuration!
+# See indra/cmake/LLSharedLibs.cmake for a macro that simplifies adding a command to a target to run this script.
+
+# This  script requires a few cmake variable to be set on the command line:
+# BIN_NAME= The full path the the binary to search for dependecies.
+# SEARCH_DIRS= The full paths to dirs to search for dependencies.
+# DST_PATH= The full path where the dependecies will be copied. 
+include(GetPrerequisites)
+message("Getting recursive dependencies for file: ${BIN_NAME}")
+set(EXCLUDE_SYSTEM 1)
+set(RECURSE 1)
+get_filename_component(EXE_PATH ${BIN_NAME} PATH)
+
+get_prerequisites( ${BIN_NAME} RESULTS ${EXCLUDE_SYSTEM} ${RECURSE} "${EXE_PATH}" "${SEARCH_DIRS}" )
+
+foreach(DEP ${RESULTS})
+  Message("Processing dependency: ${DEP}")
+  get_filename_component(DEP_FILE ${DEP} NAME)
+  set(DEP_FILES ${DEP_FILES} ${DEP_FILE})
+endforeach(DEP)
+
+if(DEP_FILES)
+  list(REMOVE_DUPLICATES DEP_FILES)
+endif(DEP_FILES)
+
+foreach(DEP_FILE ${DEP_FILES})
+  if(FOUND_FILES)
+	list(FIND FOUND_FILES ${DEP_FILE} FOUND)
+  else(FOUND_FILES)
+	set(FOUND -1)
+  endif(FOUND_FILES)
+
+  if(FOUND EQUAL -1)
+	find_path(DEP_PATH ${DEP_FILE} PATHS ${SEARCH_DIRS} NO_DEFAULT_PATH)
+	if(DEP_PATH)
+	  set(FOUND_FILES ${FOUND_FILES} "${DEP_PATH}/${DEP_FILE}")
+	  set(DEP_PATH NOTFOUND) #reset DEP_PATH for the next find_path call.
+	else(DEP_PATH)
+	  set(MISSING_FILES ${MISSING_FILES} ${DEP_FILE})
+	endif(DEP_PATH)
+  endif(FOUND EQUAL -1)
+endforeach(DEP_FILE)
+
+if(MISSING_FILES)
+  message("Missing:")
+  foreach(FILE ${MISSING_FILES})
+	message("  ${FILE}")
+  endforeach(FILE)
+  message("Searched in:")
+  foreach(SEARCH_DIR ${SEARCH_DIRS})
+	message("  ${SEARCH_DIR}")
+  endforeach(SEARCH_DIR)
+  message(FATAL_ERROR "Failed")
+endif(MISSING_FILES)
+
+if(FOUND_FILES)
+  foreach(FILE ${FOUND_FILES})
+	get_filename_component(DST_FILE ${FILE} NAME)
+	set(DST_FILE "${DST_PATH}/${DST_FILE}")
+	message("Copying ${FILE} to ${DST_FILE}")
+	execute_process(
+	  COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FILE} ${DST_FILE}
+	  )
+  endforeach(FILE ${FOUND_FILES})
+endif(FOUND_FILES)
+message("Success!")
diff --git a/indra/cmake/ExamplePlugin.cmake b/indra/cmake/ExamplePlugin.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..599787ad21a7f7f73834b57dcca55501945a064d
--- /dev/null
+++ b/indra/cmake/ExamplePlugin.cmake
@@ -0,0 +1,16 @@
+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (STANDALONE)
+    set(EXAMPLEPLUGIN OFF CACHE BOOL
+        "EXAMPLEPLUGIN support for the llplugin/llmedia test apps.")
+else (STANDALONE)
+    set(EXAMPLEPLUGIN ON CACHE BOOL
+        "EXAMPLEPLUGIN support for the llplugin/llmedia test apps.")
+endif (STANDALONE)
+
+if (WINDOWS)
+elseif (DARWIN)
+elseif (LINUX)
+endif (WINDOWS)
diff --git a/indra/cmake/Externals.cmake b/indra/cmake/Externals.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..26f3b5604937a781490838532276b2e67717e8d1
--- /dev/null
+++ b/indra/cmake/Externals.cmake
@@ -0,0 +1,34 @@
+# -*- cmake -*-
+
+include(Python)
+include(FindSVN)
+
+macro (use_svn_external _binary _path _url _rev)
+  if (NOT STANDALONE)
+    if(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
+      if(SVN_FOUND)
+        if(DEBUG_EXTERNALS)
+          message("cd ${_path} && ${SVN_EXECUTABLE} checkout -r ${_rev} ${_url} ${_binary}")
+        endif(DEBUG_EXTERNALS)
+        execute_process(COMMAND ${SVN_EXECUTABLE}
+          checkout
+          -r ${_rev}
+          ${_url}
+          ${_binary}
+          WORKING_DIRECTORY ${_path}
+          RESULT_VARIABLE ${_binary}_installed
+          )
+      else(SVN_FOUND)
+        message(FATAL_ERROR "Failed to find SVN_EXECUTABLE")
+      endif(SVN_FOUND)
+      file(WRITE ${CMAKE_BINARY_DIR}/temp/${_binary}_installed "${${_binary}_installed}")
+    else(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
+      set(${_binary}_installed 0)
+    endif(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
+    if(NOT ${_binary}_installed EQUAL 0)
+      message(FATAL_ERROR
+              "Failed to download or unpack prebuilt '${_binary}'."
+              " Process returned ${${_binary}_installed}.")
+    endif (NOT ${_binary}_installed EQUAL 0)
+  endif (NOT STANDALONE)
+endmacro (use_svn_external _binary _path _url _rev)
diff --git a/indra/cmake/FindMono.cmake b/indra/cmake/FindMono.cmake
index c36d7259e895595624eb6dfae881969c586a45d6..d956c48656a51db6a691688e6fcafff91f432560 100644
--- a/indra/cmake/FindMono.cmake
+++ b/indra/cmake/FindMono.cmake
@@ -42,7 +42,7 @@ FIND_PROGRAM (GACUTIL_EXECUTABLE gacutil
              /usr/local/bin
 )
 FIND_PROGRAM (ILASM_EXECUTABLE
-             ilasm
+             NAMES ilasm.bat ilasm
              NO_DEFAULT_PATH
              PATHS "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" /bin /usr/bin /usr/local/bin
 )
diff --git a/indra/cmake/FindSVN.cmake b/indra/cmake/FindSVN.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..3322be4ca9213bffcae36da3922d4ef8e539ecd1
--- /dev/null
+++ b/indra/cmake/FindSVN.cmake
@@ -0,0 +1,34 @@
+# -*- cmake -*-
+#
+# Find the svn executable for exporting old svn:externals.
+#
+# Input variables:
+#   SVN_FIND_REQUIRED - set this if configuration should fail without scp
+#
+# Output variables:
+#
+#   SVN_FOUND - set if svn was found
+#   SVN_EXECUTABLE - path to svn executable
+#   SVN_BATCH_FLAG - how to put svn into batch mode
+
+
+SET(SVN_EXECUTABLE)
+FIND_PROGRAM(SVN_EXECUTABLE NAMES svn svn.exe)
+
+IF (SVN_EXECUTABLE)
+  SET(SVN_FOUND ON)
+ELSE (SVN_EXECUTABLE)
+  SET(SVN_FOUND OFF)
+ENDIF (SVN_EXECUTABLE)
+
+IF (SVN_FOUND)
+  GET_FILENAME_COMPONENT(_svn_name ${SVN_EXECUTABLE} NAME_WE)
+  SET(SVN_BATCH_FLAG --non-interactive)
+ELSE (SVN_FOUND)
+  IF (SVN_FIND_REQUIRED)
+    MESSAGE(FATAL_ERROR "Could not find svn executable")
+  ENDIF (SVN_FIND_REQUIRED)
+ENDIF (SVN_FOUND)
+
+MARK_AS_ADVANCED(SVN_EXECUTABLE SVN_FOUND SVN_BATCH_FLAG)
+
diff --git a/indra/cmake/GoogleMock.cmake b/indra/cmake/GoogleMock.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..ca5a8034ba442082c5881ec4c046ebe4b7a777e9
--- /dev/null
+++ b/indra/cmake/GoogleMock.cmake
@@ -0,0 +1,27 @@
+# -*- cmake -*-
+include(Prebuilt)
+include(Linking)
+
+use_prebuilt_binary(googlemock)
+
+set(GOOGLEMOCK_INCLUDE_DIRS 
+    ${LIBS_PREBUILT_DIR}/include)
+
+if (LINUX)
+    set(GOOGLEMOCK_LIBRARIES 
+        gmock  
+        gtest)
+elseif(WINDOWS)
+    set(GOOGLEMOCK_LIBRARIES 
+        gmock)
+    set(GOOGLEMOCK_INCLUDE_DIRS 
+        ${LIBS_PREBUILT_DIR}/include
+        ${LIBS_PREBUILT_DIR}/include/gmock
+        ${LIBS_PREBUILT_DIR}/include/gmock/boost/tr1/tr1)
+elseif(DARWIN)
+    set(GOOGLEMOCK_LIBRARIES
+        gmock
+        gtest)
+endif(LINUX)
+
+
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 008b277960b7304e7943b475e130068464a443ca..d8f64199cf63abdcd92219d6b21a6e8e282a1a52 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -1,4 +1,6 @@
 # -*- cmake -*-
+include(LLTestCommand)
+include(GoogleMock)
 
 MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
   # Given a project name and a list of sourcefiles (with optional properties on each),
@@ -13,6 +15,8 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
   #
   # WARNING: do NOT modify this code without working with poppy -
   # there is another branch that will conflict heavily with any changes here.
+INCLUDE(GoogleMock)
+
 
   IF(LL_TEST_VERBOSE)
     MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
@@ -41,8 +45,10 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
     ${LLMATH_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
     ${LIBS_OPEN_DIR}/test
+    ${GOOGLEMOCK_INCLUDE_DIRS}
     )
   SET(alltest_LIBRARIES
+    ${GOOGLEMOCK_LIBRARIES}
     ${PTHREAD_LIBRARY}
     ${WINDOWS_LIBRARIES}
     )
@@ -51,6 +57,11 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
     ${CMAKE_SOURCE_DIR}/test/test.h
     )
 
+  # Use the default flags
+  if (LINUX)
+    SET(CMAKE_EXE_LINKER_FLAGS "")
+  endif (LINUX)
+
   # start the source test executable definitions
   SET(${project}_TEST_OUTPUT "")
   FOREACH (source ${sources})
@@ -93,9 +104,9 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
       MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
     ENDIF(LL_TEST_VERBOSE)
 
+
     # Setup target
     ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
-
     #
     # Per-codefile additional / external project dep and lib dep property extraction
     #
@@ -123,16 +134,20 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
     GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION)
     SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt)
     SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
-    # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
+
+	# daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
     IF(LL_TEST_VERBOSE)
       MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd  = ${TEST_CMD}")
     ENDIF(LL_TEST_VERBOSE)
-    SET(TEST_SCRIPT_CMD 
-      ${CMAKE_COMMAND} 
-      -DLD_LIBRARY_PATH=${ARCH_PREBUILT_DIRS}:/usr/lib
-      -DTEST_CMD:STRING="${TEST_CMD}" 
-      -P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake
-      )
+    
+    IF(WINDOWS)
+      set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR})
+    ELSE(WINDOWS)
+      set(LD_LIBRARY_PATH ${ARCH_PREBUILT_DIRS}:${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}:/usr/lib)
+    ENDIF(WINDOWS)
+
+    LL_TEST_COMMAND("${LD_LIBRARY_PATH}" ${TEST_CMD})
+    SET(TEST_SCRIPT_CMD ${LL_TEST_COMMAND_value})
     IF(LL_TEST_VERBOSE)
       MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script  = ${TEST_SCRIPT_CMD}")
     ENDIF(LL_TEST_VERBOSE)
@@ -176,6 +191,7 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
 
   SET(libraries
     ${library_dependencies}
+    ${GOOGLEMOCK_LIBRARIES}
     ${PTHREAD_LIBRARY}
     )
 
@@ -212,12 +228,14 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
     LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
   ENDIF (test_exe_pos LESS 0)
 
-  SET(TEST_SCRIPT_CMD 
-    ${CMAKE_COMMAND} 
-    -DLD_LIBRARY_PATH=${ARCH_PREBUILT_DIRS}:/usr/lib
-    -DTEST_CMD:STRING="${test_command}" 
-    -P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake
-    )
+  IF(WINDOWS)
+    set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR})
+  ELSE(WINDOWS)
+    set(LD_LIBRARY_PATH ${ARCH_PREBUILT_DIRS}:${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}:/usr/lib)
+  ENDIF(WINDOWS)
+
+  LL_TEST_COMMAND("${LD_LIBRARY_PATH}" ${test_command})
+  SET(TEST_SCRIPT_CMD ${LL_TEST_COMMAND_value})
 
   if(TEST_DEBUG)
     message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}")
diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake
index ef202dd8796b5ee750aefd092db9160aac541931..d1ab264a413b8a3eaf263ea3bbef32e59ac42e9c 100644
--- a/indra/cmake/LLCommon.cmake
+++ b/indra/cmake/LLCommon.cmake
@@ -17,3 +17,7 @@ set(LLCOMMON_LIBRARIES llcommon)
 
 add_definitions(${TCMALLOC_FLAG})
 
+set(LLCOMMON_LINK_SHARED ON CACHE BOOL "Build the llcommon target as a shared library.")
+if(LLCOMMON_LINK_SHARED)
+  add_definitions(-DLL_COMMON_LINK_SHARED=1)
+endif(LLCOMMON_LINK_SHARED)
diff --git a/indra/cmake/LLKDU.cmake b/indra/cmake/LLKDU.cmake
index f103dcf6649326451010bdbaf228710320ccfacb..6b69388896b0527b49b9b009bc934fea8d2ec69d 100644
--- a/indra/cmake/LLKDU.cmake
+++ b/indra/cmake/LLKDU.cmake
@@ -1,7 +1,7 @@
 # -*- cmake -*-
 include(Prebuilt)
 
-if (NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
+if (INSTALL_PROPRIETARY AND NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
   use_prebuilt_binary(kdu)
   if (WINDOWS)
     set(KDU_LIBRARY debug kdu_cored optimized kdu_core)
@@ -15,4 +15,4 @@ if (NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
   set(LLKDU_STATIC_LIBRARY llkdu_static)
   set(LLKDU_LIBRARIES ${LLKDU_LIBRARY})
   set(LLKDU_STATIC_LIBRARIES ${LLKDU_STATIC_LIBRARY})
-endif (NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
+endif (INSTALL_PROPRIETARY AND NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
diff --git a/indra/cmake/LLLogin.cmake b/indra/cmake/LLLogin.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..47d171876a00df3fea3bf61a794cb3ff81fcd07b
--- /dev/null
+++ b/indra/cmake/LLLogin.cmake
@@ -0,0 +1,7 @@
+# -*- cmake -*-
+
+set(LLLOGIN_INCLUDE_DIRS
+    ${LIBS_OPEN_DIR}/viewer_components/login
+    )
+
+set(LLLOGIN_LIBRARIES lllogin)
diff --git a/indra/cmake/LLSharedLibs.cmake b/indra/cmake/LLSharedLibs.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..3be22ab401298ab13b583cf8720a1b6efd549f01
--- /dev/null
+++ b/indra/cmake/LLSharedLibs.cmake
@@ -0,0 +1,31 @@
+# ll_deploy_sharedlibs_command
+# target_exe: the cmake target of the executable for which the shared libs will be deployed.
+# search_dirs: a list of dirs to search for the dependencies
+# dst_path: path to copy deps to, relative to the output location of the target_exe
+macro(ll_deploy_sharedlibs_command target_exe search_dirs dst_path) 
+	get_target_property(OUTPUT_LOCATION ${target_exe} LOCATION)
+
+	if(DARWIN)
+	  get_target_property(IS_BUNDLE ${target_exe} MACOSX_BUNDLE)
+	  if(IS_BUNDLE)
+		get_filename_component(TARGET_FILE ${OUTPUT_LOCATION} NAME)
+		set(OUTPUT_PATH ${OUTPUT_LOCATION}.app/Contents/MacOS)
+		set(OUTPUT_LOCATION ${OUTPUT_PATH}/${TARGET_FILE})
+	  endif(IS_BUNDLE)
+	else(APPLE)
+	  message(FATAL_ERROR "Only darwin currently supported!")
+	endif(DARWIN)
+
+	add_custom_command(
+	  TARGET ${target_exe} POST_BUILD
+	  COMMAND ${CMAKE_COMMAND} 
+	  ARGS
+        "-DBIN_NAME=\"${OUTPUT_LOCATION}\""
+		"-DSEARCH_DIRS=\"${search_dirs}\""
+		"-DDST_PATH=\"${OUTPUT_PATH}/${dst_path}\""
+		"-P"
+		"${CMAKE_SOURCE_DIR}/cmake/DeploySharedLibs.cmake"
+	  )
+
+endmacro(ll_deploy_sharedlibs_command)
+
diff --git a/indra/cmake/LLTestCommand.cmake b/indra/cmake/LLTestCommand.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..fae5640493345436507885fd5864885caa9640ab
--- /dev/null
+++ b/indra/cmake/LLTestCommand.cmake
@@ -0,0 +1,13 @@
+MACRO(LL_TEST_COMMAND LD_LIBRARY_PATH)
+  # nat wonders how Kitware can use the term 'function' for a construct that
+  # cannot return a value. And yet, variables you set inside a FUNCTION are
+  # local. Try a MACRO instead.
+  SET(LL_TEST_COMMAND_value
+    ${PYTHON_EXECUTABLE}
+    "${CMAKE_SOURCE_DIR}/cmake/run_build_test.py")
+  IF(LD_LIBRARY_PATH)
+    LIST(APPEND LL_TEST_COMMAND_value "-l${LD_LIBRARY_PATH}")
+  ENDIF(LD_LIBRARY_PATH)
+  LIST(APPEND LL_TEST_COMMAND_value ${ARGN})
+##MESSAGE(STATUS "Will run: ${LL_TEST_COMMAND_value}")
+ENDMACRO(LL_TEST_COMMAND)
diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake
index eaa8a6dc2915ce82a4d488e9da155c82ae15a7c1..1f3553539f718b878fead3974b693590ef29f215 100644
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -5,6 +5,7 @@ if (NOT STANDALONE)
     set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib)
     set(ARCH_PREBUILT_DIRS_RELEASE ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/release)
     set(ARCH_PREBUILT_DIRS_DEBUG ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/debug)
+    set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs CACHE FILEPATH "Location of staged DLLs")
   elseif (LINUX)
     if (VIEWER)
       set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib_release_client)
@@ -13,10 +14,12 @@ if (NOT STANDALONE)
     endif (VIEWER)
     set(ARCH_PREBUILT_DIRS_RELEASE ${ARCH_PREBUILT_DIRS})
     set(ARCH_PREBUILT_DIRS_DEBUG ${ARCH_PREBUILT_DIRS})
+    set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs CACHE FILEPATH "Location of staged .sos")
   elseif (DARWIN)
     set(ARCH_PREBUILT_DIRS_RELEASE ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib_release)
     set(ARCH_PREBUILT_DIRS ${ARCH_PREBUILT_DIRS_RELEASE})
     set(ARCH_PREBUILT_DIRS_DEBUG ${ARCH_PREBUILT_DIRS_RELEASE})
+    set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs CACHE FILEPATH "Location of staged DLLs")
   endif (WINDOWS)
 endif (NOT STANDALONE)
 
diff --git a/indra/cmake/Pth.cmake b/indra/cmake/Pth.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a28f6ec696efdbbcaeb8c1ee34dfb7dd7d436421
--- /dev/null
+++ b/indra/cmake/Pth.cmake
@@ -0,0 +1,21 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+set(PTH_FIND_QUIETLY ON)
+set(PTH_FIND_REQUIRED ON)
+
+if (STANDALONE)
+#  ?? How would I construct FindPTH.cmake? This file was cloned from
+#  CURL.cmake, which uses include(FindCURL), but there's no FindCURL.cmake?
+#  include(FindPTH)
+else (STANDALONE)
+  # This library is only needed to support Boost.Coroutine, and only on Mac.
+  if (DARWIN)
+    use_prebuilt_binary(pth)
+    set(PTH_LIBRARIES pth)
+    set(PTH_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
+  else (DARWIN)
+    set(PTH_LIBRARIES)
+    set(PTH_INCLUDE_DIRS)
+  endif (DARWIN)
+endif (STANDALONE)
diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..17bce6f43445792c586a0644880e59ba955b1c8a
--- /dev/null
+++ b/indra/cmake/run_build_test.py
@@ -0,0 +1,111 @@
+#!/usr/bin/python
+"""\
+@file   run_build_test.py
+@author Nat Goodspeed
+@date   2009-09-03
+@brief  Helper script to allow CMake to run some command after setting
+        environment variables.
+
+CMake has commands to run an external program. But remember that each CMake
+command must be backed by multiple build-system implementations. Unfortunately
+it seems CMake can't promise that every target build system can set specified
+environment variables before running the external program of interest.
+
+This helper script is a workaround. It simply sets the requested environment
+variables and then executes the program specified on the rest of its command
+line.
+
+Example:
+
+python run_build_test.py -DFOO=bar myprog somearg otherarg
+
+sets environment variable FOO=bar, then runs:
+myprog somearg otherarg
+
+$LicenseInfo:firstyear=2009&license=internal$
+Copyright (c) 2009, Linden Research, Inc.
+$/LicenseInfo$
+"""
+
+import os
+import sys
+import subprocess
+
+def main(command, libpath=[], vars={}):
+    """Pass:
+    command is a sequence (e.g. a list) of strings. The first item in the list
+    must be the command name, the rest are its arguments.
+
+    libpath is a sequence of directory pathnames. These will be appended to
+    the platform-specific dynamic library search path environment variable.
+
+    vars is a dict of arbitrary (var, value) pairs to be added to the
+    environment before running 'command'.
+
+    This function runs the specified command, waits for it to terminate and
+    returns its return code. This will be negative if the command terminated
+    with a signal, else it will be the process's specified exit code.
+    """
+    # Handle platform-dependent libpath first.
+    if sys.platform == "win32":
+        lpvars = ["PATH"]
+    elif sys.platform == "darwin":
+        lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"]
+    elif sys.platform.startswith("linux"):
+        lpvars = ["LD_LIBRARY_PATH"]
+    else:
+        # No idea what the right pathname might be! But only crump if this
+        # feature is requested.
+        if libpath:
+            raise NotImplemented("run_build_test: unknown platform %s" % sys.platform)
+        lpvars = []
+    for var in lpvars:
+        # Split the existing path. Bear in mind that the variable in question
+        # might not exist; instead of KeyError, just use an empty string.
+        dirs = os.environ.get(var, "").split(os.pathsep)
+        # Append the sequence in libpath
+##         print "%s += %r" % (var, libpath)
+        dirs.extend(libpath)
+        # Now rebuild the path string. This way we use a minimum of separators
+        # -- and we avoid adding a pointless separator when libpath is empty.
+        os.environ[var] = os.pathsep.join(dirs)
+    # Now handle arbitrary environment variables. The tricky part is ensuring
+    # that all the keys and values we try to pass are actually strings.
+##     if vars:
+##         print "Setting:"
+##         for key, value in vars.iteritems():
+##             print "%s=%s" % (key, value)
+    os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()]))
+    # Run the child process.
+##     print "Running: %s" % " ".join(command)
+    return subprocess.call(command)
+
+if __name__ == "__main__":
+    from optparse import OptionParser
+    parser = OptionParser(usage="usage: %prog [options] command args...")
+    # We want optparse support for the options we ourselves handle -- but we
+    # DO NOT want it looking at options for the executable we intend to run,
+    # rejecting them as invalid because we don't define them. So configure the
+    # parser to stop looking for options as soon as it sees the first
+    # positional argument (traditional Unix syntax).
+    parser.disable_interspersed_args()
+    parser.add_option("-D", "--define", dest="vars", default=[], action="append",
+                      metavar="VAR=value",
+                      help="Add VAR=value to the env variables defined")
+    parser.add_option("-l", "--libpath", dest="libpath", default=[], action="append",
+                      metavar="DIR",
+                      help="Add DIR to the platform-dependent DLL search path")
+    opts, args = parser.parse_args()
+    # What we have in opts.vars is a list of strings of the form "VAR=value"
+    # or possibly just "VAR". What we want is a dict. We can build that dict by
+    # constructing a list of ["VAR", "value"] pairs -- so split each
+    # "VAR=value" string on the '=' sign (but only once, in case we have
+    # "VAR=some=user=string"). To handle the case of just "VAR", append "" to
+    # the list returned by split(), then slice off anything after the pair we
+    # want.
+    rc = main(command=args, libpath=opts.libpath,
+              vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars]))
+    if rc not in (None, 0):
+        print >>sys.stderr, "Failure running: %s" % " ".join(args)
+        print >>sys.stderr, "Error: %s" % rc
+    sys.exit((rc < 0) and 255 or rc)
diff --git a/indra/develop.py b/indra/develop.py
index b2b494d1b3d3ee4d0ab772d3c58b6d5ac13c33c5..7836c97473b1f46236e8c6e480d4f1e4cac1501b 100755
--- a/indra/develop.py
+++ b/indra/develop.py
@@ -439,7 +439,6 @@ def cmake_commandline(self, src_dir, build_dir, opts, simple):
             )
         if self.universal == 'ON':
             args['universal'] = '-DCMAKE_OSX_ARCHITECTURES:STRING=\'i386;ppc\''
-            pass
         #if simple:
         #    return 'cmake %(opts)s %(dir)r' % args
         return ('cmake -G %(generator)r '
diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp
index 3631761c93b81419b2f8d9e97c9ab81b87f9682d..abd8f7dbdeca0280ab9cda395dc464a04b34b613 100644
--- a/indra/integration_tests/llui_libtest/llui_libtest.cpp
+++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp
@@ -84,12 +84,12 @@ class LLTexture ;
 class TestImageProvider : public LLImageProviderInterface
 {
 public:
-	/*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name)
+	/*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority)
 	{
 		return makeImage();
 	}
 
-	/*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id)
+	/*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority)
 	{
 		return makeImage();
 	}
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
index 1190d88663964a6c3dace2c291778ab676d0579e..4527b115f9ad07b6a2f9180090466c2f562112a1 100644
--- a/indra/lib/python/indra/base/llsd.py
+++ b/indra/lib/python/indra/base/llsd.py
@@ -238,7 +238,7 @@ def ARRAY(self, v):
     def MAP(self, v):
         return self.elt(
             'map',
-            ''.join(["%s%s" % (self.elt('key', key), self.generate(value))
+            ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value))
              for key, value in v.items()]))
 
     typeof = type
diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py
index aceea29cd2082273456e06da21798853ccc5f145..1cdd8e915b996cf6d315339a400260ca677a3135 100644
--- a/indra/lib/python/indra/base/lluuid.py
+++ b/indra/lib/python/indra/base/lluuid.py
@@ -26,8 +26,14 @@
 $/LicenseInfo$
 """
 
-import md5, random, socket, string, time, re
+import random, socket, string, time, re
 import uuid
+try:
+    # Python 2.6
+    from hashlib import md5
+except ImportError:
+    # Python 2.5 and earlier
+    from md5 import new as md5
 
 def _int2binstr(i,l):
     s=''
@@ -196,7 +202,7 @@ def generate(self):
         from c++ implementation for portability reasons.
         Returns self.
         """
-        m = md5.new()
+        m = md5()
         m.update(uuid.uuid1().bytes)
         self._bits = m.digest()
         return self
diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py
index c4c40739ec9514180d57f3c75db7259293ba679e..7e0e115d14600f29fe4b855077232a8d10529271 100644
--- a/indra/lib/python/indra/util/llsubprocess.py
+++ b/indra/lib/python/indra/util/llsubprocess.py
@@ -90,6 +90,17 @@ def run(command, args=None, data=None, timeout=None):
                     child.tochild.close()
         result = child.poll()
         if result != -1:
+            # At this point, the child process has exited and result
+            # is the return value from the process. Between the time
+            # we called select() and poll() the process may have
+            # exited so read all the data left on the child process
+            # stdout and stderr.
+            last = child.fromchild.read()
+            if last:
+                out.append(last)
+            last = child.childerr.read()
+            if last:
+                err.append(last)
             child.tochild.close()
             child.fromchild.close()
             child.childerr.close()
diff --git a/indra/lib/python/indra/util/llversion.py b/indra/lib/python/indra/util/llversion.py
index 770b861ddc1604e6dd2d133aa94513560c154455..2718a85f414cb958db30e8035bf21742583a084b 100644
--- a/indra/lib/python/indra/util/llversion.py
+++ b/indra/lib/python/indra/util/llversion.py
@@ -1,7 +1,7 @@
 """@file llversion.py
 @brief Utility for parsing llcommon/llversion${server}.h
        for the version string and channel string
-       Utility that parses svn info for branch and revision
+       Utility that parses hg or svn info for branch and revision
 
 $LicenseInfo:firstyear=2006&license=mit$
 
@@ -79,8 +79,8 @@ def get_svn_status_matching(regular_expression):
     status, output = commands.getstatusoutput('svn info %s' % get_src_root())
     m = regular_expression.search(output)
     if not m:
-        print "Failed to parse svn info output, resultfollows:"
-        print output
+        print >> sys.stderr, "Failed to parse svn info output, result follows:"
+        print >> sys.stderr, output
         raise Exception, "No matching svn status in "+src_root
     return m.group(1)
 
@@ -92,4 +92,35 @@ def get_svn_revision():
     last_rev_re = re.compile('Last Changed Rev: (\d+)')
     return get_svn_status_matching(last_rev_re)
 
-
+def get_hg_repo():
+    status, output = commands.getstatusoutput('hg showconfig paths.default')
+    if status:
+        print >> sys.stderr, output
+        sys.exit(1)
+    if not output:
+        print >> sys.stderr, 'ERROR: cannot find repo we cloned from'
+        sys.exit(1)
+    return output
+
+def get_hg_changeset():
+    # The right thing to do:
+    # status, output = commands.getstatusoutput('hg id -i')
+    # if status:
+    #     print >> sys.stderr, output
+    #    sys.exit(1)
+
+    # The temporary hack:
+    status, output = commands.getstatusoutput('hg parents --template "{rev}"')
+    if status:
+        print >> sys.stderr, output
+        sys.exit(1)
+    lines = output.splitlines()
+    if len(lines) > 1:
+        print >> sys.stderr, 'ERROR: working directory has %d parents' % len(lines)
+    return lines[0]
+
+def using_svn():
+    return os.path.isdir(os.path.join(get_src_root(), '.svn'))
+
+def using_hg():
+    return os.path.isdir(os.path.join(get_src_root(), '.hg'))
diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py
index 693b483f792f485d206dbac812865a6fef3d0170..5c19368240afa08b8576f3f16ec01c4b738c5f76 100644
--- a/indra/lib/python/indra/util/named_query.py
+++ b/indra/lib/python/indra/util/named_query.py
@@ -48,8 +48,8 @@
 from indra.base import config
 
 DEBUG = False
-NQ_FILE_SUFFIX = None
-NQ_FILE_SUFFIX_LEN = None
+NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
+NQ_FILE_SUFFIX_LEN  = len(NQ_FILE_SUFFIX)
 
 _g_named_manager = None
 
diff --git a/indra/lib/python/indra/util/test_win32_manifest.py b/indra/lib/python/indra/util/test_win32_manifest.py
new file mode 100644
index 0000000000000000000000000000000000000000..0149b9f43a8164860d5c696f31efa3422c3dcc65
--- /dev/null
+++ b/indra/lib/python/indra/util/test_win32_manifest.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+# @file test_win32_manifest.py
+# @brief Test an assembly binding version and uniqueness in a windows dll or exe.  
+#
+# $LicenseInfo:firstyear=2009&license=viewergpl$
+# 
+# Copyright (c) 2009, Linden Research, Inc.
+# 
+# Second Life Viewer Source Code
+# The source code in this file ("Source Code") is provided by Linden Lab
+# to you under the terms of the GNU General Public License, version 2.0
+# ("GPL"), unless you have obtained a separate licensing agreement
+# ("Other License"), formally executed by you and Linden Lab.  Terms of
+# the GPL can be found in doc/GPL-license.txt in this distribution, or
+# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+# 
+# There are special exceptions to the terms and conditions of the GPL as
+# it is applied to this Source Code. View the full text of the exception
+# in the file doc/FLOSS-exception.txt in this software distribution, or
+# online at
+# http://secondlifegrid.net/programs/open_source/licensing/flossexception
+# 
+# By copying, modifying or distributing this software, you acknowledge
+# that you have read and understood your obligations described above,
+# and agree to abide by those obligations.
+# 
+# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+# COMPLETENESS OR PERFORMANCE.
+# $/LicenseInfo$
+
+import sys, os
+import tempfile
+from xml.dom.minidom import parse
+
+class AssemblyTestException(Exception):
+    pass
+
+class NoManifestException(AssemblyTestException):
+    pass
+
+class MultipleBindingsException(AssemblyTestException):
+    pass
+
+class UnexpectedVersionException(AssemblyTestException):
+    pass
+
+class NoMatchingAssemblyException(AssemblyTestException):
+    pass
+
+def get_HKLM_registry_value(key_str, value_str):
+    import _winreg
+    reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
+    key = _winreg.OpenKey(reg, key_str)
+    value = _winreg.QueryValueEx(key, value_str)[0]
+    #print 'Found: %s' % value
+    return value
+        
+def find_vc_dir():
+    supported_versions = (r'8.0', r'9.0')
+    value_str = (r'ProductDir')
+    
+    for version in supported_versions:
+        key_str = (r'SOFTWARE\Microsoft\VisualStudio\%s\Setup\VC' %
+                   version)
+        try:
+            return get_HKLM_registry_value(key_str, value_str)
+        except WindowsError, err:
+            x64_key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
+                       version)
+            try:
+                return get_HKLM_registry_value(x64_key_str, value_str)
+            except:
+                print >> sys.stderr, "Didn't find MS VC version %s " % version
+        
+    raise
+
+def find_mt_path():
+    vc_dir = find_vc_dir()
+    mt_path = '\"%sbin\\mt.exe\"' % vc_dir
+    return mt_path
+    
+def test_assembly_binding(src_filename, assembly_name, assembly_ver):
+    print "checking %s dependency %s..." % (src_filename, assembly_name)
+
+    (tmp_file_fd, tmp_file_name) = tempfile.mkstemp(suffix='.xml')
+    tmp_file = os.fdopen(tmp_file_fd)
+    tmp_file.close()
+
+    mt_path = find_mt_path()
+    resource_id = ""
+    if os.path.splitext(src_filename)[1].lower() == ".dll":
+       resource_id = ";#2"
+    system_call = '%s -nologo -inputresource:%s%s -out:%s > NUL' % (mt_path, src_filename, resource_id, tmp_file_name)
+    print "Executing: %s" % system_call
+    mt_result = os.system(system_call)
+    if mt_result == 31:
+        print "No manifest found in %s" % src_filename
+        raise NoManifestException()
+
+    manifest_dom = parse(tmp_file_name)
+    nodes = manifest_dom.getElementsByTagName('assemblyIdentity')
+
+    versions = list()
+    for node in nodes:
+        if node.getAttribute('name') == assembly_name:
+            versions.append(node.getAttribute('version'))
+
+    if len(versions) == 0:
+        print "No matching assemblies found in %s" % src_filename
+        raise NoMatchingAssemblyException()
+        
+    elif len(versions) > 1:
+        print "Multiple bindings to %s found:" % assembly_name
+        print versions
+        print 
+        raise MultipleBindingsException(versions)
+
+    elif versions[0] != assembly_ver:
+        print "Unexpected version found for %s:" % assembly_name
+        print "Wanted %s, found %s" % (assembly_ver, versions[0])
+        print
+        raise UnexpectedVersionException(assembly_ver, versions[0])
+            
+    os.remove(tmp_file_name)
+    
+    print "SUCCESS: %s OK!" % src_filename
+    print
+  
+if __name__ == '__main__':
+
+    print
+    print "Running test_win32_manifest.py..."
+    
+    usage = 'test_win32_manfest <srcFileName> <assemblyName> <assemblyVersion>'
+
+    try:
+        src_filename = sys.argv[1]
+        assembly_name = sys.argv[2]
+        assembly_ver = sys.argv[3]
+    except:
+        print "Usage:"
+        print usage
+        print
+        raise
+    
+    test_assembly_binding(src_filename, assembly_name, assembly_ver)
+
+    
diff --git a/indra/llcharacter/llkeyframestandmotion.cpp b/indra/llcharacter/llkeyframestandmotion.cpp
index 1d42298f4d395adb638efae4713af11a74e45e72..1ae0ddeea0fba8787885b6a247866c0809973a28 100644
--- a/indra/llcharacter/llkeyframestandmotion.cpp
+++ b/indra/llcharacter/llkeyframestandmotion.cpp
@@ -190,7 +190,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask)
 	if (dot(mPelvisState->getJoint()->getWorldRotation(), mLastGoodPelvisRotation) < ROTATION_THRESHOLD)
 	{
 		mLastGoodPelvisRotation = mPelvisState->getJoint()->getWorldRotation();
-		mLastGoodPelvisRotation.normQuat();
+		mLastGoodPelvisRotation.normalize();
 		mTrackAnkles = TRUE;
 	}
 	else if ((mCharacter->getCharacterPosition() - mLastGoodPosition).magVecSquared() > POSITION_THRESHOLD)
diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index 9e4957342c3f09e7cdb036182ed3dfaa7eddb506..6232c7588bb38321c19908919965e31e79880193 100644
--- a/indra/llcharacter/llvisualparam.cpp
+++ b/indra/llcharacter/llvisualparam.cpp
@@ -173,7 +173,8 @@ LLVisualParam::LLVisualParam()
 	mTargetWeight( 0.f ),
 	mIsAnimating( FALSE ),
 	mID( -1 ),
-	mInfo( 0 )
+	mInfo( 0 ),
+	mIsDummy(FALSE)
 {
 }
 
@@ -251,6 +252,13 @@ void LLVisualParam::setWeight(F32 weight, BOOL set_by_user)
 //-----------------------------------------------------------------------------
 void LLVisualParam::setAnimationTarget(F32 target_value, BOOL set_by_user)
 {
+	// don't animate dummy parameters
+	if (mIsDummy)
+	{
+		setWeight(target_value, set_by_user);
+		return;
+	}
+
 	if (mInfo)
 	{
 		if (getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index 0b516b9374f4e042ec1f2f1fb8f605df4dd9a527..affc49debfecfabe30852965e747046bf69ebec3 100644
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -148,15 +148,19 @@ class LLVisualParam
 	LLVisualParam*			getNextParam()		{ return mNext; }
 	void					setNextParam( LLVisualParam *next );
 	
-	virtual void			setAnimating(BOOL is_animating) { mIsAnimating = is_animating; }
+	virtual void			setAnimating(BOOL is_animating) { mIsAnimating = is_animating && !mIsDummy; }
 	BOOL					getAnimating() const { return mIsAnimating; }
 
+	void					setIsDummy(BOOL is_self) { mIsDummy = is_self; }
+
 protected:
 	F32					mCurWeight;			// current weight
 	F32					mLastWeight;		// last weight
 	LLVisualParam*		mNext;				// next param in a shared chain
 	F32					mTargetWeight;		// interpolation target
 	BOOL				mIsAnimating;	// this value has been given an interpolation target
+	BOOL				mIsDummy;  // this is used to prevent dummy visual params from animating
+
 
 	S32					mID;				// id for storing weight/morphtarget compares compactly
 	LLVisualParamInfo	*mInfo;
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 7468e3dde46c62bba6e4aeda9ff1104408e0fd07..e7aaf3c984de74f5c3ed45d38b50cdb7931273a6 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -4,12 +4,19 @@ project(llcommon)
 
 include(00-Common)
 include(LLCommon)
+include(Linking)
 include(Boost)
+include (Pth)
+
+if (WINDOWS)
+    include(CopyWinLibs)
+endif (WINDOWS)
 
 include_directories(
     ${EXPAT_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
     ${ZLIB_INCLUDE_DIRS}
+    ${PTH_INCLUDE_DIRS}
     )
 
 # add_executable(lltreeiterators lltreeiterators.cpp)
@@ -26,6 +33,7 @@ set(llcommon_SOURCE_FILES
     llbase32.cpp
     llbase64.cpp
     llcommon.cpp
+    llcoros.cpp
     llcrc.cpp
     llcriticaldamp.cpp
     llcursortypes.cpp
@@ -34,6 +42,9 @@ set(llcommon_SOURCE_FILES
     llerror.cpp
     llerrorthread.cpp
     llevent.cpp
+    lleventcoro.cpp
+    lleventdispatcher.cpp
+    lleventfilter.cpp
     llevents.cpp
     llfasttimer.cpp
     llfile.cpp
@@ -64,6 +75,7 @@ set(llcommon_SOURCE_FILES
     llsdserialize_xml.cpp
     llsdutil.cpp
     llsecondlifeurls.cpp
+    llsingleton.cpp
     llstat.cpp
     llstacktrace.cpp
     llstreamtools.cpp
@@ -106,6 +118,7 @@ set(llcommon_HEADER_FILES
     llchat.h
     llclickaction.h
     llcommon.h
+    llcoros.h
     llcrc.h
     llcriticaldamp.h
     llcursortypes.h
@@ -127,6 +140,9 @@ set(llcommon_HEADER_FILES
     llerrorlegacy.h
     llerrorthread.h
     llevent.h
+    lleventcoro.h
+    lleventdispatcher.h
+    lleventfilter.h
     llevents.h
     lleventemitter.h
     llextendedstatus.h
@@ -141,6 +157,7 @@ set(llcommon_HEADER_FILES
     llhttpstatuscodes.h
     llindexedqueue.h
     llinstancetracker.h
+    llinstancetracker.h
     llkeythrottle.h
     lllazy.h
     lllinkedqueue.h
@@ -222,25 +239,63 @@ set_source_files_properties(${llcommon_HEADER_FILES}
 
 list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
 
-add_library (llcommon ${llcommon_SOURCE_FILES})
-target_link_libraries(llcommon
+if(LLCOMMON_LINK_SHARED)
+    add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
+
+    if(SHARED_LIB_STAGING_DIR)
+        # *FIX:Mani ---
+        # llcommon.dll get written to the DLL staging directory.
+        # Also this directory is shared with RunBuildTest.cmake, y'know, for the tests.
+        set_target_properties(llcommon PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${SHARED_LIB_STAGING_DIR})
+        if(NOT WINDOWS)
+          get_target_property(LLCOMMON_PATH llcommon LOCATION)
+          get_filename_component(LLCOMMON_FILE ${LLCOMMON_PATH} NAME)
+          add_custom_command(
+            TARGET llcommon POST_BUILD
+            COMMAND ${CMAKE_COMMAND}
+            ARGS
+              -E
+              copy_if_different
+              ${LLCOMMON_PATH}
+              ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/${LLCOMMON_FILE}
+            COMMENT "Copying llcommon to the staging folder."
+            )
+        endif(NOT WINDOWS)
+    endif(SHARED_LIB_STAGING_DIR)
+
+    if (DARWIN)
+      set_target_properties(llcommon PROPERTIES
+        BUILD_WITH_INSTALL_RPATH 1
+        INSTALL_NAME_DIR "@executable_path/../Resources"
+        )
+    endif(DARWIN)
+
+else(LLCOMMON_LINK_SHARED)
+    add_library (llcommon ${llcommon_SOURCE_FILES})
+endif(LLCOMMON_LINK_SHARED)
+
+target_link_libraries(
+    llcommon
     ${APRUTIL_LIBRARIES}
     ${APR_LIBRARIES}
     ${EXPAT_LIBRARIES}
     ${ZLIB_LIBRARIES}
+    ${WINDOWS_LIBRARIES}
     ${BOOST_PROGRAM_OPTIONS_LIBRARY}
     ${BOOST_REGEX_LIBRARY}
+    ${PTH_LIBRARIES}
     )
 
-#add unit tests
-INCLUDE(LLAddBuildTest)
+add_dependencies(llcommon stage_third_party_libs)
+
+include(LLAddBuildTest)
 SET(llcommon_TEST_SOURCE_FILES
   # unit-testing llcommon is not possible right now as the test-harness *itself* depends upon llcommon, causing a circular dependency.  Add your 'unit' tests as integration tests for now.
   )
 LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
 
 #set(TEST_DEBUG on)
-set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES} ${GOOGLEMOCK_LIBRARIES})
 LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}")
 LL_ADD_INTEGRATION_TEST(bitpack "" "${test_libs}")
 LL_ADD_INTEGRATION_TEST(llbase64 "" "${test_libs}")
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h
index 8687a246558253248db47bed75f113930b87f137..c2eb867795d8c87d3a0036b1d113a158c8b2dee3 100644
--- a/indra/llcommon/linden_common.h
+++ b/indra/llcommon/linden_common.h
@@ -72,13 +72,7 @@
 #ifdef LL_WINDOWS
 // Reenable warnings we disabled above
 #pragma warning (3 : 4702) // unreachable code, we like level 3, not 4
-// level 4 warnings that we need to disable:
-#pragma warning (disable : 4100) // unreferenced formal parameter
-#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) )
-#pragma warning (disable : 4244) // possible loss of data on conversions
-#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
-#pragma warning (disable : 4512) // assignment operator could not be generated
-#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) )
+// moved msvc warnings to llpreprocessor.h  *TODO - delete this comment after merge conflicts are unlikely -brad
 #endif	//	LL_WINDOWS
 
 // Linden only libs in alpha-order other than stdtypes.h
diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h
index 2b70fee0b8f9d6dd94b7b42c0aac0364305703f3..0d6f18c5d47a80cc06499df7b2e50eddd0ce0ffd 100644
--- a/indra/llcommon/llallocator.h
+++ b/indra/llcommon/llallocator.h
@@ -1,63 +1,63 @@
-/** 
- * @file llallocator.h
- * @brief Declaration of the LLAllocator class.
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * 
- * Copyright (c) 2009-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLALLOCATOR_H
-#define LL_LLALLOCATOR_H
-
-#include <string>
-
-#include "llmemtype.h"
-#include "llallocator_heap_profile.h"
-
-class LLAllocator {
-    friend class LLMemoryView;
-    friend class LLMemType;
-
-private:
-	static void pushMemType(S32 type);
-	static S32 popMemType();
-
-public:
-    void setProfilingEnabled(bool should_enable);
-
-    static bool isProfiling();
-
-    LLAllocatorHeapProfile const & getProfile();
-
-private:
-    std::string getRawProfile();
-
-private:
-    LLAllocatorHeapProfile mProf;
-};
-
-#endif // LL_LLALLOCATOR_H
+/** 
+ * @file llallocator.h
+ * @brief Declaration of the LLAllocator class.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLALLOCATOR_H
+#define LL_LLALLOCATOR_H
+
+#include <string>
+
+#include "llmemtype.h"
+#include "llallocator_heap_profile.h"
+
+class LL_COMMON_API LLAllocator {
+    friend class LLMemoryView;
+    friend class LLMemType;
+
+private:
+	static void pushMemType(S32 type);
+	static S32 popMemType();
+
+public:
+    void setProfilingEnabled(bool should_enable);
+
+    static bool isProfiling();
+
+    LLAllocatorHeapProfile const & getProfile();
+
+private:
+    std::string getRawProfile();
+
+private:
+    LLAllocatorHeapProfile mProf;
+};
+
+#endif // LL_LLALLOCATOR_H
diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp
index d82ee9ed81bc25c43fea886a95abe558bd19d07e..0a807702d0a92fbafc805a622efef16bfe2834a0 100644
--- a/indra/llcommon/llallocator_heap_profile.cpp
+++ b/indra/llcommon/llallocator_heap_profile.cpp
@@ -38,6 +38,7 @@
 // disable warning about boost::lexical_cast returning uninitialized data
 // when it fails to parse the string
 #pragma warning (disable:4701)
+#pragma warning (disable:4702)
 #endif
 
 #include <boost/algorithm/string/split.hpp>
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index e32a293f1cca8754535f73f2db3e7d34c9b6d565..1a052ce62d6c316722e6fbda471f7c03aa2427de 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -62,7 +62,7 @@ class LLChildInfo
 };
 #endif
 
-class LLApp : public LLOptionInterface
+class LL_COMMON_API LLApp : public LLOptionInterface
 {
 	friend class LLErrorThread;
 public:
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 63130a89fcd1d3f5f7d557642c159aacced9a925..0898aeec470e26e02717b8dddf03352f6e8c2373 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -1,259 +1,259 @@
-/** 
- * @file llapr.h
- * @author Phoenix
- * @date 2004-11-28
- * @brief Helper functions for using the apache portable runtime library.
- *
- * $LicenseInfo:firstyear=2004&license=viewergpl$
- * 
- * Copyright (c) 2004-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLAPR_H
-#define LL_LLAPR_H
-
-#if LL_LINUX || LL_SOLARIS
-#include <sys/param.h>  // Need PATH_MAX in APR headers...
-#endif
-
-#include <boost/noncopyable.hpp>
-
-#include "apr_thread_proc.h"
-#include "apr_thread_mutex.h"
-#include "apr_getopt.h"
-#include "apr_signal.h"
-#include "apr_atomic.h"
-#include "llstring.h"
-
-extern apr_thread_mutex_t* gLogMutexp;
-extern apr_thread_mutex_t* gCallStacksLogMutexp;
-
-/** 
- * @brief initialize the common apr constructs -- apr itself, the
- * global pool, and a mutex.
- */
-void ll_init_apr();
-
-/** 
- * @brief Cleanup those common apr constructs.
- */
-void ll_cleanup_apr();
-
-//
-//LL apr_pool
-//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
-//
-class LLAPRPool
-{
-public:
-	LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
-	~LLAPRPool() ;
-
-	apr_pool_t* getAPRPool() ;
-	apr_status_t getStatus() {return mStatus ; }
-
-protected:
-	void releaseAPRPool() ;
-	void createAPRPool() ;
-
-protected:
-	apr_pool_t*  mPool ;              //pointing to an apr_pool
-	apr_pool_t*  mParent ;			  //parent pool
-	apr_size_t   mMaxSize ;           //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work.
-	apr_status_t mStatus ;            //status when creating the pool
-	BOOL         mReleasePoolFlag ;   //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
-};
-
-//
-//volatile LL apr_pool
-//which clears memory automatically.
-//so it can not hold static data or data after memory is cleared
-//
-class LLVolatileAPRPool : public LLAPRPool
-{
-public:
-	LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
-	~LLVolatileAPRPool(){}
-
-	apr_pool_t* getVolatileAPRPool() ;
-	
-	void        clearVolatileAPRPool() ;
-
-	BOOL        isFull() ;
-	BOOL        isEmpty() {return !mNumActiveRef ;}
-private:
-	S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
-	S32 mNumTotalRef ;  //number of total pointers pointing to the apr_pool since last creating.   
-} ;
-
-/** 
- * @class LLScopedLock
- * @brief Small class to help lock and unlock mutexes.
- *
- * This class is used to have a stack level lock once you already have
- * an apr mutex handy. The constructor handles the lock, and the
- * destructor handles the unlock. Instances of this class are
- * <b>not</b> thread safe.
- */
-class LLScopedLock : private boost::noncopyable
-{
-public:
-	/**
-	 * @brief Constructor which accepts a mutex, and locks it.
-	 *
-	 * @param mutex An allocated APR mutex. If you pass in NULL,
-	 * this wrapper will not lock.
-	 */
-	LLScopedLock(apr_thread_mutex_t* mutex);
-
-	/**
-	 * @brief Destructor which unlocks the mutex if still locked.
-	 */
-	~LLScopedLock();
-
-	/** 
-	 * @brief Check lock.
-	 */
-	bool isLocked() const { return mLocked; }
-
-	/** 
-	 * @brief This method unlocks the mutex.
-	 */
-	void unlock();
-
-protected:
-	bool mLocked;
-	apr_thread_mutex_t* mMutex;
-};
-
-template <typename Type> class LLAtomic32
-{
-public:
-	LLAtomic32<Type>() {};
-	LLAtomic32<Type>(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); };
-	~LLAtomic32<Type>() {};
-
-	operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
-	Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
-	void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
-	void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
-	Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
-	Type operator --(int) { return apr_atomic_dec32(&mData); } // Type--
-	
-private:
-	apr_uint32_t mData;
-};
-
-typedef LLAtomic32<U32> LLAtomicU32;
-typedef LLAtomic32<S32> LLAtomicS32;
-
-// File IO convenience functions.
-// Returns NULL if the file fails to openm sets *sizep to file size of not NULL
-// abbreviated flags
-#define LL_APR_R (APR_READ) // "r"
-#define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w"
-#define LL_APR_RB (APR_READ|APR_BINARY) // "rb"
-#define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb"
-#define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b"
-#define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b"
-
-//
-//apr_file manager
-//which: 1)only keeps one file open;
-//       2)closes the open file in the destruction function
-//       3)informs the apr_pool to clean the memory when the file is closed.
-//Note: please close an open file at the earliest convenience. 
-//      especially do not put some time-costly operations between open() and close().
-//      otherwise it might lock the APRFilePool.
-//there are two different apr_pools the APRFile can use:
-//      1, a temperary pool passed to an APRFile function, which is used within this function and only once.
-//      2, a global pool.
-//
-class LLAPRFile
-{
-private:
-	apr_file_t* mFile ;
-	LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. 
-
-public:
-	LLAPRFile() ;
-	~LLAPRFile() ;
-
-	apr_status_t open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep = NULL);
-	apr_status_t open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool = NULL, S32* sizep = NULL);
-	apr_status_t close() ;
-
-	// Returns actual offset, -1 if seek fails
-	S32 seek(apr_seek_where_t where, S32 offset);
-	apr_status_t eof() { return apr_file_eof(mFile);}
-
-	// Returns bytes read/written, 0 if read/write fails:
-	S32 read(void* buf, S32 nbytes);
-	S32 write(const void* buf, S32 nbytes);
-	
-	apr_file_t* getFileHandle() {return mFile;}	
-
-private:
-	apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
-
-//
-//*******************************************************************************************************************************
-//static components
-//
-public:
-	static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
-
-private:
-	static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags);
-	static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ;
-	static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
-public:
-	// returns false if failure:
-	static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL);
-	static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL);
-	static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ);
-	static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL);
-	static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
-	static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
-
-	// Returns bytes read/written, 0 if read/write fails:
-	static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);	
-	static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);	
-//*******************************************************************************************************************************
-};
-
-/**
- * @brief Function which approprately logs error or remains quiet on
- * APR_SUCCESS.
- * @return Returns <code>true</code> if status is an error condition.
- */
-bool ll_apr_warn_status(apr_status_t status);
-
-void ll_apr_assert_status(apr_status_t status);
-
-extern "C" apr_pool_t* gAPRPoolp; // Global APR memory pool
-
-#endif // LL_LLAPR_H
+/** 
+ * @file llapr.h
+ * @author Phoenix
+ * @date 2004-11-28
+ * @brief Helper functions for using the apache portable runtime library.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * 
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAPR_H
+#define LL_LLAPR_H
+
+#if LL_LINUX || LL_SOLARIS
+#include <sys/param.h>  // Need PATH_MAX in APR headers...
+#endif
+
+#include <boost/noncopyable.hpp>
+
+#include "apr_thread_proc.h"
+#include "apr_thread_mutex.h"
+#include "apr_getopt.h"
+#include "apr_signal.h"
+#include "apr_atomic.h"
+#include "llstring.h"
+
+extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
+extern apr_thread_mutex_t* gCallStacksLogMutexp;
+
+/** 
+ * @brief initialize the common apr constructs -- apr itself, the
+ * global pool, and a mutex.
+ */
+void LL_COMMON_API ll_init_apr();
+
+/** 
+ * @brief Cleanup those common apr constructs.
+ */
+void LL_COMMON_API ll_cleanup_apr();
+
+//
+//LL apr_pool
+//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
+//
+class LL_COMMON_API LLAPRPool
+{
+public:
+	LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
+	~LLAPRPool() ;
+
+	apr_pool_t* getAPRPool() ;
+	apr_status_t getStatus() {return mStatus ; }
+
+protected:
+	void releaseAPRPool() ;
+	void createAPRPool() ;
+
+protected:
+	apr_pool_t*  mPool ;              //pointing to an apr_pool
+	apr_pool_t*  mParent ;			  //parent pool
+	apr_size_t   mMaxSize ;           //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work.
+	apr_status_t mStatus ;            //status when creating the pool
+	BOOL         mReleasePoolFlag ;   //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
+};
+
+//
+//volatile LL apr_pool
+//which clears memory automatically.
+//so it can not hold static data or data after memory is cleared
+//
+class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool
+{
+public:
+	LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
+	~LLVolatileAPRPool(){}
+
+	apr_pool_t* getVolatileAPRPool() ;
+	
+	void        clearVolatileAPRPool() ;
+
+	BOOL        isFull() ;
+	BOOL        isEmpty() {return !mNumActiveRef ;}
+private:
+	S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
+	S32 mNumTotalRef ;  //number of total pointers pointing to the apr_pool since last creating.   
+} ;
+
+/** 
+ * @class LLScopedLock
+ * @brief Small class to help lock and unlock mutexes.
+ *
+ * This class is used to have a stack level lock once you already have
+ * an apr mutex handy. The constructor handles the lock, and the
+ * destructor handles the unlock. Instances of this class are
+ * <b>not</b> thread safe.
+ */
+class LL_COMMON_API LLScopedLock : private boost::noncopyable
+{
+public:
+	/**
+	 * @brief Constructor which accepts a mutex, and locks it.
+	 *
+	 * @param mutex An allocated APR mutex. If you pass in NULL,
+	 * this wrapper will not lock.
+	 */
+	LLScopedLock(apr_thread_mutex_t* mutex);
+
+	/**
+	 * @brief Destructor which unlocks the mutex if still locked.
+	 */
+	~LLScopedLock();
+
+	/** 
+	 * @brief Check lock.
+	 */
+	bool isLocked() const { return mLocked; }
+
+	/** 
+	 * @brief This method unlocks the mutex.
+	 */
+	void unlock();
+
+protected:
+	bool mLocked;
+	apr_thread_mutex_t* mMutex;
+};
+
+template <typename Type> class LLAtomic32
+{
+public:
+	LLAtomic32<Type>() {};
+	LLAtomic32<Type>(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); };
+	~LLAtomic32<Type>() {};
+
+	operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
+	Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
+	void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
+	void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
+	Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
+	Type operator --(int) { return apr_atomic_dec32(&mData); } // Type--
+	
+private:
+	apr_uint32_t mData;
+};
+
+typedef LLAtomic32<U32> LLAtomicU32;
+typedef LLAtomic32<S32> LLAtomicS32;
+
+// File IO convenience functions.
+// Returns NULL if the file fails to openm sets *sizep to file size of not NULL
+// abbreviated flags
+#define LL_APR_R (APR_READ) // "r"
+#define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w"
+#define LL_APR_RB (APR_READ|APR_BINARY) // "rb"
+#define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb"
+#define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b"
+#define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b"
+
+//
+//apr_file manager
+//which: 1)only keeps one file open;
+//       2)closes the open file in the destruction function
+//       3)informs the apr_pool to clean the memory when the file is closed.
+//Note: please close an open file at the earliest convenience. 
+//      especially do not put some time-costly operations between open() and close().
+//      otherwise it might lock the APRFilePool.
+//there are two different apr_pools the APRFile can use:
+//      1, a temperary pool passed to an APRFile function, which is used within this function and only once.
+//      2, a global pool.
+//
+class LL_COMMON_API LLAPRFile
+{
+private:
+	apr_file_t* mFile ;
+	LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. 
+
+public:
+	LLAPRFile() ;
+	~LLAPRFile() ;
+
+	apr_status_t open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep = NULL);
+	apr_status_t open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool = NULL, S32* sizep = NULL);
+	apr_status_t close() ;
+
+	// Returns actual offset, -1 if seek fails
+	S32 seek(apr_seek_where_t where, S32 offset);
+	apr_status_t eof() { return apr_file_eof(mFile);}
+
+	// Returns bytes read/written, 0 if read/write fails:
+	S32 read(void* buf, S32 nbytes);
+	S32 write(const void* buf, S32 nbytes);
+	
+	apr_file_t* getFileHandle() {return mFile;}	
+
+private:
+	apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
+
+//
+//*******************************************************************************************************************************
+//static components
+//
+public:
+	static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
+
+private:
+	static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags);
+	static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ;
+	static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
+public:
+	// returns false if failure:
+	static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL);
+	static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL);
+	static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ);
+	static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL);
+	static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
+	static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
+
+	// Returns bytes read/written, 0 if read/write fails:
+	static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);	
+	static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);	
+//*******************************************************************************************************************************
+};
+
+/**
+ * @brief Function which approprately logs error or remains quiet on
+ * APR_SUCCESS.
+ * @return Returns <code>true</code> if status is an error condition.
+ */
+bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
+
+void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
+
+extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
+
+#endif // LL_LLAPR_H
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index d57494b444ce1a60a9fe404df5176f662ceeb5e5..f3aff332ba9310bdf15aa039b7769edc7e0bdf0c 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -290,6 +290,7 @@ bool LLAssetType::lookupIsEnsembleCategoryType(EType asset_type)
 			asset_type <= AT_FOLDER_ENSEMBLE_END);
 }
 
+
 // 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 a1154d16e3fb34436389f6c7133d794cf5886dbe..973b10ea6fe4c9cae8ed1c8a10c015eaf1704b1b 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -37,7 +37,7 @@
 
 #include "stdenums.h" 	// for EDragAndDropType
 
-class LLAssetType
+class LL_COMMON_API LLAssetType
 {
 public:
 	enum EType
@@ -152,6 +152,7 @@ class LLAssetType
 		    // Mesh data in our proprietary SLM format
 
 		AT_COUNT = 50,
+
 			// +*********************************************************+
 			// |  TO ADD AN ELEMENT TO THIS ENUM:                        |
 			// +*********************************************************+
diff --git a/indra/llcommon/llbase32.h b/indra/llcommon/llbase32.h
index 63a93e11ab503a952156fcdf2f588afa6ce31239..0697f7b8e204d36c28b891dd3fea241958f0b99c 100644
--- a/indra/llcommon/llbase32.h
+++ b/indra/llcommon/llbase32.h
@@ -32,9 +32,9 @@
  */
 
 #ifndef LLBASE32_H
-#define LLBASE32_h
+#define LLBASE32_H
 
-class LLBase32
+class LL_COMMON_API LLBase32
 {
 public:
 	static std::string encode(const U8* input, size_t input_size);
diff --git a/indra/llcommon/llbase64.h b/indra/llcommon/llbase64.h
index 58414bba8bb980557679258220e837a6f9b9f9cc..c48fea24783716d397734260b27ce4e604a5124a 100644
--- a/indra/llcommon/llbase64.h
+++ b/indra/llcommon/llbase64.h
@@ -32,9 +32,9 @@
  */
 
 #ifndef LLBASE64_H
-#define LLBASE64_h
+#define LLBASE64_H
 
-class LLBase64
+class LL_COMMON_API LLBase64
 {
 public:
 	static std::string encode(const U8* input, size_t input_size);
diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h
index a1808e8a6c2dc54b535f93952a37f7de01862778..b36471f9f81cac843b35140ab7df4d1c0dd1c0f5 100644
--- a/indra/llcommon/llcommon.h
+++ b/indra/llcommon/llcommon.h
@@ -37,7 +37,7 @@
 #include "lltimer.h"
 #include "llfile.h"
 
-class LLCommon
+class LL_COMMON_API LLCommon
 {
 public:
 	static void initClass();
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..377bfaa247cd422edffc4db220c15c154ccc7103
--- /dev/null
+++ b/indra/llcommon/llcoros.cpp
@@ -0,0 +1,137 @@
+/**
+ * @file   llcoros.cpp
+ * @author Nat Goodspeed
+ * @date   2009-06-03
+ * @brief  Implementation for llcoros.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llcoros.h"
+// STL headers
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+// other Linden headers
+#include "llevents.h"
+#include "llerror.h"
+#include "stringize.h"
+
+LLCoros::LLCoros()
+{
+    // Register our cleanup() method for "mainloop" ticks
+    LLEventPumps::instance().obtain("mainloop").listen(
+        "LLCoros", boost::bind(&LLCoros::cleanup, this, _1));
+}
+
+bool LLCoros::cleanup(const LLSD&)
+{
+    // Walk the mCoros map, checking and removing completed coroutines.
+    for (CoroMap::iterator mi(mCoros.begin()), mend(mCoros.end()); mi != mend; )
+    {
+        // Has this coroutine exited (normal return, exception, exit() call)
+        // since last tick?
+        if (mi->second->exited())
+        {
+            LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
+            // The erase() call will invalidate its passed iterator value --
+            // so increment mi FIRST -- but pass its original value to
+            // erase(). This is what postincrement is all about.
+            mCoros.erase(mi++);
+        }
+        else
+        {
+            // Still live, just skip this entry as if incrementing at the top
+            // of the loop as usual.
+            ++mi;
+        }
+    }
+    return false;
+}
+
+std::string LLCoros::generateDistinctName(const std::string& prefix) const
+{
+    // Allowing empty name would make getName()'s not-found return ambiguous.
+    if (prefix.empty())
+    {
+        LL_ERRS("LLCoros") << "LLCoros::launch(): pass non-empty name string" << LL_ENDL;
+    }
+
+    // If the specified name isn't already in the map, just use that.
+    std::string name(prefix);
+
+    // Find the lowest numeric suffix that doesn't collide with an existing
+    // entry. Start with 2 just to make it more intuitive for any interested
+    // parties: e.g. "joe", "joe2", "joe3"...
+    for (int i = 2; ; name = STRINGIZE(prefix << i++))
+    {
+        if (mCoros.find(name) == mCoros.end())
+        {
+            LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
+            return name;
+        }
+    }
+}
+
+bool LLCoros::kill(const std::string& name)
+{
+    CoroMap::iterator found = mCoros.find(name);
+    if (found == mCoros.end())
+    {
+        return false;
+    }
+    // Because this is a boost::ptr_map, erasing the map entry also destroys
+    // the referenced heap object, in this case the boost::coroutine object,
+    // which will terminate the coroutine.
+    mCoros.erase(found);
+    return true;
+}
+
+std::string LLCoros::getNameByID(const void* self_id) const
+{
+    // Walk the existing coroutines, looking for one from which the 'self_id'
+    // passed to us comes.
+    for (CoroMap::const_iterator mi(mCoros.begin()), mend(mCoros.end()); mi != mend; ++mi)
+    {
+        namespace coro_private = boost::coroutines::detail;
+        if (static_cast<void*>(coro_private::coroutine_accessor::get_impl(const_cast<coro&>(*mi->second)).get())
+            == self_id)
+        {
+            return mi->first;
+        }
+    }
+    return "";
+}
+
+/*****************************************************************************
+*   MUST BE LAST
+*****************************************************************************/
+// Turn off MSVC optimizations for just LLCoros::launchImpl() -- see
+// DEV-32777. But MSVC doesn't support push/pop for optimization flags as it
+// does for warning suppression, and we really don't want to force
+// optimization ON for other code even in Debug or RelWithDebInfo builds.
+
+#if LL_MSVC
+// work around broken optimizations
+#pragma warning(disable: 4748)
+#pragma optimize("", off)
+#endif // LL_MSVC
+
+std::string LLCoros::launchImpl(const std::string& prefix, coro* newCoro)
+{
+    std::string name(generateDistinctName(prefix));
+    mCoros.insert(name, newCoro);
+    /* Run the coroutine until its first wait, then return here */
+    (*newCoro)(std::nothrow);
+    return name;
+}
+
+#if LL_MSVC
+// reenable optimizations
+#pragma optimize("", on)
+#endif // LL_MSVC
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
new file mode 100644
index 0000000000000000000000000000000000000000..6c5fa5af6d6884908d36fcbd64e0510a72de6a7d
--- /dev/null
+++ b/indra/llcommon/llcoros.h
@@ -0,0 +1,149 @@
+/**
+ * @file   llcoros.h
+ * @author Nat Goodspeed
+ * @date   2009-06-02
+ * @brief  Manage running boost::coroutine instances
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLCOROS_H)
+#define LL_LLCOROS_H
+
+#include <boost/coroutine/coroutine.hpp>
+#include "llsingleton.h"
+#include <boost/ptr_container/ptr_map.hpp>
+#include <string>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <stdexcept>
+
+/**
+ * Registry of named Boost.Coroutine instances
+ *
+ * The Boost.Coroutine library supports the general case of a coroutine
+ * accepting arbitrary parameters and yielding multiple (sets of) results. For
+ * such use cases, it's natural for the invoking code to retain the coroutine
+ * instance: the consumer repeatedly calls into the coroutine, perhaps passing
+ * new parameter values, prompting it to yield its next result.
+ *
+ * Our typical coroutine usage is different, though. For us, coroutines
+ * provide an alternative to the @c Responder pattern. Our typical coroutine
+ * has @c void return, invoked in fire-and-forget mode: the handler for some
+ * user gesture launches the coroutine and promptly returns to the main loop.
+ * The coroutine initiates some action that will take multiple frames (e.g. a
+ * capability request), waits for its result, processes it and silently steals
+ * away.
+ *
+ * This usage poses two (related) problems:
+ *
+ * # Who should own the coroutine instance? If it's simply local to the
+ *   handler code that launches it, return from the handler will destroy the
+ *   coroutine object, terminating the coroutine.
+ * # Once the coroutine terminates, in whatever way, who's responsible for
+ *   cleaning up the coroutine object?
+ *
+ * LLCoros is a Singleton collection of currently-active coroutine instances.
+ * Each has a name. You ask LLCoros to launch a new coroutine with a suggested
+ * name prefix; from your prefix it generates a distinct name, registers the
+ * new coroutine and returns the actual name.
+ *
+ * The name can be used to kill off the coroutine prematurely, if needed. It
+ * can also provide diagnostic info: we can look up the name of the
+ * currently-running coroutine.
+ *
+ * Finally, the next frame ("mainloop" event) after the coroutine terminates,
+ * LLCoros will notice its demise and destroy it.
+ */
+class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
+{
+public:
+    /// Canonical boost::coroutines::coroutine signature we use
+    typedef boost::coroutines::coroutine<void()> coro;
+    /// Canonical 'self' type
+    typedef coro::self self;
+
+    /**
+     * Create and start running a new coroutine with specified name. The name
+     * string you pass is a suggestion; it will be tweaked for uniqueness. The
+     * actual name is returned to you.
+     *
+     * Usage looks like this, for (e.g.) two coroutine parameters:
+     * @code
+     * class MyClass
+     * {
+     * public:
+     *     ...
+     *     // Do NOT NOT NOT accept reference params other than 'self'!
+     *     // Pass by value only!
+     *     void myCoroutineMethod(LLCoros::self& self, std::string, LLSD);
+     *     ...
+     * };
+     * ...
+     * std::string name = LLCoros::instance().launch(
+     *    "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1,
+     *                          "somestring", LLSD(17));
+     * @endcode
+     *
+     * Your function/method must accept LLCoros::self& as its first parameter.
+     * It can accept any other parameters you want -- but ONLY BY VALUE!
+     * Other reference parameters are a BAD IDEA! You Have Been Warned. See
+     * DEV-32777 comments for an explanation.
+     *
+     * Pass a callable that accepts the single LLCoros::self& parameter. It
+     * may work to pass a free function whose only parameter is 'self'; for
+     * all other cases use boost::bind(). Of course, for a non-static class
+     * method, the first parameter must be the class instance. Use the
+     * placeholder _1 for the 'self' parameter. Any other parameters should be
+     * passed via the bind() expression.
+     *
+     * launch() tweaks the suggested name so it won't collide with any
+     * existing coroutine instance, creates the coroutine instance, registers
+     * it with the tweaked name and runs it until its first wait. At that
+     * point it returns the tweaked name.
+     */
+    template <typename CALLABLE>
+    std::string launch(const std::string& prefix, const CALLABLE& callable)
+    {
+        return launchImpl(prefix, new coro(callable));
+    }
+
+    /**
+     * Abort a running coroutine by name. Normally, when a coroutine either
+     * runs to completion or terminates with an exception, LLCoros quietly
+     * cleans it up. This is for use only when you must explicitly interrupt
+     * one prematurely. Returns @c true if the specified name was found and
+     * still running at the time.
+     */
+    bool kill(const std::string& name);
+
+    /**
+     * From within a coroutine, pass its @c self object to look up the
+     * (tweaked) name string by which this coroutine is registered. Returns
+     * the empty string if not found (e.g. if the coroutine was launched by
+     * hand rather than using LLCoros::launch()).
+     */
+    template <typename COROUTINE_SELF>
+    std::string getName(const COROUTINE_SELF& self) const
+    {
+        return getNameByID(self.get_id());
+    }
+
+    /// getName() by self.get_id()
+    std::string getNameByID(const void* self_id) const;
+
+private:
+    friend class LLSingleton<LLCoros>;
+    LLCoros();
+    std::string launchImpl(const std::string& prefix, coro* newCoro);
+    std::string generateDistinctName(const std::string& prefix) const;
+    bool cleanup(const LLSD&);
+
+    typedef boost::ptr_map<std::string, coro> CoroMap;
+    CoroMap mCoros;
+};
+
+#endif /* ! defined(LL_LLCOROS_H) */
diff --git a/indra/llcommon/llcrc.h b/indra/llcommon/llcrc.h
index 27fae7d26979b280e1f4e8fd7c5b0ff13f97b146..74369062cc112d8a8e0c6f57ab4355ab3b6bc412 100644
--- a/indra/llcommon/llcrc.h
+++ b/indra/llcommon/llcrc.h
@@ -50,7 +50,7 @@
 //  llinfos << "File crc: " << crc.getCRC() << llendl;
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-class LLCRC
+class LL_COMMON_API LLCRC
 {
 protected:
 	U32 mCurrent;
diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h
index ad98284a6c59a1174d568e5b5b8c1cbe00b6642f..1ea5914b5b972978bbd6fe8e988639bb4a811923 100644
--- a/indra/llcommon/llcriticaldamp.h
+++ b/indra/llcommon/llcriticaldamp.h
@@ -38,7 +38,7 @@
 
 #include "llframetimer.h"
 
-class LLCriticalDamp 
+class LL_COMMON_API LLCriticalDamp 
 {
 public:
 	LLCriticalDamp();
diff --git a/indra/llcommon/llcursortypes.h b/indra/llcommon/llcursortypes.h
index 35dbeaf16e63ee9aa49117a273c45b38f88ecc7d..a1b8178bfe65365b4ca81e8881814be50f4b8f49 100644
--- a/indra/llcommon/llcursortypes.h
+++ b/indra/llcommon/llcursortypes.h
@@ -71,6 +71,6 @@ enum ECursorType {
 	UI_CURSOR_COUNT			// Number of elements in this enum (NOT a cursor)
 };
 
-ECursorType getCursorFromString(const std::string& cursor_string);
+LL_COMMON_API ECursorType getCursorFromString(const std::string& cursor_string);
 
 #endif // LL_LLCURSORTYPES_H
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 40b5f782d6bf7623a72bf1619f3c52967ff74f39..f8b2f2f163e825e1858bbdc52cd14c7ff8df3d67 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -46,7 +46,7 @@
  *
  * The date class represents a point in time after epoch - 1970-01-01.
  */
-class LLDate
+class LL_COMMON_API LLDate
 {
 public:
 	/** 
@@ -156,10 +156,10 @@ class LLDate
 };
 
 // Helper function to stream out a date
-std::ostream& operator<<(std::ostream& s, const LLDate& date);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLDate& date);
 
 // Helper function to stream in a date
-std::istream& operator>>(std::istream& s, LLDate& date);
+LL_COMMON_API std::istream& operator>>(std::istream& s, LLDate& date);
 
 
 
diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h
index 82f53c6e170f1126138df55a6e95ab70a57f3dfa..e6229db834a5f6aee83051f16641245bdd68722d 100644
--- a/indra/llcommon/lldependencies.h
+++ b/indra/llcommon/lldependencies.h
@@ -81,7 +81,7 @@ struct instance_from_range: public TYPE
  * LLDependencies components that should not be reinstantiated for each KEY,
  * NODE specialization
  */
-class LLDependenciesBase
+class LL_COMMON_API LLDependenciesBase
 {
 public:
     virtual ~LLDependenciesBase() {}
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 37e922d4b7131c2362dd2236c930de00b3c6ddc4..5a4c64485943cb139dc012b899cdbdf1127c12e9 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -131,7 +131,7 @@ namespace LLError
 	
 	class CallSite;
 	
-	class Log
+	class LL_COMMON_API Log
 	{
 	public:
 		static bool shouldLog(CallSite&);
@@ -140,7 +140,7 @@ namespace LLError
 		static void flush(std::ostringstream*, const CallSite&);
 	};
 	
-	class CallSite
+	class LL_COMMON_API CallSite
 	{
 		// Represents a specific place in the code where a message is logged
 		// This is public because it is used by the macros below.  It is not
@@ -189,7 +189,7 @@ namespace LLError
 	//LLCallStacks is designed not to be thread-safe.
    //so try not to use it in multiple parallel threads at same time.
    //Used in a single thread at a time is fine.
-   class LLCallStacks
+   class LL_COMMON_API LLCallStacks
    {
    private:
        static char**  sBuffer ;
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index fab0a1ef9f4466572425ab7476af4deffa9c1ec5..233e9d33892998a89091fed99f3c4d6c9cc9f945 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -63,12 +63,12 @@ class LLLineBuffer
 
 namespace LLError
 {
-	void initForServer(const std::string& identity);
+	LL_COMMON_API void initForServer(const std::string& identity);
 		// resets all logging settings to defaults needed by server processes
 		// logs to stderr, syslog, and windows debug log
 		// the identity string is used for in the syslog
 
-	void initForApplication(const std::string& dir);
+	LL_COMMON_API void initForApplication(const std::string& dir);
 		// resets all logging settings to defaults needed by applicaitons
 		// logs to stderr and windows debug log
 		// sets up log configuration from the file logcontrol.xml in dir
@@ -79,14 +79,14 @@ namespace LLError
 		Setting a level means log messages at that level or above.
 	*/
 	
-	void setPrintLocation(bool);
-	void setDefaultLevel(LLError::ELevel);
-	void setFunctionLevel(const std::string& function_name, LLError::ELevel);
-	void setClassLevel(const std::string& class_name, LLError::ELevel);
-	void setFileLevel(const std::string& file_name, LLError::ELevel);
-	void setTagLevel(const std::string& file_name, LLError::ELevel);
+	LL_COMMON_API void setPrintLocation(bool);
+	LL_COMMON_API void setDefaultLevel(LLError::ELevel);
+	LL_COMMON_API void setFunctionLevel(const std::string& function_name, LLError::ELevel);
+	LL_COMMON_API void setClassLevel(const std::string& class_name, LLError::ELevel);
+	LL_COMMON_API void setFileLevel(const std::string& file_name, LLError::ELevel);
+	LL_COMMON_API void setTagLevel(const std::string& file_name, LLError::ELevel);
 	
-	void configure(const LLSD&);
+	LL_COMMON_API void configure(const LLSD&);
 		// the LLSD can configure all of the settings
 		// usually read automatically from the live errorlog.xml file
 
@@ -96,21 +96,21 @@ namespace LLError
 	*/
 
 	typedef boost::function<void(const std::string&)> FatalFunction;
-	void crashAndLoop(const std::string& message);
+	LL_COMMON_API void crashAndLoop(const std::string& message);
 		// Default fatal function: access null pointer and loops forever
 
-	void setFatalFunction(const FatalFunction&);
+	LL_COMMON_API void setFatalFunction(const FatalFunction&);
 		// The fatal function will be called when an message of LEVEL_ERROR
 		// is logged.  Note: supressing a LEVEL_ERROR message from being logged
 		// (by, for example, setting a class level to LEVEL_NONE), will keep
 		// the that message from causing the fatal funciton to be invoked.
 
-    FatalFunction getFatalFunction();
+    LL_COMMON_API FatalFunction getFatalFunction();
         // Retrieve the previously-set FatalFunction
 
     /// temporarily override the FatalFunction for the duration of a
     /// particular scope, e.g. for unit tests
-    class OverrideFatalFunction
+    class LL_COMMON_API OverrideFatalFunction
     {
     public:
         OverrideFatalFunction(const FatalFunction& func):
@@ -128,15 +128,15 @@ namespace LLError
     };
 
 	typedef std::string (*TimeFunction)();
-	std::string utcTime();
+	LL_COMMON_API std::string utcTime();
 	
-	void setTimeFunction(TimeFunction);
+	LL_COMMON_API void setTimeFunction(TimeFunction);
 		// The function is use to return the current time, formatted for
 		// display by those error recorders that want the time included.
 
 
 
-	class Recorder
+	class LL_COMMON_API Recorder
 	{
 		// An object that handles the actual output or error messages.
 	public:
@@ -150,17 +150,17 @@ namespace LLError
 			// included in the text of the message
 	};
 	
-	void addRecorder(Recorder*);
-	void removeRecorder(Recorder*);
+	LL_COMMON_API void addRecorder(Recorder*);
+	LL_COMMON_API void removeRecorder(Recorder*);
 		// each error message is passed to each recorder via recordMessage()
 	
-	void logToFile(const std::string& filename);
-	void logToFixedBuffer(LLLineBuffer*);
+	LL_COMMON_API void logToFile(const std::string& filename);
+	LL_COMMON_API void logToFixedBuffer(LLLineBuffer*);
 		// Utilities to add recorders for logging to a file or a fixed buffer
 		// A second call to the same function will remove the logger added
 		// with the first.
 		// Passing the empty string or NULL to just removes any prior.
-	std::string logFileName();
+	LL_COMMON_API std::string logFileName();
 		// returns name of current logging file, empty string if none
 
 
@@ -169,11 +169,11 @@ namespace LLError
 	*/
 
 	class Settings;
-	Settings* saveAndResetSettings();
-	void restoreSettings(Settings *);
+	LL_COMMON_API Settings* saveAndResetSettings();
+	LL_COMMON_API void restoreSettings(Settings *);
 		
-	std::string abbreviateFile(const std::string& filePath);
-	int shouldLogCallCount();
+	LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
+	LL_COMMON_API int shouldLogCallCount();
 	
 };
 
diff --git a/indra/llcommon/llerrorthread.h b/indra/llcommon/llerrorthread.h
index f1d6ffc34f5f05293861b0686939df9a613de359..3121d29675484ff079d536bda871ee1586157561 100644
--- a/indra/llcommon/llerrorthread.h
+++ b/indra/llcommon/llerrorthread.h
@@ -35,7 +35,7 @@
 
 #include "llthread.h"
 
-class LLErrorThread : public LLThread
+class LL_COMMON_API LLErrorThread : public LLThread
 {
 public:
 	LLErrorThread();
diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h
index 2cc8577219da76fe1e28ef9ef096782410d70f08..0ea7cf4ae83a1a3f07c3be770a8cbf2fda282bb3 100644
--- a/indra/llcommon/llevent.h
+++ b/indra/llcommon/llevent.h
@@ -47,7 +47,7 @@ class LLEventDispatcher;
 class LLObservable;
 
 // Abstract event. All events derive from LLEvent
-class LLEvent : public LLThreadSafeRefCount
+class LL_COMMON_API LLEvent : public LLThreadSafeRefCount
 {
 protected:
 	virtual ~LLEvent();
@@ -75,7 +75,7 @@ class LLEvent : public LLThreadSafeRefCount
 };
 
 // Abstract listener. All listeners derive from LLEventListener
-class LLEventListener : public LLThreadSafeRefCount
+class LL_COMMON_API LLEventListener : public LLThreadSafeRefCount
 {
 protected:
 	virtual ~LLEventListener();
@@ -92,7 +92,7 @@ class LLEventListener : public LLThreadSafeRefCount
 };
 
 // A listener which tracks references to it and cleans up when it's deallocated
-class LLSimpleListener : public LLEventListener
+class LL_COMMON_API LLSimpleListener : public LLEventListener
 {
 public:
 	void clearDispatchers();
@@ -117,7 +117,7 @@ struct LLListenerEntry
 // Base class for a dispatcher - an object which listens
 // to events being fired and relays them to their
 // appropriate destinations.
-class LLEventDispatcher : public LLThreadSafeRefCount
+class LL_COMMON_API LLEventDispatcher : public LLThreadSafeRefCount
 {
 protected:
 	virtual ~LLEventDispatcher();
@@ -160,7 +160,7 @@ class LLEventDispatcher : public LLThreadSafeRefCount
 // In order for this class to work properly, it needs
 // an instance of an LLEventDispatcher to route events to their
 // listeners.
-class LLObservable
+class LL_COMMON_API LLObservable
 {
 public:
 	// Initialize with the default Dispatcher
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d598f1cc4a80a2b7e95f1c17344c2a188e9abafd
--- /dev/null
+++ b/indra/llcommon/lleventcoro.cpp
@@ -0,0 +1,129 @@
+/**
+ * @file   lleventcoro.cpp
+ * @author Nat Goodspeed
+ * @date   2009-04-29
+ * @brief  Implementation for lleventcoro.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lleventcoro.h"
+// STL headers
+#include <map>
+// std headers
+// external library headers
+// other Linden headers
+#include "llsdserialize.h"
+#include "llerror.h"
+#include "llcoros.h"
+
+std::string LLEventDetail::listenerNameForCoroImpl(const void* self_id)
+{
+    // First, if this coroutine was launched by LLCoros::launch(), find that name.
+    std::string name(LLCoros::instance().getNameByID(self_id));
+    if (! name.empty())
+    {
+        return name;
+    }
+    // Apparently this coroutine wasn't launched by LLCoros::launch(). Check
+    // whether we have a memo for this self_id.
+    typedef std::map<const void*, std::string> MapType;
+    static MapType memo;
+    MapType::const_iterator found = memo.find(self_id);
+    if (found != memo.end())
+    {
+        // this coroutine instance has called us before, reuse same name
+        return found->second;
+    }
+    // this is the first time we've been called for this coroutine instance
+    name = LLEventPump::inventName("coro");
+    memo[self_id] = name;
+    LL_INFOS("LLEventCoro") << "listenerNameForCoroImpl(" << self_id << "): inventing coro name '"
+                            << name << "'" << LL_ENDL;
+    return name;
+}
+
+void LLEventDetail::storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value)
+{
+    if (rawPath.isUndefined())
+    {
+        // no-op case
+        return;
+    }
+
+    // Arrange to treat rawPath uniformly as an array. If it's not already an
+    // array, store it as the only entry in one.
+    LLSD path;
+    if (rawPath.isArray())
+    {
+        path = rawPath;
+    }
+    else
+    {
+        path.append(rawPath);
+    }
+
+    // Need to indicate a current destination -- but that current destination
+    // needs to change as we step through the path array. Where normally we'd
+    // use an LLSD& to capture a subscripted LLSD lvalue, this time we must
+    // instead use a pointer -- since it must be reassigned.
+    LLSD* pdest = &dest;
+
+    // Now loop through that array
+    for (LLSD::Integer i = 0; i < path.size(); ++i)
+    {
+        if (path[i].isString())
+        {
+            // *pdest is an LLSD map
+            pdest = &((*pdest)[path[i].asString()]);
+        }
+        else if (path[i].isInteger())
+        {
+            // *pdest is an LLSD array
+            pdest = &((*pdest)[path[i].asInteger()]);
+        }
+        else
+        {
+            // What do we do with Real or Array or Map or ...?
+            // As it's a coder error -- not a user error -- rub the coder's
+            // face in it so it gets fixed.
+            LL_ERRS("lleventcoro") << "storeToLLSDPath(" << dest << ", " << rawPath << ", " << value
+                                   << "): path[" << i << "] bad type " << path[i].type() << LL_ENDL;
+        }
+    }
+
+    // Here *pdest is where we should store value.
+    *pdest = value;
+}
+
+LLSD errorException(const LLEventWithID& result, const std::string& desc)
+{
+    // If the result arrived on the error pump (pump 1), instead of
+    // returning it, deliver it via exception.
+    if (result.second)
+    {
+        throw LLErrorEvent(desc, result.first);
+    }
+    // That way, our caller knows a simple return must be from the reply
+    // pump (pump 0).
+    return result.first;
+}
+
+LLSD errorLog(const LLEventWithID& result, const std::string& desc)
+{
+    // If the result arrived on the error pump (pump 1), log it as a fatal
+    // error.
+    if (result.second)
+    {
+        LL_ERRS("errorLog") << desc << ":" << std::endl;
+        LLSDSerialize::toPrettyXML(result.first, LL_CONT);
+        LL_CONT << LL_ENDL;
+    }
+    // A simple return must therefore be from the reply pump (pump 0).
+    return result.first;
+}
diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h
new file mode 100644
index 0000000000000000000000000000000000000000..c6d9de171d29f0f5a185bb60c1f48ab407867dd1
--- /dev/null
+++ b/indra/llcommon/lleventcoro.h
@@ -0,0 +1,549 @@
+/**
+ * @file   lleventcoro.h
+ * @author Nat Goodspeed
+ * @date   2009-04-29
+ * @brief  Utilities to interface between coroutines and events.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEVENTCORO_H)
+#define LL_LLEVENTCORO_H
+
+#include <boost/coroutine/coroutine.hpp>
+#include <boost/coroutine/future.hpp>
+#include <boost/optional.hpp>
+#include <string>
+#include <stdexcept>
+#include "llevents.h"
+#include "llerror.h"
+
+/**
+ * Like LLListenerOrPumpName, this is a class intended for parameter lists:
+ * accept a <tt>const LLEventPumpOrPumpName&</tt> and you can accept either an
+ * <tt>LLEventPump&</tt> or its string name. For a single parameter that could
+ * be either, it's not hard to overload the function -- but as soon as you
+ * want to accept two such parameters, this is cheaper than four overloads.
+ */
+class LLEventPumpOrPumpName
+{
+public:
+    /// Pass an actual LLEventPump&
+    LLEventPumpOrPumpName(LLEventPump& pump):
+        mPump(pump)
+    {}
+    /// Pass the string name of an LLEventPump
+    LLEventPumpOrPumpName(const std::string& pumpname):
+        mPump(LLEventPumps::instance().obtain(pumpname))
+    {}
+    /// Pass string constant name of an LLEventPump. This override must be
+    /// explicit, since otherwise passing <tt>const char*</tt> to a function
+    /// accepting <tt>const LLEventPumpOrPumpName&</tt> would require two
+    /// different implicit conversions: <tt>const char*</tt> -> <tt>const
+    /// std::string&</tt> -> <tt>const LLEventPumpOrPumpName&</tt>.
+    LLEventPumpOrPumpName(const char* pumpname):
+        mPump(LLEventPumps::instance().obtain(pumpname))
+    {}
+    /// Unspecified: "I choose not to identify an LLEventPump."
+    LLEventPumpOrPumpName() {}
+    operator LLEventPump& () const { return *mPump; }
+    LLEventPump& getPump() const { return *mPump; }
+    operator bool() const { return mPump; }
+    bool operator!() const { return ! mPump; }
+
+private:
+    boost::optional<LLEventPump&> mPump;
+};
+
+/// This is an adapter for a signature like void LISTENER(const LLSD&), which
+/// isn't a valid LLEventPump listener: such listeners should return bool.
+template <typename LISTENER>
+class LLVoidListener
+{
+public:
+    LLVoidListener(const LISTENER& listener):
+        mListener(listener)
+    {}
+    bool operator()(const LLSD& event)
+    {
+        mListener(event);
+        // don't swallow the event, let other listeners see it
+        return false;
+    }
+private:
+    LISTENER mListener;
+};
+
+/// LLVoidListener helper function to infer the type of the LISTENER
+template <typename LISTENER>
+LLVoidListener<LISTENER> voidlistener(const LISTENER& listener)
+{
+    return LLVoidListener<LISTENER>(listener);
+}
+
+namespace LLEventDetail
+{
+    /**
+     * waitForEventOn() permits a coroutine to temporarily listen on an
+     * LLEventPump any number of times. We don't really want to have to ask
+     * the caller to label each such call with a distinct string; the whole
+     * point of waitForEventOn() is to present a nice sequential interface to
+     * the underlying LLEventPump-with-named-listeners machinery. So we'll use
+     * LLEventPump::inventName() to generate a distinct name for each
+     * temporary listener. On the other hand, because a given coroutine might
+     * call waitForEventOn() any number of times, we don't really want to
+     * consume an arbitrary number of generated inventName()s: that namespace,
+     * though large, is nonetheless finite. So we memoize an invented name for
+     * each distinct coroutine instance (each different 'self' object). We
+     * can't know the type of 'self', because it depends on the coroutine
+     * body's signature. So we cast its address to void*, looking for distinct
+     * pointer values. Yes, that means that an early coroutine could cache a
+     * value here, then be destroyed, only to be supplanted by a later
+     * coroutine (of the same or different type), and we'll end up
+     * "recognizing" the second one and reusing the listener name -- but
+     * that's okay, since it won't collide with any listener name used by the
+     * earlier coroutine since that earlier coroutine no longer exists.
+     */
+    template <typename COROUTINE_SELF>
+    std::string listenerNameForCoro(COROUTINE_SELF& self)
+    {
+        return listenerNameForCoroImpl(self.get_id());
+    }
+
+    /// Implementation for listenerNameForCoro()
+    LL_COMMON_API std::string listenerNameForCoroImpl(const void* self_id);
+
+    /**
+     * Implement behavior described for postAndWait()'s @a replyPumpNamePath
+     * parameter:
+     *
+     * * If <tt>path.isUndefined()</tt>, do nothing.
+     * * If <tt>path.isString()</tt>, @a dest is an LLSD map: store @a value
+     *   into <tt>dest[path.asString()]</tt>.
+     * * If <tt>path.isInteger()</tt>, @a dest is an LLSD array: store @a
+     *   value into <tt>dest[path.asInteger()]</tt>.
+     * * If <tt>path.isArray()</tt>, iteratively apply the rules above to step
+     *   down through the structure of @a dest. The last array entry in @a
+     *   path specifies the entry in the lowest-level structure in @a dest
+     *   into which to store @a value.
+     *
+     * @note
+     * In the degenerate case in which @a path is an empty array, @a dest will
+     * @em become @a value rather than @em containing it.
+     */
+    LL_COMMON_API void storeToLLSDPath(LLSD& dest, const LLSD& path, const LLSD& value);
+} // namespace LLEventDetail
+
+/**
+ * Post specified LLSD event on the specified LLEventPump, then wait for a
+ * response on specified other LLEventPump. This is more than mere
+ * convenience: the difference between this function and the sequence
+ * @code
+ * requestPump.post(myEvent);
+ * LLSD reply = waitForEventOn(self, replyPump);
+ * @endcode
+ * is that the sequence above fails if the reply is posted immediately on
+ * @a replyPump, that is, before <tt>requestPump.post()</tt> returns. In the
+ * sequence above, the running coroutine isn't even listening on @a replyPump
+ * until <tt>requestPump.post()</tt> returns and @c waitForEventOn() is
+ * entered. Therefore, the coroutine completely misses an immediate reply
+ * event, making it wait indefinitely.
+ *
+ * By contrast, postAndWait() listens on the @a replyPump @em before posting
+ * the specified LLSD event on the specified @a requestPump.
+ *
+ * @param self The @c self object passed into a coroutine
+ * @param event LLSD data to be posted on @a requestPump
+ * @param requestPump an LLEventPump on which to post @a event. Pass either
+ * the LLEventPump& or its string name. However, if you pass a
+ * default-constructed @c LLEventPumpOrPumpName, we skip the post() call.
+ * @param replyPump an LLEventPump on which postAndWait() will listen for a
+ * reply. Pass either the LLEventPump& or its string name. The calling
+ * coroutine will wait until that reply arrives. (If you're concerned about a
+ * reply that might not arrive, please see also LLEventTimeout.)
+ * @param replyPumpNamePath specifies the location within @a event in which to
+ * store <tt>replyPump.getName()</tt>. This is a strictly optional convenience
+ * feature; obviously you can store the name in @a event "by hand" if desired.
+ * @a replyPumpNamePath can be specified in any of four forms:
+ * * @c isUndefined() (default-constructed LLSD object): do nothing. This is
+ *   the default behavior if you omit @a replyPumpNamePath.
+ * * @c isInteger(): @a event is an array. Store <tt>replyPump.getName()</tt>
+ *   in <tt>event[replyPumpNamePath.asInteger()]</tt>.
+ * * @c isString(): @a event is a map. Store <tt>replyPump.getName()</tt> in
+ *   <tt>event[replyPumpNamePath.asString()]</tt>.
+ * * @c isArray(): @a event has several levels of structure, e.g. map of
+ *   maps, array of arrays, array of maps, map of arrays, ... Store
+ *   <tt>replyPump.getName()</tt> in
+ *   <tt>event[replyPumpNamePath[0]][replyPumpNamePath[1]]...</tt> In other
+ *   words, examine each array entry in @a replyPumpNamePath in turn. If it's an
+ *   <tt>LLSD::String</tt>, the current level of @a event is a map; step down to
+ *   that map entry. If it's an <tt>LLSD::Integer</tt>, the current level of @a
+ *   event is an array; step down to that array entry. The last array entry in
+ *   @a replyPumpNamePath specifies the entry in the lowest-level structure in
+ *   @a event into which to store <tt>replyPump.getName()</tt>.
+ */
+template <typename SELF>
+LLSD postAndWait(SELF& self, const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+                 const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath=LLSD())
+{
+    // declare the future
+    boost::coroutines::future<LLSD> future(self);
+    // make a callback that will assign a value to the future, and listen on
+    // the specified LLEventPump with that callback
+    std::string listenerName(LLEventDetail::listenerNameForCoro(self));
+    LLTempBoundListener connection(
+        replyPump.getPump().listen(listenerName,
+                                   voidlistener(boost::coroutines::make_callback(future))));
+    // skip the "post" part if requestPump is default-constructed
+    if (requestPump)
+    {
+        // If replyPumpNamePath is non-empty, store the replyPump name in the
+        // request event.
+        LLSD modevent(event);
+        LLEventDetail::storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName());
+        LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
+                                 << " posting to " << requestPump.getPump().getName()
+                                 << ": " << modevent << LL_ENDL;
+        requestPump.getPump().post(modevent);
+    }
+    LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
+                             << " about to wait on LLEventPump " << replyPump.getPump().getName()
+                             << LL_ENDL;
+    // trying to dereference ("resolve") the future makes us wait for it
+    LLSD value(*future);
+    LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
+                             << " resuming with " << value << LL_ENDL;
+    // returning should disconnect the connection
+    return value;
+}
+
+/// Wait for the next event on the specified LLEventPump. Pass either the
+/// LLEventPump& or its string name.
+template <typename SELF>
+LLSD waitForEventOn(SELF& self, const LLEventPumpOrPumpName& pump)
+{
+    // This is now a convenience wrapper for postAndWait().
+    return postAndWait(self, LLSD(), LLEventPumpOrPumpName(), pump);
+}
+
+/// return type for two-pump variant of waitForEventOn()
+typedef std::pair<LLSD, int> LLEventWithID;
+
+namespace LLEventDetail
+{
+    /**
+     * This helper is specifically for the two-pump version of waitForEventOn().
+     * We use a single future object, but we want to listen on two pumps with it.
+     * Since we must still adapt from (the callable constructed by)
+     * boost::coroutines::make_callback() (void return) to provide an event
+     * listener (bool return), we've adapted LLVoidListener for the purpose. The
+     * basic idea is that we construct a distinct instance of WaitForEventOnHelper
+     * -- binding different instance data -- for each of the pumps. Then, when a
+     * pump delivers an LLSD value to either WaitForEventOnHelper, it can combine
+     * that LLSD with its discriminator to feed the future object.
+     */
+    template <typename LISTENER>
+    class WaitForEventOnHelper
+    {
+    public:
+        WaitForEventOnHelper(const LISTENER& listener, int discriminator):
+            mListener(listener),
+            mDiscrim(discriminator)
+        {}
+        // this signature is required for an LLEventPump listener
+        bool operator()(const LLSD& event)
+        {
+            // our future object is defined to accept LLEventWithID
+            mListener(LLEventWithID(event, mDiscrim));
+            // don't swallow the event, let other listeners see it
+            return false;
+        }
+    private:
+        LISTENER mListener;
+        const int mDiscrim;
+    };
+
+    /// WaitForEventOnHelper type-inference helper
+    template <typename LISTENER>
+    WaitForEventOnHelper<LISTENER> wfeoh(const LISTENER& listener, int discriminator)
+    {
+        return WaitForEventOnHelper<LISTENER>(listener, discriminator);
+    }
+} // namespace LLEventDetail
+
+/**
+ * This function waits for a reply on either of two specified LLEventPumps.
+ * Otherwise, it closely resembles postAndWait(); please see the documentation
+ * for that function for detailed parameter info.
+ *
+ * While we could have implemented the single-pump variant in terms of this
+ * one, there's enough added complexity here to make it worthwhile to give the
+ * single-pump variant its own straightforward implementation. Conversely,
+ * though we could use preprocessor logic to generate n-pump overloads up to
+ * BOOST_COROUTINE_WAIT_MAX, we don't foresee a use case. This two-pump
+ * overload exists because certain event APIs are defined in terms of a reply
+ * LLEventPump and an error LLEventPump.
+ *
+ * The LLEventWithID return value provides not only the received event, but
+ * the index of the pump on which it arrived (0 or 1).
+ *
+ * @note
+ * I'd have preferred to overload the name postAndWait() for both signatures.
+ * But consider the following ambiguous call:
+ * @code
+ * postAndWait(self, LLSD(), requestPump, replyPump, "someString");
+ * @endcode
+ * "someString" could be converted to either LLSD (@a replyPumpNamePath for
+ * the single-pump function) or LLEventOrPumpName (@a replyPump1 for two-pump
+ * function).
+ *
+ * It seems less burdensome to write postAndWait2() than to write either
+ * LLSD("someString") or LLEventOrPumpName("someString").
+ */
+template <typename SELF>
+LLEventWithID postAndWait2(SELF& self, const LLSD& event,
+                           const LLEventPumpOrPumpName& requestPump,
+                           const LLEventPumpOrPumpName& replyPump0,
+                           const LLEventPumpOrPumpName& replyPump1,
+                           const LLSD& replyPump0NamePath=LLSD(),
+                           const LLSD& replyPump1NamePath=LLSD())
+{
+    // declare the future
+    boost::coroutines::future<LLEventWithID> future(self);
+    // either callback will assign a value to this future; listen on
+    // each specified LLEventPump with a callback
+    std::string name(LLEventDetail::listenerNameForCoro(self));
+    LLTempBoundListener connection0(
+        replyPump0.getPump().listen(name + "a",
+                               LLEventDetail::wfeoh(boost::coroutines::make_callback(future), 0)));
+    LLTempBoundListener connection1(
+        replyPump1.getPump().listen(name + "b",
+                               LLEventDetail::wfeoh(boost::coroutines::make_callback(future), 1)));
+    // skip the "post" part if requestPump is default-constructed
+    if (requestPump)
+    {
+        // If either replyPumpNamePath is non-empty, store the corresponding
+        // replyPump name in the request event.
+        LLSD modevent(event);
+        LLEventDetail::storeToLLSDPath(modevent, replyPump0NamePath,
+                                       replyPump0.getPump().getName());
+        LLEventDetail::storeToLLSDPath(modevent, replyPump1NamePath,
+                                       replyPump1.getPump().getName());
+        LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name
+                                 << " posting to " << requestPump.getPump().getName()
+                                 << ": " << modevent << LL_ENDL;
+        requestPump.getPump().post(modevent);
+    }
+    LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name
+                             << " about to wait on LLEventPumps " << replyPump0.getPump().getName()
+                             << ", " << replyPump1.getPump().getName() << LL_ENDL;
+    // trying to dereference ("resolve") the future makes us wait for it
+    LLEventWithID value(*future);
+    LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << name
+                             << " resuming with (" << value.first << ", " << value.second << ")"
+                             << LL_ENDL;
+    // returning should disconnect both connections
+    return value;
+}
+
+/**
+ * Wait for the next event on either of two specified LLEventPumps.
+ */
+template <typename SELF>
+LLEventWithID
+waitForEventOn(SELF& self,
+               const LLEventPumpOrPumpName& pump0, const LLEventPumpOrPumpName& pump1)
+{
+    // This is now a convenience wrapper for postAndWait2().
+    return postAndWait2(self, LLSD(), LLEventPumpOrPumpName(), pump0, pump1);
+}
+
+/**
+ * Helper for the two-pump variant of waitForEventOn(), e.g.:
+ *
+ * @code
+ * LLSD reply = errorException(waitForEventOn(self, replyPump, errorPump),
+ *                             "error response from login.cgi");
+ * @endcode
+ *
+ * Examines an LLEventWithID, assuming that the second pump (pump 1) is
+ * listening for an error indication. If the incoming data arrived on pump 1,
+ * throw an LLErrorEvent exception. If the incoming data arrived on pump 0,
+ * just return it. Since a normal return can only be from pump 0, we no longer
+ * need the LLEventWithID's discriminator int; we can just return the LLSD.
+ *
+ * @note I'm not worried about introducing the (fairly generic) name
+ * errorException() into global namespace, because how many other overloads of
+ * the same name are going to accept an LLEventWithID parameter?
+ */
+LLSD errorException(const LLEventWithID& result, const std::string& desc);
+
+/**
+ * Exception thrown by errorException(). We don't call this LLEventError
+ * because it's not an error in event processing: rather, this exception
+ * announces an event that bears error information (for some other API).
+ */
+class LL_COMMON_API LLErrorEvent: public std::runtime_error
+{
+public:
+    LLErrorEvent(const std::string& what, const LLSD& data):
+        std::runtime_error(what),
+        mData(data)
+    {}
+    virtual ~LLErrorEvent() throw() {}
+
+    LLSD getData() const { return mData; }
+
+private:
+    LLSD mData;
+};
+
+/**
+ * Like errorException(), save that this trips a fatal error using LL_ERRS
+ * rather than throwing an exception.
+ */
+LL_COMMON_API LLSD errorLog(const LLEventWithID& result, const std::string& desc);
+
+/**
+ * Certain event APIs require the name of an LLEventPump on which they should
+ * post results. While it works to invent a distinct name and let
+ * LLEventPumps::obtain() instantiate the LLEventPump as a "named singleton,"
+ * in a certain sense it's more robust to instantiate a local LLEventPump and
+ * provide its name instead. This class packages the following idiom:
+ *
+ * 1. Instantiate a local LLCoroEventPump, with an optional name prefix.
+ * 2. Provide its actual name to the event API in question as the name of the
+ *    reply LLEventPump.
+ * 3. Initiate the request to the event API.
+ * 4. Call your LLEventTempStream's wait() method to wait for the reply.
+ * 5. Let the LLCoroEventPump go out of scope.
+ */
+class LL_COMMON_API LLCoroEventPump
+{
+public:
+    LLCoroEventPump(const std::string& name="coro"):
+        mPump(name, true)           // allow tweaking the pump instance name
+    {}
+    /// It's typical to request the LLEventPump name to direct an event API to
+    /// send its response to this pump.
+    std::string getName() const { return mPump.getName(); }
+    /// Less typically, we'd request the pump itself for some reason.
+    LLEventPump& getPump() { return mPump; }
+
+    /**
+     * Wait for an event on this LLEventPump.
+     *
+     * @note
+     * The other major usage pattern we considered was to bind @c self at
+     * LLCoroEventPump construction time, which would avoid passing the
+     * parameter to each wait() call. But if we were going to bind @c self as
+     * a class member, we'd need to specify a class template parameter
+     * indicating its type. The big advantage of passing it to the wait() call
+     * is that the type can be implicit.
+     */
+    template <typename SELF>
+    LLSD wait(SELF& self)
+    {
+        return waitForEventOn(self, mPump);
+    }
+
+    template <typename SELF>
+    LLSD postAndWait(SELF& self, const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+                     const LLSD& replyPumpNamePath=LLSD())
+    {
+        return ::postAndWait(self, event, requestPump, mPump, replyPumpNamePath);
+    }
+
+private:
+    LLEventStream mPump;
+};
+
+/**
+ * Other event APIs require the names of two different LLEventPumps: one for
+ * success response, the other for error response. Extend LLCoroEventPump
+ * for the two-pump use case.
+ */
+class LL_COMMON_API LLCoroEventPumps
+{
+public:
+    LLCoroEventPumps(const std::string& name="coro",
+                     const std::string& suff0="Reply",
+                     const std::string& suff1="Error"):
+        mPump0(name + suff0, true),   // allow tweaking the pump instance name
+        mPump1(name + suff1, true)
+    {}
+    /// request pump 0's name
+    std::string getName0() const { return mPump0.getName(); }
+    /// request pump 1's name
+    std::string getName1() const { return mPump1.getName(); }
+    /// request both names
+    std::pair<std::string, std::string> getNames() const
+    {
+        return std::pair<std::string, std::string>(mPump0.getName(), mPump1.getName());
+    }
+
+    /// request pump 0
+    LLEventPump& getPump0() { return mPump0; }
+    /// request pump 1
+    LLEventPump& getPump1() { return mPump1; }
+
+    /// waitForEventOn(self, either of our two LLEventPumps)
+    template <typename SELF>
+    LLEventWithID wait(SELF& self)
+    {
+        return waitForEventOn(self, mPump0, mPump1);
+    }
+
+    /// errorException(wait(self))
+    template <typename SELF>
+    LLSD waitWithException(SELF& self)
+    {
+        return errorException(wait(self), std::string("Error event on ") + getName1());
+    }
+
+    /// errorLog(wait(self))
+    template <typename SELF>
+    LLSD waitWithLog(SELF& self)
+    {
+        return errorLog(wait(self), std::string("Error event on ") + getName1());
+    }
+
+    template <typename SELF>
+    LLEventWithID postAndWait(SELF& self, const LLSD& event,
+                              const LLEventPumpOrPumpName& requestPump,
+                              const LLSD& replyPump0NamePath=LLSD(),
+                              const LLSD& replyPump1NamePath=LLSD())
+    {
+        return postAndWait2(self, event, requestPump, mPump0, mPump1,
+                            replyPump0NamePath, replyPump1NamePath);
+    }
+
+    template <typename SELF>
+    LLSD postAndWaitWithException(SELF& self, const LLSD& event,
+                                  const LLEventPumpOrPumpName& requestPump,
+                                  const LLSD& replyPump0NamePath=LLSD(),
+                                  const LLSD& replyPump1NamePath=LLSD())
+    {
+        return errorException(postAndWait(self, event, requestPump,
+                                          replyPump0NamePath, replyPump1NamePath),
+                              std::string("Error event on ") + getName1());
+    }
+
+    template <typename SELF>
+    LLSD postAndWaitWithLog(SELF& self, const LLSD& event,
+                            const LLEventPumpOrPumpName& requestPump,
+                            const LLSD& replyPump0NamePath=LLSD(),
+                            const LLSD& replyPump1NamePath=LLSD())
+    {
+        return errorLog(postAndWait(self, event, requestPump,
+                                    replyPump0NamePath, replyPump1NamePath),
+                        std::string("Error event on ") + getName1());
+    }
+
+private:
+    LLEventStream mPump0, mPump1;
+};
+
+#endif /* ! defined(LL_LLEVENTCORO_H) */
diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6b1413d05494851ca76373a91ed5f3569e93df1b
--- /dev/null
+++ b/indra/llcommon/lleventdispatcher.cpp
@@ -0,0 +1,133 @@
+/**
+ * @file   lleventdispatcher.cpp
+ * @author Nat Goodspeed
+ * @date   2009-06-18
+ * @brief  Implementation for lleventdispatcher.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lleventdispatcher.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llevents.h"
+#include "llerror.h"
+#include "llsdutil.h"
+
+LLEventDispatcher::LLEventDispatcher(const std::string& desc, const std::string& key):
+    mDesc(desc),
+    mKey(key)
+{
+}
+
+LLEventDispatcher::~LLEventDispatcher()
+{
+}
+
+/// Register a callable by name
+void LLEventDispatcher::add(const std::string& name, const Callable& callable, const LLSD& required)
+{
+    mDispatch[name] = DispatchMap::mapped_type(callable, required);
+}
+
+void LLEventDispatcher::addFail(const std::string& name, const std::string& classname) const
+{
+    LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << ")::add(" << name
+                                 << "): " << classname << " is not a subclass "
+                                 << "of LLEventDispatcher" << LL_ENDL;
+}
+
+/// Unregister a callable
+bool LLEventDispatcher::remove(const std::string& name)
+{
+    DispatchMap::iterator found = mDispatch.find(name);
+    if (found == mDispatch.end())
+    {
+        return false;
+    }
+    mDispatch.erase(found);
+    return true;
+}
+
+/// Call a registered callable with an explicitly-specified name. If no
+/// such callable exists, die with LL_ERRS.
+void LLEventDispatcher::operator()(const std::string& name, const LLSD& event) const
+{
+    if (! attemptCall(name, event))
+    {
+        LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << "): '" << name
+                                     << "' not found" << LL_ENDL;
+    }
+}
+
+/// Extract the @a key value from the incoming @a event, and call the
+/// callable whose name is specified by that map @a key. If no such
+/// callable exists, die with LL_ERRS.
+void LLEventDispatcher::operator()(const LLSD& event) const
+{
+    // This could/should be implemented in terms of the two-arg overload.
+    // However -- we can produce a more informative error message.
+    std::string name(event[mKey]);
+    if (! attemptCall(name, event))
+    {
+        LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << "): bad " << mKey
+                                     << " value '" << name << "'" << LL_ENDL;
+    }
+}
+
+bool LLEventDispatcher::attemptCall(const std::string& name, const LLSD& event) const
+{
+    DispatchMap::const_iterator found = mDispatch.find(name);
+    if (found == mDispatch.end())
+    {
+        // The reason we only return false, leaving it up to our caller to die
+        // with LL_ERRS, is that different callers have different amounts of
+        // available information.
+        return false;
+    }
+    // Found the name, so it's plausible to even attempt the call. But first,
+    // validate the syntax of the event itself.
+    std::string mismatch(llsd_matches(found->second.second, event));
+    if (! mismatch.empty())
+    {
+        LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << ") calling '" << name
+                                     << "': bad request: " << mismatch << LL_ENDL;
+    }
+    // Event syntax looks good, go for it!
+    (found->second.first)(event);
+    return true;                    // tell caller we were able to call
+}
+
+LLEventDispatcher::Callable LLEventDispatcher::get(const std::string& name) const
+{
+    DispatchMap::const_iterator found = mDispatch.find(name);
+    if (found == mDispatch.end())
+    {
+        return Callable();
+    }
+    return found->second.first;
+}
+
+LLDispatchListener::LLDispatchListener(const std::string& pumpname, const std::string& key):
+    LLEventDispatcher(pumpname, key),
+    mPump(pumpname, true),          // allow tweaking for uniqueness
+    mBoundListener(mPump.listen("self", boost::bind(&LLDispatchListener::process, this, _1)))
+{
+}
+
+bool LLDispatchListener::process(const LLSD& event)
+{
+    (*this)(event);
+    return false;
+}
diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..671f2a4d1cf19944a659d9d3e21704db4485db63
--- /dev/null
+++ b/indra/llcommon/lleventdispatcher.h
@@ -0,0 +1,130 @@
+/**
+ * @file   lleventdispatcher.h
+ * @author Nat Goodspeed
+ * @date   2009-06-18
+ * @brief  Central mechanism for dispatching events by string name. This is
+ *         useful when you have a single LLEventPump listener on which you can
+ *         request different operations, vs. instantiating a different
+ *         LLEventPump for each such operation.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEVENTDISPATCHER_H)
+#define LL_LLEVENTDISPATCHER_H
+
+#include <string>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <typeinfo>
+#include "llevents.h"
+
+class LLSD;
+
+/**
+ * Given an LLSD map, examine a string-valued key and call a corresponding
+ * callable. This class is designed to be contained by an LLEventPump
+ * listener class that will register some of its own methods, though any
+ * callable can be used.
+ */
+class LL_COMMON_API LLEventDispatcher
+{
+public:
+    LLEventDispatcher(const std::string& desc, const std::string& key);
+    virtual ~LLEventDispatcher();
+
+    /// Accept any C++ callable, typically a boost::bind() expression
+    typedef boost::function<void(const LLSD&)> Callable;
+
+    /**
+     * Register a @a callable by @a name. The optional @a required parameter
+     * is used to validate the structure of each incoming event (see
+     * llsd_matches()).
+     */
+    void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD());
+
+    /**
+     * Special case: a subclass of this class can pass an unbound member
+     * function pointer without explicitly specifying the
+     * <tt>boost::bind()</tt> expression.
+     */
+    template <class CLASS>
+    void add(const std::string& name, void (CLASS::*method)(const LLSD&),
+             const LLSD& required=LLSD())
+    {
+        addMethod<CLASS>(name, method, required);
+    }
+
+    /// Overload for both const and non-const methods
+    template <class CLASS>
+    void add(const std::string& name, void (CLASS::*method)(const LLSD&) const,
+             const LLSD& required=LLSD())
+    {
+        addMethod<CLASS>(name, method, required);
+    }
+
+    /// Unregister a callable
+    bool remove(const std::string& name);
+
+    /// Call a registered callable with an explicitly-specified name. If no
+    /// such callable exists, die with LL_ERRS. If the @a event fails to match
+    /// the @a required prototype specified at add() time, die with LL_ERRS.
+    void operator()(const std::string& name, const LLSD& event) const;
+
+    /// Extract the @a key value from the incoming @a event, and call the
+    /// callable whose name is specified by that map @a key. If no such
+    /// callable exists, die with LL_ERRS. If the @a event fails to match the
+    /// @a required prototype specified at add() time, die with LL_ERRS.
+    void operator()(const LLSD& event) const;
+
+    /// Fetch the Callable for the specified name. If no such name was
+    /// registered, return an empty() Callable.
+    Callable get(const std::string& name) const;
+
+private:
+    template <class CLASS, typename METHOD>
+    void addMethod(const std::string& name, const METHOD& method, const LLSD& required)
+    {
+        CLASS* downcast = dynamic_cast<CLASS*>(this);
+        if (! downcast)
+        {
+            addFail(name, typeid(CLASS).name());
+        }
+        else
+        {
+            add(name, boost::bind(method, downcast, _1), required);
+        }
+    }
+    void addFail(const std::string& name, const std::string& classname) const;
+    /// try to dispatch, return @c true if success
+    bool attemptCall(const std::string& name, const LLSD& event) const;
+
+    std::string mDesc, mKey;
+    typedef std::map<std::string, std::pair<Callable, LLSD> > DispatchMap;
+    DispatchMap mDispatch;
+};
+
+/**
+ * Bundle an LLEventPump and a listener with an LLEventDispatcher. A class
+ * that contains (or derives from) LLDispatchListener need only specify the
+ * LLEventPump name and dispatch key, and add() its methods. Incoming events
+ * will automatically be dispatched.
+ */
+class LL_COMMON_API LLDispatchListener: public LLEventDispatcher
+{
+public:
+    LLDispatchListener(const std::string& pumpname, const std::string& key);
+
+    std::string getPumpName() const { return mPump.getName(); }
+
+private:
+    bool process(const LLSD& event);
+
+    LLEventStream mPump;
+    LLTempBoundListener mBoundListener;
+};
+
+#endif /* ! defined(LL_LLEVENTDISPATCHER_H) */
diff --git a/indra/llcommon/lleventfilter.cpp b/indra/llcommon/lleventfilter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..74133781bef2503d05ba30f2a7e2509417d0c27f
--- /dev/null
+++ b/indra/llcommon/lleventfilter.cpp
@@ -0,0 +1,149 @@
+/**
+ * @file   lleventfilter.cpp
+ * @author Nat Goodspeed
+ * @date   2009-03-05
+ * @brief  Implementation for lleventfilter.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lleventfilter.h"
+// STL headers
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+// other Linden headers
+#include "llerror.h"                // LL_ERRS
+#include "llsdutil.h"               // llsd_matches()
+
+LLEventFilter::LLEventFilter(LLEventPump& source, const std::string& name, bool tweak):
+    LLEventStream(name, tweak)
+{
+    source.listen(getName(), boost::bind(&LLEventFilter::post, this, _1));
+}
+
+LLEventMatching::LLEventMatching(const LLSD& pattern):
+    LLEventFilter("matching"),
+    mPattern(pattern)
+{
+}
+
+LLEventMatching::LLEventMatching(LLEventPump& source, const LLSD& pattern):
+    LLEventFilter(source, "matching"),
+    mPattern(pattern)
+{
+}
+
+bool LLEventMatching::post(const LLSD& event)
+{
+    if (! llsd_matches(mPattern, event).empty())
+        return false;
+
+    return LLEventStream::post(event);
+}
+
+LLEventTimeoutBase::LLEventTimeoutBase():
+    LLEventFilter("timeout")
+{
+}
+
+LLEventTimeoutBase::LLEventTimeoutBase(LLEventPump& source):
+    LLEventFilter(source, "timeout")
+{
+}
+
+void LLEventTimeoutBase::actionAfter(F32 seconds, const Action& action)
+{
+    setCountdown(seconds);
+    mAction = action;
+    if (! mMainloop.connected())
+    {
+        LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+        mMainloop = mainloop.listen(getName(), boost::bind(&LLEventTimeoutBase::tick, this, _1));
+    }
+}
+
+class ErrorAfter
+{
+public:
+    ErrorAfter(const std::string& message): mMessage(message) {}
+
+    void operator()()
+    {
+        LL_ERRS("LLEventTimeout") << mMessage << LL_ENDL;
+    }
+
+private:
+    std::string mMessage;
+};
+
+void LLEventTimeoutBase::errorAfter(F32 seconds, const std::string& message)
+{
+    actionAfter(seconds, ErrorAfter(message));
+}
+
+class EventAfter
+{
+public:
+    EventAfter(LLEventPump& pump, const LLSD& event):
+        mPump(pump),
+        mEvent(event)
+    {}
+
+    void operator()()
+    {
+        mPump.post(mEvent);
+    }
+
+private:
+    LLEventPump& mPump;
+    LLSD mEvent;
+};
+
+void LLEventTimeoutBase::eventAfter(F32 seconds, const LLSD& event)
+{
+    actionAfter(seconds, EventAfter(*this, event));
+}
+
+bool LLEventTimeoutBase::post(const LLSD& event)
+{
+    cancel();
+    return LLEventStream::post(event);
+}
+
+void LLEventTimeoutBase::cancel()
+{
+    mMainloop.disconnect();
+}
+
+bool LLEventTimeoutBase::tick(const LLSD&)
+{
+    if (countdownElapsed())
+    {
+        cancel();
+        mAction();
+    }
+    return false;                   // show event to other listeners
+}
+
+LLEventTimeout::LLEventTimeout() {}
+
+LLEventTimeout::LLEventTimeout(LLEventPump& source):
+    LLEventTimeoutBase(source)
+{
+}
+
+void LLEventTimeout::setCountdown(F32 seconds)
+{
+    mTimer.setTimerExpirySec(seconds);
+}
+
+bool LLEventTimeout::countdownElapsed() const
+{
+    return mTimer.hasExpired();
+}
diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..89f0c7ea43c9702663e53dfa4fa78f5e3a7ca3cf
--- /dev/null
+++ b/indra/llcommon/lleventfilter.h
@@ -0,0 +1,186 @@
+/**
+ * @file   lleventfilter.h
+ * @author Nat Goodspeed
+ * @date   2009-03-05
+ * @brief  Define LLEventFilter: LLEventStream subclass with conditions
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEVENTFILTER_H)
+#define LL_LLEVENTFILTER_H
+
+#include "llevents.h"
+#include "stdtypes.h"
+#include "lltimer.h"
+#include <boost/function.hpp>
+
+/**
+ * Generic base class
+ */
+class LL_COMMON_API LLEventFilter: public LLEventStream
+{
+public:
+    /// construct a standalone LLEventFilter
+    LLEventFilter(const std::string& name="filter", bool tweak=true):
+        LLEventStream(name, tweak)
+    {}
+    /// construct LLEventFilter and connect it to the specified LLEventPump
+    LLEventFilter(LLEventPump& source, const std::string& name="filter", bool tweak=true);
+
+    /// Post an event to all listeners
+    virtual bool post(const LLSD& event) = 0;
+};
+
+/**
+ * Pass through only events matching a specified pattern
+ */
+class LLEventMatching: public LLEventFilter
+{
+public:
+    /// Pass an LLSD map with keys and values the incoming event must match
+    LLEventMatching(const LLSD& pattern);
+    /// instantiate and connect
+    LLEventMatching(LLEventPump& source, const LLSD& pattern);
+
+    /// Only pass through events matching the pattern
+    virtual bool post(const LLSD& event);
+
+private:
+    LLSD mPattern;
+};
+
+/**
+ * Wait for an event to be posted. If no such event arrives within a specified
+ * time, take a specified action. See LLEventTimeout for production
+ * implementation.
+ *
+ * @NOTE This is an abstract base class so that, for testing, we can use an
+ * alternate "timer" that doesn't actually consume real time.
+ */
+class LL_COMMON_API LLEventTimeoutBase: public LLEventFilter
+{
+public:
+    /// construct standalone
+    LLEventTimeoutBase();
+    /// construct and connect
+    LLEventTimeoutBase(LLEventPump& source);
+
+    /// Callable, can be constructed with boost::bind()
+    typedef boost::function<void()> Action;
+
+    /**
+     * Start countdown timer for the specified number of @a seconds. Forward
+     * all events. If any event arrives before timer expires, cancel timer. If
+     * no event arrives before timer expires, take specified @a action.
+     *
+     * This is a one-shot timer. Once it has either expired or been canceled,
+     * it is inert until another call to actionAfter().
+     *
+     * Calling actionAfter() while an existing timer is running cheaply
+     * replaces that original timer. Thus, a valid use case is to detect
+     * idleness of some event source by calling actionAfter() on each new
+     * event. A rapid sequence of events will keep the timer from expiring;
+     * the first gap in events longer than the specified timer will fire the
+     * specified Action.
+     *
+     * Any post() call cancels the timer. To be satisfied with only a
+     * particular event, chain on an LLEventMatching that only passes such
+     * events:
+     *
+     * @code
+     * event                                                 ultimate
+     * source ---> LLEventMatching ---> LLEventTimeout  ---> listener
+     * @endcode
+     *
+     * @NOTE
+     * The implementation relies on frequent events on the LLEventPump named
+     * "mainloop".
+     */
+    void actionAfter(F32 seconds, const Action& action);
+
+    /**
+     * Like actionAfter(), but where the desired Action is LL_ERRS
+     * termination. Pass the timeout time and the desired LL_ERRS @a message.
+     *
+     * This method is useful when, for instance, some async API guarantees an
+     * event, whether success or failure, within a stated time window.
+     * Instantiate an LLEventTimeout listening to that API and call
+     * errorAfter() on each async request with a timeout comfortably longer
+     * than the API's time guarantee (much longer than the anticipated
+     * "mainloop" granularity).
+     *
+     * Then if the async API breaks its promise, the program terminates with
+     * the specified LL_ERRS @a message. The client of the async API can
+     * therefore assume the guarantee is upheld.
+     *
+     * @NOTE
+     * errorAfter() is implemented in terms of actionAfter(), so all remarks
+     * about calling actionAfter() also apply to errorAfter().
+     */
+    void errorAfter(F32 seconds, const std::string& message);
+
+    /**
+     * Like actionAfter(), but where the desired Action is a particular event
+     * for all listeners. Pass the timeout time and the desired @a event data.
+     * 
+     * Suppose the timeout should only be satisfied by a particular event, but
+     * the ultimate listener must see all other incoming events as well, plus
+     * the timeout @a event if any:
+     * 
+     * @code
+     * some        LLEventMatching                           LLEventMatching
+     * event  ---> for particular  ---> LLEventTimeout  ---> for timeout
+     * source      event                                     event \
+     *       \                                                      \ ultimate
+     *        `-----------------------------------------------------> listener
+     * @endcode
+     * 
+     * Since a given listener can listen on more than one LLEventPump, we can
+     * set things up so it sees the set union of events from LLEventTimeout
+     * and the original event source. However, as LLEventTimeout passes
+     * through all incoming events, the "particular event" that satisfies the
+     * left LLEventMatching would reach the ultimate listener twice. So we add
+     * an LLEventMatching that only passes timeout events.
+     *
+     * @NOTE
+     * eventAfter() is implemented in terms of actionAfter(), so all remarks
+     * about calling actionAfter() also apply to eventAfter().
+     */
+    void eventAfter(F32 seconds, const LLSD& event);
+
+    /// Pass event through, canceling the countdown timer
+    virtual bool post(const LLSD& event);
+
+    /// Cancel timer without event
+    void cancel();
+
+protected:
+    virtual void setCountdown(F32 seconds) = 0;
+    virtual bool countdownElapsed() const = 0;
+
+private:
+    bool tick(const LLSD&);
+
+    LLBoundListener mMainloop;
+    Action mAction;
+};
+
+/// Production implementation of LLEventTimoutBase
+class LL_COMMON_API LLEventTimeout: public LLEventTimeoutBase
+{
+public:
+    LLEventTimeout();
+    LLEventTimeout(LLEventPump& source);
+
+protected:
+    virtual void setCountdown(F32 seconds);
+    virtual bool countdownElapsed() const;
+
+private:
+    LLTimer mTimer;
+};
+
+#endif /* ! defined(LL_LLEVENTFILTER_H) */
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index eb380ba7c8b04f02879fbb8bb3c95e01ed5801ea..4bdfe5a867be25aa69aab95d0b32d858491894e5 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -38,6 +38,12 @@
 #pragma warning (pop)
 #endif
 // other Linden headers
+#include "stringize.h"
+#include "llerror.h"
+#include "llsdutil.h"
+#if LL_MSVC
+#pragma warning (disable : 4702)
+#endif
 
 /*****************************************************************************
 *   queue_names: specify LLEventPump names that should be instantiated as
@@ -56,14 +62,12 @@ const char* queue_names[] =
 /*****************************************************************************
 *   If there's a "mainloop" pump, listen on that to flush all LLEventQueues
 *****************************************************************************/
-struct RegisterFlush
+struct RegisterFlush : public LLEventTrackable
 {
     RegisterFlush():
-        pumps(LLEventPumps::instance()),
-        mainloop(pumps.obtain("mainloop")),
-        name("flushLLEventQueues")
+        pumps(LLEventPumps::instance())
     {
-        mainloop.listen(name, boost::bind(&RegisterFlush::flush, this, _1));
+        pumps.obtain("mainloop").listen("flushLLEventQueues", boost::bind(&RegisterFlush::flush, this, _1));
     }
     bool flush(const LLSD&)
     {
@@ -72,11 +76,9 @@ struct RegisterFlush
     }
     ~RegisterFlush()
     {
-        mainloop.stopListening(name);
+        // LLEventTrackable handles stopListening for us.
     }
     LLEventPumps& pumps;
-    LLEventPump& mainloop;
-    const std::string name;
 };
 static RegisterFlush registerFlush;
 
@@ -124,6 +126,16 @@ void LLEventPumps::flush()
     }
 }
 
+void LLEventPumps::reset()
+{
+    // Reset every known LLEventPump instance. Leave it up to each instance to
+    // decide what to do with the reset() call.
+    for (PumpMap::iterator pmi = mPumpMap.begin(), pmend = mPumpMap.end(); pmi != pmend; ++pmi)
+    {
+        pmi->second->reset();
+    }
+}
+
 std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string& name, bool tweak)
 {
     std::pair<PumpMap::iterator, bool> inserted =
@@ -240,6 +252,7 @@ LLEventPumps::~LLEventPumps()
 LLEventPump::LLEventPump(const std::string& name, bool tweak):
     // Register every new instance with LLEventPumps
     mName(LLEventPumps::instance().registerNew(*this, name, tweak)),
+    mSignal(new LLStandardSignal()),
     mEnabled(true)
 {}
 
@@ -256,6 +269,19 @@ LLEventPump::~LLEventPump()
 // static data member
 const LLEventPump::NameList LLEventPump::empty;
 
+std::string LLEventPump::inventName(const std::string& pfx)
+{
+    static long suffix = 0;
+    return STRINGIZE(pfx << suffix++);
+}
+
+void LLEventPump::reset()
+{
+    mSignal.reset();
+    mConnections.clear();
+    //mDeps.clear();
+}
+
 LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventListener& listener,
                                          const NameList& after,
                                          const NameList& before)
@@ -397,7 +423,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
     }
     // Now that newNode has a value that places it appropriately in mSignal,
     // connect it.
-    LLBoundListener bound = mSignal.connect(newNode, listener);
+    LLBoundListener bound = mSignal->connect(newNode, listener);
     mConnections[name] = bound;
     return bound;
 }
@@ -437,7 +463,7 @@ bool LLEventStream::post(const LLSD& event)
     // Let caller know if any one listener handled the event. This is mostly
     // useful when using LLEventStream as a listener for an upstream
     // LLEventPump.
-    return mSignal(event);
+    return (*mSignal)(event);
 }
 
 /*****************************************************************************
@@ -468,7 +494,7 @@ void LLEventQueue::flush()
     mEventQueue.clear();
     for ( ; ! queue.empty(); queue.pop_front())
     {
-        mSignal(queue.front());
+        (*mSignal)(queue.front());
     }
 }
 
@@ -499,3 +525,26 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const
     }
     return (*mListener)(event);
 }
+
+void LLReqID::stamp(LLSD& response) const
+{
+    if (! (response.isUndefined() || response.isMap()))
+    {
+        // If 'response' was previously completely empty, it's okay to
+        // turn it into a map. If it was already a map, then it should be
+        // okay to add a key. But if it was anything else (e.g. a scalar),
+        // assigning a ["reqid"] key will DISCARD the previous value,
+        // replacing it with a map. That would be Bad.
+        LL_INFOS("LLReqID") << "stamp(" << mReqid << ") leaving non-map response unmodified: "
+                            << response << LL_ENDL;
+        return;
+    }
+    LLSD oldReqid(response["reqid"]);
+    if (! (oldReqid.isUndefined() || llsd_equals(oldReqid, mReqid)))
+    {
+        LL_INFOS("LLReqID") << "stamp(" << mReqid << ") preserving existing [\"reqid\"] value "
+                            << oldReqid << " in response: " << response << LL_ENDL;
+        return;
+    }
+    response["reqid"] = mReqid;
+}
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 240adcdd411211db0f54c968b441bfe10b872a0b..64e5cb5da7f290134b89f988e806f71dcd16f0b0 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -1,831 +1,943 @@
-/**
- * @file   llevents.h
- * @author Kent Quirk, Nat Goodspeed
- * @date   2008-09-11
- * @brief  This is an implementation of the event system described at
- *         https://wiki.lindenlab.com/wiki/Viewer:Messaging/Event_System,
- *         originally introduced in llnotifications.h. It has nothing
- *         whatsoever to do with the older system in llevent.h.
- * 
- * $LicenseInfo:firstyear=2008&license=viewergpl$
- * Copyright (c) 2008, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLEVENTS_H)
-#define LL_LLEVENTS_H
-
-#include <string>
-#include <map>
-#include <set>
-#include <vector>
-#include <list>
-#include <deque>
-#include <stdexcept>
-#if LL_WINDOWS
-	#pragma warning (push)
-	#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
-	#pragma warning (disable : 4264) 
-#endif
-#include <boost/signals2.hpp>
-#if LL_WINDOWS
-	#pragma warning (pop)
-#endif
-
-#include <boost/bind.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/enable_shared_from_this.hpp>
-#include <boost/utility.hpp>        // noncopyable
-#include <boost/optional/optional.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <boost/visit_each.hpp>
-#include <boost/ref.hpp>            // reference_wrapper
-#include <boost/type_traits/is_pointer.hpp>
-#include <boost/utility/addressof.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/iteration/local.hpp>
-#include <boost/function.hpp>
-#include <boost/static_assert.hpp>
-#include "llsd.h"
-#include "llsingleton.h"
-#include "lldependencies.h"
-
-// override this to allow binding free functions with more parameters
-#ifndef LLEVENTS_LISTENER_ARITY
-#define LLEVENTS_LISTENER_ARITY 10
-#endif
-
-// hack for testing
-#ifndef testable
-#define testable private
-#endif
-
-/*****************************************************************************
-*   Signal and handler declarations
-*   Using a single handler signature means that we can have a common handler
-*   type, rather than needing a distinct one for each different handler.
-*****************************************************************************/
-
-/**
- * A boost::signals Combiner that stops the first time a handler returns true
- * We need this because we want to have our handlers return bool, so that
- * we have the option to cause a handler to stop further processing. The
- * default handler fails when the signal returns a value but has no slots.
- */
-struct LLStopWhenHandled
-{
-    typedef bool result_type;
-
-    template<typename InputIterator>
-    result_type operator()(InputIterator first, InputIterator last) const
-    {
-        for (InputIterator si = first; si != last; ++si)
-		{
-            if (*si)
-			{
-                return true;
-			}
-		}
-        return false;
-    }
-};
-
-/**
- * We want to have a standard signature for all signals; this way,
- * we can easily document a protocol for communicating across
- * dlls and into scripting languages someday.
- *
- * We want to return a bool to indicate whether the signal has been
- * handled and should NOT be passed on to other listeners.
- * Return true to stop further handling of the signal, and false
- * to continue.
- *
- * We take an LLSD because this way the contents of the signal
- * are independent of the API used to communicate it.
- * It is const ref because then there's low cost to pass it;
- * if you only need to inspect it, it's very cheap.
- *
- * @internal
- * The @c float template parameter indicates that we will internally use @c
- * float to indicate relative listener order on a given LLStandardSignal.
- * Don't worry, the @c float values are strictly internal! They are not part
- * of the interface, for the excellent reason that requiring the caller to
- * specify a numeric key to establish order means that the caller must know
- * the universe of possible values. We use LLDependencies for that instead.
- */
-typedef boost::signals2::signal<bool(const LLSD&), LLStopWhenHandled, float>  LLStandardSignal;
-/// Methods that forward listeners (e.g. constructed with
-/// <tt>boost::bind()</tt>) should accept (const LLEventListener&)
-typedef LLStandardSignal::slot_type LLEventListener;
-/// Result of registering a listener, supports <tt>connected()</tt>,
-/// <tt>disconnect()</tt> and <tt>blocked()</tt>
-typedef boost::signals2::connection LLBoundListener;
-
-/**
- * A common idiom for event-based code is to accept either a callable --
- * directly called on completion -- or the string name of an LLEventPump on
- * which to post the completion event. Specifying a parameter as <tt>const
- * LLListenerOrPumpName&</tt> allows either.
- *
- * Calling a validly-constructed LLListenerOrPumpName, passing the LLSD
- * 'event' object, either calls the callable or posts the event to the named
- * LLEventPump.
- *
- * A default-constructed LLListenerOrPumpName is 'empty'. (This is useful as
- * the default value of an optional method parameter.) Calling it throws
- * LLListenerOrPumpName::Empty. Test for this condition beforehand using
- * either <tt>if (param)</tt> or <tt>if (! param)</tt>.
- */
-class LLListenerOrPumpName
-{
-public:
-    /// passing string name of LLEventPump
-    LLListenerOrPumpName(const std::string& pumpname);
-    /// passing string literal (overload so compiler isn't forced to infer
-    /// double conversion)
-    LLListenerOrPumpName(const char* pumpname);
-    /// passing listener -- the "anything else" catch-all case. The type of an
-    /// object constructed by boost::bind() isn't intended to be written out.
-    /// Normally we'd just accept 'const LLEventListener&', but that would
-    /// require double implicit conversion: boost::bind() object to
-    /// LLEventListener, LLEventListener to LLListenerOrPumpName. So use a
-    /// template to forward anything.
-    template<typename T>
-    LLListenerOrPumpName(const T& listener): mListener(listener) {}
-
-    /// for omitted method parameter: uninitialized mListener
-    LLListenerOrPumpName() {}
-
-    /// test for validity
-    operator bool() const { return bool(mListener); }
-    bool operator! () const { return ! mListener; }
-
-    /// explicit accessor
-    const LLEventListener& getListener() const { return *mListener; }
-
-    /// implicit conversion to LLEventListener
-    operator LLEventListener() const { return *mListener; }
-
-    /// allow calling directly
-    bool operator()(const LLSD& event) const;
-
-    /// exception if you try to call when empty
-    struct Empty: public std::runtime_error
-    {
-        Empty(const std::string& what):
-            std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {}
-    };
-
-private:
-    boost::optional<LLEventListener> mListener;
-};
-
-/*****************************************************************************
-*   LLEventPumps
-*****************************************************************************/
-class LLEventPump;
-
-/**
- * LLEventPumps is a Singleton manager through which one typically accesses
- * this subsystem.
- */
-class LLEventPumps: public LLSingleton<LLEventPumps>
-{
-    friend class LLSingleton<LLEventPumps>;
-public:
-    /**
-     * Find or create an LLEventPump instance with a specific name. We return
-     * a reference so there's no question about ownership. obtain() @em finds
-     * an instance without conferring @em ownership.
-     */
-    LLEventPump& obtain(const std::string& name);
-    /**
-     * Flush all known LLEventPump instances
-     */
-    void flush();
-
-private:
-    friend class LLEventPump;
-    /**
-     * Register a new LLEventPump instance (internal)
-     */
-    std::string registerNew(const LLEventPump&, const std::string& name, bool tweak);
-    /**
-     * Unregister a doomed LLEventPump instance (internal)
-     */
-    void unregister(const LLEventPump&);
-
-private:
-    LLEventPumps();
-    ~LLEventPumps();
-
-testable:
-    // Map of all known LLEventPump instances, whether or not we instantiated
-    // them. We store a plain old LLEventPump* because this map doesn't claim
-    // ownership of the instances. Though the common usage pattern is to
-    // request an instance using obtain(), it's fair to instantiate an
-    // LLEventPump subclass statically, as a class member, on the stack or on
-    // the heap. In such cases, the instantiating party is responsible for its
-    // lifespan.
-    typedef std::map<std::string, LLEventPump*> PumpMap;
-    PumpMap mPumpMap;
-    // Set of all LLEventPumps we instantiated. Membership in this set means
-    // we claim ownership, and will delete them when this LLEventPumps is
-    // destroyed.
-    typedef std::set<LLEventPump*> PumpSet;
-    PumpSet mOurPumps;
-    // LLEventPump names that should be instantiated as LLEventQueue rather
-    // than as LLEventStream
-    typedef std::set<std::string> PumpNames;
-    PumpNames mQueueNames;
-};
-
-/*****************************************************************************
-*   details
-*****************************************************************************/
-namespace LLEventDetail
-{
-    /// Any callable capable of connecting an LLEventListener to an
-    /// LLStandardSignal to produce an LLBoundListener can be mapped to this
-    /// signature.
-    typedef boost::function<LLBoundListener(const LLEventListener&)> ConnectFunc;
-
-    /**
-     * Utility template function to use Visitor appropriately
-     *
-     * @param listener Callable to connect, typically a boost::bind()
-     * expression. This will be visited by Visitor using boost::visit_each().
-     * @param connect_func Callable that will connect() @a listener to an
-     * LLStandardSignal, returning LLBoundListener.
-     */
-    template <typename LISTENER>
-    LLBoundListener visit_and_connect(const LISTENER& listener,
-                                      const ConnectFunc& connect_func);
-} // namespace LLEventDetail
-
-/*****************************************************************************
-*   LLEventPump
-*****************************************************************************/
-/**
- * LLEventPump is the base class interface through which we access the
- * concrete subclasses LLEventStream and LLEventQueue.
- */
-class LLEventPump: boost::noncopyable
-{
-public:
-    /**
-     * Exception thrown by LLEventPump(). You are trying to instantiate an
-     * LLEventPump (subclass) using the same name as some other instance, and
-     * you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
-     * variant.
-     */
-    struct DupPumpName: public std::runtime_error
-    {
-        DupPumpName(const std::string& what):
-            std::runtime_error(std::string("DupPumpName: ") + what) {}
-    };
-
-    /**
-     * Instantiate an LLEventPump (subclass) with the string name by which it
-     * can be found using LLEventPumps::obtain().
-     *
-     * If you pass (or default) @a tweak to @c false, then a duplicate name
-     * will throw DupPumpName. This won't happen if LLEventPumps::obtain()
-     * instantiates the LLEventPump, because obtain() uses find-or-create
-     * logic. It can only happen if you instantiate an LLEventPump in your own
-     * code -- and a collision with the name of some other LLEventPump is
-     * likely to cause much more subtle problems!
-     *
-     * When you hand-instantiate an LLEventPump, consider passing @a tweak as
-     * @c true. This directs LLEventPump() to append a suffix to the passed @a
-     * name to make it unique. You can retrieve the adjusted name by calling
-     * getName() on your new instance.
-     */
-    LLEventPump(const std::string& name, bool tweak=false);
-    virtual ~LLEventPump();
-
-    /// group exceptions thrown by listen(). We use exceptions because these
-    /// particular errors are likely to be coding errors, found and fixed by
-    /// the developer even before preliminary checkin.
-    struct ListenError: public std::runtime_error
-    {
-        ListenError(const std::string& what): std::runtime_error(what) {}
-    };
-    /**
-     * exception thrown by listen(). You are attempting to register a
-     * listener on this LLEventPump using the same listener name as an
-     * already-registered listener.
-     */
-    struct DupListenerName: public ListenError
-    {
-        DupListenerName(const std::string& what):
-            ListenError(std::string("DupListenerName: ") + what)
-        {}
-    };
-    /**
-     * exception thrown by listen(). The order dependencies specified for your
-     * listener are incompatible with existing listeners.
-     *
-     * Consider listener "a" which specifies before "b" and "b" which
-     * specifies before "c". You are now attempting to register "c" before
-     * "a". There is no order that can satisfy all constraints.
-     */
-    struct Cycle: public ListenError
-    {
-        Cycle(const std::string& what): ListenError(std::string("Cycle: ") + what) {}
-    };
-    /**
-     * exception thrown by listen(). This one means that your new listener
-     * would force a change to the order of previously-registered listeners,
-     * and we don't have a good way to implement that.
-     *
-     * Consider listeners "some", "other" and "third". "some" and "other" are
-     * registered earlier without specifying relative order, so "other"
-     * happens to be first. Now you attempt to register "third" after "some"
-     * and before "other". Whoops, that would require swapping "some" and
-     * "other", which we can't do. Instead we throw this exception.
-     *
-     * It may not be possible to change the registration order so we already
-     * know "third"s order requirement by the time we register the second of
-     * "some" and "other". A solution would be to specify that "some" must
-     * come before "other", or equivalently that "other" must come after
-     * "some".
-     */
-    struct OrderChange: public ListenError
-    {
-        OrderChange(const std::string& what): ListenError(std::string("OrderChange: ") + what) {}
-    };
-
-    /// used by listen()
-    typedef std::vector<std::string> NameList;
-    /// convenience placeholder for when you explicitly want to pass an empty
-    /// NameList
-    const static NameList empty;
-
-    /// Get this LLEventPump's name
-    std::string getName() const { return mName; }
-
-    /**
-     * Register a new listener with a unique name. Specify an optional list
-     * of other listener names after which this one must be called, likewise
-     * an optional list of other listener names before which this one must be
-     * called. The other listeners mentioned need not yet be registered
-     * themselves. listen() can throw any ListenError; see ListenError
-     * subclasses.
-     *
-     * If (as is typical) you pass a <tt>boost::bind()</tt> expression,
-     * listen() will inspect the components of that expression. If a bound
-     * object matches any of several cases, the connection will automatically
-     * be disconnected when that object is destroyed.
-     *
-     * * You bind a <tt>boost::weak_ptr</tt>.
-     * * Binding a <tt>boost::shared_ptr</tt> that way would ensure that the
-     *   referenced object would @em never be destroyed, since the @c
-     *   shared_ptr stored in the LLEventPump would remain an outstanding
-     *   reference. Use the weaken() function to convert your @c shared_ptr to
-     *   @c weak_ptr. Because this is easy to forget, binding a @c shared_ptr
-     *   will produce a compile error (@c BOOST_STATIC_ASSERT failure).
-     * * You bind a simple pointer or reference to an object derived from
-     *   <tt>boost::enable_shared_from_this</tt>. (UNDER CONSTRUCTION)
-     * * You bind a simple pointer or reference to an object derived from
-     *   LLEventTrackable. Unlike the cases described above, though, this is
-     *   vulnerable to a couple of cross-thread race conditions, as described
-     *   in the LLEventTrackable documentation.
-     */
-    template <typename LISTENER>
-    LLBoundListener listen(const std::string& name, const LISTENER& listener,
-                           const NameList& after=NameList(),
-                           const NameList& before=NameList())
-    {
-        // Examine listener, using our listen_impl() method to make the
-        // actual connection.
-        // This is why listen() is a template. Conversion from boost::bind()
-        // to LLEventListener performs type erasure, so it's important to look
-        // at the boost::bind object itself before that happens.
-        return LLEventDetail::visit_and_connect(listener,
-                                                boost::bind(&LLEventPump::listen_impl,
-                                                            this,
-                                                            name,
-                                                            _1,
-                                                            after,
-                                                            before));
-    }
-
-    /// Get the LLBoundListener associated with the passed name (dummy
-    /// LLBoundListener if not found)
-    virtual LLBoundListener getListener(const std::string& name) const;
-    /**
-     * Instantiate one of these to block an existing connection:
-     * @code
-     * { // in some local scope
-     *     LLEventPump::Blocker block(someLLBoundListener);
-     *     // code that needs the connection blocked
-     * } // unblock the connection again
-     * @endcode
-     */
-    typedef boost::signals2::shared_connection_block Blocker;
-    /// Unregister a listener by name. Prefer this to
-    /// <tt>getListener(name).disconnect()</tt> because stopListening() also
-    /// forgets this name.
-    virtual void stopListening(const std::string& name);
-    /// Post an event to all listeners. The @c bool return is only meaningful
-    /// if the underlying leaf class is LLEventStream -- beware of relying on
-    /// it too much! Truthfully, we return @c bool mostly to permit chaining
-    /// one LLEventPump as a listener on another.
-    virtual bool post(const LLSD&) = 0;
-    /// Enable/disable: while disabled, silently ignore all post() calls
-    virtual void enable(bool enabled=true) { mEnabled = enabled; }
-    /// query
-    virtual bool enabled() const { return mEnabled; }
-
-private:
-    friend class LLEventPumps;
-    /// flush queued events
-    virtual void flush() {}
-
-private:
-    virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&,
-                                        const NameList& after,
-                                        const NameList& before);
-    std::string mName;
-
-protected:
-    /// implement the dispatching
-    LLStandardSignal mSignal;
-    /// valve open?
-    bool mEnabled;
-    /// Map of named listeners. This tracks the listeners that actually exist
-    /// at this moment. When we stopListening(), we discard the entry from
-    /// this map.
-    typedef std::map<std::string, boost::signals2::connection> ConnectionMap;
-    ConnectionMap mConnections;
-    typedef LLDependencies<std::string, float> DependencyMap;
-    /// Dependencies between listeners. For each listener, track the float
-    /// used to establish its place in mSignal's order. This caches all the
-    /// listeners that have ever registered; stopListening() does not discard
-    /// the entry from this map. This is to avoid a new dependency sort if the
-    /// same listener with the same dependencies keeps hopping on and off this
-    /// LLEventPump.
-    DependencyMap mDeps;
-};
-
-/*****************************************************************************
-*   LLEventStream
-*****************************************************************************/
-/**
- * LLEventStream is a thin wrapper around LLStandardSignal. Posting an
- * event immediately calls all registered listeners.
- */
-class LLEventStream: public LLEventPump
-{
-public:
-    LLEventStream(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
-    virtual ~LLEventStream() {}
-
-    /// Post an event to all listeners
-    virtual bool post(const LLSD& event);
-};
-
-/*****************************************************************************
-*   LLEventQueue
-*****************************************************************************/
-/**
- * LLEventQueue isa LLEventPump whose post() method defers calling registered
- * listeners until flush() is called.
- */
-class LLEventQueue: public LLEventPump
-{
-public:
-    LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
-    virtual ~LLEventQueue() {}
-
-    /// Post an event to all listeners
-    virtual bool post(const LLSD& event);
-
-private:
-    /// flush queued events
-    virtual void flush();
-
-private:
-    typedef std::deque<LLSD> EventQueue;
-    EventQueue mEventQueue;
-};
-
-/*****************************************************************************
-*   LLEventTrackable and underpinnings
-*****************************************************************************/
-/**
- * LLEventTrackable wraps boost::signals2::trackable, which resembles
- * boost::trackable. Derive your listener class from LLEventTrackable instead,
- * and use something like
- * <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method,
- * instance, _1))</tt>. This will implicitly disconnect when the object
- * referenced by @c instance is destroyed.
- *
- * @note
- * LLEventTrackable doesn't address a couple of cases:
- * * Object destroyed during call
- *   - You enter a slot call in thread A.
- *   - Thread B destroys the object, which of course disconnects it from any
- *     future slot calls.
- *   - Thread A's call uses 'this', which now refers to a defunct object.
- *     Undefined behavior results.
- * * Call during destruction
- *   - @c MySubclass is derived from LLEventTrackable.
- *   - @c MySubclass registers one of its own methods using
- *     <tt>LLEventPump::listen()</tt>.
- *   - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt>
- *     runs, destroying state specific to the subclass. (For instance, a
- *     <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.)
- *   - The listening method will not be disconnected until
- *     <tt>~LLEventTrackable()</tt> runs.
- *   - Before we get there, another thread posts data to the @c LLEventPump
- *     instance, calling the @c MySubclass method.
- *   - The method in question relies on valid @c MySubclass state. (For
- *     instance, it attempts to dereference the <tt>Foo*</tt> pointer that was
- *     <tt>delete</tt>d but not zeroed.)
- *   - Undefined behavior results.
- * If you suspect you may encounter any such scenario, you're better off
- * managing the lifespan of your object with <tt>boost::shared_ptr</tt>.
- * Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression
- * involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging
- * thread-safe Boost.Signals2 machinery.
- */
-typedef boost::signals2::trackable LLEventTrackable;
-
-/**
- * We originally provided a suite of overloaded
- * LLEventTrackable::listenTo(LLEventPump&, ...) methods that would call
- * LLEventPump::listen(...) and then pass the returned LLBoundListener to
- * LLEventTrackable::track(). This was workable but error-prone: the coder
- * must remember to call listenTo() rather than the more straightforward
- * listen() method.
- *
- * Now we publish only the single canonical listen() method, so there's a
- * uniform mechanism. Having a single way to do this is good, in that there's
- * no question in the coder's mind which of several alternatives to choose.
- *
- * To support automatic connection management, we use boost::visit_each
- * (http://www.boost.org/doc/libs/1_37_0/doc/html/boost/visit_each.html) to
- * inspect each argument of a boost::bind expression. (Although the visit_each
- * mechanism was first introduced with the original Boost.Signals library, it
- * was only later documented.)
- *
- * Cases:
- * * At least one of the function's arguments is a boost::weak_ptr<T>. Pass
- *   the corresponding shared_ptr to slot_type::track(). Ideally that would be
- *   the object whose method we want to call, but in fact we do the same for
- *   any weak_ptr we might find among the bound arguments. If we're passing
- *   our bound method a weak_ptr to some object, wouldn't the destruction of
- *   that object invalidate the call? So we disconnect automatically when any
- *   such object is destroyed. This is the mechanism preferred by boost::
- *   signals2.
- * * One of the functions's arguments is a boost::shared_ptr<T>. This produces
- *   a compile error: the bound copy of the shared_ptr stored in the
- *   boost_bind object stored in the signal object would make the referenced
- *   T object immortal. We provide a weaken() function. Pass
- *   weaken(your_shared_ptr) instead. (We can inspect, but not modify, the
- *   boost::bind object. Otherwise we'd replace the shared_ptr with weak_ptr
- *   implicitly and just proceed.)
- * * One of the function's arguments is a plain pointer/reference to an object
- *   derived from boost::enable_shared_from_this. We assume that this object
- *   is managed using boost::shared_ptr, so we implicitly extract a shared_ptr
- *   and track that. (UNDER CONSTRUCTION)
- * * One of the function's arguments is derived from LLEventTrackable. Pass
- *   the LLBoundListener to its LLEventTrackable::track(). This is vulnerable
- *   to a couple different race conditions, as described in LLEventTrackable
- *   documentation. (NOTE: Now that LLEventTrackable is a typedef for
- *   boost::signals2::trackable, the Signals2 library handles this itself, so
- *   our visitor needs no special logic for this case.)
- * * Any other argument type is irrelevant to automatic connection management.
- */
-
-namespace LLEventDetail
-{
-    template <typename F>
-    const F& unwrap(const F& f) { return f; }
-
-    template <typename F>
-    const F& unwrap(const boost::reference_wrapper<F>& f) { return f.get(); }
-
-    // Most of the following is lifted from the Boost.Signals use of
-    // visit_each.
-    template<bool Cond> struct truth {};
-
-    /**
-     * boost::visit_each() Visitor, used on a template argument <tt>const F&
-     * f</tt> as follows (see visit_and_connect()):
-     * @code
-     * LLEventListener listener(f);
-     * Visitor visitor(listener); // bind listener so it can track() shared_ptrs
-     * using boost::visit_each;   // allow unqualified visit_each() call for ADL
-     * visit_each(visitor, unwrap(f));
-     * @endcode
-     */
-    class Visitor
-    {
-    public:
-        /**
-         * Visitor binds a reference to LLEventListener so we can track() any
-         * shared_ptrs we find in the argument list.
-         */
-        Visitor(LLEventListener& listener):
-            mListener(listener)
-        {
-        }
-
-        /**
-         * boost::visit_each() calls this method for each component of a
-         * boost::bind() expression.
-         */
-        template <typename T>
-        void operator()(const T& t) const
-        {
-            decode(t, 0);
-        }
-
-    private:
-        // decode() decides between a reference wrapper and anything else
-        // boost::ref() variant
-        template<typename T>
-        void decode(const boost::reference_wrapper<T>& t, int) const
-        {
-//          add_if_trackable(t.get_pointer());
-        }
-
-        // decode() anything else
-        template<typename T>
-        void decode(const T& t, long) const
-        {
-            typedef truth<(boost::is_pointer<T>::value)> is_a_pointer;
-            maybe_get_pointer(t, is_a_pointer());
-        }
-
-        // maybe_get_pointer() decides between a pointer and a non-pointer
-        // plain pointer variant
-        template<typename T>
-        void maybe_get_pointer(const T& t, truth<true>) const
-        {
-//          add_if_trackable(t);
-        }
-
-        // shared_ptr variant
-        template<typename T>
-        void maybe_get_pointer(const boost::shared_ptr<T>& t, truth<false>) const
-        {
-            // If we have a shared_ptr to this object, it doesn't matter
-            // whether the object is derived from LLEventTrackable, so no
-            // further analysis of T is needed.
-//          mListener.track(t);
-
-            // Make this case illegal. Passing a bound shared_ptr to
-            // slot_type::track() is useless, since the bound shared_ptr will
-            // keep the object alive anyway! Force the coder to cast to weak_ptr.
-
-            // Trivial as it is, make the BOOST_STATIC_ASSERT() condition
-            // dependent on template param so the macro is only evaluated if
-            // this method is in fact instantiated, as described here:
-            // http://www.boost.org/doc/libs/1_34_1/doc/html/boost_staticassert.html
-
-            // ATTENTION: Don't bind a shared_ptr<anything> using
-            // LLEventPump::listen(boost::bind()). Doing so captures a copy of
-            // the shared_ptr, making the referenced object effectively
-            // immortal. Use the weaken() function, e.g.:
-            // somepump.listen(boost::bind(...weaken(my_shared_ptr)...));
-            // This lets us automatically disconnect when the referenced
-            // object is destroyed.
-            BOOST_STATIC_ASSERT(sizeof(T) == 0);
-        }
-
-        // weak_ptr variant
-        template<typename T>
-        void maybe_get_pointer(const boost::weak_ptr<T>& t, truth<false>) const
-        {
-            // If we have a weak_ptr to this object, it doesn't matter
-            // whether the object is derived from LLEventTrackable, so no
-            // further analysis of T is needed.
-            mListener.track(t);
-//          std::cout << "Found weak_ptr<" << typeid(T).name() << ">!\n";
-        }
-
-#if 0
-        // reference to anything derived from boost::enable_shared_from_this
-        template <typename T>
-        inline void maybe_get_pointer(const boost::enable_shared_from_this<T>& ct,
-                                      truth<false>) const
-        {
-            // Use the slot_type::track(shared_ptr) mechanism. Cast away
-            // const-ness because (in our code base anyway) it's unusual
-            // to find shared_ptr<const T>.
-            boost::enable_shared_from_this<T>&
-                t(const_cast<boost::enable_shared_from_this<T>&>(ct));
-            std::cout << "Capturing shared_from_this()" << std::endl;
-            boost::shared_ptr<T> sp(t.shared_from_this());
-/*==========================================================================*|
-            std::cout << "Capturing weak_ptr" << std::endl;
-            boost::weak_ptr<T> wp(sp);
-|*==========================================================================*/
-            std::cout << "Tracking shared__ptr" << std::endl;
-            mListener.track(sp);
-        }
-#endif
-
-        // non-pointer variant
-        template<typename T>
-        void maybe_get_pointer(const T& t, truth<false>) const
-        {
-            // Take the address of this object, because the object itself may be
-            // trackable
-//          add_if_trackable(boost::addressof(t));
-        }
-
-/*==========================================================================*|
-        // add_if_trackable() adds LLEventTrackable objects to mTrackables
-        inline void add_if_trackable(const LLEventTrackable* t) const
-        {
-            if (t)
-            {
-            }
-        }
-
-        // pointer to anything not an LLEventTrackable subclass
-        inline void add_if_trackable(const void*) const
-        {
-        }
-
-        // pointer to free function
-        // The following construct uses the preprocessor to generate
-        // add_if_trackable() overloads accepting pointer-to-function taking
-        // 0, 1, ..., LLEVENTS_LISTENER_ARITY parameters of arbitrary type.
-#define BOOST_PP_LOCAL_MACRO(n)                                     \
-        template <typename R                                        \
-                  BOOST_PP_COMMA_IF(n)                              \
-                  BOOST_PP_ENUM_PARAMS(n, typename T)>              \
-        inline void                                                 \
-        add_if_trackable(R (*)(BOOST_PP_ENUM_PARAMS(n, T))) const   \
-        {                                                           \
-        }
-#define BOOST_PP_LOCAL_LIMITS (0, LLEVENTS_LISTENER_ARITY)
-#include BOOST_PP_LOCAL_ITERATE()
-#undef  BOOST_PP_LOCAL_MACRO
-#undef  BOOST_PP_LOCAL_LIMITS
-|*==========================================================================*/
-
-        /// Bind a reference to the LLEventListener to call its track() method.
-        LLEventListener& mListener;
-    };
-
-    /**
-     * Utility template function to use Visitor appropriately
-     *
-     * @param raw_listener Callable to connect, typically a boost::bind()
-     * expression. This will be visited by Visitor using boost::visit_each().
-     * @param connect_funct Callable that will connect() @a raw_listener to an
-     * LLStandardSignal, returning LLBoundListener.
-     */
-    template <typename LISTENER>
-    LLBoundListener visit_and_connect(const LISTENER& raw_listener,
-                                      const ConnectFunc& connect_func)
-    {
-        // Capture the listener
-        LLEventListener listener(raw_listener);
-        // Define our Visitor, binding the listener so we can call
-        // listener.track() if we discover any shared_ptr<Foo>.
-        LLEventDetail::Visitor visitor(listener);
-        // Allow unqualified visit_each() call for ADL
-        using boost::visit_each;
-        // Visit each component of a boost::bind() expression. Pass
-        // 'raw_listener', our template argument, rather than 'listener' from
-        // which type details have been erased. unwrap() comes from
-        // Boost.Signals, in case we were passed a boost::ref().
-        visit_each(visitor, LLEventDetail::unwrap(raw_listener));
-        // Make the connection using passed function. At present, wrapping
-        // this functionality into this function is a bit silly: we don't
-        // really need a visit_and_connect() function any more, just a visit()
-        // function. The definition of this function dates from when, after
-        // visit_each(), after establishing the connection, we had to
-        // postprocess the new connection with the visitor object. That's no
-        // longer necessary.
-        return connect_func(listener);
-    }
-} // namespace LLEventDetail
-
-// Somewhat to my surprise, passing boost::bind(...boost::weak_ptr<T>...) to
-// listen() fails in Boost code trying to instantiate LLEventListener (i.e.
-// LLStandardSignal::slot_type) because the boost::get_pointer() utility function isn't
-// specialized for boost::weak_ptr. This remedies that omission.
-namespace boost
-{
-    template <typename T>
-    T* get_pointer(const weak_ptr<T>& ptr) { return shared_ptr<T>(ptr).get(); }
-}
-
-/// Since we forbid use of listen(boost::bind(...shared_ptr<T>...)), provide an
-/// easy way to cast to the corresponding weak_ptr.
-template <typename T>
-boost::weak_ptr<T> weaken(const boost::shared_ptr<T>& ptr)
-{
-    return boost::weak_ptr<T>(ptr);
-}
-
-#endif /* ! defined(LL_LLEVENTS_H) */
+/**
+ * @file   llevents.h
+ * @author Kent Quirk, Nat Goodspeed
+ * @date   2008-09-11
+ * @brief  This is an implementation of the event system described at
+ *         https://wiki.lindenlab.com/wiki/Viewer:Messaging/Event_System,
+ *         originally introduced in llnotifications.h. It has nothing
+ *         whatsoever to do with the older system in llevent.h.
+ * 
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEVENTS_H)
+#define LL_LLEVENTS_H
+
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+#include <deque>
+#include <stdexcept>
+#if LL_WINDOWS
+	#pragma warning (push)
+	#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
+	#pragma warning (disable : 4264) 
+#endif
+#include <boost/signals2.hpp>
+#if LL_WINDOWS
+	#pragma warning (pop)
+#endif
+
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/utility.hpp>        // noncopyable
+#include <boost/optional/optional.hpp>
+#include <boost/visit_each.hpp>
+#include <boost/ref.hpp>            // reference_wrapper
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/function.hpp>
+#include <boost/static_assert.hpp>
+#include "llsd.h"
+#include "llsingleton.h"
+#include "lldependencies.h"
+
+// override this to allow binding free functions with more parameters
+#ifndef LLEVENTS_LISTENER_ARITY
+#define LLEVENTS_LISTENER_ARITY 10
+#endif
+
+// hack for testing
+#ifndef testable
+#define testable private
+#endif
+
+/*****************************************************************************
+*   Signal and handler declarations
+*   Using a single handler signature means that we can have a common handler
+*   type, rather than needing a distinct one for each different handler.
+*****************************************************************************/
+
+/**
+ * A boost::signals Combiner that stops the first time a handler returns true
+ * We need this because we want to have our handlers return bool, so that
+ * we have the option to cause a handler to stop further processing. The
+ * default handler fails when the signal returns a value but has no slots.
+ */
+struct LLStopWhenHandled
+{
+    typedef bool result_type;
+
+    template<typename InputIterator>
+    result_type operator()(InputIterator first, InputIterator last) const
+    {
+        for (InputIterator si = first; si != last; ++si)
+		{
+            if (*si)
+			{
+                return true;
+			}
+		}
+        return false;
+    }
+};
+
+/**
+ * We want to have a standard signature for all signals; this way,
+ * we can easily document a protocol for communicating across
+ * dlls and into scripting languages someday.
+ *
+ * We want to return a bool to indicate whether the signal has been
+ * handled and should NOT be passed on to other listeners.
+ * Return true to stop further handling of the signal, and false
+ * to continue.
+ *
+ * We take an LLSD because this way the contents of the signal
+ * are independent of the API used to communicate it.
+ * It is const ref because then there's low cost to pass it;
+ * if you only need to inspect it, it's very cheap.
+ *
+ * @internal
+ * The @c float template parameter indicates that we will internally use @c
+ * float to indicate relative listener order on a given LLStandardSignal.
+ * Don't worry, the @c float values are strictly internal! They are not part
+ * of the interface, for the excellent reason that requiring the caller to
+ * specify a numeric key to establish order means that the caller must know
+ * the universe of possible values. We use LLDependencies for that instead.
+ */
+typedef boost::signals2::signal<bool(const LLSD&), LLStopWhenHandled, float>  LLStandardSignal;
+/// Methods that forward listeners (e.g. constructed with
+/// <tt>boost::bind()</tt>) should accept (const LLEventListener&)
+typedef LLStandardSignal::slot_type LLEventListener;
+/// Result of registering a listener, supports <tt>connected()</tt>,
+/// <tt>disconnect()</tt> and <tt>blocked()</tt>
+typedef boost::signals2::connection LLBoundListener;
+/// Storing an LLBoundListener in LLTempBoundListener will disconnect the
+/// referenced listener when the LLTempBoundListener instance is destroyed.
+typedef boost::signals2::scoped_connection LLTempBoundListener;
+
+/**
+ * A common idiom for event-based code is to accept either a callable --
+ * directly called on completion -- or the string name of an LLEventPump on
+ * which to post the completion event. Specifying a parameter as <tt>const
+ * LLListenerOrPumpName&</tt> allows either.
+ *
+ * Calling a validly-constructed LLListenerOrPumpName, passing the LLSD
+ * 'event' object, either calls the callable or posts the event to the named
+ * LLEventPump.
+ *
+ * A default-constructed LLListenerOrPumpName is 'empty'. (This is useful as
+ * the default value of an optional method parameter.) Calling it throws
+ * LLListenerOrPumpName::Empty. Test for this condition beforehand using
+ * either <tt>if (param)</tt> or <tt>if (! param)</tt>.
+ */
+class LL_COMMON_API LLListenerOrPumpName
+{
+public:
+    /// passing string name of LLEventPump
+    LLListenerOrPumpName(const std::string& pumpname);
+    /// passing string literal (overload so compiler isn't forced to infer
+    /// double conversion)
+    LLListenerOrPumpName(const char* pumpname);
+    /// passing listener -- the "anything else" catch-all case. The type of an
+    /// object constructed by boost::bind() isn't intended to be written out.
+    /// Normally we'd just accept 'const LLEventListener&', but that would
+    /// require double implicit conversion: boost::bind() object to
+    /// LLEventListener, LLEventListener to LLListenerOrPumpName. So use a
+    /// template to forward anything.
+    template<typename T>
+    LLListenerOrPumpName(const T& listener): mListener(listener) {}
+
+    /// for omitted method parameter: uninitialized mListener
+    LLListenerOrPumpName() {}
+
+    /// test for validity
+    operator bool() const { return bool(mListener); }
+    bool operator! () const { return ! mListener; }
+
+    /// explicit accessor
+    const LLEventListener& getListener() const { return *mListener; }
+
+    /// implicit conversion to LLEventListener
+    operator LLEventListener() const { return *mListener; }
+
+    /// allow calling directly
+    bool operator()(const LLSD& event) const;
+
+    /// exception if you try to call when empty
+    struct Empty: public std::runtime_error
+    {
+        Empty(const std::string& what):
+            std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {}
+    };
+
+private:
+    boost::optional<LLEventListener> mListener;
+};
+
+/*****************************************************************************
+*   LLEventPumps
+*****************************************************************************/
+class LLEventPump;
+
+/**
+ * LLEventPumps is a Singleton manager through which one typically accesses
+ * this subsystem.
+ */
+class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
+{
+    friend class LLSingleton<LLEventPumps>;
+public:
+    /**
+     * Find or create an LLEventPump instance with a specific name. We return
+     * a reference so there's no question about ownership. obtain() @em finds
+     * an instance without conferring @em ownership.
+     */
+    LLEventPump& obtain(const std::string& name);
+    /**
+     * Flush all known LLEventPump instances
+     */
+    void flush();
+
+    /**
+     * Reset all known LLEventPump instances
+     * workaround for DEV-35406 crash on shutdown
+     */
+    void reset();
+
+private:
+    friend class LLEventPump;
+    /**
+     * Register a new LLEventPump instance (internal)
+     */
+    std::string registerNew(const LLEventPump&, const std::string& name, bool tweak);
+    /**
+     * Unregister a doomed LLEventPump instance (internal)
+     */
+    void unregister(const LLEventPump&);
+
+private:
+    LLEventPumps();
+    ~LLEventPumps();
+
+testable:
+    // Map of all known LLEventPump instances, whether or not we instantiated
+    // them. We store a plain old LLEventPump* because this map doesn't claim
+    // ownership of the instances. Though the common usage pattern is to
+    // request an instance using obtain(), it's fair to instantiate an
+    // LLEventPump subclass statically, as a class member, on the stack or on
+    // the heap. In such cases, the instantiating party is responsible for its
+    // lifespan.
+    typedef std::map<std::string, LLEventPump*> PumpMap;
+    PumpMap mPumpMap;
+    // Set of all LLEventPumps we instantiated. Membership in this set means
+    // we claim ownership, and will delete them when this LLEventPumps is
+    // destroyed.
+    typedef std::set<LLEventPump*> PumpSet;
+    PumpSet mOurPumps;
+    // LLEventPump names that should be instantiated as LLEventQueue rather
+    // than as LLEventStream
+    typedef std::set<std::string> PumpNames;
+    PumpNames mQueueNames;
+};
+
+/*****************************************************************************
+*   details
+*****************************************************************************/
+namespace LLEventDetail
+{
+    /// Any callable capable of connecting an LLEventListener to an
+    /// LLStandardSignal to produce an LLBoundListener can be mapped to this
+    /// signature.
+    typedef boost::function<LLBoundListener(const LLEventListener&)> ConnectFunc;
+
+    /**
+     * Utility template function to use Visitor appropriately
+     *
+     * @param listener Callable to connect, typically a boost::bind()
+     * expression. This will be visited by Visitor using boost::visit_each().
+     * @param connect_func Callable that will connect() @a listener to an
+     * LLStandardSignal, returning LLBoundListener.
+     */
+    template <typename LISTENER>
+    LLBoundListener visit_and_connect(const LISTENER& listener,
+                                      const ConnectFunc& connect_func);
+} // namespace LLEventDetail
+
+/*****************************************************************************
+*   LLEventTrackable
+*****************************************************************************/
+/**
+ * LLEventTrackable wraps boost::signals2::trackable, which resembles
+ * boost::trackable. Derive your listener class from LLEventTrackable instead,
+ * and use something like
+ * <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method,
+ * instance, _1))</tt>. This will implicitly disconnect when the object
+ * referenced by @c instance is destroyed.
+ *
+ * @note
+ * LLEventTrackable doesn't address a couple of cases:
+ * * Object destroyed during call
+ *   - You enter a slot call in thread A.
+ *   - Thread B destroys the object, which of course disconnects it from any
+ *     future slot calls.
+ *   - Thread A's call uses 'this', which now refers to a defunct object.
+ *     Undefined behavior results.
+ * * Call during destruction
+ *   - @c MySubclass is derived from LLEventTrackable.
+ *   - @c MySubclass registers one of its own methods using
+ *     <tt>LLEventPump::listen()</tt>.
+ *   - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt>
+ *     runs, destroying state specific to the subclass. (For instance, a
+ *     <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.)
+ *   - The listening method will not be disconnected until
+ *     <tt>~LLEventTrackable()</tt> runs.
+ *   - Before we get there, another thread posts data to the @c LLEventPump
+ *     instance, calling the @c MySubclass method.
+ *   - The method in question relies on valid @c MySubclass state. (For
+ *     instance, it attempts to dereference the <tt>Foo*</tt> pointer that was
+ *     <tt>delete</tt>d but not zeroed.)
+ *   - Undefined behavior results.
+ * If you suspect you may encounter any such scenario, you're better off
+ * managing the lifespan of your object with <tt>boost::shared_ptr</tt>.
+ * Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression
+ * involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging
+ * thread-safe Boost.Signals2 machinery.
+ */
+typedef boost::signals2::trackable LLEventTrackable;
+
+/*****************************************************************************
+*   LLEventPump
+*****************************************************************************/
+/**
+ * LLEventPump is the base class interface through which we access the
+ * concrete subclasses LLEventStream and LLEventQueue.
+ *
+ * @NOTE
+ * LLEventPump derives from LLEventTrackable so that when you "chain"
+ * LLEventPump instances together, they will automatically disconnect on
+ * destruction. Please see LLEventTrackable documentation for situations in
+ * which this may be perilous across threads.
+ */
+class LL_COMMON_API LLEventPump: public LLEventTrackable
+{
+public:
+    /**
+     * Exception thrown by LLEventPump(). You are trying to instantiate an
+     * LLEventPump (subclass) using the same name as some other instance, and
+     * you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
+     * variant.
+     */
+    struct DupPumpName: public std::runtime_error
+    {
+        DupPumpName(const std::string& what):
+            std::runtime_error(std::string("DupPumpName: ") + what) {}
+    };
+
+    /**
+     * Instantiate an LLEventPump (subclass) with the string name by which it
+     * can be found using LLEventPumps::obtain().
+     *
+     * If you pass (or default) @a tweak to @c false, then a duplicate name
+     * will throw DupPumpName. This won't happen if LLEventPumps::obtain()
+     * instantiates the LLEventPump, because obtain() uses find-or-create
+     * logic. It can only happen if you instantiate an LLEventPump in your own
+     * code -- and a collision with the name of some other LLEventPump is
+     * likely to cause much more subtle problems!
+     *
+     * When you hand-instantiate an LLEventPump, consider passing @a tweak as
+     * @c true. This directs LLEventPump() to append a suffix to the passed @a
+     * name to make it unique. You can retrieve the adjusted name by calling
+     * getName() on your new instance.
+     */
+    LLEventPump(const std::string& name, bool tweak=false);
+    virtual ~LLEventPump();
+
+    /// group exceptions thrown by listen(). We use exceptions because these
+    /// particular errors are likely to be coding errors, found and fixed by
+    /// the developer even before preliminary checkin.
+    struct ListenError: public std::runtime_error
+    {
+        ListenError(const std::string& what): std::runtime_error(what) {}
+    };
+    /**
+     * exception thrown by listen(). You are attempting to register a
+     * listener on this LLEventPump using the same listener name as an
+     * already-registered listener.
+     */
+    struct DupListenerName: public ListenError
+    {
+        DupListenerName(const std::string& what):
+            ListenError(std::string("DupListenerName: ") + what)
+        {}
+    };
+    /**
+     * exception thrown by listen(). The order dependencies specified for your
+     * listener are incompatible with existing listeners.
+     *
+     * Consider listener "a" which specifies before "b" and "b" which
+     * specifies before "c". You are now attempting to register "c" before
+     * "a". There is no order that can satisfy all constraints.
+     */
+    struct Cycle: public ListenError
+    {
+        Cycle(const std::string& what): ListenError(std::string("Cycle: ") + what) {}
+    };
+    /**
+     * exception thrown by listen(). This one means that your new listener
+     * would force a change to the order of previously-registered listeners,
+     * and we don't have a good way to implement that.
+     *
+     * Consider listeners "some", "other" and "third". "some" and "other" are
+     * registered earlier without specifying relative order, so "other"
+     * happens to be first. Now you attempt to register "third" after "some"
+     * and before "other". Whoops, that would require swapping "some" and
+     * "other", which we can't do. Instead we throw this exception.
+     *
+     * It may not be possible to change the registration order so we already
+     * know "third"s order requirement by the time we register the second of
+     * "some" and "other". A solution would be to specify that "some" must
+     * come before "other", or equivalently that "other" must come after
+     * "some".
+     */
+    struct OrderChange: public ListenError
+    {
+        OrderChange(const std::string& what): ListenError(std::string("OrderChange: ") + what) {}
+    };
+
+    /// used by listen()
+    typedef std::vector<std::string> NameList;
+    /// convenience placeholder for when you explicitly want to pass an empty
+    /// NameList
+    const static NameList empty;
+
+    /// Get this LLEventPump's name
+    std::string getName() const { return mName; }
+
+    /**
+     * Register a new listener with a unique name. Specify an optional list
+     * of other listener names after which this one must be called, likewise
+     * an optional list of other listener names before which this one must be
+     * called. The other listeners mentioned need not yet be registered
+     * themselves. listen() can throw any ListenError; see ListenError
+     * subclasses.
+     *
+     * The listener name must be unique among active listeners for this
+     * LLEventPump, else you get DupListenerName. If you don't care to invent
+     * a name yourself, use inventName(). (I was tempted to recognize e.g. ""
+     * and internally generate a distinct name for that case. But that would
+     * handle badly the scenario in which you want to add, remove, re-add,
+     * etc. the same listener: each new listen() call would necessarily
+     * perform a new dependency sort. Assuming you specify the same
+     * after/before lists each time, using inventName() when you first
+     * instantiate your listener, then passing the same name on each listen()
+     * call, allows us to optimize away the second and subsequent dependency
+     * sorts.
+     *
+     * If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a
+     * listener, listen() will inspect the components of that expression. If a
+     * bound object matches any of several cases, the connection will
+     * automatically be disconnected when that object is destroyed.
+     *
+     * * You bind a <tt>boost::weak_ptr</tt>.
+     * * Binding a <tt>boost::shared_ptr</tt> that way would ensure that the
+     *   referenced object would @em never be destroyed, since the @c
+     *   shared_ptr stored in the LLEventPump would remain an outstanding
+     *   reference. Use the weaken() function to convert your @c shared_ptr to
+     *   @c weak_ptr. Because this is easy to forget, binding a @c shared_ptr
+     *   will produce a compile error (@c BOOST_STATIC_ASSERT failure).
+     * * You bind a simple pointer or reference to an object derived from
+     *   <tt>boost::enable_shared_from_this</tt>. (UNDER CONSTRUCTION)
+     * * You bind a simple pointer or reference to an object derived from
+     *   LLEventTrackable. Unlike the cases described above, though, this is
+     *   vulnerable to a couple of cross-thread race conditions, as described
+     *   in the LLEventTrackable documentation.
+     */
+    template <typename LISTENER>
+    LLBoundListener listen(const std::string& name, const LISTENER& listener,
+                           const NameList& after=NameList(),
+                           const NameList& before=NameList())
+    {
+        // Examine listener, using our listen_impl() method to make the
+        // actual connection.
+        // This is why listen() is a template. Conversion from boost::bind()
+        // to LLEventListener performs type erasure, so it's important to look
+        // at the boost::bind object itself before that happens.
+        return LLEventDetail::visit_and_connect(listener,
+                                                boost::bind(&LLEventPump::listen_impl,
+                                                            this,
+                                                            name,
+                                                            _1,
+                                                            after,
+                                                            before));
+    }
+
+    /// Get the LLBoundListener associated with the passed name (dummy
+    /// LLBoundListener if not found)
+    virtual LLBoundListener getListener(const std::string& name) const;
+    /**
+     * Instantiate one of these to block an existing connection:
+     * @code
+     * { // in some local scope
+     *     LLEventPump::Blocker block(someLLBoundListener);
+     *     // code that needs the connection blocked
+     * } // unblock the connection again
+     * @endcode
+     */
+    typedef boost::signals2::shared_connection_block Blocker;
+    /// Unregister a listener by name. Prefer this to
+    /// <tt>getListener(name).disconnect()</tt> because stopListening() also
+    /// forgets this name.
+    virtual void stopListening(const std::string& name);
+    /// Post an event to all listeners. The @c bool return is only meaningful
+    /// if the underlying leaf class is LLEventStream -- beware of relying on
+    /// it too much! Truthfully, we return @c bool mostly to permit chaining
+    /// one LLEventPump as a listener on another.
+    virtual bool post(const LLSD&) = 0;
+    /// Enable/disable: while disabled, silently ignore all post() calls
+    virtual void enable(bool enabled=true) { mEnabled = enabled; }
+    /// query
+    virtual bool enabled() const { return mEnabled; }
+
+    /// Generate a distinct name for a listener -- see listen()
+    static std::string inventName(const std::string& pfx="listener");
+
+private:
+    friend class LLEventPumps;
+    /// flush queued events
+    virtual void flush() {}
+
+    virtual void reset();
+
+private:
+    virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&,
+                                        const NameList& after,
+                                        const NameList& before);
+    std::string mName;
+
+protected:
+    /// implement the dispatching
+    boost::scoped_ptr<LLStandardSignal> mSignal;
+
+    /// valve open?
+    bool mEnabled;
+    /// Map of named listeners. This tracks the listeners that actually exist
+    /// at this moment. When we stopListening(), we discard the entry from
+    /// this map.
+    typedef std::map<std::string, boost::signals2::connection> ConnectionMap;
+    ConnectionMap mConnections;
+    typedef LLDependencies<std::string, float> DependencyMap;
+    /// Dependencies between listeners. For each listener, track the float
+    /// used to establish its place in mSignal's order. This caches all the
+    /// listeners that have ever registered; stopListening() does not discard
+    /// the entry from this map. This is to avoid a new dependency sort if the
+    /// same listener with the same dependencies keeps hopping on and off this
+    /// LLEventPump.
+    DependencyMap mDeps;
+};
+
+/*****************************************************************************
+*   LLEventStream
+*****************************************************************************/
+/**
+ * LLEventStream is a thin wrapper around LLStandardSignal. Posting an
+ * event immediately calls all registered listeners.
+ */
+class LL_COMMON_API LLEventStream: public LLEventPump
+{
+public:
+    LLEventStream(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
+    virtual ~LLEventStream() {}
+
+    /// Post an event to all listeners
+    virtual bool post(const LLSD& event);
+};
+
+/*****************************************************************************
+*   LLEventQueue
+*****************************************************************************/
+/**
+ * LLEventQueue isa LLEventPump whose post() method defers calling registered
+ * listeners until flush() is called.
+ */
+class LL_COMMON_API LLEventQueue: public LLEventPump
+{
+public:
+    LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
+    virtual ~LLEventQueue() {}
+
+    /// Post an event to all listeners
+    virtual bool post(const LLSD& event);
+
+private:
+    /// flush queued events
+    virtual void flush();
+
+private:
+    typedef std::deque<LLSD> EventQueue;
+    EventQueue mEventQueue;
+};
+
+/*****************************************************************************
+*   LLReqID
+*****************************************************************************/
+/**
+ * This class helps the implementer of a given event API to honor the
+ * ["reqid"] convention. By this convention, each event API stamps into its
+ * response LLSD a ["reqid"] key whose value echoes the ["reqid"] value, if
+ * any, from the corresponding request.
+ *
+ * This supports an (atypical, but occasionally necessary) use case in which
+ * two or more asynchronous requests are multiplexed onto the same ["reply"]
+ * LLEventPump. Since the response events could arrive in arbitrary order, the
+ * caller must be able to demux them. It does so by matching the ["reqid"]
+ * value in each response with the ["reqid"] value in the corresponding
+ * request.
+ *
+ * It is the caller's responsibility to ensure distinct ["reqid"] values for
+ * that case. Though LLSD::UUID is guaranteed to work, it might be overkill:
+ * the "namespace" of unique ["reqid"] values is simply the set of requests
+ * specifying the same ["reply"] LLEventPump name.
+ *
+ * Making a given event API echo the request's ["reqid"] into the response is
+ * nearly trivial. This helper is mostly for mnemonic purposes, to serve as a
+ * place to put these comments. We hope that each time a coder implements a
+ * new event API based on some existing one, s/he will say, "Huh, what's an
+ * LLReqID?" and look up this material.
+ *
+ * The hardest part about the convention is deciding where to store the
+ * ["reqid"] value. Ironically, LLReqID can't help with that: you must store
+ * an LLReqID instance in whatever storage will persist until the reply is
+ * sent. For example, if the request ultimately ends up using a Responder
+ * subclass, storing an LLReqID instance in the Responder works.
+ *
+ * @note
+ * The @em implementer of an event API must honor the ["reqid"] convention.
+ * However, the @em caller of an event API need only use it if s/he is sharing
+ * the same ["reply"] LLEventPump for two or more asynchronous event API
+ * requests.
+ *
+ * In most cases, it's far easier for the caller to instantiate a local
+ * LLEventStream and pass its name to the event API in question. Then it's
+ * perfectly reasonable not to set a ["reqid"] key in the request, ignoring
+ * the @c isUndefined() ["reqid"] value in the response.
+ */
+class LL_COMMON_API LLReqID
+{
+public:
+    /**
+     * If you have the request in hand at the time you instantiate the
+     * LLReqID, pass that request to extract its ["reqid"].
+ */
+    LLReqID(const LLSD& request):
+        mReqid(request["reqid"])
+    {}
+    /// If you don't yet have the request, use setFrom() later.
+    LLReqID() {}
+
+    /// Extract and store the ["reqid"] value from an incoming request.
+    void setFrom(const LLSD& request)
+    {
+        mReqid = request["reqid"];
+    }
+
+    /// Set ["reqid"] key into a pending response LLSD object.
+    void stamp(LLSD& response) const;
+
+    /// Make a whole new response LLSD object with our ["reqid"].
+    LLSD makeResponse() const
+    {
+        LLSD response;
+        stamp(response);
+        return response;
+    }
+
+    /// Not really sure of a use case for this accessor...
+    LLSD getReqID() const { return mReqid; }
+
+private:
+    LLSD mReqid;
+};
+
+/*****************************************************************************
+*   Underpinnings
+*****************************************************************************/
+/**
+ * We originally provided a suite of overloaded
+ * LLEventTrackable::listenTo(LLEventPump&, ...) methods that would call
+ * LLEventPump::listen(...) and then pass the returned LLBoundListener to
+ * LLEventTrackable::track(). This was workable but error-prone: the coder
+ * must remember to call listenTo() rather than the more straightforward
+ * listen() method.
+ *
+ * Now we publish only the single canonical listen() method, so there's a
+ * uniform mechanism. Having a single way to do this is good, in that there's
+ * no question in the coder's mind which of several alternatives to choose.
+ *
+ * To support automatic connection management, we use boost::visit_each
+ * (http://www.boost.org/doc/libs/1_37_0/doc/html/boost/visit_each.html) to
+ * inspect each argument of a boost::bind expression. (Although the visit_each
+ * mechanism was first introduced with the original Boost.Signals library, it
+ * was only later documented.)
+ *
+ * Cases:
+ * * At least one of the function's arguments is a boost::weak_ptr<T>. Pass
+ *   the corresponding shared_ptr to slot_type::track(). Ideally that would be
+ *   the object whose method we want to call, but in fact we do the same for
+ *   any weak_ptr we might find among the bound arguments. If we're passing
+ *   our bound method a weak_ptr to some object, wouldn't the destruction of
+ *   that object invalidate the call? So we disconnect automatically when any
+ *   such object is destroyed. This is the mechanism preferred by boost::
+ *   signals2.
+ * * One of the functions's arguments is a boost::shared_ptr<T>. This produces
+ *   a compile error: the bound copy of the shared_ptr stored in the
+ *   boost_bind object stored in the signal object would make the referenced
+ *   T object immortal. We provide a weaken() function. Pass
+ *   weaken(your_shared_ptr) instead. (We can inspect, but not modify, the
+ *   boost::bind object. Otherwise we'd replace the shared_ptr with weak_ptr
+ *   implicitly and just proceed.)
+ * * One of the function's arguments is a plain pointer/reference to an object
+ *   derived from boost::enable_shared_from_this. We assume that this object
+ *   is managed using boost::shared_ptr, so we implicitly extract a shared_ptr
+ *   and track that. (UNDER CONSTRUCTION)
+ * * One of the function's arguments is derived from LLEventTrackable. Pass
+ *   the LLBoundListener to its LLEventTrackable::track(). This is vulnerable
+ *   to a couple different race conditions, as described in LLEventTrackable
+ *   documentation. (NOTE: Now that LLEventTrackable is a typedef for
+ *   boost::signals2::trackable, the Signals2 library handles this itself, so
+ *   our visitor needs no special logic for this case.)
+ * * Any other argument type is irrelevant to automatic connection management.
+ */
+
+namespace LLEventDetail
+{
+    template <typename F>
+    const F& unwrap(const F& f) { return f; }
+
+    template <typename F>
+    const F& unwrap(const boost::reference_wrapper<F>& f) { return f.get(); }
+
+    // Most of the following is lifted from the Boost.Signals use of
+    // visit_each.
+    template<bool Cond> struct truth {};
+
+    /**
+     * boost::visit_each() Visitor, used on a template argument <tt>const F&
+     * f</tt> as follows (see visit_and_connect()):
+     * @code
+     * LLEventListener listener(f);
+     * Visitor visitor(listener); // bind listener so it can track() shared_ptrs
+     * using boost::visit_each;   // allow unqualified visit_each() call for ADL
+     * visit_each(visitor, unwrap(f));
+     * @endcode
+     */
+    class Visitor
+    {
+    public:
+        /**
+         * Visitor binds a reference to LLEventListener so we can track() any
+         * shared_ptrs we find in the argument list.
+         */
+        Visitor(LLEventListener& listener):
+            mListener(listener)
+        {
+        }
+
+        /**
+         * boost::visit_each() calls this method for each component of a
+         * boost::bind() expression.
+         */
+        template <typename T>
+        void operator()(const T& t) const
+        {
+            decode(t, 0);
+        }
+
+    private:
+        // decode() decides between a reference wrapper and anything else
+        // boost::ref() variant
+        template<typename T>
+        void decode(const boost::reference_wrapper<T>& t, int) const
+        {
+//          add_if_trackable(t.get_pointer());
+        }
+
+        // decode() anything else
+        template<typename T>
+        void decode(const T& t, long) const
+        {
+            typedef truth<(boost::is_pointer<T>::value)> is_a_pointer;
+            maybe_get_pointer(t, is_a_pointer());
+        }
+
+        // maybe_get_pointer() decides between a pointer and a non-pointer
+        // plain pointer variant
+        template<typename T>
+        void maybe_get_pointer(const T& t, truth<true>) const
+        {
+//          add_if_trackable(t);
+        }
+
+        // shared_ptr variant
+        template<typename T>
+        void maybe_get_pointer(const boost::shared_ptr<T>& t, truth<false>) const
+        {
+            // If we have a shared_ptr to this object, it doesn't matter
+            // whether the object is derived from LLEventTrackable, so no
+            // further analysis of T is needed.
+//          mListener.track(t);
+
+            // Make this case illegal. Passing a bound shared_ptr to
+            // slot_type::track() is useless, since the bound shared_ptr will
+            // keep the object alive anyway! Force the coder to cast to weak_ptr.
+
+            // Trivial as it is, make the BOOST_STATIC_ASSERT() condition
+            // dependent on template param so the macro is only evaluated if
+            // this method is in fact instantiated, as described here:
+            // http://www.boost.org/doc/libs/1_34_1/doc/html/boost_staticassert.html
+
+            // ATTENTION: Don't bind a shared_ptr<anything> using
+            // LLEventPump::listen(boost::bind()). Doing so captures a copy of
+            // the shared_ptr, making the referenced object effectively
+            // immortal. Use the weaken() function, e.g.:
+            // somepump.listen(boost::bind(...weaken(my_shared_ptr)...));
+            // This lets us automatically disconnect when the referenced
+            // object is destroyed.
+            BOOST_STATIC_ASSERT(sizeof(T) == 0);
+        }
+
+        // weak_ptr variant
+        template<typename T>
+        void maybe_get_pointer(const boost::weak_ptr<T>& t, truth<false>) const
+        {
+            // If we have a weak_ptr to this object, it doesn't matter
+            // whether the object is derived from LLEventTrackable, so no
+            // further analysis of T is needed.
+            mListener.track(t);
+//          std::cout << "Found weak_ptr<" << typeid(T).name() << ">!\n";
+        }
+
+#if 0
+        // reference to anything derived from boost::enable_shared_from_this
+        template <typename T>
+        inline void maybe_get_pointer(const boost::enable_shared_from_this<T>& ct,
+                                      truth<false>) const
+        {
+            // Use the slot_type::track(shared_ptr) mechanism. Cast away
+            // const-ness because (in our code base anyway) it's unusual
+            // to find shared_ptr<const T>.
+            boost::enable_shared_from_this<T>&
+                t(const_cast<boost::enable_shared_from_this<T>&>(ct));
+            std::cout << "Capturing shared_from_this()" << std::endl;
+            boost::shared_ptr<T> sp(t.shared_from_this());
+/*==========================================================================*|
+            std::cout << "Capturing weak_ptr" << std::endl;
+            boost::weak_ptr<T> wp(sp);
+|*==========================================================================*/
+            std::cout << "Tracking shared__ptr" << std::endl;
+            mListener.track(sp);
+        }
+#endif
+
+        // non-pointer variant
+        template<typename T>
+        void maybe_get_pointer(const T& t, truth<false>) const
+        {
+            // Take the address of this object, because the object itself may be
+            // trackable
+//          add_if_trackable(boost::addressof(t));
+        }
+
+/*==========================================================================*|
+        // add_if_trackable() adds LLEventTrackable objects to mTrackables
+        inline void add_if_trackable(const LLEventTrackable* t) const
+        {
+            if (t)
+            {
+            }
+        }
+
+        // pointer to anything not an LLEventTrackable subclass
+        inline void add_if_trackable(const void*) const
+        {
+        }
+
+        // pointer to free function
+        // The following construct uses the preprocessor to generate
+        // add_if_trackable() overloads accepting pointer-to-function taking
+        // 0, 1, ..., LLEVENTS_LISTENER_ARITY parameters of arbitrary type.
+#define BOOST_PP_LOCAL_MACRO(n)                                     \
+        template <typename R                                        \
+                  BOOST_PP_COMMA_IF(n)                              \
+                  BOOST_PP_ENUM_PARAMS(n, typename T)>              \
+        inline void                                                 \
+        add_if_trackable(R (*)(BOOST_PP_ENUM_PARAMS(n, T))) const   \
+        {                                                           \
+        }
+#define BOOST_PP_LOCAL_LIMITS (0, LLEVENTS_LISTENER_ARITY)
+#include BOOST_PP_LOCAL_ITERATE()
+#undef  BOOST_PP_LOCAL_MACRO
+#undef  BOOST_PP_LOCAL_LIMITS
+|*==========================================================================*/
+
+        /// Bind a reference to the LLEventListener to call its track() method.
+        LLEventListener& mListener;
+    };
+
+    /**
+     * Utility template function to use Visitor appropriately
+     *
+     * @param raw_listener Callable to connect, typically a boost::bind()
+     * expression. This will be visited by Visitor using boost::visit_each().
+     * @param connect_funct Callable that will connect() @a raw_listener to an
+     * LLStandardSignal, returning LLBoundListener.
+     */
+    template <typename LISTENER>
+    LLBoundListener visit_and_connect(const LISTENER& raw_listener,
+                                      const ConnectFunc& connect_func)
+    {
+        // Capture the listener
+        LLEventListener listener(raw_listener);
+        // Define our Visitor, binding the listener so we can call
+        // listener.track() if we discover any shared_ptr<Foo>.
+        LLEventDetail::Visitor visitor(listener);
+        // Allow unqualified visit_each() call for ADL
+        using boost::visit_each;
+        // Visit each component of a boost::bind() expression. Pass
+        // 'raw_listener', our template argument, rather than 'listener' from
+        // which type details have been erased. unwrap() comes from
+        // Boost.Signals, in case we were passed a boost::ref().
+        visit_each(visitor, LLEventDetail::unwrap(raw_listener));
+        // Make the connection using passed function. At present, wrapping
+        // this functionality into this function is a bit silly: we don't
+        // really need a visit_and_connect() function any more, just a visit()
+        // function. The definition of this function dates from when, after
+        // visit_each(), after establishing the connection, we had to
+        // postprocess the new connection with the visitor object. That's no
+        // longer necessary.
+        return connect_func(listener);
+    }
+} // namespace LLEventDetail
+
+// Somewhat to my surprise, passing boost::bind(...boost::weak_ptr<T>...) to
+// listen() fails in Boost code trying to instantiate LLEventListener (i.e.
+// LLStandardSignal::slot_type) because the boost::get_pointer() utility function isn't
+// specialized for boost::weak_ptr. This remedies that omission.
+namespace boost
+{
+    template <typename T>
+    T* get_pointer(const weak_ptr<T>& ptr) { return shared_ptr<T>(ptr).get(); }
+}
+
+/// Since we forbid use of listen(boost::bind(...shared_ptr<T>...)), provide an
+/// easy way to cast to the corresponding weak_ptr.
+template <typename T>
+boost::weak_ptr<T> weaken(const boost::shared_ptr<T>& ptr)
+{
+    return boost::weak_ptr<T>(ptr);
+}
+
+#endif /* ! defined(LL_LLEVENTS_H) */
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 576e45d2aee7f14bd0a983f4735804b6aa8ff5b1..905d736d6213a1a38f1db81e2bced96c40d1ddab 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -1,317 +1,317 @@
-/** 
- * @file llfasttimer.h
- * @brief Declaration of a fast timer.
- *
- * $LicenseInfo:firstyear=2004&license=viewergpl$
- * 
- * Copyright (c) 2004-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_FASTTIMER_H
-#define LL_FASTTIMER_H
-
-#include "llinstancetracker.h"
-
-#define FAST_TIMER_ON 1
-
-#if LL_WINDOWS
-
-// shift off lower 8 bits for lower resolution but longer term timing
-// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
-inline U32 get_cpu_clock_count_32()
-{
-	U32 ret_val;
-	__asm 
-	{
-        _emit   0x0f
-        _emit   0x31
-		shr eax,8
-		shl edx,24
-		or eax, edx
-		mov dword ptr [ret_val], eax
-	}
-    return ret_val;
-}
-
-// return full timer value, still shifted by 8 bits
-inline U64 get_cpu_clock_count_64()
-{
-	U64 ret_val;
-	__asm 
-	{
-        _emit   0x0f
-        _emit   0x31
-		mov eax,eax
-		mov edx,edx
-		mov dword ptr [ret_val+4], edx
-		mov dword ptr [ret_val], eax
-	}
-    return ret_val >> 8;
-}
-
-#endif // LL_WINDOWS
-
-#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
-inline U32 get_cpu_clock_count_32()
-{																	
-	U64 x;															
-	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));					
-	return (U32)x >> 8;													
-}
-
-inline U32 get_cpu_clock_count_64()
-{																	
-	U64 x;
-	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
-	return x >> 8;
-}
-#endif
-
-#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__))
-//
-// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock
-//
-// Just use gettimeofday implementation for now
-
-inline U32 get_cpu_clock_count_32()
-{
-	return (U32)get_clock_count();
-}
-
-inline U32 get_cpu_clock_count_64()
-{																	
-	return get_clock_count();
-}
-#endif
-
-class LLMutex;
-
-#include <queue>
-#include "llsd.h"
-
-
-class LLFastTimer
-{
-public:
-	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
-	class NamedTimer 
-	:	public LLInstanceTracker<NamedTimer>
-	{
-		friend class DeclareTimer;
-	public:
-		~NamedTimer();
-
-		enum { HISTORY_NUM = 60 };
-
-		const std::string& getName() const { return mName; }
-		NamedTimer* getParent() const { return mParent; }
-		void setParent(NamedTimer* parent);
-		S32 getDepth();
-		std::string getToolTip(S32 history_index = -1);
-
-		typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
-		child_const_iter beginChildren();
-		child_const_iter endChildren();
-		std::vector<NamedTimer*>& getChildren();
-
-		void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
-		bool getCollapsed() const { return mCollapsed; }
-
-		U32 getCountAverage() const { return mCountAverage; }
-		U32 getCallAverage() const { return mCallAverage; }
-
-		U32 getHistoricalCount(S32 history_index = 0) const;
-		U32 getHistoricalCalls(S32 history_index = 0) const;
-
-		static NamedTimer& getRootNamedTimer();
-
-		struct FrameState
-		{
-			FrameState(NamedTimer* timerp);
-
-			U32 		mSelfTimeCounter;
-			U32 		mCalls;
-			FrameState*	mParent;		// info for caller timer
-			FrameState*	mLastCaller;	// used to bootstrap tree construction
-			NamedTimer*	mTimer;
-			U16			mActiveCount;	// number of timers with this ID active on stack
-			bool		mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame
-		};
-
-		S32 getFrameStateIndex() const { return mFrameStateIndex; }
-
-		FrameState& getFrameState() const;
-
-
-	private: 
-		friend class LLFastTimer;
-		friend class NamedTimerFactory;
-
-		//
-		// methods
-		//
-		NamedTimer(const std::string& name);
-		// recursive call to gather total time from children
-		static void accumulateTimings();
-
-		// updates cumulative times and hierarchy, 
-		// can be called multiple times in a frame, at any point
-		static void processTimes();
-
-		static void buildHierarchy();
-		static void resetFrame();
-		static void reset();
-
-	
-		//
-		// members
-		//
-		S32			mFrameStateIndex;
-
-		std::string	mName;
-
-		U32 		mTotalTimeCounter;
-
-		U32 		mCountAverage;
-		U32			mCallAverage;
-
-		U32*		mCountHistory;
-		U32*		mCallHistory;
-
-		// tree structure
-		NamedTimer*					mParent;				// NamedTimer of caller(parent)
-		std::vector<NamedTimer*>	mChildren;
-		bool						mCollapsed;				// don't show children
-		bool						mNeedsSorting;			// sort children whenever child added
-
-	};
-
-	// used to statically declare a new named timer
-	class DeclareTimer 
-	:	public LLInstanceTracker<DeclareTimer>
-	{
-	public:
-		DeclareTimer(const std::string& name, bool open);
-		DeclareTimer(const std::string& name);
-
-		static void updateCachedPointers();
-
-		// convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer)
-		operator NamedTimer::FrameState&() { return *mFrameState; }
-	private:
-		NamedTimer&				mTimer;
-		NamedTimer::FrameState* mFrameState; 
-	};
-
-
-public:
-	static LLMutex* sLogLock;
-	static std::queue<LLSD> sLogQueue;
-	static BOOL sLog;
-	static BOOL sMetricLog;
-
-	typedef std::vector<NamedTimer::FrameState> info_list_t;
-	static info_list_t& getFrameStateList();
-
-	enum RootTimerMarker { ROOT };
-	LLFastTimer(RootTimerMarker);
-
-	LLFastTimer(NamedTimer::FrameState& timer)
-	:	mFrameState(&timer)
-	{
-#if FAST_TIMER_ON
-		NamedTimer::FrameState* frame_state = &timer;
-		U32 cur_time = get_cpu_clock_count_32();
-		mStartSelfTime = cur_time;
-		mStartTotalTime = cur_time;
-
-		frame_state->mActiveCount++;
-		frame_state->mCalls++;
-		// keep current parent as long as it is active when we are
-		frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
-	
-		mLastTimer = sCurTimer;
-		sCurTimer = this;
-#endif
-	}
-
-	~LLFastTimer()
-	{
-#if FAST_TIMER_ON
-		NamedTimer::FrameState* frame_state = mFrameState;
-		U32 cur_time = get_cpu_clock_count_32();
-		frame_state->mSelfTimeCounter += cur_time - mStartSelfTime;
-
-		frame_state->mActiveCount--;
-		LLFastTimer* last_timer = mLastTimer;
-		sCurTimer = last_timer;
-
-		// store last caller to bootstrap tree creation
-		frame_state->mLastCaller = last_timer->mFrameState;
-
-		// we are only tracking self time, so subtract our total time delta from parents
-		U32 total_time = cur_time - mStartTotalTime;
-		last_timer->mStartSelfTime += total_time;
-#endif
-	}
-
-
-	// call this once a frame to reset timers
-	static void nextFrame();
-
-	// dumps current cumulative frame stats to log
-	// call nextFrame() to reset timers
-	static void dumpCurTimes(); 
-
-	// call this to reset timer hierarchy, averages, etc.
-	static void reset();
-
-	static U64 countsPerSecond();
-	static S32 getLastFrameIndex() { return sLastFrameIndex; }
-	static S32 getCurFrameIndex() { return sCurFrameIndex; }
-
-	static void writeLog(std::ostream& os);
-	static const NamedTimer* getTimerByName(const std::string& name);
-
-public:
-	static bool 		sPauseHistory;
-	static bool 		sResetHistory;
-	
-private:
-	typedef std::vector<LLFastTimer*> timer_stack_t;
-	static LLFastTimer*		sCurTimer;
-	static S32				sCurFrameIndex;
-	static S32				sLastFrameIndex;
-	static U64				sLastFrameTime;
-	static info_list_t*		sTimerInfos;
-
-	U32						mStartSelfTime;	// start time + time of all child timers
-	U32						mStartTotalTime;	// start time + time of all child timers
-	NamedTimer::FrameState*	mFrameState;
-	LLFastTimer*			mLastTimer;
-};
-
-#endif // LL_LLFASTTIMER_H
+/** 
+ * @file llfasttimer.h
+ * @brief Declaration of a fast timer.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * 
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_FASTTIMER_H
+#define LL_FASTTIMER_H
+
+#include "llinstancetracker.h"
+
+#define FAST_TIMER_ON 1
+
+#if LL_WINDOWS
+
+// shift off lower 8 bits for lower resolution but longer term timing
+// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
+inline U32 get_cpu_clock_count_32()
+{
+	U32 ret_val;
+	__asm 
+	{
+        _emit   0x0f
+        _emit   0x31
+		shr eax,8
+		shl edx,24
+		or eax, edx
+		mov dword ptr [ret_val], eax
+	}
+    return ret_val;
+}
+
+// return full timer value, still shifted by 8 bits
+inline U64 get_cpu_clock_count_64()
+{
+	U64 ret_val;
+	__asm 
+	{
+        _emit   0x0f
+        _emit   0x31
+		mov eax,eax
+		mov edx,edx
+		mov dword ptr [ret_val+4], edx
+		mov dword ptr [ret_val], eax
+	}
+    return ret_val >> 8;
+}
+
+#endif // LL_WINDOWS
+
+#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
+inline U32 get_cpu_clock_count_32()
+{																	
+	U64 x;															
+	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));					
+	return (U32)x >> 8;													
+}
+
+inline U32 get_cpu_clock_count_64()
+{																	
+	U64 x;
+	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+	return x >> 8;
+}
+#endif
+
+#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__))
+//
+// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock
+//
+// Just use gettimeofday implementation for now
+
+inline U32 get_cpu_clock_count_32()
+{
+	return (U32)get_clock_count();
+}
+
+inline U32 get_cpu_clock_count_64()
+{																	
+	return get_clock_count();
+}
+#endif
+
+class LLMutex;
+
+#include <queue>
+#include "llsd.h"
+
+
+class LL_COMMON_API LLFastTimer
+{
+public:
+	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
+	class LL_COMMON_API NamedTimer 
+	:	public LLInstanceTracker<NamedTimer>
+	{
+		friend class DeclareTimer;
+	public:
+		~NamedTimer();
+
+		enum { HISTORY_NUM = 60 };
+
+		const std::string& getName() const { return mName; }
+		NamedTimer* getParent() const { return mParent; }
+		void setParent(NamedTimer* parent);
+		S32 getDepth();
+		std::string getToolTip(S32 history_index = -1);
+
+		typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
+		child_const_iter beginChildren();
+		child_const_iter endChildren();
+		std::vector<NamedTimer*>& getChildren();
+
+		void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
+		bool getCollapsed() const { return mCollapsed; }
+
+		U32 getCountAverage() const { return mCountAverage; }
+		U32 getCallAverage() const { return mCallAverage; }
+
+		U32 getHistoricalCount(S32 history_index = 0) const;
+		U32 getHistoricalCalls(S32 history_index = 0) const;
+
+		static NamedTimer& getRootNamedTimer();
+
+		struct FrameState
+		{
+			FrameState(NamedTimer* timerp);
+
+			U32 		mSelfTimeCounter;
+			U32 		mCalls;
+			FrameState*	mParent;		// info for caller timer
+			FrameState*	mLastCaller;	// used to bootstrap tree construction
+			NamedTimer*	mTimer;
+			U16			mActiveCount;	// number of timers with this ID active on stack
+			bool		mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame
+		};
+
+		S32 getFrameStateIndex() const { return mFrameStateIndex; }
+
+		FrameState& getFrameState() const;
+
+
+	private: 
+		friend class LLFastTimer;
+		friend class NamedTimerFactory;
+
+		//
+		// methods
+		//
+		NamedTimer(const std::string& name);
+		// recursive call to gather total time from children
+		static void accumulateTimings();
+
+		// updates cumulative times and hierarchy, 
+		// can be called multiple times in a frame, at any point
+		static void processTimes();
+
+		static void buildHierarchy();
+		static void resetFrame();
+		static void reset();
+
+	
+		//
+		// members
+		//
+		S32			mFrameStateIndex;
+
+		std::string	mName;
+
+		U32 		mTotalTimeCounter;
+
+		U32 		mCountAverage;
+		U32			mCallAverage;
+
+		U32*		mCountHistory;
+		U32*		mCallHistory;
+
+		// tree structure
+		NamedTimer*					mParent;				// NamedTimer of caller(parent)
+		std::vector<NamedTimer*>	mChildren;
+		bool						mCollapsed;				// don't show children
+		bool						mNeedsSorting;			// sort children whenever child added
+
+	};
+
+	// used to statically declare a new named timer
+	class LL_COMMON_API DeclareTimer
+	:	public LLInstanceTracker<DeclareTimer>
+	{
+	public:
+		DeclareTimer(const std::string& name, bool open);
+		DeclareTimer(const std::string& name);
+
+		static void updateCachedPointers();
+
+		// convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer)
+		operator NamedTimer::FrameState&() { return *mFrameState; }
+	private:
+		NamedTimer&				mTimer;
+		NamedTimer::FrameState* mFrameState; 
+	};
+
+
+public:
+	static LLMutex* sLogLock;
+	static std::queue<LLSD> sLogQueue;
+	static BOOL sLog;
+	static BOOL sMetricLog;
+
+	typedef std::vector<NamedTimer::FrameState> info_list_t;
+	static info_list_t& getFrameStateList();
+
+	enum RootTimerMarker { ROOT };
+	LLFastTimer(RootTimerMarker);
+
+	LLFastTimer(NamedTimer::FrameState& timer)
+	:	mFrameState(&timer)
+	{
+#if FAST_TIMER_ON
+		NamedTimer::FrameState* frame_state = &timer;
+		U32 cur_time = get_cpu_clock_count_32();
+		mStartSelfTime = cur_time;
+		mStartTotalTime = cur_time;
+
+		frame_state->mActiveCount++;
+		frame_state->mCalls++;
+		// keep current parent as long as it is active when we are
+		frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
+	
+		mLastTimer = sCurTimer;
+		sCurTimer = this;
+#endif
+	}
+
+	~LLFastTimer()
+	{
+#if FAST_TIMER_ON
+		NamedTimer::FrameState* frame_state = mFrameState;
+		U32 cur_time = get_cpu_clock_count_32();
+		frame_state->mSelfTimeCounter += cur_time - mStartSelfTime;
+
+		frame_state->mActiveCount--;
+		LLFastTimer* last_timer = mLastTimer;
+		sCurTimer = last_timer;
+
+		// store last caller to bootstrap tree creation
+		frame_state->mLastCaller = last_timer->mFrameState;
+
+		// we are only tracking self time, so subtract our total time delta from parents
+		U32 total_time = cur_time - mStartTotalTime;
+		last_timer->mStartSelfTime += total_time;
+#endif
+	}
+
+
+	// call this once a frame to reset timers
+	static void nextFrame();
+
+	// dumps current cumulative frame stats to log
+	// call nextFrame() to reset timers
+	static void dumpCurTimes(); 
+
+	// call this to reset timer hierarchy, averages, etc.
+	static void reset();
+
+	static U64 countsPerSecond();
+	static S32 getLastFrameIndex() { return sLastFrameIndex; }
+	static S32 getCurFrameIndex() { return sCurFrameIndex; }
+
+	static void writeLog(std::ostream& os);
+	static const NamedTimer* getTimerByName(const std::string& name);
+
+public:
+	static bool 		sPauseHistory;
+	static bool 		sResetHistory;
+	
+private:
+	typedef std::vector<LLFastTimer*> timer_stack_t;
+	static LLFastTimer*		sCurTimer;
+	static S32				sCurFrameIndex;
+	static S32				sLastFrameIndex;
+	static U64				sLastFrameTime;
+	static info_list_t*		sTimerInfos;
+
+	U32						mStartSelfTime;	// start time + time of all child timers
+	U32						mStartTotalTime;	// start time + time of all child timers
+	NamedTimer::FrameState*	mFrameState;
+	LLFastTimer*			mLastTimer;
+};
+
+#endif // LL_LLFASTTIMER_H
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index c6092f7b9c4de29676f1cf1d9e2d5b5b969ff293..fea5d3ed2b8ee3495b73bf2e1c6156ae31cbd36a 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -70,7 +70,7 @@ typedef struct stat		llstat;
 
 #include "llstring.h" // safe char* -> std::string conversion
 
-class	LLFile
+class LL_COMMON_API LLFile
 {
 public:
 	// All these functions take UTF8 path/filenames.
@@ -95,7 +95,7 @@ class	LLFile
 
 #if USE_LLFILESTREAMS
 
-class	llifstream	:	public	std::basic_istream < char , std::char_traits < char > >
+class LL_COMMON_API llifstream	:	public	std::basic_istream < char , std::char_traits < char > >
 {
 	// input stream associated with a C stream
 public:
@@ -136,7 +136,7 @@ class	llifstream	:	public	std::basic_istream < char , std::char_traits < char >
 };
 
 
-class	llofstream	:	public	std::basic_ostream< char , std::char_traits < char > >
+class LL_COMMON_API llofstream	:	public	std::basic_ostream< char , std::char_traits < char > >
 {
 public:
 	typedef std::basic_ostream< char , std::char_traits < char > > _Myt;
@@ -185,7 +185,7 @@ class	llofstream	:	public	std::basic_ostream< char , std::char_traits < char > >
 //#define	llifstream	std::ifstream
 //#define	llofstream	std::ofstream
 
-class	llifstream	:	public	std::ifstream
+class LL_COMMON_API llifstream	:	public	std::ifstream
 {
 public:
 	llifstream() : std::ifstream()
@@ -203,7 +203,7 @@ class	llifstream	:	public	std::ifstream
 };
 
 
-class	llofstream	:	public	std::ofstream
+class LL_COMMON_API llofstream	:	public	std::ofstream
 {
 public:
 	llofstream() : std::ofstream()
@@ -231,7 +231,7 @@ class	llofstream	:	public	std::ofstream
  * and should only be used for config files and the like -- not in a
  * loop.
  */
-std::streamsize llifstream_size(llifstream& fstr);
-std::streamsize llofstream_size(llofstream& fstr);
+std::streamsize LL_COMMON_API llifstream_size(llifstream& fstr);
+std::streamsize LL_COMMON_API llofstream_size(llofstream& fstr);
 
 #endif // not LL_LLFILE_H
diff --git a/indra/llcommon/llfindlocale.h b/indra/llcommon/llfindlocale.h
index f17c7740f38fbba162ad3b17bf4a23eadd6d7831..b812a065db71b291907f488bab75da6e199a5cea 100644
--- a/indra/llcommon/llfindlocale.h
+++ b/indra/llcommon/llfindlocale.h
@@ -59,8 +59,8 @@ typedef enum {
 /* This allocates/fills in a FL_Locale structure with pointers to
    strings (which should be treated as static), or NULL for inappropriate /
    undetected fields. */
-FL_Success FL_FindLocale(FL_Locale **locale, FL_Domain domain);
+LL_COMMON_API FL_Success FL_FindLocale(FL_Locale **locale, FL_Domain domain);
 /* This should be used to free the struct written by FL_FindLocale */
-void FL_FreeLocale(FL_Locale **locale);
+LL_COMMON_API void FL_FreeLocale(FL_Locale **locale);
 
 #endif /*__findlocale_h_*/
diff --git a/indra/llcommon/llfixedbuffer.h b/indra/llcommon/llfixedbuffer.h
index 01b46d327ab08b956665fdef4953639af6ae319b..17fdef27d7d79dda2a0511292d4f38ed4e3fc4eb 100644
--- a/indra/llcommon/llfixedbuffer.h
+++ b/indra/llcommon/llfixedbuffer.h
@@ -41,7 +41,7 @@
 #include "llerrorcontrol.h"
 
 //  fixed buffer implementation
-class LLFixedBuffer : public LLLineBuffer
+class LL_COMMON_API LLFixedBuffer : public LLLineBuffer
 {
 public:
 	LLFixedBuffer(const U32 max_lines = 20);
diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h
index 44c62d971015255cf75c4aea70ba964915157665..dc64edb26da3fdb31b9781cbdf291d4355a0b3e9 100644
--- a/indra/llcommon/llformat.h
+++ b/indra/llcommon/llformat.h
@@ -40,6 +40,6 @@
 // *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun)
 // should perhaps be replaced with boost::format.
 
-std::string llformat(const char *fmt, ...);
+std::string LL_COMMON_API llformat(const char *fmt, ...);
 
 #endif // LL_LLFORMAT_H
diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h
index 8f51272af24f8fb5b854d78e1067b606329ccb3d..be2d9b070340c30a1b8f8e6ccc30d60ced40fec8 100644
--- a/indra/llcommon/llframetimer.h
+++ b/indra/llcommon/llframetimer.h
@@ -43,7 +43,7 @@
 #include "lltimer.h"
 #include "timing.h"
 
-class LLFrameTimer 
+class LL_COMMON_API LLFrameTimer 
 {
 public:
 	LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(TRUE) {}
diff --git a/indra/llcommon/llheartbeat.h b/indra/llcommon/llheartbeat.h
index fecb5b1e5460d5e11d434a6d8006415519be9017..6f7026970fe4d66c680dbbe14ab1d472a67c21b7 100644
--- a/indra/llcommon/llheartbeat.h
+++ b/indra/llcommon/llheartbeat.h
@@ -40,7 +40,7 @@
 // Note: Win32 does not support the heartbeat/smackdown system;
 //   heartbeat-delivery turns into a no-op there.
 
-class LLHeartbeat
+class LL_COMMON_API LLHeartbeat
 {
 public:
 	// secs_between_heartbeat: after a heartbeat is successfully delivered,
diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h
index 873f50a65ef8abbeb1d2fcdbd2f50025f66cf90f..7544ab1d11ffb2a3f853d1709457186689fbf828 100644
--- a/indra/llcommon/llkeythrottle.h
+++ b/indra/llcommon/llkeythrottle.h
@@ -118,6 +118,63 @@ class LLKeyThrottle
 		THROTTLE_BLOCKED,		// rate exceed, block key
 	};
 
+	F64 getActionCount(const T& id)
+	{
+		U64 now = 0;
+		if ( mIsRealtime )
+		{
+			now = LLKeyThrottleImpl<T>::getTime();
+		}
+		else
+		{
+			now = LLKeyThrottleImpl<T>::getFrame();
+		}
+
+		if (now >= (m.startTime + m.intervalLength))
+		{
+			if (now < (m.startTime + 2 * m.intervalLength))
+			{
+				// prune old data
+				delete m.prevMap;
+				m.prevMap = m.currMap;
+				m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+				m.startTime += m.intervalLength;
+			}
+			else
+			{
+				// lots of time has passed, all data is stale
+				delete m.prevMap;
+				delete m.currMap;
+				m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+				m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+				m.startTime = now;
+			}
+		}
+
+		U32 prevCount = 0;
+
+		typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
+		if (prev != m.prevMap->end())
+		{
+			prevCount = prev->second.count;
+		}
+
+		typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
+
+		// curr.count is the number of keys in
+		// this current 'time slice' from the beginning of it until now
+		// prevCount is the number of keys in the previous
+		// time slice scaled to be one full time slice back from the current 
+		// (now) time.
+
+		// compute current, windowed rate
+		F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
+		F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
+		return averageCount;
+	}
+
 	// call each time the key wants use
 	State noteAction(const T& id, S32 weight = 1)
 	{
diff --git a/indra/llcommon/llliveappconfig.h b/indra/llcommon/llliveappconfig.h
index a6ece6e8b39caac0236f13ae2ccf2178c134025f..73b3a2335272cd695d2ff9f0d4b108e6faff7d56 100644
--- a/indra/llcommon/llliveappconfig.h
+++ b/indra/llcommon/llliveappconfig.h
@@ -45,7 +45,7 @@
  * loop.  The traditional name for it is live_config.  Be sure to call
  * <code>live_config.checkAndReload()</code> periodically.
  */
-class LLLiveAppConfig : public LLLiveFile
+class LL_COMMON_API LLLiveAppConfig : public LLLiveFile
 {
 public:
 
diff --git a/indra/llcommon/lllivefile.h b/indra/llcommon/lllivefile.h
index 89b5d95e449c0cc211124fa919c213202820f6d8..2453d7a125a6fd44f949df7ae5190329049cda89 100644
--- a/indra/llcommon/lllivefile.h
+++ b/indra/llcommon/lllivefile.h
@@ -36,7 +36,7 @@
 extern const F32 DEFAULT_CONFIG_FILE_REFRESH;
 
 
-class LLLiveFile
+class LL_COMMON_API LLLiveFile
 {
 public:
 	LLLiveFile(const std::string& filename, const F32 refresh_period = 5.f);
diff --git a/indra/llcommon/lllog.h b/indra/llcommon/lllog.h
index 7ac6c8aa42a20cbb50ad1146902cfffec1841b63..4b6777bb9c7fa2fea2a175a64b0b5e3dbac49af6 100644
--- a/indra/llcommon/lllog.h
+++ b/indra/llcommon/lllog.h
@@ -41,7 +41,7 @@ class LLLogImpl;
 class LLApp;
 class LLSD;
 
-class LLLog
+class LL_COMMON_API LLLog
 {
 public:
 	LLLog(LLApp* app);
diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h
index d8bca03e4ecad6b3a23e7176c64aba6cef619173..df9d7324ab67f6a6115c193040f4979133470a54 100644
--- a/indra/llcommon/llmd5.h
+++ b/indra/llcommon/llmd5.h
@@ -80,7 +80,7 @@ const int MD5RAW_BYTES = 16;
 const int MD5HEX_STR_SIZE = 33;  // char hex[MD5HEX_STR_SIZE]; with null
 const int MD5HEX_STR_BYTES = 32; // message system fixed size
 
-class LLMD5 {
+class LL_COMMON_API LLMD5 {
 // first, some types:
   typedef unsigned       int uint4; // assumes integer is 4 words long
   typedef unsigned short int uint2; // assumes short integer is 2 words long
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index f41da37ba649e34b72f9e167457ef19d0c7ddf4f..09f19532b7c56439e2b580cdffd326ba9b14cf1d 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -1,65 +1,65 @@
-/** 
- * @file llmemory.h
- * @brief Memory allocation/deallocation header-stuff goes here.
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- * 
- * Copyright (c) 2002-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-#ifndef LLMEMORY_H
-#define LLMEMORY_H
-
-
-
-extern S32 gTotalDAlloc;
-extern S32 gTotalDAUse;
-extern S32 gDACount;
-
-extern void* ll_allocate (size_t size);
-extern void ll_release (void *p);
-
-class LLMemory
-{
-public:
-	static void initClass();
-	static void cleanupClass();
-	static void freeReserve();
-	// Return the resident set size of the current process, in bytes.
-	// Return value is zero if not known.
-	static U64 getCurrentRSS();
-private:
-	static char* reserveMem;
-};
-
-// LLRefCount moved to llrefcount.h
-
-// LLPointer moved to llpointer.h
-
-// LLSafeHandle moved to llsafehandle.h
-
-// LLSingleton moved to llsingleton.h
-
-#endif
+/** 
+ * @file llmemory.h
+ * @brief Memory allocation/deallocation header-stuff goes here.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ * 
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLMEMORY_H
+#define LLMEMORY_H
+
+
+
+extern S32 gTotalDAlloc;
+extern S32 gTotalDAUse;
+extern S32 gDACount;
+
+extern void* ll_allocate (size_t size);
+extern void ll_release (void *p);
+
+class LL_COMMON_API LLMemory
+{
+public:
+	static void initClass();
+	static void cleanupClass();
+	static void freeReserve();
+	// Return the resident set size of the current process, in bytes.
+	// Return value is zero if not known.
+	static U64 getCurrentRSS();
+private:
+	static char* reserveMem;
+};
+
+// LLRefCount moved to llrefcount.h
+
+// LLPointer moved to llpointer.h
+
+// LLSafeHandle moved to llsafehandle.h
+
+// LLSingleton moved to llsingleton.h
+
+#endif
diff --git a/indra/llcommon/llmemorystream.h b/indra/llcommon/llmemorystream.h
index f3486324c57b6a0cdf79d0eac00edca48260d250..fa0f5d22f2aa330c468786d81a955b3d12d6a15b 100644
--- a/indra/llcommon/llmemorystream.h
+++ b/indra/llcommon/llmemorystream.h
@@ -52,7 +52,7 @@
  * be careful to always pass in a valid memory location that exists
  * for at least as long as this streambuf.
  */
-class LLMemoryStreamBuf : public std::streambuf
+class LL_COMMON_API LLMemoryStreamBuf : public std::streambuf
 {
 public:
 	LLMemoryStreamBuf(const U8* start, S32 length);
@@ -74,7 +74,7 @@ class LLMemoryStreamBuf : public std::streambuf
  * be careful to always pass in a valid memory location that exists
  * for at least as long as this streambuf.
  */
-class LLMemoryStream : public std::istream
+class LL_COMMON_API LLMemoryStream : public std::istream
 {
 public:
 	LLMemoryStream(const U8* start, S32 length);
diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h
index 12310fcdb4fed67f4a58fddf3a68eea0deba0dec..5952a3a7c5a5b69ea782a1b174aaf145db0aa774 100644
--- a/indra/llcommon/llmemtype.h
+++ b/indra/llcommon/llmemtype.h
@@ -1,248 +1,248 @@
-/** 
- * @file llmemtype.h
- * @brief Runtime memory usage debugging utilities.
- *
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- * 
- * Copyright (c) 2005-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_MEMTYPE_H
-#define LL_MEMTYPE_H
-
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-
-#include "linden_common.h"
-//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-// WARNING: Never commit with MEM_TRACK_MEM == 1
-//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-#define MEM_TRACK_MEM (0 && LL_WINDOWS)
-
-#include <vector>
-
-#define MEM_TYPE_NEW(T)
-
-class LLMemType
-{
-public:
-
-	// class we'll initialize all instances of as
-	// static members of MemType.  Then use
-	// to construct any new mem type.
-	class DeclareMemType
-	{
-	public:
-		DeclareMemType(char const * st);
-		~DeclareMemType();
-	
-		S32 mID;
-		char const * mName;
-		
-		// array so we can map an index ID to Name
-		static std::vector<char const *> mNameList;
-	};
-
-	LLMemType(DeclareMemType& dt);
-	~LLMemType();
-
-	static char const * getNameFromID(S32 id);
-
-	static DeclareMemType MTYPE_INIT;
-	static DeclareMemType MTYPE_STARTUP;
-	static DeclareMemType MTYPE_MAIN;
-	static DeclareMemType MTYPE_FRAME;
-
-	static DeclareMemType MTYPE_GATHER_INPUT;
-	static DeclareMemType MTYPE_JOY_KEY;
-
-	static DeclareMemType MTYPE_IDLE;
-	static DeclareMemType MTYPE_IDLE_PUMP;
-	static DeclareMemType MTYPE_IDLE_NETWORK;
-	static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS;
-	static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION;
-	static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE;
-	static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY;
-	static DeclareMemType MTYPE_IDLE_AUDIO;
-
-	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING;
-	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS;
-	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES;
-
-	static DeclareMemType MTYPE_MESSAGE_CHECK_ALL;
-	static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS;
-
-	static DeclareMemType MTYPE_RENDER;
-	static DeclareMemType MTYPE_SLEEP;
-
-	static DeclareMemType MTYPE_NETWORK;
-	static DeclareMemType MTYPE_PHYSICS;
-	static DeclareMemType MTYPE_INTERESTLIST;
-
-	static DeclareMemType MTYPE_IMAGEBASE;
-	static DeclareMemType MTYPE_IMAGERAW;
-	static DeclareMemType MTYPE_IMAGEFORMATTED;
-	
-	static DeclareMemType MTYPE_APPFMTIMAGE;
-	static DeclareMemType MTYPE_APPRAWIMAGE;
-	static DeclareMemType MTYPE_APPAUXRAWIMAGE;
-	
-	static DeclareMemType MTYPE_DRAWABLE;
-	
-	static DeclareMemType MTYPE_OBJECT;
-	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE;
-	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE;
-
-	static DeclareMemType MTYPE_DISPLAY;
-	static DeclareMemType MTYPE_DISPLAY_UPDATE;
-	static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA;
-	static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM;
-	static DeclareMemType MTYPE_DISPLAY_SWAP;
-	static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD;
-	static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION;
-	static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE;
-	static DeclareMemType MTYPE_DISPLAY_STATE_SORT;
-	static DeclareMemType MTYPE_DISPLAY_SKY;
-	static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM;
-	static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH;
-	static DeclareMemType MTYPE_DISPLAY_RENDER_UI;
-	static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS;
-
-	static DeclareMemType MTYPE_VERTEX_DATA;
-	static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR;
-	static DeclareMemType MTYPE_VERTEX_DESTRUCTOR;
-	static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES;
-	static DeclareMemType MTYPE_VERTEX_CREATE_INDICES;
-	static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER;	
-	static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES;
-	static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS;
-	static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES;
-	static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER;
-	static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER;
-	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER;
-	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES;
-	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES;
-	static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER;
-	static DeclareMemType MTYPE_VERTEX_SET_STRIDE;
-	static DeclareMemType MTYPE_VERTEX_SET_BUFFER;
-	static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER;
-	static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS;
-
-	static DeclareMemType MTYPE_SPACE_PARTITION;
-
-	static DeclareMemType MTYPE_PIPELINE;
-	static DeclareMemType MTYPE_PIPELINE_INIT;
-	static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS;
-	static DeclareMemType MTYPE_PIPELINE_RESTORE_GL;
-	static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS;
-	static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL;
-	static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE;
-	static DeclareMemType MTYPE_PIPELINE_ADD_POOL;
-	static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE;
-	static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT;
-	static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS;
-	static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE;
-	static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM;
-	static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE;
-	static DeclareMemType MTYPE_PIPELINE_MARK_MOVED;
-	static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT;
-	static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS;
-	static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED;
-	static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD;
-	static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL;
-	static DeclareMemType MTYPE_PIPELINE_STATE_SORT;
-	static DeclareMemType MTYPE_PIPELINE_POST_SORT;
-	
-	static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS;
-	static DeclareMemType MTYPE_PIPELINE_RENDER_HL;
-	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM;
-	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED;
-	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF;
-	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW;
-	static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT;
-	static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS;
-	static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP;
-	static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS;
-	static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR;
-	static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM;
-
-	static DeclareMemType MTYPE_UPKEEP_POOLS;
-
-	static DeclareMemType MTYPE_AVATAR;
-	static DeclareMemType MTYPE_AVATAR_MESH;
-	static DeclareMemType MTYPE_PARTICLES;
-	static DeclareMemType MTYPE_REGIONS;
-
-	static DeclareMemType MTYPE_INVENTORY;
-	static DeclareMemType MTYPE_INVENTORY_DRAW;
-	static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS;
-	static DeclareMemType MTYPE_INVENTORY_DO_FOLDER;
-	static DeclareMemType MTYPE_INVENTORY_POST_BUILD;
-	static DeclareMemType MTYPE_INVENTORY_FROM_XML;
-	static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM;
-	static DeclareMemType MTYPE_INVENTORY_VIEW_INIT;
-	static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW;
-	static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE;
-
-	static DeclareMemType MTYPE_ANIMATION;
-	static DeclareMemType MTYPE_VOLUME;
-	static DeclareMemType MTYPE_PRIMITIVE;
-	
-	static DeclareMemType MTYPE_SCRIPT;
-	static DeclareMemType MTYPE_SCRIPT_RUN;
-	static DeclareMemType MTYPE_SCRIPT_BYTECODE;
-	
-	static DeclareMemType MTYPE_IO_PUMP;
-	static DeclareMemType MTYPE_IO_TCP;
-	static DeclareMemType MTYPE_IO_BUFFER;
-	static DeclareMemType MTYPE_IO_HTTP_SERVER;
-	static DeclareMemType MTYPE_IO_SD_SERVER;
-	static DeclareMemType MTYPE_IO_SD_CLIENT;
-	static DeclareMemType MTYPE_IO_URL_REQUEST;
-
-	static DeclareMemType MTYPE_DIRECTX_INIT;
-
-	static DeclareMemType MTYPE_TEMP1;
-	static DeclareMemType MTYPE_TEMP2;
-	static DeclareMemType MTYPE_TEMP3;
-	static DeclareMemType MTYPE_TEMP4;
-	static DeclareMemType MTYPE_TEMP5;
-	static DeclareMemType MTYPE_TEMP6;
-	static DeclareMemType MTYPE_TEMP7;
-	static DeclareMemType MTYPE_TEMP8;
-	static DeclareMemType MTYPE_TEMP9;
-
-	static DeclareMemType MTYPE_OTHER; // Special; used by display code
-
-	S32 mTypeIndex;
-};
-
-//----------------------------------------------------------------------------
-
-#endif
-
+/** 
+ * @file llmemtype.h
+ * @brief Runtime memory usage debugging utilities.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ * 
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_MEMTYPE_H
+#define LL_MEMTYPE_H
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+
+#include "linden_common.h"
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// WARNING: Never commit with MEM_TRACK_MEM == 1
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#define MEM_TRACK_MEM (0 && LL_WINDOWS)
+
+#include <vector>
+
+#define MEM_TYPE_NEW(T)
+
+class LL_COMMON_API LLMemType
+{
+public:
+
+	// class we'll initialize all instances of as
+	// static members of MemType.  Then use
+	// to construct any new mem type.
+	class LL_COMMON_API DeclareMemType
+	{
+	public:
+		DeclareMemType(char const * st);
+		~DeclareMemType();
+	
+		S32 mID;
+		char const * mName;
+		
+		// array so we can map an index ID to Name
+		static std::vector<char const *> mNameList;
+	};
+
+	LLMemType(DeclareMemType& dt);
+	~LLMemType();
+
+	static char const * getNameFromID(S32 id);
+
+	static DeclareMemType MTYPE_INIT;
+	static DeclareMemType MTYPE_STARTUP;
+	static DeclareMemType MTYPE_MAIN;
+	static DeclareMemType MTYPE_FRAME;
+
+	static DeclareMemType MTYPE_GATHER_INPUT;
+	static DeclareMemType MTYPE_JOY_KEY;
+
+	static DeclareMemType MTYPE_IDLE;
+	static DeclareMemType MTYPE_IDLE_PUMP;
+	static DeclareMemType MTYPE_IDLE_NETWORK;
+	static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS;
+	static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION;
+	static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE;
+	static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY;
+	static DeclareMemType MTYPE_IDLE_AUDIO;
+
+	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING;
+	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS;
+	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES;
+
+	static DeclareMemType MTYPE_MESSAGE_CHECK_ALL;
+	static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS;
+
+	static DeclareMemType MTYPE_RENDER;
+	static DeclareMemType MTYPE_SLEEP;
+
+	static DeclareMemType MTYPE_NETWORK;
+	static DeclareMemType MTYPE_PHYSICS;
+	static DeclareMemType MTYPE_INTERESTLIST;
+
+	static DeclareMemType MTYPE_IMAGEBASE;
+	static DeclareMemType MTYPE_IMAGERAW;
+	static DeclareMemType MTYPE_IMAGEFORMATTED;
+	
+	static DeclareMemType MTYPE_APPFMTIMAGE;
+	static DeclareMemType MTYPE_APPRAWIMAGE;
+	static DeclareMemType MTYPE_APPAUXRAWIMAGE;
+	
+	static DeclareMemType MTYPE_DRAWABLE;
+	
+	static DeclareMemType MTYPE_OBJECT;
+	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE;
+	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE;
+
+	static DeclareMemType MTYPE_DISPLAY;
+	static DeclareMemType MTYPE_DISPLAY_UPDATE;
+	static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA;
+	static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM;
+	static DeclareMemType MTYPE_DISPLAY_SWAP;
+	static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD;
+	static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION;
+	static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE;
+	static DeclareMemType MTYPE_DISPLAY_STATE_SORT;
+	static DeclareMemType MTYPE_DISPLAY_SKY;
+	static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM;
+	static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH;
+	static DeclareMemType MTYPE_DISPLAY_RENDER_UI;
+	static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS;
+
+	static DeclareMemType MTYPE_VERTEX_DATA;
+	static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR;
+	static DeclareMemType MTYPE_VERTEX_DESTRUCTOR;
+	static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES;
+	static DeclareMemType MTYPE_VERTEX_CREATE_INDICES;
+	static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER;	
+	static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES;
+	static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS;
+	static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES;
+	static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER;
+	static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER;
+	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER;
+	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES;
+	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES;
+	static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER;
+	static DeclareMemType MTYPE_VERTEX_SET_STRIDE;
+	static DeclareMemType MTYPE_VERTEX_SET_BUFFER;
+	static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER;
+	static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS;
+
+	static DeclareMemType MTYPE_SPACE_PARTITION;
+
+	static DeclareMemType MTYPE_PIPELINE;
+	static DeclareMemType MTYPE_PIPELINE_INIT;
+	static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS;
+	static DeclareMemType MTYPE_PIPELINE_RESTORE_GL;
+	static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS;
+	static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL;
+	static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE;
+	static DeclareMemType MTYPE_PIPELINE_ADD_POOL;
+	static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE;
+	static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT;
+	static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS;
+	static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE;
+	static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM;
+	static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE;
+	static DeclareMemType MTYPE_PIPELINE_MARK_MOVED;
+	static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT;
+	static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS;
+	static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED;
+	static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD;
+	static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL;
+	static DeclareMemType MTYPE_PIPELINE_STATE_SORT;
+	static DeclareMemType MTYPE_PIPELINE_POST_SORT;
+	
+	static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS;
+	static DeclareMemType MTYPE_PIPELINE_RENDER_HL;
+	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM;
+	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED;
+	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF;
+	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW;
+	static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT;
+	static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS;
+	static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP;
+	static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS;
+	static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR;
+	static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM;
+
+	static DeclareMemType MTYPE_UPKEEP_POOLS;
+
+	static DeclareMemType MTYPE_AVATAR;
+	static DeclareMemType MTYPE_AVATAR_MESH;
+	static DeclareMemType MTYPE_PARTICLES;
+	static DeclareMemType MTYPE_REGIONS;
+
+	static DeclareMemType MTYPE_INVENTORY;
+	static DeclareMemType MTYPE_INVENTORY_DRAW;
+	static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS;
+	static DeclareMemType MTYPE_INVENTORY_DO_FOLDER;
+	static DeclareMemType MTYPE_INVENTORY_POST_BUILD;
+	static DeclareMemType MTYPE_INVENTORY_FROM_XML;
+	static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM;
+	static DeclareMemType MTYPE_INVENTORY_VIEW_INIT;
+	static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW;
+	static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE;
+
+	static DeclareMemType MTYPE_ANIMATION;
+	static DeclareMemType MTYPE_VOLUME;
+	static DeclareMemType MTYPE_PRIMITIVE;
+	
+	static DeclareMemType MTYPE_SCRIPT;
+	static DeclareMemType MTYPE_SCRIPT_RUN;
+	static DeclareMemType MTYPE_SCRIPT_BYTECODE;
+	
+	static DeclareMemType MTYPE_IO_PUMP;
+	static DeclareMemType MTYPE_IO_TCP;
+	static DeclareMemType MTYPE_IO_BUFFER;
+	static DeclareMemType MTYPE_IO_HTTP_SERVER;
+	static DeclareMemType MTYPE_IO_SD_SERVER;
+	static DeclareMemType MTYPE_IO_SD_CLIENT;
+	static DeclareMemType MTYPE_IO_URL_REQUEST;
+
+	static DeclareMemType MTYPE_DIRECTX_INIT;
+
+	static DeclareMemType MTYPE_TEMP1;
+	static DeclareMemType MTYPE_TEMP2;
+	static DeclareMemType MTYPE_TEMP3;
+	static DeclareMemType MTYPE_TEMP4;
+	static DeclareMemType MTYPE_TEMP5;
+	static DeclareMemType MTYPE_TEMP6;
+	static DeclareMemType MTYPE_TEMP7;
+	static DeclareMemType MTYPE_TEMP8;
+	static DeclareMemType MTYPE_TEMP9;
+
+	static DeclareMemType MTYPE_OTHER; // Special; used by display code
+
+	S32 mTypeIndex;
+};
+
+//----------------------------------------------------------------------------
+
+#endif
+
diff --git a/indra/llcommon/llmetrics.h b/indra/llcommon/llmetrics.h
index 1d91e8c8a287c618c8bec4e42b5191d22976616d..f6f49eb4562b2f70ced98d14ffd0f9703f86aa34 100644
--- a/indra/llcommon/llmetrics.h
+++ b/indra/llcommon/llmetrics.h
@@ -38,7 +38,7 @@
 class LLMetricsImpl;
 class LLSD;
 
-class LLMetrics
+class LL_COMMON_API LLMetrics
 {
 public:
 	LLMetrics();
diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h
index fcda3df58e3eae9e5865d790ec6a4b010a6d9b8f..27bd8cd9b5c2ef2962e659ab26cd1d4d5a84ba1c 100644
--- a/indra/llcommon/llmortician.h
+++ b/indra/llcommon/llmortician.h
@@ -35,7 +35,7 @@
 
 #include "stdtypes.h"
 
-class LLMortician 
+class LL_COMMON_API LLMortician 
 {
 public:
 	LLMortician() { mIsDead = FALSE; }
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index bb598a2be1b494b5a314a147bae81912af2a722e..48baa50edbe809cd5a8c4f850966f281ea5f7955 100644
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -1,142 +1,168 @@
-/** 
- * @file llpreprocessor.h
- * @brief This file should be included in all Linden Lab files and
- * should only contain special preprocessor directives
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
- * Copyright (c) 2001-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LLPREPROCESSOR_H
-#define LLPREPROCESSOR_H
-
-// Figure out endianness of platform
-#ifdef LL_LINUX
-#define __ENABLE_WSTRING
-#include <endian.h>
-#endif	//	LL_LINUX
-
-#if LL_SOLARIS
-#   ifdef  __sparc     // Since we're talking Solaris 10 and up, only 64 bit is supported.
-#      define LL_BIG_ENDIAN 1
-#      define LL_SOLARIS_ALIGNED_CPU 1     //  used to designate issues where SPARC alignment is addressed
-#      define LL_SOLARIS_NON_MESA_GL 1      //  The SPARC GL does not provide a MESA-based GL API
-#   endif
-#   include <sys/isa_defs.h> // ensure we know which end is up
-#endif // LL_SOLARIS
-
-#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(LL_SOLARIS) && defined(__i386)))
-#define LL_LITTLE_ENDIAN 1
-#else
-#define LL_BIG_ENDIAN 1
-#endif
-
-// Per-compiler switches
-#ifdef __GNUC__
-#define LL_FORCE_INLINE inline __attribute__((always_inline))
-#else
-#define LL_FORCE_INLINE __forceinline
-#endif
-
-// Figure out differences between compilers
-#if defined(__GNUC__)
-	#define GCC_VERSION (__GNUC__ * 10000 \
-						+ __GNUC_MINOR__ * 100 \
-						+ __GNUC_PATCHLEVEL__)
-	#ifndef LL_GNUC
-		#define LL_GNUC 1
-	#endif
-#elif defined(__MSVC_VER__) || defined(_MSC_VER)
-	#ifndef LL_MSVC
-		#define LL_MSVC 1
-	#endif
-	#if _MSC_VER < 1400
-		#define LL_MSVC7 //Visual C++ 2003 or earlier
-	#endif
-#endif
-
-// Deal with minor differences on Unixy OSes.
-#if LL_DARWIN || LL_LINUX
-	// Different name, same functionality.
-	#define stricmp strcasecmp
-	#define strnicmp strncasecmp
-
-	// Not sure why this is different, but...
-	#ifndef MAX_PATH
-		#define MAX_PATH PATH_MAX
-	#endif	//	not MAX_PATH
-
-#endif
-
-
-// Deal with the differeneces on Windows
-#if LL_MSVC
-namespace snprintf_hack
-{
-	int snprintf(char *str, size_t size, const char *format, ...);
-}
-
-// #define snprintf safe_snprintf		/* Flawfinder: ignore */
-using snprintf_hack::snprintf;
-#endif	// LL_MSVC
-
-// Static linking with apr on windows needs to be declared.
-#ifdef LL_WINDOWS
-#ifndef APR_DECLARE_STATIC
-#define APR_DECLARE_STATIC // For APR on Windows
-#endif
-#ifndef APU_DECLARE_STATIC
-#define APU_DECLARE_STATIC // For APR util on Windows
-#endif
-#endif
-
-#if defined(LL_WINDOWS)
-#define BOOST_REGEX_NO_LIB 1
-#define CURL_STATICLIB 1
-#ifndef XML_STATIC
-#define XML_STATIC
-#endif
-#endif	//	LL_WINDOWS
-
-
-// Deal with VC6 problems
-#if LL_MSVC
-#pragma warning( 3	     : 4701 )	// "local variable used without being initialized"  Treat this as level 3, not level 4.
-#pragma warning( 3	     : 4702 )	// "unreachable code"  Treat this as level 3, not level 4.
-#pragma warning( 3	     : 4189 )	// "local variable initialized but not referenced"  Treat this as level 3, not level 4.
-//#pragma warning( 3	: 4018 )	// "signed/unsigned mismatch"  Treat this as level 3, not level 4.
-#pragma warning( 3      :  4263 )	// 'function' : member function does not override any base class virtual member function
-#pragma warning( 3      :  4264 )	// "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden"
-#pragma warning( 3       : 4265 )	// "class has virtual functions, but destructor is not virtual"
-#pragma warning( 3      :  4266 )	// 'function' : no override available for virtual member function from base 'type'; function is hidden
-#pragma warning( disable : 4284 )	// silly MS warning deep inside their <map> include file
-#pragma warning( disable : 4503 )	// 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
-#pragma warning( disable : 4800 )	// 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
-#pragma warning( disable : 4996 )	// warning: deprecated
-#endif	//	LL_MSVC
-
-#endif	//	not LL_LINDEN_PREPROCESSOR_H
+/** 
+ * @file llpreprocessor.h
+ * @brief This file should be included in all Linden Lab files and
+ * should only contain special preprocessor directives
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLPREPROCESSOR_H
+#define LLPREPROCESSOR_H
+
+// Figure out endianness of platform
+#ifdef LL_LINUX
+#define __ENABLE_WSTRING
+#include <endian.h>
+#endif	//	LL_LINUX
+
+#if LL_SOLARIS
+#   ifdef  __sparc     // Since we're talking Solaris 10 and up, only 64 bit is supported.
+#      define LL_BIG_ENDIAN 1
+#      define LL_SOLARIS_ALIGNED_CPU 1     //  used to designate issues where SPARC alignment is addressed
+#      define LL_SOLARIS_NON_MESA_GL 1      //  The SPARC GL does not provide a MESA-based GL API
+#   endif
+#   include <sys/isa_defs.h> // ensure we know which end is up
+#endif // LL_SOLARIS
+
+#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(LL_SOLARIS) && defined(__i386)))
+#define LL_LITTLE_ENDIAN 1
+#else
+#define LL_BIG_ENDIAN 1
+#endif
+
+// Per-compiler switches
+#ifdef __GNUC__
+#define LL_FORCE_INLINE inline __attribute__((always_inline))
+#else
+#define LL_FORCE_INLINE __forceinline
+#endif
+
+// Figure out differences between compilers
+#if defined(__GNUC__)
+	#define GCC_VERSION (__GNUC__ * 10000 \
+						+ __GNUC_MINOR__ * 100 \
+						+ __GNUC_PATCHLEVEL__)
+	#ifndef LL_GNUC
+		#define LL_GNUC 1
+	#endif
+#elif defined(__MSVC_VER__) || defined(_MSC_VER)
+	#ifndef LL_MSVC
+		#define LL_MSVC 1
+	#endif
+	#if _MSC_VER < 1400
+		#define LL_MSVC7 //Visual C++ 2003 or earlier
+	#endif
+#endif
+
+// Deal with minor differences on Unixy OSes.
+#if LL_DARWIN || LL_LINUX
+	// Different name, same functionality.
+	#define stricmp strcasecmp
+	#define strnicmp strncasecmp
+
+	// Not sure why this is different, but...
+	#ifndef MAX_PATH
+		#define MAX_PATH PATH_MAX
+	#endif	//	not MAX_PATH
+
+#endif
+
+
+// Static linking with apr on windows needs to be declared.
+#if LL_WINDOWS && !LL_COMMON_LINK_SHARED
+#ifndef APR_DECLARE_STATIC
+#define APR_DECLARE_STATIC // For APR on Windows
+#endif
+#ifndef APU_DECLARE_STATIC
+#define APU_DECLARE_STATIC // For APR util on Windows
+#endif
+#endif
+
+#if defined(LL_WINDOWS)
+#define BOOST_REGEX_NO_LIB 1
+#define CURL_STATICLIB 1
+#ifndef XML_STATIC
+#define XML_STATIC
+#endif
+#endif	//	LL_WINDOWS
+
+
+// Deal with VC6 problems
+#if LL_MSVC
+#pragma warning( 3	     : 4701 )	// "local variable used without being initialized"  Treat this as level 3, not level 4.
+#pragma warning( 3	     : 4702 )	// "unreachable code"  Treat this as level 3, not level 4.
+#pragma warning( 3	     : 4189 )	// "local variable initialized but not referenced"  Treat this as level 3, not level 4.
+//#pragma warning( 3	: 4018 )	// "signed/unsigned mismatch"  Treat this as level 3, not level 4.
+#pragma warning( 3      :  4263 )	// 'function' : member function does not override any base class virtual member function
+#pragma warning( 3      :  4264 )	// "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden"
+#pragma warning( 3       : 4265 )	// "class has virtual functions, but destructor is not virtual"
+#pragma warning( 3      :  4266 )	// 'function' : no override available for virtual member function from base 'type'; function is hidden
+#pragma warning( disable : 4284 )	// silly MS warning deep inside their <map> include file
+#pragma warning( disable : 4503 )	// 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
+#pragma warning( disable : 4800 )	// 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
+#pragma warning( disable : 4996 )	// warning: deprecated
+
+// level 4 warnings that we need to disable:
+#pragma warning (disable : 4100) // unreferenced formal parameter
+#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) )
+#pragma warning (disable : 4244) // possible loss of data on conversions
+#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
+#pragma warning (disable : 4512) // assignment operator could not be generated
+#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) )
+
+#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class
+#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class
+#endif	//	LL_MSVC
+
+#if LL_WINDOWS
+#define LL_DLLEXPORT __declspec(dllexport)
+#define LL_DLLIMPORT __declspec(dllimport)
+#elif LL_LINUX
+#define LL_DLLEXPORT __attribute__ ((visibility("default")))
+#define LL_DLLIMPORT
+#else
+#define LL_DLLEXPORT
+#define LL_DLLIMPORT
+#endif // LL_WINDOWS
+
+#if LL_COMMON_LINK_SHARED
+// CMake automagically defines llcommon_EXPORTS only when building llcommon
+// sources, and only when llcommon is a shared library (i.e. when
+// LL_COMMON_LINK_SHARED). We must still test LL_COMMON_LINK_SHARED because
+// otherwise we can't distinguish between (non-llcommon source) and (llcommon
+// not shared).
+# if defined(llcommon_EXPORTS)
+#   define LL_COMMON_API LL_DLLEXPORT
+# else //llcommon_EXPORTS
+#   define LL_COMMON_API LL_DLLIMPORT
+# endif //llcommon_EXPORTS
+#else // LL_COMMON_LINK_SHARED
+# define LL_COMMON_API
+#endif // LL_COMMON_LINK_SHARED
+
+#endif	//	not LL_LINDEN_PREPROCESSOR_H
diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h
index a1b8e22691f4137fbde0e11338c77762d83c8222..880562157fbcdb6f4f6cd8a8481ec6e4993d71c6 100644
--- a/indra/llcommon/llprocesslauncher.h
+++ b/indra/llcommon/llprocesslauncher.h
@@ -42,7 +42,7 @@
 	It also keeps track of whether the process is still running, and can kill it if required.
 */
 
-class LLProcessLauncher
+class LL_COMMON_API LLProcessLauncher
 {
 	LOG_CLASS(LLProcessLauncher);
 public:
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index 3ba43e1e070db57c3ffa3d7b15744163e45b3988..8bfa5632a162ee4da4f0cd8587bb316c6914fe76 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -47,7 +47,7 @@
 // Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small
 //   It is assumed that LLQueuedThreads are rarely created/destroyed.
 
-class LLQueuedThread : public LLThread
+class LL_COMMON_API LLQueuedThread : public LLThread
 {
 	//------------------------------------------------------------------------
 public:
@@ -80,7 +80,7 @@ class LLQueuedThread : public LLThread
 	//------------------------------------------------------------------------
 public:
 
-	class QueuedRequest : public LLSimpleHashEntry<handle_t>
+	class LL_COMMON_API QueuedRequest : public LLSimpleHashEntry<handle_t>
 	{
 		friend class LLQueuedThread;
 		
@@ -148,6 +148,7 @@ class LLQueuedThread : public LLThread
 		}
 	};
 
+
 	//------------------------------------------------------------------------
 	
 public:
diff --git a/indra/llcommon/llrand.h b/indra/llcommon/llrand.h
index d12597bb53e727f714c45f532ff38f5fc5e4b2df..30fec9b982b25234f7139bd3753b57230a22cf6a 100644
--- a/indra/llcommon/llrand.h
+++ b/indra/llcommon/llrand.h
@@ -65,32 +65,32 @@
 /**
  *@brief Generate a float from [0, RAND_MAX).
  */
-S32 ll_rand();
+S32 LL_COMMON_API ll_rand();
 
 /**
  *@brief Generate a float from [0, val) or (val, 0].
  */
-S32 ll_rand(S32 val);
+S32 LL_COMMON_API ll_rand(S32 val);
 
 /**
  *@brief Generate a float from [0, 1.0).
  */
-F32 ll_frand();
+F32 LL_COMMON_API ll_frand();
 
 /**
  *@brief Generate a float from [0, val) or (val, 0].
  */
-F32 ll_frand(F32 val);
+F32 LL_COMMON_API ll_frand(F32 val);
 
 /**
  *@brief Generate a double from [0, 1.0).
  */
-F64 ll_drand();
+F64 LL_COMMON_API ll_drand();
 
 /**
  *@brief Generate a double from [0, val) or (val, 0].
  */
-F64 ll_drand(F64 val);
+F64 LL_COMMON_API ll_drand(F64 val);
 
 /**
  * @brief typedefs for good boost lagged fibonacci.
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index d3597b454c87885f8fa449bd2c6651ba75feaab7..9ab844eb22ee03ff8647b9d736f226c72f5d2763 100644
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -39,9 +39,9 @@
 // see llthread.h for LLThreadSafeRefCount
 //----------------------------------------------------------------------------
 
-class LLRefCount
+class LL_COMMON_API LLRefCount
 {
-protected:
+private:
 	LLRefCount(const LLRefCount& other); // no implementation
 private:
 	LLRefCount& operator=(const LLRefCount&); // no implementation
diff --git a/indra/llcommon/llrun.h b/indra/llcommon/llrun.h
index 77b23d9051f1ffa0fe60e9c6d4a6d2d50ac1b6d9..1fc9925df9ca15c447c9d03bb29b31061d559b00 100644
--- a/indra/llcommon/llrun.h
+++ b/indra/llcommon/llrun.h
@@ -48,7 +48,7 @@ class LLRunnable;
  * which are scheduled to run on a repeating or one time basis.
  * @see LLRunnable
  */
-class LLRunner
+class LL_COMMON_API LLRunner
 {
 public:
 	/**
@@ -149,7 +149,7 @@ class LLRunner
  * something useful.
  * @see LLRunner
  */
-class LLRunnable
+class LL_COMMON_API LLRunnable
 {
 public:
 	LLRunnable();
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index d2845a3757e205dbd06cbbcb0b6a740f0b1cca7f..552bb57498e6280407fe02d4181d2fea920aed0a 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -89,7 +89,7 @@
 	@nosubgrouping
 */
 
-class LLSD
+class LL_COMMON_API LLSD
 {
 public:
 		LLSD();		///< initially Undefined
@@ -387,7 +387,7 @@ struct llsd_select_string : public std::unary_function<LLSD, LLSD::String>
 	}
 };
 
-std::ostream& operator<<(std::ostream& s, const LLSD& llsd);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLSD& llsd);
 
 /** QUESTIONS & TO DOS
 	- Would Binary be more convenient as usigned char* buffer semantics?
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 7463d1e5ddd345067d3ee7d2335ff9b1e84678a9..2f2b292189bf099373899d3eb48d0ddddc16d74c 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -44,7 +44,7 @@
  * @class LLSDParser
  * @brief Abstract base class for LLSD parsers.
  */
-class LLSDParser : public LLRefCount
+class LL_COMMON_API LLSDParser : public LLRefCount
 {
 protected:
 	/** 
@@ -221,7 +221,7 @@ class LLSDParser : public LLRefCount
  * @class LLSDNotationParser
  * @brief Parser which handles the original notation format for LLSD.
  */
-class LLSDNotationParser : public LLSDParser
+class LL_COMMON_API LLSDNotationParser : public LLSDParser
 {
 protected:
 	/** 
@@ -294,7 +294,7 @@ class LLSDNotationParser : public LLSDParser
  * @class LLSDXMLParser
  * @brief Parser which handles XML format LLSD.
  */
-class LLSDXMLParser : public LLSDParser
+class LL_COMMON_API LLSDXMLParser : public LLSDParser
 {
 protected:
 	/** 
@@ -342,7 +342,7 @@ class LLSDXMLParser : public LLSDParser
  * @class LLSDBinaryParser
  * @brief Parser which handles binary formatted LLSD.
  */
-class LLSDBinaryParser : public LLSDParser
+class LL_COMMON_API LLSDBinaryParser : public LLSDParser
 {
 protected:
 	/** 
@@ -407,7 +407,7 @@ class LLSDBinaryParser : public LLSDParser
  * @class LLSDFormatter
  * @brief Abstract base class for formatting LLSD.
  */
-class LLSDFormatter : public LLRefCount
+class LL_COMMON_API LLSDFormatter : public LLRefCount
 {
 protected:
 	/** 
@@ -479,7 +479,7 @@ class LLSDFormatter : public LLRefCount
  * @class LLSDNotationFormatter
  * @brief Formatter which outputs the original notation format for LLSD.
  */
-class LLSDNotationFormatter : public LLSDFormatter
+class LL_COMMON_API LLSDNotationFormatter : public LLSDFormatter
 {
 protected:
 	/** 
@@ -520,7 +520,7 @@ class LLSDNotationFormatter : public LLSDFormatter
  * @class LLSDXMLFormatter
  * @brief Formatter which outputs the LLSD as XML.
  */
-class LLSDXMLFormatter : public LLSDFormatter
+class LL_COMMON_API LLSDXMLFormatter : public LLSDFormatter
 {
 protected:
 	/** 
@@ -588,7 +588,7 @@ class LLSDXMLFormatter : public LLSDFormatter
  * Map: '{' + 4 byte integer size  every(key + value) + '}'<br>
  *  map keys are serialized as 'k' + 4 byte integer size + string
  */
-class LLSDBinaryFormatter : public LLSDFormatter
+class LL_COMMON_API LLSDBinaryFormatter : public LLSDFormatter
 {
 protected:
 	/** 
@@ -638,9 +638,14 @@ class LLSDBinaryFormatter : public LLSDFormatter
  *	params << "[{'version':i1}," << LLSDOStreamer<LLSDNotationFormatter>(sd)
  *    << "]";
  *  </code>
+ *
+ * *NOTE - formerly this class inherited from its template parameter Formatter,
+ * but all insnatiations passed in LLRefCount subclasses.  This conflicted with
+ * the auto allocation intended for this class template (demonstrated in the
+ * example above).  -brad
  */
 template <class Formatter>
-class LLSDOStreamer : public Formatter
+class LLSDOStreamer
 {
 public:
 	/** 
@@ -661,7 +666,8 @@ class LLSDOStreamer : public Formatter
 		std::ostream& str,
 		const LLSDOStreamer<Formatter>& formatter)
 	{
-		formatter.format(formatter.mSD, str, formatter.mOptions);
+		LLPointer<Formatter> f = new Formatter;
+		f->format(formatter.mSD, str, formatter.mOptions);
 		return str;
 	}
 
@@ -677,7 +683,7 @@ typedef LLSDOStreamer<LLSDXMLFormatter>			LLSDXMLStreamer;
  * @class LLSDSerialize
  * @brief Serializer / deserializer for the various LLSD formats
  */
-class LLSDSerialize
+class LL_COMMON_API LLSDSerialize
 {
 public:
 	enum ELLSD_Serialize
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index c12ca350de53f301860ed57bd42c2f8e323a82fc..7e1c2e35e0da678d2fdf7d0acbfde9c001fa6173 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -37,6 +37,7 @@
 #include <deque>
 
 #include "apr_base64.h"
+#include <boost/regex.hpp>
 
 extern "C"
 {
@@ -777,10 +778,17 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
 		
 		case ELEMENT_BINARY:
 		{
-			S32 len = apr_base64_decode_len(mCurrentContent.c_str());
+			// Regex is expensive, but only fix for whitespace in base64,
+			// created by python and other non-linden systems - DEV-39358
+			// Fortunately we have very little binary passing now,
+			// so performance impact shold be negligible. + poppy 2009-09-04
+			boost::regex r;
+			r.assign("\\s");
+			std::string stripped = boost::regex_replace(mCurrentContent, r, "");
+			S32 len = apr_base64_decode_len(stripped.c_str());
 			std::vector<U8> data;
 			data.resize(len);
-			len = apr_base64_decode_binary(&data[0], mCurrentContent.c_str());
+			len = apr_base64_decode_binary(&data[0], stripped.c_str());
 			data.resize(len);
 			value = data;
 			break;
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 0202a033c3ccab7d5bd87f7d11701ad62f20d07c..c8d8030e87550363bdb0e46e5b9be14a2d20003d 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -46,6 +46,11 @@
 #endif
 
 #include "llsdserialize.h"
+#include "stringize.h"
+
+#include <map>
+#include <set>
+#include <boost/range.hpp>
 
 // U32
 LLSD ll_sd_from_U32(const U32 val)
@@ -313,3 +318,353 @@ BOOL compare_llsd_with_template(
 
 	return TRUE;
 }
+
+/*****************************************************************************
+*   Helpers for llsd_matches()
+*****************************************************************************/
+// raw data used for LLSD::Type lookup
+struct Data
+{
+    LLSD::Type type;
+    const char* name;
+} typedata[] =
+{
+#define def(type) { LLSD::type, #type + 4 }
+    def(TypeUndefined),
+    def(TypeBoolean),
+    def(TypeInteger),
+    def(TypeReal),
+    def(TypeString),
+    def(TypeUUID),
+    def(TypeDate),
+    def(TypeURI),
+    def(TypeBinary),
+    def(TypeMap),
+    def(TypeArray)
+#undef  def
+};
+
+// LLSD::Type lookup class into which we load the above static data
+class TypeLookup
+{
+    typedef std::map<LLSD::Type, std::string> MapType;
+
+public:
+    TypeLookup()
+    {
+        for (const Data *di(boost::begin(typedata)), *dend(boost::end(typedata)); di != dend; ++di)
+        {
+            mMap[di->type] = di->name;
+        }
+    }
+
+    std::string lookup(LLSD::Type type) const
+    {
+        MapType::const_iterator found = mMap.find(type);
+        if (found != mMap.end())
+        {
+            return found->second;
+        }
+        return STRINGIZE("<unknown LLSD type " << type << ">");
+    }
+
+private:
+    MapType mMap;
+};
+
+// static instance of the lookup class
+static const TypeLookup sTypes;
+
+// describe a mismatch; phrasing may want tweaking
+const std::string op(" required instead of ");
+
+// llsd_matches() wants to identify specifically where in a complex prototype
+// structure the mismatch occurred. This entails passing a prefix string,
+// empty for the top-level call. If the prototype contains an array of maps,
+// and the mismatch occurs in the second map in a key 'foo', we want to
+// decorate the returned string with: "[1]['foo']: etc." On the other hand, we
+// want to omit the entire prefix -- including colon -- if the mismatch is at
+// top level. This helper accepts the (possibly empty) recursively-accumulated
+// prefix string, returning either empty or the original string with colon
+// appended.
+static std::string colon(const std::string& pfx)
+{
+    if (pfx.empty())
+        return pfx;
+    return pfx + ": ";
+}
+
+// param type for match_types
+typedef std::vector<LLSD::Type> TypeVector;
+
+// The scalar cases in llsd_matches() use this helper. In most cases, we can
+// accept not only the exact type specified in the prototype, but also other
+// types convertible to the expected type. That implies looping over an array
+// of such types. If the actual type doesn't match any of them, we want to
+// provide a list of acceptable conversions as well as the exact type, e.g.:
+// "Integer (or Boolean, Real, String) required instead of UUID". Both the
+// implementation and the calling logic are simplified by separating out the
+// expected type from the convertible types.
+static std::string match_types(LLSD::Type expect, // prototype.type()
+                               const TypeVector& accept, // types convertible to that type
+                               LLSD::Type actual,        // type we're checking
+                               const std::string& pfx)   // as for llsd_matches
+{
+    // Trivial case: if the actual type is exactly what we expect, we're good.
+    if (actual == expect)
+        return "";
+
+    // For the rest of the logic, build up a suitable error string as we go so
+    // we only have to make a single pass over the list of acceptable types.
+    // If we detect success along the way, we'll simply discard the partial
+    // error string.
+    std::ostringstream out;
+    out << colon(pfx) << sTypes.lookup(expect);
+
+    // If there are any convertible types, append that list.
+    if (! accept.empty())
+    {
+        out << " (";
+        const char* sep = "or ";
+        for (TypeVector::const_iterator ai(accept.begin()), aend(accept.end());
+             ai != aend; ++ai, sep = ", ")
+        {
+            // Don't forget to return success if we match any of those types...
+            if (actual == *ai)
+                return "";
+            out << sep << sTypes.lookup(*ai);
+        }
+        out << ')';
+    }
+    // If we got this far, it's because 'actual' was not one of the acceptable
+    // types, so we must return an error. 'out' already contains colon(pfx)
+    // and the formatted list of acceptable types, so just append the mismatch
+    // phrase and the actual type.
+    out << op << sTypes.lookup(actual);
+    return out.str();
+}
+
+// see docstring in .h file
+std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx)
+{
+    // An undefined prototype means that any data is valid.
+    // An undefined slot in an array or map prototype means that any data
+    // may fill that slot.
+    if (prototype.isUndefined())
+        return "";
+    // A prototype array must match a data array with at least as many
+    // entries. Moreover, every prototype entry must match the
+    // corresponding data entry.
+    if (prototype.isArray())
+    {
+        if (! data.isArray())
+        {
+            return STRINGIZE(colon(pfx) << "Array" << op << sTypes.lookup(data.type()));
+        }
+        if (data.size() < prototype.size())
+        {
+            return STRINGIZE(colon(pfx) << "Array size " << prototype.size() << op
+                             << "Array size " << data.size());
+        }
+        for (LLSD::Integer i = 0; i < prototype.size(); ++i)
+        {
+            std::string match(llsd_matches(prototype[i], data[i], STRINGIZE('[' << i << ']')));
+            if (! match.empty())
+            {
+                return match;
+            }
+        }
+        return "";
+    }
+    // A prototype map must match a data map. Every key in the prototype
+    // must have a corresponding key in the data map; every value in the
+    // prototype must match the corresponding key's value in the data.
+    if (prototype.isMap())
+    {
+        if (! data.isMap())
+        {
+            return STRINGIZE(colon(pfx) << "Map" << op << sTypes.lookup(data.type()));
+        }
+        // If there are a number of keys missing from the data, it would be
+        // frustrating to a coder to discover them one at a time, with a big
+        // build each time. Enumerate all missing keys.
+        std::ostringstream out;
+        out << colon(pfx);
+        const char* init = "Map missing keys: ";
+        const char* sep = init;
+        for (LLSD::map_const_iterator mi = prototype.beginMap(); mi != prototype.endMap(); ++mi)
+        {
+            if (! data.has(mi->first))
+            {
+                out << sep << mi->first;
+                sep = ", ";
+            }
+        }
+        // So... are we missing any keys?
+        if (sep != init)
+        {
+            return out.str();
+        }
+        // Good, the data block contains all the keys required by the
+        // prototype. Now match the prototype entries.
+        for (LLSD::map_const_iterator mi2 = prototype.beginMap(); mi2 != prototype.endMap(); ++mi2)
+        {
+            std::string match(llsd_matches(mi2->second, data[mi2->first],
+                                           STRINGIZE("['" << mi2->first << "']")));
+            if (! match.empty())
+            {
+                return match;
+            }
+        }
+        return "";
+    }
+    // A String prototype can match String, Boolean, Integer, Real, UUID,
+    // Date and URI, because any of these can be converted to String.
+    if (prototype.isString())
+    {
+        static LLSD::Type accept[] =
+        {
+            LLSD::TypeBoolean,
+            LLSD::TypeInteger,
+            LLSD::TypeReal,
+            LLSD::TypeUUID,
+            LLSD::TypeDate,
+            LLSD::TypeURI
+        };
+        return match_types(prototype.type(),
+                           TypeVector(boost::begin(accept), boost::end(accept)),
+                           data.type(),
+                           pfx);
+    }
+    // Boolean, Integer, Real match each other or String. TBD: ensure that
+    // a String value is numeric.
+    if (prototype.isBoolean() || prototype.isInteger() || prototype.isReal())
+    {
+        static LLSD::Type all[] =
+        {
+            LLSD::TypeBoolean,
+            LLSD::TypeInteger,
+            LLSD::TypeReal,
+            LLSD::TypeString
+        };
+        // Funny business: shuffle the set of acceptable types to include all
+        // but the prototype's type. Get the acceptable types in a set.
+        std::set<LLSD::Type> rest(boost::begin(all), boost::end(all));
+        // Remove the prototype's type because we pass that separately.
+        rest.erase(prototype.type());
+        return match_types(prototype.type(),
+                           TypeVector(rest.begin(), rest.end()),
+                           data.type(),
+                           pfx);
+    }
+    // UUID, Date and URI match themselves or String.
+    if (prototype.isUUID() || prototype.isDate() || prototype.isURI())
+    {
+        static LLSD::Type accept[] =
+        {
+            LLSD::TypeString
+        };
+        return match_types(prototype.type(),
+                           TypeVector(boost::begin(accept), boost::end(accept)),
+                           data.type(),
+                           pfx);
+    }
+    // We don't yet know the conversion semantics associated with any new LLSD
+    // data type that might be added, so until we've been extended to handle
+    // them, assume it's strict: the new type matches only itself. (This is
+    // true of Binary, which is why we don't handle that case separately.) Too
+    // bad LLSD doesn't define isConvertible(Type to, Type from).
+    return match_types(prototype.type(), TypeVector(), data.type(), pfx);
+}
+
+bool llsd_equals(const LLSD& lhs, const LLSD& rhs)
+{
+    // We're comparing strict equality of LLSD representation rather than
+    // performing any conversions. So if the types aren't equal, the LLSD
+    // values aren't equal.
+    if (lhs.type() != rhs.type())
+    {
+        return false;
+    }
+
+    // Here we know both types are equal. Now compare values.
+    switch (lhs.type())
+    {
+    case LLSD::TypeUndefined:
+        // Both are TypeUndefined. There's nothing more to know.
+        return true;
+
+#define COMPARE_SCALAR(type)                                    \
+    case LLSD::Type##type:                                      \
+        /* LLSD::URI has operator!=() but not operator==() */   \
+        /* rely on the optimizer for all others */              \
+        return (! (lhs.as##type() != rhs.as##type()))
+
+    COMPARE_SCALAR(Boolean);
+    COMPARE_SCALAR(Integer);
+    // The usual caveats about comparing floating-point numbers apply. This is
+    // only useful when we expect identical bit representation for a given
+    // Real value, e.g. for integer-valued Reals.
+    COMPARE_SCALAR(Real);
+    COMPARE_SCALAR(String);
+    COMPARE_SCALAR(UUID);
+    COMPARE_SCALAR(Date);
+    COMPARE_SCALAR(URI);
+    COMPARE_SCALAR(Binary);
+
+#undef COMPARE_SCALAR
+
+    case LLSD::TypeArray:
+    {
+        LLSD::array_const_iterator
+            lai(lhs.beginArray()), laend(lhs.endArray()),
+            rai(rhs.beginArray()), raend(rhs.endArray());
+        // Compare array elements, walking the two arrays in parallel.
+        for ( ; lai != laend && rai != raend; ++lai, ++rai)
+        {
+            // If any one array element is unequal, the arrays are unequal.
+            if (! llsd_equals(*lai, *rai))
+                return false;
+        }
+        // Here we've reached the end of one or the other array. They're equal
+        // only if they're BOTH at end: that is, if they have equal length too.
+        return (lai == laend && rai == raend);
+    }
+
+    case LLSD::TypeMap:
+    {
+        // Build a set of all rhs keys.
+        std::set<LLSD::String> rhskeys;
+        for (LLSD::map_const_iterator rmi(rhs.beginMap()), rmend(rhs.endMap());
+             rmi != rmend; ++rmi)
+        {
+            rhskeys.insert(rmi->first);
+        }
+        // Now walk all the lhs keys.
+        for (LLSD::map_const_iterator lmi(lhs.beginMap()), lmend(lhs.endMap());
+             lmi != lmend; ++lmi)
+        {
+            // Try to erase this lhs key from the set of rhs keys. If rhs has
+            // no such key, the maps are unequal. erase(key) returns count of
+            // items erased.
+            if (rhskeys.erase(lmi->first) != 1)
+                return false;
+            // Both maps have the current key. Compare values.
+            if (! llsd_equals(lmi->second, rhs[lmi->first]))
+                return false;
+        }
+        // We've now established that all the lhs keys have equal values in
+        // both maps. The maps are equal unless rhs contains a superset of
+        // those keys.
+        return rhskeys.empty();
+    }
+
+    default:
+        // We expect that every possible type() value is specifically handled
+        // above. Failing to extend this switch to support a new LLSD type is
+        // an error that must be brought to the coder's attention.
+        LL_ERRS("llsd_equals") << "llsd_equals(" << lhs << ", " << rhs << "): "
+            "unknown type " << lhs.type() << LL_ENDL;
+        return false;               // pacify the compiler
+    }
+}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 501600f1d906a367c14c8b520f7bafd8062730bd..6a6c396687000edcfc7601ff2ff2e7cce7aeb287 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -35,62 +35,32 @@
 #ifndef LL_LLSDUTIL_H
 #define LL_LLSDUTIL_H
 
-#include "llsd.h"
-
-// vector3
-class LLVector3;
-LLSD ll_sd_from_vector3(const LLVector3& vec);
-LLVector3 ll_vector3_from_sd(const LLSD& sd, S32 start_index = 0);
-
-// vector4
-class LLVector4;
-LLSD ll_sd_from_vector4(const LLVector4& vec);
-LLVector4 ll_vector4_from_sd(const LLSD& sd, S32 start_index = 0);
-
-// vector3d (double)
-class LLVector3d;
-LLSD ll_sd_from_vector3d(const LLVector3d& vec);
-LLVector3d ll_vector3d_from_sd(const LLSD& sd, S32 start_index = 0);
-
-// vector2
-class LLVector2;
-LLSD ll_sd_from_vector2(const LLVector2& vec);
-LLVector2 ll_vector2_from_sd(const LLSD& sd);
-
-// Quaternion
-class LLQuaternion;
-LLSD ll_sd_from_quaternion(const LLQuaternion& quat);
-LLQuaternion ll_quaternion_from_sd(const LLSD& sd);
-
-// color4
-class LLColor4;
-LLSD ll_sd_from_color4(const LLColor4& c);
-LLColor4 ll_color4_from_sd(const LLSD& sd);
+class LLSD;
 
 // U32
-LLSD ll_sd_from_U32(const U32);
-U32 ll_U32_from_sd(const LLSD& sd);
+LL_COMMON_API LLSD ll_sd_from_U32(const U32);
+LL_COMMON_API U32 ll_U32_from_sd(const LLSD& sd);
 
 // U64
-LLSD ll_sd_from_U64(const U64);
-U64 ll_U64_from_sd(const LLSD& sd);
+LL_COMMON_API LLSD ll_sd_from_U64(const U64);
+LL_COMMON_API U64 ll_U64_from_sd(const LLSD& sd);
 
 // IP Address
-LLSD ll_sd_from_ipaddr(const U32);
-U32 ll_ipaddr_from_sd(const LLSD& sd);
+LL_COMMON_API LLSD ll_sd_from_ipaddr(const U32);
+LL_COMMON_API U32 ll_ipaddr_from_sd(const LLSD& sd);
 
 // Binary to string
-LLSD ll_string_from_binary(const LLSD& sd);
+LL_COMMON_API LLSD ll_string_from_binary(const LLSD& sd);
 
 //String to binary
-LLSD ll_binary_from_string(const LLSD& sd);
+LL_COMMON_API LLSD ll_binary_from_string(const LLSD& sd);
 
 // Serializes sd to static buffer and returns pointer, useful for gdb debugging.
-char* ll_print_sd(const LLSD& sd);
+LL_COMMON_API char* ll_print_sd(const LLSD& sd);
 
 // Serializes sd to static buffer and returns pointer, using "pretty printing" mode.
-char* ll_pretty_print_sd_ptr(const LLSD* sd);
-char* ll_pretty_print_sd(const LLSD& sd);
+LL_COMMON_API char* ll_pretty_print_sd_ptr(const LLSD* sd);
+LL_COMMON_API char* ll_pretty_print_sd(const LLSD& sd);
 
 //compares the structure of an LLSD to a template LLSD and stores the
 //"valid" values in a 3rd LLSD. Default values
@@ -99,11 +69,69 @@ char* ll_pretty_print_sd(const LLSD& sd);
 //Returns false if the test is of same type but values differ in type
 //Otherwise, returns true
 
-BOOL compare_llsd_with_template(
+LL_COMMON_API BOOL compare_llsd_with_template(
 	const LLSD& llsd_to_test,
 	const LLSD& template_llsd,
 	LLSD& resultant_llsd);
 
+/**
+ * Recursively determine whether a given LLSD data block "matches" another
+ * LLSD prototype. The returned string is empty() on success, non-empty() on
+ * mismatch.
+ *
+ * This function tests structure (types) rather than data values. It is
+ * intended for when a consumer expects an LLSD block with a particular
+ * structure, and must succinctly detect whether the arriving block is
+ * well-formed. For instance, a test of the form:
+ * @code
+ * if (! (data.has("request") && data.has("target") && data.has("modifier") ...))
+ * @endcode
+ * could instead be expressed by initializing a prototype LLSD map with the
+ * required keys and writing:
+ * @code
+ * if (! llsd_matches(prototype, data).empty())
+ * @endcode
+ *
+ * A non-empty return value is an error-message fragment intended to indicate
+ * to (English-speaking) developers where in the prototype structure the
+ * mismatch occurred.
+ *
+ * * If a slot in the prototype isUndefined(), then anything is valid at that
+ *   place in the real object. (Passing prototype == LLSD() matches anything
+ *   at all.)
+ * * An array in the prototype must match a data array at least that large.
+ *   (Additional entries in the data array are ignored.) Every isDefined()
+ *   entry in the prototype array must match the corresponding entry in the
+ *   data array.
+ * * A map in the prototype must match a map in the data. Every key in the
+ *   prototype map must match a corresponding key in the data map. (Additional
+ *   keys in the data map are ignored.) Every isDefined() value in the
+ *   prototype map must match the corresponding key's value in the data map.
+ * * Scalar values in the prototype are tested for @em type rather than value.
+ *   For instance, a String in the prototype matches any String at all. In
+ *   effect, storing an Integer at a particular place in the prototype asserts
+ *   that the caller intends to apply asInteger() to the corresponding slot in
+ *   the data.
+ * * A String in the prototype matches String, Boolean, Integer, Real, UUID,
+ *   Date and URI, because asString() applied to any of these produces a
+ *   meaningful result.
+ * * Similarly, a Boolean, Integer or Real in the prototype can match any of
+ *   Boolean, Integer or Real in the data -- or even String.
+ * * UUID matches UUID or String.
+ * * Date matches Date or String.
+ * * URI matches URI or String.
+ * * Binary in the prototype matches only Binary in the data.
+ *
+ * @TODO: when a Boolean, Integer or Real in the prototype matches a String in
+ * the data, we should examine the String @em value to ensure it can be
+ * meaningfully converted to the requested type. The same goes for UUID, Date
+ * and URI.
+ */
+LL_COMMON_API std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx="");
+
+/// Deep equality
+LL_COMMON_API bool llsd_equals(const LLSD& lhs, const LLSD& rhs);
+
 // Simple function to copy data out of input & output iterators if
 // there is no need for casting.
 template<typename Input> LLSD llsd_copy_array(Input iter, Input end)
diff --git a/indra/llcommon/llsecondlifeurls.h b/indra/llcommon/llsecondlifeurls.h
index a2e5f0b9c60f6e3c385ae0a5113e675a2dfe792c..bd2f9f760435d663c07fe1bb604bf209f69c4455 100644
--- a/indra/llcommon/llsecondlifeurls.h
+++ b/indra/llcommon/llsecondlifeurls.h
@@ -34,49 +34,49 @@
 #define LL_LLSECONDLIFEURLS_H
 /*
 // Account registration web page
-extern const std::string CREATE_ACCOUNT_URL;
+LL_COMMON_API extern const std::string CREATE_ACCOUNT_URL;
 
 // Manage Account
-extern const std::string MANAGE_ACCOUNT;
+LL_COMMON_API extern const std::string MANAGE_ACCOUNT;
 
-extern const std::string AUCTION_URL; 
+LL_COMMON_API extern const std::string AUCTION_URL; 
 
-extern const std::string EVENTS_URL;
+LL_COMMON_API extern const std::string EVENTS_URL;
 */
 // Tier up to a new land level.
-extern const std::string TIER_UP_URL;
+LL_COMMON_API extern const std::string TIER_UP_URL;
 
 
 // Tier up to a new land level.
-extern const std::string LAND_URL;
+LL_COMMON_API extern const std::string LAND_URL;
 
 // How to get DirectX 9
-extern const std::string DIRECTX_9_URL;
+LL_COMMON_API extern const std::string DIRECTX_9_URL;
 
 /*
 // Upgrade from basic membership to premium membership
-extern const std::string UPGRADE_TO_PREMIUM_URL;
+LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
 
 
 // Out of date VIA chipset
-extern const std::string VIA_URL;
+LL_COMMON_API extern const std::string VIA_URL;
 
 // Support URL
-extern const std::string SUPPORT_URL;
+LL_COMMON_API extern const std::string SUPPORT_URL;
 
 // Linden Blogs page
-extern const std::string BLOGS_URL;
+LL_COMMON_API extern const std::string BLOGS_URL;
 
 // Currency page
-extern const std::string BUY_CURRENCY_URL;
+LL_COMMON_API extern const std::string BUY_CURRENCY_URL;
 
 // LSL script wiki
-extern const std::string LSL_DOC_URL;
+LL_COMMON_API extern const std::string LSL_DOC_URL;
 
 // SL KnowledgeBase page
-extern const std::string SL_KB_URL;
+LL_COMMON_API extern const std::string SL_KB_URL;
 
 // Release Notes Redirect URL for Server and Viewer
-extern const std::string RELEASE_NOTES_BASE_URL;
+LL_COMMON_API extern const std::string RELEASE_NOTES_BASE_URL;
 */
 #endif
diff --git a/indra/llcommon/llsimplehash.h b/indra/llcommon/llsimplehash.h
index 0ba2a3014c7dd0c2f24cc82371bb495e498a815f..5df93b646ec31af12d59e0b4138297000aac58a3 100644
--- a/indra/llcommon/llsimplehash.h
+++ b/indra/llcommon/llsimplehash.h
@@ -64,7 +64,7 @@ class LLSimpleHashEntry
 };
 
 template <typename HASH_KEY_TYPE, int TABLE_SIZE>
-class LLSimpleHash
+class LL_COMMON_API LLSimpleHash
 {
 public:
 	LLSimpleHash()
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6b5feaf1c46a0553cab0e65f6a9ef6672fc54bde
--- /dev/null
+++ b/indra/llcommon/llsingleton.cpp
@@ -0,0 +1,38 @@
+/** 
+ * @file llsingleton.cpp
+ * @author Brad Kittenbrink
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llsingleton.h"
+
+std::map<std::string, void *> * LLSingletonRegistry::sSingletonMap = NULL;
+
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 2e7d845bf717e7a516b4ce38354db8b53e269a5d..f55fafadd8dff8ea44e9b41eec191d86879a9053 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -33,7 +33,41 @@
 
 #include "llerror.h"	// *TODO: eliminate this
 
+#include <typeinfo>
 #include <boost/noncopyable.hpp>
+#include <boost/any.hpp>
+
+/// @brief A global registry of all singletons to prevent duplicate allocations
+/// across shared library boundaries
+class LL_COMMON_API LLSingletonRegistry {
+	private:
+		typedef std::map<std::string, void *> TypeMap;
+		static TypeMap * sSingletonMap;
+
+		static void checkInit()
+		{
+			if(sSingletonMap == NULL)
+			{
+				sSingletonMap = new TypeMap();
+			}
+		}
+
+	public:
+		template<typename T> static void * & get()
+		{
+			std::string name(typeid(T).name());
+
+			checkInit();
+
+			// the first entry of the pair returned by insert will be either the existing
+			// iterator matching our key, or the newly inserted NULL initialized entry
+			// see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
+			TypeMap::iterator result =
+				sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first;
+
+			return result->second;
+		}
+};
 
 // LLSingleton implements the getInstance() method part of the Singleton
 // pattern. It can't make the derived class constructors protected, though, so
@@ -107,8 +141,17 @@ class LLSingleton : private boost::noncopyable
 
 	static SingletonInstanceData& getData()
 	{
-		static SingletonInstanceData data;
-		return data;
+		// this is static to cache the lookup results
+		static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
+
+		// *TODO - look into making this threadsafe
+		if(NULL == registry)
+		{
+			static SingletonInstanceData data;
+			registry = &data;
+		}
+
+		return *static_cast<SingletonInstanceData *>(registry);
 	}
 
 	static DERIVED_TYPE* getInstance()
diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp
index 4be91b5b11f48b8128f5ba50b796da73b4102a99..3cb074257bc8927e6f05e53c1aa3161f18707a94 100644
--- a/indra/llcommon/llstacktrace.cpp
+++ b/indra/llcommon/llstacktrace.cpp
@@ -1,141 +1,142 @@
-/** 
- * @file llstacktrace.cpp
- * @brief stack tracing functionality
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
- * Copyright (c) 2001-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "llstacktrace.h"
-
-#ifdef LL_WINDOWS
-
-#include <iostream>
-#include <sstream>
-
-#include "windows.h"
-#include "Dbghelp.h"
-
-typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
-    IN ULONG frames_to_skip,
-    IN ULONG frames_to_capture,
-    OUT PVOID *backtrace,
-    OUT PULONG backtrace_hash);
-
-static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
-   (RtlCaptureStackBackTrace_Function*)
-   GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
-
-bool ll_get_stack_trace(std::vector<std::string>& lines)
-{
-	const S32 MAX_STACK_DEPTH = 32;
-	const S32 STRING_NAME_LENGTH = 200;
-	const S32 FRAME_SKIP = 2;
-	static BOOL symbolsLoaded = false;
-	static BOOL firstCall = true;
-
-	HANDLE hProc = GetCurrentProcess();
-
-	// load the symbols if they're not loaded
-	if(!symbolsLoaded && firstCall)
-	{
-		symbolsLoaded = SymInitialize(hProc, NULL, true);
-		firstCall = false;
-	}
-
-	// if loaded, get the call stack
-	if(symbolsLoaded)
-	{
-		// create the frames to hold the addresses
-		void* frames[MAX_STACK_DEPTH];
-		memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
-		S32 depth = 0;
-
-		// get the addresses
-		depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
-
-		IMAGEHLP_LINE64 line;
-		memset(&line, 0, sizeof(IMAGEHLP_LINE64));
-		line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
-
-		// create something to hold address info
-		PIMAGEHLP_SYMBOL64 pSym;
-		pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
-		memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
-		pSym->MaxNameLength = STRING_NAME_LENGTH;
-		pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
-
-		// get address info for each address frame
-		// and store
-		for(S32 i=0; i < depth; i++)
-		{
-			std::stringstream stack_line;
-			BOOL ret;
-
-			DWORD64 addr = (DWORD64)frames[i];
-			ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
-			if(ret)
-			{
-				stack_line << pSym->Name << " ";
-			}
-
-			DWORD dummy;
-			ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
-			if(ret)
-			{
-				std::string file_name = line.FileName;
-				std::string::size_type index = file_name.rfind("\\");
-				stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; 
-			}
-
-			lines.push_back(stack_line.str());
-		}
-		
-		free(pSym);
-
-		// TODO: figure out a way to cleanup symbol loading
-		// Not hugely necessary, however.
-		//SymCleanup(hProc);
-		return true;
-	}
-	else
-	{
-		lines.push_back("Stack Trace Failed.  PDB symbol info not loaded");
-	}
-
-	return false;
-}
-
-#else
-
-bool ll_get_stack_trace(std::vector<std::string>& lines)
-{
-	return false;
-}
-
-#endif
-
+/** 
+ * @file llstacktrace.cpp
+ * @brief stack tracing functionality
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llstacktrace.h"
+
+#ifdef LL_WINDOWS
+
+#include <iostream>
+#include <sstream>
+
+#include "windows.h"
+#include "Dbghelp.h"
+
+typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
+    IN ULONG frames_to_skip,
+    IN ULONG frames_to_capture,
+    OUT PVOID *backtrace,
+    OUT PULONG backtrace_hash);
+
+static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
+   (RtlCaptureStackBackTrace_Function*)
+   GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
+
+bool ll_get_stack_trace(std::vector<std::string>& lines)
+{
+	const S32 MAX_STACK_DEPTH = 32;
+	const S32 STRING_NAME_LENGTH = 200;
+	const S32 FRAME_SKIP = 2;
+	static BOOL symbolsLoaded = false;
+	static BOOL firstCall = true;
+
+	HANDLE hProc = GetCurrentProcess();
+
+	// load the symbols if they're not loaded
+	if(!symbolsLoaded && firstCall)
+	{
+		symbolsLoaded = SymInitialize(hProc, NULL, true);
+		firstCall = false;
+	}
+
+	// if loaded, get the call stack
+	if(symbolsLoaded)
+	{
+		// create the frames to hold the addresses
+		void* frames[MAX_STACK_DEPTH];
+		memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
+		S32 depth = 0;
+
+		// get the addresses
+		depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
+
+		IMAGEHLP_LINE64 line;
+		memset(&line, 0, sizeof(IMAGEHLP_LINE64));
+		line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+
+		// create something to hold address info
+		PIMAGEHLP_SYMBOL64 pSym;
+		pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
+		memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
+		pSym->MaxNameLength = STRING_NAME_LENGTH;
+		pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+
+		// get address info for each address frame
+		// and store
+		for(S32 i=0; i < depth; i++)
+		{
+			std::stringstream stack_line;
+			BOOL ret;
+
+			DWORD64 addr = (DWORD64)frames[i];
+			ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
+			if(ret)
+			{
+				stack_line << pSym->Name << " ";
+			}
+
+			DWORD dummy;
+			ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
+			if(ret)
+			{
+				std::string file_name = line.FileName;
+				std::string::size_type index = file_name.rfind("\\");
+				stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; 
+			}
+
+			lines.push_back(stack_line.str());
+		}
+		
+		free(pSym);
+
+		// TODO: figure out a way to cleanup symbol loading
+		// Not hugely necessary, however.
+		//SymCleanup(hProc);
+		return true;
+	}
+	else
+	{
+		lines.push_back("Stack Trace Failed.  PDB symbol info not loaded");
+	}
+
+	return false;
+}
+
+#else
+
+bool ll_get_stack_trace(std::vector<std::string>& lines)
+{
+	return false;
+}
+
+#endif
+
diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h
index 609b934a9745616974c1a36934561650110e0077..b84b1aa6ade73d81ad6fb642f37b46c7904fbadb 100644
--- a/indra/llcommon/llstacktrace.h
+++ b/indra/llcommon/llstacktrace.h
@@ -1,44 +1,44 @@
-/** 
- * @file llstacktrace.h
- * @brief stack trace functions
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
- * Copyright (c) 2001-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-
-#ifndef LL_LLSTACKTRACE_H
-#define LL_LLSTACKTRACE_H
-
-#include "stdtypes.h"
-#include <vector>
-#include <string>
-
-bool ll_get_stack_trace(std::vector<std::string>& lines);
-
-#endif
-
+/** 
+ * @file llstacktrace.h
+ * @brief stack trace functions
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_LLSTACKTRACE_H
+#define LL_LLSTACKTRACE_H
+
+#include "stdtypes.h"
+#include <vector>
+#include <string>
+
+LL_COMMON_API bool ll_get_stack_trace(std::vector<std::string>& lines);
+
+#endif
+
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 90dae117937254d03e8f2fabe78bc8ed23c6cecd..0bd2609f4a9ab462cbc4eecd483bbba2c680a240 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -43,7 +43,7 @@
 
 
 // statics
-BOOL            LLPerfBlock::sStatsEnabled = FALSE;    // Flag for detailed information
+S32	            LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS;       // Control what is being recorded
 LLPerfBlock::stat_map_t    LLPerfBlock::sStatMap;    // Map full path string to LLStatTime objects, tracks all active objects
 std::string        LLPerfBlock::sCurrentStatPath = "";    // Something like "/total_time/physics/physics step"
 LLStat::stat_map_t LLStat::sStatList;
@@ -130,6 +130,7 @@ bool LLStatsConfigFile::loadFile()
 
     F32 duration = 0.f;
     F32 interval = 0.f;
+	S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS;
 
     const char * w = "duration";
     if (stats_config.has(w))
@@ -141,8 +142,18 @@ bool LLStatsConfigFile::loadFile()
     {
         interval = (F32)stats_config[w].asReal();
     } 
+    w = "flags";
+    if (stats_config.has(w))
+    {
+		flags = (S32)stats_config[w].asInteger();
+		if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS &&
+			duration > 0)
+		{   // No flags passed in, but have a duration, so reset to basic stats
+			flags = LLPerfBlock::LLSTATS_BASIC_STATS;
+		}
+    } 
 
-    mStatsp->setReportPerformanceDuration( duration );
+    mStatsp->setReportPerformanceDuration( duration, flags );
     mStatsp->setReportPerformanceInterval( interval );
 
     if ( duration > 0 )
@@ -254,13 +265,14 @@ void LLPerfStats::dumpIntervalPerformanceStats()
     }
 }
 
-// Set length of performance stat recording
-void    LLPerfStats::setReportPerformanceDuration( F32 seconds )
+// Set length of performance stat recording.  
+// If turning stats on, caller must provide flags
+void    LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ )
 { 
 	if ( seconds <= 0.f )
 	{
 		mReportPerformanceStatEnd = 0.0;
-		LLPerfBlock::setStatsEnabled( FALSE );
+		LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS);		// Make sure all recording is off
 		mFrameStatsFile.close();
 		LLPerfBlock::clearDynamicStats();
 	}
@@ -269,8 +281,8 @@ void    LLPerfStats::setReportPerformanceDuration( F32 seconds )
 		mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
 		// Clear failure flag to try and create the log file once
 		mFrameStatsFileFailure = FALSE;
-		LLPerfBlock::setStatsEnabled( TRUE );
 		mSkipFirstFrameStats = TRUE;		// Skip the first report (at the end of this frame)
+		LLPerfBlock::setStatsFlags(flags);
 	}
 }
 
@@ -612,11 +624,26 @@ LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicSta
     }
 }
 
-// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key.
-// These are also turned on or off via the switch passed in
-LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+// Use this constructor for normal, optional LLPerfBlock time slices
+LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL)
 {
-    if (!sStatsEnabled) return;
+    if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0)
+	{	// These are off unless the base set is enabled
+		return;
+	}
+
+	initDynamicStat(key);
+}
+
+	
+// Use this constructor for dynamically created LLPerfBlock time slices
+// that are only enabled by specific control flags
+LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+{
+    if ((sStatsFlags & flags) == 0)
+	{
+		return;
+	}
 
     if (NULL == key2 || strlen(key2) == 0)
     {
@@ -630,10 +657,12 @@ LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat
     }
 }
 
+// Set up the result data map if dynamic stats are enabled
 void LLPerfBlock::initDynamicStat(const std::string& key)
 {
     // Early exit if dynamic stats aren't enabled.
-    if (!sStatsEnabled) return;
+    if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS) 
+		return;
 
     mLastPath = sCurrentStatPath;		// Save and restore current path
     sCurrentStatPath += "/" + key;		// Add key to current path
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
index bad18f46a0aea70e8abfeacca42703f96a86553c..bd73c9a6bb50af848082725f643b589ae9e90838 100644
--- a/indra/llcommon/llstat.h
+++ b/indra/llcommon/llstat.h
@@ -52,7 +52,7 @@ class	LLSD;
 // amounts of time with very low memory cost.
 //
 
-class LLStatAccum
+class LL_COMMON_API LLStatAccum
 {
 protected:
 	LLStatAccum(bool use_frame_timer);
@@ -116,7 +116,7 @@ class LLStatAccum
 	F64 	mLastSampleValue;
 };
 
-class LLStatMeasure : public LLStatAccum
+class LL_COMMON_API LLStatMeasure : public LLStatAccum
 	// gathers statistics about things that are measured
 	// ex.: tempature, time dilation
 {
@@ -131,7 +131,7 @@ class LLStatMeasure : public LLStatAccum
 };
 
 
-class LLStatRate : public LLStatAccum
+class LL_COMMON_API LLStatRate : public LLStatAccum
 	// gathers statistics about things that can be counted over time
 	// ex.: LSL instructions executed, messages sent, simulator frames completed
 	// renders it in terms of rate of thing per second
@@ -147,7 +147,7 @@ class LLStatRate : public LLStatAccum
 };
 
 
-class LLStatTime : public LLStatAccum
+class LL_COMMON_API LLStatTime : public LLStatAccum
 	// gathers statistics about time spent in a block of code
 	// measure average duration per second in the block
 {
@@ -178,7 +178,7 @@ class LLStatTime : public LLStatAccum
 
 
 // Use this class on the stack to record statistics about an area of code
-class LLPerfBlock
+class LL_COMMON_API LLPerfBlock
 {
 public:
     struct StatEntry
@@ -192,14 +192,23 @@ class LLPerfBlock
 	// Use this constructor for pre-defined LLStatTime objects
 	LLPerfBlock(LLStatTime* stat);
 
-	// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key
-	LLPerfBlock( const char* key1, const char* key2 = NULL);
+	// Use this constructor for normal, optional LLPerfBlock time slices
+	LLPerfBlock( const char* key );
 
+	// Use this constructor for dynamically created LLPerfBlock time slices
+	// that are only enabled by specific control flags
+	LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS );
 
 	~LLPerfBlock();
 
-	static void setStatsEnabled( BOOL enable )		{ sStatsEnabled = enable;	};
-	static S32  getStatsEnabled()					{ return sStatsEnabled;		};
+	enum
+	{	// Stats bitfield flags
+		LLSTATS_NO_OPTIONAL_STATS	= 0x00,		// No optional stats gathering, just pre-defined LLStatTime objects
+		LLSTATS_BASIC_STATS			= 0x01,		// Gather basic optional runtime stats
+		LLSTATS_SCRIPT_FUNCTIONS	= 0x02,		// Include LSL function calls
+	};
+	static void setStatsFlags( S32 flags )	{ sStatsFlags = flags;	};
+	static S32  getStatsFlags()				{ return sStatsFlags;	};
 
 	static void clearDynamicStats();		// Reset maps to clear out dynamic objects
 	static void addStatsToLLSDandReset( LLSD & stats,		// Get current information and clear time bin
@@ -213,14 +222,14 @@ class LLPerfBlock
 	LLStatTime * 			mPredefinedStat;		// LLStatTime object to get data
 	StatEntry *				mDynamicStat;   		// StatEntryobject to get data
 
-	static BOOL				sStatsEnabled;			// Normally FALSE
+	static S32				sStatsFlags;			// Control what is being recorded
     static stat_map_t		sStatMap;				// Map full path string to LLStatTime objects
 	static std::string		sCurrentStatPath;		// Something like "frame/physics/physics step"
 };
 
 // ----------------------------------------------------------------------------
 
-class LLPerfStats
+class LL_COMMON_API LLPerfStats
 {
 public:
     LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0);
@@ -236,7 +245,7 @@ class LLPerfStats
     BOOL    frameStatsIsRunning()                                { return (mReportPerformanceStatEnd > 0.);        };
     F32     getReportPerformanceInterval() const                { return mReportPerformanceStatInterval;        };
     void    setReportPerformanceInterval( F32 interval )        { mReportPerformanceStatInterval = interval;    };
-    void    setReportPerformanceDuration( F32 seconds );
+    void    setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS );
     void    setProcessName(const std::string& process_name) { mProcessName = process_name; }
     void    setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
 
@@ -256,7 +265,7 @@ class LLPerfStats
 };
 
 // ----------------------------------------------------------------------------
-class LLStat
+class LL_COMMON_API LLStat
 {
 private:
 	typedef std::multimap<std::string, LLStat*> stat_map_t;
diff --git a/indra/llcommon/llstreamtools.h b/indra/llcommon/llstreamtools.h
index a6dc4d51e27acc7fc920dcee88c26867063c69ad..f64e76140936842b82ad9269c8c3cbbe320833ae 100644
--- a/indra/llcommon/llstreamtools.h
+++ b/indra/llcommon/llstreamtools.h
@@ -39,23 +39,23 @@
 // unless specifed otherwise these all return input_stream.good()
 
 // skips spaces and tabs
-bool skip_whitespace(std::istream& input_stream);
+LL_COMMON_API bool skip_whitespace(std::istream& input_stream);
 
 // skips whitespace and newlines
-bool skip_emptyspace(std::istream& input_stream);
+LL_COMMON_API bool skip_emptyspace(std::istream& input_stream);
 
 // skips emptyspace and lines that start with a #
-bool skip_comments_and_emptyspace(std::istream& input_stream);
+LL_COMMON_API bool skip_comments_and_emptyspace(std::istream& input_stream);
 
 // skips to character after next newline
-bool skip_line(std::istream& input_stream);
+LL_COMMON_API bool skip_line(std::istream& input_stream);
 
 // skips to beginning of next non-emptyspace
-bool skip_to_next_word(std::istream& input_stream);
+LL_COMMON_API bool skip_to_next_word(std::istream& input_stream);
 
 // skips to character after the end of next keyword 
 // a 'keyword' is defined as the first word on a line
-bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream);
+LL_COMMON_API bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream);
 
 // skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug 
 // in windows iostream
@@ -65,14 +65,14 @@ bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream
 
 // characters are pulled out of input_stream and appended to output_string
 // returns result of input_stream.good() after characters are pulled
-bool get_word(std::string& output_string, std::istream& input_stream);
-bool get_line(std::string& output_string, std::istream& input_stream);
+LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stream);
+LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream);
 
 // characters are pulled out of input_stream (up to a max of 'n')
 // and appended to output_string 
 // returns result of input_stream.good() after characters are pulled
-bool get_word(std::string& output_string, std::istream& input_stream, int n);
-bool get_line(std::string& output_string, std::istream& input_stream, int n);
+LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stream, int n);
+LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream, int n);
 
 // unget_line() is disabled -- might tickle corruption bug in windows iostream
 //// backs up the input_stream by line_size + 1 characters
@@ -82,28 +82,28 @@ bool get_line(std::string& output_string, std::istream& input_stream, int n);
 
 // removes the last char in 'line' if it matches 'c'
 // returns true if removed last char
-bool remove_last_char(char c, std::string& line);
+LL_COMMON_API bool remove_last_char(char c, std::string& line);
 
 // replaces escaped characters with the correct characters from left to right
 // "\\" ---> '\\' 
 // "\n" ---> '\n' 
-void unescape_string(std::string& line);
+LL_COMMON_API void unescape_string(std::string& line);
 
 // replaces unescaped characters with expanded equivalents from left to right
 // '\\' ---> "\\" 
 // '\n' ---> "\n" 
-void escape_string(std::string& line);
+LL_COMMON_API void escape_string(std::string& line);
 
 // replaces each '\n' character with ' '
-void replace_newlines_with_whitespace(std::string& line);
+LL_COMMON_API void replace_newlines_with_whitespace(std::string& line);
 
 // erases any double-quote characters in line
-void remove_double_quotes(std::string& line);
+LL_COMMON_API void remove_double_quotes(std::string& line);
 
 // the 'keyword' is defined as the first word on a line
 // the 'value' is everything after the keyword on the same line
 // starting at the first non-whitespace and ending right before the newline
-void get_keyword_and_value(std::string& keyword, 
+LL_COMMON_API void get_keyword_and_value(std::string& keyword, 
 						   std::string& value, 
 						   const std::string& line);
 
@@ -111,13 +111,13 @@ void get_keyword_and_value(std::string& keyword,
 // read anymore or until we hit the count.  Some istream
 // implimentations have a max that they will read.
 // Returns the number of bytes read.
-std::streamsize fullread(
+LL_COMMON_API std::streamsize fullread(
 	std::istream& istr,
 	char* buf,
 	std::streamsize requested);
 
 
-std::istream& operator>>(std::istream& str, const char *tocheck);
+LL_COMMON_API std::istream& operator>>(std::istream& str, const char *tocheck);
 
 #endif
 
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index f2edd5c559a2e11227bf75a4e4182a08124c7923..c027aa7bdd5959dab532f8cbe7bc983c3b6f83ce 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -671,9 +671,9 @@ std::string ll_convert_wide_to_string(const wchar_t* in)
 }
 #endif // LL_WINDOWS
 
-long LLStringOps::sltOffset;
-long LLStringOps::localTimeOffset;
-bool LLStringOps::daylightSavings;
+long LLStringOps::sPacificTimeOffset = 0;
+long LLStringOps::sLocalTimeOffset = 0;
+bool LLStringOps::sPacificDaylightTime = 0;
 std::map<std::string, std::string> LLStringOps::datetimeToCodes;
 
 S32	LLStringOps::collate(const llwchar* a, const llwchar* b)
@@ -700,11 +700,11 @@ void LLStringOps::setupDatetimeInfo (bool daylight)
 	tmpT = gmtime (&nowT);
 	gmtT = mktime (tmpT);
 
-	localTimeOffset = (long) (gmtT - localT);
+	sLocalTimeOffset = (long) (gmtT - localT);
 
 
-	daylightSavings = daylight;
-	sltOffset = (daylightSavings? 7 : 8 ) * 60 * 60;
+	sPacificDaylightTime = daylight;
+	sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;
 
 	datetimeToCodes["wkday"]	= "%a";		// Thu
 	datetimeToCodes["weekday"]	= "%A";		// Thursday
@@ -957,36 +957,35 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
 	}
 	else if (param != "utc") // slt
 	{
-		secFromEpoch -= LLStringOps::getSltOffset();
+		secFromEpoch -= LLStringOps::getPacificTimeOffset();
 	}
 		
 	// if never fell into those two ifs above, param must be utc
 	if (secFromEpoch < 0) secFromEpoch = 0;
 
-	LLDate * datetime = new LLDate((F64)secFromEpoch);
+	LLDate datetime((F64)secFromEpoch);
 	std::string code = LLStringOps::getDatetimeCode (token);
 
 	// special case to handle timezone
 	if (code == "%Z") {
 		if (param == "utc")
+		{
 			replacement = "GMT";
-		else if (param == "slt")
-			replacement = "SLT";
-		else if (param != "local") // *TODO Vadim: not local? then what?
-			replacement = LLStringOps::getDaylightSavings() ? "PDT" : "PST";
-
-		return true;
-	}
-	replacement = datetime->toHTTPDateString(code);
-
-	if (code.empty())
-	{
-		return false;
-	}
-	else
-	{
+		}
+		else if (param == "local")
+		{
+			replacement = "";		// user knows their own timezone
+		}
+		else
+		{
+			// "slt" = Second Life Time, which is deprecated.
+			// If not utc or user local time, fallback to Pacific time
+			replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST";
+		}
 		return true;
 	}
+	replacement = datetime.toHTTPDateString(code);
+	return !code.empty();
 }
 
 // LLStringUtil::format recogizes the following patterns.
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index eca7e922fd4d792a2b1e6c72729d9d82a5efa5ae..edbb007f61c852bb09154ae60241ee26b776d418 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -1,1290 +1,1300 @@
-/** 
- * @file llstring.h
- * @brief String utility functions and std::string class.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
- * Copyright (c) 2001-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSTRING_H
-#define LL_LLSTRING_H
-
-#include <string>
-#include <cstdio>
-#include <locale>
-#include <iomanip>
-#include "llsd.h"
-#include "llfasttimer.h"
-
-#if LL_LINUX || LL_SOLARIS
-#include <wctype.h>
-#include <wchar.h>
-#endif
-
-#include <string.h>
-
-#if LL_SOLARIS
-// stricmp and strnicmp do not exist on Solaris:
-#define stricmp strcasecmp
-#define strnicmp strncasecmp
-#endif
-
-const char LL_UNKNOWN_CHAR = '?';
-
-#if LL_DARWIN || LL_LINUX || LL_SOLARIS
-// Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already)
-#include <cstring>
-
-namespace std
-{
-template<>
-struct char_traits<U16>
-{
-	typedef U16 		char_type;
-	typedef int 	    int_type;
-	typedef streampos 	pos_type;
-	typedef streamoff 	off_type;
-	typedef mbstate_t 	state_type;
-	
-	static void 
-		assign(char_type& __c1, const char_type& __c2)
-	{ __c1 = __c2; }
-	
-	static bool 
-		eq(const char_type& __c1, const char_type& __c2)
-	{ return __c1 == __c2; }
-	
-	static bool 
-		lt(const char_type& __c1, const char_type& __c2)
-	{ return __c1 < __c2; }
-	
-	static int 
-		compare(const char_type* __s1, const char_type* __s2, size_t __n)
-	{ return memcmp(__s1, __s2, __n * sizeof(char_type)); }
-	
-	static size_t
-		length(const char_type* __s)
-	{
-		const char_type *cur_char = __s;
-		while (*cur_char != 0)
-		{
-			++cur_char;
-		}
-		return cur_char - __s;
-	}
-	
-	static const char_type* 
-		find(const char_type* __s, size_t __n, const char_type& __a)
-	{ return static_cast<const char_type*>(memchr(__s, __a, __n * sizeof(char_type))); }
-	
-	static char_type* 
-		move(char_type* __s1, const char_type* __s2, size_t __n)
-	{ return static_cast<char_type*>(memmove(__s1, __s2, __n * sizeof(char_type))); }
-	
-	static char_type* 
-		copy(char_type* __s1, const char_type* __s2, size_t __n)
-	{  return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); }	/* Flawfinder: ignore */
-	
-	static char_type* 
-		assign(char_type* __s, size_t __n, char_type __a)
-	{ 
-		// This isn't right.
-		//return static_cast<char_type*>(memset(__s, __a, __n * sizeof(char_type))); 
-		
-		// I don't think there's a standard 'memset' for 16-bit values.
-		// Do this the old-fashioned way.
-		
-		size_t __i;
-		for(__i = 0; __i < __n; __i++)
-		{
-			__s[__i] = __a;
-		}
-		return __s; 
-	}
-	
-	static char_type 
-		to_char_type(const int_type& __c)
-	{ return static_cast<char_type>(__c); }
-	
-	static int_type 
-		to_int_type(const char_type& __c)
-	{ return static_cast<int_type>(__c); }
-	
-	static bool 
-		eq_int_type(const int_type& __c1, const int_type& __c2)
-	{ return __c1 == __c2; }
-	
-	static int_type 
-		eof() { return static_cast<int_type>(EOF); }
-	
-	static int_type 
-		not_eof(const int_type& __c)
-      { return (__c == eof()) ? 0 : __c; }
-  };
-};
-#endif
-
-class LLStringOps
-{
-private:
-	static long sltOffset;
-	static long localTimeOffset;
-	static bool daylightSavings;
-	static std::map<std::string, std::string> datetimeToCodes;
-
-public:
-	static char toUpper(char elem) { return toupper((unsigned char)elem); }
-	static llwchar toUpper(llwchar elem) { return towupper(elem); }
-	
-	static char toLower(char elem) { return tolower((unsigned char)elem); }
-	static llwchar toLower(llwchar elem) { return towlower(elem); }
-
-	static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; }
-	static bool isSpace(llwchar elem) { return iswspace(elem) != 0; }
-
-	static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; }
-	static bool isUpper(llwchar elem) { return iswupper(elem) != 0; }
-
-	static bool isLower(char elem) { return islower((unsigned char)elem) != 0; }
-	static bool isLower(llwchar elem) { return iswlower(elem) != 0; }
-
-	static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; }
-	static bool isDigit(llwchar a) { return iswdigit(a) != 0; }
-
-	static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; }
-	static bool isPunct(llwchar a) { return iswpunct(a) != 0; }
-
-	static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
-	static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
-
-	static S32	collate(const char* a, const char* b) { return strcoll(a, b); }
-	static S32	collate(const llwchar* a, const llwchar* b);
-
-	static void setupDatetimeInfo (bool daylight);
-	static long getSltOffset (void) {return sltOffset;}
-	static long getLocalTimeOffset (void) {return localTimeOffset;}
-	static bool getDaylightSavings (void) {return daylightSavings;}
-	static std::string getDatetimeCode (std::string key);
-};
-
-/**
- * @brief Return a string constructed from in without crashing if the
- * pointer is NULL.
- */
-std::string ll_safe_string(const char* in);
-std::string ll_safe_string(const char* in, S32 maxlen);
-
-
-// Allowing assignments from non-strings into format_map_t is apparently
-// *really* error-prone, so subclass std::string with just basic c'tors.
-class LLFormatMapString
-{
-public:
-	LLFormatMapString() {};
-	LLFormatMapString(const char* s) : mString(ll_safe_string(s)) {};
-	LLFormatMapString(const std::string& s) : mString(s) {};
-	operator std::string() const { return mString; }
-	bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; }
-	std::size_t length() const { return mString.length(); }
-	
-private:
-	std::string mString;
-};
-
-template <class T>
-class LLStringUtilBase
-{
-private:
-	static std::string sLocale;
-
-public:
-	typedef typename std::basic_string<T>::size_type size_type;
-	
-public:
-	/////////////////////////////////////////////////////////////////////////////////////////
-	// Static Utility functions that operate on std::strings
-
-	static std::basic_string<T> null;
-	
-	typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
-	static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
-	static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
-	static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
-	static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
-	static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
-	static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
-	static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions);
-	static void setLocale (std::string inLocale) {sLocale = inLocale;};
-	static std::string getLocale (void) {return sLocale;};
-	
-	static bool isValidIndex(const std::basic_string<T>& string, size_type i)
-	{
-		return !string.empty() && (0 <= i) && (i <= string.size());
-	}
-
-	static void	trimHead(std::basic_string<T>& string);
-	static void	trimTail(std::basic_string<T>& string);
-	static void	trim(std::basic_string<T>& string)	{ trimHead(string); trimTail(string); }
-	static void truncate(std::basic_string<T>& string, size_type count);
-
-	static void	toUpper(std::basic_string<T>& string);
-	static void	toLower(std::basic_string<T>& string);
-	
-	// True if this is the head of s.
-	static BOOL	isHead( const std::basic_string<T>& string, const T* s ); 
-
-	/**
-	 * @brief Returns true if string starts with substr
-	 *
-	 * If etither string or substr are empty, this method returns false.
-	 */
-	static bool startsWith(
-		const std::basic_string<T>& string,
-		const std::basic_string<T>& substr);
-
-	/**
-	 * @brief Returns true if string ends in substr
-	 *
-	 * If etither string or substr are empty, this method returns false.
-	 */
-	static bool endsWith(
-		const std::basic_string<T>& string,
-		const std::basic_string<T>& substr);
-
-	static void	addCRLF(std::basic_string<T>& string);
-	static void	removeCRLF(std::basic_string<T>& string);
-
-	static void	replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab );
-	static void	replaceNonstandardASCII( std::basic_string<T>& string, T replacement );
-	static void	replaceChar( std::basic_string<T>& string, T target, T replacement );
-	static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement );
-	
-	static BOOL	containsNonprintable(const std::basic_string<T>& string);
-	static void	stripNonprintable(std::basic_string<T>& string);
-
-	/**
-	 * @brief Unsafe way to make ascii characters. You should probably
-	 * only call this when interacting with the host operating system.
-	 * The 1 byte std::string does not work correctly.
-	 * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII
-	 * should work.
-	 */
-	static void _makeASCII(std::basic_string<T>& string);
-
-	// Conversion to other data types
-	static BOOL	convertToBOOL(const std::basic_string<T>& string, BOOL& value);
-	static BOOL	convertToU8(const std::basic_string<T>& string, U8& value);
-	static BOOL	convertToS8(const std::basic_string<T>& string, S8& value);
-	static BOOL	convertToS16(const std::basic_string<T>& string, S16& value);
-	static BOOL	convertToU16(const std::basic_string<T>& string, U16& value);
-	static BOOL	convertToU32(const std::basic_string<T>& string, U32& value);
-	static BOOL	convertToS32(const std::basic_string<T>& string, S32& value);
-	static BOOL	convertToF32(const std::basic_string<T>& string, F32& value);
-	static BOOL	convertToF64(const std::basic_string<T>& string, F64& value);
-
-	/////////////////////////////////////////////////////////////////////////////////////////
-	// Utility functions for working with char*'s and strings
-
-	// Like strcmp but also handles empty strings. Uses
-	// current locale.
-	static S32		compareStrings(const T* lhs, const T* rhs);
-	static S32		compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
-	
-	// case insensitive version of above. Uses current locale on
-	// Win32, and falls back to a non-locale aware comparison on
-	// Linux.
-	static S32		compareInsensitive(const T* lhs, const T* rhs);
-	static S32		compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
-
-	// Case sensitive comparison with good handling of numbers.  Does not use current locale.
-	// a.k.a. strdictcmp()
-	static S32		compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b);
-
-	// Case *in*sensitive comparison with good handling of numbers.  Does not use current locale.
-	// a.k.a. strdictcmp()
-	static S32		compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b);
-
-	// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
-	static BOOL		precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
-
-	// A replacement for strncpy.
-	// If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds
-	// up to dst_size-1 characters of src.
-	static void		copy(T* dst, const T* src, size_type dst_size);
-	
-	// Copies src into dst at a given offset.  
-	static void		copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset);
-	
-	static bool		isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); }
-
-
-#ifdef _DEBUG	
-	static void		testHarness();
-#endif
-
-private:
-	static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
-};
-
-template<class T> std::basic_string<T> LLStringUtilBase<T>::null;
-template<class T> std::string LLStringUtilBase<T>::sLocale;
-
-typedef LLStringUtilBase<char> LLStringUtil;
-typedef LLStringUtilBase<llwchar> LLWStringUtil;
-typedef std::basic_string<llwchar> LLWString;
-
-//@ Use this where we want to disallow input in the form of "foo"
-//  This is used to catch places where english text is embedded in the code
-//  instead of in a translatable XUI file.
-class LLStringExplicit : public std::string
-{
-public:
-	explicit LLStringExplicit(const char* s) : std::string(s) {}
-	LLStringExplicit(const std::string& s) : std::string(s) {}
-	LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : std::string(s, pos, n) {}
-};
-
-struct LLDictionaryLess
-{
-public:
-	bool operator()(const std::string& a, const std::string& b)
-	{
-		return (LLStringUtil::precedesDict(a, b) ? true : false);
-	}
-};
-
-
-/**
- * Simple support functions
- */
-
-/**
- * @brief chop off the trailing characters in a string.
- *
- * This function works on bytes rather than glyphs, so this will
- * incorrectly truncate non-single byte strings.
- * Use utf8str_truncate() for utf8 strings
- * @return a copy of in string minus the trailing count bytes.
- */
-inline std::string chop_tail_copy(
-	const std::string& in,
-	std::string::size_type count)
-{
-	return std::string(in, 0, in.length() - count);
-}
-
-/**
- * @brief This translates a nybble stored as a hex value from 0-f back
- * to a nybble in the low order bits of the return byte.
- */
-U8 hex_as_nybble(char hex);
-
-/**
- * @brief read the contents of a file into a string.
- *
- * Since this function has no concept of character encoding, most
- * anything you do with this method ill-advised. Please avoid.
- * @param str [out] The string which will have.
- * @param filename The full name of the file to read.
- * @return Returns true on success. If false, str is unmodified.
- */
-bool _read_file_into_string(std::string& str, const std::string& filename);
-bool iswindividual(llwchar elem);
-
-/**
- * Unicode support
- */
-
-// Make the incoming string a utf8 string. Replaces any unknown glyph
-// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
-// of the data may not be recovered.
-std::string rawstr_to_utf8(const std::string& raw);
-
-//
-// We should never use UTF16 except when communicating with Win32!
-//
-typedef std::basic_string<U16> llutf16string;
-
-LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
-LLWString utf16str_to_wstring(const llutf16string &utf16str);
-
-llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
-llutf16string wstring_to_utf16str(const LLWString &utf32str);
-
-llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
-llutf16string utf8str_to_utf16str ( const std::string& utf8str );
-
-LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
-LLWString utf8str_to_wstring(const std::string &utf8str);
-// Same function, better name. JC
-inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
-
-//
-S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
-
-std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
-std::string wstring_to_utf8str(const LLWString &utf32str);
-
-std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
-std::string utf16str_to_utf8str(const llutf16string &utf16str);
-
-// Length of this UTF32 string in bytes when transformed to UTF8
-S32 wstring_utf8_length(const LLWString& wstr); 
-
-// Length in bytes of this wide char in a UTF8 string
-S32 wchar_utf8_length(const llwchar wc); 
-
-std::string utf8str_tolower(const std::string& utf8str);
-
-// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
-S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
-
-// Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
-S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
-
-// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.)
-S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
-
-/**
- * @brief Properly truncate a utf8 string to a maximum byte count.
- * 
- * The returned string may be less than max_len if the truncation
- * happens in the middle of a glyph. If max_len is longer than the
- * string passed in, the return value == utf8str.
- * @param utf8str A valid utf8 string to truncate.
- * @param max_len The maximum number of bytes in the return value.
- * @return Returns a valid utf8 string with byte count <= max_len.
- */
-std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
-
-std::string utf8str_trim(const std::string& utf8str);
-
-S32 utf8str_compare_insensitive(
-	const std::string& lhs,
-	const std::string& rhs);
-
-/**
- * @brief Replace all occurences of target_char with replace_char
- *
- * @param utf8str A utf8 string to process.
- * @param target_char The wchar to be replaced
- * @param replace_char The wchar which is written on replace
- */
-std::string utf8str_substChar(
-	const std::string& utf8str,
-	const llwchar target_char,
-	const llwchar replace_char);
-
-std::string utf8str_makeASCII(const std::string& utf8str);
-
-// Hack - used for evil notecards.
-std::string mbcsstring_makeASCII(const std::string& str); 
-
-std::string utf8str_removeCRLF(const std::string& utf8str);
-
-
-#if LL_WINDOWS
-/* @name Windows string helpers
- */
-//@{
-
-/**
- * @brief Implementation the expected snprintf interface.
- *
- * If the size of the passed in buffer is not large enough to hold the string,
- * two bad things happen:
- * 1. resulting formatted string is NOT null terminated
- * 2. Depending on the platform, the return value could be a) the required
- *    size of the buffer to copy the entire formatted string or b) -1.
- *    On Windows with VS.Net 2003, it returns -1 e.g. 
- *
- * safe_snprintf always adds a NULL terminator so that the caller does not
- * need to check for return value or need to add the NULL terminator.
- * It does not, however change the return value - to let the caller know
- * that the passed in buffer size was not large enough to hold the
- * formatted string.
- *
- */
-int safe_snprintf(char* str, size_t size, const char* format, ...);
-
-/**
- * @brief Convert a wide string to std::string
- *
- * This replaces the unsafe W2A macro from ATL.
- */
-std::string ll_convert_wide_to_string(const wchar_t* in);
-
-//@}
-#endif // LL_WINDOWS
-
-/**
- * Many of the 'strip' and 'replace' methods of LLStringUtilBase need
- * specialization to work with the signed char type.
- * Sadly, it is not possible (AFAIK) to specialize a single method of
- * a template class.
- * That stuff should go here.
- */
-namespace LLStringFn
-{
-	/**
-	 * @brief Replace all non-printable characters with replacement in
-	 * string.
-	 * NOTE - this will zap non-ascii
-	 *
-	 * @param [in,out] string the to modify. out value is the string
-	 * with zero non-printable characters.
-	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
-	 */
-	void replace_nonprintable_in_ascii(
-		std::basic_string<char>& string,
-		char replacement);
-
-
-	/**
-	 * @brief Replace all non-printable characters and pipe characters
-	 * with replacement in a string.
-	 * NOTE - this will zap non-ascii
-	 *
-	 * @param [in,out] the string to modify. out value is the string
-	 * with zero non-printable characters and zero pipe characters.
-	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
-	 */
-	void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
-									   char replacement);
-
-
-	/**
-	 * @brief Remove all characters that are not allowed in XML 1.0.
-	 * Returns a copy of the string with those characters removed.
-	 * Works with US ASCII and UTF-8 encoded strings.  JC
-	 */
-	std::string strip_invalid_xml(const std::string& input);
-
-
-	/**
-	 * @brief Replace all control characters (0 <= c < 0x20) with replacement in
-	 * string.   This is safe for utf-8
-	 *
-	 * @param [in,out] string the to modify. out value is the string
-	 * with zero non-printable characters.
-	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
-	 */
-	void replace_ascii_controlchars(
-		std::basic_string<char>& string,
-		char replacement);
-}
-
-////////////////////////////////////////////////////////////
-// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp.
-// There is no LLWStringUtil::format implementation currently.
-// Calling thse for anything other than LLStringUtil will produce link errors.
-
-////////////////////////////////////////////////////////////
-
-
-// static
-template<class T> 
-S32 LLStringUtilBase<T>::compareStrings(const T* lhs, const T* rhs)
-{	
-	S32 result;
-	if( lhs == rhs )
-	{
-		result = 0;
-	}
-	else
-	if ( !lhs || !lhs[0] )
-	{
-		result = ((!rhs || !rhs[0]) ? 0 : 1);
-	}
-	else
-	if ( !rhs || !rhs[0])
-	{
-		result = -1;
-	}
-	else
-	{
-		result = LLStringOps::collate(lhs, rhs);
-	}
-	return result;
-}
-
-//static 
-template<class T> 
-S32 LLStringUtilBase<T>::compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
-{
-	return LLStringOps::collate(lhs.c_str(), rhs.c_str());
-}
-
-// static
-template<class T> 
-S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs )
-{
-	S32 result;
-	if( lhs == rhs )
-	{
-		result = 0;
-	}
-	else
-	if ( !lhs || !lhs[0] )
-	{
-		result = ((!rhs || !rhs[0]) ? 0 : 1);
-	}
-	else
-	if ( !rhs || !rhs[0] )
-	{
-		result = -1;
-	}
-	else
-	{
-		std::basic_string<T> lhs_string(lhs);
-		std::basic_string<T> rhs_string(rhs);
-		LLStringUtilBase<T>::toUpper(lhs_string);
-		LLStringUtilBase<T>::toUpper(rhs_string);
-		result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
-	}
-	return result;
-}
-
-//static 
-template<class T> 
-S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
-{
-	std::basic_string<T> lhs_string(lhs);
-	std::basic_string<T> rhs_string(rhs);
-	LLStringUtilBase<T>::toUpper(lhs_string);
-	LLStringUtilBase<T>::toUpper(rhs_string);
-	return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
-}
-
-// Case sensitive comparison with good handling of numbers.  Does not use current locale.
-// a.k.a. strdictcmp()
-
-//static 
-template<class T>
-S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
-{
-	const T* a = astr.c_str();
-	const T* b = bstr.c_str();
-	T ca, cb;
-	S32 ai, bi, cnt = 0;
-	S32 bias = 0;
-
-	ca = *(a++);
-	cb = *(b++);
-	while( ca && cb ){
-		if( bias==0 ){
-			if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; }
-			if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; }
-		}else{
-			if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
-			if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
-		}
-		if( LLStringOps::isDigit(ca) ){
-			if( cnt-->0 ){
-				if( cb!=ca ) break;
-			}else{
-				if( !LLStringOps::isDigit(cb) ) break;
-				for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
-				for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
-				if( ai<bi ){ ca=0; break; }
-				if( bi<ai ){ cb=0; break; }
-				if( ca!=cb ) break;
-				cnt = ai;
-			}
-		}else if( ca!=cb ){   break;
-		}
-		ca = *(a++);
-		cb = *(b++);
-	}
-	if( ca==cb ) ca += bias;
-	return ca-cb;
-}
-
-// static
-template<class T>
-S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
-{
-	const T* a = astr.c_str();
-	const T* b = bstr.c_str();
-	T ca, cb;
-	S32 ai, bi, cnt = 0;
-
-	ca = *(a++);
-	cb = *(b++);
-	while( ca && cb ){
-		if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
-		if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
-		if( LLStringOps::isDigit(ca) ){
-			if( cnt-->0 ){
-				if( cb!=ca ) break;
-			}else{
-				if( !LLStringOps::isDigit(cb) ) break;
-				for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
-				for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
-				if( ai<bi ){ ca=0; break; }
-				if( bi<ai ){ cb=0; break; }
-				if( ca!=cb ) break;
-				cnt = ai;
-			}
-		}else if( ca!=cb ){   break;
-		}
-		ca = *(a++);
-		cb = *(b++);
-	}
-	return ca-cb;
-}
-
-// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
-// static 
-template<class T> 
-BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b )
-{
-	if( a.size() && b.size() )
-	{
-		return (LLStringUtilBase<T>::compareDict(a.c_str(), b.c_str()) < 0);
-	}
-	else
-	{
-		return (!b.empty());
-	}
-}
-
-//static
-template<class T> 
-void LLStringUtilBase<T>::toUpper(std::basic_string<T>& string)	
-{ 
-	if( !string.empty() )
-	{ 
-		std::transform(
-			string.begin(),
-			string.end(),
-			string.begin(),
-			(T(*)(T)) &LLStringOps::toUpper);
-	}
-}
-
-//static
-template<class T> 
-void LLStringUtilBase<T>::toLower(std::basic_string<T>& string)
-{ 
-	if( !string.empty() )
-	{ 
-		std::transform(
-			string.begin(),
-			string.end(),
-			string.begin(),
-			(T(*)(T)) &LLStringOps::toLower);
-	}
-}
-
-//static
-template<class T> 
-void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string)
-{			
-	if( !string.empty() )
-	{
-		size_type i = 0;
-		while( i < string.length() && LLStringOps::isSpace( string[i] ) )
-		{
-			i++;
-		}
-		string.erase(0, i);
-	}
-}
-
-//static
-template<class T> 
-void LLStringUtilBase<T>::trimTail(std::basic_string<T>& string)
-{			
-	if( string.size() )
-	{
-		size_type len = string.length();
-		size_type i = len;
-		while( i > 0 && LLStringOps::isSpace( string[i-1] ) )
-		{
-			i--;
-		}
-
-		string.erase( i, len - i );
-	}
-}
-
-
-// Replace line feeds with carriage return-line feed pairs.
-//static
-template<class T>
-void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string)
-{
-	const T LF = 10;
-	const T CR = 13;
-
-	// Count the number of line feeds
-	size_type count = 0;
-	size_type len = string.size();
-	size_type i;
-	for( i = 0; i < len; i++ )
-	{
-		if( string[i] == LF )
-		{
-			count++;
-		}
-	}
-
-	// Insert a carriage return before each line feed
-	if( count )
-	{
-		size_type size = len + count;
-		T *t = new T[size];
-		size_type j = 0;
-		for( i = 0; i < len; ++i )
-		{
-			if( string[i] == LF )
-			{
-				t[j] = CR;
-				++j;
-			}
-			t[j] = string[i];
-			++j;
-		}
-
-		string.assign(t, size);
-	}
-}
-
-// Remove all carriage returns
-//static
-template<class T> 
-void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& string)
-{
-	const T CR = 13;
-
-	size_type cr_count = 0;
-	size_type len = string.size();
-	size_type i;
-	for( i = 0; i < len - cr_count; i++ )
-	{
-		if( string[i+cr_count] == CR )
-		{
-			cr_count++;
-		}
-
-		string[i] = string[i+cr_count];
-	}
-	string.erase(i, cr_count);
-}
-
-//static
-template<class T> 
-void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
-{
-	size_type found_pos = 0;
-	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) 
-	{
-		string[found_pos] = replacement;
-		found_pos++; // avoid infinite defeat if target == replacement
-	}
-}
-
-//static
-template<class T> 
-void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement )
-{
-	size_type found_pos = 0;
-	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
-	{
-		string.replace( found_pos, target.length(), replacement );
-		found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
-	}
-}
-
-//static
-template<class T> 
-void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T replacement )
-{
-	const char LF = 10;
-	const S8 MIN = 32;
-//	const S8 MAX = 127;
-
-	size_type len = string.size();
-	for( size_type i = 0; i < len; i++ )
-	{
-		// No need to test MAX < mText[i] because we treat mText[i] as a signed char,
-		// which has a max value of 127.
-		if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
-		{
-			string[i] = replacement;
-		}
-	}
-}
-
-//static
-template<class T> 
-void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab )
-{
-	const T TAB = '\t';
-	const T SPACE = ' ';
-
-	std::basic_string<T> out_str;
-	// Replace tabs with spaces
-	for (size_type i = 0; i < str.length(); i++)
-	{
-		if (str[i] == TAB)
-		{
-			for (size_type j = 0; j < spaces_per_tab; j++)
-				out_str += SPACE;
-		}
-		else
-		{
-			out_str += str[i];
-		}
-	}
-	str = out_str;
-}
-
-//static
-template<class T> 
-BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& string)
-{
-	const char MIN = 32;
-	BOOL rv = FALSE;
-	for (size_type i = 0; i < string.size(); i++)
-	{
-		if(string[i] < MIN)
-		{
-			rv = TRUE;
-			break;
-		}
-	}
-	return rv;
-}
-
-//static
-template<class T> 
-void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string)
-{
-	const char MIN = 32;
-	size_type j = 0;
-	if (string.empty())
-	{
-		return;
-	}
-	size_t src_size = string.size();
-	char* c_string = new char[src_size + 1];
-	if(c_string == NULL)
-	{
-		return;
-	}
-	copy(c_string, string.c_str(), src_size+1);
-	char* write_head = &c_string[0];
-	for (size_type i = 0; i < src_size; i++)
-	{
-		char* read_head = &string[i];
-		write_head = &c_string[j];
-		if(!(*read_head < MIN))
-		{
-			*write_head = *read_head;
-			++j;
-		}
-	}
-	c_string[j]= '\0';
-	string = c_string;
-	delete []c_string;
-}
-
-template<class T> 
-void LLStringUtilBase<T>::_makeASCII(std::basic_string<T>& string)
-{
-	// Replace non-ASCII chars with LL_UNKNOWN_CHAR
-	for (size_type i = 0; i < string.length(); i++)
-	{
-		if (string[i] > 0x7f)
-		{
-			string[i] = LL_UNKNOWN_CHAR;
-		}
-	}
-}
-
-// static
-template<class T> 
-void LLStringUtilBase<T>::copy( T* dst, const T* src, size_type dst_size )
-{
-	if( dst_size > 0 )
-	{
-		size_type min_len = 0;
-		if( src )
-		{
-			min_len = llmin( dst_size - 1, strlen( src ) );  /* Flawfinder: ignore */
-			memcpy(dst, src, min_len * sizeof(T));		/* Flawfinder: ignore */
-		}
-		dst[min_len] = '\0';
-	}
-}
-
-// static
-template<class T> 
-void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset)
-{
-	if ( offset == dst.length() )
-	{
-		// special case - append to end of string and avoid expensive
-		// (when strings are large) string manipulations
-		dst += src;
-	}
-	else
-	{
-		std::basic_string<T> tail = dst.substr(offset);
-
-		dst = dst.substr(0, offset);
-		dst += src;
-		dst += tail;
-	};
-}
-
-// True if this is the head of s.
-//static
-template<class T> 
-BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s ) 
-{ 
-	if( string.empty() )
-	{
-		// Early exit
-		return FALSE;
-	}
-	else
-	{
-		return (strncmp( s, string.c_str(), string.size() ) == 0);
-	}
-}
-
-// static
-template<class T> 
-bool LLStringUtilBase<T>::startsWith(
-	const std::basic_string<T>& string,
-	const std::basic_string<T>& substr)
-{
-	if(string.empty() || (substr.empty())) return false;
-	if(0 == string.find(substr)) return true;
-	return false;
-}
-
-// static
-template<class T> 
-bool LLStringUtilBase<T>::endsWith(
-	const std::basic_string<T>& string,
-	const std::basic_string<T>& substr)
-{
-	if(string.empty() || (substr.empty())) return false;
-	std::string::size_type idx = string.rfind(substr);
-	if(std::string::npos == idx) return false;
-	return (idx == (string.size() - substr.size()));
-}
-
-
-template<class T> 
-BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value)
-{
-	if( string.empty() )
-	{
-		return FALSE;
-	}
-
-	std::basic_string<T> temp( string );
-	trim(temp);
-	if( 
-		(temp == "1") || 
-		(temp == "T") || 
-		(temp == "t") || 
-		(temp == "TRUE") || 
-		(temp == "true") || 
-		(temp == "True") )
-	{
-		value = TRUE;
-		return TRUE;
-	}
-	else
-	if( 
-		(temp == "0") || 
-		(temp == "F") || 
-		(temp == "f") || 
-		(temp == "FALSE") || 
-		(temp == "false") || 
-		(temp == "False") )
-	{
-		value = FALSE;
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-template<class T> 
-BOOL LLStringUtilBase<T>::convertToU8(const std::basic_string<T>& string, U8& value) 
-{
-	S32 value32 = 0;
-	BOOL success = convertToS32(string, value32);
-	if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) )
-	{
-		value = (U8) value32;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-template<class T> 
-BOOL LLStringUtilBase<T>::convertToS8(const std::basic_string<T>& string, S8& value) 
-{
-	S32 value32 = 0;
-	BOOL success = convertToS32(string, value32);
-	if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) )
-	{
-		value = (S8) value32;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-template<class T> 
-BOOL LLStringUtilBase<T>::convertToS16(const std::basic_string<T>& string, S16& value) 
-{
-	S32 value32 = 0;
-	BOOL success = convertToS32(string, value32);
-	if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) )
-	{
-		value = (S16) value32;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-template<class T> 
-BOOL LLStringUtilBase<T>::convertToU16(const std::basic_string<T>& string, U16& value) 
-{
-	S32 value32 = 0;
-	BOOL success = convertToS32(string, value32);
-	if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) )
-	{
-		value = (U16) value32;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-template<class T> 
-BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32& value) 
-{
-	if( string.empty() )
-	{
-		return FALSE;
-	}
-
-	std::basic_string<T> temp( string );
-	trim(temp);
-	U32 v;
-	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
-	if(i_stream >> v)
-	{
-		value = v;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-template<class T> 
-BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& value) 
-{
-	if( string.empty() )
-	{
-		return FALSE;
-	}
-
-	std::basic_string<T> temp( string );
-	trim(temp);
-	S32 v;
-	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
-	if(i_stream >> v)
-	{
-		//TODO: figure out overflow and underflow reporting here
-		//if((LONG_MAX == v) || (LONG_MIN == v))
-		//{
-		//	// Underflow or overflow
-		//	return FALSE;
-		//}
-
-		value = v;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-template<class T> 
-BOOL LLStringUtilBase<T>::convertToF32(const std::basic_string<T>& string, F32& value) 
-{
-	F64 value64 = 0.0;
-	BOOL success = convertToF64(string, value64);
-	if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) )
-	{
-		value = (F32) value64;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-template<class T> 
-BOOL LLStringUtilBase<T>::convertToF64(const std::basic_string<T>& string, F64& value)
-{
-	if( string.empty() )
-	{
-		return FALSE;
-	}
-
-	std::basic_string<T> temp( string );
-	trim(temp);
-	F64 v;
-	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
-	if(i_stream >> v)
-	{
-		//TODO: figure out overflow and underflow reporting here
-		//if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) )
-		//{
-		//	// Underflow or overflow
-		//	return FALSE;
-		//}
-
-		value = v;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-template<class T> 
-void LLStringUtilBase<T>::truncate(std::basic_string<T>& string, size_type count)
-{
-	size_type cur_size = string.size();
-	string.resize(count < cur_size ? count : cur_size);
-}
-
-#endif  // LL_STRING_H
+/** 
+ * @file llstring.h
+ * @brief String utility functions and std::string class.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSTRING_H
+#define LL_LLSTRING_H
+
+#include <string>
+#include <cstdio>
+#include <locale>
+#include <iomanip>
+#include "llsd.h"
+#include "llfasttimer.h"
+
+#if LL_LINUX || LL_SOLARIS
+#include <wctype.h>
+#include <wchar.h>
+#endif
+
+#include <string.h>
+
+#if LL_SOLARIS
+// stricmp and strnicmp do not exist on Solaris:
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+#endif
+
+const char LL_UNKNOWN_CHAR = '?';
+
+#if LL_DARWIN || LL_LINUX || LL_SOLARIS
+// Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already)
+#include <cstring>
+
+namespace std
+{
+template<>
+struct char_traits<U16>
+{
+	typedef U16 		char_type;
+	typedef int 	    int_type;
+	typedef streampos 	pos_type;
+	typedef streamoff 	off_type;
+	typedef mbstate_t 	state_type;
+	
+	static void 
+		assign(char_type& __c1, const char_type& __c2)
+	{ __c1 = __c2; }
+	
+	static bool 
+		eq(const char_type& __c1, const char_type& __c2)
+	{ return __c1 == __c2; }
+	
+	static bool 
+		lt(const char_type& __c1, const char_type& __c2)
+	{ return __c1 < __c2; }
+	
+	static int 
+		compare(const char_type* __s1, const char_type* __s2, size_t __n)
+	{ return memcmp(__s1, __s2, __n * sizeof(char_type)); }
+	
+	static size_t
+		length(const char_type* __s)
+	{
+		const char_type *cur_char = __s;
+		while (*cur_char != 0)
+		{
+			++cur_char;
+		}
+		return cur_char - __s;
+	}
+	
+	static const char_type* 
+		find(const char_type* __s, size_t __n, const char_type& __a)
+	{ return static_cast<const char_type*>(memchr(__s, __a, __n * sizeof(char_type))); }
+	
+	static char_type* 
+		move(char_type* __s1, const char_type* __s2, size_t __n)
+	{ return static_cast<char_type*>(memmove(__s1, __s2, __n * sizeof(char_type))); }
+	
+	static char_type* 
+		copy(char_type* __s1, const char_type* __s2, size_t __n)
+	{  return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); }	/* Flawfinder: ignore */
+	
+	static char_type* 
+		assign(char_type* __s, size_t __n, char_type __a)
+	{ 
+		// This isn't right.
+		//return static_cast<char_type*>(memset(__s, __a, __n * sizeof(char_type))); 
+		
+		// I don't think there's a standard 'memset' for 16-bit values.
+		// Do this the old-fashioned way.
+		
+		size_t __i;
+		for(__i = 0; __i < __n; __i++)
+		{
+			__s[__i] = __a;
+		}
+		return __s; 
+	}
+	
+	static char_type 
+		to_char_type(const int_type& __c)
+	{ return static_cast<char_type>(__c); }
+	
+	static int_type 
+		to_int_type(const char_type& __c)
+	{ return static_cast<int_type>(__c); }
+	
+	static bool 
+		eq_int_type(const int_type& __c1, const int_type& __c2)
+	{ return __c1 == __c2; }
+	
+	static int_type 
+		eof() { return static_cast<int_type>(EOF); }
+	
+	static int_type 
+		not_eof(const int_type& __c)
+      { return (__c == eof()) ? 0 : __c; }
+  };
+};
+#endif
+
+class LL_COMMON_API LLStringOps
+{
+private:
+	static long sPacificTimeOffset;
+	static long sLocalTimeOffset;
+	static bool sPacificDaylightTime;
+	static std::map<std::string, std::string> datetimeToCodes;
+
+public:
+	static char toUpper(char elem) { return toupper((unsigned char)elem); }
+	static llwchar toUpper(llwchar elem) { return towupper(elem); }
+	
+	static char toLower(char elem) { return tolower((unsigned char)elem); }
+	static llwchar toLower(llwchar elem) { return towlower(elem); }
+
+	static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; }
+	static bool isSpace(llwchar elem) { return iswspace(elem) != 0; }
+
+	static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; }
+	static bool isUpper(llwchar elem) { return iswupper(elem) != 0; }
+
+	static bool isLower(char elem) { return islower((unsigned char)elem) != 0; }
+	static bool isLower(llwchar elem) { return iswlower(elem) != 0; }
+
+	static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; }
+	static bool isDigit(llwchar a) { return iswdigit(a) != 0; }
+
+	static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; }
+	static bool isPunct(llwchar a) { return iswpunct(a) != 0; }
+
+	static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
+	static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
+
+	static S32	collate(const char* a, const char* b) { return strcoll(a, b); }
+	static S32	collate(const llwchar* a, const llwchar* b);
+
+	static void setupDatetimeInfo(bool pacific_daylight_time);
+	static long getPacificTimeOffset(void) { return sPacificTimeOffset;}
+	static long getLocalTimeOffset(void) { return sLocalTimeOffset;}
+	// Is the Pacific time zone (aka server time zone)
+	// currently in daylight savings time?
+	static bool getPacificDaylightTime(void) { return sPacificDaylightTime;}
+
+	static std::string getDatetimeCode (std::string key);
+};
+
+/**
+ * @brief Return a string constructed from in without crashing if the
+ * pointer is NULL.
+ */
+LL_COMMON_API std::string ll_safe_string(const char* in);
+LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen);
+
+
+// Allowing assignments from non-strings into format_map_t is apparently
+// *really* error-prone, so subclass std::string with just basic c'tors.
+class LLFormatMapString
+{
+public:
+	LLFormatMapString() {};
+	LLFormatMapString(const char* s) : mString(ll_safe_string(s)) {};
+	LLFormatMapString(const std::string& s) : mString(s) {};
+	operator std::string() const { return mString; }
+	bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; }
+	std::size_t length() const { return mString.length(); }
+	
+private:
+	std::string mString;
+};
+
+template <class T>
+class LLStringUtilBase
+{
+private:
+	static std::string sLocale;
+
+public:
+	typedef typename std::basic_string<T>::size_type size_type;
+	
+public:
+	/////////////////////////////////////////////////////////////////////////////////////////
+	// Static Utility functions that operate on std::strings
+
+	static std::basic_string<T> null;
+	
+	typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
+	LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
+	LL_COMMON_API static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
+	LL_COMMON_API static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
+	LL_COMMON_API static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
+	LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
+	LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
+	LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions);
+	static void setLocale (std::string inLocale) {sLocale = inLocale;};
+	static std::string getLocale (void) {return sLocale;};
+	
+	static bool isValidIndex(const std::basic_string<T>& string, size_type i)
+	{
+		return !string.empty() && (0 <= i) && (i <= string.size());
+	}
+
+	static void	trimHead(std::basic_string<T>& string);
+	static void	trimTail(std::basic_string<T>& string);
+	static void	trim(std::basic_string<T>& string)	{ trimHead(string); trimTail(string); }
+	static void truncate(std::basic_string<T>& string, size_type count);
+
+	static void	toUpper(std::basic_string<T>& string);
+	static void	toLower(std::basic_string<T>& string);
+	
+	// True if this is the head of s.
+	static BOOL	isHead( const std::basic_string<T>& string, const T* s ); 
+
+	/**
+	 * @brief Returns true if string starts with substr
+	 *
+	 * If etither string or substr are empty, this method returns false.
+	 */
+	static bool startsWith(
+		const std::basic_string<T>& string,
+		const std::basic_string<T>& substr);
+
+	/**
+	 * @brief Returns true if string ends in substr
+	 *
+	 * If etither string or substr are empty, this method returns false.
+	 */
+	static bool endsWith(
+		const std::basic_string<T>& string,
+		const std::basic_string<T>& substr);
+
+	static void	addCRLF(std::basic_string<T>& string);
+	static void	removeCRLF(std::basic_string<T>& string);
+
+	static void	replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab );
+	static void	replaceNonstandardASCII( std::basic_string<T>& string, T replacement );
+	static void	replaceChar( std::basic_string<T>& string, T target, T replacement );
+	static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement );
+	
+	static BOOL	containsNonprintable(const std::basic_string<T>& string);
+	static void	stripNonprintable(std::basic_string<T>& string);
+
+	/**
+	 * @brief Unsafe way to make ascii characters. You should probably
+	 * only call this when interacting with the host operating system.
+	 * The 1 byte std::string does not work correctly.
+	 * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII
+	 * should work.
+	 */
+	static void _makeASCII(std::basic_string<T>& string);
+
+	// Conversion to other data types
+	static BOOL	convertToBOOL(const std::basic_string<T>& string, BOOL& value);
+	static BOOL	convertToU8(const std::basic_string<T>& string, U8& value);
+	static BOOL	convertToS8(const std::basic_string<T>& string, S8& value);
+	static BOOL	convertToS16(const std::basic_string<T>& string, S16& value);
+	static BOOL	convertToU16(const std::basic_string<T>& string, U16& value);
+	static BOOL	convertToU32(const std::basic_string<T>& string, U32& value);
+	static BOOL	convertToS32(const std::basic_string<T>& string, S32& value);
+	static BOOL	convertToF32(const std::basic_string<T>& string, F32& value);
+	static BOOL	convertToF64(const std::basic_string<T>& string, F64& value);
+
+	/////////////////////////////////////////////////////////////////////////////////////////
+	// Utility functions for working with char*'s and strings
+
+	// Like strcmp but also handles empty strings. Uses
+	// current locale.
+	static S32		compareStrings(const T* lhs, const T* rhs);
+	static S32		compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
+	
+	// case insensitive version of above. Uses current locale on
+	// Win32, and falls back to a non-locale aware comparison on
+	// Linux.
+	static S32		compareInsensitive(const T* lhs, const T* rhs);
+	static S32		compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
+
+	// Case sensitive comparison with good handling of numbers.  Does not use current locale.
+	// a.k.a. strdictcmp()
+	static S32		compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b);
+
+	// Case *in*sensitive comparison with good handling of numbers.  Does not use current locale.
+	// a.k.a. strdictcmp()
+	static S32		compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b);
+
+	// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
+	static BOOL		precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
+
+	// A replacement for strncpy.
+	// If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds
+	// up to dst_size-1 characters of src.
+	static void		copy(T* dst, const T* src, size_type dst_size);
+	
+	// Copies src into dst at a given offset.  
+	static void		copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset);
+	
+	static bool		isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); }
+
+
+#ifdef _DEBUG	
+	LL_COMMON_API static void		testHarness();
+#endif
+
+private:
+	LL_COMMON_API static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
+};
+
+template<class T> std::basic_string<T> LLStringUtilBase<T>::null;
+template<class T> std::string LLStringUtilBase<T>::sLocale;
+
+typedef LLStringUtilBase<char> LLStringUtil;
+typedef LLStringUtilBase<llwchar> LLWStringUtil;
+typedef std::basic_string<llwchar> LLWString;
+
+//@ Use this where we want to disallow input in the form of "foo"
+//  This is used to catch places where english text is embedded in the code
+//  instead of in a translatable XUI file.
+class LLStringExplicit : public std::string
+{
+public:
+	explicit LLStringExplicit(const char* s) : std::string(s) {}
+	LLStringExplicit(const std::string& s) : std::string(s) {}
+	LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : std::string(s, pos, n) {}
+};
+
+struct LLDictionaryLess
+{
+public:
+	bool operator()(const std::string& a, const std::string& b)
+	{
+		return (LLStringUtil::precedesDict(a, b) ? true : false);
+	}
+};
+
+
+/**
+ * Simple support functions
+ */
+
+/**
+ * @brief chop off the trailing characters in a string.
+ *
+ * This function works on bytes rather than glyphs, so this will
+ * incorrectly truncate non-single byte strings.
+ * Use utf8str_truncate() for utf8 strings
+ * @return a copy of in string minus the trailing count bytes.
+ */
+inline std::string chop_tail_copy(
+	const std::string& in,
+	std::string::size_type count)
+{
+	return std::string(in, 0, in.length() - count);
+}
+
+/**
+ * @brief This translates a nybble stored as a hex value from 0-f back
+ * to a nybble in the low order bits of the return byte.
+ */
+LL_COMMON_API U8 hex_as_nybble(char hex);
+
+/**
+ * @brief read the contents of a file into a string.
+ *
+ * Since this function has no concept of character encoding, most
+ * anything you do with this method ill-advised. Please avoid.
+ * @param str [out] The string which will have.
+ * @param filename The full name of the file to read.
+ * @return Returns true on success. If false, str is unmodified.
+ */
+LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename);
+LL_COMMON_API bool iswindividual(llwchar elem);
+
+/**
+ * Unicode support
+ */
+
+// Make the incoming string a utf8 string. Replaces any unknown glyph
+// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
+// of the data may not be recovered.
+LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);
+
+//
+// We should never use UTF16 except when communicating with Win32!
+//
+typedef std::basic_string<U16> llutf16string;
+
+LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
+LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str);
+
+LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
+LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str);
+
+LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
+LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str );
+
+LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
+LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str);
+// Same function, better name. JC
+inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
+
+//
+LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
+
+LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
+LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
+
+LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
+LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
+
+// Length of this UTF32 string in bytes when transformed to UTF8
+LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr); 
+
+// Length in bytes of this wide char in a UTF8 string
+LL_COMMON_API S32 wchar_utf8_length(const llwchar wc); 
+
+LL_COMMON_API std::string utf8str_tolower(const std::string& utf8str);
+
+// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
+LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
+
+// Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
+LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
+
+// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.)
+LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
+
+/**
+ * @brief Properly truncate a utf8 string to a maximum byte count.
+ * 
+ * The returned string may be less than max_len if the truncation
+ * happens in the middle of a glyph. If max_len is longer than the
+ * string passed in, the return value == utf8str.
+ * @param utf8str A valid utf8 string to truncate.
+ * @param max_len The maximum number of bytes in the return value.
+ * @return Returns a valid utf8 string with byte count <= max_len.
+ */
+LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
+
+LL_COMMON_API std::string utf8str_trim(const std::string& utf8str);
+
+LL_COMMON_API S32 utf8str_compare_insensitive(
+	const std::string& lhs,
+	const std::string& rhs);
+
+/**
+ * @brief Replace all occurences of target_char with replace_char
+ *
+ * @param utf8str A utf8 string to process.
+ * @param target_char The wchar to be replaced
+ * @param replace_char The wchar which is written on replace
+ */
+LL_COMMON_API std::string utf8str_substChar(
+	const std::string& utf8str,
+	const llwchar target_char,
+	const llwchar replace_char);
+
+LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str);
+
+// Hack - used for evil notecards.
+LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str); 
+
+LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
+
+
+#if LL_WINDOWS
+/* @name Windows string helpers
+ */
+//@{
+
+/**
+ * @brief Implementation the expected snprintf interface.
+ *
+ * If the size of the passed in buffer is not large enough to hold the string,
+ * two bad things happen:
+ * 1. resulting formatted string is NOT null terminated
+ * 2. Depending on the platform, the return value could be a) the required
+ *    size of the buffer to copy the entire formatted string or b) -1.
+ *    On Windows with VS.Net 2003, it returns -1 e.g. 
+ *
+ * safe_snprintf always adds a NULL terminator so that the caller does not
+ * need to check for return value or need to add the NULL terminator.
+ * It does not, however change the return value - to let the caller know
+ * that the passed in buffer size was not large enough to hold the
+ * formatted string.
+ *
+ */
+
+// Deal with the differeneces on Windows
+namespace snprintf_hack
+{
+	LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...);
+}
+
+using snprintf_hack::snprintf;
+
+/**
+ * @brief Convert a wide string to std::string
+ *
+ * This replaces the unsafe W2A macro from ATL.
+ */
+LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in);
+
+//@}
+#endif // LL_WINDOWS
+
+/**
+ * Many of the 'strip' and 'replace' methods of LLStringUtilBase need
+ * specialization to work with the signed char type.
+ * Sadly, it is not possible (AFAIK) to specialize a single method of
+ * a template class.
+ * That stuff should go here.
+ */
+namespace LLStringFn
+{
+	/**
+	 * @brief Replace all non-printable characters with replacement in
+	 * string.
+	 * NOTE - this will zap non-ascii
+	 *
+	 * @param [in,out] string the to modify. out value is the string
+	 * with zero non-printable characters.
+	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
+	 */
+	LL_COMMON_API void replace_nonprintable_in_ascii(
+		std::basic_string<char>& string,
+		char replacement);
+
+
+	/**
+	 * @brief Replace all non-printable characters and pipe characters
+	 * with replacement in a string.
+	 * NOTE - this will zap non-ascii
+	 *
+	 * @param [in,out] the string to modify. out value is the string
+	 * with zero non-printable characters and zero pipe characters.
+	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
+	 */
+	LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
+									   char replacement);
+
+
+	/**
+	 * @brief Remove all characters that are not allowed in XML 1.0.
+	 * Returns a copy of the string with those characters removed.
+	 * Works with US ASCII and UTF-8 encoded strings.  JC
+	 */
+	LL_COMMON_API std::string strip_invalid_xml(const std::string& input);
+
+
+	/**
+	 * @brief Replace all control characters (0 <= c < 0x20) with replacement in
+	 * string.   This is safe for utf-8
+	 *
+	 * @param [in,out] string the to modify. out value is the string
+	 * with zero non-printable characters.
+	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
+	 */
+	LL_COMMON_API void replace_ascii_controlchars(
+		std::basic_string<char>& string,
+		char replacement);
+}
+
+////////////////////////////////////////////////////////////
+// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp.
+// There is no LLWStringUtil::format implementation currently.
+// Calling thse for anything other than LLStringUtil will produce link errors.
+
+////////////////////////////////////////////////////////////
+
+
+// static
+template<class T> 
+S32 LLStringUtilBase<T>::compareStrings(const T* lhs, const T* rhs)
+{	
+	S32 result;
+	if( lhs == rhs )
+	{
+		result = 0;
+	}
+	else
+	if ( !lhs || !lhs[0] )
+	{
+		result = ((!rhs || !rhs[0]) ? 0 : 1);
+	}
+	else
+	if ( !rhs || !rhs[0])
+	{
+		result = -1;
+	}
+	else
+	{
+		result = LLStringOps::collate(lhs, rhs);
+	}
+	return result;
+}
+
+//static 
+template<class T> 
+S32 LLStringUtilBase<T>::compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
+{
+	return LLStringOps::collate(lhs.c_str(), rhs.c_str());
+}
+
+// static
+template<class T> 
+S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs )
+{
+	S32 result;
+	if( lhs == rhs )
+	{
+		result = 0;
+	}
+	else
+	if ( !lhs || !lhs[0] )
+	{
+		result = ((!rhs || !rhs[0]) ? 0 : 1);
+	}
+	else
+	if ( !rhs || !rhs[0] )
+	{
+		result = -1;
+	}
+	else
+	{
+		std::basic_string<T> lhs_string(lhs);
+		std::basic_string<T> rhs_string(rhs);
+		LLStringUtilBase<T>::toUpper(lhs_string);
+		LLStringUtilBase<T>::toUpper(rhs_string);
+		result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
+	}
+	return result;
+}
+
+//static 
+template<class T> 
+S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
+{
+	std::basic_string<T> lhs_string(lhs);
+	std::basic_string<T> rhs_string(rhs);
+	LLStringUtilBase<T>::toUpper(lhs_string);
+	LLStringUtilBase<T>::toUpper(rhs_string);
+	return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
+}
+
+// Case sensitive comparison with good handling of numbers.  Does not use current locale.
+// a.k.a. strdictcmp()
+
+//static 
+template<class T>
+S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
+{
+	const T* a = astr.c_str();
+	const T* b = bstr.c_str();
+	T ca, cb;
+	S32 ai, bi, cnt = 0;
+	S32 bias = 0;
+
+	ca = *(a++);
+	cb = *(b++);
+	while( ca && cb ){
+		if( bias==0 ){
+			if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; }
+			if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; }
+		}else{
+			if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
+			if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
+		}
+		if( LLStringOps::isDigit(ca) ){
+			if( cnt-->0 ){
+				if( cb!=ca ) break;
+			}else{
+				if( !LLStringOps::isDigit(cb) ) break;
+				for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
+				for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
+				if( ai<bi ){ ca=0; break; }
+				if( bi<ai ){ cb=0; break; }
+				if( ca!=cb ) break;
+				cnt = ai;
+			}
+		}else if( ca!=cb ){   break;
+		}
+		ca = *(a++);
+		cb = *(b++);
+	}
+	if( ca==cb ) ca += bias;
+	return ca-cb;
+}
+
+// static
+template<class T>
+S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
+{
+	const T* a = astr.c_str();
+	const T* b = bstr.c_str();
+	T ca, cb;
+	S32 ai, bi, cnt = 0;
+
+	ca = *(a++);
+	cb = *(b++);
+	while( ca && cb ){
+		if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
+		if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
+		if( LLStringOps::isDigit(ca) ){
+			if( cnt-->0 ){
+				if( cb!=ca ) break;
+			}else{
+				if( !LLStringOps::isDigit(cb) ) break;
+				for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
+				for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
+				if( ai<bi ){ ca=0; break; }
+				if( bi<ai ){ cb=0; break; }
+				if( ca!=cb ) break;
+				cnt = ai;
+			}
+		}else if( ca!=cb ){   break;
+		}
+		ca = *(a++);
+		cb = *(b++);
+	}
+	return ca-cb;
+}
+
+// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
+// static 
+template<class T> 
+BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b )
+{
+	if( a.size() && b.size() )
+	{
+		return (LLStringUtilBase<T>::compareDict(a.c_str(), b.c_str()) < 0);
+	}
+	else
+	{
+		return (!b.empty());
+	}
+}
+
+//static
+template<class T> 
+void LLStringUtilBase<T>::toUpper(std::basic_string<T>& string)	
+{ 
+	if( !string.empty() )
+	{ 
+		std::transform(
+			string.begin(),
+			string.end(),
+			string.begin(),
+			(T(*)(T)) &LLStringOps::toUpper);
+	}
+}
+
+//static
+template<class T> 
+void LLStringUtilBase<T>::toLower(std::basic_string<T>& string)
+{ 
+	if( !string.empty() )
+	{ 
+		std::transform(
+			string.begin(),
+			string.end(),
+			string.begin(),
+			(T(*)(T)) &LLStringOps::toLower);
+	}
+}
+
+//static
+template<class T> 
+void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string)
+{			
+	if( !string.empty() )
+	{
+		size_type i = 0;
+		while( i < string.length() && LLStringOps::isSpace( string[i] ) )
+		{
+			i++;
+		}
+		string.erase(0, i);
+	}
+}
+
+//static
+template<class T> 
+void LLStringUtilBase<T>::trimTail(std::basic_string<T>& string)
+{			
+	if( string.size() )
+	{
+		size_type len = string.length();
+		size_type i = len;
+		while( i > 0 && LLStringOps::isSpace( string[i-1] ) )
+		{
+			i--;
+		}
+
+		string.erase( i, len - i );
+	}
+}
+
+
+// Replace line feeds with carriage return-line feed pairs.
+//static
+template<class T>
+void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string)
+{
+	const T LF = 10;
+	const T CR = 13;
+
+	// Count the number of line feeds
+	size_type count = 0;
+	size_type len = string.size();
+	size_type i;
+	for( i = 0; i < len; i++ )
+	{
+		if( string[i] == LF )
+		{
+			count++;
+		}
+	}
+
+	// Insert a carriage return before each line feed
+	if( count )
+	{
+		size_type size = len + count;
+		T *t = new T[size];
+		size_type j = 0;
+		for( i = 0; i < len; ++i )
+		{
+			if( string[i] == LF )
+			{
+				t[j] = CR;
+				++j;
+			}
+			t[j] = string[i];
+			++j;
+		}
+
+		string.assign(t, size);
+	}
+}
+
+// Remove all carriage returns
+//static
+template<class T> 
+void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& string)
+{
+	const T CR = 13;
+
+	size_type cr_count = 0;
+	size_type len = string.size();
+	size_type i;
+	for( i = 0; i < len - cr_count; i++ )
+	{
+		if( string[i+cr_count] == CR )
+		{
+			cr_count++;
+		}
+
+		string[i] = string[i+cr_count];
+	}
+	string.erase(i, cr_count);
+}
+
+//static
+template<class T> 
+void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
+{
+	size_type found_pos = 0;
+	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) 
+	{
+		string[found_pos] = replacement;
+		found_pos++; // avoid infinite defeat if target == replacement
+	}
+}
+
+//static
+template<class T> 
+void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement )
+{
+	size_type found_pos = 0;
+	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
+	{
+		string.replace( found_pos, target.length(), replacement );
+		found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
+	}
+}
+
+//static
+template<class T> 
+void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T replacement )
+{
+	const char LF = 10;
+	const S8 MIN = 32;
+//	const S8 MAX = 127;
+
+	size_type len = string.size();
+	for( size_type i = 0; i < len; i++ )
+	{
+		// No need to test MAX < mText[i] because we treat mText[i] as a signed char,
+		// which has a max value of 127.
+		if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
+		{
+			string[i] = replacement;
+		}
+	}
+}
+
+//static
+template<class T> 
+void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab )
+{
+	const T TAB = '\t';
+	const T SPACE = ' ';
+
+	std::basic_string<T> out_str;
+	// Replace tabs with spaces
+	for (size_type i = 0; i < str.length(); i++)
+	{
+		if (str[i] == TAB)
+		{
+			for (size_type j = 0; j < spaces_per_tab; j++)
+				out_str += SPACE;
+		}
+		else
+		{
+			out_str += str[i];
+		}
+	}
+	str = out_str;
+}
+
+//static
+template<class T> 
+BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& string)
+{
+	const char MIN = 32;
+	BOOL rv = FALSE;
+	for (size_type i = 0; i < string.size(); i++)
+	{
+		if(string[i] < MIN)
+		{
+			rv = TRUE;
+			break;
+		}
+	}
+	return rv;
+}
+
+//static
+template<class T> 
+void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string)
+{
+	const char MIN = 32;
+	size_type j = 0;
+	if (string.empty())
+	{
+		return;
+	}
+	size_t src_size = string.size();
+	char* c_string = new char[src_size + 1];
+	if(c_string == NULL)
+	{
+		return;
+	}
+	copy(c_string, string.c_str(), src_size+1);
+	char* write_head = &c_string[0];
+	for (size_type i = 0; i < src_size; i++)
+	{
+		char* read_head = &string[i];
+		write_head = &c_string[j];
+		if(!(*read_head < MIN))
+		{
+			*write_head = *read_head;
+			++j;
+		}
+	}
+	c_string[j]= '\0';
+	string = c_string;
+	delete []c_string;
+}
+
+template<class T> 
+void LLStringUtilBase<T>::_makeASCII(std::basic_string<T>& string)
+{
+	// Replace non-ASCII chars with LL_UNKNOWN_CHAR
+	for (size_type i = 0; i < string.length(); i++)
+	{
+		if (string[i] > 0x7f)
+		{
+			string[i] = LL_UNKNOWN_CHAR;
+		}
+	}
+}
+
+// static
+template<class T> 
+void LLStringUtilBase<T>::copy( T* dst, const T* src, size_type dst_size )
+{
+	if( dst_size > 0 )
+	{
+		size_type min_len = 0;
+		if( src )
+		{
+			min_len = llmin( dst_size - 1, strlen( src ) );  /* Flawfinder: ignore */
+			memcpy(dst, src, min_len * sizeof(T));		/* Flawfinder: ignore */
+		}
+		dst[min_len] = '\0';
+	}
+}
+
+// static
+template<class T> 
+void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset)
+{
+	if ( offset == dst.length() )
+	{
+		// special case - append to end of string and avoid expensive
+		// (when strings are large) string manipulations
+		dst += src;
+	}
+	else
+	{
+		std::basic_string<T> tail = dst.substr(offset);
+
+		dst = dst.substr(0, offset);
+		dst += src;
+		dst += tail;
+	};
+}
+
+// True if this is the head of s.
+//static
+template<class T> 
+BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s ) 
+{ 
+	if( string.empty() )
+	{
+		// Early exit
+		return FALSE;
+	}
+	else
+	{
+		return (strncmp( s, string.c_str(), string.size() ) == 0);
+	}
+}
+
+// static
+template<class T> 
+bool LLStringUtilBase<T>::startsWith(
+	const std::basic_string<T>& string,
+	const std::basic_string<T>& substr)
+{
+	if(string.empty() || (substr.empty())) return false;
+	if(0 == string.find(substr)) return true;
+	return false;
+}
+
+// static
+template<class T> 
+bool LLStringUtilBase<T>::endsWith(
+	const std::basic_string<T>& string,
+	const std::basic_string<T>& substr)
+{
+	if(string.empty() || (substr.empty())) return false;
+	std::string::size_type idx = string.rfind(substr);
+	if(std::string::npos == idx) return false;
+	return (idx == (string.size() - substr.size()));
+}
+
+
+template<class T> 
+BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value)
+{
+	if( string.empty() )
+	{
+		return FALSE;
+	}
+
+	std::basic_string<T> temp( string );
+	trim(temp);
+	if( 
+		(temp == "1") || 
+		(temp == "T") || 
+		(temp == "t") || 
+		(temp == "TRUE") || 
+		(temp == "true") || 
+		(temp == "True") )
+	{
+		value = TRUE;
+		return TRUE;
+	}
+	else
+	if( 
+		(temp == "0") || 
+		(temp == "F") || 
+		(temp == "f") || 
+		(temp == "FALSE") || 
+		(temp == "false") || 
+		(temp == "False") )
+	{
+		value = FALSE;
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+template<class T> 
+BOOL LLStringUtilBase<T>::convertToU8(const std::basic_string<T>& string, U8& value) 
+{
+	S32 value32 = 0;
+	BOOL success = convertToS32(string, value32);
+	if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) )
+	{
+		value = (U8) value32;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+template<class T> 
+BOOL LLStringUtilBase<T>::convertToS8(const std::basic_string<T>& string, S8& value) 
+{
+	S32 value32 = 0;
+	BOOL success = convertToS32(string, value32);
+	if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) )
+	{
+		value = (S8) value32;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+template<class T> 
+BOOL LLStringUtilBase<T>::convertToS16(const std::basic_string<T>& string, S16& value) 
+{
+	S32 value32 = 0;
+	BOOL success = convertToS32(string, value32);
+	if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) )
+	{
+		value = (S16) value32;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+template<class T> 
+BOOL LLStringUtilBase<T>::convertToU16(const std::basic_string<T>& string, U16& value) 
+{
+	S32 value32 = 0;
+	BOOL success = convertToS32(string, value32);
+	if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) )
+	{
+		value = (U16) value32;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+template<class T> 
+BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32& value) 
+{
+	if( string.empty() )
+	{
+		return FALSE;
+	}
+
+	std::basic_string<T> temp( string );
+	trim(temp);
+	U32 v;
+	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
+	if(i_stream >> v)
+	{
+		value = v;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+template<class T> 
+BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& value) 
+{
+	if( string.empty() )
+	{
+		return FALSE;
+	}
+
+	std::basic_string<T> temp( string );
+	trim(temp);
+	S32 v;
+	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
+	if(i_stream >> v)
+	{
+		//TODO: figure out overflow and underflow reporting here
+		//if((LONG_MAX == v) || (LONG_MIN == v))
+		//{
+		//	// Underflow or overflow
+		//	return FALSE;
+		//}
+
+		value = v;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+template<class T> 
+BOOL LLStringUtilBase<T>::convertToF32(const std::basic_string<T>& string, F32& value) 
+{
+	F64 value64 = 0.0;
+	BOOL success = convertToF64(string, value64);
+	if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) )
+	{
+		value = (F32) value64;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+template<class T> 
+BOOL LLStringUtilBase<T>::convertToF64(const std::basic_string<T>& string, F64& value)
+{
+	if( string.empty() )
+	{
+		return FALSE;
+	}
+
+	std::basic_string<T> temp( string );
+	trim(temp);
+	F64 v;
+	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
+	if(i_stream >> v)
+	{
+		//TODO: figure out overflow and underflow reporting here
+		//if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) )
+		//{
+		//	// Underflow or overflow
+		//	return FALSE;
+		//}
+
+		value = v;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+template<class T> 
+void LLStringUtilBase<T>::truncate(std::basic_string<T>& string, size_type count)
+{
+	size_type cur_size = string.size();
+	string.resize(count < cur_size ? count : cur_size);
+}
+
+#endif  // LL_STRING_H
diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h
index 888361b0b9a1168e77df70a3ac57aba8f5b134f8..d40c9d8dfdab77df16f2f72800756a5e0b74edcf 100644
--- a/indra/llcommon/llstringtable.h
+++ b/indra/llcommon/llstringtable.h
@@ -48,15 +48,17 @@
 //# define STRING_TABLE_HASH_MAP 1
 #endif
 
-#if LL_WINDOWS
-#include <hash_map>
-#else
-#include <ext/hash_map>
+#if STRING_TABLE_HASH_MAP
+# if LL_WINDOWS
+#  include <hash_map>
+# else
+#  include <ext/hash_map>
+# endif
 #endif
 
 const U32 MAX_STRINGS_LENGTH = 256;
 
-class LLStringTableEntry
+class LL_COMMON_API LLStringTableEntry
 {
 public:
 	LLStringTableEntry(const char *str);
@@ -69,7 +71,7 @@ class LLStringTableEntry
 	S32  mCount;
 };
 
-class LLStringTable
+class LL_COMMON_API LLStringTable
 {
 public:
 	LLStringTable(int tablesize);
@@ -103,7 +105,7 @@ class LLStringTable
 #endif	
 };
 
-extern LLStringTable gStringTable;
+extern LL_COMMON_API LLStringTable gStringTable;
 
 //============================================================================
 
@@ -113,7 +115,7 @@ extern LLStringTable gStringTable;
 
 typedef const std::string* LLStdStringHandle;
 
-class LLStdStringTable
+class LL_COMMON_API LLStdStringTable
 {
 public:
 	LLStdStringTable(S32 tablesize = 0)
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 47374212893cbda75bbc9c0f3aa58279fa4b1932..3652eeba729a282be83c6561fc7edbd9a42aae7a 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -161,8 +161,16 @@ LLOSInfo::LLOSInfo() :
 						mOSStringSimple = "Microsoft Windows Vista Server ";
 				}
 			}
+			else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1)
+			{
+				 if(osvi.wProductType == VER_NT_WORKSTATION)
+					mOSStringSimple = "Microsoft Windows 7 ";
+				 else mOSStringSimple = "Microsoft Windows 7 Server ";
+			}
 			else   // Use the registry on early versions of Windows NT.
 			{
+				mOSStringSimple = "Microsoft Windows (unrecognized) ";
+
 				HKEY hKey;
 				WCHAR szProductType[80];
 				DWORD dwBufLen;
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index 03f48ca0187cbe5a1d21e3230ece3325be510945..c2c45bec9a2a01ea8ce735a70d4d0995176a0a56 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -45,7 +45,7 @@
 #include <iosfwd>
 #include <string>
 
-class LLOSInfo
+class LL_COMMON_API LLOSInfo
 {
 public:
 	LLOSInfo();
@@ -70,7 +70,7 @@ class LLOSInfo
 };
 
 
-class LLCPUInfo
+class LL_COMMON_API LLCPUInfo
 {
 public:
 	LLCPUInfo();	
@@ -99,7 +99,7 @@ class LLCPUInfo
 //
 //	CLASS		LLMemoryInfo
 
-class LLMemoryInfo
+class LL_COMMON_API LLMemoryInfo
 
 /*!	@brief		Class to query the memory subsystem
 
@@ -123,15 +123,15 @@ class LLMemoryInfo
 };
 
 
-std::ostream& operator<<(std::ostream& s, const LLOSInfo& info);
-std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info);
-std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLOSInfo& info);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info);
 
 // gunzip srcfile into dstfile.  Returns FALSE on error.
-BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile);
+BOOL LL_COMMON_API gunzip_file(const std::string& srcfile, const std::string& dstfile);
 // gzip srcfile into dstfile.  Returns FALSE on error.
-BOOL gzip_file(const std::string& srcfile, const std::string& dstfile);
+BOOL LL_COMMON_API gzip_file(const std::string& srcfile, const std::string& dstfile);
 
-extern LLCPUInfo gSysCPU;
+extern LL_COMMON_API LLCPUInfo gSysCPU;
 
 #endif // LL_LLSYS_H
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index f25339f48d124ce2d8baf9d77984bcaa0afcb69e..c3d7650bd9b2d101ddb117c5b1fa679665f17f75 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -42,7 +42,7 @@ class LLThread;
 class LLMutex;
 class LLCondition;
 
-class LLThread
+class LL_COMMON_API LLThread
 {
 public:
 	typedef enum e_thread_status
@@ -130,7 +130,7 @@ class LLThread
 
 //============================================================================
 
-class LLMutex
+class LL_COMMON_API LLMutex
 {
 public:
 	LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
@@ -147,7 +147,7 @@ class LLMutex
 };
 
 // Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
-class LLCondition : public LLMutex
+class LL_COMMON_API LLCondition : public LLMutex
 {
 public:
 	LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
@@ -194,7 +194,7 @@ void LLThread::unlockData()
 
 // see llmemory.h for LLPointer<> definition
 
-class LLThreadSafeRefCount
+class LL_COMMON_API LLThreadSafeRefCount
 {
 public:
 	static void initThreadSafeRefCount(); // creates sMutex
@@ -246,7 +246,7 @@ class LLThreadSafeRefCount
 
 // Simple responder for self destructing callbacks
 // Pure virtual class
-class LLResponder : public LLThreadSafeRefCount
+class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
 {
 protected:
 	virtual ~LLResponder();
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index 0319bec45b62f7da8d1c72c80b5502e74d718657..d009c0f5f7dfc7b05dadac715b195c33eddd99ee 100644
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -55,7 +55,7 @@ const U32	USEC_PER_HOUR	= USEC_PER_MIN * MIN_PER_HOUR;
 const U32	SEC_PER_HOUR	= SEC_PER_MIN * MIN_PER_HOUR;
 const F64 	SEC_PER_USEC 	= 1.0 / (F64) USEC_PER_SEC;
 
-class LLTimer 
+class LL_COMMON_API LLTimer 
 {
 public:
 	static LLTimer *sTimer;				// global timer
@@ -114,17 +114,17 @@ class LLTimer
 //
 // Various functions for initializing/accessing clock and timing stuff.  Don't use these without REALLY knowing how they work.
 //
-U64 get_clock_count();
-F64 calc_clock_frequency(U32 msecs);
-void update_clock_frequencies();
+LL_COMMON_API U64 get_clock_count();
+LL_COMMON_API F64 calc_clock_frequency(U32 msecs);
+LL_COMMON_API void update_clock_frequencies();
 
 // Sleep for milliseconds
-void ms_sleep(U32 ms);
-U32 micro_sleep(U64 us, U32 max_yields = 0xFFFFFFFF);
+LL_COMMON_API void ms_sleep(U32 ms);
+LL_COMMON_API U32 micro_sleep(U64 us, U32 max_yields = 0xFFFFFFFF);
 
 // Returns the correct UTC time in seconds, like time(NULL).
 // Useful on the viewer, which may have its local clock set wrong.
-time_t time_corrected();
+LL_COMMON_API time_t time_corrected();
 
 static inline time_t time_min()
 {
@@ -155,24 +155,24 @@ static inline time_t time_max()
 }
 
 // Correction factor used by time_corrected() above.
-extern S32 gUTCOffset;
+extern LL_COMMON_API S32 gUTCOffset;
 
 // Is the current computer (in its current time zone)
 // observing daylight savings time?
-BOOL is_daylight_savings();
+LL_COMMON_API BOOL is_daylight_savings();
 
 // Converts internal "struct tm" time buffer to Pacific Standard/Daylight Time
 // Usage:
 // S32 utc_time;
 // utc_time = time_corrected();
 // struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight);
-struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
+LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
 
-void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
-void secondsToTimecodeString(F32 current_time, std::string& tcstring);
+LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
+LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
 
 // class for scheduling a function to be called at a given frequency (approximate, inprecise)
-class LLEventTimer : protected LLInstanceTracker<LLEventTimer>
+class LL_COMMON_API LLEventTimer : protected LLInstanceTracker<LLEventTimer>
 {
 public:
 	LLEventTimer(F32 period);	// period is the amount of time between each call to tick() in seconds
@@ -190,4 +190,6 @@ class LLEventTimer : protected LLInstanceTracker<LLEventTimer>
 	F32 mPeriod;
 };
 
+U64 LL_COMMON_API totalTime();					// Returns current system time in microseconds
+
 #endif
diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h
index 8e46e2e89ef3049bea7445d0b6b2b7d23ae8f99f..8e69e8558ac178d3eaecb035eff26db3947a6f47 100644
--- a/indra/llcommon/lluri.h
+++ b/indra/llcommon/lluri.h
@@ -47,7 +47,7 @@ class LLApp;
  * See: http://www.ietf.org/rfc/rfc3986.txt
  *
  */
-class LLURI
+class LL_COMMON_API LLURI
 {
 public:
   LLURI();
@@ -178,6 +178,6 @@ class LLURI
 };
 
 // this operator required for tut
-bool operator!=(const LLURI& first, const LLURI& second);
+LL_COMMON_API bool operator!=(const LLURI& first, const LLURI& second);
 
 #endif // LL_LLURI_H
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 4b32138a065a0a7878948d0f1cc4908068fc42d2..c78fb1201804686242792e28950e4a340f4a1cc8 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -35,6 +35,7 @@
 #include <iostream>
 #include <set>
 #include "stdtypes.h"
+#include "llpreprocessor.h"
 
 const S32 UUID_BYTES = 16;
 const S32 UUID_WORDS = 4;
@@ -47,7 +48,7 @@ struct uuid_time_t {
 	U32 low;
 		};
 
-class LLUUID
+class LL_COMMON_API LLUUID
 {
 public:
 	//
@@ -106,8 +107,8 @@ class LLUUID
 	LLUUID combine(const LLUUID& other) const;
 	void combine(const LLUUID& other, LLUUID& result) const;  
 
-	friend std::ostream&	 operator<<(std::ostream& s, const LLUUID &uuid);
-	friend std::istream&	 operator>>(std::istream& s, LLUUID &uuid);
+	friend LL_COMMON_API std::ostream&	 operator<<(std::ostream& s, const LLUUID &uuid);
+	friend LL_COMMON_API std::istream&	 operator>>(std::istream& s, LLUUID &uuid);
 
 	void toString(char *out) const;		// Does not allocate memory, needs 36 characters (including \0)
 	void toString(std::string& out) const;
@@ -323,7 +324,7 @@ typedef std::set<LLUUID, lluuid_less> uuid_list_t;
  */
 typedef LLUUID LLAssetID;
 
-class LLTransactionID : public LLUUID
+class LL_COMMON_API LLTransactionID : public LLUUID
 {
 public:
 	LLTransactionID() : LLUUID() { }
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h
index 23e39ceb08f0f02d5848c45f2cf7d0e56d485b2d..71c6fc059192e85fe03ca70fded4c6a8d90ceaba 100644
--- a/indra/llcommon/llversionserver.h
+++ b/indra/llcommon/llversionserver.h
@@ -34,9 +34,9 @@
 #define LL_LLVERSIONSERVER_H
 
 const S32 LL_VERSION_MAJOR = 1;
-const S32 LL_VERSION_MINOR = 29;
+const S32 LL_VERSION_MINOR = 31;
 const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_BUILD = 3256;
 
 const char * const LL_CHANNEL = "Second Life Server";
 
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 2c3e9c73337275b6a6932433415aca4c54f80e28..082d054ba2efa5a6d53bf6bed1c8e86d561c4bb4 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -36,7 +36,7 @@
 const S32 LL_VERSION_MAJOR = 2;
 const S32 LL_VERSION_MINOR = 0;
 const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_BUILD = 3256;
 
 const char * const LL_CHANNEL = "Second Life Developer";
 
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index 19407f4463886b922163d9857a2bed49457db130..a12bd52a648775f4532606848442873e6e89148d 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -50,7 +50,7 @@ class LLWorkerClass;
 // Note: ~LLWorkerThread is O(N) N=# of worker threads, assumed to be small
 //   It is assumed that LLWorkerThreads are rarely created/destroyed.
 
-class LLWorkerThread : public LLQueuedThread
+class LL_COMMON_API LLWorkerThread : public LLQueuedThread
 {
 public:
 	class WorkRequest : public LLQueuedThread::QueuedRequest
@@ -113,7 +113,7 @@ class LLWorkerThread : public LLQueuedThread
 // Only one background task can be active at a time (per instance).
 //  i.e. don't call addWork() if haveWork() returns true
 
-class LLWorkerClass
+class LL_COMMON_API LLWorkerClass
 {
 	friend class LLWorkerThread;
 	friend class LLWorkerThread::WorkRequest;
diff --git a/indra/llcommon/metaclass.h b/indra/llcommon/metaclass.h
index cc10f1675f25c55903710996235883e589ba4138..f38bcd2d57c8058c49668552113b29162c97f889 100644
--- a/indra/llcommon/metaclass.h
+++ b/indra/llcommon/metaclass.h
@@ -43,7 +43,7 @@
 class LLReflective;
 class LLMetaProperty;
 class LLMetaMethod;
-class LLMetaClass
+class LL_COMMON_API LLMetaClass
 {
 public:
 
diff --git a/indra/llcommon/metaproperty.h b/indra/llcommon/metaproperty.h
index e5ac35907c0e96b6887e029834714366350bcd3c..6c016c56ddce9ebb8dc803aa63067d7c969893e6 100644
--- a/indra/llcommon/metaproperty.h
+++ b/indra/llcommon/metaproperty.h
@@ -41,7 +41,7 @@
 
 class LLMetaClass;
 class LLReflective;
-class LLMetaProperty
+class LL_COMMON_API LLMetaProperty
 {
 public:
 	LLMetaProperty(const std::string& name, const LLMetaClass& object_class);
diff --git a/indra/llcommon/metapropertyt.h b/indra/llcommon/metapropertyt.h
index 79a536a224ffaf1ae668747fb5ab3bfd95451b93..5ad230d1d5e8fb8556b84fa28a5a873c673e2621 100644
--- a/indra/llcommon/metapropertyt.h
+++ b/indra/llcommon/metapropertyt.h
@@ -93,6 +93,13 @@ inline const LLReflective* LLMetaPropertyT<LLUUID>::get(const LLReflective* obje
 	return NULL;
 }
 
+template <>
+inline const LLReflective* LLMetaPropertyT<bool>::get(const LLReflective* object) const
+{
+	checkObjectClass(object);
+	return NULL;
+}
+
 template <>
 inline LLSD LLMetaPropertyT<S32>::getLLSD(const LLReflective* object) const
 {
@@ -111,6 +118,12 @@ inline LLSD LLMetaPropertyT<LLUUID>::getLLSD(const LLReflective* object) const
 	return *(getProperty(object));
 }
 
+template <>
+inline LLSD LLMetaPropertyT<bool>::getLLSD(const LLReflective* object) const
+{
+	return *(getProperty(object));
+}
+
 template<class TObject, class TProperty>
 class LLMetaPropertyTT : public LLMetaPropertyT<TProperty>
 {
diff --git a/indra/llcommon/reflective.h b/indra/llcommon/reflective.h
index e2c18ebc6da96ce0f5888d030000d2d73543e5f1..a13537681d7259adbf27e6bc497569f5fcaea7a6 100644
--- a/indra/llcommon/reflective.h
+++ b/indra/llcommon/reflective.h
@@ -36,7 +36,7 @@
 #define LL_REFLECTIVE_H
 
 class LLMetaClass;
-class LLReflective
+class LL_COMMON_API LLReflective
 {
 public:
 	LLReflective();
diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h
index 1b2958020fa91f9f28a4cc6b97717a570d3c8a8f..6399547f5e628830727041e8af7e73560a50e533 100644
--- a/indra/llcommon/stringize.h
+++ b/indra/llcommon/stringize.h
@@ -13,6 +13,7 @@
 #define LL_STRINGIZE_H
 
 #include <sstream>
+#include <boost/lambda/lambda.hpp>
 
 /**
  * stringize(item) encapsulates an idiom we use constantly, using
@@ -27,6 +28,17 @@ std::string stringize(const T& item)
     return out.str();
 }
 
+/**
+ * stringize_f(functor)
+ */
+template <typename Functor>
+std::string stringize_f(Functor const & f)
+{
+    std::ostringstream out;
+    f(out);
+    return out.str();
+}
+
 /**
  * STRINGIZE(item1 << item2 << item3 ...) effectively expands to the
  * following:
@@ -36,40 +48,43 @@ std::string stringize(const T& item)
  * return out.str();
  * @endcode
  */
-#define STRINGIZE(EXPRESSION) (static_cast<std::ostringstream&>(Stringize() << EXPRESSION).str())
+#define STRINGIZE(EXPRESSION) (stringize_f(boost::lambda::_1 << EXPRESSION))
+
 
 /**
- * Helper class for STRINGIZE() macro. Ideally the body of
- * STRINGIZE(EXPRESSION) would look something like this:
+ * destringize(str)
+ * defined for symmetry with stringize
+ * *NOTE - this has distinct behavior from boost::lexical_cast<T> regarding
+ * leading/trailing whitespace and handling of bad_lexical_cast exceptions
+ */
+template <typename T>
+T destringize(std::string const & str)
+{
+	T val;
+    std::istringstream in(str);
+	in >> val;
+    return val;
+}
+
+/**
+ * destringize_f(str, functor)
+ */
+template <typename Functor>
+void destringize_f(std::string const & str, Functor const & f)
+{
+    std::istringstream in(str);
+    f(in);
+}
+
+/**
+ * DESTRINGIZE(str, item1 >> item2 >> item3 ...) effectively expands to the
+ * following:
  * @code
- * (std::ostringstream() << EXPRESSION).str()
+ * std::istringstream in(str);
+ * in >> item1 >> item2 >> item3 ... ;
  * @endcode
- * That doesn't work because each of the relevant operator<<() functions
- * accepts a non-const std::ostream&, to which you can't pass a temp instance
- * of std::ostringstream. Stringize plays the necessary const tricks to make
- * the whole thing work.
  */
-class Stringize
-{
-public:
-    /**
-     * This is the essence of Stringize. The leftmost << operator (the one
-     * coded in the STRINGIZE() macro) engages this operator<<() const method
-     * on the temp Stringize instance. Every other << operator (ones embedded
-     * in EXPRESSION) simply sees the std::ostream& returned by the first one.
-     *
-     * Finally, the STRINGIZE() macro downcasts that std::ostream& to
-     * std::ostringstream&.
-     */
-    template <typename T>
-    std::ostream& operator<<(const T& item) const
-    {
-        mOut << item;
-        return mOut;
-    }
+#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), (boost::lambda::_1 >> EXPRESSION)))
 
-private:
-    mutable std::ostringstream mOut;
-};
 
 #endif /* ! defined(LL_STRINGIZE_H) */
diff --git a/indra/llcommon/tests/listener.h b/indra/llcommon/tests/listener.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa12f944ef58def17b8c194b9a0e997b24540932
--- /dev/null
+++ b/indra/llcommon/tests/listener.h
@@ -0,0 +1,139 @@
+/**
+ * @file   listener.h
+ * @author Nat Goodspeed
+ * @date   2009-03-06
+ * @brief  Useful for tests of the LLEventPump family of classes
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LISTENER_H)
+#define LL_LISTENER_H
+
+#include "llsd.h"
+#include <iostream>
+
+/*****************************************************************************
+*   test listener class
+*****************************************************************************/
+class Listener;
+std::ostream& operator<<(std::ostream&, const Listener&);
+
+/// Bear in mind that this is strictly for testing
+class Listener
+{
+public:
+    /// Every Listener is instantiated with a name
+    Listener(const std::string& name):
+        mName(name)
+    {
+//      std::cout << *this << ": ctor\n";
+    }
+/*==========================================================================*|
+    // These methods are only useful when trying to track Listener instance
+    // lifespan
+    Listener(const Listener& that):
+        mName(that.mName),
+        mLastEvent(that.mLastEvent)
+    {
+        std::cout << *this << ": copy\n";
+    }
+    virtual ~Listener()
+    {
+        std::cout << *this << ": dtor\n";
+    }
+|*==========================================================================*/
+    /// You can request the name
+    std::string getName() const { return mName; }
+    /// This is a typical listener method that returns 'false' when done,
+    /// allowing subsequent listeners on the LLEventPump to process the
+    /// incoming event.
+    bool call(const LLSD& event)
+    {
+//      std::cout << *this << "::call(" << event << ")\n";
+        mLastEvent = event;
+        return false;
+    }
+    /// This is an alternate listener that returns 'true' when done, which
+    /// stops processing of the incoming event.
+    bool callstop(const LLSD& event)
+    {
+//      std::cout << *this << "::callstop(" << event << ")\n";
+        mLastEvent = event;
+        return true;
+    }
+    /// ListenMethod can represent either call() or callstop().
+    typedef bool (Listener::*ListenMethod)(const LLSD&);
+    /**
+     * This helper method is only because our test code makes so many
+     * repetitive listen() calls to ListenerMethods. In real code, you should
+     * call LLEventPump::listen() directly so it can examine the specific
+     * object you pass to boost::bind().
+     */
+    LLBoundListener listenTo(LLEventPump& pump,
+                             ListenMethod method=&Listener::call,
+                             const LLEventPump::NameList& after=LLEventPump::empty,
+                             const LLEventPump::NameList& before=LLEventPump::empty)
+    {
+        return pump.listen(getName(), boost::bind(method, this, _1), after, before);
+    }
+    /// Both call() and callstop() set mLastEvent. Retrieve it.
+    LLSD getLastEvent() const
+    {
+//      std::cout << *this << "::getLastEvent() -> " << mLastEvent << "\n";
+        return mLastEvent;
+    }
+    /// Reset mLastEvent to a known state.
+    void reset(const LLSD& to = LLSD())
+    {
+//      std::cout << *this << "::reset(" << to << ")\n";
+        mLastEvent = to;
+    }
+
+private:
+    std::string mName;
+    LLSD mLastEvent;
+};
+
+std::ostream& operator<<(std::ostream& out, const Listener& listener)
+{
+    out << "Listener(" << listener.getName() /* << "@" << &listener */ << ')';
+    return out;
+}
+
+/**
+ * This class tests the relative order in which various listeners on a given
+ * LLEventPump are called. Each listen() call binds a particular string, which
+ * we collect for later examination. The actual event is ignored.
+ */
+struct Collect
+{
+    bool add(const std::string& bound, const LLSD& event)
+    {
+        result.push_back(bound);
+        return false;
+    }
+    void clear() { result.clear(); }
+    typedef std::vector<std::string> StringList;
+    StringList result;
+};
+
+std::ostream& operator<<(std::ostream& out, const Collect::StringList& strings)
+{
+    out << '(';
+    Collect::StringList::const_iterator begin(strings.begin()), end(strings.end());
+    if (begin != end)
+    {
+        out << '"' << *begin << '"';
+        while (++begin != end)
+        {
+            out << ", \"" << *begin << '"';
+        }
+    }
+    out << ')';
+    return out;
+}
+
+#endif /* ! defined(LL_LISTENER_H) */
diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3a2cda773509b13e69b12678be3d6cceb94eeb60
--- /dev/null
+++ b/indra/llcommon/tests/lleventcoro_test.cpp
@@ -0,0 +1,782 @@
+/**
+ * @file   coroutine_test.cpp
+ * @author Nat Goodspeed
+ * @date   2009-04-22
+ * @brief  Test for coroutine.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+/*****************************************************************************/
+//  test<1>() is cloned from a Boost.Coroutine example program whose copyright
+//  info is reproduced here:
+/*---------------------------------------------------------------------------*/
+//  Copyright (c) 2006, Giovanni P. Deretta
+//
+//  This code may be used under either of the following two licences:
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy 
+//  of this software and associated documentation files (the "Software"), to deal 
+//  in the Software without restriction, including without limitation the rights 
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+//  copies of the Software, and to permit persons to whom the Software is 
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in 
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
+//  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
+//  THE SOFTWARE. OF SUCH DAMAGE.
+//
+//  Or:
+//
+//  Distributed under the Boost Software License, Version 1.0.
+//  (See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+/*****************************************************************************/
+
+// On some platforms, Boost.Coroutine must #define magic symbols before
+// #including platform-API headers. Naturally, that's ineffective unless the
+// Boost.Coroutine #include is the *first* #include of the platform header.
+// That means that client code must generally #include Boost.Coroutine headers
+// before anything else.
+#include <boost/coroutine/coroutine.hpp>
+// Normally, lleventcoro.h obviates future.hpp. We only include this because
+// we implement a "by hand" test of future functionality.
+#include <boost/coroutine/future.hpp>
+#include <boost/bind.hpp>
+#include <boost/range.hpp>
+
+#include "linden_common.h"
+
+#include <iostream>
+#include <string>
+
+#include "../test/lltut.h"
+#include "llsd.h"
+#include "llevents.h"
+#include "tests/wrapllerrs.h"
+#include "stringize.h"
+#include "lleventcoro.h"
+#include "../test/debug.h"
+
+/*****************************************************************************
+*   from the banana.cpp example program borrowed for test<1>()
+*****************************************************************************/
+namespace coroutines = boost::coroutines;
+using coroutines::coroutine;
+
+template<typename Iter>
+bool match(Iter first, Iter last, std::string match) {
+  std::string::iterator i = match.begin();
+  i != match.end();
+  for(; (first != last) && (i != match.end()); ++i) {
+    if (*first != *i)
+      return false;
+    ++first;
+  }
+  return i == match.end();
+}
+
+template<typename BidirectionalIterator> 
+BidirectionalIterator 
+match_substring(BidirectionalIterator begin, 
+		BidirectionalIterator end, 
+		std::string xmatch,
+		BOOST_DEDUCED_TYPENAME coroutine<BidirectionalIterator(void)>::self& self) { 
+  BidirectionalIterator begin_ = begin;
+  for(; begin != end; ++begin) 
+    if(match(begin, end, xmatch)) {
+      self.yield(begin);
+    }
+  return end;
+} 
+
+typedef coroutine<std::string::iterator(void)> match_coroutine_type;
+
+/*****************************************************************************
+*   Test helpers
+*****************************************************************************/
+// I suspect this will be typical of coroutines used in Linden software
+typedef boost::coroutines::coroutine<void()> coroutine_type;
+
+/// Simulate an event API whose response is immediate: sent on receipt of the
+/// initial request, rather than after some delay. This is the case that
+/// distinguishes postAndWait() from calling post(), then calling
+/// waitForEventOn().
+class ImmediateAPI
+{
+public:
+    ImmediateAPI():
+        mPump("immediate", true)
+    {
+        mPump.listen("API", boost::bind(&ImmediateAPI::operator(), this, _1));
+    }
+
+    LLEventPump& getPump() { return mPump; }
+
+    // Invoke this with an LLSD map containing:
+    // ["value"]: Integer value. We will reply with ["value"] + 1.
+    // ["reply"]: Name of LLEventPump on which to send success response.
+    // ["error"]: Name of LLEventPump on which to send error response.
+    // ["fail"]: Presence of this key selects ["error"], else ["success"] as
+    // the name of the pump on which to send the response.
+    bool operator()(const LLSD& event) const
+    {
+        LLSD::Integer value(event["value"]);
+        LLSD::String replyPumpName(event.has("fail")? "error" : "reply");
+        LLEventPumps::instance().obtain(event[replyPumpName]).post(value + 1);
+        return false;
+    }
+
+private:
+    LLEventStream mPump;
+};
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct coroutine_data
+    {
+        // Define coroutine bodies as methods here so they can use ensure*()
+
+        void explicit_wait(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                // ... do whatever preliminary stuff must happen ...
+
+                // declare the future
+                boost::coroutines::future<LLSD> future(self);
+                // tell the future what to wait for
+                LLTempBoundListener connection(
+                    LLEventPumps::instance().obtain("source").listen("coro", voidlistener(boost::coroutines::make_callback(future))));
+                ensure("Not yet", ! future);
+                // attempting to dereference ("resolve") the future causes the calling
+                // coroutine to wait for it
+                debug("about to wait");
+                result = *future;
+                ensure("Got it", future);
+            }
+            END
+        }
+
+        void waitForEventOn1(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                result = waitForEventOn(self, "source");
+            }
+            END
+        }
+
+        void waitForEventOn2(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLEventWithID pair = waitForEventOn(self, "reply", "error");
+                result = pair.first;
+                which  = pair.second;
+                debug(STRINGIZE("result = " << result << ", which = " << which));
+            }
+            END
+        }
+
+        void postAndWait1(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                result = postAndWait(self,
+                                     LLSD().insert("value", 17), // request event
+                                     immediateAPI.getPump(),     // requestPump
+                                     "reply1",                   // replyPump
+                                     "reply");                   // request["reply"] = name
+            }
+            END
+        }
+
+        void postAndWait2(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLEventWithID pair = ::postAndWait2(self,
+                                                    LLSD().insert("value", 18),
+                                                    immediateAPI.getPump(),
+                                                    "reply2",
+                                                    "error2",
+                                                    "reply",
+                                                    "error");
+                result = pair.first;
+                which  = pair.second;
+                debug(STRINGIZE("result = " << result << ", which = " << which));
+            }
+            END
+        }
+
+        void postAndWait2_1(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLEventWithID pair = ::postAndWait2(self,
+                                                    LLSD().insert("value", 18).insert("fail", LLSD()),
+                                                    immediateAPI.getPump(),
+                                                    "reply2",
+                                                    "error2",
+                                                    "reply",
+                                                    "error");
+                result = pair.first;
+                which  = pair.second;
+                debug(STRINGIZE("result = " << result << ", which = " << which));
+            }
+            END
+        }
+
+        void coroPump(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPump waiter;
+                replyName = waiter.getName();
+                result = waiter.wait(self);
+            }
+            END
+        }
+
+        void coroPumpPost(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPump waiter;
+                result = waiter.postAndWait(self, LLSD().insert("value", 17),
+                                            immediateAPI.getPump(), "reply");
+            }
+            END
+        }
+
+        void coroPumps(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                replyName = waiter.getName0();
+                errorName = waiter.getName1();
+                LLEventWithID pair(waiter.wait(self));
+                result = pair.first;
+                which  = pair.second;
+            }
+            END
+        }
+
+        void coroPumpsNoEx(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                replyName = waiter.getName0();
+                errorName = waiter.getName1();
+                result = waiter.waitWithException(self);
+            }
+            END
+        }
+
+        void coroPumpsEx(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                replyName = waiter.getName0();
+                errorName = waiter.getName1();
+                try
+                {
+                    result = waiter.waitWithException(self);
+                    debug("no exception");
+                }
+                catch (const LLErrorEvent& e)
+                {
+                    debug(STRINGIZE("exception " << e.what()));
+                    errordata = e.getData();
+                }
+            }
+            END
+        }
+
+        void coroPumpsNoLog(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                replyName = waiter.getName0();
+                errorName = waiter.getName1();
+                result = waiter.waitWithLog(self);
+            }
+            END
+        }
+
+        void coroPumpsLog(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                replyName = waiter.getName0();
+                errorName = waiter.getName1();
+                WrapLL_ERRS capture;
+                try
+                {
+                    result = waiter.waitWithLog(self);
+                    debug("no exception");
+                }
+                catch (const WrapLL_ERRS::FatalException& e)
+                {
+                    debug(STRINGIZE("exception " << e.what()));
+                    threw = e.what();
+                }
+            }
+            END
+        }
+
+        void coroPumpsPost(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                LLEventWithID pair(waiter.postAndWait(self, LLSD().insert("value", 23),
+                                                      immediateAPI.getPump(), "reply", "error"));
+                result = pair.first;
+                which  = pair.second;
+            }
+            END
+        }
+
+        void coroPumpsPost_1(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                LLEventWithID pair(
+                    waiter.postAndWait(self, LLSD().insert("value", 23).insert("fail", LLSD()),
+                                       immediateAPI.getPump(), "reply", "error"));
+                result = pair.first;
+                which  = pair.second;
+            }
+            END
+        }
+
+        void coroPumpsPostNoEx(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                result = waiter.postAndWaitWithException(self, LLSD().insert("value", 8),
+                                                         immediateAPI.getPump(), "reply", "error");
+            }
+            END
+        }
+
+        void coroPumpsPostEx(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                try
+                {
+                    result = waiter.postAndWaitWithException(self,
+                        LLSD().insert("value", 9).insert("fail", LLSD()),
+                        immediateAPI.getPump(), "reply", "error");
+                    debug("no exception");
+                }
+                catch (const LLErrorEvent& e)
+                {
+                    debug(STRINGIZE("exception " << e.what()));
+                    errordata = e.getData();
+                }
+            }
+            END
+        }
+
+        void coroPumpsPostNoLog(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                result = waiter.postAndWaitWithLog(self, LLSD().insert("value", 30),
+                                                   immediateAPI.getPump(), "reply", "error");
+            }
+            END
+        }
+
+        void coroPumpsPostLog(coroutine_type::self& self)
+        {
+            BEGIN
+            {
+                LLCoroEventPumps waiter;
+                WrapLL_ERRS capture;
+                try
+                {
+                    result = waiter.postAndWaitWithLog(self,
+                        LLSD().insert("value", 31).insert("fail", LLSD()),
+                        immediateAPI.getPump(), "reply", "error");
+                    debug("no exception");
+                }
+                catch (const WrapLL_ERRS::FatalException& e)
+                {
+                    debug(STRINGIZE("exception " << e.what()));
+                    threw = e.what();
+                }
+            }
+            END
+        }
+
+        void ensure_done(coroutine_type& coro)
+        {
+            ensure("coroutine complete", ! coro);
+        }
+
+        ImmediateAPI immediateAPI;
+        std::string replyName, errorName, threw;
+        LLSD result, errordata;
+        int which;
+    };
+    typedef test_group<coroutine_data> coroutine_group;
+    typedef coroutine_group::object object;
+    coroutine_group coroutinegrp("coroutine");
+
+    template<> template<>
+    void object::test<1>()
+    {
+        set_test_name("From banana.cpp example program in Boost.Coroutine distro");
+        std::string buffer = "banananana"; 
+        std::string match = "nana"; 
+        std::string::iterator begin = buffer.begin();
+        std::string::iterator end = buffer.end();
+
+#if defined(BOOST_CORO_POSIX_IMPL)
+//      std::cout << "Using Boost.Coroutine " << BOOST_CORO_POSIX_IMPL << '\n';
+#else
+//      std::cout << "Using non-Posix Boost.Coroutine implementation" << std::endl;
+#endif
+
+        typedef std::string::iterator signature(std::string::iterator, 
+                                                std::string::iterator, 
+                                                std::string,
+                                                match_coroutine_type::self&);
+
+        coroutine<std::string::iterator(void)> matcher
+            (boost::bind(static_cast<signature*>(match_substring), 
+                         begin, 
+                         end, 
+                         match, 
+                         _1)); 
+
+        std::string::iterator i = matcher();
+/*==========================================================================*|
+        while(matcher && i != buffer.end()) {
+            std::cout <<"Match at: "<< std::distance(buffer.begin(), i)<<'\n'; 
+            i = matcher();
+        }
+|*==========================================================================*/
+        size_t matches[] = { 2, 4, 6 };
+        for (size_t *mi(boost::begin(matches)), *mend(boost::end(matches));
+             mi != mend; ++mi, i = matcher())
+        {
+            ensure("more", matcher);
+            ensure("found", i != buffer.end());
+            ensure_equals("value", std::distance(buffer.begin(), i), *mi);
+        }
+        ensure("done", ! matcher);
+    }
+
+    template<> template<>
+    void object::test<2>()
+    {
+        set_test_name("explicit_wait");
+        DEBUG;
+
+        // Construct the coroutine instance that will run explicit_wait.
+        // Pass the ctor a callable that accepts the coroutine_type::self
+        // param passed by the library.
+        coroutine_type coro(boost::bind(&coroutine_data::explicit_wait, this, _1));
+        // Start the coroutine
+        coro(std::nothrow);
+        // When the coroutine waits for the event pump, it returns here.
+        debug("about to send");
+        // Satisfy the wait.
+        LLEventPumps::instance().obtain("source").post("received");
+        // Now wait for the coroutine to complete.
+        ensure_done(coro);
+        // ensure the coroutine ran and woke up again with the intended result
+        ensure_equals(result.asString(), "received");
+    }
+
+    template<> template<>
+    void object::test<3>()
+    {
+        set_test_name("waitForEventOn1");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn1, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain("source").post("received");
+        debug("back from send");
+        ensure_done(coro);
+        ensure_equals(result.asString(), "received");
+    }
+
+    template<> template<>
+    void object::test<4>()
+    {
+        set_test_name("waitForEventOn2 reply");
+        {
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn2, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain("reply").post("received");
+        debug("back from send");
+        ensure_done(coro);
+        }
+        ensure_equals(result.asString(), "received");
+        ensure_equals("which pump", which, 0);
+    }
+
+    template<> template<>
+    void object::test<5>()
+    {
+        set_test_name("waitForEventOn2 error");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn2, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain("error").post("badness");
+        debug("back from send");
+        ensure_done(coro);
+        ensure_equals(result.asString(), "badness");
+        ensure_equals("which pump", which, 1);
+    }
+
+    template<> template<>
+    void object::test<6>()
+    {
+        set_test_name("coroPump");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPump, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain(replyName).post("received");
+        debug("back from send");
+        ensure_done(coro);
+        ensure_equals(result.asString(), "received");
+    }
+
+    template<> template<>
+    void object::test<7>()
+    {
+        set_test_name("coroPumps reply");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumps, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain(replyName).post("received");
+        debug("back from send");
+        ensure_done(coro);
+        ensure_equals(result.asString(), "received");
+        ensure_equals("which pump", which, 0);
+    }
+
+    template<> template<>
+    void object::test<8>()
+    {
+        set_test_name("coroPumps error");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumps, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain(errorName).post("badness");
+        debug("back from send");
+        ensure_done(coro);
+        ensure_equals(result.asString(), "badness");
+        ensure_equals("which pump", which, 1);
+    }
+
+    template<> template<>
+    void object::test<9>()
+    {
+        set_test_name("coroPumpsNoEx");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsNoEx, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain(replyName).post("received");
+        debug("back from send");
+        ensure_done(coro);
+        ensure_equals(result.asString(), "received");
+    }
+
+    template<> template<>
+    void object::test<10>()
+    {
+        set_test_name("coroPumpsEx");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsEx, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain(errorName).post("badness");
+        debug("back from send");
+        ensure_done(coro);
+        ensure("no result", result.isUndefined());
+        ensure_equals("got error", errordata.asString(), "badness");
+    }
+
+    template<> template<>
+    void object::test<11>()
+    {
+        set_test_name("coroPumpsNoLog");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsNoLog, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain(replyName).post("received");
+        debug("back from send");
+        ensure_done(coro);
+        ensure_equals(result.asString(), "received");
+    }
+
+    template<> template<>
+    void object::test<12>()
+    {
+        set_test_name("coroPumpsLog");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsLog, this, _1));
+        coro(std::nothrow);
+        debug("about to send");
+        LLEventPumps::instance().obtain(errorName).post("badness");
+        debug("back from send");
+        ensure_done(coro);
+        ensure("no result", result.isUndefined());
+        ensure_contains("got error", threw, "badness");
+    }
+
+    template<> template<>
+    void object::test<13>()
+    {
+        set_test_name("postAndWait1");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::postAndWait1, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure_equals(result.asInteger(), 18);
+    }
+
+    template<> template<>
+    void object::test<14>()
+    {
+        set_test_name("postAndWait2");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::postAndWait2, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure_equals(result.asInteger(), 19);
+        ensure_equals(which, 0);
+    }
+
+    template<> template<>
+    void object::test<15>()
+    {
+        set_test_name("postAndWait2_1");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::postAndWait2_1, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure_equals(result.asInteger(), 19);
+        ensure_equals(which, 1);
+    }
+
+    template<> template<>
+    void object::test<16>()
+    {
+        set_test_name("coroPumpPost");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpPost, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure_equals(result.asInteger(), 18);
+    }
+
+    template<> template<>
+    void object::test<17>()
+    {
+        set_test_name("coroPumpsPost reply");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPost, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure_equals(result.asInteger(), 24);
+        ensure_equals("which pump", which, 0);
+    }
+
+    template<> template<>
+    void object::test<18>()
+    {
+        set_test_name("coroPumpsPost error");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPost_1, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure_equals(result.asInteger(), 24);
+        ensure_equals("which pump", which, 1);
+    }
+
+    template<> template<>
+    void object::test<19>()
+    {
+        set_test_name("coroPumpsPostNoEx");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostNoEx, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure_equals(result.asInteger(), 9);
+    }
+
+    template<> template<>
+    void object::test<20>()
+    {
+        set_test_name("coroPumpsPostEx");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostEx, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure("no result", result.isUndefined());
+        ensure_equals("got error", errordata.asInteger(), 10);
+    }
+
+    template<> template<>
+    void object::test<21>()
+    {
+        set_test_name("coroPumpsPostNoLog");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostNoLog, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure_equals(result.asInteger(), 31);
+    }
+
+    template<> template<>
+    void object::test<22>()
+    {
+        set_test_name("coroPumpsPostLog");
+        DEBUG;
+        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostLog, this, _1));
+        coro(std::nothrow);
+        ensure_done(coro);
+        ensure("no result", result.isUndefined());
+        ensure_contains("got error", threw, "32");
+    }
+} // namespace tut
diff --git a/indra/llcommon/tests/lleventfilter_test.cpp b/indra/llcommon/tests/lleventfilter_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..28b909298e1979ccd9c554c5ba31592aebae4cdc
--- /dev/null
+++ b/indra/llcommon/tests/lleventfilter_test.cpp
@@ -0,0 +1,276 @@
+/**
+ * @file   lleventfilter_test.cpp
+ * @author Nat Goodspeed
+ * @date   2009-03-06
+ * @brief  Test for lleventfilter.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lleventfilter.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "../test/lltut.h"
+#include "stringize.h"
+#include "listener.h"
+#include "tests/wrapllerrs.h"
+
+/*****************************************************************************
+*   Test classes
+*****************************************************************************/
+// Strictly speaking, we're testing LLEventTimeoutBase rather than the
+// production LLEventTimeout (using LLTimer) because we don't want every test
+// run to pause for some number of seconds until we reach a real timeout. But
+// as we've carefully put all functionality except actual LLTimer calls into
+// LLEventTimeoutBase, that should suffice. We're not not not trying to test
+// LLTimer here.
+class TestEventTimeout: public LLEventTimeoutBase
+{
+public:
+    TestEventTimeout():
+        mElapsed(true)
+    {}
+    TestEventTimeout(LLEventPump& source):
+        LLEventTimeoutBase(source),
+        mElapsed(true)
+    {}
+
+    // test hook
+    void forceTimeout(bool timeout=true) { mElapsed = timeout; }
+
+protected:
+    virtual void setCountdown(F32 seconds) { mElapsed = false; }
+    virtual bool countdownElapsed() const { return mElapsed; }
+
+private:
+    bool mElapsed;
+};
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct filter_data
+    {
+        // The resemblance between this test data and that in llevents_tut.cpp
+        // is not coincidental.
+        filter_data():
+            pumps(LLEventPumps::instance()),
+            mainloop(pumps.obtain("mainloop")),
+            listener0("first"),
+            listener1("second")
+        {}
+        LLEventPumps& pumps;
+        LLEventPump& mainloop;
+        Listener listener0;
+        Listener listener1;
+
+        void check_listener(const std::string& desc, const Listener& listener, const LLSD& got)
+        {
+            ensure_equals(STRINGIZE(listener << ' ' << desc),
+                          listener.getLastEvent(), got);
+        }
+    };
+    typedef test_group<filter_data> filter_group;
+    typedef filter_group::object filter_object;
+    filter_group filtergrp("lleventfilter");
+
+    template<> template<>
+    void filter_object::test<1>()
+    {
+        set_test_name("LLEventMatching");
+        LLEventPump& driver(pumps.obtain("driver"));
+        listener0.reset(0);
+        // Listener isn't derived from LLEventTrackable specifically to test
+        // various connection-management mechanisms. But that means we have a
+        // couple of transient Listener objects, one of which is listening to
+        // a persistent LLEventPump. Capture those connections in local
+        // LLTempBoundListener instances so they'll disconnect
+        // on destruction.
+        LLTempBoundListener temp1(
+            listener0.listenTo(driver));
+        // Construct a pattern LLSD: desired Event must have a key "foo"
+        // containing string "bar"
+        LLEventMatching filter(driver, LLSD().insert("foo", "bar"));
+        listener1.reset(0);
+        LLTempBoundListener temp2(
+            listener1.listenTo(filter));
+        driver.post(1);
+        check_listener("direct", listener0, LLSD(1));
+        check_listener("filtered", listener1, LLSD(0));
+        // Okay, construct an LLSD map matching the pattern
+        LLSD data;
+        data["foo"] = "bar";
+        data["random"] = 17;
+        driver.post(data);
+        check_listener("direct", listener0, data);
+        check_listener("filtered", listener1, data);
+    }
+
+    template<> template<>
+    void filter_object::test<2>()
+    {
+        set_test_name("LLEventTimeout::actionAfter()");
+        LLEventPump& driver(pumps.obtain("driver"));
+        TestEventTimeout filter(driver);
+        listener0.reset(0);
+        LLTempBoundListener temp1(
+            listener0.listenTo(filter));
+        // Use listener1.call() as the Action for actionAfter(), since it
+        // already provides a way to sense the call
+        listener1.reset(0);
+        // driver --> filter --> listener0
+        filter.actionAfter(20,
+                           boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
+        // Okay, (fake) timer is ticking. 'filter' can only sense the timer
+        // when we pump mainloop. Do that right now to take the logic path
+        // before either the anticipated event arrives or the timer expires.
+        mainloop.post(17);
+        check_listener("no timeout 1", listener1, LLSD(0));
+        // Expected event arrives...
+        driver.post(1);
+        check_listener("event passed thru", listener0, LLSD(1));
+        // Should have canceled the timer. Verify that by asserting that the
+        // time has expired, then pumping mainloop again.
+        filter.forceTimeout();
+        mainloop.post(17);
+        check_listener("no timeout 2", listener1, LLSD(0));
+        // Verify chained actionAfter() calls, that is, that a second
+        // actionAfter() resets the timer established by the first
+        // actionAfter().
+        filter.actionAfter(20,
+                           boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
+        // Since our TestEventTimeout class isn't actually manipulating time
+        // (quantities of seconds), only a bool "elapsed" flag, sense that by
+        // forcing the flag between actionAfter() calls.
+        filter.forceTimeout();
+        // Pumping mainloop here would result in a timeout (as we'll verify
+        // below). This state simulates a ticking timer that has not yet timed
+        // out. But now, before a mainloop event lets 'filter' recognize
+        // timeout on the previous actionAfter() call, pretend we're pushing
+        // that timeout farther into the future.
+        filter.actionAfter(20,
+                           boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
+        // Look ma, no timeout!
+        mainloop.post(17);
+        check_listener("no timeout 3", listener1, LLSD(0));
+        // Now let the updated actionAfter() timer expire.
+        filter.forceTimeout();
+        // Notice the timeout.
+        mainloop.post(17);
+        check_listener("timeout", listener1, LLSD("timeout"));
+        // Timing out cancels the timer. Verify that.
+        listener1.reset(0);
+        filter.forceTimeout();
+        mainloop.post(17);
+        check_listener("no timeout 4", listener1, LLSD(0));
+        // Reset the timer and then cancel() it.
+        filter.actionAfter(20,
+                           boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
+        // neither expired nor satisified
+        mainloop.post(17);
+        check_listener("no timeout 5", listener1, LLSD(0));
+        // cancel
+        filter.cancel();
+        // timeout!
+        filter.forceTimeout();
+        mainloop.post(17);
+        check_listener("no timeout 6", listener1, LLSD(0));
+    }
+
+    template<> template<>
+    void filter_object::test<3>()
+    {
+        set_test_name("LLEventTimeout::eventAfter()");
+        LLEventPump& driver(pumps.obtain("driver"));
+        TestEventTimeout filter(driver);
+        listener0.reset(0);
+        LLTempBoundListener temp1(
+            listener0.listenTo(filter));
+        filter.eventAfter(20, LLSD("timeout"));
+        // Okay, (fake) timer is ticking. 'filter' can only sense the timer
+        // when we pump mainloop. Do that right now to take the logic path
+        // before either the anticipated event arrives or the timer expires.
+        mainloop.post(17);
+        check_listener("no timeout 1", listener0, LLSD(0));
+        // Expected event arrives...
+        driver.post(1);
+        check_listener("event passed thru", listener0, LLSD(1));
+        // Should have canceled the timer. Verify that by asserting that the
+        // time has expired, then pumping mainloop again.
+        filter.forceTimeout();
+        mainloop.post(17);
+        check_listener("no timeout 2", listener0, LLSD(1));
+        // Set timer again.
+        filter.eventAfter(20, LLSD("timeout"));
+        // Now let the timer expire.
+        filter.forceTimeout();
+        // Notice the timeout.
+        mainloop.post(17);
+        check_listener("timeout", listener0, LLSD("timeout"));
+        // Timing out cancels the timer. Verify that.
+        listener0.reset(0);
+        filter.forceTimeout();
+        mainloop.post(17);
+        check_listener("no timeout 3", listener0, LLSD(0));
+    }
+
+    template<> template<>
+    void filter_object::test<4>()
+    {
+        set_test_name("LLEventTimeout::errorAfter()");
+        WrapLL_ERRS capture;
+        LLEventPump& driver(pumps.obtain("driver"));
+        TestEventTimeout filter(driver);
+        listener0.reset(0);
+        LLTempBoundListener temp1(
+            listener0.listenTo(filter));
+        filter.errorAfter(20, "timeout");
+        // Okay, (fake) timer is ticking. 'filter' can only sense the timer
+        // when we pump mainloop. Do that right now to take the logic path
+        // before either the anticipated event arrives or the timer expires.
+        mainloop.post(17);
+        check_listener("no timeout 1", listener0, LLSD(0));
+        // Expected event arrives...
+        driver.post(1);
+        check_listener("event passed thru", listener0, LLSD(1));
+        // Should have canceled the timer. Verify that by asserting that the
+        // time has expired, then pumping mainloop again.
+        filter.forceTimeout();
+        mainloop.post(17);
+        check_listener("no timeout 2", listener0, LLSD(1));
+        // Set timer again.
+        filter.errorAfter(20, "timeout");
+        // Now let the timer expire.
+        filter.forceTimeout();
+        // Notice the timeout.
+        std::string threw;
+        try
+        {
+            mainloop.post(17);
+        }
+        catch (const WrapLL_ERRS::FatalException& e)
+        {
+            threw = e.what();
+        }
+        ensure_contains("errorAfter() timeout exception", threw, "timeout");
+        // Timing out cancels the timer. Verify that.
+        listener0.reset(0);
+        filter.forceTimeout();
+        mainloop.post(17);
+        check_listener("no timeout 3", listener0, LLSD(0));
+    }
+} // namespace tut
+
+/*****************************************************************************
+*   Link dependencies
+*****************************************************************************/
+#include "llsdutil.cpp"
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index f13c69f1e3d67618c9ef8b55fd27084ad056cb9c..6ab48ec34ae2251d7769920e89d78bec53850a5a 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -48,6 +48,18 @@
 typedef U32 uint32_t;
 #endif
 
+std::vector<U8> string_to_vector(std::string str)
+{
+	// bc LLSD can't...
+	size_t len = (size_t)str.length();
+	std::vector<U8> v(len);
+	for (size_t i = 0; i < len ; i++)
+	{
+		v[i] = str[i];
+	}
+	return v;
+}
+
 namespace tut
 {
 	struct sd_xml_data
@@ -107,7 +119,16 @@ namespace tut
 		expected = "<llsd><date>2006-04-24T16:11:33Z</date></llsd>\n";
 		xml_test("date", expected);
 
-		// *FIX: test binary
+		// Generated by: echo -n 'hello' | openssl enc -e -base64
+		std::vector<U8> hello;
+		hello.push_back('h');
+		hello.push_back('e');
+		hello.push_back('l');
+		hello.push_back('l');
+		hello.push_back('o');
+		mSD = hello;
+		expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+		xml_test("binary", expected);
 	}
 	
 	template<> template<>
@@ -199,6 +220,21 @@ namespace tut
 		xml_test("2 element map", expected);
 	}
 	
+	template<> template<>
+	void sd_xml_object::test<6>()
+	{
+		// tests with binary
+		std::string expected;
+
+		// Generated by: echo -n 'hello' | openssl enc -e -base64
+		mSD = string_to_vector("hello");
+		expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+		xml_test("binary", expected);
+
+		mSD = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+		expected = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+		xml_test("binary", expected);
+	}
 	
 	class TestLLSDSerializeData
 	{
@@ -637,6 +673,42 @@ namespace tut
 			v.size() + 1);
 	}
 
+	template<> template<> 
+	void TestLLSDXMLParsingObject::test<4>()
+	{
+		// test handling of binary object in XML
+		std::string xml;
+		LLSD expected;
+
+		// Generated by: echo -n 'hello' | openssl enc -e -base64
+		expected = string_to_vector("hello");
+		xml = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+		ensureParse(
+			"the word 'hello' packed in binary encoded base64",
+			xml,
+			expected,
+			1);
+
+		expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+		xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+		ensureParse(
+			"a common binary blob for object -> agent offline inv transfer",
+			xml,
+			expected,
+			1);
+
+		expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+		xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBl\n";
+		xml += "NDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5\n";
+		xml += "LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZm\n";
+		xml += "ZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMy\n";
+		xml += "OXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+		ensureParse(
+			"a common binary blob for object -> agent offline inv transfer",
+			xml,
+			expected,
+			1);
+	}
 	/*
 	TODO:
 		test XML parsing
diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp
index 6a2ebc61f5d5fff88bcb7860c91b73f9e3aeaeae..beba55416ad50fc3b4c28a44e45f4d09f8b44b39 100644
--- a/indra/llcommon/tests/llstring_test.cpp
+++ b/indra/llcommon/tests/llstring_test.cpp
@@ -32,6 +32,7 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
 #include "../test/lltut.h"
 
 #include "../llstring.h"
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
new file mode 100644
index 0000000000000000000000000000000000000000..1001ebc466c8495db35b5f9b072d3f2f5b3af14a
--- /dev/null
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -0,0 +1,56 @@
+/**
+ * @file   wrapllerrs.h
+ * @author Nat Goodspeed
+ * @date   2009-03-11
+ * @brief  Define a class useful for unit tests that engage llerrs (LL_ERRS) functionality
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_WRAPLLERRS_H)
+#define LL_WRAPLLERRS_H
+
+#include "llerrorcontrol.h"
+
+struct WrapLL_ERRS
+{
+    WrapLL_ERRS():
+        // Resetting Settings discards the default Recorder that writes to
+        // stderr. Otherwise, expected llerrs (LL_ERRS) messages clutter the
+        // console output of successful tests, potentially confusing things.
+        mPriorErrorSettings(LLError::saveAndResetSettings()),
+        // Save shutdown function called by LL_ERRS
+        mPriorFatal(LLError::getFatalFunction())
+    {
+        // Make LL_ERRS call our own operator() method
+        LLError::setFatalFunction(boost::bind(&WrapLL_ERRS::operator(), this, _1));
+    }
+
+    ~WrapLL_ERRS()
+    {
+        LLError::setFatalFunction(mPriorFatal);
+        LLError::restoreSettings(mPriorErrorSettings);
+    }
+
+    struct FatalException: public std::runtime_error
+    {
+        FatalException(const std::string& what): std::runtime_error(what) {}
+    };
+
+    void operator()(const std::string& message)
+    {
+        // Save message for later in case consumer wants to sense the result directly
+        error = message;
+        // Also throw an appropriate exception since calling code is likely to
+        // assume that control won't continue beyond LL_ERRS.
+        throw FatalException(message);
+    }
+
+    std::string error;
+    LLError::Settings* mPriorErrorSettings;
+    LLError::FatalFunction mPriorFatal;
+};
+
+#endif /* ! defined(LL_WRAPLLERRS_H) */
diff --git a/indra/llcommon/timing.h b/indra/llcommon/timing.h
index 2b9f60adad70bc3213060fb29279447469a231a9..140ce1fcaa11de68935460eb6f74706f21f0688c 100644
--- a/indra/llcommon/timing.h
+++ b/indra/llcommon/timing.h
@@ -43,7 +43,6 @@ const F32 SEC_TO_MICROSEC = 1000000.f;
 const U64 SEC_TO_MICROSEC_U64 = 1000000;
 const U32 SEC_PER_DAY = 86400;
 
-// This is just a stub, implementation in lltimer.cpp.  This file will be deprecated in the future.
-U64 totalTime();					// Returns current system time in microseconds
+// functionality has been moved lltimer.{cpp,h}.  This file will be deprecated in the future.
 
 #endif
diff --git a/indra/llcommon/u64.h b/indra/llcommon/u64.h
index 09a6b3e18d8eedef0b18480a349073b5b43c944a..eb51131e94655d5d8b0b4fbc40d68bb8884514cd 100644
--- a/indra/llcommon/u64.h
+++ b/indra/llcommon/u64.h
@@ -39,14 +39,14 @@
  * @param str The string to parse.
  * @return Returns the first U64 value found in the string or 0 on failure.
  */
-U64 str_to_U64(const std::string& str);
+LL_COMMON_API U64 str_to_U64(const std::string& str);
 
 /**
  * @brief Given a U64 value, return a printable representation.
  * @param value The U64 to turn into a printable character array.
  * @return Returns the result string.
  */
-std::string U64_to_str(U64 value);
+LL_COMMON_API std::string U64_to_str(U64 value);
 
 /**
  * @brief Given a U64 value, return a printable representation.
@@ -65,16 +65,16 @@ std::string U64_to_str(U64 value);
  * @param result_size The size of the buffer allocated. Use U64_BUF.
  * @return Returns the result pointer.
  */
-char* U64_to_str(U64 value, char* result, S32 result_size);
+LL_COMMON_API char* U64_to_str(U64 value, char* result, S32 result_size);
 
 /**
  * @brief Convert a U64 to the closest F64 value.
  */
-F64 U64_to_F64(const U64 value);
+LL_COMMON_API F64 U64_to_F64(const U64 value);
 
 /**
  * @brief Helper function to wrap strtoull() which is not available on windows.
  */
-U64 llstrtou64(const char* str, char** end, S32 base);
+LL_COMMON_API U64 llstrtou64(const char* str, char** end, S32 base);
 
 #endif
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 363486fb9c013caa8e9ec4141c412638171e9188..2352c8edd725112b80c12cd7937d9ed538ef4dd6 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -178,8 +178,8 @@ LLImageJ2C::LLImageJ2C() : 	LLImageFormatted(IMG_CODEC_J2C),
 							mMaxBytes(0),
 							mRawDiscardLevel(-1),
 							mRate(0.0f),
-							mReversible(FALSE)
-	
+							mReversible(FALSE),
+							mAreaUsedForDataSizeCalcs(0)
 {
 	//We assume here that if we wanted to create via
 	//a dynamic library that the approriate open calls were made
@@ -195,6 +195,12 @@ LLImageJ2C::LLImageJ2C() : 	LLImageFormatted(IMG_CODEC_J2C),
 	}
 
 	mImpl = j2cimpl_create_func();
+
+	// Clear data size table
+	for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++)
+	{	// Array size is MAX_DISCARD_LEVEL+1
+		mDataSizes[i] = 0;
+	}
 }
 
 // virtual
@@ -367,9 +373,45 @@ S32 LLImageJ2C::calcHeaderSize()
 	return calcHeaderSizeJ2C();
 }
 
+
+// calcDataSize() returns how many bytes to read 
+// to load discard_level (including header and higher discard levels)
 S32 LLImageJ2C::calcDataSize(S32 discard_level)
 {
-	return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate);
+	discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL);
+
+	if ( mAreaUsedForDataSizeCalcs != (getHeight() * getWidth()) 
+		|| mDataSizes[0] == 0)
+	{
+		mAreaUsedForDataSizeCalcs = getHeight() * getWidth();
+		
+		S32 level = MAX_DISCARD_LEVEL;	// Start at the highest discard
+		while ( level >= 0 )
+		{
+			mDataSizes[level] = calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+			level--;
+		}
+
+		/* This is technically a more correct way to calculate the size required
+		   for each discard level, since they should include the size needed for
+		   lower levels.   Unfortunately, this doesn't work well and will lead to 
+		   download stalls.  The true correct way is to parse the header.  This will
+		   all go away with http textures at some point.
+
+		// Calculate the size for each discard level.   Lower levels (higher quality)
+		// contain the cumulative size of higher levels		
+		S32 total_size = calcHeaderSizeJ2C();
+
+		S32 level = MAX_DISCARD_LEVEL;	// Start at the highest discard
+		while ( level >= 0 )
+		{	// Add in this discard level and all before it
+			total_size += calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+			mDataSizes[level] = total_size;
+			level--;
+		}
+		*/
+	}
+	return mDataSizes[discard_level];
 }
 
 S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index 23f6ef5fd10b8a7a82cc4283143acd990eaf51e8..55df7f44296e537ec9cf50c796a7831ed3b48a21 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -87,6 +87,10 @@ class LLImageJ2C : public LLImageFormatted
 	void updateRawDiscardLevel();
 
 	S32 mMaxBytes; // Maximum number of bytes of data to use...
+	
+	S32 mDataSizes[MAX_DISCARD_LEVEL+1];		// Size of data required to reach a given level
+	U32 mAreaUsedForDataSizeCalcs;				// Height * width used to calculate mDataSizes
+
 	S8  mRawDiscardLevel;
 	F32 mRate;
 	BOOL mReversible;
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index e2a77f1d1e5f4f7f14b6daf16a9a401d15546d34..5d3fbe51289192d1c33db39247376434fa9df1be 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -458,6 +458,39 @@ void LLInventoryItem::setCreationDate(time_t creation_date_utc)
 	mCreationDate = creation_date_utc;
 }
 
+void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item)
+{
+	// Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags 
+	// because we now detect when they should be set.
+	setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItem::II_FLAGS_PERM_OVERWRITE_MASK)) );
+
+	// Enforce the PERM_OVERWRITE flags for any masks that are different
+	// but only for AT_OBJECT's since that is the only asset type that can 
+	// exist in-world (instead of only in-inventory or in-object-contents).
+	if (LLAssetType::AT_OBJECT == getType())
+	{
+		LLPermissions old_permissions = old_item.getPermissions();
+		U32 flags_to_be_set = 0;
+		if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+		}
+		if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+		}
+		if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+		}
+		LLSaleInfo old_sale_info = old_item.getSaleInfo();
+		if(old_sale_info != getSaleInfo())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
+		}
+		setFlags(getFlags() | flags_to_be_set);
+	}
+}
 
 const LLSaleInfo& LLInventoryItem::getSaleInfo() const
 {
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 64af6c94f5dd996cbd368b4313e0bd293fd2785d..bd581e860f3a230dd919f9836e3d402c3c8aaf0b 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -93,7 +93,6 @@ class LLInventoryObject : public LLRefCount
 	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; // bypasses indirection for linked items
@@ -263,6 +262,10 @@ class LLInventoryItem : public LLInventoryObject
 	void setInventoryType(LLInventoryType::EType inv_type);
 	void setFlags(U32 flags);
 	void setCreationDate(time_t creation_date_utc);
+
+	// Check for changes in permissions masks and sale info
+	// and set the corresponding bits in mFlags
+	void accumulatePermissionSlamBits(const LLInventoryItem& old_item);
 	
 	// This is currently only used in the Viewer to handle calling cards
 	// where the creator is actually used to store the target.
diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp
index f208d82084c632ca55f03ba3d291556b865618cf..ec21ae40e732d7499bab1ffa82982e9446ba4afa 100644
--- a/indra/llinventory/llparcel.cpp
+++ b/indra/llinventory/llparcel.cpp
@@ -43,7 +43,7 @@
 #include "llsdutil.h"
 #include "lltransactiontypes.h"
 #include "lltransactionflags.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
 #include "message.h"
 #include "u64.h"
 
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index aa8391230c30b72cc3bd5b85360e6224355de8c1..2a9a596912fce7403ab1da61cc7590f8128ccaa2 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -136,9 +136,9 @@ class LLSD;
 class LLAccessEntry
 {
 public:
-	LLUUID		mID;
-	S32			mTime;
-	U32			mFlags;
+	LLUUID		mID;		// Agent ID
+	S32			mTime;		// Time (unix seconds) when entry expires
+	U32			mFlags;		// Not used - currently should always be zero
 };
 
 typedef std::map<LLUUID,LLAccessEntry>::iterator access_map_iterator;
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index 0babf26457e91ee463ae662697d5c4aea7b3380f..d2e503473401a6063679c4ea0dfff1ecac5040ed 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -288,6 +288,17 @@ BOOL LLPermissions::setOwnerAndGroup(
 	return allowed;
 }
 
+//Fix for DEV-33917, last owner isn't used much and has little impact on
+//permissions so it's reasonably safe to do this, however, for now, 
+//limiting the functionality of this routine to objects which are 
+//group owned.
+void LLPermissions::setLastOwner(const LLUUID& last_owner)
+{
+	if (isGroupOwned())
+		mLastOwner = last_owner;
+}
+
+ 
 // only call this if you know what you're doing
 // there are usually perm-bit consequences when the 
 // ownerhsip changes
@@ -895,6 +906,8 @@ void LLMetaClassT<LLPermissions>::reflectProperties(LLMetaClass& meta_class)
 {
 	reflectProperty(meta_class, "mCreator", &LLPermissions::mCreator);
 	reflectProperty(meta_class, "mOwner", &LLPermissions::mOwner);
+	reflectProperty(meta_class, "mGroup", &LLPermissions::mGroup);
+	reflectProperty(meta_class, "mIsGroupOwned", &LLPermissions::mIsGroupOwned);
 }
 
 // virtual
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index 864088148f58ccb64f3582dacc75c262324bb53e..d5a0881c8f2ab684ed52f526c3e29dc26c3154de 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -232,6 +232,10 @@ class LLPermissions : public LLReflective
 	// ownerhsip changes
 	void yesReallySetOwner(const LLUUID& owner, bool group_owned);
 
+	// Last owner doesn't have much in the way of permissions so it's 
+	//not too dangerous to do this. 
+	void setLastOwner(const LLUUID& last_owner);
+
 	// saves last owner, sets owner to uuid null, sets group
 	// owned. group_id must be the group of the object (that's who it
 	// is being deeded to) and the object must be group
diff --git a/indra/llinventory/lltransactiontypes.h b/indra/llinventory/lltransactiontypes.h
index 1cb7308bd417fbcfd473e5b65385359df6753719..2c699bcb87cb7761882b5435b2c1b78c8ee7b93a 100644
--- a/indra/llinventory/lltransactiontypes.h
+++ b/indra/llinventory/lltransactiontypes.h
@@ -69,6 +69,12 @@ const S32 TRANS_PARCEL_DIR_FEE		= 2003;
 const S32 TRANS_GROUP_TAX		    = 2004; // Taxes incurred as part of group membership
 const S32 TRANS_CLASSIFIED_RENEW	= 2005;
 
+// Codes 2100-2999 reserved for recurring billing services
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC  = 2100;
+
 // Codes 3000-3999 reserved for inventory transactions
 const S32 TRANS_GIVE_INVENTORY		= 3000;
 
@@ -84,6 +90,12 @@ const S32 TRANS_DWELL_BONUS			= 5007;
 const S32 TRANS_PAY_OBJECT			= 5008;
 const S32 TRANS_OBJECT_PAYS			= 5009;
 
+// Codes 5100-5999 reserved for recurring billing transfers between users
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC_USER  = 5100;
+
 // Codes 6000-6999 reserved for group transactions
 //const S32 TRANS_GROUP_JOIN		    = 6000;  //reserved for future use
 const S32 TRANS_GROUP_LAND_DEED		= 6001;
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index 9006a8a284ee5986dec86eac281815a7491cc76f..7957c32be2c05288ca725b95689c1deec5aa9f6a 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -64,6 +64,7 @@ set(llmath_HEADER_FILES
     llv4vector3.h
     llvolume.h
     llvolumemgr.h
+    llsdutil_math.h
     m3math.h
     m4math.h
     raytrace.h
diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp
index acf93a2a38fc2e0efbc2cb144af5bece154362ab..914cbfdc124fe2b0b74c6f96388481d3795c0978 100644
--- a/indra/llmath/llbbox.cpp
+++ b/indra/llmath/llbbox.cpp
@@ -30,6 +30,8 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
+
 // self include
 #include "llbbox.h"
 
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index f85c4f39f412d625fa5358635a4b6cf259192d30..7a5d51ff768609bf384029c81ea69a94424f8aeb 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -35,6 +35,7 @@
 
 #include <cmath>
 #include <cstdlib>
+#include <complex>
 #include "lldefs.h"
 //#include "llstl.h" // *TODO: Remove when LLString is gone
 //#include "llstring.h" // *TODO: Remove when LLString is gone
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index cfd6183ec44cc3f118b16647b028fded6b811b9e..fdcc19d657b6ee0144121cdbd411fc82b22b6513 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -121,7 +121,7 @@ void	LLQuaternion::quantize16(F32 lower, F32 upper)
 	mQ[VZ] = z;
 	mQ[VS] = s;
 
-	normQuat();
+	normalize();
 }
 
 void	LLQuaternion::quantize8(F32 lower, F32 upper)
@@ -131,7 +131,7 @@ void	LLQuaternion::quantize8(F32 lower, F32 upper)
 	mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper);
 	mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper);
 
-	normQuat();
+	normalize();
 }
 
 // LLVector3 Magnitude and Normalization Functions
@@ -346,7 +346,7 @@ const LLQuaternion&	LLQuaternion::setQuat(const LLMatrix4 &mat)
 //    mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ);
 //#endif
 //
-//	normQuat();
+//	normalize();
 //	return (*this);
 }
 
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index 5db9c5be2ed5167b82d85db3d1847d3fb6f5d31e..0769f29f235d747a3a36ef74d34027fcb6a659e9 100644
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -469,20 +469,30 @@ inline const LLQuaternion&	operator*=(LLQuaternion &a, const LLQuaternion &b)
 	return a;
 }
 
+const F32 ONE_PART_IN_A_MILLION = 0.000001f;
+
 inline F32	LLQuaternion::normalize()
 {
 	F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
 
 	if (mag > FP_MAG_THRESHOLD)
 	{
-		F32 oomag = 1.f/mag;
-		mQ[VX] *= oomag;
-		mQ[VY] *= oomag;
-		mQ[VZ] *= oomag;
-		mQ[VS] *= oomag;
+		// Floating point error can prevent some quaternions from achieving
+		// exact unity length.  When trying to renormalize such quaternions we
+		// can oscillate between multiple quantized states.  To prevent such
+		// drifts we only renomalize if the length is far enough from unity.
+		if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+		{
+			F32 oomag = 1.f/mag;
+			mQ[VX] *= oomag;
+			mQ[VY] *= oomag;
+			mQ[VZ] *= oomag;
+			mQ[VS] *= oomag;
+		}
 	}
 	else
 	{
+		// we were given a very bad quaternion so we set it to identity
 		mQ[VX] = 0.f;
 		mQ[VY] = 0.f;
 		mQ[VZ] = 0.f;
@@ -499,11 +509,15 @@ inline F32	LLQuaternion::normQuat()
 
 	if (mag > FP_MAG_THRESHOLD)
 	{
-		F32 oomag = 1.f/mag;
-		mQ[VX] *= oomag;
-		mQ[VY] *= oomag;
-		mQ[VZ] *= oomag;
-		mQ[VS] *= oomag;
+		if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+		{
+			// only renormalize if length not close enough to 1.0 already
+			F32 oomag = 1.f/mag;
+			mQ[VX] *= oomag;
+			mQ[VY] *= oomag;
+			mQ[VZ] *= oomag;
+			mQ[VS] *= oomag;
+		}
 	}
 	else
 	{
diff --git a/indra/llmath/llsdutil_math.cpp b/indra/llmath/llsdutil_math.cpp
index c5176681cef05230597fabf5c50e338b6c18b0dd..1bd12ae5137d0ea2beeed6223f9a79576c42ee22 100644
--- a/indra/llmath/llsdutil_math.cpp
+++ b/indra/llmath/llsdutil_math.cpp
@@ -34,7 +34,7 @@
 
 #include "linden_common.h"
 
-#include "llsdutil.h"
+#include "llsdutil_math.h"
 
 #include "v3math.h"
 #include "v4math.h"
diff --git a/indra/llmath/llsdutil_math.h b/indra/llmath/llsdutil_math.h
new file mode 100644
index 0000000000000000000000000000000000000000..121f4b746a820c22efe3bf524c2849ab4358f46f
--- /dev/null
+++ b/indra/llmath/llsdutil_math.h
@@ -0,0 +1,70 @@
+/** 
+ * @file llsdutil_math.h
+ * @author Brad
+ * @date 2009-05-19
+ * @brief Utility classes, functions, etc, for using structured data with math classes.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSDUTIL_MATH_H
+#define LL_LLSDUTIL_MATH_H
+
+class LL_COMMON_API LLSD;
+
+// vector3
+class LLVector3;
+LLSD ll_sd_from_vector3(const LLVector3& vec);
+LLVector3 ll_vector3_from_sd(const LLSD& sd, S32 start_index = 0);
+
+// vector4
+class LLVector4;
+LLSD ll_sd_from_vector4(const LLVector4& vec);
+LLVector4 ll_vector4_from_sd(const LLSD& sd, S32 start_index = 0);
+
+// vector3d (double)
+class LLVector3d;
+LLSD ll_sd_from_vector3d(const LLVector3d& vec);
+LLVector3d ll_vector3d_from_sd(const LLSD& sd, S32 start_index = 0);
+
+// vector2
+class LLVector2;
+LLSD ll_sd_from_vector2(const LLVector2& vec);
+LLVector2 ll_vector2_from_sd(const LLSD& sd);
+
+// Quaternion
+class LLQuaternion;
+LLSD ll_sd_from_quaternion(const LLQuaternion& quat);
+LLQuaternion ll_quaternion_from_sd(const LLSD& sd);
+
+// color4
+class LLColor4;
+LLSD ll_sd_from_color4(const LLColor4& c);
+LLColor4 ll_color4_from_sd(const LLSD& sd);
+
+#endif // LL_LLSDUTIL_MATH_H
diff --git a/indra/llmath/tests/llbbox_test.cpp b/indra/llmath/tests/llbbox_test.cpp
index b310baf07f1b40505ea0eb4241f8b5d6ec7b0edb..3031310a5dfa7d0c4211285f4f3076f20765c79e 100644
--- a/indra/llmath/tests/llbbox_test.cpp
+++ b/indra/llmath/tests/llbbox_test.cpp
@@ -32,6 +32,8 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
+
 #include "../test/lltut.h"
 
 #include "../llbbox.h"
diff --git a/indra/llmath/tests/llbboxlocal_test.cpp b/indra/llmath/tests/llbboxlocal_test.cpp
index ae75e056d1574444d84b0cb339108bbf6f11d1c0..fb51deab4a21ca875efd698d9f2e6f4d9795d8b6 100644
--- a/indra/llmath/tests/llbboxlocal_test.cpp
+++ b/indra/llmath/tests/llbboxlocal_test.cpp
@@ -32,11 +32,10 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
 #include "../test/lltut.h"
-
 #include "../llbboxlocal.h"
 
-
 namespace tut
 {
 	struct LLBBoxLocalData
diff --git a/indra/llmath/tests/llrect_test.cpp b/indra/llmath/tests/llrect_test.cpp
index 4b39f777726226f3d47eb4c8fa0fc5cdf7bdbbec..c5e9e425bb6f3997520308d19f94268ec7a56efb 100644
--- a/indra/llmath/tests/llrect_test.cpp
+++ b/indra/llmath/tests/llrect_test.cpp
@@ -32,8 +32,8 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
 #include "../test/lltut.h"
-
 #include "../llrect.h"
 
 namespace tut
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 47fbc3ab69d28d02437072b89b847d4c5177f7ff..a611de0cda901aeee5483baf9a275091548563bc 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -3,6 +3,7 @@
 project(llmessage)
 
 include(00-Common)
+include(GoogleMock)
 include(LLAddBuildTest)
 include(LLCommon)
 include(LLMath)
@@ -22,6 +23,7 @@ include_directories(
 
 set(llmessage_SOURCE_FILES
     llares.cpp
+    llareslistener.cpp
     llassetstorage.cpp
     llblowfishcipher.cpp
     llbuffer.cpp
@@ -104,6 +106,7 @@ set(llmessage_HEADER_FILES
     CMakeLists.txt
 
     llares.h
+    llareslistener.h
     llassetstorage.h
     llblowfishcipher.h
     llbuffer.h
@@ -221,6 +224,7 @@ SET(llmessage_TEST_SOURCE_FILES
   llnamevalue.cpp
   lltrustedmessageservice.cpp
   lltemplatemessagedispatcher.cpp
+      llregionpresenceverifier.cpp
   )
 LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
 
@@ -231,6 +235,7 @@ set(test_libs
   ${LLVFS_LIBRARIES}
   ${LLMATH_LIBRARIES}
   ${LLCOMMON_LIBRARIES}
+      ${GOOGLEMOCK_LIBRARIES}
   )
 
 LL_ADD_INTEGRATION_TEST(
diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp
index fe37fe8142c1fd6102cda912f9787ee4dae642fc..acbf51d75ca26be890928c262ffd5e39f4f5918d 100644
--- a/indra/llmessage/llares.cpp
+++ b/indra/llmessage/llares.cpp
@@ -33,6 +33,7 @@
  */
 
 #include "linden_common.h"
+#include "llares.h"
 
 #include <ares_dns.h>
 #include <ares_version.h>
@@ -42,9 +43,10 @@
 #include "apr_poll.h"
 
 #include "llapr.h"
-#include "llares.h"
+#include "llareslistener.h"
 
 #if defined(LL_WINDOWS)
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
 # define ns_c_in 1
 # define NS_HFIXEDSZ     12      /* #/bytes of fixed data in header */
 # define NS_QFIXEDSZ     4       /* #/bytes of fixed data in query */
@@ -102,7 +104,9 @@ void LLAres::QueryResponder::queryError(int code)
 }
 
 LLAres::LLAres() :
-chan_(NULL), mInitSuccess(false)
+    chan_(NULL),
+    mInitSuccess(false),
+    mListener(new LLAresListener("LLAres", this))
 {
 	if (ares_init(&chan_) != ARES_SUCCESS)
 	{
diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h
index c709a08499473b7808909934236654c7df314357..78febcd560fdb2af07c4d053b1245fb1b0d810f8 100644
--- a/indra/llmessage/llares.h
+++ b/indra/llmessage/llares.h
@@ -36,7 +36,13 @@
 #define LL_LLARES_H
 
 #ifdef LL_WINDOWS
+// ares.h is broken on windows in that it depends on types defined in ws2tcpip.h
+// we need to include them first to work around it, but the headers issue warnings
+# pragma warning(push)
+# pragma warning(disable:4996)
+# include <winsock2.h>
 # include <ws2tcpip.h>
+# pragma warning(pop)
 #endif
 
 #ifdef LL_STANDALONE
@@ -49,7 +55,10 @@
 #include "llrefcount.h"
 #include "lluri.h"
 
+#include <boost/shared_ptr.hpp>
+
 class LLQueryResponder;
+class LLAresListener;
 
 /**
  * @brief Supported DNS RR types.
@@ -444,6 +453,9 @@ class LLAres
 protected:
 	ares_channel chan_;
 	bool mInitSuccess;
+    // boost::scoped_ptr would actually fit the requirement better, but it
+    // can't handle incomplete types as boost::shared_ptr can.
+    boost::shared_ptr<LLAresListener> mListener;
 };
 	
 /**
diff --git a/indra/llmessage/llareslistener.cpp b/indra/llmessage/llareslistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a8beb8cbde350d7a414eccd7d8855903b69387bc
--- /dev/null
+++ b/indra/llmessage/llareslistener.cpp
@@ -0,0 +1,75 @@
+/**
+ * @file   llareslistener.cpp
+ * @author Nat Goodspeed
+ * @date   2009-03-18
+ * @brief  Implementation for llareslistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llareslistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llares.h"
+#include "llerror.h"
+#include "llevents.h"
+#include "llsdutil.h"
+
+LLAresListener::LLAresListener(const std::string& pumpname, LLAres* llares):
+    LLDispatchListener(pumpname, "op"),
+    mAres(llares)
+{
+    // add() every method we want to be able to invoke via this event API.
+    // Optional third parameter validates expected LLSD request structure.
+    add("rewriteURI", &LLAresListener::rewriteURI,
+        LLSD().insert("uri", LLSD()).insert("reply", LLSD()));
+}
+
+/// This UriRewriteResponder subclass packages returned URIs as an LLSD
+/// array to send back to the requester.
+class UriRewriteResponder: public LLAres::UriRewriteResponder
+{
+public:
+    /**
+     * Specify the request, containing the event pump name on which to send
+     * the reply.
+     */
+    UriRewriteResponder(const LLSD& request):
+        mReqID(request),
+        mPumpName(request["reply"])
+    {}
+
+    /// Called by base class with results. This is called in both the
+    /// success and error cases. On error, the calling logic passes the
+    /// original URI.
+    virtual void rewriteResult(const std::vector<std::string>& uris)
+    {
+        LLSD result;
+        for (std::vector<std::string>::const_iterator ui(uris.begin()), uend(uris.end());
+             ui != uend; ++ui)
+        {
+            result.append(*ui);
+        }
+        // This call knows enough to avoid trying to insert a map key into an
+        // LLSD array. It's there so that if, for any reason, we ever decide
+        // to change the response from array to map, it will Just Start Working.
+        mReqID.stamp(result);
+        LLEventPumps::instance().obtain(mPumpName).post(result);
+    }
+
+private:
+    LLReqID mReqID;
+    const std::string mPumpName;
+};
+
+void LLAresListener::rewriteURI(const LLSD& data)
+{
+    mAres->rewriteURI(data["uri"], new UriRewriteResponder(data));
+}
diff --git a/indra/llmessage/llareslistener.h b/indra/llmessage/llareslistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..bf093b3d3d79bfb17dadf5e98cf2ff62c695bb51
--- /dev/null
+++ b/indra/llmessage/llareslistener.h
@@ -0,0 +1,37 @@
+/**
+ * @file   llareslistener.h
+ * @author Nat Goodspeed
+ * @date   2009-03-18
+ * @brief  LLEventPump API for LLAres. This header doesn't actually define the
+ *         API; the API is defined by the pump name on which this class
+ *         listens, and by the expected content of LLSD it receives.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLARESLISTENER_H)
+#define LL_LLARESLISTENER_H
+
+#include "lleventdispatcher.h"
+
+class LLAres;
+class LLSD;
+
+/// Listen on an LLEventPump with specified name for LLAres request events.
+class LLAresListener: public LLDispatchListener
+{
+public:
+    /// Specify the pump name on which to listen, and bind the LLAres instance
+    /// to use (e.g. gAres)
+    LLAresListener(const std::string& pumpname, LLAres* llares);
+
+private:
+    /// command["op"] == "rewriteURI" 
+    void rewriteURI(const LLSD& data);
+
+    LLAres* mAres;
+};
+
+#endif /* ! defined(LL_LLARESLISTENER_H) */
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 47d49076f4a28ed1b38407a5c82ffd957472a2fc..8641437d86216317cdb7ff1fd04924c9a48f0d45 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -42,9 +42,9 @@ class LLUUID;
 
 
 typedef boost::signals2::signal<void (const LLUUID& id,
-							const std::string& first_name,
-							const std::string& last_name,
-							BOOL is_group)> LLCacheNameSignal;
+                                      const std::string& first_name,
+                                      const std::string& last_name,
+                                      BOOL is_group)> LLCacheNameSignal;
 typedef LLCacheNameSignal::slot_type LLCacheNameCallback;
 
 // Old callback with user data for compatability
@@ -100,7 +100,6 @@ class LLCacheName
 	
 	// LEGACY
 	boost::signals2::connection get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data);
-
 	// This method needs to be called from time to time to send out
 	// requests.
 	void processPending();
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index a4af8e989ba7436c067ae67105c197feb19af458..5ff41322b7b65ca2168245ca8ab7c5f12737ce62 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -131,7 +131,7 @@ void LLCurl::Responder::errorWithContent(
 // virtual
 void LLCurl::Responder::error(U32 status, const std::string& reason)
 {
-	llinfos << status << ": " << reason << llendl;
+	llinfos << mURL << " [" << status << "]: " << reason << llendl;
 }
 
 // virtual
@@ -139,6 +139,11 @@ void LLCurl::Responder::result(const LLSD& content)
 {
 }
 
+void LLCurl::Responder::setURL(const std::string& url)
+{
+	mURL = url;
+}
+
 // virtual
 void LLCurl::Responder::completedRaw(
 	U32 status,
@@ -148,7 +153,11 @@ void LLCurl::Responder::completedRaw(
 {
 	LLSD content;
 	LLBufferStream istr(channels, buffer.get());
-	LLSDSerialize::fromXML(content, istr);
+	if (!LLSDSerialize::fromXML(content, istr))
+	{
+		llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl;
+	}
+
 	completed(status, reason, content);
 }
 
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index fbd3077cbf75eddadebadb6ecb535fb7757ee8cd..0b58e7c4a59fa82538b2fa31b4fc93dbcf3a81d2 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -120,8 +120,14 @@ class LLCurl
 			// of the header can be parsed.  In the ::completed call above only the body is contained in the LLSD.
 			virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content);
 
+			// Used internally to set the url for debugging later.
+			void setURL(const std::string& url);
+
 	public: /* but not really -- don't touch this */
 		U32 mReferenceCount;
+
+	private:
+		std::string mURL;
 	};
 	typedef boost::intrusive_ptr<Responder>	ResponderPtr;
 
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 8b90a4c5cacd2ed5df432d2ca9c3e7f49847deae..12ecbb36eb8ea85862fe1e723daaa1c27ffc9bf0 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -265,6 +265,11 @@ static void request(
 		}
 	}
 
+	if (responder)
+	{
+		responder->setURL(url);
+	}
+
 	req->setCallback(new LLHTTPClientURLAdaptor(responder));
 
 	if (method == LLURLRequest::HTTP_POST  &&  gMessageSystem)
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index b6988224ce7356524caa73e4d37681a84a84f3bf..9d3c83f82870c2f13f2b8115dd520400b83e3aea 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llhttpclientadapter.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index 7f76390d0c59d9a2ff2cb43966867f407ff3a86d..a205a2f260e122faa8a636e90f88c7d5ccb86233 100644
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llhttpclientadepter.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 42a8e5cd0a9bac2068c71a12ca73569c33f949f7..085a59cf2776816ff67ed8dfe766b188eba71ecd 100644
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llhttpclientinterface.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp
index 7c636250040c2ef54fef28556591a8c81d8fcf7e..3da41939fae047184f0ae872779690b207e4e2fa 100644
--- a/indra/llmessage/llinstantmessage.cpp
+++ b/indra/llmessage/llinstantmessage.cpp
@@ -40,7 +40,7 @@
 #include "lluuid.h"
 #include "llsd.h"
 #include "llsdserialize.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
 #include "llpointer.h"
 #include "message.h"
 
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index a00dbd180906235cf13f3fd688b2b9ed54c99815..97134bd336c45938f464646dacf36b4025728e78 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -521,7 +521,7 @@ class LLHTTPResponder : public LLIOPipe
 	 * seek orfor string assignment.
 	 * @returns Returns true if a line was found.
 	 */
-	bool readLine(
+	bool readHeaderLine(
 		const LLChannelDescriptors& channels,
 		buffer_ptr_t buffer,
 		U8* dest,
@@ -592,7 +592,7 @@ LLHTTPResponder::~LLHTTPResponder()
 	//lldebugs << "destroying LLHTTPResponder" << llendl;
 }
 
-bool LLHTTPResponder::readLine(
+bool LLHTTPResponder::readHeaderLine(
 	const LLChannelDescriptors& channels,
 	buffer_ptr_t buffer,
 	U8* dest,
@@ -670,7 +670,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 #endif
 		
 		PUMP_DEBUG;
-		if(readLine(channels, buffer, (U8*)buf, len))
+		if(readHeaderLine(channels, buffer, (U8*)buf, len))
 		{
 			bool read_next_line = false;
 			bool parse_all = true;
@@ -734,7 +734,13 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 					if(read_next_line)
 					{
 						len = HEADER_BUFFER_SIZE;	
-						readLine(channels, buffer, (U8*)buf, len);
+						if (!readHeaderLine(channels, buffer, (U8*)buf, len))
+						{
+							// Failed to read the header line, probably too long.
+							// readHeaderLine already marked the channel/buffer as bad.
+							keep_parsing = false;
+							break;
+						}
 					}
 					if(0 == len)
 					{
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index d52ff6c7e8bbc0eb063a38131c24f6b04d88ac99..ce206d8d7d17bb7ffdefb4d861db5ea433f1d831 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -265,7 +265,7 @@ std::string LLMail::buildSMTPTransaction(
 // static
 bool LLMail::send(
 	const std::string& header,
-	const std::string& message,
+	const std::string& raw_message,
 	const char* from_address,
 	const char* to_address)
 {
@@ -276,8 +276,20 @@ bool LLMail::send(
 		return false;
 	}
 
-	// *FIX: this translation doesn't deal with a single period on a
-	// line by itself.
+	// remove any "." SMTP commands to prevent injection (DEV-35777)
+	// we don't need to worry about "\r\n.\r\n" because of the 
+	// "\n" --> "\n\n" conversion going into rfc2822_msg below
+	std::string message = raw_message;
+	std::string bad_string = "\n.\n";
+	std::string good_string = "\n..\n";
+	while (1)
+	{
+		int index = message.find(bad_string);
+		if (index == std::string::npos) break;
+		message.replace(index, bad_string.size(), good_string);
+	}
+
+	// convert all "\n" into "\r\n"
 	std::ostringstream rfc2822_msg;
 	for(U32 i = 0; i < message.size(); ++i)
 	{
diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h
index 119eb1d7f73f2013e01af8ea9b711b6a7a9bbb7c..af6733fa05acecb377a6ac5787c4c318a5ea521e 100644
--- a/indra/llmessage/llmessagesenderinterface.h
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llmessagesenderinterface.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp
index 485bc6aa4468a921eda5a003911fbab17efc1227..9376cde7b50f6212e75d579779782f32771ac841 100644
--- a/indra/llmessage/llpartdata.cpp
+++ b/indra/llmessage/llpartdata.cpp
@@ -39,6 +39,8 @@
 #include "v4coloru.h"
 
 #include "llsdutil.h"
+#include "llsdutil_math.h"
+
 
 
 const S32 PS_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; // 18
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
index 0527d5cb8debff456cbf674598a5a22a0fe944b0..b1868e6a00f3d355028f3b65291c8bc2912046de 100644
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ b/indra/llmessage/llregionpresenceverifier.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llregionpresenceverifier.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -30,17 +30,48 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
+
 #include "llregionpresenceverifier.h"
 #include "llhttpclientinterface.h"
 #include <sstream>
 #include "net.h"
 #include "message.h"
 
+namespace boost
+{
+	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p)
+	{
+		++p->mReferenceCount;
+	}
+	
+	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p)
+	{
+		if(p && 0 == --p->mReferenceCount)
+		{
+			delete p;
+		}
+	}
+};
 
-LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data)
+LLRegionPresenceVerifier::Response::~Response()
 {
 }
 
+LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string&
+														   uri,
+														   ResponsePtr data,
+														   S32 retry_count) :
+	mUri(uri),
+	mSharedData(data),
+	mRetryCount(retry_count)
+{
+}
+
+//virtual
+LLRegionPresenceVerifier::RegionResponder::~RegionResponder()
+{
+}
 
 void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
 {
@@ -49,30 +80,36 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
 	LLHost destination(host, port);
 	LLUUID id = content["region_id"];
 
-	llinfos << "Verifying " << destination.getString() << " is region " << id << llendl;
+	lldebugs << "Verifying " << destination.getString() << " is region " << id << llendl;
 
 	std::stringstream uri;
 	uri << "http://" << destination.getString() << "/state/basic/";
-	mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content));
+	mSharedData->getHttpClient().get(
+		uri.str(),
+		new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));
 }
 
-void LLRegionPresenceVerifier::RegionResponder::completed(
-	U32 status,
-	const std::string& reason,
-	const LLSD& content)
+void LLRegionPresenceVerifier::RegionResponder::error(U32 status,
+													 const std::string& reason)
 {
-	LLHTTPClient::Responder::completed(status, reason, content);
-	
-	mSharedData->onCompletedRegionRequest();
+	// TODO: babbage: distinguish between region presence service and
+	// region verification errors?
+	mSharedData->onRegionVerificationFailed();
 }
 
-
-LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content)
+LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content,
+	S32 retry_count):
+	mUri(uri),
+	mSharedData(data),
+	mContent(content),
+	mRetryCount(retry_count) 
 {
 }
 
-
-
+//virtual
+LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder()
+{
+}
 
 void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
 {
@@ -87,13 +124,14 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD&
 	{
 		mSharedData->onRegionVerified(mContent);
 	}
-	else if (mSharedData->shouldRetry())
+	else if (mRetryCount > 0)
 	{
 		retry();
 	}
 	else
 	{
-		llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl;
+		llwarns << "Simulator verification failed. Region: " << mUri << llendl;
+		mSharedData->onRegionVerificationFailed();
 	}
 }
 
@@ -101,13 +139,21 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()
 {
 	LLSD headers;
 	headers["Cache-Control"] = "no-cache, max-age=0";
-	llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl;
-	mSharedData->decrementRetries();
-	mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers);
+	llinfos << "Requesting region information, get uncached for region "
+			<< mUri << llendl;
+	--mRetryCount;
+	mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);
 }
 
 void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)
 {
-	retry();
+	if(mRetryCount > 0)
+	{
+		retry();
+	}
+	else
+	{
+		llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl;
+		mSharedData->onRegionVerificationFailed();
+	}
 }
-
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
index 54ad6226d645cbe7c4aed403aec028367b504504..f57a62a731317f509b84a7f7208174a5eab4d250 100644
--- a/indra/llmessage/llregionpresenceverifier.h
+++ b/indra/llmessage/llregionpresenceverifier.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llregionpresenceverifier.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -37,7 +37,7 @@
 #include "llhttpclient.h"
 #include <string>
 #include "llsd.h"
-#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
 
 class LLHTTPClientInterface;
 
@@ -47,49 +47,58 @@ class LLRegionPresenceVerifier
 	class Response
 	{
 	public:
-		virtual ~Response() {}
+		virtual ~Response() = 0;
 
 		virtual bool checkValidity(const LLSD& content) const = 0;
 		virtual void onRegionVerified(const LLSD& region_details) = 0;
-
-		virtual void decrementRetries() = 0;
+		virtual void onRegionVerificationFailed() = 0;
 
 		virtual LLHTTPClientInterface& getHttpClient() = 0;
-		virtual std::string getRegionUri() const = 0;
-		virtual bool shouldRetry() const = 0;
 
-		virtual void onCompletedRegionRequest() {}
+	public: /* but not really -- don't touch this */
+		U32 mReferenceCount;		
 	};
 
-	typedef boost::shared_ptr<Response> ResponsePtr;
+	typedef boost::intrusive_ptr<Response> ResponsePtr;
 
 	class RegionResponder : public LLHTTPClient::Responder
 	{
 	public:
-		RegionResponder(ResponsePtr data);
+		RegionResponder(const std::string& uri, ResponsePtr data,
+						S32 retry_count);
+		virtual ~RegionResponder(); 
 		virtual void result(const LLSD& content);
-		virtual void completed(
-			U32 status,
-			const std::string& reason,
-			const LLSD& content);
+		virtual void error(U32 status, const std::string& reason);
 
 	private:
 		ResponsePtr mSharedData;
+		std::string mUri;
+		S32 mRetryCount;
 	};
 
 	class VerifiedDestinationResponder : public LLHTTPClient::Responder
 	{
 	public:
-		VerifiedDestinationResponder(ResponsePtr data, const LLSD& content);
+		VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
+									 const LLSD& content, S32 retry_count);
+		virtual ~VerifiedDestinationResponder();
 		virtual void result(const LLSD& content);
 		
 		virtual void error(U32 status, const std::string& reason);
+		
 	private:
 		void retry();
 		ResponsePtr mSharedData;
 		LLSD mContent;
+		std::string mUri;
+		S32 mRetryCount;
 	};
 };
 
+namespace boost
+{
+	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p);
+	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p);
+};
 
 #endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp
index 9967a6197fe4e7a2abbd52cd23fb660aedc0d753..2cb742e2619a6796c1bab7c51b0cd2396a126822 100644
--- a/indra/llmessage/llsdmessage.cpp
+++ b/indra/llmessage/llsdmessage.cpp
@@ -68,6 +68,7 @@ bool LLSDMessage::httpListener(const LLSD& request)
     }
     LLHTTPClient::post(url, payload,
                        new LLSDMessage::EventResponder(LLEventPumps::instance(),
+                                                       request,
                                                        url, "POST", reply, error),
                        LLSD(),      // headers
                        timeout);
@@ -81,7 +82,9 @@ void LLSDMessage::EventResponder::result(const LLSD& data)
     // to the pump whose name is "".
     if (! mReplyPump.empty())
     {
-        mPumps.obtain(mReplyPump).post(data);
+        LLSD response(data);
+        mReqID.stamp(response);
+        mPumps.obtain(mReplyPump).post(response);
     }
     else                            // default success handling
     {
@@ -98,7 +101,7 @@ void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string
     // explicit pump name.
     if (! mErrorPump.empty())
     {
-        LLSD info;
+        LLSD info(mReqID.makeResponse());
         info["target"]  = mTarget;
         info["message"] = mMessage;
         info["status"]  = LLSD::Integer(status);
diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h
index 65503756a83585881eb43bbb4f463e0b07c1a3f9..6ee00fd41d25b5a6175405542190b354c7a065b4 100644
--- a/indra/llmessage/llsdmessage.h
+++ b/indra/llmessage/llsdmessage.h
@@ -121,9 +121,11 @@ class LLSDMessage
          * (e.g. "POST") as @a message.
          */
         EventResponder(LLEventPumps& pumps,
+                       const LLSD& request,
                        const std::string& target, const std::string& message,
                        const std::string& replyPump, const std::string& errorPump):
             mPumps(pumps),
+            mReqID(request),
             mTarget(target),
             mMessage(message),
             mReplyPump(replyPump),
@@ -135,6 +137,7 @@ class LLSDMessage
     
     private:
         LLEventPumps& mPumps;
+        LLReqID mReqID;
         const std::string mTarget, mMessage, mReplyPump, mErrorPump;
     };
 
diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp
index 21937f022f4edf042a6b3829e14919d782ba0d9c..6e41b03895c04a44670b828f0c57c85eb3f001a5 100755
--- a/indra/llmessage/llsdmessagebuilder.cpp
+++ b/indra/llmessage/llsdmessagebuilder.cpp
@@ -37,6 +37,7 @@
 #include "llmessagetemplate.h"
 #include "llquaternion.h"
 #include "llsdutil.h"
+#include "llsdutil_math.h"
 #include "llsdserialize.h"
 #include "u64.h"
 #include "v3dmath.h"
diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp
index e699ec9e28b467c7ed93e719684b78f96a3ccc89..845a12d23b9c7383e1366d7738dd64e5efd4e424 100755
--- a/indra/llmessage/llsdmessagereader.cpp
+++ b/indra/llmessage/llsdmessagereader.cpp
@@ -38,6 +38,7 @@
 #include "llsdmessagebuilder.h"
 #include "llsdutil.h"
 
+#include "llsdutil_math.h"
 #include "v3math.h"
 #include "v4math.h"
 #include "v3dmath.h"
diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp
index 32cbb15cb385fcf072e5e7375634fe353db704bf..d6b2f45d04e58d08f6fa411e64431f74d2bc5e72 100644
--- a/indra/llmessage/llstoredmessage.cpp
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llstoredmessage.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
index 5069c2cb2e19226d283d19fe6dfefa8c02321e9e..359e4c5aeac96ba32f23aee834792a9d95d02a92 100644
--- a/indra/llmessage/llstoredmessage.h
+++ b/indra/llmessage/llstoredmessage.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llstoredmessage.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp
index 70279a3c62d033ab8eab74103eac4d93bf548bdf..0872efba508ff8d427f557881356de7bf4320fc6 100644
--- a/indra/llmessage/llthrottle.cpp
+++ b/indra/llmessage/llthrottle.cpp
@@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)
 	return changed;
 }
 
+// Return bits available in the channel
+S32		LLThrottleGroup::getAvailable(S32 throttle_cat)
+{
+	S32 retval = 0;
+
+	F32 category_bps = mCurrentBPS[throttle_cat];
+	F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+	// use a temporary bits_available
+	// since we don't want to change mBitsAvailable every time
+	F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
+	F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
+
+	if (bits_available >= lookahead_bits)
+	{
+		retval = (S32) gThrottleMaximumBPS[throttle_cat];
+	}
+	else 
+	{
+		retval = (S32) bits_available;
+	}
+	
+	return retval;
+}
+
 
 BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
 {
diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h
index 7d1679beb232ead9c23259f0bab6799fdca3d9f8..47a7c653b23b1679a73d845c9da4a4ec73172468 100644
--- a/indra/llmessage/llthrottle.h
+++ b/indra/llmessage/llthrottle.h
@@ -84,6 +84,8 @@ class LLThrottleGroup
 	BOOL	dynamicAdjust();		// Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred
 	BOOL	setNominalBPS(F32* throttle_vec);				// TRUE if any value was different, resets adjustment system if was different
 
+	S32		getAvailable(S32 throttle_cat);					// Return bits available in the channel
+
 	void packThrottle(LLDataPacker &dp) const;
 	void unpackThrottle(LLDataPacker &dp);
 public:
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index f255a2cf7ec8b4d052f0cb57983476bf77b1858b..57d0201fab12a203779e48ed95d96aadb471629f 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -270,7 +270,6 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type)
 		case LLAssetType::AT_BODYPART:
 		case LLAssetType::AT_ANIMATION:
 		case LLAssetType::AT_GESTURE:
-		case LLAssetType::AT_FAVORITE:
 		case LLAssetType::AT_MESH:
 			rv = true;
 			break;
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 3ab8057abb0951576a5f4d1dea241e404c65e4c3..81b7761ed5fdec3b2263ab3c6c6da23d2f471f31 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -51,6 +51,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
  * String constants
  */
 const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
+const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
 
 
 static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
@@ -247,7 +248,29 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	//llinfos << "LLURLRequest::process_impl()" << llendl;
-	if(!buffer) return STATUS_ERROR;
+	if (!buffer) return STATUS_ERROR;
+	
+	// we're still waiting or prcessing, check how many
+	// bytes we have accumulated.
+	const S32 MIN_ACCUMULATION = 100000;
+	if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
+	{
+		 // This is a pretty sloppy calculation, but this
+		 // tries to make the gross assumption that if data
+		 // is coming in at 56kb/s, then this transfer will
+		 // probably succeed. So, if we're accumlated
+		 // 100,000 bytes (MIN_ACCUMULATION) then let's
+		 // give this client another 2s to complete.
+		 const F32 TIMEOUT_ADJUSTMENT = 2.0f;
+		 mDetail->mByteAccumulator = 0;
+		 pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
+		 lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl;
+		 if (mState == STATE_INITIALIZED)
+		 {
+			  llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl;
+		 }
+	}
+
 	switch(mState)
 	{
 	case STATE_INITIALIZED:
@@ -286,27 +309,14 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 			bool newmsg = mDetail->mCurlRequest->getResult(&result);
 			if(!newmsg)
 			{
-				// we're still waiting or prcessing, check how many
-				// bytes we have accumulated.
-				const S32 MIN_ACCUMULATION = 100000;
-				if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
-				{
-					// This is a pretty sloppy calculation, but this
-					// tries to make the gross assumption that if data
-					// is coming in at 56kb/s, then this transfer will
-					// probably succeed. So, if we're accumlated
-					// 100,000 bytes (MIN_ACCUMULATION) then let's
-					// give this client another 2s to complete.
-					const F32 TIMEOUT_ADJUSTMENT = 2.0f;
-					mDetail->mByteAccumulator = 0;
-					pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
-				}
-
 				// keep processing
 				break;
 			}
 
 			mState = STATE_HAVE_RESPONSE;
+			context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+			context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+			lldebugs << this << "Setting context to " << context << llendl;
 			switch(result)
 			{
 				case CURLE_OK:
@@ -353,10 +363,16 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 		// we already stuffed everything into channel in in the curl
 		// callback, so we are done.
 		eos = true;
+		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+		lldebugs << this << "Setting context to " << context << llendl;
 		return STATUS_DONE;
 
 	default:
 		PUMP_DEBUG;
+		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+		lldebugs << this << "Setting context to " << context << llendl;
 		return STATUS_ERROR;
 	}
 }
@@ -369,6 +385,8 @@ void LLURLRequest::initialize()
 	mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
 	mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
 	mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
+	mRequestTransferedBytes = 0;
+	mResponseTransferedBytes = 0;
 }
 
 bool LLURLRequest::configure()
@@ -471,6 +489,7 @@ size_t LLURLRequest::downCallback(
 		req->mDetail->mChannels.out(),
 		(U8*)data,
 		bytes);
+	req->mResponseTransferedBytes += bytes;
 	req->mDetail->mByteAccumulator += bytes;
 	return bytes;
 }
@@ -494,6 +513,7 @@ size_t LLURLRequest::upCallback(
 		req->mDetail->mLastRead,
 		(U8*)data,
 		bytes);
+	req->mRequestTransferedBytes += bytes;
 	return bytes;
 }
 
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 86ef71f085b7048386f68a9c086681987d9d5b21..cb3c46644062cbb26530cc4fbc4e13c90a99309e 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -45,6 +45,12 @@
 #include "llchainio.h"
 #include "llerror.h"
 
+
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_DEST_URI_SD_LABEL;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_TRANSFERED_BYTES;
+
 class LLURLRequestDetail;
 
 class LLURLRequestComplete;
@@ -208,6 +214,8 @@ class LLURLRequest : public LLIOPipe
 	ERequestAction mAction;
 	LLURLRequestDetail* mDetail;
 	LLIOPipe::ptr_t mCompletionCallback;
+	 S32 mRequestTransferedBytes;
+	 S32 mResponseTransferedBytes;
 
 private:
 	/** 
diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp
index 08c9192c9ff5c4ddc117de55811223ad464903dd..209bdb2249459fe446fb336e4b287db0ebf08ed6 100644
--- a/indra/llmessage/llxfermanager.cpp
+++ b/indra/llmessage/llxfermanager.cpp
@@ -760,30 +760,36 @@ static bool remove_prefix(std::string& filename, const std::string& prefix)
 static bool verify_cache_filename(const std::string& filename)
 {
 	//NOTE: This routine is only used to check file names that our own
-	// code places in the cache directory.  As such, it can be limited
-	// to this very restrictive file name pattern.  It does not need to
-	// handle other characters.
-
+	// code places in the cache directory.	As such, it can be limited
+	// to this very restrictive file name pattern.	It does not need to
+	// handle other characters. The only known uses of this are (with examples):
+	//	sim to sim object pass:			fc0b72d8-9456-63d9-a802-a557ef847313.tmp
+	//	sim to viewer mute list:		mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp
+	//	sim to viewer task inventory:	inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp
+	
+	//IMPORTANT: Do not broaden the filenames accepted by this routine
+	// without careful analysis. Anything allowed by this function can
+	// be downloaded by the viewer.
+	
 	size_t len = filename.size();
-	//const boost::regex expr("[a-zA-Z0-9][-_.a-zA-Z0-9]<0,49>");
-	if (len < 1 || len > 50)
-	{
+	//const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp");
+	if (len < 5 || len > 50)
+	{	
 		return false;
 	}
-	for(unsigned i=0; i<len; ++i)
-	{
+	for(size_t i=0; i<(len-4); ++i)
+	{	
 		char c = filename[i];
-		bool ok = isalnum(c);
-		if (!ok && i > 0)
-		{
-			ok = '_'==c || '-'==c || '.'==c;
-		}
+		bool ok = isalnum(c) || '_'==c || '-'==c;
 		if (!ok)
 		{
 			return false;
 		}
 	}
-	return true;
+	return filename[len-4] == '.'
+		&& filename[len-3] == 't'
+		&& filename[len-2] == 'm'
+		&& filename[len-1] == 'p';
 }
 
 void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/)
diff --git a/indra/llmessage/tests/llareslistener_test.cpp b/indra/llmessage/tests/llareslistener_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ac4886ccf4f023bd343b753b5497ea619aed1555
--- /dev/null
+++ b/indra/llmessage/tests/llareslistener_test.cpp
@@ -0,0 +1,200 @@
+/**
+ * @file   llareslistener_test.cpp
+ * @author Mark Palange
+ * @date   2009-02-26
+ * @brief  Tests of llareslistener.h.
+ * 
+ * $LicenseInfo:firstyear=2009&license=internal$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "../llareslistener.h"
+// STL headers
+#include <iostream>
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+
+// other Linden headers
+#include "llsd.h"
+#include "llares.h"
+#include "../test/lltut.h"
+#include "llevents.h"
+#include "tests/wrapllerrs.h"
+
+/*****************************************************************************
+*   Dummy stuff
+*****************************************************************************/
+LLAres::LLAres():
+    // Simulate this much of the real LLAres constructor: we need an
+    // LLAresListener instance.
+    mListener(new LLAresListener("LLAres", this))
+{}
+LLAres::~LLAres() {}
+void LLAres::rewriteURI(const std::string &uri,
+					LLAres::UriRewriteResponder *resp)
+{
+	// This is the only LLAres method I chose to implement.
+	// The effect is that LLAres returns immediately with
+	// a result that is equal to the input uri.
+	std::vector<std::string> result;
+	result.push_back(uri);
+	resp->rewriteResult(result);
+}
+
+LLAres::QueryResponder::~QueryResponder() {}
+void LLAres::QueryResponder::queryError(int) {}
+void LLAres::QueryResponder::queryResult(char const*, size_t) {}
+LLQueryResponder::LLQueryResponder() {}
+void LLQueryResponder::queryResult(char const*, size_t) {}
+void LLQueryResponder::querySuccess() {}
+void LLAres::UriRewriteResponder::queryError(int) {}
+void LLAres::UriRewriteResponder::querySuccess() {}
+void LLAres::UriRewriteResponder::rewriteResult(const std::vector<std::string>& uris) {}
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct data
+    {
+        LLAres dummyAres;
+    };
+    typedef test_group<data> llareslistener_group;
+    typedef llareslistener_group::object object;
+    llareslistener_group llareslistenergrp("llareslistener");
+
+	struct ResponseCallback
+	{
+		std::vector<std::string> mURIs;
+		bool operator()(const LLSD& response)
+		{
+            mURIs.clear();
+            for (LLSD::array_const_iterator ri(response.beginArray()), rend(response.endArray());
+                 ri != rend; ++ri)
+            {
+                mURIs.push_back(*ri);
+            }
+            return false;
+		}
+	};
+
+    template<> template<>
+    void object::test<1>()
+    {
+        set_test_name("test event");
+		// Tests the success and failure cases, since they both use 
+		// the same code paths in the LLAres responder.
+		ResponseCallback response;
+        std::string pumpname("trigger");
+        // Since we're asking LLEventPumps to obtain() the pump by the desired
+        // name, it will persist beyond the current scope, so ensure we
+        // disconnect from it when 'response' goes away.
+        LLTempBoundListener temp(
+            LLEventPumps::instance().obtain(pumpname).listen("rewriteURIresponse",
+                                                             boost::bind(&ResponseCallback::operator(), &response, _1)));
+        // Now build an LLSD request that will direct its response events to
+        // that pump.
+		const std::string testURI("login.bar.com");
+        LLSD request;
+        request["op"] = "rewriteURI";
+        request["uri"] = testURI;
+        request["reply"] = pumpname;
+        LLEventPumps::instance().obtain("LLAres").post(request);
+		ensure_equals(response.mURIs.size(), 1);
+		ensure_equals(response.mURIs.front(), testURI); 
+	}
+
+    template<> template<>
+    void object::test<2>()
+    {
+        set_test_name("bad op");
+        WrapLL_ERRS capture;
+        LLSD request;
+        request["op"] = "foo";
+        std::string threw;
+        try
+        {
+            LLEventPumps::instance().obtain("LLAres").post(request);
+        }
+        catch (const WrapLL_ERRS::FatalException& e)
+        {
+            threw = e.what();
+        }
+        ensure_contains("LLAresListener bad op", threw, "bad");
+    }
+
+    template<> template<>
+    void object::test<3>()
+    {
+        set_test_name("bad rewriteURI request");
+        WrapLL_ERRS capture;
+        LLSD request;
+        request["op"] = "rewriteURI";
+        std::string threw;
+        try
+        {
+            LLEventPumps::instance().obtain("LLAres").post(request);
+        }
+        catch (const WrapLL_ERRS::FatalException& e)
+        {
+            threw = e.what();
+        }
+        ensure_contains("LLAresListener bad req", threw, "missing");
+        ensure_contains("LLAresListener bad req", threw, "reply");
+        ensure_contains("LLAresListener bad req", threw, "uri");
+    }
+
+    template<> template<>
+    void object::test<4>()
+    {
+        set_test_name("bad rewriteURI request");
+        WrapLL_ERRS capture;
+        LLSD request;
+        request["op"] = "rewriteURI";
+        request["reply"] = "nonexistent";
+        std::string threw;
+        try
+        {
+            LLEventPumps::instance().obtain("LLAres").post(request);
+        }
+        catch (const WrapLL_ERRS::FatalException& e)
+        {
+            threw = e.what();
+        }
+        ensure_contains("LLAresListener bad req", threw, "missing");
+        ensure_contains("LLAresListener bad req", threw, "uri");
+        ensure_does_not_contain("LLAresListener bad req", threw, "reply");
+    }
+
+    template<> template<>
+    void object::test<5>()
+    {
+        set_test_name("bad rewriteURI request");
+        WrapLL_ERRS capture;
+        LLSD request;
+        request["op"] = "rewriteURI";
+        request["uri"] = "foo.bar.com";
+        std::string threw;
+        try
+        {
+            LLEventPumps::instance().obtain("LLAres").post(request);
+        }
+        catch (const WrapLL_ERRS::FatalException& e)
+        {
+            threw = e.what();
+        }
+        ensure_contains("LLAresListener bad req", threw, "missing");
+        ensure_contains("LLAresListener bad req", threw, "reply");
+        ensure_does_not_contain("LLAresListener bad req", threw, "uri");
+    }
+}
diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp
index 5dc5932fde9db420c408ac4a0747a92e34cc01c7..e6a5ad9946d8347ded67f231bc0e0e88c5121ddb 100644
--- a/indra/llmessage/tests/llcurl_stub.cpp
+++ b/indra/llmessage/tests/llcurl_stub.cpp
@@ -22,6 +22,7 @@
 #include "linden_common.h"
 
 LLCurl::Responder::Responder()
+	: mReferenceCount(0)
 {
 }
 
diff --git a/indra/llmessage/tests/llhost_test.cpp b/indra/llmessage/tests/llhost_test.cpp
index 2424dbcb6b43d05d3574932d2d8e4eded9144cdf..7e5c3a117b326e51b0ea9db67ed28ae50b3e7609 100644
--- a/indra/llmessage/tests/llhost_test.cpp
+++ b/indra/llmessage/tests/llhost_test.cpp
@@ -157,7 +157,8 @@ namespace tut
 	template<> template<>
 	void host_object::test<9>()
 	{
-		std::string hostStr = "linux.org";
+//		skip("setHostByName(\"google.com\"); getHostName() -> (e.g.) \"yx-in-f100.1e100.net\"");
+		std::string hostStr = "linux.org";		
 		LLHost host;
 		host.setHostByName(hostStr);	
 
@@ -166,7 +167,15 @@ namespace tut
 		// the main domain name and not do the exact compare
 		
 		std::string hostname = host.getHostName();
-		ensure("getHostName failed", hostname.find(hostStr) != std::string::npos);
+		try
+		{
+			ensure("getHostName failed", hostname.find(hostStr) != std::string::npos);
+		}
+		catch (const std::exception&)
+		{
+			std::cerr << "set '" << hostStr << "'; reported '" << hostname << "'" << std::endl;
+			throw;
+		}
 	}
 
 //	setHostByName for dotted IP
diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h
new file mode 100644
index 0000000000000000000000000000000000000000..2f55e97fcc95f89a9eaf390e3c5e95314df4eb90
--- /dev/null
+++ b/indra/llmessage/tests/llmockhttpclient.h
@@ -0,0 +1,61 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/* Macro Definitions */
+#ifndef LL_LLMOCKHTTPCLIENT_H
+#define LL_LLMOCKHTTPCLIENT_H
+
+#include "linden_common.h"
+#include "llhttpclientinterface.h"
+
+#include <gmock/gmock.h>
+
+class LLMockHTTPClient : public LLHTTPClientInterface
+{
+public:
+  MOCK_METHOD2(get, void(const std::string& url, LLCurl::ResponderPtr responder));
+  MOCK_METHOD3(get, void(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers));
+  MOCK_METHOD3(put, void(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder));
+};
+
+// A helper to match responder types
+template<typename T>
+struct ResponderType
+{
+	bool operator()(LLCurl::ResponderPtr ptr) const
+	{
+		T* p = dynamic_cast<T*>(ptr.get());
+		return p != NULL;
+	}
+};
+
+inline bool operator==(const LLSD& l, const LLSD& r)
+{
+	std::ostringstream ls, rs;
+	ls << l;
+	rs << r;
+	return ls.str() == rs.str();
+
+}
+
+
+#endif //LL_LLMOCKHTTPCLIENT_H
+
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c86126406ec0afe2e7510999cf8d4b3065119770
--- /dev/null
+++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
@@ -0,0 +1,113 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+#include "llregionpresenceverifier.h"
+#include "llcurl_stub.cpp"
+#include "llhost.cpp"
+#include "net.cpp"
+#include "lltesthttpclientadapter.cpp"
+
+class LLTestResponse : public LLRegionPresenceVerifier::Response
+{
+public:
+
+	virtual bool checkValidity(const LLSD& content) const
+	{
+		return true;
+	}
+
+	virtual void onRegionVerified(const LLSD& region_details)
+	{
+	}
+
+	virtual void onRegionVerificationFailed()
+	{
+	}
+	
+	virtual LLHTTPClientInterface& getHttpClient()
+	{
+		return mHttpInterface;
+	}
+
+	LLTestHTTPClientAdapter mHttpInterface;
+};
+
+namespace tut
+{
+	struct LLRegionPresenceVerifierData
+	{
+		LLRegionPresenceVerifierData() :
+			mResponse(new LLTestResponse()),
+			mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse),
+					   LLSD(), 3)
+		{
+		}
+		
+		LLTestResponse* mResponse;
+		LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder;
+	};
+
+	typedef test_group<LLRegionPresenceVerifierData> factory;
+	typedef factory::object object;
+}
+
+namespace
+{
+	tut::factory tf("LLRegionPresenceVerifier test");
+}
+
+namespace tut
+{
+	// Test that VerifiedDestinationResponder does retry
+    // on error when shouldRetry returns true.
+	template<> template<>
+	void object::test<1>()
+	{
+		mResponder.error(500, "Internal server error");
+		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1);
+	}
+
+	// Test that VerifiedDestinationResponder only retries
+	// on error until shouldRetry returns false.
+	template<> template<>
+	void object::test<2>()
+	{
+		mResponder.error(500, "Internal server error");
+		mResponder.error(500, "Internal server error");
+		mResponder.error(500, "Internal server error");
+		mResponder.error(500, "Internal server error");
+		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3);
+	}
+}
+
diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py
index e62f20912be58a8d7235ebb815a4141913624479..86d5761b1b4bf69c7ebcfccfb41814bdc97d89c9 100644
--- a/indra/llmessage/tests/test_llsdmessage_peer.py
+++ b/indra/llmessage/tests/test_llsdmessage_peer.py
@@ -16,16 +16,12 @@
 import sys
 from threading import Thread
 from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
+
 mydir = os.path.dirname(__file__)       # expected to be .../indra/llmessage/tests/
 sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
 from indra.util.fastest_elementtree import parse as xml_parse
 from indra.base import llsd
-
-def debug(*args):
-    sys.stdout.writelines(args)
-    sys.stdout.flush()
-# comment out the line below to enable debug output
-debug = lambda *args: None
+from testrunner import run, debug
 
 class TestHTTPRequestHandler(BaseHTTPRequestHandler):
     """This subclass of BaseHTTPRequestHandler is to receive and echo
@@ -106,25 +102,5 @@ def run(self):
         debug("Starting HTTP server...\n")
         httpd.serve_forever()
 
-def main(*args):
-    # Start HTTP server thread. Note that this and all other comm server
-    # threads should be daemon threads: we'll let them run "forever,"
-    # confident that the whole process will terminate when the main thread
-    # terminates, which will be when the test executable child process
-    # terminates.
-    httpThread = TestHTTPServer(name="httpd")
-    httpThread.setDaemon(True)
-    httpThread.start()
-    # choice of os.spawnv():
-    # - [v vs. l] pass a list of args vs. individual arguments,
-    # - [no p] don't use the PATH because we specifically want to invoke the
-    #   executable passed as our first arg,
-    # - [no e] child should inherit this process's environment.
-    debug("Running %s...\n" % (" ".join(args)))
-    sys.stdout.flush()
-    rc = os.spawnv(os.P_WAIT, args[0], args)
-    debug("%s returned %s\n" % (args[0], rc))
-    return rc
-
 if __name__ == "__main__":
-    sys.exit(main(*sys.argv[1:]))
+    sys.exit(run(server=TestHTTPServer(name="httpd"), *sys.argv[1:]))
diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py
new file mode 100644
index 0000000000000000000000000000000000000000..3b9c3a7a1976dd8cba3a7e4daf8a1f21c6bfc558
--- /dev/null
+++ b/indra/llmessage/tests/testrunner.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+"""\
+@file   testrunner.py
+@author Nat Goodspeed
+@date   2009-03-20
+@brief  Utilities for writing wrapper scripts for ADD_COMM_BUILD_TEST unit tests
+
+$LicenseInfo:firstyear=2009&license=viewergpl$
+Copyright (c) 2009, Linden Research, Inc.
+$/LicenseInfo$
+"""
+
+import os
+import sys
+
+def debug(*args):
+    sys.stdout.writelines(args)
+    sys.stdout.flush()
+# comment out the line below to enable debug output
+debug = lambda *args: None
+
+def run(*args, **kwds):
+    """All positional arguments collectively form a command line, executed as
+    a synchronous child process.
+    In addition, pass server=new_thread_instance as an explicit keyword (to
+    differentiate it from an additional command-line argument).
+    new_thread_instance should be an instantiated but not yet started Thread
+    subclass instance, e.g.:
+    run("python", "-c", 'print "Hello, world!"', server=TestHTTPServer(name="httpd"))
+    """
+    # If there's no server= keyword arg, don't start a server thread: simply
+    # run a child process.
+    try:
+        thread = kwds.pop("server")
+    except KeyError:
+        pass
+    else:
+        # Start server thread. Note that this and all other comm server
+        # threads should be daemon threads: we'll let them run "forever,"
+        # confident that the whole process will terminate when the main thread
+        # terminates, which will be when the child process terminates.
+        thread.setDaemon(True)
+        thread.start()
+    # choice of os.spawnv():
+    # - [v vs. l] pass a list of args vs. individual arguments,
+    # - [no p] don't use the PATH because we specifically want to invoke the
+    #   executable passed as our first arg,
+    # - [no e] child should inherit this process's environment.
+    debug("Running %s...\n" % (" ".join(args)))
+    sys.stdout.flush()
+    rc = os.spawnv(os.P_WAIT, args[0], args)
+    debug("%s returned %s\n" % (args[0], rc))
+    return rc
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 7299ede22d7d455373fb7a520ce0297d5c17e6e9..457c074ef1e6046b92c69f2a8a50198fdfb7a600 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -112,6 +112,8 @@ void LLPluginClassMedia::reset()
 	mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
 	mAllowDownsample = false;
 	mPadding = 0;
+	mLastMouseX = 0;
+	mLastMouseY = 0;
 	mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
 	mSleepTime = 1.0f / 100.0f;
 	mCanCut = false;
@@ -133,6 +135,7 @@ void LLPluginClassMedia::reset()
 	mCurrentTime = 0.0f;
 	mDuration = 0.0f;
 	mCurrentRate = 0.0f;
+	mLoadedDuration = 0.0f;
 }
 
 void LLPluginClassMedia::idle(void)
@@ -411,8 +414,20 @@ std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
 	return result;
 }
 
-void LLPluginClassMedia::mouseEvent(EMouseEventType type, int x, int y, MASK modifiers)
+void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
 {
+	if(type == MOUSE_EVENT_MOVE)
+	{
+		if((x == mLastMouseX) && (y == mLastMouseY))
+		{
+			// Don't spam unnecessary mouse move events.
+			return;
+		}
+		
+		mLastMouseX = x;
+		mLastMouseY = y;
+	}
+	
 	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
 	std::string temp;
 	switch(type)
@@ -424,6 +439,8 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int x, int y, MASK mod
 	}
 	message.setValue("event", temp);
 
+	message.setValueS32("button", button);
+
 	message.setValueS32("x", x);
 	
 	// Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
@@ -514,11 +531,12 @@ void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
 	sendMessage(message);
 }
 	
-bool LLPluginClassMedia::textInput(const std::string &text)
+bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers)
 {
 	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
 
 	message.setValue("text", text);
+	message.setValue("modifiers", translateModifiers(modifiers));
 	
 	sendMessage(message);
 	
@@ -534,6 +552,23 @@ void LLPluginClassMedia::loadURI(const std::string &uri)
 	sendMessage(message);
 }
 
+const char* LLPluginClassMedia::priorityToString(EPriority priority)
+{
+	const char* result = "UNKNOWN";
+	switch(priority)
+	{
+		case PRIORITY_UNLOADED:		result = "unloaded";	break;
+		case PRIORITY_STOPPED:		result = "stopped";		break;
+		case PRIORITY_HIDDEN:		result = "hidden";		break;
+		case PRIORITY_SLIDESHOW:	result = "slideshow";	break;
+		case PRIORITY_LOW:			result = "low";			break;
+		case PRIORITY_NORMAL:		result = "normal";		break;
+		case PRIORITY_HIGH:			result = "high";		break;
+	}
+	
+	return result;
+}
+
 void LLPluginClassMedia::setPriority(EPriority priority)
 {
 	if(mPriority != priority)
@@ -542,35 +577,28 @@ void LLPluginClassMedia::setPriority(EPriority priority)
 
 		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
 		
-		std::string priority_string;
+		std::string priority_string = priorityToString(priority);
 		switch(priority)
 		{
 			case PRIORITY_UNLOADED:	
-				priority_string = "unloaded";	
 				mSleepTime = 1.0f;
 			break;
 			case PRIORITY_STOPPED:	
-				priority_string = "stopped";	
 				mSleepTime = 1.0f;
 			break;
 			case PRIORITY_HIDDEN:	
-				priority_string = "hidden";	
 				mSleepTime = 1.0f;
 			break;
 			case PRIORITY_SLIDESHOW:
-				priority_string = "slideshow";		
 				mSleepTime = 1.0f;
 			break;
 			case PRIORITY_LOW:		
-				priority_string = "low";		
 				mSleepTime = 1.0f / 50.0f;
 			break;
 			case PRIORITY_NORMAL:	
-				priority_string = "normal";	
 				mSleepTime = 1.0f / 100.0f;
 			break;
 			case PRIORITY_HIGH:		
-				priority_string = "high";		
 				mSleepTime = 1.0f / 100.0f;
 			break;
 		}
@@ -705,6 +733,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 			
 
 			bool time_duration_updated = false;
+			int previous_percent = mProgressPercent;
 
 			if(message.hasValue("current_time"))
 			{
@@ -722,11 +751,32 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 				mCurrentRate = message.getValueReal("current_rate");
 			}
 			
+			if(message.hasValue("loaded_duration"))
+			{
+				mLoadedDuration = message.getValueReal("loaded_duration");
+				time_duration_updated = true;
+			}
+			else
+			{
+				// If the message doesn't contain a loaded_duration param, assume it's equal to duration
+				mLoadedDuration = mDuration;
+			}
+			
+			// Calculate a percentage based on the loaded duration and total duration.
+			if(mDuration != 0.0f)	// Don't divide by zero.
+			{
+				mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
+			}
+
 			if(time_duration_updated)
 			{
 				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
 			}
 			
+			if(previous_percent != mProgressPercent)
+			{
+				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+			}
 		}
 		else if(message_name == "media_status")
 		{
@@ -754,6 +804,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 			{
 				mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
 			}
+			else if(status == "done")
+			{
+				mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+			}
 			else
 			{
 				// empty string or any unknown string
@@ -812,6 +866,11 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 				mCanPaste = message.getValueBoolean("paste");
 			}
 		}
+		else if(message_name == "name_text")
+		{
+			mMediaName = message.getValue("name");
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
+		}
 		else
 		{
 			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
@@ -883,6 +942,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 
 }
 
+/* virtual */ 
+void LLPluginClassMedia::pluginLaunchFailed()
+{
+	mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+}
+
 /* virtual */ 
 void LLPluginClassMedia::pluginDied()
 {
@@ -1078,6 +1143,11 @@ void LLPluginClassMedia::setVolume(float volume)
 	}
 }
 
+float LLPluginClassMedia::getVolume()
+{
+	return mRequestedVolume;
+}
+
 void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
 {
 	// Send URL history to plugin
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 331ca5f6dcd58ee492fc46bafc7d68eb9ce33d64..90ecd1e0735d3792699f7a332ae4264dc8bf2b7d 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -101,7 +101,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 		MOUSE_EVENT_DOUBLE_CLICK
 	}EMouseEventType;
 	
-	void mouseEvent(EMouseEventType type, int x, int y, MASK modifiers);
+	void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
 
 	typedef enum 
 	{
@@ -115,7 +115,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	void scrollEvent(int x, int y, MASK modifiers);
 	
 	// Text may be unicode (utf8 encoded)
-	bool textInput(const std::string &text);
+	bool textInput(const std::string &text, MASK modifiers);
 	
 	void loadURI(const std::string &uri);
 	
@@ -135,6 +135,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	
 	// Inherited from LLPluginProcessParentOwner
 	/* virtual */ void receivePluginMessage(const LLPluginMessage &message);
+	/* virtual */ void pluginLaunchFailed();
 	/* virtual */ void pluginDied();
 	
 	
@@ -149,6 +150,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 		PRIORITY_HIGH		// media has user focus and/or is taking up most of the screen
 	}EPriority;
 
+	static const char* priorityToString(EPriority priority);
 	void setPriority(EPriority priority);
 	void setLowPrioritySizeLimit(int size);
 	
@@ -226,10 +228,12 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	void seek(float time);
 	void setLoop(bool loop);
 	void setVolume(float volume);
+	float getVolume();
 	
 	F64 getCurrentTime(void) const { return mCurrentTime; };
 	F64 getDuration(void) const { return mDuration; };
 	F64 getCurrentPlayRate(void) { return mCurrentRate; };
+	F64 getLoadedDuration(void) const { return mLoadedDuration; };
 	
 	// Initialize the URL history of the plugin by sending
 	// "init_history" message 
@@ -308,6 +312,8 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	std::string translateModifiers(MASK modifiers);
 	
 	std::string mCursorName;
+	int			mLastMouseX;
+	int			mLastMouseY;
 
 	LLPluginClassMediaOwner::EMediaStatus mStatus;
 	
@@ -338,6 +344,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	F64				mCurrentTime;
 	F64				mDuration;
 	F64				mCurrentRate;
+	F64				mLoadedDuration;
 	
 };
 
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index df6de0925e8c27f3d8a91fdef4d0cfb646a5cd30..c798af29caf1e1c3e9a742f21f70ff1060bbf1ec 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -52,11 +52,13 @@ class LLPluginClassMediaOwner
 		MEDIA_EVENT_NAVIGATE_COMPLETE,		// browser has finished navigation
 		MEDIA_EVENT_PROGRESS_UPDATED,		// browser has updated loading progress
 		MEDIA_EVENT_STATUS_TEXT_CHANGED,	// browser has updated the status text
+		MEDIA_EVENT_NAME_CHANGED,			// browser has updated the name of the media (typically <title> tag)
 		MEDIA_EVENT_LOCATION_CHANGED,		// browser location (URL) has changed (maybe due to internal navagation/frames/etc)
 		MEDIA_EVENT_CLICK_LINK_HREF,		// I'm not entirely sure what the semantics of these two are
 		MEDIA_EVENT_CLICK_LINK_NOFOLLOW,
 		
-		MEDIA_EVENT_PLUGIN_FAILED			// The plugin failed to launch or died unexpectedly
+		MEDIA_EVENT_PLUGIN_FAILED_LAUNCH,	// The plugin failed to launch 
+		MEDIA_EVENT_PLUGIN_FAILED			// The plugin died unexpectedly
 		
 	} EMediaEvent;
 	
@@ -68,7 +70,8 @@ class LLPluginClassMediaOwner
 		MEDIA_ERROR,		// navigation/preroll failed
 		MEDIA_PLAYING,		// playing (only for time-based media)
 		MEDIA_PAUSED,		// paused (only for time-based media)
-		
+		MEDIA_DONE			// finished playing (only for time-based media)
+	
 	} EMediaStatus;
 	
 	virtual ~LLPluginClassMediaOwner() {};
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 41784a713c4b0f367ed82faeab615ccf5c008b7c..39f9438fb3de59279cbf173ed2b5ec650cd074e7 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -55,6 +55,11 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
 	mBoundPort = 0;
 	mState = STATE_UNINITIALIZED;
 	mDisableTimeout = false;
+
+	// initialize timer - heartbeat test (mHeartbeat.hasExpired()) 
+	// can sometimes return true immediately otherwise and plugins 
+	// fail immediately because it looks like 
+	mHeartbeat.setTimerExpirySec(PLUGIN_LOCKED_UP_SECONDS);
 }
 
 LLPluginProcessParent::~LLPluginProcessParent()
@@ -83,6 +88,14 @@ void LLPluginProcessParent::killSockets(void)
 	mSocket.reset();
 }
 
+void LLPluginProcessParent::errorState(void)
+{
+	if(mState < STATE_RUNNING)
+		setState(STATE_LAUNCH_FAILURE);
+	else
+		setState(STATE_ERROR);
+}
+
 void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename)
 {	
 	mProcess.setExecutable(launcher_filename);
@@ -132,7 +145,7 @@ bool LLPluginProcessParent::accept()
 		ll_apr_warn_status(status);
 		
 		// Some other error.
-		setState(STATE_ERROR);
+		errorState();
 	}
 	
 	return result;	
@@ -150,15 +163,15 @@ void LLPluginProcessParent::idle(void)
 			if(!mMessagePipe->pump())
 			{
 //				LL_WARNS("Plugin") << "Message pipe hit an error state" << LL_ENDL;
-				setState(STATE_ERROR);
+				errorState();
 			}
 		}
 
-		if((mSocketError != APR_SUCCESS) && (mState < STATE_ERROR))
+		if((mSocketError != APR_SUCCESS) && (mState <= STATE_RUNNING))
 		{
 			// The socket is in an error state -- the plugin is gone.
 			LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL;
-			setState(STATE_ERROR);
+			errorState();
 		}	
 		
 		// If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
@@ -191,7 +204,7 @@ void LLPluginProcessParent::idle(void)
 				if(ll_apr_warn_status(status))
 				{
 					killSockets();
-					setState(STATE_ERROR);
+					errorState();
 					break;
 				}
 
@@ -202,7 +215,7 @@ void LLPluginProcessParent::idle(void)
 				if(ll_apr_warn_status(status))
 				{
 					killSockets();
-					setState(STATE_ERROR);
+					errorState();
 					break;
 				}
 
@@ -212,7 +225,7 @@ void LLPluginProcessParent::idle(void)
 					if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket())))
 					{
 						killSockets();
-						setState(STATE_ERROR);
+						errorState();
 						break;
 					}
 					mBoundPort = bound_addr->port;	
@@ -222,7 +235,7 @@ void LLPluginProcessParent::idle(void)
 						LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL;
 						
 						killSockets();
-						setState(STATE_ERROR);
+						errorState();
 						break;
 					}
 				}
@@ -234,7 +247,7 @@ void LLPluginProcessParent::idle(void)
 				if(ll_apr_warn_status(status))
 				{
 					killSockets();
-					setState(STATE_ERROR);
+					errorState();
 					break;
 				}
 
@@ -242,7 +255,7 @@ void LLPluginProcessParent::idle(void)
 				if(ll_apr_warn_status(status))
 				{
 					killSockets();
-					setState(STATE_ERROR);
+					errorState();
 					break;
 				}
 				
@@ -255,7 +268,7 @@ void LLPluginProcessParent::idle(void)
 				if(ll_apr_warn_status(status))
 				{
 					killSockets();
-					setState(STATE_ERROR);
+					errorState();
 					break;
 				}
 				
@@ -274,7 +287,7 @@ void LLPluginProcessParent::idle(void)
 				mProcess.addArgument(stream.str());
 				if(mProcess.launch() != 0)
 				{
-					setState(STATE_ERROR);
+					errorState();
 				}
 				else
 				{
@@ -290,7 +303,7 @@ void LLPluginProcessParent::idle(void)
 				// waiting for the plugin to connect
 				if(pluginLockedUpOrQuit())
 				{
-					setState(STATE_ERROR);
+					errorState();
 				}
 				else
 				{
@@ -309,7 +322,7 @@ void LLPluginProcessParent::idle(void)
 
 				if(pluginLockedUpOrQuit())
 				{
-					setState(STATE_ERROR);
+					errorState();
 				}
 			break;
 
@@ -330,14 +343,14 @@ void LLPluginProcessParent::idle(void)
 				// The load_plugin_response message will kick us from here into STATE_RUNNING
 				if(pluginLockedUpOrQuit())
 				{
-					setState(STATE_ERROR);
+					errorState();
 				}
 			break;
 			
 			case STATE_RUNNING:
 				if(pluginLockedUpOrQuit())
 				{
-					setState(STATE_ERROR);
+					errorState();
 				}
 			break;
 			
@@ -349,10 +362,18 @@ void LLPluginProcessParent::idle(void)
 				else if(pluginLockedUp())
 				{
 					LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << llendl;
-					setState(STATE_ERROR);
+					errorState();
 				}
 			break;
 
+			case STATE_LAUNCH_FAILURE:
+				if(mOwner != NULL)
+				{
+					mOwner->pluginLaunchFailed();
+				}
+				setState(STATE_CLEANUP);
+			break;
+
 			case STATE_ERROR:
 				if(mOwner != NULL)
 				{
@@ -467,7 +488,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
 			else
 			{
 				LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL;
-				setState(STATE_ERROR);
+				errorState();
 			}
 			
 		}
@@ -477,6 +498,9 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
 			{
 				// Plugin has been loaded. 
 				
+				mPluginVersionString = message.getValue("plugin_version");
+				LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL;
+
 				// Check which message classes/versions the plugin supports.
 				// TODO: check against current versions
 				// TODO: kill plugin on major mismatches?
@@ -487,8 +511,6 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
 					LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL;
 				}
 				
-				mPluginVersionString = message.getValue("plugin_version");
-				
 				// Send initial sleep time
 				setSleepTime(mSleepTime, true);			
 
@@ -497,7 +519,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
 			else
 			{
 				LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL;
-				setState(STATE_ERROR);
+				errorState();
 			}
 		}
 		else if(message_name == "heartbeat")
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index 0d0b047c88c22ad81b0a4a22ab32f01bf7a22700..754ebeb94683efc033c077013f0f06bc48dde25b 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -45,6 +45,7 @@ class LLPluginProcessParentOwner
 	virtual ~LLPluginProcessParentOwner();
 	virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
 	// This will only be called when the plugin has died unexpectedly 
+	virtual void pluginLaunchFailed() {};
 	virtual void pluginDied() {};
 };
 
@@ -68,6 +69,9 @@ class LLPluginProcessParent : public LLPluginMessagePipeOwner
 	bool isDone(void);	
 	
 	void killSockets(void);
+	
+	// Go to the proper error state
+	void errorState(void);
 
 	void setSleepTime(F64 sleep_time, bool force_send = false);
 	F64 getSleepTime(void) const { return mSleepTime; };
@@ -110,6 +114,7 @@ class LLPluginProcessParent : public LLPluginMessagePipeOwner
 		STATE_HELLO,			// first message from the plugin process has been received
 		STATE_LOADING,			// process has been asked to load the plugin
 		STATE_RUNNING,			// 
+		STATE_LAUNCH_FAILURE,	// Failure before plugin loaded
 		STATE_ERROR,			// generic bailout state
 		STATE_CLEANUP,			// clean everything up
 		STATE_EXITING,			// Tried to kill process, waiting for it to exit
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 2675a27c08eee2c0c6ee0582df853142d4730049..da1cfc2074b4acd58c651167598d5a68d9b45585 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -43,7 +43,7 @@
 #include "llvolumemgr.h"
 #include "llstring.h"
 #include "lldatapacker.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
 #include "llprimtexturelist.h"
 
 /**
@@ -743,12 +743,204 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
 		setNumTEs(mVolumep->getNumFaces());
 		return TRUE;
 	}
+	
+	U32 old_face_mask = mVolumep->mFaceMask;
+
+	S32 face_bit = 0;
+	S32 cur_mask = 0;
+
+	// Grab copies of the old faces from the original shape, ordered by type.
+	// We will use these to figure out what old texture info gets mapped to new
+	// faces in the new shape.
+	std::vector<LLProfile::Face> old_faces; 
+	for (S32 face = 0; face < mVolumep->getNumFaces(); face++)
+	{
+		old_faces.push_back(mVolumep->getProfile().mFaces[face]);
+	}
+
+	// Copy the old texture info off to the side, but not in the order in which
+	// they live in the mTextureList, rather in order of ther "face id" which
+	// is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex.
+	//
+	// Hence, some elements of old_tes::mEntryList will be invalid.  It is
+	// initialized to a size of 9 (max number of possible faces on a volume?)
+	// and only the ones with valid types are filled in.
+	LLPrimTextureList old_tes;
+	old_tes.setSize(9);
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		cur_mask = 0x1 << face_bit;
+		if (old_face_mask & cur_mask)
+		{
+			S32 te_index = face_index_from_id(cur_mask, old_faces);
+			old_tes.copyTexture(face_bit, *(getTE(te_index)));
+			//llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl;
+		}
+	}
+
 
 	// build the new object
 	sVolumeManager->unrefVolume(mVolumep);
 	mVolumep = volumep;
+	
+	U32 new_face_mask = mVolumep->mFaceMask;
+	S32 i;
+
+	if (old_face_mask == new_face_mask) 
+	{
+		// nothing to do
+		return TRUE;
+	}
+
+	if (mVolumep->getNumFaces() == 0 && new_face_mask != 0)
+	{
+		llwarns << "Object with 0 faces found...INCORRECT!" << llendl;
+		setNumTEs(mVolumep->getNumFaces());
+		return TRUE;
+	}
+
+	// initialize face_mapping
+	S32 face_mapping[9];
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		face_mapping[face_bit] = face_bit;
+	}
+
+	// The new shape may have more faces than the original, but we can't just
+	// add them to the end -- the ordering matters and it may be that we must
+	// insert the new faces in the middle of the list.  When we add a face it
+	// will pick up the texture/color info of one of the old faces an so we
+	// now figure out which old face info gets mapped to each new face, and 
+	// store in the face_mapping lookup table.
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		cur_mask = 0x1 << face_bit;
+		if (!(new_face_mask & cur_mask))
+		{
+			// Face doesn't exist in new map.
+			face_mapping[face_bit] = -1;
+			continue;
+		}
+		else if (old_face_mask & cur_mask)
+		{
+			// Face exists in new and old map.
+			face_mapping[face_bit] = face_bit;
+			continue;
+		}
+
+		// OK, how we've got a mismatch, where we have to fill a new face with one from
+		// the old face.
+		if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE))
+		{
+			// It's a top/bottom/hollow interior face.
+			if (old_face_mask & LL_FACE_PATH_END)
+			{
+				face_mapping[face_bit] = 1;
+				continue;
+			}
+			else
+			{
+				S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+				for (i = 0; i < 4; i++)
+				{
+					if (old_face_mask & cur_outer_mask)
+					{
+						face_mapping[face_bit] = 5 + i;
+						break;
+					}
+					cur_outer_mask <<= 1;
+				}
+				if (i == 4)
+				{
+					llwarns << "No path end or outer face in volume!" << llendl;
+				}
+				continue;
+			}
+		}
+
+		if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END))
+		{
+			// A cut slice.  Use the hollow interior if we have it.
+			if (old_face_mask & LL_FACE_INNER_SIDE)
+			{
+				face_mapping[face_bit] = 2;
+				continue;
+			}
+
+			// No interior, use the bottom face.
+			// Could figure out which of the outer faces was nearest, but that would be harder.
+			if (old_face_mask & LL_FACE_PATH_END)
+			{
+				face_mapping[face_bit] = 1;
+				continue;
+			}
+			else
+			{
+				S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+				for (i = 0; i < 4; i++)
+				{
+					if (old_face_mask & cur_outer_mask)
+					{
+						face_mapping[face_bit] = 5 + i;
+						break;
+					}
+					cur_outer_mask <<= 1;
+				}
+				if (i == 4)
+				{
+					llwarns << "No path end or outer face in volume!" << llendl;
+				}
+				continue;
+			}
+		}
+
+		// OK, the face that's missing is an outer face...
+		// Pull from the nearest adjacent outer face (there's always guaranteed to be one...
+		S32 cur_outer = face_bit - 5;
+		S32 min_dist = 5;
+		S32 min_outer_bit = -1;
+		S32 i;
+		for (i = 0; i < 4; i++)
+		{
+			if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i))
+			{
+				S32 dist = abs(i - cur_outer);
+				if (dist < min_dist)
+				{
+					min_dist = dist;
+					min_outer_bit = i + 5;
+				}
+			}
+		}
+		if (-1 == min_outer_bit)
+		{
+			llinfos << (LLVolume *)mVolumep << llendl;
+			llwarns << "Bad!  No outer faces, impossible!" << llendl;
+		}
+		face_mapping[face_bit] = min_outer_bit;
+	}
+	
+
 	setNumTEs(mVolumep->getNumFaces());
-		
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		// For each possible face type on the new shape we check to see if that
+		// face exists and if it does we create a texture entry that is a copy
+		// of one of the originals.  Since the originals might not have a
+		// matching face, we use the face_mapping lookup table to figure out
+		// which face information to copy.
+		cur_mask = 0x1 << face_bit;
+		if (new_face_mask & cur_mask)
+		{
+			if (-1 == face_mapping[face_bit])
+			{
+				llwarns << "No mapping from old face to new face!" << llendl;
+			}
+
+			S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces);
+			setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit])));
+		}
+	}
 	return TRUE;
 }
 
@@ -1708,10 +1900,10 @@ LLSD LLLightImageParams::asLLSD() const
 
 bool LLLightImageParams::fromLLSD(LLSD& sd)
 {
-	if (sd.has("texture") && sd.has("params") && sd["params"].size() == 3)
+	if (sd.has("texture"))
 	{
 		setLightTexture( sd["texture"] );
-		setParams( LLVector3(sd["params"][0].asReal(), sd["params"][1].asReal(), sd["params"][2].asReal()) );
+		setParams( LLVector3( sd["params"] ) );
 		return true;
 	} 
 	
diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp
index d03150fc78b2b0873eedb452186087296679b61e..1c7de9597545627504c1c85cfb5cbeabc5bc7937 100644
--- a/indra/llprimitive/llprimtexturelist.cpp
+++ b/indra/llprimitive/llprimtexturelist.cpp
@@ -135,13 +135,12 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te)
 {
 	if (S32(index) >= mEntryList.size())
 	{
-		// TODO -- assert here
 		S32 current_size = mEntryList.size();
-		llerrs << "index = " << S32(index) << "  current_size = " << current_size << llendl;
+		llwarns << "ignore copy of index = " << S32(index) << " into texture entry list of size = " << current_size << llendl;
 		return TEM_CHANGE_NONE;
 	}
 
-	// we're changing an existing entry
+		// we're changing an existing entry
 	llassert(mEntryList[index]);
 	delete (mEntryList[index]);
 	if  (&te)
@@ -387,8 +386,18 @@ void LLPrimTextureList::setSize(S32 new_size)
 		mEntryList.resize(new_size);
 		for (S32 index = current_size; index < new_size; ++index)
 		{
-			LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
-			mEntryList[index] = new_entry;
+			if (current_size > 0
+				&& mEntryList[current_size - 1])
+			{
+				// copy the last valid entry for the new one
+				mEntryList[index] = mEntryList[current_size - 1]->newCopy();
+			}
+			else
+			{
+				// no valid enries to copy, so we new one up
+				LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
+				mEntryList[index] = new_entry;
+			}
 		}
 	}
 	else if (new_size < current_size)
diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp
index b534939dfc436d741731d62f4784df083ce0dc93..f75f1d9b8cd4d1e03102aae060039510f0bee670 100644
--- a/indra/llprimitive/lltextureentry.cpp
+++ b/indra/llprimitive/lltextureentry.cpp
@@ -35,7 +35,7 @@
 #include "lluuid.h"
 #include "llmediaentry.h"
 #include "lltextureentry.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
 #include "v4color.h"
 
 const U8 DEFAULT_BUMP_CODE = 0;  // no bump or shininess
@@ -646,3 +646,9 @@ LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &versi
     }
     return id;
 }
+
+//static
+bool LLTextureEntry::isMediaVersionString(const std::string &version_string)
+{
+	return std::string::npos != version_string.find(MEDIA_VERSION_STRING_PREFIX);
+}
diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index 8d2834f78c5a4218718dd55154059da8531e73a8..d6366b9bb253c74ada0048c44d8944c4d4656dd9 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -171,7 +171,9 @@ class LLTextureEntry
     static U32 getVersionFromMediaVersionString(const std::string &version_string);
     // Given a media version string, return the UUID of the agent
     static LLUUID getAgentIDFromMediaVersionString(const std::string &version_string);
-
+	// Return whether or not the given string is actually a media version
+	static bool isMediaVersionString(const std::string &version_string);
+	
 	// Media flags
 	enum { MF_NONE = 0x0, MF_HAS_MEDIA = 0x1 };
 
diff --git a/indra/llprimitive/tests/llmediaentry_test.cpp b/indra/llprimitive/tests/llmediaentry_test.cpp
index 72478d0459112198b7a7f2e6282d456965ce6608..9ce65609237884ed5c888e6b172043b02c61ee51 100644
--- a/indra/llprimitive/tests/llmediaentry_test.cpp
+++ b/indra/llprimitive/tests/llmediaentry_test.cpp
@@ -157,7 +157,7 @@ namespace tut
 
     void ensure_llsd_equals(const std::string& msg, const LLSD& expected, const LLSD& actual)
     {
-        if (! llsd_equals(expected, actual))
+        if (!tut::llsd_equals(expected, actual))
         {
             std::string message = msg;
             message += ": actual: ";
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index c9163d28906999b20acf48dafeda15dd941b2e13..793a526c2602f9c710f99d8e153600baa6d8edae 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -893,6 +893,13 @@ LLFontGL* LLFontGL::getFontByName(const std::string& name)
 	}
 }
 
+//static
+LLFontGL* LLFontGL::getFontDefault()
+{
+	return getFontSansSerif(); // Fallback to sans serif as default font
+}
+
+
 // static 
 std::string LLFontGL::getFontPathSystem()
 {
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index a278d88287042d39f8e68de92f90130e6fd1ce88..5f2c86c6c129ffa887aeaf695822f4c75c6cdec7 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -165,6 +165,7 @@ class LLFontGL
 	static LLFontGL* getFont(const LLFontDescriptor& desc);
 	// Use with legacy names like "SANSSERIF_SMALL" or "OCRA"
 	static LLFontGL* getFontByName(const std::string& name);
+	static LLFontGL* getFontDefault(); // default fallback font
 
 	static std::string getFontPathLocal();
 	static std::string getFontPathSystem();
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index 45573cd817a93f1c634a29107be2d3949927fef6..7a3d6ec4f2d09356a92b0566775a1571ebbe4f04 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -380,7 +380,10 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
 	LLFontDescriptor nearest_exact_desc = *match_desc;
 	nearest_exact_desc.setSize(norm_desc.getSize());
 	font_reg_map_t::iterator it = mFontMap.find(nearest_exact_desc);
-	if (it != mFontMap.end())
+	// If we fail to find a font in the fonts directory, it->second might be NULL.
+	// We shouldn't construcnt a font with a NULL mFontFreetype.
+	// This may not be the best solution, but it at least prevents a crash.
+	if (it != mFontMap.end() && it->second != NULL)
 	{
 		llinfos << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << llendl;
 		
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 10315bacf1b90bb81124f7800ac92d9e70d737a2..3400a7238572439f961e3b3148c56c7dd8bfe79f 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -593,8 +593,6 @@ void LLGLManager::shutdownGL()
 // these are used to turn software blending on. They appear in the Debug/Avatar menu
 // presence of vertex skinning/blending or vertex programs will set these to FALSE by default.
 
-extern LLCPUInfo gSysCPU;
-
 void LLGLManager::initExtensions()
 {
 #if LL_MESA_HEADLESS
diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h
index c18917b66346296b862584875fb58f9a34d1ccf8..0cd96676444b18222b33cc4bacb766b951c62367 100644
--- a/indra/llrender/lltexture.h
+++ b/indra/llrender/lltexture.h
@@ -61,6 +61,8 @@ class LLTexture : public LLRefCount
 	//
 	//interfaces to access LLViewerTexture
 	//
+	virtual S8         getType() const = 0 ;
+	virtual void       setKnownDrawSize(S32 width, S32 height) = 0 ;
 	virtual bool       bindDefaultImage(const S32 stage = 0) const = 0 ;
 	virtual void       forceImmediateUpdate() = 0 ;
 	virtual void       setActive() = 0 ;
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index f4d1284095fdccc1ea986916b26c8a442506c96e..f0b4436df584d87a8760421caa90d9c729f500cc 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -43,6 +43,7 @@ set(llui_SOURCE_FILES
     llflatlistview.cpp
     llfloater.cpp
     llfloaterreg.cpp
+    llfloaterreglistener.cpp
     llflyoutbutton.cpp 
     llfocusmgr.cpp
     llfunctorregistry.cpp
@@ -58,6 +59,7 @@ set(llui_SOURCE_FILES
     llmultislider.cpp
     llmultisliderctrl.cpp
     llnotifications.cpp
+    llnotificationslistener.cpp
     llpanel.cpp
     llprogressbar.cpp
     llradiogroup.cpp
@@ -127,6 +129,7 @@ set(llui_HEADER_FILES
     llflatlistview.h
     llfloater.h
     llfloaterreg.h
+    llfloaterreglistener.h
     llflyoutbutton.h 
     llfocusmgr.h
     llfunctorregistry.h
@@ -145,6 +148,7 @@ set(llui_HEADER_FILES
     llmultisliderctrl.h
     llmultislider.h
     llnotifications.h
+    llnotificationslistener.h
     llpanel.h
     llprogressbar.h
     llradiogroup.h
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index fd369730d6428854050736f0b750cb856810a551..a7946cacf54a06c285dd80ca05fa147a554ed9cb 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -486,6 +486,11 @@ void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)
 	mNeedsHighlight = FALSE;
 }
 
+void LLButton::setHighlight(bool b)
+{
+	mNeedsHighlight = b;
+}
+
 BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
 {
 	if (!childrenHandleHover(x, y, mask))
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 7fc49971336794b82004d8584e4ec4d2fde60526..85580a98bf25f3c781c66a718a4ff0438e181550 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -176,6 +176,7 @@ class LLButton
 	BOOL			getToggleState() const;
 	void			setToggleState(BOOL b);
 
+	void			setHighlight(bool b);
 	void			setFlashing( BOOL b );
 	BOOL			getFlashing() const		{ return mFlashing; }
 
@@ -241,8 +242,8 @@ class LLButton
 	void		setForcePressedState(BOOL b) { mForcePressedState = b; }
 	
 protected:
-	const LLPointer<LLUIImage>&	getImageUnselected() const	{ return mImageUnselected; }
-	const LLPointer<LLUIImage>& getImageSelected() const	{ return mImageSelected; }
+	LLPointer<LLUIImage> getImageUnselected() const	{ return mImageUnselected; }
+	LLPointer<LLUIImage> getImageSelected() const	{ return mImageSelected; }
 
 	LLFrameTimer	mMouseDownTimer;
 
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index 285ce82d2d61cfccfee88ff0a4fadfbab39b95b4..e0053b4cc70ce0a5a64ec4d4eb057c759e1c5ec3 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -120,6 +120,11 @@ void LLConsole::setFontSize(S32 size_index)
 	{
 		mFont = LLFontGL::getFontSansSerifHuge();
 	}
+	// Make sure the font exists
+	if (mFont == NULL)
+	{
+		mFont = LLFontGL::getFontDefault();
+	}
 	
 	for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++)
 	{
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
index 8eccd709ce6b669511900b4d10882673a9b35561..d9b98b1c285f579d823acda7edaf697dd804f12c 100644
--- a/indra/llui/lldraghandle.cpp
+++ b/indra/llui/lldraghandle.cpp
@@ -49,9 +49,9 @@
 #include "lluictrlfactory.h"
 
 const S32 LEADING_PAD = 5;
-const S32 TITLE_PAD = 8;
+const S32 TITLE_HPAD = 8;
 const S32 BORDER_PAD = 1;
-const S32 LEFT_PAD = BORDER_PAD + TITLE_PAD + LEADING_PAD;
+const S32 LEFT_PAD = BORDER_PAD + TITLE_HPAD + LEADING_PAD;
 const S32 RIGHT_PAD = BORDER_PAD + 32; // HACK: space for close btn and minimize btn
 
 S32 LLDragHandle::sSnapMargin = 5;
@@ -240,19 +240,20 @@ void LLDragHandleLeft::draw()
 
 void LLDragHandleTop::reshapeTitleBox()
 {
+	static LLUICachedControl<S32> title_vpad("UIFloaterTitleVPad", 0);
 	if( ! mTitleBox)
 	{
 		return;
 	}
 	const LLFontGL* font = LLFontGL::getFontSansSerif();
-	S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_PAD;
+	S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_HPAD;
 	if (getMaxTitleWidth() > 0)
 		title_width = llmin(title_width, getMaxTitleWidth());
 	S32 title_height = llround(font->getLineHeight());
 	LLRect title_rect;
 	title_rect.setLeftTopAndSize( 
 		LEFT_PAD, 
-		getRect().getHeight() - BORDER_PAD,
+		getRect().getHeight() - title_vpad,
 		getRect().getWidth() - LEFT_PAD - RIGHT_PAD,
 		title_height);
 
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 0c0c5921ceb16128b8b0392069049d3ece32bd02..8c72b079eee4dc71222705579a9824dc972fcfec 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -61,6 +61,7 @@
 #include "lltrans.h"
 #include "llhelp.h"
 #include "llmultifloater.h"
+#include "llsdutil.h"
 
 // use this to control "jumping" behavior when Ctrl-Tabbing
 const S32 TABBED_FLOATER_OFFSET = 0;
@@ -132,6 +133,16 @@ LLFloater::handle_map_t	LLFloater::sFloaterMap;
 
 LLFloaterView* gFloaterView = NULL;
 
+/*==========================================================================*|
+// DEV-38598: The fundamental problem with this operation is that it can only
+// support a subset of LLSD values. While it's plausible to compare two arrays
+// lexicographically, what strict ordering can you impose on maps?
+// (LLFloaterTOS's current key is an LLSD map.)
+
+// Of course something like this is necessary if you want to build a std::set
+// or std::map with LLSD keys. Fortunately we're getting by with other
+// container types for now.
+
 //static
 bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b)
 {
@@ -159,32 +170,11 @@ bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b)
 	else
 		return false; // no valid operation for Binary
 }
+|*==========================================================================*/
 
 bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b)
 {
-	if (a.type() != b.type())
-	{
-		//llerrs << "Mismatched LLSD types: (" << a << ") mismatches (" << b << ")" << llendl;
-		return false;
-	}
-	else if (a.isUndefined())
-		return true;
-	else if (a.isInteger())
-		return a.asInteger() == b.asInteger();
-	else if (a.isReal())
-		return a.asReal() == b.asReal();
-	else if (a.isString())
-		return a.asString() == b.asString();
-	else if (a.isUUID())
-		return a.asUUID() == b.asUUID();
-	else if (a.isDate())
-		return a.asDate() == b.asDate();
-	else if (a.isURI())
-		return a.asString() == b.asString(); // compare URIs as strings
-	else if (a.isBoolean())
-		return a.asBoolean() == b.asBoolean();
-	else
-		return false; // no valid operation for Binary
+	return llsd_equals(a, b);
 }
 
 //************************************
@@ -199,11 +189,14 @@ LLFloater::Params::Params()
 	can_close("can_close", true),
 	can_drag_on_left("can_drag_on_left", false),
 	can_tear_off("can_tear_off", true),
+	save_dock_state("save_dock_state", false),
 	save_rect("save_rect", false),
 	save_visibility("save_visibility", false),
+	can_dock("can_dock", false),
+	header_height("header_height", 0),
+	legacy_header_height("legacy_header_height", 0),
 	open_callback("open_callback"),
-	close_callback("close_callback"),
-	can_dock("can_dock", false)
+	close_callback("close_callback")
 {
 	visible = false;
 }
@@ -229,7 +222,7 @@ void LLFloater::initClass()
 static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater");
 
 LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
-:	LLPanel(),
+:	LLPanel(),	// intentionally do not pass params here, see initFromParams
 	mDragHandle(NULL),
 	mTitle(p.title),
 	mShortTitle(p.short_title),
@@ -243,6 +236,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
 	mResizable(p.can_resize),
 	mMinWidth(p.min_width),
 	mMinHeight(p.min_height),
+	mHeaderHeight(p.header_height),
+	mLegacyHeaderHeight(p.legacy_header_height),
 	mMinimized(FALSE),
 	mForeground(FALSE),
 	mFirstLook(TRUE),
@@ -273,11 +268,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
 		mButtonsEnabled[i] = FALSE;
 		mButtons[i] = NULL;
 	}
-	for (S32 i = 0; i < 4; i++) 
-	{
-		mResizeBar[i] = NULL; 
-		mResizeHandle[i] = NULL;
-	}
+	addDragHandle();
+	addResizeCtrls();
 	
 	initFromParams(p);
 	
@@ -290,10 +282,6 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
 // Note: Floaters constructed from XML call init() twice!
 void LLFloater::initFloater()
 {
-	addDragHandle();
-	
-	addResizeCtrls();
-
 	// Close button.
 	if (mCanClose)
 	{
@@ -333,9 +321,6 @@ void LLFloater::initFloater()
 
 void LLFloater::addDragHandle()
 {
-	static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
-	S32 close_box_size = mCanClose ? floater_close_box_size : 0;
-	
 	if (!mDragHandle)
 	{
 		if (mDragOnLeft)
@@ -356,6 +341,14 @@ void LLFloater::addDragHandle()
 		}
 		addChild(mDragHandle);
 	}
+	layoutDragHandle();
+}
+
+void LLFloater::layoutDragHandle()
+{
+	static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
+	S32 close_box_size = mCanClose ? floater_close_box_size : 0;
+	
 	LLRect rect;
 	if (mDragOnLeft)
 	{
@@ -371,40 +364,17 @@ void LLFloater::addDragHandle()
 }
 
 void LLFloater::addResizeCtrls()
-{
-	for (S32 i = 0; i < 4; i++) 
-	{
-		if (mResizeBar[i])
-		{
-			removeChild(mResizeBar[i]);
-			delete mResizeBar[i];
-			mResizeBar[i] = NULL;
-		}
-		if (mResizeHandle[i])
-		{
-			removeChild(mResizeHandle[i]);
-			delete mResizeHandle[i];
-			mResizeHandle[i] = NULL;
-		}
-	}
-	if( !mResizable )
-	{
-		return;
-	}
-	
+{	
 	// Resize bars (sides)
-	const S32 RESIZE_BAR_THICKNESS = 3;
 	LLResizeBar::Params p;
 	p.name("resizebar_left");
 	p.resizing_view(this);
-	p.rect(LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0));
 	p.min_size(mMinWidth);
 	p.side(LLResizeBar::LEFT);
 	mResizeBar[LLResizeBar::LEFT] = LLUICtrlFactory::create<LLResizeBar>(p);
 	addChild( mResizeBar[LLResizeBar::LEFT] );
 
 	p.name("resizebar_top");
-	p.rect(LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS));
 	p.min_size(mMinHeight);
 	p.side(LLResizeBar::TOP);
 
@@ -412,15 +382,12 @@ void LLFloater::addResizeCtrls()
 	addChild( mResizeBar[LLResizeBar::TOP] );
 
 	p.name("resizebar_right");
-	p.rect(LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0));
 	p.min_size(mMinWidth);
-	p.side(LLResizeBar::RIGHT);
-	
+	p.side(LLResizeBar::RIGHT);	
 	mResizeBar[LLResizeBar::RIGHT] = LLUICtrlFactory::create<LLResizeBar>(p);
 	addChild( mResizeBar[LLResizeBar::RIGHT] );
 
 	p.name("resizebar_bottom");
-	p.rect(LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0));
 	p.min_size(mMinHeight);
 	p.side(LLResizeBar::BOTTOM);
 	mResizeBar[LLResizeBar::BOTTOM] = LLUICtrlFactory::create<LLResizeBar>(p);
@@ -431,27 +398,69 @@ void LLFloater::addResizeCtrls()
 	// handles must not be mouse-opaque, otherwise they block hover events
 	// to other buttons like the close box. JC
 	handle_p.mouse_opaque(false);
-	handle_p.rect(LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0));
 	handle_p.min_width(mMinWidth);
 	handle_p.min_height(mMinHeight);
 	handle_p.corner(LLResizeHandle::RIGHT_BOTTOM);
 	mResizeHandle[0] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
 	addChild(mResizeHandle[0]);
 
-	handle_p.rect(LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT));
 	handle_p.corner(LLResizeHandle::RIGHT_TOP);
 	mResizeHandle[1] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
 	addChild(mResizeHandle[1]);
 	
-	handle_p.rect(LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ));
 	handle_p.corner(LLResizeHandle::LEFT_BOTTOM);
 	mResizeHandle[2] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
 	addChild(mResizeHandle[2]);
 
-	handle_p.rect(LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ));
 	handle_p.corner(LLResizeHandle::LEFT_TOP);
 	mResizeHandle[3] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
 	addChild(mResizeHandle[3]);
+
+	layoutResizeCtrls();
+}
+
+void LLFloater::layoutResizeCtrls()
+{
+	LLRect rect;
+
+	// Resize bars (sides)
+	const S32 RESIZE_BAR_THICKNESS = 3;
+	rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0);
+	mResizeBar[LLResizeBar::LEFT]->setRect(rect);
+
+	rect = LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS);
+	mResizeBar[LLResizeBar::TOP]->setRect(rect);
+
+	rect = LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0);
+	mResizeBar[LLResizeBar::RIGHT]->setRect(rect);
+
+	rect = LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0);
+	mResizeBar[LLResizeBar::BOTTOM]->setRect(rect);
+
+	// Resize handles (corners)
+	rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0);
+	mResizeHandle[0]->setRect(rect);
+
+	rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT);
+	mResizeHandle[1]->setRect(rect);
+	
+	rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 );
+	mResizeHandle[2]->setRect(rect);
+
+	rect = LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT );
+	mResizeHandle[3]->setRect(rect);
+}
+
+void LLFloater::enableResizeCtrls(bool enable)
+{
+	for (S32 i = 0; i < 4; ++i)
+	{
+		mResizeBar[i]->setVisible(enable);
+		mResizeBar[i]->setEnabled(enable);
+
+		mResizeHandle[i]->setVisible(enable);
+		mResizeHandle[i]->setEnabled(enable);
+	}
 }
 
 // virtual
@@ -493,6 +502,7 @@ LLFloater::~LLFloater()
 	storeRectControl();
 	setVisible(false); // We're not visible if we're destroyed
 	storeVisibilityControl();
+	storeDockStateControl();
 }
 
 void LLFloater::storeRectControl()
@@ -511,6 +521,15 @@ void LLFloater::storeVisibilityControl()
 	}
 }
 
+void LLFloater::storeDockStateControl()
+{
+	if( !sQuitting && mDocStateControl.size() > 1 )
+	{
+		LLUI::sSettingGroups["floater"]->setBOOL( mDocStateControl, isDocked() );
+	}
+}
+
+
 void LLFloater::setVisible( BOOL visible )
 {
 	LLPanel::setVisible(visible); // calls handleVisibilityChange()
@@ -769,6 +788,16 @@ void LLFloater::applyRectControl()
 	}
 }
 
+void LLFloater::applyDockState()
+{
+	if (mDocStateControl.size() > 1)
+	{
+		bool dockState = LLUI::sSettingGroups["floater"]->getBOOL(mDocStateControl);
+		setDocked(dockState);
+	}
+
+}
+
 void LLFloater::applyTitle()
 {
 	if (!mDragHandle)
@@ -919,7 +948,8 @@ void LLFloater::handleReshape(const LLRect& new_rect, bool by_user)
 
 void LLFloater::setMinimized(BOOL minimize)
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+	S32 floater_header_size = default_params.header_height;
 	static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0);
 
 	if (minimize == mMinimized) return;
@@ -1092,7 +1122,8 @@ void LLFloater::setFocus( BOOL b )
 void LLFloater::setRect(const LLRect &rect)
 {
 	LLPanel::setRect(rect);
-	addDragHandle(); // re-add drag handle, sized based on rect
+	layoutDragHandle();
+	layoutResizeCtrls();
 }
 
 // virtual
@@ -1386,7 +1417,10 @@ void LLFloater::setDocked(bool docked, bool pop_on_undock)
 		mButtonsEnabled[BUTTON_DOCK] = !mDocked;
 		mButtonsEnabled[BUTTON_UNDOCK] = mDocked;
 		updateButtons();
+
+		storeDockStateControl();
 	}
+	
 }
 
 // static
@@ -1399,9 +1433,9 @@ void LLFloater::onClickMinimize(LLFloater* self)
 
 void LLFloater::onClickTearOff(LLFloater* self)
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
 	if (!self)
 		return;
+	S32 floater_header_size = self->mHeaderHeight;
 	LLMultiFloater* host_floater = self->getHost();
 	if (host_floater) //Tear off
 	{
@@ -1558,26 +1592,42 @@ void LLFloater::draw()
 			shadow_color % alpha, 
 			llround(shadow_offset));
 
-		// No transparent windows in simple UI
+		LLUIImage* image = NULL;
+		LLColor4 color;
 		if (isBackgroundOpaque())
 		{
-			gl_rect_2d( left, top, right, bottom, getBackgroundColor() % alpha );
+			// NOTE: image may not be set
+			image = getBackgroundImage();
+			color = getBackgroundColor();
 		}
 		else
 		{
-			gl_rect_2d( left, top, right, bottom, getTransparentColor() % alpha );
+			image = getTransparentImage();
+			color = getTransparentColor();
 		}
 
-		if(hasFocus() 
-			&& !getIsChrome() 
-			&& !getCurrentTitle().empty())
+		if (image)
 		{
-			static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor");
+			// We're using images for this floater's backgrounds
+			image->draw(getLocalRect(), UI_VERTEX_COLOR % alpha);
+		}
+		else
+		{
+			// We're not using images, use old-school flat colors
+			gl_rect_2d( left, top, right, bottom, color % alpha );
+
 			// draw highlight on title bar to indicate focus.  RDW
-			const LLFontGL* font = LLFontGL::getFontSansSerif();
-			LLRect r = getRect();
-			gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, 
-				titlebar_focus_color % alpha, 0, TRUE);
+			if(hasFocus() 
+				&& !getIsChrome() 
+				&& !getCurrentTitle().empty())
+			{
+				static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor");
+				
+				const LLFontGL* font = LLFontGL::getFontSansSerif();
+				LLRect r = getRect();
+				gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, 
+					titlebar_focus_color % alpha, 0, TRUE);
+			}
 		}
 	}
 
@@ -1627,18 +1677,6 @@ void LLFloater::draw()
 		drawChild(focused_child);
 	}
 
-	if( isBackgroundVisible() )
-	{
-		// add in a border to improve spacialized visual aclarity ;)
-		// use lines instead of gl_rect_2d so we can round the edges as per james' recommendation
-		static LLUIColor focus_border_color = LLUIColorTable::instance().getColor("FloaterFocusBorderColor");
-		static LLUIColor unfocus_border_color = LLUIColorTable::instance().getColor("FloaterUnfocusBorderColor");
-		LLUI::setLineWidth(1.5f);
-		LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? focus_border_color : unfocus_border_color;
-		gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor % alpha, -LLPANEL_BORDER_WIDTH, FALSE);
-		LLUI::setLineWidth(1.f);
-	}
-
 	// update tearoff button for torn off floaters
 	// when last host goes away
 	if (mCanTearOff && !getHost())
@@ -1687,7 +1725,7 @@ void	LLFloater::setCanTearOff(BOOL can_tear_off)
 void LLFloater::setCanResize(BOOL can_resize)
 {
 	mResizable = can_resize;
-	addResizeCtrls();
+	enableResizeCtrls(can_resize);
 }
 
 void LLFloater::setCanDrag(BOOL can_drag)
@@ -2123,7 +2161,8 @@ void LLFloaterView::focusFrontFloater()
 
 void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+	S32 floater_header_size = default_params.header_height;
 	static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0);
 	S32 col = 0;
 	LLRect snap_rect_local = getLocalSnapRect();
@@ -2498,6 +2537,11 @@ void LLFloater::setInstanceName(const std::string& name)
 		{
 			mVisibilityControl = LLFloaterReg::declareVisibilityControl(mInstanceName);
 		}
+		if(!mDocStateControl.empty())
+		{
+			mDocStateControl = LLFloaterReg::declareDockStateControl(mInstanceName);
+		}
+
 	}
 }
 
@@ -2538,6 +2582,9 @@ void LLFloater::setupParamsForExport(Params& p, LLView* parent)
 
 void LLFloater::initFromParams(const LLFloater::Params& p)
 {
+	// *NOTE: We have too many classes derived from LLFloater to retrofit them 
+	// all to pass in params via constructors.  So we use this method.
+
 	 // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible
 	LLPanel::initFromParams(p);
 
@@ -2549,11 +2596,12 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
 	setCanMinimize(p.can_minimize);
 	setCanClose(p.can_close);
 	setCanDock(p.can_dock);
+	setCanResize(p.can_resize);
+	setResizeLimits(p.min_width, p.min_height);
 	
 	mDragOnLeft = p.can_drag_on_left;
-	mResizable = p.can_resize;
-	mMinWidth = p.min_width;
-	mMinHeight = p.min_height;
+	mHeaderHeight = p.header_height;
+	mLegacyHeaderHeight = p.legacy_header_height;
 	mSingleInstance = p.single_instance;
 	mAutoTile = p.auto_tile;
 
@@ -2565,6 +2613,11 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
 	{
 		mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set
 	}
+
+	if(p.save_dock_state)
+	{
+		mDocStateControl = "t"; // flag to build mDocStateControl name once mInstanceName is set
+	}
 	
 	// open callback 
 	if (p.open_callback.isProvided())
@@ -2609,6 +2662,23 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
 		LLFloater::setFloaterHost(last_host);
 	}
 	
+	// HACK: When we changed the header height to 25 pixels in Viewer 2, rather
+	// than re-layout all the floaters we use this value in pixels to make the
+	// whole floater bigger and change the top-left coordinate for widgets.
+	// The goal is to eventually set mLegacyHeaderHeight to zero, which would
+	// make the top-left corner for widget layout the same as the top-left
+	// corner of the window's content area.  James
+	S32 header_stretch = (mHeaderHeight - mLegacyHeaderHeight);
+	if (header_stretch > 0)
+	{
+		// Stretch the floater vertically, don't move widgets
+		LLRect rect = getRect();
+		rect.mTop += header_stretch;
+
+		// This will also update drag handle, title bar, close box, etc.
+		setRect(rect);
+	}
+
 	BOOL result;
 	{
 		LLFastTimer ft(POST_BUILD);
@@ -2626,6 +2696,18 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
 
 	moveResizeHandlesToFront();
 
+	applyDockState();
+
 	return true; // *TODO: Error checking
 }
 
+bool LLFloater::isShown() const
+{
+    return ! isMinimized() && isInVisibleChain();
+}
+
+/* static */
+bool LLFloater::isShown(const LLFloater* floater)
+{
+    return floater && floater->isShown();
+}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 123de1239824381b338bb8f2c39e76260f082634..ef0d06a58eaa347b3d9705ecbcf690b55771720a 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -87,12 +87,14 @@ friend class LLMultiFloater;
 public:
 	struct KeyCompare
 	{
-		static bool compare(const LLSD& a, const LLSD& b);
+//		static bool compare(const LLSD& a, const LLSD& b);
 		static bool equate(const LLSD& a, const LLSD& b);
+/*==========================================================================*|
 		bool operator()(const LLSD& a, const LLSD& b) const
 		{
 			return compare(a, b);
 		}
+|*==========================================================================*/
 	};
 	
 	enum EFloaterButtons
@@ -122,7 +124,10 @@ friend class LLMultiFloater;
 								can_tear_off,
 								save_rect,
 								save_visibility,
+								save_dock_state,
 								can_dock;
+		Optional<S32>			header_height,
+								legacy_header_height; // HACK see initFromXML()
 		
 		Optional<CommitCallbackParam> open_callback,
 									  close_callback;
@@ -183,7 +188,13 @@ friend class LLMultiFloater;
 	void			addDependentFloater(LLHandle<LLFloater> dependent_handle, BOOL reposition = TRUE);
 	LLFloater*		getDependee() { return (LLFloater*)mDependeeHandle.get(); }
 	void		removeDependentFloater(LLFloater* dependent);
-	BOOL			isMinimized()					{ return mMinimized; }
+	BOOL			isMinimized() const				{ return mMinimized; }
+	/// isShown() differs from getVisible() in that isShown() also considers
+	/// isMinimized(). isShown() is true only if visible and not minimized.
+	bool			isShown() const;
+	/// The static isShown() can accept a NULL pointer (which of course
+	/// returns false). When non-NULL, it calls the non-static isShown().
+	static bool		isShown(const LLFloater* floater);
 	BOOL			isFrontmost();
 	BOOL			isDependent()					{ return !mDependeeHandle.isDead(); }
 	void			setCanMinimize(BOOL can_minimize);
@@ -201,6 +212,7 @@ friend class LLMultiFloater;
 	bool			isDragOnLeft() const{ return mDragOnLeft; }
 	S32				getMinWidth() const{ return mMinWidth; }
 	S32				getMinHeight() const{ return mMinHeight; }
+	S32				getHeaderHeight() const { return mHeaderHeight; }
 
 	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);
@@ -269,8 +281,10 @@ friend class LLMultiFloater;
 
 	void			setRectControl(const std::string& rectname) { mRectControl = rectname; };
 	void			applyRectControl();
+	void			applyDockState();
 	void			storeRectControl();
 	void			storeVisibilityControl();
+	void			storeDockStateControl();
 
 	void		 	setKey(const LLSD& key);
 	void		 	setInstanceName(const std::string& name);
@@ -294,7 +308,10 @@ friend class LLMultiFloater;
 	void			buildButtons();
 	BOOL			offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index);
 	void			addResizeCtrls();
+	void			layoutResizeCtrls();
+	void			enableResizeCtrls(bool enable);
 	void 			addDragHandle();
+	void			layoutDragHandle();		// repair layout
 
 public:
 	// Called when floater is opened, passes mKey
@@ -308,6 +325,7 @@ friend class LLMultiFloater;
 protected:
 	std::string		mRectControl;
 	std::string		mVisibilityControl;
+	std::string		mDocStateControl;
 	LLSD			mKey;				// Key used for retrieving instances; set (for now) by LLFLoaterReg
 
 	LLDragHandle*	mDragHandle;
@@ -332,6 +350,8 @@ friend class LLMultiFloater;
 	
 	S32				mMinWidth;
 	S32				mMinHeight;
+	S32				mHeaderHeight;		// height in pixels of header for title, drag bar
+	S32				mLegacyHeaderHeight;// HACK see initFloaterXML()
 	
 	BOOL			mMinimized;
 	BOOL			mForeground;
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 815260dff3e721c8015a662ef1ffd576dd022bb7..aca4dc56eed59bc9f53da99dd3b6e1a5ac23ec89 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -36,6 +36,7 @@
 
 #include "llfloater.h"
 #include "llmultifloater.h"
+#include "llfloaterreglistener.h"
 
 //*******************************************************
 
@@ -45,6 +46,8 @@ LLFloaterReg::instance_map_t LLFloaterReg::sInstanceMap;
 LLFloaterReg::build_map_t LLFloaterReg::sBuildMap;
 std::map<std::string,std::string> LLFloaterReg::sGroupMap;
 
+static LLFloaterRegListener sFloaterRegListener("LLFloaterReg");
+
 //*******************************************************
 
 //static
@@ -124,7 +127,7 @@ LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key)
 				bool success = LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, NULL);
 				if (!success)
 				{
-					llwarns << "Failed to buid floater type: '" << name << "'." << llendl;
+					llwarns << "Failed to build floater type: '" << name << "'." << llendl;
 					return NULL;
 				}
 					
@@ -132,6 +135,7 @@ LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key)
 				res->mKey = key;
 				res->setInstanceName(name);
 				res->applyRectControl(); // Can't apply rect control until setting instance name
+				res->applyDockState();//same...
 				if (res->mAutoTile && !res->getHost() && index > 0)
 				{
 					const LLRect& cur_rect = res->getRect();
@@ -249,7 +253,7 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key)
 bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
 {
 	LLFloater* instance = findInstance(name, key); 
-	if (instance && !instance->isMinimized() && instance->isInVisibleChain())
+	if (LLFloater::isShown(instance))
 	{
 		// When toggling *visibility*, close the host instead of the floater when hosted
 		if (instance->getHost())
@@ -269,14 +273,7 @@ bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
 bool LLFloaterReg::instanceVisible(const std::string& name, const LLSD& key)
 {
 	LLFloater* instance = findInstance(name, key); 
-	if (instance && !instance->isMinimized() && instance->isInVisibleChain())
-	{
-		return true;
-	}
-	else
-	{
-		return false;
-	}
+	return LLFloater::isShown(instance);
 }
 
 //static
@@ -367,6 +364,26 @@ std::string LLFloaterReg::declareVisibilityControl(const std::string& name)
 	return controlname;
 }
 
+//static
+std::string LLFloaterReg::declareDockStateControl(const std::string& name)
+{
+	std::string controlname = getDockStateControlName(name);
+	LLUI::sSettingGroups["floater"]->declareBOOL(controlname, FALSE,
+												 llformat("Window Docking state for %s", name.c_str()),
+												 TRUE);
+	return controlname;
+
+}
+
+//static
+std::string LLFloaterReg::getDockStateControlName(const std::string& name)
+{
+	std::string res = std::string("floater_dock_") + name;
+	LLStringUtil::replaceChar( res, ' ', '_' );
+	return res;
+}
+
+
 //static
 void LLFloaterReg::registerControlVariables()
 {
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index 7edac43c96b45701e89d5a4364da8776397b972a..634a235926b305e6e6ba1467889c5a9427728222 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -70,6 +70,7 @@ class LLFloaterReg
 	typedef std::map<std::string, BuildData> build_map_t;
 	
 private:
+	friend class LLFloaterRegListener;
 	static instance_list_t sNullInstanceList;
 	static instance_map_t sInstanceMap;
 	static build_map_t sBuildMap;
@@ -120,6 +121,10 @@ class LLFloaterReg
 	static std::string declareRectControl(const std::string& name);
 	static std::string getVisibilityControlName(const std::string& name);
 	static std::string declareVisibilityControl(const std::string& name);
+
+	static std::string declareDockStateControl(const std::string& name);
+	static std::string getDockStateControlName(const std::string& name);
+
 	static void registerControlVariables();
 
 	// Callback wrappers
diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..57d148b5af474025a2fd9bbbc94f816c7850da2a
--- /dev/null
+++ b/indra/llui/llfloaterreglistener.cpp
@@ -0,0 +1,114 @@
+/**
+ * @file   llfloaterreglistener.cpp
+ * @author Nat Goodspeed
+ * @date   2009-08-12
+ * @brief  Implementation for llfloaterreglistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llfloaterreglistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llfloaterreg.h"
+#include "llfloater.h"
+#include "llbutton.h"
+
+LLFloaterRegListener::LLFloaterRegListener(const std::string& pumpName):
+    LLDispatchListener(pumpName, "op")
+{
+    add("getBuildMap",  &LLFloaterRegListener::getBuildMap,  LLSD().insert("reply", LLSD()));
+    LLSD requiredName;
+    requiredName["name"] = LLSD();
+    add("showInstance", &LLFloaterRegListener::showInstance, requiredName);
+    add("hideInstance", &LLFloaterRegListener::hideInstance, requiredName);
+    add("toggleInstance", &LLFloaterRegListener::toggleInstance, requiredName);
+    LLSD requiredNameButton;
+    requiredNameButton["name"] = LLSD();
+    requiredNameButton["button"] = LLSD();
+    add("clickButton", &LLFloaterRegListener::clickButton, requiredNameButton);
+}
+
+void LLFloaterRegListener::getBuildMap(const LLSD& event) const
+{
+    // Honor the "reqid" convention by echoing event["reqid"] in our reply packet.
+    LLReqID reqID(event);
+    LLSD reply(reqID.makeResponse());
+    // Build an LLSD map that mirrors sBuildMap. Since we have no good way to
+    // represent a C++ callable in LLSD, the only part of BuildData we can
+    // store is the filename. For each LLSD map entry, it would be more
+    // extensible to store a nested LLSD map containing a single key "file" --
+    // but we don't bother, simply storing the string filename instead.
+    for (LLFloaterReg::build_map_t::const_iterator mi(LLFloaterReg::sBuildMap.begin()),
+                                                   mend(LLFloaterReg::sBuildMap.end());
+         mi != mend; ++mi)
+    {
+        reply[mi->first] = mi->second.mFile;
+    }
+    // Send the reply to the LLEventPump named in event["reply"].
+    LLEventPumps::instance().obtain(event["reply"]).post(reply);
+}
+
+void LLFloaterRegListener::showInstance(const LLSD& event) const
+{
+    LLFloaterReg::showInstance(event["name"], event["key"], event["focus"]);
+}
+
+void LLFloaterRegListener::hideInstance(const LLSD& event) const
+{
+    LLFloaterReg::hideInstance(event["name"], event["key"]);
+}
+
+void LLFloaterRegListener::toggleInstance(const LLSD& event) const
+{
+    LLFloaterReg::toggleInstance(event["name"], event["key"]);
+}
+
+void LLFloaterRegListener::clickButton(const LLSD& event) const
+{
+    // If the caller requests a reply, build the reply.
+    LLReqID reqID(event);
+    LLSD reply(reqID.makeResponse());
+
+    LLFloater* floater = LLFloaterReg::findInstance(event["name"], event["key"]);
+    if (! LLFloater::isShown(floater))
+    {
+        reply["type"]  = "LLFloater";
+        reply["name"]  = event["name"];
+        reply["key"]   = event["key"];
+        reply["error"] = floater? "!isShown()" : "NULL";
+    }
+    else
+    {
+        // Here 'floater' points to an LLFloater instance with the specified
+        // name and key which isShown().
+        LLButton* button = floater->findChild<LLButton>(event["button"]);
+        if (! LLButton::isAvailable(button))
+        {
+            reply["type"]  = "LLButton";
+            reply["name"]  = event["button"];
+            reply["error"] = button? "!isAvailable()" : "NULL";
+        }
+        else
+        {
+            // Here 'button' points to an isAvailable() LLButton child of
+            // 'floater' with the specified button name. Pretend to click it.
+            button->onCommit();
+            // Leave reply["error"] isUndefined(): no error, i.e. success.
+        }
+    }
+
+    // Send a reply only if caller asked for a reply.
+    LLSD replyPump(event["reply"]);
+    if (replyPump.isString())       // isUndefined() if absent
+    {
+        LLEventPumps::instance().obtain(replyPump).post(reply);
+    }
+}
diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..304ecd10904aebd567289db04c69c7da45136318
--- /dev/null
+++ b/indra/llui/llfloaterreglistener.h
@@ -0,0 +1,36 @@
+/**
+ * @file   llfloaterreglistener.h
+ * @author Nat Goodspeed
+ * @date   2009-08-12
+ * @brief  Wrap (subset of) LLFloaterReg API with an event API
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLFLOATERREGLISTENER_H)
+#define LL_LLFLOATERREGLISTENER_H
+
+#include "lleventdispatcher.h"
+#include <string>
+
+class LLSD;
+
+/// Event API wrapper for LLFloaterReg
+class LLFloaterRegListener: public LLDispatchListener
+{
+public:
+    /// As all public LLFloaterReg methods are static, there's no point in
+    /// binding an LLFloaterReg instance.
+    LLFloaterRegListener(const std::string& pumpName);
+
+private:
+    void getBuildMap(const LLSD& event) const;
+    void showInstance(const LLSD& event) const;
+    void hideInstance(const LLSD& event) const;
+    void toggleInstance(const LLSD& event) const;
+    void clickButton(const LLSD& event) const;
+};
+
+#endif /* ! defined(LL_LLFLOATERREGLISTENER_H) */
diff --git a/indra/llui/llfunctorregistry.cpp b/indra/llui/llfunctorregistry.cpp
index 0c5b1655b1011a4d49c7a0094a9446d85931cd0d..5f9644f258476bb8b74757705042e88ba035956d 100644
--- a/indra/llui/llfunctorregistry.cpp
+++ b/indra/llui/llfunctorregistry.cpp
@@ -31,6 +31,7 @@
  * $/LicenseInfo$
  **/
 
+#include "linden_common.h"
 #include "llfunctorregistry.h"
 
 // This is a default functor always resident in the system.
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index 0330a2b374c44498f6d6f253ad4ec482678fde26..1e2353b488d88e8cfca241a08ddd5b640ec04f85 100644
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -56,7 +56,10 @@ LLIconCtrl::Params::Params()
 LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p)
 :	LLUICtrl(p),
 	mColor(p.color()),
-	mImagep(p.image)
+	mImagep(p.image),
+	mPriority(0),
+	mDrawWidth(0),
+	mDrawHeight(0)
 {
 	if (mImagep.notNull())
 	{
@@ -93,12 +96,14 @@ void LLIconCtrl::setValue(const LLSD& value )
 	LLUICtrl::setValue(tvalue);
 	if (tvalue.isUUID())
 	{
-		mImagep = LLUI::getUIImageByID(tvalue.asUUID());
+		mImagep = LLUI::getUIImageByID(tvalue.asUUID(), mPriority);
 	}
 	else
 	{
-		mImagep = LLUI::getUIImage(tvalue.asString());
+		mImagep = LLUI::getUIImage(tvalue.asString(), mPriority);
 	}
+
+	setIconImageDrawSize();
 }
 
 std::string LLIconCtrl::getImageName() const
@@ -108,3 +113,16 @@ std::string LLIconCtrl::getImageName() const
 	else
 		return std::string();
 }
+
+void LLIconCtrl::setIconImageDrawSize()
+{
+	if(mImagep.notNull() && mDrawWidth && mDrawHeight)
+	{
+		if(mImagep->getImage().notNull())
+		{
+			mImagep->getImage()->setKnownDrawSize(mDrawWidth, mDrawHeight) ;
+		}
+	}
+}
+
+
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index ff25b0d53eabe113c79928c24b3a3133e6483123..66368f979b6a74d9baedc8294fe1f6d5c6d6b844 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -60,6 +60,7 @@ class LLIconCtrl
 protected:
 	LLIconCtrl(const Params&);
 	friend class LLUICtrlFactory;
+
 public:
 	virtual ~LLIconCtrl();
 
@@ -72,10 +73,20 @@ class LLIconCtrl
 	std::string	getImageName() const;
 
 	void			setColor(const LLColor4& color) { mColor = color; }
+	
+private:
+	void setIconImageDrawSize() ;
+
+protected:
+	S32 mPriority;
+
+	//the output size of the icon image if set.
+	S32 mDrawWidth ;
+	S32 mDrawHeight ;
 
 private:
 	LLUIColor mColor;
-	LLPointer<LLUIImage>	mImagep;
+	LLPointer<LLUIImage> mImagep;
 };
 
 #endif
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index e053477d58e1acd19074713634a07b5aa117de89..75905d092740d4e838eb12e53a83b00e7d5f9f6f 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -1544,18 +1544,24 @@ void LLLineEditor::drawBackground()
 		image = mBgImage;
 	}
 	
+	F32 alpha = getDrawContext().mAlpha;
 	// optionally draw programmatic border
 	if (has_focus)
 	{
+		LLColor4 tmp_color = gFocusMgr.getFocusColor();
+		tmp_color.setAlpha(alpha);
 		image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(),
-						  gFocusMgr.getFocusColor(),
+						  tmp_color,
 						  gFocusMgr.getFocusFlashWidth());
 	}
-	image->draw(getLocalRect());
+	LLColor4 tmp_color = UI_VERTEX_COLOR;
+	tmp_color.setAlpha(alpha);
+	image->draw(getLocalRect(), tmp_color);
 }
 
 void LLLineEditor::draw()
 {
+	F32 alpha = getDrawContext().mAlpha;
 	S32 text_len = mText.length();
 	static LLUICachedControl<S32> lineeditor_cursor_thickness ("UILineEditorCursorThickness", 0);
 	static LLUICachedControl<S32> lineeditor_v_pad ("UILineEditorVPad", 0);
@@ -1608,8 +1614,10 @@ void LLLineEditor::draw()
 	{
 		text_color = mReadOnlyFgColor.get();
 	}
+	text_color.setAlpha(alpha);
 	LLColor4 label_color = mTentativeFgColor.get();
-
+	label_color.setAlpha(alpha);
+	
 	if (hasPreeditString())
 	{
 		// Draw preedit markers.  This needs to be before drawing letters.
@@ -1632,7 +1640,7 @@ void LLLineEditor::draw()
 						preedit_pixels_right - preedit_standout_gap - 1,
 						background.mBottom + preedit_standout_position - preedit_standout_thickness,
 						(text_color * preedit_standout_brightness 
-						 + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(1.0f));
+						 + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(alpha/*1.0f*/));
 				}
 				else
 				{
@@ -1641,7 +1649,7 @@ void LLLineEditor::draw()
 						preedit_pixels_right - preedit_marker_gap - 1,
 						background.mBottom + preedit_marker_position - preedit_marker_thickness,
 						(text_color * preedit_marker_brightness
-						 + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(1.0f));
+						 + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(alpha/*1.0f*/));
 				}
 			}
 		}
@@ -1684,15 +1692,17 @@ void LLLineEditor::draw()
 		if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )
 		{
 			LLColor4 color = mHighlightColor;
+			color.setAlpha(alpha);
 			// selected middle
 			S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text);
 			width = llmin(width, mMaxHPixels - llround(rendered_pixels_right));
 			gl_rect_2d(llround(rendered_pixels_right), cursor_top, llround(rendered_pixels_right)+width, cursor_bottom, color);
 
+			LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
 			rendered_text += mGLFont->render( 
 				mText, mScrollHPos + rendered_text,
 				rendered_pixels_right, text_bottom,
-				LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
+				tmp_color,
 				LLFontGL::LEFT, LLFontGL::BOTTOM,
 				0,
 				LLFontGL::NO_SHADOW,
@@ -1758,8 +1768,9 @@ void LLLineEditor::draw()
 					cursor_right, cursor_bottom, text_color);
 				if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
 				{
+					LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
 					mGLFont->render(mText, getCursor(), (F32)(cursor_left + lineeditor_cursor_thickness / 2), text_bottom, 
-						LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
+						tmp_color,
 						LLFontGL::LEFT, LLFontGL::BOTTOM,
 						0,
 						LLFontGL::NO_SHADOW,
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index 8dbcd6e22921e0729fd1b3bbb6842846edc9435d..a657ed039a0e1861f9f268e6837e72b954af3a60 100644
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -85,6 +85,8 @@ void LLMenuButton::toggleMenu()
 
 void LLMenuButton::hideMenu() 
 { 
+	if(!mMenu)
+		return;
 	mMenu->setVisible(FALSE); 
 }
 
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index cf013efca02cd1cffd61eb184967abc72422eb4a..91e7e46195d5da1a2e6398b75ab230192faae97a 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -2894,8 +2894,8 @@ void hide_top_view( LLView* view )
 }
 
 
-// x and y are the desired location for the popup, NOT necessarily the
-// mouse location
+// x and y are the desired location for the popup, in the spawning_view's
+// coordinate frame, NOT necessarily the mouse location
 // static
 void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
 {
@@ -3435,7 +3435,7 @@ void LLMenuHolderGL::setActivatedItem(LLMenuItemGL* item)
 LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : 
 	LLFloater(LLSD())
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	S32 floater_header_size = getHeaderHeight();
 
 	setName(menup->getName());
 	setTitle(menup->getLabel());
@@ -3479,7 +3479,6 @@ LLTearOffMenu::~LLTearOffMenu()
 
 void LLTearOffMenu::draw()
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
 	mMenu->setBackgroundVisible(isBackgroundOpaque());
 	mMenu->needsArrange();
 
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 48887ec3520169fc2b03a51ffec060a3cf915e54..09d9e407c7bea43e03860ae2a82fdfadc5697563 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -505,7 +505,7 @@ class LLMenuGL
 	void buildDrawLabels();
 	void createJumpKeys();
 
-	// Show popup at a specific location.
+	// Show popup at a specific location, in the spawn_view's coordinate frame
 	static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y);
 
 	// Whether to drop shadow menu bar 
diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp
index f77ec5f4c7658f2c334e4ad8056fcee2d874ee1b..387af05935738ea896ce03bd70738679999bc338 100644
--- a/indra/llui/llmodaldialog.cpp
+++ b/indra/llui/llmodaldialog.cpp
@@ -297,5 +297,16 @@ void LLModalDialog::onAppFocusGained()
 	}
 }
 
-
-
+void LLModalDialog::shutdownModals()
+{
+	// This method is only for use during app shutdown. ~LLModalDialog()
+	// checks sModalStack, and if the dialog instance is still there, it
+	// crumps with "Attempt to delete dialog while still in sModalStack!" But
+	// at app shutdown, all bets are off. If the user asks to shut down the
+	// app, we shouldn't have to care WHAT's open. Put differently, if a modal
+	// dialog is so crucial that we can't let the user terminate until s/he
+	// addresses it, we should reject a termination request. The current state
+	// of affairs is that we accept it, but then produce an llerrs popup that
+	// simply makes our software look unreliable.
+	sModalStack.clear();
+}
diff --git a/indra/llui/llmodaldialog.h b/indra/llui/llmodaldialog.h
index 9d716a1880455d88190412b24aedfe083eab62a7..863572fb5acc110e5b508f7c9394e2a8f7b0d62e 100644
--- a/indra/llui/llmodaldialog.h
+++ b/indra/llui/llmodaldialog.h
@@ -73,7 +73,8 @@ class LLModalDialog : public LLFloater
 	static void		onAppFocusGained();
 
 	static S32		activeCount() { return sModalStack.size(); }
-	
+	static void		shutdownModals();
+
 protected:
 	void			centerOnScreen();
 
diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp
index e8ce1a8d97977634b342fa82c6af03b94649b2a6..78738c826dd08a9e3bbd5bc87729716bde4d115a 100644
--- a/indra/llui/llmultifloater.cpp
+++ b/indra/llui/llmultifloater.cpp
@@ -54,7 +54,8 @@ LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params)
 
 void LLMultiFloater::buildTabContainer()
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+	S32 floater_header_size = default_params.header_height;
 	
 	LLTabContainer::Params p;
 	p.name(std::string("Preview Tabs"));
@@ -131,7 +132,8 @@ BOOL LLMultiFloater::closeAllFloaters()
 void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
 {
 	static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+	S32 floater_header_size = default_params.header_height;
 	S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
 	S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
 	S32 new_height = llmax(getRect().getHeight(), content_height + floater_header_size + tabcntr_header_height);
@@ -432,6 +434,7 @@ void LLMultiFloater::onTabSelected()
 void LLMultiFloater::setCanResize(BOOL can_resize)
 {
 	LLFloater::setCanResize(can_resize);
+	if (!mTabContainer) return;
 	if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
 	{
 		mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
@@ -455,13 +458,16 @@ BOOL LLMultiFloater::postBuild()
 	}
 
 	mTabContainer = getChild<LLTabContainer>("Preview Tabs");
+	
+	setCanResize(mResizable);
 	return TRUE;
 }
 
 void LLMultiFloater::updateResizeLimits()
 {
 	static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+	S32 floater_header_size = default_params.header_height;
 	S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
 	// initialize minimum size constraint to the original xml values.
 	S32 new_min_width = mOrigMinWidth;
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index a0e51151c942774f39d73fe1d9538e942c2f18ee..ef222bad608cad3379b25c5c964964acb4a4312a 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -40,6 +40,7 @@
 #include "lldir.h"
 #include "llsdserialize.h"
 #include "lltrans.h"
+#include "llnotificationslistener.h"
 
 #include <algorithm>
 #include <boost/regex.hpp>
@@ -945,6 +946,8 @@ LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFil
 									mIgnoreAllNotifications(false)
 {
 	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
+
+    mListener.reset(new LLNotificationsListener(*this));
 }
 
 
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index cd05db3c30ea8d9c3ce861165023b9f8e0c9a21e..0d7cb74f7044602874487569445acfff12503b82 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -102,6 +102,7 @@
 #include "llfunctorregistry.h"
 #include "llpointer.h"
 #include "llinitparam.h"
+#include "llnotificationslistener.h"
 
 class LLNotification;
 typedef boost::shared_ptr<LLNotification> LLNotificationPtr;
@@ -812,9 +813,19 @@ class LLNotificationChannel :
 	LLNotificationComparator mComparator;
 };
 
-
+// An interface class to provide a clean linker seam to the LLNotifications class.
+// Extend this interface as needed for your use of LLNotifications.
+class LLNotificationsInterface
+{
+public:
+	virtual LLNotificationPtr add(const std::string& name, 
+						const LLSD& substitutions, 
+						const LLSD& payload, 
+						LLNotificationFunctorRegistry::ResponseFunctor functor) = 0;
+};
 
 class LLNotifications : 
+	public LLNotificationsInterface,
 	public LLSingleton<LLNotifications>, 
 	public LLNotificationChannelBase
 {
@@ -838,7 +849,7 @@ class LLNotifications :
 						const LLSD& substitutions, 
 						const LLSD& payload, 
 						const std::string& functor_name);
-	LLNotificationPtr add(const std::string& name, 
+	/* virtual */ LLNotificationPtr add(const std::string& name, 
 						const LLSD& substitutions, 
 						const LLSD& payload, 
 						LLNotificationFunctorRegistry::ResponseFunctor functor);
@@ -917,6 +928,8 @@ class LLNotifications :
 	GlobalStringMap mGlobalStrings;
 
 	bool mIgnoreAllNotifications;
+
+    boost::scoped_ptr<LLNotificationsListener> mListener;
 };
 
 
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..75f4d6177dc3958e5b1fc0b9f54dc6133e8a7ccb
--- /dev/null
+++ b/indra/llui/llnotificationslistener.cpp
@@ -0,0 +1,55 @@
+/**
+ * @file   llnotificationslistener.cpp
+ * @author Brad Kittenbrink
+ * @date   2009-07-08
+ * @brief  Implementation for llnotificationslistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llnotificationslistener.h"
+
+#include "llnotifications.h"
+
+LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
+    LLDispatchListener("LLNotifications", "op"),
+    mNotifications(notifications)
+{
+    add("requestAdd", &LLNotificationsListener::requestAdd);
+}
+
+void LLNotificationsListener::requestAdd(const LLSD& event_data) const
+{
+	if(event_data.has("reply"))
+	{
+		mNotifications.add(event_data["name"], 
+						   event_data["substitutions"], 
+						   event_data["payload"],
+						   boost::bind(&LLNotificationsListener::NotificationResponder, 
+									   this, 
+									   event_data["reply"].asString(), 
+									   _1, _2
+									   )
+						   );
+	}
+	else
+	{
+		mNotifications.add(event_data["name"], 
+						   event_data["substitutions"], 
+						   event_data["payload"]);
+	}
+}
+
+void LLNotificationsListener::NotificationResponder(const std::string& reply_pump, 
+										const LLSD& notification, 
+										const LLSD& response) const
+{
+	LLSD reponse_event;
+	reponse_event["notification"] = notification;
+	reponse_event["response"] = response;
+	LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
+}
diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f71a7c7817dc6490592e9c570c4f386d8977788
--- /dev/null
+++ b/indra/llui/llnotificationslistener.h
@@ -0,0 +1,34 @@
+/**
+ * @file   llnotificationslistener.h
+ * @author Brad Kittenbrink
+ * @date   2009-07-08
+ * @brief  Wrap subset of LLNotifications API in event API for test scripts.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNOTIFICATIONSLISTENER_H
+#define LL_LLNOTIFICATIONSLISTENER_H
+
+#include "lleventdispatcher.h"
+
+class LLNotifications;
+class LLSD;
+
+class LLNotificationsListener : public LLDispatchListener
+{
+public:
+    LLNotificationsListener(LLNotifications & notifications);
+
+    void requestAdd(LLSD const & event_data) const;
+
+private:
+	void NotificationResponder(const std::string& replypump, 
+							   const LLSD& notification, 
+							   const LLSD& response) const;
+	LLNotifications & mNotifications;
+};
+
+#endif // LL_LLNOTIFICATIONSLISTENER_H
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 095200ddc3d502f02562521550065f97bc1fe4b9..07c0f3ce847eaff623422813a29b5e2488efae4c 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -71,10 +71,12 @@ const LLPanel::Params& LLPanel::getDefaultParams()
 LLPanel::Params::Params()
 :	has_border("border", false),
 	border(""),
-	bg_opaque_color("bg_opaque_color"),
-	bg_alpha_color("bg_alpha_color"),
 	background_visible("background_visible", false),
 	background_opaque("background_opaque", false),
+	bg_opaque_color("bg_opaque_color"),
+	bg_alpha_color("bg_alpha_color"),
+	bg_opaque_image("bg_opaque_image"),
+	bg_alpha_image("bg_alpha_image"),
 	min_width("min_width", 100),
 	min_height("min_height", 100),
 	strings("string"),
@@ -92,10 +94,12 @@ LLPanel::Params::Params()
 
 LLPanel::LLPanel(const LLPanel::Params& p)
 :	LLUICtrl(p),
-	mBgColorAlpha(p.bg_alpha_color()),
-	mBgColorOpaque(p.bg_opaque_color()),
 	mBgVisible(p.background_visible),
 	mBgOpaque(p.background_opaque),
+	mBgOpaqueColor(p.bg_opaque_color()),
+	mBgAlphaColor(p.bg_alpha_color()),
+	mBgOpaqueImage(p.bg_opaque_image()),
+	mBgAlphaImage(p.bg_alpha_image()),
 	mDefaultBtn(NULL),
 	mBorder(NULL),
 	mLabel(p.label),
@@ -103,9 +107,9 @@ LLPanel::LLPanel(const LLPanel::Params& p)
 	mCommitCallbackRegistrar(false),
 	mEnableCallbackRegistrar(false),
 	mXMLFilename(p.filename)
+	// *NOTE: Be sure to also change LLPanel::initFromParams().  We have too
+	// many classes derived from LLPanel to retrofit them all to pass in params.
 {
-	setIsChrome(FALSE);
-
 	if (p.has_border)
 	{
 		addBorder(p.border);
@@ -178,19 +182,31 @@ void LLPanel::draw()
 	// draw background
 	if( mBgVisible )
 	{
-		//RN: I don't see the point of this
-		S32 left = 0;//LLPANEL_BORDER_WIDTH;
-		S32 top = getRect().getHeight();// - LLPANEL_BORDER_WIDTH;
-		S32 right = getRect().getWidth();// - LLPANEL_BORDER_WIDTH;
-		S32 bottom = 0;//LLPANEL_BORDER_WIDTH;
-
+		LLRect local_rect = getLocalRect();
 		if (mBgOpaque )
 		{
-			gl_rect_2d( left, top, right, bottom, mBgColorOpaque.get() % alpha);
+			// opaque, in-front look
+			if (mBgOpaqueImage.notNull())
+			{
+				mBgOpaqueImage->draw( local_rect, UI_VERTEX_COLOR % alpha );
+			}
+			else
+			{
+				// fallback to flat colors when there are no images
+				gl_rect_2d( local_rect, mBgOpaqueColor.get() % alpha);
+			}
 		}
 		else
 		{
-			gl_rect_2d( left, top, right, bottom, mBgColorAlpha.get() % alpha);
+			// transparent, in-back look
+			if (mBgAlphaImage.notNull())
+			{
+				mBgAlphaImage->draw( local_rect, UI_VERTEX_COLOR % alpha );
+			}
+			else
+			{
+				gl_rect_2d( local_rect, mBgAlphaColor.get() % alpha );
+			}
 		}
 	}
 
@@ -443,7 +459,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p)
 	setBackgroundOpaque(p.background_opaque);
 	setBackgroundColor(p.bg_opaque_color().get());
 	setTransparentColor(p.bg_alpha_color().get());
-	
+	mBgOpaqueImage = p.bg_opaque_image();
+	mBgAlphaImage = p.bg_alpha_image();
 }
 
 static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index e8db68ffbb8c0d2d249e8063c9944ea6d044623e..c213809d685a4d556ad3f044a1a6e6f435e4b803 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -48,6 +48,7 @@ const BOOL BORDER_YES = TRUE;
 const BOOL BORDER_NO = FALSE;
 
 class LLButton;
+class LLUIImage;
 
 /*
  * General purpose concrete view base class.
@@ -72,12 +73,15 @@ class LLPanel : public LLUICtrl
 		Optional<bool>			has_border;
 		Optional<LLViewBorder::Params>	border;
 
-		Optional<LLUIColor>		bg_opaque_color,
-								bg_alpha_color;
-
 		Optional<bool>			background_visible,
 								background_opaque;
 
+		Optional<LLUIColor>		bg_opaque_color,
+								bg_alpha_color;
+		// opaque image is for "panel in foreground" look
+		Optional<LLUIImage*>	bg_opaque_image,
+								bg_alpha_image;
+
 		Optional<S32>			min_width,
 								min_height;
 
@@ -127,10 +131,12 @@ class LLPanel : public LLUICtrl
 	BOOL			hasBorder() const { return mBorder != NULL; }
 	void			setBorderVisible( BOOL b );
 
-	void			setBackgroundColor( const LLColor4& color ) { mBgColorOpaque = color; }
-	const LLColor4&	getBackgroundColor() const { return mBgColorOpaque; }
-	void			setTransparentColor(const LLColor4& color) { mBgColorAlpha = color; }
-	const LLColor4& getTransparentColor() const { return mBgColorAlpha; }
+	void			setBackgroundColor( const LLColor4& color ) { mBgOpaqueColor = color; }
+	const LLColor4&	getBackgroundColor() const { return mBgOpaqueColor; }
+	void			setTransparentColor(const LLColor4& color) { mBgAlphaColor = color; }
+	const LLColor4& getTransparentColor() const { return mBgAlphaColor; }
+	LLPointer<LLUIImage> getBackgroundImage() const { return mBgOpaqueImage; }
+	LLPointer<LLUIImage> getTransparentImage() const { return mBgAlphaImage; }
 	void			setBackgroundVisible( BOOL b )	{ mBgVisible = b; }
 	BOOL			isBackgroundVisible() const { return mBgVisible; }
 	void			setBackgroundOpaque(BOOL b)		{ mBgOpaque = b; }
@@ -248,10 +254,12 @@ class LLPanel : public LLUICtrl
 	std::string		mHelpTopic;         // the name of this panel's help topic to display in the Help Viewer
 	
 private:
-	LLUIColor		mBgColorAlpha;
-	LLUIColor		mBgColorOpaque;
-	BOOL			mBgVisible;
-	BOOL			mBgOpaque;
+	BOOL			mBgVisible;				// any background at all?
+	BOOL			mBgOpaque;				// use opaque color or image
+	LLUIColor		mBgOpaqueColor;
+	LLUIColor		mBgAlphaColor;
+	LLPointer<LLUIImage> mBgOpaqueImage;	// "panel in front" look
+	LLPointer<LLUIImage> mBgAlphaImage;		// "panel in back" look
 	LLViewBorder*	mBorder;
 	LLButton*		mDefaultBtn;
 	LLUIString		mLabel;
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index f9f0307d17c27020ec479f82f10b1a65b75e5baf..86bd2f05ce99cc5034169f07c5d0ad63ddf70d7f 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -106,7 +106,7 @@ void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled)
 			child->setEnabled(enabled);
 			if (index == mSelectedIndex && enabled == FALSE)
 			{
-				mSelectedIndex = -1;
+				setSelectedIndex(-1);
 			}
 			break;
 		}
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index d8606c6889b283b786d24bf04a863b995290960f..5e17372fe948edec09a23f15d44206fdfee0e3ad 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -432,7 +432,7 @@ void LLScrollContainer::draw()
 
 			LLLocalClipRect clip(LLRect(mInnerRect.mLeft, 
 					mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height,
-					visible_width,
+					mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0),
 					mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0)
 					));
 			drawChild(mScrolledView);
diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp
index 073e14386f63312a58323c5781d19e5560415533..ba53f84877478e48cf5dc783e9e56e42a3e79065 100644
--- a/indra/llui/llscrolllistcolumn.cpp
+++ b/indra/llui/llscrolllistcolumn.cpp
@@ -47,6 +47,21 @@ const S32 MIN_COLUMN_WIDTH = 20;
 //---------------------------------------------------------------------------
 // LLScrollColumnHeader
 //---------------------------------------------------------------------------
+LLScrollColumnHeader::Params::Params()
+:	column("column")
+{
+	name  = "column_header";
+	image_unselected.name("square_btn_32x128.tga");
+	image_selected.name("square_btn_selected_32x128.tga");
+	image_disabled.name("square_btn_32x128.tga");
+	image_disabled_selected.name("square_btn_selected_32x128.tga");
+	image_overlay.name("combobox_arrow.tga");
+	image_overlay_alignment("right");
+	font_halign = LLFontGL::LEFT;
+	tab_stop(false);
+	scale_image(true);
+}
+
 
 LLScrollColumnHeader::LLScrollColumnHeader(const LLScrollColumnHeader::Params& p) 
 :	LLButton(p), // use combobox params to steal images
diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h
index 23318fd7c4e6792b1cf4ceda85bd52e815ef05db..5aef6e8e94e3bfd65b77fc2e30064fe5d51f577c 100644
--- a/indra/llui/llscrolllistcolumn.h
+++ b/indra/llui/llscrolllistcolumn.h
@@ -50,20 +50,7 @@ class LLScrollColumnHeader : public LLButton
 	{
 		Mandatory<LLScrollListColumn*> column;
 
-		Params()
-		:	column("column")
-		{
-			name  = "column_header";
-			image_unselected.name("square_btn_32x128.tga");
-			image_selected.name("square_btn_selected_32x128.tga");
-			image_disabled.name("square_btn_32x128.tga");
-			image_disabled_selected.name("square_btn_selected_32x128.tga");
-			image_overlay.name("combobox_arrow.tga");
-			image_overlay_alignment("right");
-			font_halign = LLFontGL::LEFT;
-			tab_stop(false);
-			scale_image(true);
-		}
+		Params();
 	};
 	LLScrollColumnHeader(const Params&);
 	~LLScrollColumnHeader();
diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp
index 07b68953789ab4f1bb45db8d8ef48685e099ad34..f86776384ada0dae375bdc0b913b226a4e4f20af 100644
--- a/indra/llui/llslider.cpp
+++ b/indra/llui/llslider.cpp
@@ -43,6 +43,8 @@
 #include "lluictrlfactory.h"
 
 static LLDefaultChildRegistry::Register<LLSlider> r1("slider_bar");
+//FIXME: make this into an unregistered template so that code constructed sliders don't
+// have ambigious template lookup problem
 
 LLSlider::Params::Params()
 :	track_color("track_color"),
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index 3ecf62908284aa561e6bc804816f85626ec0f403..ed22c0a47f8ac07ea994edf0d85e6fb0102e18af 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -396,4 +396,3 @@ void LLSliderCtrl::reportInvalidData()
 	make_ui_sound("UISndBadKeystroke");
 }
 
-
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 732c01614bc35798b752d2dba2ca8b3d502e7b30..cde4c755184d899c97053e8c069235f0a17c25ad 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -44,6 +44,7 @@
 #include "lluictrlfactory.h"
 #include "llrender.h"
 #include "llfloater.h"
+#include "lltrans.h"
 
 //----------------------------------------------------------------------------
 
@@ -153,6 +154,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
 	mRightTabBtnOffset(p.tab_padding_right),
 	mTotalTabWidth(0),
 	mTabPosition(p.tab_position),
+	mFontHalign(p.font_halign),
+	mFont(p.font.isProvided() ? p.font() : (mIsVertical ? LLFontGL::getFontSansSerif() : LLFontGL::getFontSansSerifSmall())),
 	mFirstTabParams(p.first_tab),
 	mMiddleTabParams(p.middle_tab),
 	mLastTabParams(p.last_tab)
@@ -401,12 +404,6 @@ void LLTabContainer::draw()
 					}
 				}
 			}
-			LLUI::pushMatrix();
-			{
-				LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
-				tuple->mButton->draw();
-			}
-			LLUI::popMatrix();
 
 			idx++;
 		}
@@ -641,12 +638,6 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
 				}
 			}
 		}
-
-		for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
-		{
-			LLTabTuple* tuple = *iter;
-			tuple->mButton->setVisible( FALSE );
-		}
 	}
 	return handled;
 }
@@ -836,8 +827,6 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 		// already a child of mine
 		return;
 	}
-	const LLFontGL* font =
-		(mIsVertical ? LLFontGL::getFontSansSerif() : LLFontGL::getFontSansSerifSmall());
 
 	// Store the original label for possible xml export.
 	child->setLabel(label);
@@ -847,7 +836,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 	S32 button_width = mMinTabWidth;
 	if (!mIsVertical)
 	{
-		button_width = llclamp(font->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
+		button_width = llclamp(mFont->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
 	}
 	
 	// Tab panel
@@ -934,7 +923,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 		params.name(trimmed_label);
 		params.rect(btn_rect);
 		params.initial_value(trimmed_label);
-		params.font(font);
+		params.font(mFont);
 		textbox = LLUICtrlFactory::create<LLTextBox> (params);
 		
 		LLButton::Params p;
@@ -950,12 +939,12 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 			p.rect(btn_rect);
 			p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
 			p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
-			p.font(font);
+			p.font(mFont);
 			p.label(trimmed_label);
 			p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
 			p.image_selected(mMiddleTabParams.tab_left_image_selected);
 			p.scale_image(true);
-			p.font_halign = LLFontGL::LEFT;
+			p.font_halign = mFontHalign;
 			p.tab_stop(false);
 			if (indent)
 			{
@@ -965,18 +954,13 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 		}
 		else
 		{
-			std::string tooltip = trimmed_label;
-			tooltip += "\nAlt-Left arrow for previous tab";
-			tooltip += "\nAlt-Right arrow for next tab";
-
 			LLButton::Params p;
 			p.name(std::string(child->getName()) + " tab");
 			p.rect(btn_rect);
 			p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
-			p.font(font);
+			p.font(mFont);
 			p.label(trimmed_label);
 			p.visible(false);
-			p.tool_tip(tooltip);
 			p.scale_image(true);
 			p.image_unselected(tab_img);
 			p.image_selected(tab_selected_img);
@@ -984,7 +968,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 			// Try to squeeze in a bit more text
 			p.pad_left(4);
 			p.pad_right(2);
-			p.font_halign = LLFontGL::LEFT;
+			p.font_halign = mFontHalign;
 			p.follows.flags = FOLLOWS_LEFT;
 			p.follows.flags = FOLLOWS_LEFT;
 	
@@ -1505,7 +1489,6 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
 
 		if (!mIsVertical)
 		{
-			const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall();
 			// remove current width from total tab strip width
 			mTotalTabWidth -= tuple->mButton->getRect().getWidth();
 
@@ -1516,7 +1499,7 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
 			tuple->mPadding = image_overlay_width;
 
 			tuple->mButton->setRightHPad(6);
-			tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth), 
+			tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth), 
 									tuple->mButton->getRect().getHeight());
 			// add back in button width to total tab strip width
 			mTotalTabWidth += tuple->mButton->getRect().getWidth();
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index a81974cd4226b826cbf8094d5875793c67280860..be9c6c7d065849cc0803ec3d4951b97bea2f1b7f 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -262,6 +262,9 @@ class LLTabContainer : public LLPanel
 	S32								mTabHeight;
 
 	LLFrameTimer					mDragAndDropDelayTimer;
+	
+	LLFontGL::HAlign                mFontHalign;
+	const LLFontGL*					mFont;
 
 	TabParams						mFirstTabParams;
 	TabParams						mMiddleTabParams;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 22cce755b0d36a5d29da071c038b11ae299e1486..9a26f0b4726be0e54ebf089ac5ffd58b40bc9479 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -232,7 +232,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
 
 	createDefaultSegment();
 
-	updateTextRect();
+	updateRects();
 }
 
 LLTextBase::~LLTextBase()
@@ -419,9 +419,6 @@ void LLTextBase::drawCursor()
 			return;
 		}
 
-		if (!mTextRect.contains(cursor_rect))
-			return;
-
 		// Draw the cursor
 		// (Flash the cursor every half second starting a fixed time after the last keystroke)
 		F32 elapsed = mCursorBlinkTimer.getElapsedTimeF32();
@@ -538,10 +535,6 @@ void LLTextBase::drawText()
 			next_start = getLineStart(cur_line + 1);
 			line_end = next_start;
 		}
-		if ( text[line_end-1] == '\n' )
-		{
-			--line_end;
-		}
 
 		LLRect text_rect(line.mRect.mLeft + mTextRect.mLeft - scrolled_view_rect.mLeft,
 						line.mRect.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom,
@@ -940,13 +933,16 @@ BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask)
 
 void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
 {
-	LLUICtrl::reshape( width, height, called_from_parent );
+	if (width != getRect().getWidth() || height != getRect().getHeight())
+	{
+		LLUICtrl::reshape( width, height, called_from_parent );
 
-	// do this first after reshape, because other things depend on
-	// up-to-date mTextRect
-	updateTextRect();
-	
-	needsReflow();
+		// do this first after reshape, because other things depend on
+		// up-to-date mTextRect
+		updateRects();
+		
+		needsReflow();
+	}
 }
 
 void LLTextBase::draw()
@@ -957,17 +953,27 @@ void LLTextBase::draw()
 	// then update scroll position, as cursor may have moved
 	updateScrollFromCursor();
 
+	LLRect doc_rect;
+	if (mScroller)
+	{
+		mScroller->localRectToOtherView(mScroller->getContentWindowRect(), &doc_rect, this);
+	}
+	else
+	{
+		doc_rect = getLocalRect();
+	}
+
 	if (mBGVisible)
 	{
 		// clip background rect against extents, if we support scrolling
-		LLLocalClipRect clip(getLocalRect(), mScroller != NULL);
+		LLLocalClipRect clip(doc_rect, mScroller != NULL);
 
 		LLColor4 bg_color = mReadOnly 
 							? mReadOnlyBgColor.get()
 							: hasFocus() 
 								? mFocusBgColor.get() 
 								: mWriteableBgColor.get();
-		gl_rect_2d(mDocumentView->getRect(), bg_color, TRUE);
+		gl_rect_2d(mTextRect, bg_color, TRUE);
 	}
 
 	// draw document view
@@ -975,7 +981,7 @@ void LLTextBase::draw()
 
 	{
 		// only clip if we support scrolling (mScroller != NULL)
-		LLLocalClipRect clip(mTextRect, mScroller != NULL);
+		LLLocalClipRect clip(doc_rect, mScroller != NULL);
 		drawSelectionBackground();
 		drawText();
 		drawCursor();
@@ -1028,13 +1034,13 @@ S32 LLTextBase::getLeftOffset(S32 width)
 	switch (mHAlign)
 	{
 	case LLFontGL::LEFT:
-		return 0;
+		return mHPad;
 	case LLFontGL::HCENTER:
-		return (mTextRect.getWidth() - width) / 2;
+		return mHPad + (mTextRect.getWidth() - width - mHPad) / 2;
 	case LLFontGL::RIGHT:
 		return mTextRect.getWidth() - width;
 	default:
-		return 0;
+		return mHPad;
 	}
 }
 
@@ -1042,8 +1048,6 @@ S32 LLTextBase::getLeftOffset(S32 width)
 static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow");
 void LLTextBase::reflow(S32 start_index)
 {
-	if (!mReflowNeeded) return;
-
 	LLFastTimer ft(FTM_TEXT_REFLOW);
 
 	updateSegments();
@@ -1072,7 +1076,7 @@ void LLTextBase::reflow(S32 start_index)
 		segment_set_t::iterator seg_iter = mSegments.begin();
 		S32 seg_offset = 0;
 		S32 line_start_index = 0;
-		const S32 text_width = mTextRect.getWidth();  // optionally reserve room for margin
+		const S32 text_width = mTextRect.getWidth() - mHPad;  // reserve room for margin
 		S32 remaining_pixels = text_width;
 		LLWString text(getWText());
 		S32 line_count = 0;
@@ -1154,60 +1158,8 @@ void LLTextBase::reflow(S32 start_index)
 			}
 		}
 
-		if (mLineInfoList.empty()) 
-		{
-			mContentsRect = LLRect(0, mVPad, mHPad, 0);
-		}
-		else
-		{
-
-			mContentsRect = mLineInfoList.begin()->mRect;
-			for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin();
-				line_iter != mLineInfoList.end();
-				++line_iter)
-			{
-				mContentsRect.unionWith(line_iter->mRect);
-			}
-
-			mContentsRect.mRight += mHPad;
-			mContentsRect.mTop += mVPad;
-			// get around rounding errors when clipping text against rectangle
-			mContentsRect.stretch(1);
-		}
-
-		// change mDocumentView size to accomodate reflowed text
-		LLRect document_rect;
-		if (mScroller)
-		{
-			// document is size of scroller or size of text contents, whichever is larger
-			document_rect.setOriginAndSize(0, 0, 
-										mScroller->getContentWindowRect().getWidth(), 
-										llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight()));
-		}
-		else
-		{
-			// document size is just extents of reflowed text, reset to origin 0,0
-			document_rect.set(0, 
-							getLocalRect().getHeight(), 
-							getLocalRect().getWidth(), 
-							llmin(0, getLocalRect().getHeight() - mContentsRect.getHeight()));
-		}
-		mDocumentView->setShape(document_rect);
-
-		// after making document big enough to hold all the text, move the text to fit in the document
-		if (!mLineInfoList.empty())
-		{
-			S32 delta_pos = mDocumentView->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad;
-			// move line segments to fit new document rect
-			for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
-			{
-				it->mRect.translate(0, delta_pos);
-			}
-			mContentsRect.translate(0, delta_pos);
-		}
-
 		// calculate visible region for diplaying text
-		updateTextRect();
+		updateRects();
 
 		for (segment_set_t::iterator segment_it = mSegments.begin();
 			segment_it != mSegments.end();
@@ -1244,11 +1196,10 @@ void LLTextBase::reflow(S32 start_index)
 				//llassert_always(getLocalRectFromDocIndex(mScrollIndex).mBottom == first_char_rect.mBottom);
 			}
 		}
-	}
-
 
-	// reset desired x cursor position
-	updateCursorXPos();
+		// reset desired x cursor position
+		updateCursorXPos();
+	}
 }
 
 LLRect LLTextBase::getContentsRect()
@@ -2075,8 +2026,44 @@ S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction)
 	}
 }
 
-void LLTextBase::updateTextRect()
+void LLTextBase::updateRects()
 {
+	if (mLineInfoList.empty()) 
+	{
+		mContentsRect = LLRect(0, mVPad, mHPad, 0);
+	}
+	else
+	{
+		mContentsRect = mLineInfoList.begin()->mRect;
+		for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin();
+			line_iter != mLineInfoList.end();
+			++line_iter)
+		{
+			mContentsRect.unionWith(line_iter->mRect);
+		}
+
+		mContentsRect.mLeft = 0;
+		mContentsRect.mTop += mVPad;
+
+		S32 delta_pos = -mContentsRect.mBottom;
+		// move line segments to fit new document rect
+		for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
+		{
+			it->mRect.translate(0, delta_pos);
+		}
+		mContentsRect.translate(0, delta_pos);
+	}
+
+	// update document container dimensions according to text contents
+	LLRect doc_rect = mContentsRect;
+	// use old mTextRect constraint document to width of viewable region
+	doc_rect.mRight = doc_rect.mLeft + mTextRect.getWidth();
+
+	mDocumentView->setShape(doc_rect);
+
+	//update mTextRect *after* mDocumentView has been resized
+	// so that scrollbars are added if document needs to scroll
+	// since mTextRect does not include scrollbars
 	LLRect old_text_rect = mTextRect;
 	mTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
 	//FIXME: replace border with image?
@@ -2084,12 +2071,14 @@ void LLTextBase::updateTextRect()
 	{
 		mTextRect.stretch(-1);
 	}
-	mTextRect.mLeft += mHPad;
-	mTextRect.mTop -= mVPad;
 	if (mTextRect != old_text_rect)
 	{
 		needsReflow();
 	}
+
+	// update document container again, using new mTextRect
+	doc_rect.mRight = doc_rect.mLeft + mTextRect.getWidth();
+	mDocumentView->setShape(doc_rect);
 }
 
 
@@ -2121,9 +2110,12 @@ LLRect LLTextBase::getVisibleDocumentRect() const
 	}
 	else
 	{
-		// entire document rect when not scrolling
+		// entire document rect is visible when not scrolling
+		// but offset according to height of widget
 		LLRect doc_rect = mDocumentView->getLocalRect();
-		doc_rect.translate(-mDocumentView->getRect().mLeft, -mDocumentView->getRect().mBottom);
+		doc_rect.mLeft -= mDocumentView->getRect().mLeft;
+		// adjust for height of text above widget baseline
+		doc_rect.mBottom = llmin(0, doc_rect.getHeight() - mTextRect.getHeight());
 		return doc_rect;
 	}
 }
@@ -2218,6 +2210,11 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
 
 	const LLWString &text = mEditor.getWText();
 
+	if ( text[seg_end-1] == '\n' )
+	{
+		--seg_end;
+	}
+
 	F32 right_x = rect.mLeft;
 	if (!mStyle->isVisible())
 	{
@@ -2362,16 +2359,7 @@ void LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
 {
 	LLWString text = mEditor.getWText();
 
-	// look for any printable character, then return the font height
-	height = 0;
-	for (S32 index = mStart + first_char; index < mStart + first_char + num_chars; ++index)
-	{
-		if (text[index] != '\n')
-		{
-			height = mFontHeight;
-			break;
-		}
-	}
+	height = mFontHeight;
 	width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
 }
 
@@ -2393,7 +2381,10 @@ S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
 	S32 last_char = mStart + segment_offset;
 	for (; last_char != mEnd; ++last_char)
 	{
-		if (text[last_char] == '\n') break;
+		if (text[last_char] == '\n') 
+		{
+			break;
+		}
 	}
 
 	// set max characters to length of segment, or to first newline
@@ -2411,12 +2402,13 @@ S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
 		// If at the beginning of a line, and a single character won't fit, draw it anyway
 		num_chars = 1;
 	}
-	if (mStart + segment_offset + num_chars == mEditor.getLength())
-	{
-		// include terminating NULL
-		num_chars++;
-	}
-	else if (text[mStart + segment_offset + num_chars] == '\n')
+
+	// include *either* the EOF or newline character in this run of text
+	// but not both
+	S32 last_char_in_run = mStart + segment_offset + num_chars;
+	// check length first to avoid indexing off end of string
+	if (last_char_in_run >= mEditor.getLength() 
+		|| text[last_char_in_run] == '\n')
 	{
 		num_chars++;
 	}
@@ -2439,12 +2431,14 @@ void LLNormalTextSegment::dump() const
 // LLInlineViewSegment
 //
 
-LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end, bool force_new_line, S32 hpad, S32 vpad)
+LLInlineViewSegment::LLInlineViewSegment(const Params& p, S32 start, S32 end)
 :	LLTextSegment(start, end),
-	mView(view),
-	mForceNewLine(force_new_line),
-	mHPad(hpad), // one sided padding (applied to left and right)
-	mVPad(vpad)
+	mView(p.view),
+	mForceNewLine(p.force_newline),
+	mLeftPad(p.left_pad),
+	mRightPad(p.right_pad),
+	mTopPad(p.top_pad),
+	mBottomPad(p.bottom_pad)
 {
 } 
 
@@ -2464,8 +2458,8 @@ void	LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
 	}
 	else
 	{
-		width = mHPad * 2 + mView->getRect().getWidth();
-		height = mVPad * 2 + mView->getRect().getHeight();
+		width = mLeftPad + mRightPad + mView->getRect().getWidth();
+		height = mBottomPad + mTopPad + mView->getRect().getHeight();
 	}
 }
 
@@ -2488,14 +2482,14 @@ S32	LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
 void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
 {
 	LLRect start_rect = editor.getDocRectFromDocIndex(mStart);
-	mView->setOrigin(start_rect.mLeft + mHPad, start_rect.mBottom + mVPad);
+	mView->setOrigin(start_rect.mLeft + mLeftPad, start_rect.mBottom + mBottomPad);
 }
 
 F32	LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
 {
 	// return padded width of widget
 	// widget is actually drawn during mDocumentView's draw()
-	return (F32)(draw_rect.mLeft + mView->getRect().getWidth() + mHPad * 2);
+	return (F32)(draw_rect.mLeft + mView->getRect().getWidth() + mLeftPad + mRightPad);
 }
 
 void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor)
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index f0b88784915fe97a57d4df61ecabbd7927e2242a..4cca522a23501ec3893e4144e0d49c3f911b0c3f 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -154,6 +154,9 @@ class LLTextBase
 	LLRect					getContentsRect();
 	LLRect					getVisibleDocumentRect() const;
 
+	S32						getVPad() { return mVPad; }
+	S32						getHPad() { return mHPad; }
+
 
 	S32						getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
 	LLRect					getLocalRectFromDocIndex(S32 pos) const;
@@ -294,7 +297,7 @@ class LLTextBase
 	void 							endSelection();
 
 	// misc
-	void							updateTextRect();
+	void							updateRects();
 	void							needsReflow() { mReflowNeeded = TRUE; }
 	void							needsScroll() { mScrollNeeded = TRUE; }
 	void							replaceUrlLabel(const std::string &url, const std::string &label);
@@ -459,7 +462,17 @@ class LLIndexSegment : public LLTextSegment
 class LLInlineViewSegment : public LLTextSegment
 {
 public:
-	LLInlineViewSegment(LLView* widget, S32 start, S32 end, bool force_new_line, S32 hpad = 0, S32 vpad = 0);
+	struct Params : public LLInitParam::Block<Params>
+	{
+		Mandatory<LLView*>		view;
+		Optional<bool>			force_newline;
+		Optional<S32>			left_pad,
+								right_pad,
+								bottom_pad,
+								top_pad;
+	};
+
+	LLInlineViewSegment(const Params& p, S32 start, S32 end);
 	~LLInlineViewSegment();
 	/*virtual*/ void		getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
 	/*virtual*/ S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
@@ -470,8 +483,10 @@ class LLInlineViewSegment : public LLTextSegment
 	/*virtual*/ void		linkToDocument(class LLTextBase* editor);
 
 private:
-	S32 mHPad;
-	S32 mVPad;
+	S32 mLeftPad;
+	S32 mRightPad;
+	S32 mTopPad;
+	S32 mBottomPad;
 	LLView* mView;
 	bool	mForceNewLine;
 };
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index d507cf7ce441b23714e53445a725eb9efc891004..3ce5a0320be63dd849375a12369349bf4edf9ee9 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -63,6 +63,7 @@
 #include "llpanel.h"
 #include "llurlregistry.h"
 #include "lltooltip.h"
+#include "llmenugl.h"
 
 #include <queue>
 #include "llcombobox.h"
@@ -252,7 +253,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
 	mHandleEditKeysDirectly( p.handle_edit_keys_directly ),
 	mMouseDownX(0),
 	mMouseDownY(0),
-	mTabsToNextField(p.ignore_tab)
+	mTabsToNextField(p.ignore_tab),
+	mContextMenu(NULL)
 {
 	mDefaultFont = p.font;
 
@@ -273,7 +275,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
 	if (mShowLineNumbers)
 	{
 		mHPad += UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
-		updateTextRect();
+		updateRects();
 	}
 }
 
@@ -301,6 +303,8 @@ LLTextEditor::~LLTextEditor()
 
 	// Scrollbar is deleted by LLView
 	std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
+
+	delete mContextMenu;
 }
 
 ////////////////////////////////////////////////////////////
@@ -648,6 +652,13 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	BOOL	handled = FALSE;
 
+	// set focus first, in case click callbacks want to change it
+	// RN: do we really need to have a tab stop?
+	if (hasTabStop())
+	{
+		setFocus( TRUE );
+	}
+
 	// Let scrollbar have first dibs
 	handled = LLTextBase::handleMouseDown(x, y, mask);
 
@@ -690,30 +701,40 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
 		handled = TRUE;
 	}
 
-	if (hasTabStop())
-	{
-		setFocus( TRUE );
-		handled = TRUE;
-	}
-
 	// Delay cursor flashing
 	resetCursorBlink();
 
 	return handled;
 }
 
+BOOL LLTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+	if (hasTabStop())
+	{
+		setFocus(TRUE);
+	}
+	if (!LLTextBase::handleRightMouseDown(x, y, mask))
+	{
+		showContextMenu(x, y);
+	}
+	return TRUE;
+}
+
+
 
 BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
 {
-	BOOL	handled = FALSE;
-	handled = LLTextBase::handleMouseDown(x, y, mask);
+	if (hasTabStop())
+	{
+		setFocus(TRUE);
+	}
 
-	if (!handled)
+	if (!LLTextBase::handleMouseDown(x, y, mask))
 	{
-		setFocus( TRUE );
 		if( canPastePrimary() )
 		{
 			setCursorAtLocalPos( x, y, true );
+			// does not rely on focus being set
 			pastePrimary();
 		}
 	}
@@ -736,7 +757,6 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
 			setCursorAtLocalPos( clamped_x, clamped_y, true );
 			mSelectionEnd = mCursorPos;
 		}
-
 		lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;		
 		getWindow()->setCursor(UI_CURSOR_IBEAM);
 		handled = TRUE;
@@ -1991,6 +2011,21 @@ void LLTextEditor::setEnabled(BOOL enabled)
 	}
 }
 
+void LLTextEditor::showContextMenu(S32 x, S32 y)
+{
+	if (!mContextMenu)
+	{
+		mContextMenu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_text_editor.xml", 
+																				LLMenuGL::sMenuContainer, 
+																				LLMenuHolderGL::child_registry_t::instance());
+	}
+
+	S32 screen_x, screen_y;
+	localPointToScreen(x, y, &screen_x, &screen_y);
+	mContextMenu->show(screen_x, screen_y);
+}
+
+
 void LLTextEditor::drawPreeditMarker()
 {
 	static LLUICachedControl<F32> preedit_marker_brightness ("UIPreeditMarkerBrightness", 0);
@@ -2276,7 +2311,7 @@ void LLTextEditor::insertText(const std::string &new_text)
 	setEnabled( enabled );
 }
 
-void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_new_line, S32 hpad, S32 vpad)
+void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo)
 {
 	// Save old state
 	S32 selection_start = mSelectionStart;
@@ -2290,12 +2325,9 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
 
 	setCursorPos(old_length);
 
-	LLWString widget_wide_text;
-
-	// Add carriage return if not first line
-	widget_wide_text = utf8str_to_wstring(widget_text);
+	LLWString widget_wide_text = utf8str_to_wstring(text);
 
-	LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size(), force_new_line, hpad, vpad);
+	LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
 	insert(getLength(), widget_wide_text, FALSE, segment);
 
 	needsReflow();
@@ -2318,7 +2350,7 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
 		setCursorPos(cursor_pos);
 	}
 
-	if( !allow_undo )
+	if (!allow_undo)
 	{
 		blockUndo();
 	}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 481a4d1a78d1fe3bc7c4028958a72216528fbe37..10fc94dedc1e4810785ec474947932efd72df17a 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -99,6 +99,7 @@ class LLTextEditor :
 	// mousehandler overrides
 	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
+	virtual BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask );
 	virtual BOOL	handleMiddleMouseDown(S32 x,S32 y,MASK mask);
@@ -165,7 +166,7 @@ class LLTextEditor :
 	// inserts text at cursor
 	void			insertText(const std::string &text);
 
-	void			appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_newline, S32 hpad, S32 vpad);
+	void			appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
 	// Non-undoable
 	void			setText(const LLStringExplicit &utf8str);
 
@@ -201,6 +202,7 @@ class LLTextEditor :
 	void getSelectedSegments(segment_vec_t& segments) const;
 
 protected:
+	void			showContextMenu(S32 x, S32 y);
 	void			drawPreeditMarker();
 
 	void 			assignEmbedded(const std::string &s);
@@ -328,6 +330,8 @@ class LLTextEditor :
 	LLCoordGL		mLastIMEPosition;		// Last position of the IME editor
 
 	keystroke_signal_t mKeystrokeSignal;
+
+	LLContextMenu* mContextMenu;
 }; // end class LLTextEditor
 
 
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index c8094f9c7c6a5a6fbe7986f56ac1990be6273ebe..23c87c7522cca89063c1fb3187d6dcb3065506fa 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -38,10 +38,11 @@
 // Library includes
 #include "lltextbox.h"
 #include "lliconctrl.h"
+#include "llbutton.h"
 #include "llmenugl.h"       // hideMenus()
 #include "llui.h"			// positionViewNearMouse()
 #include "llwindow.h"
-
+#include "lltrans.h"
 //
 // Constants
 //
@@ -155,19 +156,23 @@ LLToolTip::Params::Params()
 	visible_time_near("visible_time_near", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeNear" )),
 	visible_time_far("visible_time_far", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeFar" )),
 	sticky_rect("sticky_rect"),
-	image("image")
+	image("image"),
+	time_based_media("time_based_media", false),
+	web_based_media("web_based_media", false),
+	media_playing("media_playing", false)
 {
-	name = "tooltip";
-	font = LLFontGL::getFontSansSerif();
-	bg_opaque_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" );
-	background_visible = true;
+	chrome = true;
 }
 
 LLToolTip::LLToolTip(const LLToolTip::Params& p)
 :	LLPanel(p),
 	mMaxWidth(p.max_width),
 	mHasClickCallback(p.click_callback.isProvided()),
-	mPadding(p.padding)
+	mPadding(p.padding),
+	mTextBox(NULL),
+	mInfoButton(NULL),
+	mPlayMediaButton(NULL),
+	mHomePageButton(NULL)
 {
 	LLTextBox::Params params;
 	params.initial_value = "tip_text";
@@ -186,25 +191,80 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
 	params.allow_html = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips
 	mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
 	addChild(mTextBox);
-
+	
+	S32 TOOLTIP_ICON_SIZE = 0;
+	S32 TOOLTIP_PLAYBUTTON_SIZE = 0;
 	if (p.image.isProvided())
 	{
-		LLIconCtrl::Params icon_params;
-		icon_params.name = "tooltip_icon";
+		LLButton::Params icon_params;
+		icon_params.name = "tooltip_info";
 		LLRect icon_rect;
 		LLUIImage* imagep = p.image;
-		const S32 TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16);
+		TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16);
 		icon_rect.setOriginAndSize(mPadding, mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
 		icon_params.rect = icon_rect;
-		icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM;
-		icon_params.image = p.image;
-		icon_params.mouse_opaque = false;
-		addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_params));
-
+		//icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM;
+		icon_params.image_unselected(imagep);
+		icon_params.image_selected(imagep);
+		icon_params.scale_image(true);
+		icon_params.flash_color(icon_params.highlight_color());
+		mInfoButton  = LLUICtrlFactory::create<LLButton>(icon_params);
+		if (p.click_callback.isProvided())
+		{
+			mInfoButton->setCommitCallback(boost::bind(p.click_callback()));
+		}
+		addChild(mInfoButton);
+		
 		// move text over to fit image in
 		mTextBox->translate(TOOLTIP_ICON_SIZE + mPadding, 0);
 	}
-
+	
+	if (p.time_based_media)
+	{
+		LLButton::Params p_button;
+		p_button.name(std::string("play_media"));
+		TOOLTIP_PLAYBUTTON_SIZE = 16;
+		LLRect button_rect;
+		button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
+		p_button.rect = button_rect;
+		p_button.image_selected.name("button_anim_pause.tga");
+		p_button.image_unselected.name("button_anim_play.tga");
+		p_button.scale_image(true);
+		
+		mPlayMediaButton = LLUICtrlFactory::create<LLButton>(p_button); 
+		if(p.click_playmedia_callback.isProvided())
+		{
+			mPlayMediaButton->setCommitCallback(boost::bind(p.click_playmedia_callback()));
+		}
+		mPlayMediaButton->setToggleState(p.media_playing);
+		addChild(mPlayMediaButton);
+		
+		// move text over to fit image in
+		mTextBox->translate(TOOLTIP_PLAYBUTTON_SIZE + mPadding, 0);
+	}
+	
+	if (p.web_based_media)
+	{
+		LLButton::Params p_w_button;
+		p_w_button.name(std::string("home_page"));
+		TOOLTIP_PLAYBUTTON_SIZE = 16;
+		LLRect button_rect;
+		button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
+		p_w_button.rect = button_rect;
+		p_w_button.image_unselected.name("map_home.tga");
+		p_w_button.scale_image(true);
+		
+		mHomePageButton = LLUICtrlFactory::create<LLButton>(p_w_button); 
+		if(p.click_homepage_callback.isProvided())
+		{
+			mHomePageButton->setCommitCallback(boost::bind(p.click_homepage_callback()));
+		}
+		addChild(mHomePageButton);
+		
+		// move text over to fit image in
+		mTextBox->translate(TOOLTIP_PLAYBUTTON_SIZE + mPadding, 0);
+	}
+	
 	if (p.click_callback.isProvided())
 	{
 		setMouseUpCallback(boost::bind(p.click_callback()));
@@ -255,6 +315,10 @@ void LLToolTip::setVisible(BOOL visible)
 
 BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask)
 {
+	//mInfoButton->setFlashing(true);
+	if(mInfoButton)
+		mInfoButton->setHighlight(true);
+	
 	LLPanel::handleHover(x, y, mask);
 	if (mHasClickCallback)
 	{
@@ -263,6 +327,14 @@ BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask)
 	return TRUE;
 }
 
+void LLToolTip::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+	//mInfoButton->setFlashing(true);
+	if(mInfoButton)
+		mInfoButton->setHighlight(false);
+	LLUICtrl::onMouseLeave(x, y, mask);
+}
+
 void LLToolTip::draw()
 {
 	F32 alpha = 1.f;
@@ -378,7 +450,10 @@ void LLToolTipMgr::show(const std::string& msg)
 
 void LLToolTipMgr::show(const LLToolTip::Params& params)
 {
-	if (!params.validateBlock()) 
+	// fill in default tooltip params from tool_tip.xml
+	LLToolTip::Params params_with_defaults(params);
+	params_with_defaults.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLToolTip>());
+	if (!params_with_defaults.validateBlock()) 
 	{
 		llwarns << "Could not display tooltip!" << llendl;
 		return;
@@ -390,10 +465,12 @@ void LLToolTipMgr::show(const LLToolTip::Params& params)
 
 	// are we ready to show the tooltip?
 	if (!mToolTipsBlocked									// we haven't hit a key, moved the mouse, etc.
-		&& LLUI::getMouseIdleTime() > params.delay_time)	// the mouse has been still long enough
+		&& LLUI::getMouseIdleTime() > params_with_defaults.delay_time)	// the mouse has been still long enough
 	{
-		bool tooltip_changed = mLastToolTipParams.message() != params.message()
-								|| mLastToolTipParams.pos() != params.pos();
+		bool tooltip_changed = mLastToolTipParams.message() != params_with_defaults.message()
+								|| mLastToolTipParams.pos() != params_with_defaults.pos()
+								|| mLastToolTipParams.time_based_media() != params_with_defaults.time_based_media()
+								|| mLastToolTipParams.web_based_media() != params_with_defaults.web_based_media();
 
 		bool tooltip_shown = mToolTip 
 							 && mToolTip->getVisible() 
@@ -401,7 +478,7 @@ void LLToolTipMgr::show(const LLToolTip::Params& params)
 
 		mNeedsToolTip = tooltip_changed || !tooltip_shown;
 		// store description of tooltip for later creation
-		mNextToolTipParams = params;
+		mNextToolTipParams = params_with_defaults;
 	}
 }
 
diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h
index 63e7249a12b1d5c6da6d0270cde9b7f60d9314d9..30d251266c0ff8e9b306803159cfc41d51391bf6 100644
--- a/indra/llui/lltooltip.h
+++ b/indra/llui/lltooltip.h
@@ -78,9 +78,13 @@ class LLToolTip : public LLPanel
 									visible_time_far;	// time for which tooltip is visible while mouse moved away
 		Optional<LLRect>			sticky_rect;
 		Optional<const LLFontGL*>	font;
-
-		Optional<click_callback_t>	click_callback;
 		Optional<LLUIImage*>		image;
+		Optional<bool>				time_based_media,
+									web_based_media,
+									media_playing;
+		Optional<click_callback_t>	click_callback,
+									click_playmedia_callback,
+									click_homepage_callback;
 		Optional<S32>				max_width;
 		Optional<S32>				padding;
 		Optional<bool>				wrap;
@@ -89,7 +93,7 @@ class LLToolTip : public LLPanel
 	};
 	/*virtual*/ void draw();
 	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
-
+	/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
 	/*virtual*/ void setValue(const LLSD& value);
 	/*virtual*/ void setVisible(BOOL visible);
 
@@ -101,6 +105,10 @@ class LLToolTip : public LLPanel
 
 private:
 	class LLTextBox*	mTextBox;
+	class LLButton*     mInfoButton;
+	class LLButton*     mPlayMediaButton;
+	class LLButton*     mHomePageButton;
+
 	LLFrameTimer	mFadeTimer;
 	LLFrameTimer	mVisibleTimer;
 	S32				mMaxWidth;
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index f253857851549eb61309540d0c103e019d511199..a82e6eb372a9f12f3e8f2a87a70803893bd55ee1 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -1807,11 +1807,11 @@ void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen)
 }
 
 //static
-LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id)
+LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id, S32 priority)
 {
 	if (sImageProvider)
 	{
-		return sImageProvider->getUIImageByID(image_id);
+		return sImageProvider->getUIImageByID(image_id, priority);
 	}
 	else
 	{
@@ -1820,10 +1820,10 @@ LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id)
 }
 
 //static 
-LLPointer<LLUIImage> LLUI::getUIImage(const std::string& name)
+LLPointer<LLUIImage> LLUI::getUIImage(const std::string& name, S32 priority)
 {
 	if (!name.empty() && sImageProvider)
-		return sImageProvider->getUIImage(name);
+		return sImageProvider->getUIImage(name, priority);
 	else
 		return NULL;
 }
@@ -1952,7 +1952,7 @@ namespace LLInitParam
 				return fontp;
 			}
 		}
-
+		
 		// default to current value
 		return mData.mValue;
 	}
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 6ab78ab3cd906535967fc7b107533045d0646e6f..5ec07f1941b726439649298358a1152a7f8a3d3f 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -195,8 +195,8 @@ class LLUI
 	static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y);
 	static void setScaleFactor(const LLVector2& scale_factor);
 	static void setLineWidth(F32 width);
-	static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id);
-	static LLPointer<LLUIImage> getUIImage(const std::string& name);
+	static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
+	static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
 	static LLVector2 getWindowSize();
 	static void screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y);
 	static void glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y);
@@ -241,8 +241,8 @@ class LLImageProviderInterface
 	LLImageProviderInterface() {};
 	virtual ~LLImageProviderInterface() {};
 public:
-	virtual LLPointer<LLUIImage> getUIImage(const std::string& name) = 0;
-	virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id) = 0;
+	virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
+	virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
 	virtual void cleanUp() = 0;
 };
 
@@ -404,6 +404,20 @@ namespace LLInitParam
 		LLUIColor getValueFromBlock() const;
 	};
 
+	// provide a better default for Optional<const LLFontGL*> than NULL
+	template <>
+	struct DefaultInitializer<const LLFontGL*>
+	{
+		// return reference to a single default instance of T
+		// built-in types will be initialized to zero, default constructor otherwise
+		static const LLFontGL* get() 
+		{ 
+			static const LLFontGL* sDefaultFont = LLFontGL::getFontDefault();  
+			return sDefaultFont;
+		} 
+	};
+
+
 	template<>
 	class TypedParam<const LLFontGL*> 
 	:	public BlockValue<const LLFontGL*>
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 0faff5eff682ec4a76b46071d9213330093f584f..08fc8fb7849203697e2e183446b80ba4709356bb 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -42,6 +42,7 @@ static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl");
 
 LLUICtrl::Params::Params()
 :	tab_stop("tab_stop", true),
+	chrome("chrome", false),
 	label("label"),
 	initial_value("value"),
 	init_callback("init_callback"),
@@ -86,6 +87,7 @@ void LLUICtrl::initFromParams(const Params& p)
 {
 	LLView::initFromParams(p);
 
+	setIsChrome(p.chrome);
 	setControlName(p.control_name);
 	if(p.enabled_controls.isProvided())
 	{
@@ -582,7 +584,6 @@ void LLUICtrl::setIsChrome(BOOL is_chrome)
 // virtual
 BOOL LLUICtrl::getIsChrome() const
 { 
-
 	LLView* parent_ctrl = getParent();
 	while(parent_ctrl)
 	{
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 45fe47772b52da6577559501a2be98684d0122e0..dd22851100b0f3cf081ed5c32dee8266b1da76e9 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -126,7 +126,8 @@ class LLUICtrl
 	struct Params : public LLInitParam::Block<Params, LLView::Params>
 	{
 		Optional<std::string>			label;
-		Optional<bool>					tab_stop;
+		Optional<bool>					tab_stop,
+										chrome;
 		Optional<LLSD>					initial_value;
 
 		Optional<CommitCallbackParam>	init_callback,
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 31f12fe312cab8c2755a7fd314b02d071b5e000b..fe7fd59de80e3a4c32288bfc022bf5ae84d22484 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -437,6 +437,18 @@ void LLView::setEnabled(BOOL enabled)
 	mEnabled = enabled;
 }
 
+//virtual
+bool LLView::isAvailable() const
+{
+    return isInEnabledChain() && isInVisibleChain();
+}
+
+//static
+bool LLView::isAvailable(const LLView* view)
+{
+    return view && view->isAvailable();
+}
+
 //virtual
 BOOL LLView::setLabelArg( const std::string& key, const LLStringExplicit& text )
 {
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 73146b2c1f5d0b242aedc88a79eb636124f38d9b..c3b442e0224383803325c76ab3658da33d70892e 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -304,6 +304,11 @@ class LLView : public LLMouseHandler, public LLMortician, public LLFocusableElem
 	BOOL			getVisible() const			{ return mVisible; }
 	virtual void	setEnabled(BOOL enabled);
 	BOOL			getEnabled() const			{ return mEnabled; }
+	/// 'available' in this context means 'visible and enabled': in other
+	/// words, can a user actually interact with this?
+	virtual bool	isAvailable() const;
+	/// The static isAvailable() tests an LLView* that could be NULL.
+	static bool		isAvailable(const LLView* view);
 	U8              getSoundFlags() const       { return mSoundFlags; }
 
 	virtual BOOL	setLabelArg( const std::string& key, const LLStringExplicit& text );
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index 93ac1203023c45ca049a259f1143718f8e183b51..315baa001d2a6a0c01596ac6e7d1a8e1e062af90 100755
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -62,7 +62,7 @@ class LLPidLockFile
 			mSaving(FALSE), mWaiting(FALSE), 
 			mClean(TRUE), mPID(getpid())
 		{
-			mLockName = gDirUtilp->getTempDir() + "/savelock";
+			mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
 		}
 		bool requestLock(LLNameTable<void *> *name_table, bool autosave,
 						bool force_immediate=FALSE, F32 timeout=300.0);
diff --git a/indra/llwindow/llwindowmesaheadless.cpp b/indra/llwindow/llwindowmesaheadless.cpp
index 7ee09f4a24fcf37a9864bb43fe45bd2ac4b98d11..48736d920706c2d88246b75191ffb5a385318657 100644
--- a/indra/llwindow/llwindowmesaheadless.cpp
+++ b/indra/llwindow/llwindowmesaheadless.cpp
@@ -45,7 +45,7 @@ U16 *gMesaBuffer = NULL;
 // LLWindowMesaHeadless
 //
 LLWindowMesaHeadless::LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
-			 				 const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
+                                           const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
 							 U32 flags,  BOOL fullscreen, BOOL clearBg,
 							 BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
 	: LLWindow(callbacks, fullscreen, flags)
diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h
index 22e0ec126d507957b52dd863e047d4d3c16c0d82..46b62b914c092fc507175e94726e92323cd881a4 100644
--- a/indra/llwindow/llwindowmesaheadless.h
+++ b/indra/llwindow/llwindowmesaheadless.h
@@ -99,7 +99,7 @@ class LLWindowMesaHeadless : public LLWindow
 	/*virtual*/ void bringToFront() {};
 	
 	LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
-			      const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
+                         const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
 				  U32 flags,  BOOL fullscreen, BOOL clearBg,
 				  BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
 	~LLWindowMesaHeadless();
diff --git a/indra/llxuixml/lluicolor.cpp b/indra/llxuixml/lluicolor.cpp
index 856c05cf4af5d660b575dad16756db5552371549..424d878a6b23a9c46a7ed360005670145bd0b096 100644
--- a/indra/llxuixml/lluicolor.cpp
+++ b/indra/llxuixml/lluicolor.cpp
@@ -7,6 +7,8 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
+
 #include "lluicolor.h"
 
 LLUIColor::LLUIColor()
diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h
index ba2c46bef253bf3a0fa685b7f49b8e26710159dc..a54ebd5831a122350e28e834443a8737a12ac562 100644
--- a/indra/lscript/lscript_byteformat.h
+++ b/indra/lscript/lscript_byteformat.h
@@ -556,7 +556,7 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =
 // http_request string constants
 extern const char* URL_REQUEST_GRANTED;
 extern const char* URL_REQUEST_DENIED;
-extern const U64 LSL_HTTP_REQUEST_TIMEOUT;
+extern const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC;
 
 #endif
 
diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
index 98146d6f2bd9ba299ee838a6f5b55dd3ba8289a0..3b8bbbe805f57d305624ec53c6e119726a37fcb1 100644
--- a/indra/lscript/lscript_compile/lscript_tree.cpp
+++ b/indra/lscript/lscript_compile/lscript_tree.cpp
@@ -631,9 +631,7 @@ static void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetTy
 		switch(targetType)
 		{
 		case LST_INTEGER:
-			//fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
-			fprintf(fp, "conv.i4\n"); // TODO replace this line with the above
-			// we the entire grid is > 1.25.1
+			fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
 			break;
 		case LST_STRING:
 			fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ToString(float32)\n");
@@ -8375,10 +8373,18 @@ void LLScriptStateChange::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp
 			chunk->addInteger(mIdentifier->mScopeEntry->mCount);
 		}
 		break;
+	case LSCP_TYPE:
+		mReturnType = basetype;
+		break;
 	case LSCP_EMIT_CIL_ASSEMBLY:
 		fprintf(fp, "ldarg.0\n");
 		fprintf(fp, "ldstr \"%s\"\n", mIdentifier->mName);
 		fprintf(fp, "call instance void class [LslUserScript]LindenLab.SecondLife.LslUserScript::ChangeState(string)\n");
+		// We are doing a state change. In the LSL interpreter, this is basically a longjmp. We emulate it
+		// here using a call to the ChangeState followed by a short cut return of the current method. To
+		// maintain type safety we need to push an arbitrary variable of the current method's return type
+		// onto the stack before returning. This will be ignored and discarded.
+		print_cil_init_variable(fp, mReturnType);
 		fprintf(fp, "ret\n");
 		break;
 	default:
diff --git a/indra/lscript/lscript_compile/lscript_tree.h b/indra/lscript/lscript_compile/lscript_tree.h
index 12c16908af2b6aab5313e63014dbd0b9b6979702..a667e1eb5b796fbbea67a1dd34793a7e06df6f54 100644
--- a/indra/lscript/lscript_compile/lscript_tree.h
+++ b/indra/lscript/lscript_compile/lscript_tree.h
@@ -1888,6 +1888,7 @@ class LLScriptStateChange : public LLScriptStatement
 	S32 getSize();
 
 	LLScriptIdentifier *mIdentifier;
+	LSCRIPTType mReturnType;
 };
 
 class LLScriptJump : public LLScriptStatement
diff --git a/indra/lscript/lscript_execute.h b/indra/lscript/lscript_execute.h
index 245fc320d1154ee84b0847bebba58adf2fb69332..96855abea0fdf7f9cd60a99c3df828277b1b5d83 100644
--- a/indra/lscript/lscript_execute.h
+++ b/indra/lscript/lscript_execute.h
@@ -371,8 +371,7 @@ class LLScriptExecute
 {
 public:
 	LLScriptExecute();
-	virtual ~LLScriptExecute() {;}
-
+	virtual ~LLScriptExecute()  = 0;
 	virtual S32 getVersion() const = 0;
 	virtual void deleteAllEvents() = 0;
 	virtual void addEvent(LLScriptDataCollection* event) = 0;
diff --git a/indra/lscript/lscript_execute/llscriptresource.cpp b/indra/lscript/lscript_execute/llscriptresource.cpp
index 6c4776c2e446cb1021d789c7b39221ed24f94ccc..cd3696ab3faddee6970fef502d4dc7c05ecb4c0b 100644
--- a/indra/lscript/lscript_execute/llscriptresource.cpp
+++ b/indra/lscript/lscript_execute/llscriptresource.cpp
@@ -30,6 +30,8 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
+
 #include "llscriptresource.h"
 #include "llerror.h"
 
diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp
index 2fd81210c069ef68545d80e26fd51dbd03db552f..e849fa9a6e8532586fc8d70913b157e62917be7c 100644
--- a/indra/lscript/lscript_execute/lscript_execute.cpp
+++ b/indra/lscript/lscript_execute/lscript_execute.cpp
@@ -41,6 +41,8 @@
 #include "lscript_library.h"
 #include "lscript_heapruntime.h"
 #include "lscript_alloc.h"
+#include "llstat.h"
+
 
 // Static
 const	S32	DEFAULT_SCRIPT_TIMER_CHECK_SKIP = 4;
@@ -72,7 +74,7 @@ const char* URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED";
 const char* URL_REQUEST_DENIED = "URL_REQUEST_DENIED";
 
 // HTTP Requests to LSL scripts will time out after 25 seconds.
-const U64 LSL_HTTP_REQUEST_TIMEOUT = 25 * USEC_PER_SEC; 
+const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC = 25 * USEC_PER_SEC; 
 
 LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp)
 {
@@ -110,6 +112,7 @@ LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size)
 	init();
 }
 
+LLScriptExecute::~LLScriptExecute() {}
 LLScriptExecuteLSL2::~LLScriptExecuteLSL2()
 {
 	delete[] mBuffer;
@@ -4234,19 +4237,16 @@ S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer)
 	return 4;
 }
 
-BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+
+// Shared code for run_calllib() and run_calllib_two_byte()
+BOOL run_calllib_common(U8 *buffer, S32 &offset, const LLUUID &id, U16 arg)
 {
-	if (b_print)
-		printf("[0x%X]\tCALLLIB ", offset);
-	offset++;
-	U8 arg = safe_instruction_bytestream2byte(buffer, offset);
-	if (arg >= (U8)gScriptLibrary.mFunctions.size())
+	if (arg >= gScriptLibrary.mFunctions.size())
 	{
 		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
 		return FALSE;
 	}
-	if (b_print)
-		printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
+	LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
 
 	// pull out the arguments and the return values
 	LLScriptLibData	*arguments = NULL;
@@ -4254,14 +4254,14 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 
 	S32 i, number;
 
-	if (gScriptLibrary.mFunctions[arg].mReturnType)
+	if (function.mReturnType)
 	{
 		returnvalue = new LLScriptLibData;
 	}
 
-	if (gScriptLibrary.mFunctions[arg].mArgs)
+	if (function.mArgs)
 	{
-		number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs);		/*Flawfinder: ignore*/
+		number = (S32)strlen(function.mArgs);		//Flawfinder: ignore
 		arguments = new LLScriptLibData[number];
 	}
 	else
@@ -4271,23 +4271,18 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 
 	for (i = number - 1; i >= 0; i--)
 	{
-		lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
+		lscript_pop_variable(&arguments[i], buffer, function.mArgs[i]);
 	}
 
-	if (b_print)
-	{
-		printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
-	}
+	// Actually execute the function call
+	function.mExecFunc(returnvalue, arguments, id);
 
-	{
-		gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
-	}
-	add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
-	add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
+	add_register_fp(buffer, LREG_ESR, -(function.mEnergyUse));
+	add_register_fp(buffer, LREG_SLR, function.mSleepTime);
 
 	if (returnvalue)
 	{
-		returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
+		returnvalue->mType = char2type(*function.mReturnType);
 		lscript_push_return_variable(returnvalue, buffer);
 	}
 
@@ -4304,71 +4299,32 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 }
 
 
-BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 {
-	if (b_print)
-		printf("[0x%X]\tCALLLIB ", offset);
 	offset++;
-	U16 arg = safe_instruction_bytestream2u16(buffer, offset);
-	if (arg >= (U16)gScriptLibrary.mFunctions.size())
+	U16 arg = (U16) safe_instruction_bytestream2byte(buffer, offset);
+	if (b_print &&
+		arg < gScriptLibrary.mFunctions.size())
 	{
-		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
-		return FALSE;
-	}
-	if (b_print)
-		printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
-
-	// pull out the arguments and the return values
-	LLScriptLibData	*arguments = NULL;
-	LLScriptLibData	*returnvalue = NULL;
-
-	S32 i, number;
-
-	if (gScriptLibrary.mFunctions[arg].mReturnType)
-	{
-		returnvalue = new LLScriptLibData;
-	}
-
-	if (gScriptLibrary.mFunctions[arg].mArgs)
-	{
-		number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs);		/*Flawfinder: ignore*/
-		arguments = new LLScriptLibData[number];
-	}
-	else
-	{
-		number = 0;
-	}
-
-	for (i = number - 1; i >= 0; i--)
-	{
-		lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
-	}
-
-	if (b_print)
-	{
-		printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
-	}
-
-	{
-		gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
+		printf("[0x%X]\tCALLLIB ", offset);
+		LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+		printf("%d (%s)\n", (U32)arg, function.mName);
+		//printf("%s\n", function.mDesc);
 	}
-	add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
-	add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
+	return run_calllib_common(buffer, offset, id, arg);
+}
 
-	if (returnvalue)
+BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+{
+	offset++;
+	U16 arg = safe_instruction_bytestream2u16(buffer, offset);
+	if (b_print &&
+		arg < gScriptLibrary.mFunctions.size())
 	{
-		returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
-		lscript_push_return_variable(returnvalue, buffer);
+		printf("[0x%X]\tCALLLIB ", (offset-1));
+		LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+		printf("%d (%s)\n", (U32)arg, function.mName);
+		//printf("%s\n", function.mDesc);
 	}
-
-	delete [] arguments;
-	delete returnvalue;
-
-	// reset the BP after calling the library files
-	S32 bp = lscript_pop_int(buffer);
-	set_bp(buffer, bp);
-
-	// pop off the spot for the instruction pointer
-	lscript_poparg(buffer, 4);
-	return FALSE;
+	return run_calllib_common(buffer, offset, id, arg);
 }
diff --git a/indra/mac_crash_logger/CMakeLists.txt b/indra/mac_crash_logger/CMakeLists.txt
index daf3e10857af5e9361ff9c47e5e785675d705077..1d6494fecff6f1d201f2813f066c83fe393261f4 100644
--- a/indra/mac_crash_logger/CMakeLists.txt
+++ b/indra/mac_crash_logger/CMakeLists.txt
@@ -10,6 +10,7 @@ include(LLMessage)
 include(LLVFS)
 include(LLXML)
 include(Linking)
+include(LLSharedLibs)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
@@ -74,3 +75,7 @@ add_custom_command(
     ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-crash-logger.app/Contents/Resources/CrashReporter.nib
   )
 
+ll_deploy_sharedlibs_command(
+  mac-crash-logger
+  "${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR};${ARCH_PREBUILT_DIRS}" 
+  "../Resources") 
diff --git a/indra/mac_updater/CMakeLists.txt b/indra/mac_updater/CMakeLists.txt
index 0eac76fa697ca6e3fcd9e0ab84553cb2dc9a177d..d7bd6f993ce0e3a0c46bf1496267165c178786f9 100644
--- a/indra/mac_updater/CMakeLists.txt
+++ b/indra/mac_updater/CMakeLists.txt
@@ -77,3 +77,7 @@ add_custom_command(
     ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-updater.app/Contents/Resources/AutoUpdater.nib
   )
 
+ll_deploy_sharedlibs_command(
+  mac-updater
+  "${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR};${ARCH_PREBUILT_DIRS}" 
+  "../Resources") 
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
index d35afd8cbd782d87d790841a254c7fd07a453f25..cc03d9cb72d58a7970d8ad2be59aeb5334e04b57 100644
--- a/indra/media_plugins/CMakeLists.txt
+++ b/indra/media_plugins/CMakeLists.txt
@@ -9,3 +9,5 @@ add_subdirectory(gstreamer010)
 if (WINDOWS OR DARWIN)
     add_subdirectory(quicktime)
 endif (WINDOWS OR DARWIN)
+
+add_subdirectory(example)
diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp
index 0b7092fad601ecf94e5d97a7bdb15c5af1360457..6acac074233cb578171a71a4c07b90535fde6449 100644
--- a/indra/media_plugins/base/media_plugin_base.cpp
+++ b/indra/media_plugins/base/media_plugin_base.cpp
@@ -64,6 +64,7 @@ std::string MediaPluginBase::statusString()
 		case STATUS_ERROR:		result = "error";		break;
 		case STATUS_PLAYING:	result = "playing";		break;
 		case STATUS_PAUSED:		result = "paused";		break;
+		case STATUS_DONE:		result = "done";		break;
 		default:
 			// keep the empty string
 		break;
diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h
index 8f600cb8d617385845627a6117deb1eb139a1f13..f1e96335f92e301170369343ca64292dcaee840f 100644
--- a/indra/media_plugins/base/media_plugin_base.h
+++ b/indra/media_plugins/base/media_plugin_base.h
@@ -56,6 +56,7 @@ class MediaPluginBase
 		STATUS_ERROR,
 		STATUS_PLAYING,
 		STATUS_PAUSED,
+		STATUS_DONE
 	} EStatus;
 
 	class SharedSegmentInfo
diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4d82f2747c0a7bf1dbc4428473774d2378242c5f
--- /dev/null
+++ b/indra/media_plugins/example/CMakeLists.txt
@@ -0,0 +1,74 @@
+# -*- cmake -*-
+
+project(media_plugin_example)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLPlugin)
+include(LLMath)
+include(LLRender)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(MediaPluginBase)
+include(FindOpenGL)
+
+include(ExamplePlugin)
+
+include_directories(
+    ${LLPLUGIN_INCLUDE_DIRS}
+    ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
+    ${LLCOMMON_INCLUDE_DIRS}
+    ${LLMATH_INCLUDE_DIRS}
+    ${LLIMAGE_INCLUDE_DIRS}
+    ${LLRENDER_INCLUDE_DIRS}
+    ${LLWINDOW_INCLUDE_DIRS}
+)
+
+
+### media_plugin_example
+
+set(media_plugin_example_SOURCE_FILES
+    media_plugin_example.cpp
+    )
+
+add_library(media_plugin_example
+    SHARED
+    ${media_plugin_example_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_example
+  ${LLPLUGIN_LIBRARIES}
+  ${MEDIA_PLUGIN_BASE_LIBRARIES}
+  ${LLCOMMON_LIBRARIES}
+  ${EXAMPLE_PLUGIN_LIBRARIES}
+  ${PLUGIN_API_WINDOWS_LIBRARIES}
+)
+
+add_dependencies(media_plugin_example
+  ${LLPLUGIN_LIBRARIES}
+  ${MEDIA_PLUGIN_BASE_LIBRARIES}
+  ${LLCOMMON_LIBRARIES}
+)
+
+if (WINDOWS)
+  set_target_properties(
+    media_plugin_example
+    PROPERTIES
+    LINK_FLAGS "/MANIFEST:NO"
+    )
+endif (WINDOWS)
+
+if (DARWIN)
+  # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
+  set_target_properties(
+    media_plugin_example
+    PROPERTIES
+    PREFIX ""
+    BUILD_WITH_INSTALL_RPATH 1
+    INSTALL_NAME_DIR "@executable_path"
+    LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
+  )
+
+endif (DARWIN)
\ No newline at end of file
diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..99e0199a293ed4a43200aa1b885f462330079f7b
--- /dev/null
+++ b/indra/media_plugins/example/media_plugin_example.cpp
@@ -0,0 +1,488 @@
+/**
+ * @file media_plugin_example.cpp
+ * @brief Example plugin for LLMedia API plugin system
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llgl.h"
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#include <time.h>
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginExample :
+		public MediaPluginBase
+{
+	public:
+		MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data );
+		~MediaPluginExample();
+
+		/*virtual*/ void receiveMessage( const char* message_string );
+
+	private:
+		bool init();
+		void update( F64 milliseconds );
+		void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b );
+		bool mFirstTime;
+
+		time_t mLastUpdateTime;
+		enum Constants { ENumObjects = 10 };
+		unsigned char* mBackgroundPixels;
+		int mColorR[ ENumObjects ];
+		int mColorG[ ENumObjects ];
+		int mColorB[ ENumObjects ];
+		int mXpos[ ENumObjects ];
+		int mYpos[ ENumObjects ];
+		int mXInc[ ENumObjects ];
+		int mYInc[ ENumObjects ];
+		int mBlockSize[ ENumObjects ];
+		bool mMouseButtonDown;
+		bool mStopAction;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginExample::MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) :
+	MediaPluginBase( host_send_func, host_user_data )
+{
+	mFirstTime = true;
+	mWidth = 0;
+	mHeight = 0;
+	mDepth = 4;
+	mPixels = 0;
+	mMouseButtonDown = false;
+	mStopAction = false;
+	mLastUpdateTime = 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginExample::~MediaPluginExample()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginExample::receiveMessage( const char* message_string )
+{
+	LLPluginMessage message_in;
+
+	if ( message_in.parse( message_string ) >= 0 )
+	{
+		std::string message_class = message_in.getClass();
+		std::string message_name = message_in.getName();
+
+		if ( message_class == LLPLUGIN_MESSAGE_CLASS_BASE )
+		{
+			if ( message_name == "init" )
+			{
+				LLPluginMessage message( "base", "init_response" );
+				LLSD versions = LLSD::emptyMap();
+				versions[ LLPLUGIN_MESSAGE_CLASS_BASE ] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+				versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+				versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
+				message.setValueLLSD( "versions", versions );
+
+				std::string plugin_version = "Example media plugin, Example Version 1.0.0.0";
+				message.setValue( "plugin_version", plugin_version );
+				sendMessage( message );
+
+				// Plugin gets to decide the texture parameters to use.
+				message.setMessage( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" );
+				message.setValueS32( "default_width", mWidth );
+				message.setValueS32( "default_height", mHeight );
+				message.setValueS32( "depth", mDepth );
+				message.setValueU32( "internalformat", GL_RGBA );
+				message.setValueU32( "format", GL_RGBA );
+				message.setValueU32( "type", GL_UNSIGNED_BYTE );
+				message.setValueBoolean( "coords_opengl", false );
+				sendMessage( message );
+			}
+			else
+			if ( message_name == "idle" )
+			{
+				// no response is necessary here.
+				F64 time = message_in.getValueReal( "time" );
+
+				// Convert time to milliseconds for update()
+				update( time );
+			}
+			else
+			if ( message_name == "cleanup" )
+			{
+				// clean up here
+			}
+			else
+			if ( message_name == "shm_added" )
+			{
+				SharedSegmentInfo info;
+				info.mAddress = message_in.getValuePointer( "address" );
+				info.mSize = ( size_t )message_in.getValueS32( "size" );
+				std::string name = message_in.getValue( "name" );
+
+				mSharedSegments.insert( SharedSegmentMap::value_type( name, info ) );
+
+			}
+			else
+			if ( message_name == "shm_remove" )
+			{
+				std::string name = message_in.getValue( "name" );
+
+				SharedSegmentMap::iterator iter = mSharedSegments.find( name );
+				if( iter != mSharedSegments.end() )
+				{
+					if ( mPixels == iter->second.mAddress )
+					{
+						// This is the currently active pixel buffer.
+						// Make sure we stop drawing to it.
+						mPixels = NULL;
+						mTextureSegmentName.clear();
+					};
+					mSharedSegments.erase( iter );
+				}
+				else
+				{
+					//std::cerr << "MediaPluginExample::receiveMessage: unknown shared memory region!" << std::endl;
+				};
+
+				// Send the response so it can be cleaned up.
+				LLPluginMessage message( "base", "shm_remove_response" );
+				message.setValue( "name", name );
+				sendMessage( message );
+			}
+			else
+			{
+				//std::cerr << "MediaPluginExample::receiveMessage: unknown base message: " << message_name << std::endl;
+			};
+		}
+		else
+		if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA )
+		{
+			if ( message_name == "size_change" )
+			{
+				std::string name = message_in.getValue( "name" );
+				S32 width = message_in.getValueS32( "width" );
+				S32 height = message_in.getValueS32( "height" );
+				S32 texture_width = message_in.getValueS32( "texture_width" );
+				S32 texture_height = message_in.getValueS32( "texture_height" );
+
+				if ( ! name.empty() )
+				{
+					// Find the shared memory region with this name
+					SharedSegmentMap::iterator iter = mSharedSegments.find( name );
+					if ( iter != mSharedSegments.end() )
+					{
+						mPixels = ( unsigned char* )iter->second.mAddress;
+						mWidth = width;
+						mHeight = height;
+
+						mTextureWidth = texture_width;
+						mTextureHeight = texture_height;
+
+						init();
+					};
+				};
+
+				LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response" );
+				message.setValue( "name", name );
+				message.setValueS32( "width", width );
+				message.setValueS32( "height", height );
+				message.setValueS32( "texture_width", texture_width );
+				message.setValueS32( "texture_height", texture_height );
+				sendMessage( message );
+			}
+			else
+			if ( message_name == "load_uri" )
+			{
+				std::string uri = message_in.getValue( "uri" );
+				if ( ! uri.empty() )
+				{
+				};
+			}
+			else
+			if ( message_name == "mouse_event" )
+			{
+				std::string event = message_in.getValue( "event" );
+				S32 button = message_in.getValueS32( "button" );
+
+				// left mouse button
+				if ( button == 0 )
+				{
+					int mouse_x = message_in.getValueS32( "x" );
+					int mouse_y = message_in.getValueS32( "y" );
+					std::string modifiers = message_in.getValue( "modifiers" );
+
+					if ( event == "move" )
+					{
+						if ( mMouseButtonDown )
+							write_pixel( mouse_x, mouse_y, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80 );
+					}
+					else
+					if ( event == "down" )
+					{
+						mMouseButtonDown = true;
+					}
+					else
+					if ( event == "up" )
+					{
+						mMouseButtonDown = false;
+					}
+					else
+					if ( event == "double_click" )
+					{
+					};
+				};
+			}
+			else
+			if ( message_name == "key_event" )
+			{
+				std::string event = message_in.getValue( "event" );
+				S32 key = message_in.getValueS32( "key" );
+				std::string modifiers = message_in.getValue( "modifiers" );
+
+				if ( event == "down" )
+				{
+					if ( key == ' ')
+					{
+						mLastUpdateTime = 0;
+						update( 0.0f );
+					};
+				};
+			}
+			else
+			{
+				//std::cerr << "MediaPluginExample::receiveMessage: unknown media message: " << message_string << std::endl;
+			};
+		}
+		else
+		if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER )
+		{
+			if ( message_name == "browse_reload" )
+			{
+				mLastUpdateTime = 0;
+				mFirstTime = true;
+				mStopAction = false;
+				update( 0.0f );
+			}
+			else
+			if ( message_name == "browse_stop" )
+			{
+				for( int n = 0; n < ENumObjects; ++n )
+					mXInc[ n ] = mYInc[ n ] = 0;
+
+				mStopAction = true;
+				update( 0.0f );
+			}
+			else
+			{
+				//std::cerr << "MediaPluginExample::receiveMessage: unknown media_browser message: " << message_string << std::endl;
+			};
+		}
+		else
+		{
+			//std::cerr << "MediaPluginExample::receiveMessage: unknown message class: " << message_class << std::endl;
+		};
+	};
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b )
+{
+	// make sure we don't write outside the buffer
+	if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) )
+		return;
+		
+	if ( mBackgroundPixels != NULL )
+	{
+		unsigned char *pixel = mBackgroundPixels;
+		pixel += y * mWidth * mDepth;
+		pixel += ( x * mDepth );
+		pixel[ 0 ] = b;
+		pixel[ 1 ] = g;
+		pixel[ 2 ] = r;
+
+		setDirty( x, y, x + 1, y + 1 );
+	};
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginExample::update( F64 milliseconds )
+{
+	if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 )
+		return;
+
+	if ( mPixels == 0 )
+			return;
+
+	if ( mFirstTime )
+	{
+		for( int n = 0; n < ENumObjects; ++n )
+		{
+			mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 );
+			mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 );
+
+			mColorR[ n ] = rand() % 0x60 + 0x60;
+			mColorG[ n ] = rand() % 0x60 + 0x60;
+			mColorB[ n ] = rand() % 0x60 + 0x60;
+
+			mXInc[ n ] = 0;
+			while ( mXInc[ n ] == 0 )
+				mXInc[ n ] = rand() % 7 - 3;
+
+			mYInc[ n ] = 0;
+			while ( mYInc[ n ] == 0 )
+				mYInc[ n ] = rand() % 9 - 4;
+
+			mBlockSize[ n ] = rand() % 0x30 + 0x10;
+		};
+
+		delete [] mBackgroundPixels;
+				
+		mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ];
+
+		mFirstTime = false;
+	};
+
+	if ( mStopAction )
+		return;
+
+	if ( time( NULL ) > mLastUpdateTime + 3 )
+	{
+		const int num_squares = rand() % 20 + 4;
+		int sqr1_r = rand() % 0x80 + 0x20;
+		int sqr1_g = rand() % 0x80 + 0x20;
+		int sqr1_b = rand() % 0x80 + 0x20;
+		int sqr2_r = rand() % 0x80 + 0x20;
+		int sqr2_g = rand() % 0x80 + 0x20;
+		int sqr2_b = rand() % 0x80 + 0x20;
+
+		for ( int y1 = 0; y1 < num_squares; ++y1 )
+		{
+			for ( int x1 = 0; x1 < num_squares; ++x1 )
+			{
+				int px_start = mWidth * x1 / num_squares;
+				int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares;
+				int py_start = mHeight * y1 / num_squares;
+				int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares;
+
+				for( int y2 = py_start; y2 < py_end; ++y2 )
+				{
+					for( int x2 = px_start; x2 < px_end; ++x2 )
+					{
+						int rowspan = mWidth * mDepth;
+
+						if ( ( y1 % 2 ) ^ ( x1 % 2 ) )
+						{
+							mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r;
+							mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g;
+							mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b;
+						}
+						else
+						{
+							mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r;
+							mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g;
+							mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b;
+						};
+					};
+				};
+			};
+		};
+
+		time( &mLastUpdateTime );
+	};
+
+	memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth );
+
+	for( int n = 0; n < ENumObjects; ++n )
+	{
+		if ( rand() % 50 == 0 )
+		{
+				mXInc[ n ] = 0;
+				while ( mXInc[ n ] == 0 )
+					mXInc[ n ] = rand() % 7 - 3;
+
+				mYInc[ n ] = 0;
+				while ( mYInc[ n ] == 0 )
+					mYInc[ n ] = rand() % 9 - 4;
+		};
+
+		if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] )
+			mXInc[ n ] =- mXInc[ n ];
+
+		if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] )
+			mYInc[ n ] =- mYInc[ n ];
+
+		mXpos[ n ] += mXInc[ n ];
+		mYpos[ n ] += mYInc[ n ];
+
+		for( int y = 0; y < mBlockSize[ n ]; ++y )
+		{
+			for( int x = 0; x < mBlockSize[ n ]; ++x )
+			{
+				mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ];
+				mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ];
+				mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ];
+			};
+		};
+	};
+
+	setDirty( 0, 0, mWidth, mHeight );
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool MediaPluginExample::init()
+{
+	LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" );
+	message.setValue( "name", "Example Plugin" );
+	sendMessage( message );
+
+	return true;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func,
+						void* host_user_data,
+						LLPluginInstance::sendMessageFunction *plugin_send_func,
+						void **plugin_user_data )
+{
+	MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data );
+	*plugin_send_func = MediaPluginExample::staticReceiveMessage;
+	*plugin_user_data = ( void* )self;
+
+	return 0;
+}
diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt
index db11c9ae218b7667bd7e71d72cb3a86315c355d3..f0b8f0d16706f5b491d783b45559b0cd9d8d8a31 100644
--- a/indra/media_plugins/quicktime/CMakeLists.txt
+++ b/indra/media_plugins/quicktime/CMakeLists.txt
@@ -56,6 +56,14 @@ add_dependencies(media_plugin_quicktime
   ${LLCOMMON_LIBRARIES}
 )
 
+if (WINDOWS)
+  set_target_properties(
+    media_plugin_quicktime
+    PROPERTIES
+    LINK_FLAGS "/MANIFEST:NO"
+    )
+endif (WINDOWS)
+
 if (QUICKTIME)
 
     add_definitions(-DLL_QUICKTIME_ENABLED=1)
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index fbda65120d729708844453c2cc7bb967b349b424..fb6d5b29054ce58dd61177322d236c9add308e69 100644
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -1,981 +1,1098 @@
-/** 
- * @file media_plugin_quicktime.cpp
- * @brief QuickTime plugin for LLMedia API plugin system
- *
- * $LicenseInfo:firstyear=2008&license=viewergpl$
- *
- * Copyright (c) 2008, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llgl.h"
-
-#include "llplugininstance.h"
-#include "llpluginmessage.h"
-#include "llpluginmessageclasses.h"
-#include "media_plugin_base.h"
-
-#if LL_QUICKTIME_ENABLED
-
-#if defined(LL_DARWIN)
-	#include <QuickTime/QuickTime.h>
-#elif defined(LL_WINDOWS)
-	#include "MacTypes.h"
-	#include "QTML.h"
-	#include "Movies.h"
-	#include "QDoffscreen.h"
-	#include "FixMath.h"
-#endif
-
-// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
-////////////////////////////////////////////////////////////////////////////////
-//
-class MediaPluginQuickTime : public MediaPluginBase
-{
-public:
-	MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
-	~MediaPluginQuickTime();
-
-	/* virtual */ void receiveMessage(const char *message_string);
-
-private:
-
-	int mNaturalWidth;
-	int mNaturalHeight;
-	Movie mMovieHandle;
-	GWorldPtr mGWorldHandle;
-	ComponentInstance mMovieController;
-	int mCurVolume;
-	bool mMediaSizeChanging;
-	bool mIsLooping;
-	const int mMinWidth;
-	const int mMaxWidth;
-	const int mMinHeight;
-	const int mMaxHeight;
-	F64 mPlayRate;
-
-	enum ECommand {
-		COMMAND_NONE,
-		COMMAND_STOP,
-		COMMAND_PLAY,
-		COMMAND_FAST_FORWARD,
-		COMMAND_FAST_REWIND,
-		COMMAND_PAUSE,
-		COMMAND_SEEK,
-	};
-	ECommand mCommand;
-
-	// Override this to add current time and duration to the message
-	/*virtual*/ void setDirty(int left, int top, int right, int bottom)
-	{
-		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
-
-		message.setValueS32("left", left);
-		message.setValueS32("top", top);
-		message.setValueS32("right", right);
-		message.setValueS32("bottom", bottom);
-		
-		if(mMovieHandle)
-		{
-			message.setValueReal("current_time", getCurrentTime());
-			message.setValueReal("duration", getDuration());
-			message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle)));
-		}
-			
-		sendMessage(message);
-	}
-
-
-	static Rect rectFromSize(int width, int height)
-	{
-		Rect result;
-		
-
-		result.left = 0;
-		result.top = 0;
-		result.right = width;
-		result.bottom = height;
-		
-		return result;
-	}
-	
-	Fixed getPlayRate(void)
-	{
-		Fixed result;
-		if(mPlayRate == 0.0f)
-		{
-			// Default to the movie's preferred rate
-			result = GetMoviePreferredRate(mMovieHandle);
-			if(result == 0)
-			{
-				// Don't return a 0 play rate, ever.
-				std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl;
-				result = X2Fix(1.0f);
-			}
-		}
-		else
-		{
-			result = X2Fix(mPlayRate);
-		}
-		
-		return result;
-	}
-	
-	void load( const std::string url )
-	{
-		if ( url.empty() )
-			return;
-		
-		// Stop and unload any existing movie before starting another one.
-		unload();
-			
-		setStatus(STATUS_LOADING);
-		
-		//In case std::string::c_str() makes a copy of the url data,
-		//make sure there is memory to hold it before allocating memory for handle.
-		//if fails, NewHandleClear(...) should return NULL.
-		const char* url_string = url.c_str() ;
-		Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) );
-		if ( NULL == handle || noErr != MemError() || NULL == *handle )
-		{
-			setStatus(STATUS_ERROR);
-			return;
-		}
-
-		BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) );
-
-		OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType );
-		DisposeHandle( handle );
-		if ( noErr != err )
-		{
-			setStatus(STATUS_ERROR);
-			return;
-		};
-
-		// do pre-roll actions (typically fired for streaming movies but not always)
-		PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this );
-
-		Rect movie_rect = rectFromSize(mWidth, mHeight);
-
-		// make a new movie controller
-		mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie );
-
-		// movie controller
-		MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this );
-
-		SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize );
-
-		// function that gets called when a frame is drawn
-		SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this );
-
-		setStatus(STATUS_LOADED);
-		
-		sizeChanged();
-	};
-
-	bool unload()
-	{
-		if ( mMovieHandle )
-		{
-			StopMovie( mMovieHandle );
-			if ( mMovieController )
-			{
-				MCMovieChanged( mMovieController, mMovieHandle );
-			};
-		};
-
-		if ( mMovieController )
-		{
-			MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this );
-			DisposeMovieController( mMovieController );
-			mMovieController = NULL;
-		};
-
-		if ( mMovieHandle )
-		{
-			SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this );
-			DisposeMovie( mMovieHandle );
-			mMovieHandle = NULL;
-		};
-
-		if ( mGWorldHandle )
-		{
-			DisposeGWorld( mGWorldHandle );
-			mGWorldHandle = NULL;
-		};
-		
-		setStatus(STATUS_NONE);
-
-		return true;
-	}
-
-	bool navigateTo( const std::string url )
-	{
-		unload();
-		load( url );
-		
-		return true;
-	};
-
-	bool sizeChanged()
-	{
-		if ( ! mMovieHandle )
-			return false;
-		
-		// Check to see whether the movie's natural size has updated
-		{
-			int width, height;
-			getMovieNaturalSize(&width, &height);
-			if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight)))
-			{
-				mNaturalWidth = width;
-				mNaturalHeight = height;
-
-				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
-				message.setValue("name", mTextureSegmentName);
-				message.setValueS32("width", width);
-				message.setValueS32("height", height);
-				sendMessage(message);
-				//std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl;
-			}
-		}
-		
-		// sanitize destination size
-		Rect dest_rect = rectFromSize(mWidth, mHeight);
-
-		// media depth won't change
-		int depth_bits = mDepth * 8;
-		long rowbytes = mDepth * mTextureWidth;
-				
-		GWorldPtr old_gworld_handle = mGWorldHandle;
-
-		if(mPixels != NULL)
-		{
-			// We have pixels.  Set up a GWorld pointing at the texture.
-			OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
-			if ( noErr != result )
-			{
-				// TODO: unrecoverable??  throw exception?  return something?
-				return false;
-			}
-		}
-		else
-		{
-			// We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally.
-			Rect tempRect = rectFromSize(1, 1);
-			OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
-			if ( noErr != result )
-			{
-				// TODO: unrecoverable??  throw exception?  return something?
-				return false;
-			}
-		}
-
-		SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) );
-
-		// If the GWorld was already set up, delete it.
-		if(old_gworld_handle != NULL)
-		{
-			DisposeGWorld( old_gworld_handle );
-		}
-		
-		// Set up the movie display matrix
-		{
-			// scale movie to fit rect and invert vertically to match opengl image format
-			MatrixRecord transform;
-			SetIdentityMatrix( &transform );	// transforms are additive so start from identify matrix
-			double scaleX = (double) mWidth / mNaturalWidth;
-			double scaleY = -1.0 * (double) mHeight / mNaturalHeight;
-			double centerX = mWidth / 2.0;
-			double centerY = mHeight / 2.0;
-			ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) );
-			SetMovieMatrix( mMovieHandle, &transform );
-		}
-		
-		// update movie controller
-		if ( mMovieController )
-		{
-			MCSetControllerPort( mMovieController, mGWorldHandle );
-			MCPositionController( mMovieController, &dest_rect, &dest_rect,
-								  mcTopLeftMovie | mcPositionDontInvalidate );
-			MCMovieChanged( mMovieController, mMovieHandle );
-		}
-
-
-		// Emit event with size change so the calling app knows about it too
-		// TODO:
-		//LLMediaEvent event( this );
-		//mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event );
-
-		return true;
-	}
-
-	static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref )
-	{
-		Boolean result = false;
-
-		MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
-
-		switch( action )
-		{
-			// handle window resizing
-			case mcActionControllerSizeChanged:				
-				// Ensure that the movie draws correctly at the new size
-				self->sizeChanged();						
-				break;
-
-			// Block any movie controller actions that open URLs.
-			case mcActionLinkToURL:
-			case mcActionGetNextURL:
-			case mcActionLinkToURLExtended:
-				// Prevent the movie controller from handling the message
-				result = true;
-				break;
-
-			default:
-				break;
-		};
-
-		return result;
-	};
-
-	static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref )
-	{
-		MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
-
-		// IMPORTANT: typically, a consumer who is observing this event will set a flag
-		// when this event is fired then render later. Be aware that the media stream
-		// can change during this period - dimensions, depth, format etc.
-		//LLMediaEvent event( self );
-//		self->updateQuickTime();
-		// TODO ^^^
-
-		if ( self->mWidth > 0 && self->mHeight > 0 )
-			self->setDirty( 0, 0, self->mWidth, self->mHeight );
-
-		return noErr;
-	};
-
-	static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref )
-	{
-		//MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
-
-		// TODO:
-		//LLMediaEvent event( self );
-		//self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event );
-	};
-
-
-	void rewind()
-	{
-		GoToBeginningOfMovie( mMovieHandle );
-		MCMovieChanged( mMovieController, mMovieHandle );
-	};
-
-	bool processState()
-	{
-		if ( mCommand == COMMAND_PLAY )
-		{
-			if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING )
-			{
-				long state = GetMovieLoadState( mMovieHandle );
-
-				if ( state >= kMovieLoadStatePlaythroughOK )
-				{
-					// if the movie is at the end (generally because it reached it naturally)
-					// and we play is requested, jump back to the start of the movie.
-					// note: this is different from having loop flag set.
-					if ( IsMovieDone( mMovieHandle ) )
-					{
-						Fixed rate = X2Fix( 0.0 );
-						MCDoAction( mMovieController, mcActionPlay, (void*)rate );
-						rewind();
-					};
-					
-					MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
-					MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
-					setStatus(STATUS_PLAYING);
-					mCommand = COMMAND_NONE;
-				};
-			};
-		}
-		else
-		if ( mCommand == COMMAND_STOP )
-		{
-			if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED )
-			{
-				if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
-				{
-					Fixed rate = X2Fix( 0.0 );
-					MCDoAction( mMovieController, mcActionPlay, (void*)rate );
-					rewind();
-
-					setStatus(STATUS_LOADED);
-					mCommand = COMMAND_NONE;
-				};
-			};
-		}
-		else
-		if ( mCommand == COMMAND_PAUSE )
-		{
-			if ( mStatus == STATUS_PLAYING )
-			{				
-				if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
-				{
-					Fixed rate = X2Fix( 0.0 );
-					MCDoAction( mMovieController, mcActionPlay, (void*)rate );
-					setStatus(STATUS_PAUSED);
-					mCommand = COMMAND_NONE;
-				};
-			};
-		};
-
-		return true;
-	};
-
-	void play(F64 rate)
-	{
-		mPlayRate = rate;
-		mCommand = COMMAND_PLAY;
-	};
-
-	void stop()
-	{
-		mCommand = COMMAND_STOP;
-	};
-
-	void pause()
-	{
-		mCommand = COMMAND_PAUSE;
-	};
-
-	void getMovieNaturalSize(int *movie_width, int *movie_height)
-	{
-		Rect rect;
-		
-		GetMovieNaturalBoundsRect( mMovieHandle, &rect );
-
-		int width  = ( rect.right - rect.left );
-		int height = ( rect.bottom - rect.top );
-
-		// make sure width and height fall in valid range
-		if ( width < mMinWidth )
-			width = mMinWidth;
-
-		if ( width > mMaxWidth )
-			width = mMaxWidth;
-
-		if ( height < mMinHeight )
-			height = mMinHeight;
-
-		if ( height > mMaxHeight )
-			height = mMaxHeight;
-
-		// return the new rect
-		*movie_width = width;
-		*movie_height = height;
-	}
-	
-	void updateQuickTime(int milliseconds)
-	{
-		if ( ! mMovieHandle )
-			return;
-
-		if ( ! mMovieController )
-			return;
-
-		// service QuickTime
-		// Calling it this way doesn't have good behavior on Windows...
-//		MoviesTask( mMovieHandle, milliseconds );
-		// This was the original, but I think using both MoviesTask and MCIdle is redundant.  Trying with only MCIdle.
-//		MoviesTask( mMovieHandle, 0 );
-
-		MCIdle( mMovieController );
-
-		if ( ! mGWorldHandle )
-			return;
-
-		if ( mMediaSizeChanging )
-			return;
-
-		// update state machine
-		processState();
-
-		// special code for looping - need to rewind at the end of the movie
-		if ( mIsLooping )
-		{
-			// QT call to see if we are at the end - can't do with controller
-			if ( IsMovieDone( mMovieHandle ) )
-			{
-				// go back to start
-				rewind();
-
-				if ( mMovieController )
-				{
-					// kick off new play
-					MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
-
-					// set the volume
-					MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
-				};
-			};
-		};
-	};
-
-	int getDataWidth() const
-	{
-		if ( mGWorldHandle )
-		{
-			int depth = mDepth;
-
-			if (depth < 1)
-				depth = 1;
-
-			// ALWAYS use the row bytes from the PixMap if we have a GWorld because
-			// sometimes it's not the same as mMediaDepth * mMediaWidth !
-			PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle );
-			return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth;
-		}
-		else
-		{
-			// TODO :   return LLMediaImplCommon::getaDataWidth();
-			return 0;
-		}
-	};
-
-	void seek( F64 time )
-	{
-		if ( mMovieController )
-		{
-			TimeRecord when;
-			when.scale = GetMovieTimeScale( mMovieHandle );
-			when.base = 0;
-
-			// 'time' is in (floating point) seconds.  The timebase time will be in 'units', where
-			// there are 'scale' units per second.
-			SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) );
-
-			when.value.hi = ( SInt32 )( raw_time >> 32 );
-			when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) );
-
-			MCDoAction( mMovieController, mcActionGoToTime, &when );
-		};
-	};
-
-	F64 getDuration()
-	{
-		TimeValue duration = GetMovieDuration( mMovieHandle );
-		TimeValue scale = GetMovieTimeScale( mMovieHandle );
-
-		return (F64)duration / (F64)scale;
-	};
-
-	F64 getCurrentTime()
-	{
-		TimeValue curr_time = GetMovieTime( mMovieHandle, 0 );
-		TimeValue scale = GetMovieTimeScale( mMovieHandle );
-
-		return (F64)curr_time / (F64)scale;
-	};
-
-	void setVolume( F64 volume )
-	{
-		mCurVolume = (short)(volume * ( double ) 0x100 );
-
-		if ( mMovieController )
-		{
-			MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
-		};
-	};
-
-	////////////////////////////////////////////////////////////////////////////////
-	//
-	void update(int milliseconds = 0)
-	{
-		updateQuickTime(milliseconds);
-	};
-
-	////////////////////////////////////////////////////////////////////////////////
-	//
-	void mouseDown( int x, int y )
-	{
-	};
-
-	////////////////////////////////////////////////////////////////////////////////
-	//
-	void mouseUp( int x, int y )
-	{
-	};
-
-	////////////////////////////////////////////////////////////////////////////////
-	//
-	void mouseMove( int x, int y )
-	{
-	};
-
-	////////////////////////////////////////////////////////////////////////////////
-	//
-	void keyPress( unsigned char key )
-	{
-	};
-
-};
-
-MediaPluginQuickTime::MediaPluginQuickTime(
-	LLPluginInstance::sendMessageFunction host_send_func,
-	void *host_user_data ) :
-	MediaPluginBase(host_send_func, host_user_data),
-	mMinWidth( 0 ),
-	mMaxWidth( 2048 ),
-	mMinHeight( 0 ),
-	mMaxHeight( 2048 )
-{
-//	std::cerr << "MediaPluginQuickTime constructor" << std::endl;
-
-	mNaturalWidth = -1;
-	mNaturalHeight = -1;
-	mMovieHandle = 0;
-	mGWorldHandle = 0;
-	mMovieController = 0;
-	mCurVolume = 0x99;
-	mMediaSizeChanging = false;
-	mIsLooping = false;
-	mCommand = COMMAND_NONE;
-	mPlayRate = 0.0f;
-	mStatus = STATUS_NONE;
-}
-
-MediaPluginQuickTime::~MediaPluginQuickTime()
-{
-//	std::cerr << "MediaPluginQuickTime destructor" << std::endl;
-
-	ExitMovies();
-
-#ifdef LL_WINDOWS
-	TerminateQTML();
-//		std::cerr << "QuickTime closing down" << std::endl;
-#endif
-}
-
-
-void MediaPluginQuickTime::receiveMessage(const char *message_string)
-{
-//	std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
-	LLPluginMessage message_in;
-
-	if(message_in.parse(message_string) >= 0)
-	{
-		std::string message_class = message_in.getClass();
-		std::string message_name = message_in.getName();
-		if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
-		{
-			if(message_name == "init")
-			{
-				LLPluginMessage message("base", "init_response");
-				LLSD versions = LLSD::emptyMap();
-				versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
-				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
-				// Normally a plugin would only specify one of these two subclasses, but this is a demo...
-//				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
-				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
-				message.setValueLLSD("versions", versions);
-
-				#ifdef LL_WINDOWS
-				if ( InitializeQTML( 0L ) != noErr )
-				{
-					//TODO: If no QT on Windows, this fails - respond accordingly.
-					//return false;
-				}
-				else
-				{
-//					std::cerr << "QuickTime initialized" << std::endl;
-				};
-				#endif
-
-				EnterMovies();
-
-				std::string plugin_version = "QuickTime media plugin, QuickTime version ";
-
-				long version = 0;
-				Gestalt( gestaltQuickTimeVersion, &version );
-				std::ostringstream codec( "" );
-				codec << std::hex << version << std::dec;
-				plugin_version += codec.str();
-				message.setValue("plugin_version", plugin_version);
-				sendMessage(message);
-
-				// Plugin gets to decide the texture parameters to use.
-				message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
-				#if defined(LL_WINDOWS)
-					// Values for Windows
-					mDepth = 3;	
-					message.setValueU32("format", GL_RGB);
-					message.setValueU32("type", GL_UNSIGNED_BYTE);
-
-					// We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even.
-					// Padding to a multiple of 3*32 guarantees it'll divide out properly.
-					message.setValueU32("padding", 32 * 3);
-				#else
-					// Values for Mac
-					mDepth = 4;	
-					message.setValueU32("format", GL_BGRA_EXT);
-					#ifdef __BIG_ENDIAN__
-						message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV );
-					#else
-						message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8);
-					#endif
-
-					// Pad texture width to a multiple of 32 bytes, to line up with cache lines.
-					message.setValueU32("padding", 32);
-				#endif
-				message.setValueS32("depth", mDepth);
-				message.setValueU32("internalformat", GL_RGB);
-				message.setValueBoolean("coords_opengl", true);	// true == use OpenGL-style coordinates, false == (0,0) is upper left.
-				message.setValueBoolean("allow_downsample", true);
-				sendMessage(message);
-			}
-			else if(message_name == "idle")
-			{
-				// no response is necessary here.
-				F64 time = message_in.getValueReal("time");
-				
-				// Convert time to milliseconds for update()
-				update((int)(time * 1000.0f));
-			}
-			else if(message_name == "cleanup")
-			{
-				// TODO: clean up here
-			}
-			else if(message_name == "shm_added")
-			{
-				SharedSegmentInfo info;
-				info.mAddress = message_in.getValuePointer("address");
-				info.mSize = (size_t)message_in.getValueS32("size");
-				std::string name = message_in.getValue("name");
-
-
-//				std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name
-//					<< ", size: " << info.mSize
-//					<< ", address: " << info.mAddress
-//					<< std::endl;
-
-				mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
-
-			}
-			else if(message_name == "shm_remove")
-			{
-				std::string name = message_in.getValue("name");
-
-//				std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl;
-
-				SharedSegmentMap::iterator iter = mSharedSegments.find(name);
-				if(iter != mSharedSegments.end())
-				{
-					if(mPixels == iter->second.mAddress)
-					{
-						// This is the currently active pixel buffer.  Make sure we stop drawing to it.
-						mPixels = NULL;
-						mTextureSegmentName.clear();
-						
-						// Make sure the movie GWorld is no longer pointed at the shared segment.
-						sizeChanged();						
-					}
-					mSharedSegments.erase(iter);
-				}
-				else
-				{
-//					std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl;
-				}
-
-				// Send the response so it can be cleaned up.
-				LLPluginMessage message("base", "shm_remove_response");
-				message.setValue("name", name);
-				sendMessage(message);
-			}
-			else
-			{
-//				std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl;
-			}
-		}
-		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
-		{
-			if(message_name == "size_change")
-			{
-				std::string name = message_in.getValue("name");
-				S32 width = message_in.getValueS32("width");
-				S32 height = message_in.getValueS32("height");
-				S32 texture_width = message_in.getValueS32("texture_width");
-				S32 texture_height = message_in.getValueS32("texture_height");
-
-				//std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl;
-
-				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
-				message.setValue("name", name);
-				message.setValueS32("width", width);
-				message.setValueS32("height", height);
-				message.setValueS32("texture_width", texture_width);
-				message.setValueS32("texture_height", texture_height);
-				sendMessage(message);
-
-				if(!name.empty())
-				{
-					// Find the shared memory region with this name
-					SharedSegmentMap::iterator iter = mSharedSegments.find(name);
-					if(iter != mSharedSegments.end())
-					{
-//						std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl;
-//						std::cerr << "%%%%  texture size is " << texture_width << " by " << texture_height << std::endl;
-
-						mPixels = (unsigned char*)iter->second.mAddress;
-						mTextureSegmentName = name;
-						mWidth = width;
-						mHeight = height;
-
-						mTextureWidth = texture_width;
-						mTextureHeight = texture_height;
-
-						mMediaSizeChanging = false;
-						
-						sizeChanged();
-						
-						update();
-					};
-				};
-			}
-			else if(message_name == "load_uri")
-			{
-				std::string uri = message_in.getValue("uri");
-				load( uri );
-				sendStatus();		
-			}
-			else if(message_name == "mouse_event")
-			{
-				std::string event = message_in.getValue("event");
-				S32 x = message_in.getValueS32("x");
-				S32 y = message_in.getValueS32("y");
-				
-				if(event == "down")
-				{
-					mouseDown(x, y);
-				}
-				else if(event == "up")
-				{
-					mouseUp(x, y);
-				}
-				else if(event == "move")
-				{
-					mouseMove(x, y);
-				};
-			};
-		}
-		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
-		{
-			if(message_name == "stop")
-			{
-				stop();
-			}
-			else if(message_name == "start")
-			{
-				F64 rate = 0.0;
-				if(message_in.hasValue("rate"))
-				{
-					rate = message_in.getValueReal("rate");
-				}
-				play(rate);
-			}
-			else if(message_name == "pause")
-			{
-				pause();
-			}
-			else if(message_name == "seek")
-			{
-				F64 time = message_in.getValueReal("time");
-				seek(time);
-			}
-			else if(message_name == "set_loop")
-			{
-				bool loop = message_in.getValueBoolean("loop");
-				mIsLooping = loop;
-			}
-			else if(message_name == "set_volume")
-			{
-				F64 volume = message_in.getValueReal("volume");
-				setVolume(volume);
-			}
-		}
-		else
-		{
-//			std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl;
-		};
-	};
-}
-
-int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
-{
-	MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data);
-	*plugin_send_func = MediaPluginQuickTime::staticReceiveMessage;
-	*plugin_user_data = (void*)self;
-
-	return 0;
-}
-
-#else // LL_QUICKTIME_ENABLED
-
-// Stubbed-out class with constructor/destructor (necessary or windows linker
-// will just think its dead code and optimize it all out)
-class MediaPluginQuickTime : public MediaPluginBase
-{
-public:
-	MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
-	~MediaPluginQuickTime();
-	/* virtual */ void receiveMessage(const char *message_string);
-};
-
-MediaPluginQuickTime::MediaPluginQuickTime(
-	LLPluginInstance::sendMessageFunction host_send_func,
-	void *host_user_data ) :
-	MediaPluginBase(host_send_func, host_user_data)
-{
-    // no-op
-}
-
-MediaPluginQuickTime::~MediaPluginQuickTime()
-{
-    // no-op
-}
-
-void MediaPluginQuickTime::receiveMessage(const char *message_string)
-{
-    // no-op 
-}
-
-// We're building without quicktime enabled.  Just refuse to initialize.
-int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
-{
-    return -1;
-}
-
-#endif // LL_QUICKTIME_ENABLED
+/**
+ * @file media_plugin_quicktime.cpp
+ * @brief QuickTime plugin for LLMedia API plugin system
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llgl.h"
+
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#if LL_QUICKTIME_ENABLED
+
+#if defined(LL_DARWIN)
+	#include <QuickTime/QuickTime.h>
+#elif defined(LL_WINDOWS)
+	#include "MacTypes.h"
+	#include "QTML.h"
+	#include "Movies.h"
+	#include "QDoffscreen.h"
+	#include "FixMath.h"
+	#include "QTLoadLibraryUtils.h"
+#endif
+
+// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginQuickTime : public MediaPluginBase
+{
+public:
+	MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+	~MediaPluginQuickTime();
+
+	/* virtual */ void receiveMessage(const char *message_string);
+
+private:
+
+	int mNaturalWidth;
+	int mNaturalHeight;
+	Movie mMovieHandle;
+	GWorldPtr mGWorldHandle;
+	ComponentInstance mMovieController;
+	int mCurVolume;
+	bool mMediaSizeChanging;
+	bool mIsLooping;
+	std::string mMovieTitle;
+	bool mReceivedTitle;
+	const int mMinWidth;
+	const int mMaxWidth;
+	const int mMinHeight;
+	const int mMaxHeight;
+	F64 mPlayRate;
+	std::string mNavigateURL;
+
+	enum ECommand {
+		COMMAND_NONE,
+		COMMAND_STOP,
+		COMMAND_PLAY,
+		COMMAND_FAST_FORWARD,
+		COMMAND_FAST_REWIND,
+		COMMAND_PAUSE,
+		COMMAND_SEEK,
+	};
+	ECommand mCommand;
+
+	// Override this to add current time and duration to the message
+	/*virtual*/ void setDirty(int left, int top, int right, int bottom)
+	{
+		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
+
+		message.setValueS32("left", left);
+		message.setValueS32("top", top);
+		message.setValueS32("right", right);
+		message.setValueS32("bottom", bottom);
+
+		if(mMovieHandle)
+		{
+			message.setValueReal("current_time", getCurrentTime());
+			message.setValueReal("duration", getDuration());
+			message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle)));
+		}
+
+		sendMessage(message);
+	}
+
+
+	static Rect rectFromSize(int width, int height)
+	{
+		Rect result;
+
+
+		result.left = 0;
+		result.top = 0;
+		result.right = width;
+		result.bottom = height;
+
+		return result;
+	}
+
+	Fixed getPlayRate(void)
+	{
+		Fixed result;
+		if(mPlayRate == 0.0f)
+		{
+			// Default to the movie's preferred rate
+			result = GetMoviePreferredRate(mMovieHandle);
+			if(result == 0)
+			{
+				// Don't return a 0 play rate, ever.
+				std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl;
+				result = X2Fix(1.0f);
+			}
+		}
+		else
+		{
+			result = X2Fix(mPlayRate);
+		}
+
+		return result;
+	}
+
+	void load( const std::string url )
+	{
+
+		if ( url.empty() )
+			return;
+
+		// Stop and unload any existing movie before starting another one.
+		unload();
+
+		setStatus(STATUS_LOADING);
+
+		//In case std::string::c_str() makes a copy of the url data,
+		//make sure there is memory to hold it before allocating memory for handle.
+		//if fails, NewHandleClear(...) should return NULL.
+		const char* url_string = url.c_str() ;
+		Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) );
+
+		if ( NULL == handle || noErr != MemError() || NULL == *handle )
+		{
+			setStatus(STATUS_ERROR);
+			return;
+		}
+
+		BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) );
+
+		OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType );
+		DisposeHandle( handle );
+		if ( noErr != err )
+		{
+			setStatus(STATUS_ERROR);
+			return;
+		};
+		
+		mNavigateURL = url;
+		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
+		message.setValue("uri", mNavigateURL);
+		sendMessage(message);
+
+		// do pre-roll actions (typically fired for streaming movies but not always)
+		PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this );
+
+		Rect movie_rect = rectFromSize(mWidth, mHeight);
+
+		// make a new movie controller
+		mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie );
+
+		// movie controller
+		MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this );
+
+		SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize );
+
+		// function that gets called when a frame is drawn
+		SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this );
+
+		setStatus(STATUS_LOADED);
+
+		sizeChanged();
+	};
+
+	bool unload()
+	{
+		// new movie and have to get title again
+		mReceivedTitle = false;
+
+		if ( mMovieHandle )
+		{
+			StopMovie( mMovieHandle );
+			if ( mMovieController )
+			{
+				MCMovieChanged( mMovieController, mMovieHandle );
+			};
+		};
+
+		if ( mMovieController )
+		{
+			MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this );
+			DisposeMovieController( mMovieController );
+			mMovieController = NULL;
+		};
+
+		if ( mMovieHandle )
+		{
+			SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this );
+			DisposeMovie( mMovieHandle );
+			mMovieHandle = NULL;
+		};
+
+		if ( mGWorldHandle )
+		{
+			DisposeGWorld( mGWorldHandle );
+			mGWorldHandle = NULL;
+		};
+
+		setStatus(STATUS_NONE);
+
+		return true;
+	}
+
+	bool navigateTo( const std::string url )
+	{
+		unload();
+		load( url );
+
+		return true;
+	};
+
+	bool sizeChanged()
+	{
+		if ( ! mMovieHandle )
+			return false;
+
+		// Check to see whether the movie's natural size has updated
+		{
+			int width, height;
+			getMovieNaturalSize(&width, &height);
+			if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight)))
+			{
+				mNaturalWidth = width;
+				mNaturalHeight = height;
+
+				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
+				message.setValue("name", mTextureSegmentName);
+				message.setValueS32("width", width);
+				message.setValueS32("height", height);
+				sendMessage(message);
+				//std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl;
+			}
+		}
+
+		// sanitize destination size
+		Rect dest_rect = rectFromSize(mWidth, mHeight);
+
+		// media depth won't change
+		int depth_bits = mDepth * 8;
+		long rowbytes = mDepth * mTextureWidth;
+
+		GWorldPtr old_gworld_handle = mGWorldHandle;
+
+		if(mPixels != NULL)
+		{
+			// We have pixels.  Set up a GWorld pointing at the texture.
+			OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
+			if ( noErr != result )
+			{
+				// TODO: unrecoverable??  throw exception?  return something?
+				return false;
+			}
+		}
+		else
+		{
+			// We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally.
+			Rect tempRect = rectFromSize(1, 1);
+			OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
+			if ( noErr != result )
+			{
+				// TODO: unrecoverable??  throw exception?  return something?
+				return false;
+			}
+		}
+
+		SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) );
+
+		// If the GWorld was already set up, delete it.
+		if(old_gworld_handle != NULL)
+		{
+			DisposeGWorld( old_gworld_handle );
+		}
+
+		// Set up the movie display matrix
+		{
+			// scale movie to fit rect and invert vertically to match opengl image format
+			MatrixRecord transform;
+			SetIdentityMatrix( &transform );	// transforms are additive so start from identify matrix
+			double scaleX = (double) mWidth / mNaturalWidth;
+			double scaleY = -1.0 * (double) mHeight / mNaturalHeight;
+			double centerX = mWidth / 2.0;
+			double centerY = mHeight / 2.0;
+			ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) );
+			SetMovieMatrix( mMovieHandle, &transform );
+		}
+
+		// update movie controller
+		if ( mMovieController )
+		{
+			MCSetControllerPort( mMovieController, mGWorldHandle );
+			MCPositionController( mMovieController, &dest_rect, &dest_rect,
+								  mcTopLeftMovie | mcPositionDontInvalidate );
+			MCMovieChanged( mMovieController, mMovieHandle );
+		}
+
+
+		// Emit event with size change so the calling app knows about it too
+		// TODO:
+		//LLMediaEvent event( this );
+		//mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event );
+
+		return true;
+	}
+	static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref )
+	{
+		Boolean result = false;
+
+		MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
+
+		switch( action )
+		{
+			// handle window resizing
+			case mcActionControllerSizeChanged:
+				// Ensure that the movie draws correctly at the new size
+				self->sizeChanged();
+				break;
+
+			// Block any movie controller actions that open URLs.
+			case mcActionLinkToURL:
+			case mcActionGetNextURL:
+			case mcActionLinkToURLExtended:
+				// Prevent the movie controller from handling the message
+				result = true;
+				break;
+
+			default:
+				break;
+		};
+
+		return result;
+	};
+
+	static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref )
+	{
+		MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
+
+		// IMPORTANT: typically, a consumer who is observing this event will set a flag
+		// when this event is fired then render later. Be aware that the media stream
+		// can change during this period - dimensions, depth, format etc.
+		//LLMediaEvent event( self );
+//		self->updateQuickTime();
+		// TODO ^^^
+
+
+		if ( self->mWidth > 0 && self->mHeight > 0 )
+			self->setDirty( 0, 0, self->mWidth, self->mHeight );
+
+		return noErr;
+	};
+
+	static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref )
+	{
+		MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
+
+		// TODO:
+		//LLMediaEvent event( self );
+		//self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event );
+		
+		// Send a "navigate complete" event.
+		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
+		message.setValue("uri", self->mNavigateURL);
+		message.setValueS32("result_code", 200);
+		message.setValue("result_string", "OK");
+		self->sendMessage(message);
+	};
+
+
+	void rewind()
+	{
+		GoToBeginningOfMovie( mMovieHandle );
+		MCMovieChanged( mMovieController, mMovieHandle );
+	};
+
+	bool processState()
+	{
+		if ( mCommand == COMMAND_PLAY )
+		{
+			if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE )
+			{
+				long state = GetMovieLoadState( mMovieHandle );
+
+				if ( state >= kMovieLoadStatePlaythroughOK )
+				{
+					// if the movie is at the end (generally because it reached it naturally)
+					// and we play is requested, jump back to the start of the movie.
+					// note: this is different from having loop flag set.
+					if ( IsMovieDone( mMovieHandle ) )
+					{
+						Fixed rate = X2Fix( 0.0 );
+						MCDoAction( mMovieController, mcActionPlay, (void*)rate );
+						rewind();
+					};
+
+					MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
+					MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
+					setStatus(STATUS_PLAYING);
+					mCommand = COMMAND_NONE;
+				};
+			};
+		}
+		else
+		if ( mCommand == COMMAND_STOP )
+		{
+			if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE )
+			{
+				if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
+				{
+					Fixed rate = X2Fix( 0.0 );
+					MCDoAction( mMovieController, mcActionPlay, (void*)rate );
+					rewind();
+
+					setStatus(STATUS_LOADED);
+					mCommand = COMMAND_NONE;
+				};
+			};
+		}
+		else
+		if ( mCommand == COMMAND_PAUSE )
+		{
+			if ( mStatus == STATUS_PLAYING )
+			{
+				if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
+				{
+					Fixed rate = X2Fix( 0.0 );
+					MCDoAction( mMovieController, mcActionPlay, (void*)rate );
+					setStatus(STATUS_PAUSED);
+					mCommand = COMMAND_NONE;
+				};
+			};
+		};
+
+		return true;
+	};
+
+	void play(F64 rate)
+	{
+		mPlayRate = rate;
+		mCommand = COMMAND_PLAY;
+	};
+
+	void stop()
+	{
+		mCommand = COMMAND_STOP;
+	};
+
+	void pause()
+	{
+		mCommand = COMMAND_PAUSE;
+	};
+
+	void getMovieNaturalSize(int *movie_width, int *movie_height)
+	{
+		Rect rect;
+
+		GetMovieNaturalBoundsRect( mMovieHandle, &rect );
+
+		int width  = ( rect.right - rect.left );
+		int height = ( rect.bottom - rect.top );
+
+		// make sure width and height fall in valid range
+		if ( width < mMinWidth )
+			width = mMinWidth;
+
+		if ( width > mMaxWidth )
+			width = mMaxWidth;
+
+		if ( height < mMinHeight )
+			height = mMinHeight;
+
+		if ( height > mMaxHeight )
+			height = mMaxHeight;
+
+		// return the new rect
+		*movie_width = width;
+		*movie_height = height;
+	}
+
+	void updateQuickTime(int milliseconds)
+	{
+		if ( ! mMovieHandle )
+			return;
+
+		if ( ! mMovieController )
+			return;
+
+		// service QuickTime
+		// Calling it this way doesn't have good behavior on Windows...
+//		MoviesTask( mMovieHandle, milliseconds );
+		// This was the original, but I think using both MoviesTask and MCIdle is redundant.  Trying with only MCIdle.
+//		MoviesTask( mMovieHandle, 0 );
+
+		MCIdle( mMovieController );
+
+		if ( ! mGWorldHandle )
+			return;
+
+		if ( mMediaSizeChanging )
+			return;
+
+		// update state machine
+		processState();
+
+		// see if title arrived and if so, update member variable with contents
+		checkTitle();
+		
+		// QT call to see if we are at the end - can't do with controller
+		if ( IsMovieDone( mMovieHandle ) )
+		{
+			// special code for looping - need to rewind at the end of the movie
+			if ( mIsLooping )
+			{
+				// go back to start
+				rewind();
+
+				if ( mMovieController )
+				{
+					// kick off new play
+					MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
+
+					// set the volume
+					MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
+				};
+			}
+			else
+			{
+				if(mStatus == STATUS_PLAYING)
+				{
+					setStatus(STATUS_DONE);
+				}
+			}
+		}
+
+	};
+
+	int getDataWidth() const
+	{
+		if ( mGWorldHandle )
+		{
+			int depth = mDepth;
+
+			if (depth < 1)
+				depth = 1;
+
+			// ALWAYS use the row bytes from the PixMap if we have a GWorld because
+			// sometimes it's not the same as mMediaDepth * mMediaWidth !
+			PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle );
+			return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth;
+		}
+		else
+		{
+			// TODO :   return LLMediaImplCommon::getaDataWidth();
+			return 0;
+		}
+	};
+
+	void seek( F64 time )
+	{
+		if ( mMovieController )
+		{
+			TimeRecord when;
+			when.scale = GetMovieTimeScale( mMovieHandle );
+			when.base = 0;
+
+			// 'time' is in (floating point) seconds.  The timebase time will be in 'units', where
+			// there are 'scale' units per second.
+			SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) );
+
+			when.value.hi = ( SInt32 )( raw_time >> 32 );
+			when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) );
+
+			MCDoAction( mMovieController, mcActionGoToTime, &when );
+		};
+	};
+
+	F64 getLoadedDuration() 	  	 
+	{ 	  	 
+		TimeValue duration; 	  	 
+		if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr) 	  	 
+		{ 	  	 
+			// If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie. 	  	 
+			duration = GetMovieDuration( mMovieHandle ); 	  	 
+		} 	  	 
+		TimeValue scale = GetMovieTimeScale( mMovieHandle ); 	  	 
+
+		return (F64)duration / (F64)scale; 	  	 
+	}; 	  	 
+
+	F64 getDuration()
+	{
+		TimeValue duration = GetMovieDuration( mMovieHandle );
+		TimeValue scale = GetMovieTimeScale( mMovieHandle );
+
+		return (F64)duration / (F64)scale;
+	};
+
+	F64 getCurrentTime()
+	{
+		TimeValue curr_time = GetMovieTime( mMovieHandle, 0 );
+		TimeValue scale = GetMovieTimeScale( mMovieHandle );
+
+		return (F64)curr_time / (F64)scale;
+	};
+
+	void setVolume( F64 volume )
+	{
+		mCurVolume = (short)(volume * ( double ) 0x100 );
+
+		if ( mMovieController )
+		{
+			MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
+		};
+	};
+
+	////////////////////////////////////////////////////////////////////////////////
+	//
+	void update(int milliseconds = 0)
+	{
+		updateQuickTime(milliseconds);
+	};
+
+	////////////////////////////////////////////////////////////////////////////////
+	//
+	void mouseDown( int x, int y )
+	{
+	};
+
+	////////////////////////////////////////////////////////////////////////////////
+	//
+	void mouseUp( int x, int y )
+	{
+	};
+
+	////////////////////////////////////////////////////////////////////////////////
+	//
+	void mouseMove( int x, int y )
+	{
+	};
+
+	////////////////////////////////////////////////////////////////////////////////
+	//
+	void keyPress( unsigned char key )
+	{
+	};
+
+	////////////////////////////////////////////////////////////////////////////////
+	// Grab movie title into mMovieTitle - should be called repeatedly
+	// until it returns true since movie title takes a while to become 
+	// available.
+	const bool getMovieTitle()
+	{
+		// grab meta data from movie
+		QTMetaDataRef media_data_ref;
+		OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref );
+		if ( noErr != result ) 
+			return false;
+
+		// look up "Display Name" in meta data
+		OSType meta_data_key = kQTMetaDataCommonKeyDisplayName;
+		QTMetaDataItem item = kQTMetaDataItemUninitialized;
+		result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard, 
+										0, kQTMetaDataKeyFormatCommon, 
+										(const UInt8 *)&meta_data_key, 
+										sizeof( meta_data_key ), &item );
+		if ( noErr != result ) 
+			return false;
+
+		// find the size of the title
+		ByteCount size;
+		result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size );
+		if ( noErr != result || size <= 0 ) 
+			return false;
+
+		// allocate some space and grab it
+		UInt8* item_data = new UInt8( size );
+		memset( item_data, 0, size * sizeof( UInt8* ) );
+		result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
+		if ( noErr != result ) 
+			return false;
+
+		// save it
+		mMovieTitle = std::string( (char* )item_data );
+
+		// clean up
+		delete [] item_data;
+
+		return true;
+	};
+
+	// called regularly to see if title changed
+	void checkTitle()
+	{
+		// we did already receive title so keep checking
+		if ( ! mReceivedTitle )
+		{
+			// grab title from movie meta data
+			if ( getMovieTitle() )
+			{
+				// pass back to host application
+				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+				message.setValue("name", mMovieTitle );
+				sendMessage( message );
+
+				// stop looking once we find a title for this movie.
+				// TODO: this may to be reset if movie title changes
+				// during playback but this is okay for now
+				mReceivedTitle = true;
+			};
+		};
+	};
+};
+
+MediaPluginQuickTime::MediaPluginQuickTime(
+	LLPluginInstance::sendMessageFunction host_send_func,
+	void *host_user_data ) :
+	MediaPluginBase(host_send_func, host_user_data),
+	mMinWidth( 0 ),
+	mMaxWidth( 2048 ),
+	mMinHeight( 0 ),
+	mMaxHeight( 2048 )
+{
+//	std::cerr << "MediaPluginQuickTime constructor" << std::endl;
+
+	mNaturalWidth = -1;
+	mNaturalHeight = -1;
+	mMovieHandle = 0;
+	mGWorldHandle = 0;
+	mMovieController = 0;
+	mCurVolume = 0x99;
+	mMediaSizeChanging = false;
+	mIsLooping = false;
+	mMovieTitle = std::string();
+	mReceivedTitle = false;
+	mCommand = COMMAND_NONE;
+	mPlayRate = 0.0f;
+	mStatus = STATUS_NONE;
+}
+
+MediaPluginQuickTime::~MediaPluginQuickTime()
+{
+//	std::cerr << "MediaPluginQuickTime destructor" << std::endl;
+
+	ExitMovies();
+
+#ifdef LL_WINDOWS
+	TerminateQTML();
+//		std::cerr << "QuickTime closing down" << std::endl;
+#endif
+}
+
+
+void MediaPluginQuickTime::receiveMessage(const char *message_string)
+{
+//	std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
+	LLPluginMessage message_in;
+
+	if(message_in.parse(message_string) >= 0)
+	{
+		std::string message_class = message_in.getClass();
+		std::string message_name = message_in.getName();
+		if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+		{
+			if(message_name == "init")
+			{
+				LLPluginMessage message("base", "init_response");
+				LLSD versions = LLSD::emptyMap();
+				versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+				// Normally a plugin would only specify one of these two subclasses, but this is a demo...
+				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
+				message.setValueLLSD("versions", versions);
+
+				#ifdef LL_WINDOWS
+
+				// QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime
+				// according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html
+				// The solution presented there appears to work.
+				QTLoadLibrary("qtcf.dll");
+
+				// main initialization for QuickTime - only required on Windows
+				OSErr result = InitializeQTML( 0L );
+				if ( result != noErr )
+				{
+					//TODO: If no QT on Windows, this fails - respond accordingly.
+				}
+				else
+				{
+					//std::cerr << "QuickTime initialized" << std::endl;
+				};
+				#endif
+
+				// required for both Windows and Mac
+				EnterMovies();
+
+				std::string plugin_version = "QuickTime media plugin, QuickTime version ";
+
+				long version = 0;
+				Gestalt( gestaltQuickTimeVersion, &version );
+				std::ostringstream codec( "" );
+				codec << std::hex << version << std::dec;
+				plugin_version += codec.str();
+				message.setValue("plugin_version", plugin_version);
+				sendMessage(message);
+
+				// Plugin gets to decide the texture parameters to use.
+				message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+				#if defined(LL_WINDOWS)
+					// Values for Windows
+					mDepth = 3;
+					message.setValueU32("format", GL_RGB);
+					message.setValueU32("type", GL_UNSIGNED_BYTE);
+
+					// We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even.
+					// Padding to a multiple of 3*32 guarantees it'll divide out properly.
+					message.setValueU32("padding", 32 * 3);
+				#else
+					// Values for Mac
+					mDepth = 4;
+					message.setValueU32("format", GL_BGRA_EXT);
+					#ifdef __BIG_ENDIAN__
+						message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV );
+					#else
+						message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8);
+					#endif
+
+					// Pad texture width to a multiple of 32 bytes, to line up with cache lines.
+					message.setValueU32("padding", 32);
+				#endif
+				message.setValueS32("depth", mDepth);
+				message.setValueU32("internalformat", GL_RGB);
+				message.setValueBoolean("coords_opengl", true);	// true == use OpenGL-style coordinates, false == (0,0) is upper left.
+				message.setValueBoolean("allow_downsample", true);
+				sendMessage(message);
+			}
+			else if(message_name == "idle")
+			{
+				// no response is necessary here.
+				F64 time = message_in.getValueReal("time");
+
+				// Convert time to milliseconds for update()
+				update((int)(time * 1000.0f));
+			}
+			else if(message_name == "cleanup")
+			{
+				// TODO: clean up here
+			}
+			else if(message_name == "shm_added")
+			{
+				SharedSegmentInfo info;
+				info.mAddress = message_in.getValuePointer("address");
+				info.mSize = (size_t)message_in.getValueS32("size");
+				std::string name = message_in.getValue("name");
+//				std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name
+//					<< ", size: " << info.mSize
+//					<< ", address: " << info.mAddress
+//					<< std::endl;
+
+				mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
+
+			}
+			else if(message_name == "shm_remove")
+			{
+				std::string name = message_in.getValue("name");
+
+//				std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl;
+
+				SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+				if(iter != mSharedSegments.end())
+				{
+					if(mPixels == iter->second.mAddress)
+					{
+						// This is the currently active pixel buffer.  Make sure we stop drawing to it.
+						mPixels = NULL;
+						mTextureSegmentName.clear();
+
+						// Make sure the movie GWorld is no longer pointed at the shared segment.
+						sizeChanged();
+					}
+					mSharedSegments.erase(iter);
+				}
+				else
+				{
+//					std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl;
+				}
+
+				// Send the response so it can be cleaned up.
+				LLPluginMessage message("base", "shm_remove_response");
+				message.setValue("name", name);
+				sendMessage(message);
+			}
+			else
+			{
+//				std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl;
+			}
+		}
+		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+		{
+			if(message_name == "size_change")
+			{
+				std::string name = message_in.getValue("name");
+				S32 width = message_in.getValueS32("width");
+				S32 height = message_in.getValueS32("height");
+				S32 texture_width = message_in.getValueS32("texture_width");
+				S32 texture_height = message_in.getValueS32("texture_height");
+
+				//std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl;
+
+				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+				message.setValue("name", name);
+				message.setValueS32("width", width);
+				message.setValueS32("height", height);
+				message.setValueS32("texture_width", texture_width);
+				message.setValueS32("texture_height", texture_height);
+				sendMessage(message);
+
+				if(!name.empty())
+				{
+					// Find the shared memory region with this name
+					SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+					if(iter != mSharedSegments.end())
+					{
+//						std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl;
+//						std::cerr << "%%%%  texture size is " << texture_width << " by " << texture_height << std::endl;
+
+						mPixels = (unsigned char*)iter->second.mAddress;
+						mTextureSegmentName = name;
+						mWidth = width;
+						mHeight = height;
+
+						mTextureWidth = texture_width;
+						mTextureHeight = texture_height;
+
+						mMediaSizeChanging = false;
+
+						sizeChanged();
+
+						update();
+					};
+				};
+			}
+			else if(message_name == "load_uri")
+			{
+				std::string uri = message_in.getValue("uri");
+				load( uri );
+				sendStatus();
+			}
+			else if(message_name == "mouse_event")
+			{
+				std::string event = message_in.getValue("event");
+				S32 x = message_in.getValueS32("x");
+				S32 y = message_in.getValueS32("y");
+
+				if(event == "down")
+				{
+					mouseDown(x, y);
+				}
+				else if(event == "up")
+				{
+					mouseUp(x, y);
+				}
+				else if(event == "move")
+				{
+					mouseMove(x, y);
+				};
+			};
+		}
+		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+		{
+			if(message_name == "stop")
+			{
+				stop();
+			}
+			else if(message_name == "start")
+			{
+				F64 rate = 0.0;
+				if(message_in.hasValue("rate"))
+				{
+					rate = message_in.getValueReal("rate");
+				}
+				play(rate);
+			}
+			else if(message_name == "pause")
+			{
+				pause();
+			}
+			else if(message_name == "seek")
+			{
+				F64 time = message_in.getValueReal("time");
+				seek(time);
+			}
+			else if(message_name == "set_loop")
+			{
+				bool loop = message_in.getValueBoolean("loop");
+				mIsLooping = loop;
+			}
+			else if(message_name == "set_volume")
+			{
+				F64 volume = message_in.getValueReal("volume");
+				setVolume(volume);
+			}
+		}
+		else
+		{
+//			std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl;
+		};
+	};
+}
+
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+	MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data);
+	*plugin_send_func = MediaPluginQuickTime::staticReceiveMessage;
+	*plugin_user_data = (void*)self;
+
+	return 0;
+}
+
+#else // LL_QUICKTIME_ENABLED
+
+// Stubbed-out class with constructor/destructor (necessary or windows linker
+// will just think its dead code and optimize it all out)
+class MediaPluginQuickTime : public MediaPluginBase
+{
+public:
+	MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+	~MediaPluginQuickTime();
+	/* virtual */ void receiveMessage(const char *message_string);
+};
+
+MediaPluginQuickTime::MediaPluginQuickTime(
+	LLPluginInstance::sendMessageFunction host_send_func,
+	void *host_user_data ) :
+	MediaPluginBase(host_send_func, host_user_data)
+{
+    // no-op
+}
+
+MediaPluginQuickTime::~MediaPluginQuickTime()
+{
+    // no-op
+}
+
+void MediaPluginQuickTime::receiveMessage(const char *message_string)
+{
+    // no-op
+}
+
+// We're building without quicktime enabled.  Just refuse to initialize.
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+    return -1;
+}
+
+#endif // LL_QUICKTIME_ENABLED
diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt
index d96477279d86207438fc8c9be9e44cb12feebc63..5bccd589d80de18d27311d7591971814997f087d 100644
--- a/indra/media_plugins/webkit/CMakeLists.txt
+++ b/indra/media_plugins/webkit/CMakeLists.txt
@@ -52,6 +52,14 @@ add_dependencies(media_plugin_webkit
   ${LLCOMMON_LIBRARIES}
 )
 
+if (WINDOWS)
+  set_target_properties(
+    media_plugin_webkit
+    PROPERTIES
+    LINK_FLAGS "/MANIFEST:NO"
+    )
+endif (WINDOWS)
+
 if (DARWIN)
   # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
   set_target_properties(
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index eb2457744ab5d67bd91832a421f26c7215274dcd..3ce8ff3deb826ed775d623fc2a187ac058e0725f 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -48,6 +48,18 @@
 #include <stdlib.h>
 #endif
 
+#if LL_WINDOWS
+	// *NOTE:Mani - This captures the module handle fo rthe dll. This is used below
+	// to get the path to this dll for webkit initialization.
+	// I don't know how/if this can be done with apr...
+	namespace {	HMODULE gModuleHandle;};
+	BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+	{
+		gModuleHandle = (HMODULE) hinstDLL;
+		return TRUE;
+	}
+#endif
+
 ////////////////////////////////////////////////////////////////////////////////
 //
 class MediaPluginWebKit : 
@@ -69,6 +81,9 @@ class MediaPluginWebKit :
 	bool	mCanCut;
 	bool	mCanCopy;
 	bool	mCanPaste;
+	int mLastMouseX;
+	int mLastMouseY;
+	bool mFirstFocus;
 	
 	////////////////////////////////////////////////////////////////////////////////
 	//
@@ -126,7 +141,31 @@ class MediaPluginWebKit :
 			return false;
 		}
 		std::string application_dir = std::string( cwd );
+
+#if LL_WINDOWS
+		//*NOTE:Mani - On windows, at least, the component path is the
+		// location of this dll's image file. 
+		std::string component_dir;
+		char dll_path[_MAX_PATH];
+		DWORD len = GetModuleFileNameA(gModuleHandle, (LPCH)&dll_path, _MAX_PATH);
+		while(len && dll_path[ len ] != ('\\') )
+		{
+			len--;
+		}
+		if(len >= 0)
+		{
+			dll_path[len] = 0;
+			component_dir = dll_path;
+		}
+		else
+		{
+			// *NOTE:Mani - This case should be an rare exception. 
+			// GetModuleFileNameA should always give you a full path, no?
+			component_dir = application_dir;
+		}
+#else
 		std::string component_dir = application_dir;
+#endif
 		std::string profileDir = application_dir + "/" + "browser_profile";		// cross platform?
 
 		// window handle - needed on Windows and must be app window.
@@ -147,7 +186,7 @@ class MediaPluginWebKit :
 
 #if LL_WINDOWS
 			// Enable plugins
-			LLQtWebKit::getInstance()->enablePlugins(false);
+			LLQtWebKit::getInstance()->enablePlugins(true);
 #elif LL_DARWIN
 			// Disable plugins
 			LLQtWebKit::getInstance()->enablePlugins(false);
@@ -168,14 +207,13 @@ class MediaPluginWebKit :
 			// don't flip bitmap
 			LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
 			
-			// Set the background color to black
-			LLQtWebKit::getInstance()->
 			// set background color to be black - mostly for initial login page
 			LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, 0x00, 0x00, 0x00 );
 
-			// go to the "home page"
 			// Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
-//			LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
+			// FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
+			// for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date.
+			LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
 
 			// set flag so we don't do this again
 			mBrowserInitialized = true;
@@ -272,7 +310,16 @@ class MediaPluginWebKit :
 		message.setValue("status", event.getStringValue());
 		sendMessage(message);
 	}
-	
+
+	////////////////////////////////////////////////////////////////////////////////
+	// virtual
+	void onTitleChange(const EventType& event)
+	{
+		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+		message.setValue("name", event.getStringValue());
+		sendMessage(message);
+	}
+
 	////////////////////////////////////////////////////////////////////////////////
 	// virtual
 	void onLocationChange(const EventType& event)
@@ -300,33 +347,30 @@ class MediaPluginWebKit :
 		message.setValue("uri", event.getStringValue());
 		sendMessage(message);
 	}
-
-	////////////////////////////////////////////////////////////////////////////////
-	//
-	void mouseDown( int x, int y )
-	{
-		LLQtWebKit::getInstance()->mouseDown( mBrowserWindowId, x, y );
-	};
-
-	////////////////////////////////////////////////////////////////////////////////
-	//
-	void mouseUp( int x, int y )
+	
+	LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers)
 	{
-		LLQtWebKit::getInstance()->mouseUp( mBrowserWindowId, x, y );
-		LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, true );
-		checkEditState();
-	};
+		int result = 0;
+		
+		if(modifiers.find("shift") != std::string::npos)
+			result |= LLQtWebKit::KM_MODIFIER_SHIFT;
 
-	////////////////////////////////////////////////////////////////////////////////
-	//
-	void mouseMove( int x, int y )
-	{
-		LLQtWebKit::getInstance()->mouseMove( mBrowserWindowId, x, y );
-	};
+		if(modifiers.find("alt") != std::string::npos)
+			result |= LLQtWebKit::KM_MODIFIER_ALT;
+		
+		if(modifiers.find("control") != std::string::npos)
+			result |= LLQtWebKit::KM_MODIFIER_CONTROL;
+		
+		if(modifiers.find("meta") != std::string::npos)
+			result |= LLQtWebKit::KM_MODIFIER_META;
+		
+		return (LLQtWebKit::EKeyboardModifier)result;
+	}
+	
 
 	////////////////////////////////////////////////////////////////////////////////
 	//
-	void keyPress( int key )
+	void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers)
 	{
 		int llqt_key;
 		
@@ -380,7 +424,7 @@ class MediaPluginWebKit :
 		
 		if(llqt_key != 0)
 		{
-			LLQtWebKit::getInstance()->keyPress( mBrowserWindowId, llqt_key );
+			LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, key_event, llqt_key, modifiers);
 		}
 
 		checkEditState();
@@ -388,7 +432,7 @@ class MediaPluginWebKit :
 
 	////////////////////////////////////////////////////////////////////////////////
 	//
-	void unicodeInput( const std::string &utf8str )
+	void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers)
 	{
 		LLWString wstr = utf8str_to_wstring(utf8str);
 		
@@ -397,7 +441,7 @@ class MediaPluginWebKit :
 		{
 //			std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl;
 			
-			LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i]);
+			LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers);
 		}
 
 		checkEditState();
@@ -449,6 +493,9 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_
 	mCanCut = false;
 	mCanCopy = false;
 	mCanPaste = false;
+	mLastMouseX = 0;
+	mLastMouseY = 0;
+	mFirstFocus = true;
 }
 
 MediaPluginWebKit::~MediaPluginWebKit()
@@ -633,66 +680,84 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
 			else if(message_name == "mouse_event")
 			{
 				std::string event = message_in.getValue("event");
-				S32 x = message_in.getValueS32("x");
-				S32 y = message_in.getValueS32("y");
-				// std::string modifiers = message.getValue("modifiers");
-	
+				S32 button = message_in.getValueS32("button");
+				mLastMouseX = message_in.getValueS32("x");
+				mLastMouseY = message_in.getValueS32("y");
+				std::string modifiers = message_in.getValue("modifiers");
+				
+				// Treat unknown mouse events as mouse-moves.
+				LLQtWebKit::EMouseEvent mouse_event = LLQtWebKit::ME_MOUSE_MOVE;
 				if(event == "down")
 				{
-					mouseDown(x, y);
-					//std::cout << "Mouse down at " << x << " x " << y << std::endl;
+					mouse_event = LLQtWebKit::ME_MOUSE_DOWN;
 				}
 				else if(event == "up")
 				{
-					mouseUp(x, y);
-					//std::cout << "Mouse up at " << x << " x " << y << std::endl;
+					mouse_event = LLQtWebKit::ME_MOUSE_UP;
 				}
-				else if(event == "move")
+				else if(event == "double_click")
 				{
-					mouseMove(x, y);
-					//std::cout << ">>>>>>>>>>>>>>>>>>>> Mouse move at " << x << " x " << y << std::endl;
+					mouse_event = LLQtWebKit::ME_MOUSE_DOUBLE_CLICK;
 				}
+				
+				LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, mouse_event, button, mLastMouseX, mLastMouseY, decodeModifiers(modifiers));
+				checkEditState();
 			}
 			else if(message_name == "scroll_event")
 			{
-				// S32 x = message_in.getValueS32("x");
+				S32 x = message_in.getValueS32("x");
 				S32 y = message_in.getValueS32("y");
-				// std::string modifiers = message.getValue("modifiers");
+				std::string modifiers = message_in.getValue("modifiers");
+				
+				// Incoming scroll events are adjusted so that 1 detent is approximately 1 unit.
+				// Qt expects 1 detent to be 120 units.
+				// It also seems that our y scroll direction is inverted vs. what Qt expects.
 				
-				// We currently ignore horizontal scrolling.
-				// The scroll values are roughly 1 per wheel click, so we need to magnify them by some factor.
-				// Arbitrarily, I choose 16.
-				y *= 16;
-				LLQtWebKit::getInstance()->scrollByLines(mBrowserWindowId, y);
+				x *= 120;
+				y *= -120;
+				
+				LLQtWebKit::getInstance()->scrollWheelEvent(mBrowserWindowId, mLastMouseX, mLastMouseY, x, y, decodeModifiers(modifiers));
 			}
 			else if(message_name == "key_event")
 			{
 				std::string event = message_in.getValue("event");
-
-				// act on "key down" or "key repeat"
-				if ( (event == "down") || (event == "repeat") )
+				S32 key = message_in.getValueS32("key");
+				std::string modifiers = message_in.getValue("modifiers");
+				
+				// Treat unknown events as key-up for safety.
+				LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP;
+				if(event == "down")
 				{
-					S32 key = message_in.getValueS32("key");
-					keyPress( key );
-				};
+					key_event = LLQtWebKit::KE_KEY_DOWN;
+				}
+				else if(event == "repeat")
+				{
+					key_event = LLQtWebKit::KE_KEY_REPEAT;
+				}
+				
+				keyEvent(key_event, key, decodeModifiers(modifiers));
 			}
 			else if(message_name == "text_event")
 			{
 				std::string text = message_in.getValue("text");
+				std::string modifiers = message_in.getValue("modifiers");
 				
-				unicodeInput(text);
+				unicodeInput(text, decodeModifiers(modifiers));
 			}
 			if(message_name == "edit_cut")
 			{
 				LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT );
+				checkEditState();
 			}
 			if(message_name == "edit_copy")
 			{
 				LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY );
+				checkEditState();
 			}
 			if(message_name == "edit_paste")
 			{
 				LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE );
+				checkEditState();
 			}
 			else
 			{
@@ -705,6 +770,15 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
 			{
 				bool val = message_in.getValueBoolean("focused");
 				LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val );
+				
+				if(mFirstFocus && val)
+				{
+					// On the first focus, post a tab key event.  This fixes a problem with initial focus.
+					std::string empty;
+					keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty));
+					keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty));
+					mFirstFocus = false;
+				}
 			}
 			else if(message_name == "clear_cache")
 			{
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3cee6394e036dc8ea12d03b9c56f532767e46110..4a19293f99a39a050a61f94bc29a81e2aff0de7d 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -36,11 +36,9 @@ include(UI)
 include(UnixInstall)
 include(LLKDU)
 include(ViewerMiscLibs)
+include(LLLogin)
 include(GLOD)
-
-if (WINDOWS)
-    include(CopyWinLibs)
-endif (WINDOWS)
+include(CMakeCopyIfDifferent)
 
 include_directories(
     ${DBUSGLIB_INCLUDE_DIRS}
@@ -63,17 +61,19 @@ include_directories(
     ${LLXUIXML_INCLUDE_DIRS}
     ${LSCRIPT_INCLUDE_DIRS}
     ${LSCRIPT_INCLUDE_DIRS}/lscript_compile
+    ${LLLOGIN_INCLUDE_DIRS}
     ${LIBS_PREBUILT_DIR}/include/collada
     ${LIBS_PREBUILT_DIR}/include/collada/1.4
     )
 
 set(viewer_SOURCE_FILES
-    llaccordionctrltab.cpp
     llaccordionctrl.cpp
+    llaccordionctrltab.cpp
     llagent.cpp
     llagentaccess.cpp
     llagentdata.cpp
     llagentlanguage.cpp
+    llagentlistener.cpp
     llagentpicksinfo.cpp
     llagentpilot.cpp
     llagentui.cpp
@@ -81,8 +81,9 @@ set(viewer_SOURCE_FILES
     llanimstatelabels.cpp
     llappearancemgr.cpp
     llappviewer.cpp
-    llassetuploadresponders.cpp
+    llappviewerlistener.cpp
     llassetuploadqueue.cpp
+    llassetuploadresponders.cpp
     llaudiosourcevo.cpp
     llavataractions.cpp
     llavatariconctrl.cpp
@@ -98,8 +99,8 @@ set(viewer_SOURCE_FILES
     llcaphttpsender.cpp
     llchannelmanager.cpp
     llchatbar.cpp
-    llchatitemscontainerctrl.cpp
     llchathistory.cpp
+    llchatitemscontainerctrl.cpp
     llchatmsgbox.cpp
     llchiclet.cpp
     llclassifiedinfo.cpp
@@ -119,10 +120,10 @@ set(viewer_SOURCE_FILES
     lldirpicker.cpp
     lldndbutton.cpp
     lldrawable.cpp
+    lldrawpool.cpp
     lldrawpoolalpha.cpp
     lldrawpoolavatar.cpp
     lldrawpoolbump.cpp
-    lldrawpool.cpp
     lldrawpoolground.cpp
     lldrawpoolsimple.cpp
     lldrawpoolsky.cpp
@@ -154,8 +155,8 @@ set(viewer_SOURCE_FILES
     llfloaterbuildoptions.cpp
     llfloaterbulkpermission.cpp
     llfloaterbump.cpp
-    llfloaterbuycontents.cpp
     llfloaterbuy.cpp
+    llfloaterbuycontents.cpp
     llfloaterbuycurrency.cpp
     llfloaterbuyland.cpp
     llfloatercall.cpp
@@ -166,8 +167,8 @@ set(viewer_SOURCE_FILES
     llfloatercustomize.cpp
     llfloaterdaycycle.cpp
     llfloaterenvsettings.cpp
-    llfloaterfriends.cpp
     llfloaterfonttest.cpp
+    llfloaterfriends.cpp
     llfloatergesture.cpp
     llfloatergodtools.cpp
     llfloatergroupinvite.cpp
@@ -175,8 +176,6 @@ set(viewer_SOURCE_FILES
     llfloaterhandler.cpp
     llfloaterhardwaresettings.cpp
     llfloaterhelpbrowser.cpp
-    llfloatermediabrowser.cpp
-    llfloatermediasettings.cpp
     llfloaterhud.cpp
     llfloaterimagepreview.cpp
     llfloaterimportcollada.cpp
@@ -187,9 +186,12 @@ set(viewer_SOURCE_FILES
     llfloaterland.cpp
     llfloaterlandholdings.cpp
     llfloatermap.cpp
+    llfloatermediabrowser.cpp
+    llfloatermediasettings.cpp
     llfloatermemleak.cpp
     llfloatermodelpreview.cpp
     llfloaternamedesc.cpp
+	llfloaternearbymedia.cpp
     llfloaternotificationsconsole.cpp
     llfloateropenobject.cpp
     llfloaterparcel.cpp
@@ -232,8 +234,8 @@ set(viewer_SOURCE_FILES
     llgroupmgr.cpp
     llgroupnotify.cpp
     llhomelocationresponder.cpp
-    llhudeffectbeam.cpp
     llhudeffect.cpp
+    llhudeffectbeam.cpp
     llhudeffectlookat.cpp
     llhudeffectpointat.cpp
     llhudeffecttrail.cpp
@@ -243,11 +245,11 @@ set(viewer_SOURCE_FILES
     llhudrender.cpp
     llhudtext.cpp
     llhudview.cpp
+    llimcontrolpanel.cpp
     llimfloater.cpp
     llimhandler.cpp
     llimpanel.cpp
     llimview.cpp
-    llimcontrolpanel.cpp
     llinspect.cpp
     llinspectavatar.cpp
     llinspectgroup.cpp
@@ -265,9 +267,9 @@ set(viewer_SOURCE_FILES
     lllocaltextureobject.cpp
     lllocationhistory.cpp
     lllocationinputctrl.cpp
-    llurllineeditorctrl.cpp
     lllogchat.cpp
     llloginhandler.cpp
+    lllogininstance.cpp
     llmanip.cpp
     llmaniprotate.cpp
     llmanipscale.cpp
@@ -316,8 +318,8 @@ set(viewer_SOURCE_FILES
     llpanelgrouplandmoney.cpp
     llpanelgroupnotices.cpp
     llpanelgrouproles.cpp
-    llpanelinventory.cpp
     llpanelimcontrolpanel.cpp
+    llpanelinventory.cpp
     llpanelland.cpp
     llpanellandaudio.cpp
     llpanellandmarks.cpp
@@ -326,11 +328,10 @@ set(viewer_SOURCE_FILES
     llpanellookinfo.cpp
     llpanellooks.cpp
     llpanelmedia.cpp
-    llpanelmediahud.cpp
-    llpanelmeprofile.cpp
     llpanelmediasettingsgeneral.cpp
-    llpanelmediasettingssecurity.cpp
     llpanelmediasettingspermissions.cpp
+    llpanelmediasettingssecurity.cpp
+    llpanelmeprofile.cpp
     llpanelobject.cpp
     llpanelpeople.cpp
     llpanelpeoplemenus.cpp
@@ -341,8 +342,10 @@ set(viewer_SOURCE_FILES
     llpanelplaceinfo.cpp
     llpanelplaces.cpp
     llpanelplacestab.cpp
+    llpanelprimmediacontrols.cpp
     llpanelprofile.cpp
     llpanelprofileview.cpp
+    llpanelshower.cpp
     llpanelteleporthistory.cpp
     llpanelvolume.cpp
     llparcelselection.cpp
@@ -351,8 +354,8 @@ set(viewer_SOURCE_FILES
     llplacesinventorybridge.cpp
     llpolymesh.cpp
     llpolymorph.cpp
-    llpreviewanim.cpp
     llpreview.cpp
+    llpreviewanim.cpp
     llpreviewgesture.cpp
     llpreviewnotecard.cpp
     llpreviewscript.cpp
@@ -374,9 +377,9 @@ set(viewer_SOURCE_FILES
     llsky.cpp
     llslurl.cpp
     llspatialpartition.cpp
+    llspeakers.cpp
     llsplitbutton.cpp
     llsprite.cpp
-    llsrv.cpp
     llstartup.cpp
     llstatusbar.cpp
     llstylemap.cpp
@@ -401,10 +404,10 @@ set(viewer_SOURCE_FILES
     lltoastimpanel.cpp
     lltoastnotifypanel.cpp
     lltoastpanel.cpp
+    lltool.cpp
     lltoolbar.cpp
     lltoolbrush.cpp
     lltoolcomp.cpp
-    lltool.cpp
     lltooldraganddrop.cpp
     lltoolface.cpp
     lltoolfocus.cpp
@@ -423,19 +426,21 @@ set(viewer_SOURCE_FILES
     lltracker.cpp
     lltransientdockablefloater.cpp
     lltransientfloatermgr.cpp
+    lluilistener.cpp
     lluploaddialog.cpp
     llurl.cpp
     llurldispatcher.cpp
     llurlhistory.cpp
+    llurllineeditorctrl.cpp
     llurlsimstring.cpp
     llurlwhitelist.cpp
-    lluserauth.cpp
     llvectorperfoptions.cpp
     llviewchildren.cpp
     llviewerassetstorage.cpp
     llvieweraudio.cpp
     llviewercamera.cpp
     llviewercontrol.cpp
+    llviewercontrollistener.cpp
     llviewerdisplay.cpp
     llviewerfloaterreg.cpp
     llviewergenericmessage.cpp
@@ -443,18 +448,18 @@ set(viewer_SOURCE_FILES
     llviewerhelp.cpp
     llviewerhelputil.cpp
     llviewerinventory.cpp
-    llviewerjointattachment.cpp
     llviewerjoint.cpp
+    llviewerjointattachment.cpp
     llviewerjointmesh.cpp
-    llviewerjointmesh_sse2.cpp
     llviewerjointmesh_sse.cpp
+    llviewerjointmesh_sse2.cpp
     llviewerjointmesh_vec.cpp
     llviewerjoystick.cpp
     llviewerkeyboard.cpp
     llviewerlayer.cpp
     llviewermedia.cpp
-    llviewermediafocus.cpp
     llviewermedia_streamingaudio.cpp
+    llviewermediafocus.cpp
     llviewermenu.cpp
     llviewermenufile.cpp
     llviewermessage.cpp
@@ -477,6 +482,7 @@ set(viewer_SOURCE_FILES
     llviewerthrottle.cpp
     llviewervisualparam.cpp
     llviewerwindow.cpp
+    llviewerwindowlistener.cpp
     llvlcomposition.cpp
     llvlmanager.cpp
     llvoavatar.cpp
@@ -486,10 +492,11 @@ set(viewer_SOURCE_FILES
     llvoclouds.cpp
     llvograss.cpp
     llvoground.cpp
+    llvoicechannel.cpp
     llvoiceclient.cpp
+    llvoicecontrolpanel.cpp
     llvoiceremotectrl.cpp
     llvoicevisualizer.cpp
-    llvoicecontrolpanel.cpp
     llvoinventorylistener.cpp
     llvopartgroup.cpp
     llvosky.cpp
@@ -514,6 +521,7 @@ set(viewer_SOURCE_FILES
     llworld.cpp
     llworldmap.cpp
     llworldmapview.cpp
+    llxmlrpclistener.cpp
     llxmlrpctransaction.cpp
     noise.cpp
     pipeline.cpp
@@ -539,23 +547,25 @@ endif (LINUX)
 set(viewer_HEADER_FILES
     CMakeLists.txt
     ViewerInstall.cmake
-    llaccordionctrltab.h
     llaccordionctrl.h
+    llaccordionctrltab.h
     llagent.h
     llagentaccess.h
     llagentdata.h
     llagentlanguage.h
+    llagentlistener.h
     llagentpicksinfo.h
     llagentpilot.h
     llagentui.h
     llagentwearables.h
     llanimstatelabels.h
     llappearance.h
+    llappearancemgr.h
     llappviewer.h
-    llassetuploadresponders.h
+    llappviewerlistener.h
     llassetuploadqueue.h
+    llassetuploadresponders.h
     llaudiosourcevo.h
-    llappearancemgr.h
     llavataractions.h
     llavatariconctrl.h
     llavatarlist.h
@@ -571,8 +581,8 @@ set(viewer_HEADER_FILES
     llcaphttpsender.h
     llchannelmanager.h
     llchatbar.h
-    llchatitemscontainerctrl.h
     llchathistory.h
+    llchatitemscontainerctrl.h
     llchatmsgbox.h
     llchiclet.h
     llclassifiedinfo.h
@@ -649,8 +659,6 @@ set(viewer_HEADER_FILES
     llfloaterhandler.h
     llfloaterhardwaresettings.h
     llfloaterhelpbrowser.h
-    llfloatermediabrowser.h
-    llfloatermediasettings.h
     llfloaterhud.h
     llfloaterimagepreview.h
     llfloaterimportcollada.h
@@ -661,17 +669,20 @@ set(viewer_HEADER_FILES
     llfloaterland.h
     llfloaterlandholdings.h
     llfloatermap.h
+    llfloatermediabrowser.h
+    llfloatermediasettings.h
     llfloatermemleak.h
     llfloatermodelpreview.h
     llfloaternamedesc.h
+	llfloaternearbymedia.h
     llfloaternotificationsconsole.h
     llfloateropenobject.h
     llfloaterparcel.h
     llfloaterpay.h
+    llfloaterperms.h
     llfloaterpostcard.h
     llfloaterpostprocess.h
     llfloaterpreference.h
-    llfloaterperms.h
     llfloaterproperties.h
     llfloaterregioninfo.h
     llfloaterreporter.h
@@ -717,12 +728,12 @@ set(viewer_HEADER_FILES
     llhudrender.h
     llhudtext.h
     llhudview.h
+    llimcontrolpanel.h
     llimfloater.h
     llimpanel.h
     llimview.h
-    llimcontrolpanel.h
-    llinspectavatar.h
     llinspect.h
+    llinspectavatar.h
     llinspectgroup.h
     llinspectobject.h
     llinventorybridge.h
@@ -739,14 +750,15 @@ set(viewer_HEADER_FILES
     lllocaltextureobject.h
     lllocationhistory.h
     lllocationinputctrl.h
-    llurllineeditorctrl.h
     lllogchat.h
     llloginhandler.h
+    lllogininstance.h
     llmanip.h
     llmaniprotate.h
     llmanipscale.h
     llmaniptranslate.h
     llmapresponders.h
+    llmediactrl.h
     llmediadataclient.h
     llmediaremotectrl.h
     llmemoryview.h
@@ -786,8 +798,8 @@ set(viewer_HEADER_FILES
     llpanelgrouplandmoney.h
     llpanelgroupnotices.h
     llpanelgrouproles.h
-    llpanelinventory.h
     llpanelimcontrolpanel.h
+    llpanelinventory.h
     llpanelland.h
     llpanellandaudio.h
     llpanellandmarks.h
@@ -796,11 +808,10 @@ set(viewer_HEADER_FILES
     llpanellookinfo.h
     llpanellooks.h
     llpanelmedia.h
-    llpanelmediahud.h
-    llpanelmeprofile.h
     llpanelmediasettingsgeneral.h
-    llpanelmediasettingssecurity.h
     llpanelmediasettingspermissions.h
+    llpanelmediasettingssecurity.h
+    llpanelmeprofile.h
     llpanelobject.h
     llpanelpeople.h
     llpanelpeoplemenus.h
@@ -811,8 +822,10 @@ set(viewer_HEADER_FILES
     llpanelplaceinfo.h
     llpanelplaces.h
     llpanelplacestab.h
+    llpanelprimmediacontrols.h
     llpanelprofile.h
     llpanelprofileview.h
+    llpanelshower.h
     llpanelteleporthistory.h
     llpanelvolume.h
     llparcelselection.h
@@ -835,9 +848,9 @@ set(viewer_HEADER_FILES
     llremoteparcelrequest.h
     llresourcedata.h
     llrootview.h
+    llsavedsettingsglue.h
     llscreenchannel.h
     llscrollingpanelparam.h
-    llsavedsettingsglue.h
     llsearchcombobox.h
     llsearchhistory.h
     llselectmgr.h
@@ -846,9 +859,9 @@ set(viewer_HEADER_FILES
     llsky.h
     llslurl.h
     llspatialpartition.h
+    llspeakers.h
     llsplitbutton.h
     llsprite.h
-    llsrv.h
     llstartup.h
     llstatusbar.h
     llstylemap.h
@@ -897,13 +910,14 @@ set(viewer_HEADER_FILES
     lltransientdockablefloater.h
     lltransientfloatermgr.h
     lluiconstants.h
+    lluilistener.h
     lluploaddialog.h
     llurl.h
     llurldispatcher.h
     llurlhistory.h
+    llurllineeditorctrl.h
     llurlsimstring.h
     llurlwhitelist.h
-    lluserauth.h
     llvectorperfoptions.h
     llviewchildren.h
     llviewerassetstorage.h
@@ -911,6 +925,7 @@ set(viewer_HEADER_FILES
     llviewerbuild.h
     llviewercamera.h
     llviewercontrol.h
+    llviewercontrollistener.h
     llviewerdisplay.h
     llviewerfloaterreg.h
     llviewergenericmessage.h
@@ -924,8 +939,8 @@ set(viewer_HEADER_FILES
     llviewerkeyboard.h
     llviewerlayer.h
     llviewermedia.h
-    llviewermediaobserver.h
     llviewermediafocus.h
+    llviewermediaobserver.h
     llviewermenu.h
     llviewermenufile.h
     llviewermessage.h
@@ -949,6 +964,7 @@ set(viewer_HEADER_FILES
     llviewerthrottle.h
     llviewervisualparam.h
     llviewerwindow.h
+    llviewerwindowlistener.h
     llvlcomposition.h
     llvlmanager.h
     llvoavatar.h
@@ -958,10 +974,11 @@ set(viewer_HEADER_FILES
     llvoclouds.h
     llvograss.h
     llvoground.h
+    llvoicechannel.h
     llvoiceclient.h
+    llvoicecontrolpanel.h
     llvoiceremotectrl.h
     llvoicevisualizer.h
-    llvoicecontrolpanel.h
     llvoinventorylistener.h
     llvopartgroup.h
     llvosky.h
@@ -979,7 +996,6 @@ set(viewer_HEADER_FILES
     llwearabledictionary.h
     llwearablelist.h
     llweb.h
-    llmediactrl.h
     llwind.h
     llwindebug.h
     llwlanimator.h
@@ -989,6 +1005,7 @@ set(viewer_HEADER_FILES
     llworld.h
     llworldmap.h
     llworldmapview.h
+    llxmlrpclistener.h
     llxmlrpctransaction.h
     macmain.h
     noise.h
@@ -1145,7 +1162,6 @@ if (WINDOWS)
         comdlg32
         ${DINPUT_LIBRARY}
         ${DXGUID_LIBRARY}
-        fmodvc
         kernel32
         libboost_system
         odbc32
@@ -1190,6 +1206,15 @@ file(GLOB DEFAULT_WIDGET_FILE_GLOB_LIST
      ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/widgets/*.xml)
 list(APPEND viewer_XUI_FILES ${DEFAULT_WIDGET_FILE_GLOB_LIST})
 
+file(GLOB SILVER_XUI_FILE_GLOB_LIST
+     ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/*.xml)
+list(APPEND viewer_XUI_FILES ${SILVER_XUI_FILE_GLOB_LIST})
+
+# Cannot append empty lists in CMake, wait until we have files here.
+#file(GLOB SILVER_WIDGET_FILE_GLOB_LIST
+#     ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/widgets/*.xml)
+#list(APPEND viewer_XUI_FILES ${SILVER_WIDGET_FILE_GLOB_LIST})
+
 list(SORT viewer_XUI_FILES)
 
 source_group("XUI Files" FILES ${viewer_XUI_FILES})
@@ -1264,23 +1289,23 @@ endif (OPENAL)
 if (FMOD)
   set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD")
 
-  if (NOT WINDOWS)
+  if (DARWIN)
     set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp)
     add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES})
-    set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY})
-    if (DARWIN)
-      list(APPEND fmodwrapper_needed_LIBRARIES ${CARBON_LIBRARY})
-      set_target_properties(
-        fmodwrapper
-        PROPERTIES
-        BUILD_WITH_INSTALL_RPATH 1
-        INSTALL_NAME_DIR "@executable_path/../Resources"
-        LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp"
-        )
-    endif (DARWIN)
+    set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY})
+    set_target_properties(
+      fmodwrapper
+      PROPERTIES
+      BUILD_WITH_INSTALL_RPATH 1
+      INSTALL_NAME_DIR "@executable_path/../Resources"
+      LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp"
+      )
     set(FMODWRAPPER_LIBRARY fmodwrapper)
     target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES})
-  endif (NOT WINDOWS)
+  else (DARWIN)
+    # fmodwrapper unnecessary on linux or windows
+    set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY})
+  endif (DARWIN)
 endif (FMOD)
 
 set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
@@ -1301,6 +1326,11 @@ if (LLKDU_LIBRARY)
   add_dependencies(${VIEWER_BINARY_NAME} ${LLKDU_LIBRARY})
 endif (LLKDU_LIBRARY)
 
+# add package files
+file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST
+     ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py)
+list(APPEND EVENT_HOST_SCRIPTS ${EVENT_HOST_SCRIPT_GLOB_LIST})
+
 set(PACKAGE OFF CACHE BOOL
     "Add a package target that builds an installer package.")
 
@@ -1357,7 +1387,28 @@ if (WINDOWS)
         COMMENT "Copying message.xml to the runtime folder."
         )
        
-    add_dependencies(${VIEWER_BINARY_NAME} copy_win_libs)
+    if(WINDOWS)
+      # Copy Win Libs...
+      # This happens at build time, not config time. We can't glob files in this cmake.
+      # *FIX:Mani Write a sub script to glob the files...
+      # *FIX:Mani Use actually dependencies rather than bulk copy.
+      add_custom_command(
+        TARGET ${VIEWER_BINARY_NAME} PRE_BUILD
+        COMMAND ${CMAKE_COMMAND}
+        ARGS
+          -E
+          copy_directory
+          ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}
+          ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
+        COMMENT "Copying staged dlls."
+        )
+
+      add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon)
+      if(LLKDU_LIBRARY)
+	# kdu may not exist!
+	add_dependencies(${VIEWER_BINARY_NAME} llkdu)
+      endif(LLKDU_LIBRARY)
+    endif(WINDOWS)    
 
     if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
       add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
@@ -1383,8 +1434,29 @@ if (WINDOWS)
     add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit)
 
     if (PACKAGE)
-      add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat)
+      add_custom_command(
+          OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2
+          COMMAND ${PYTHON_EXECUTABLE}
+          ARGS
+            ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/..
+            ${CMAKE_CURRENT_BINARY_DIR}
+            ${CMAKE_CFG_INTDIR}
+
+          DEPENDS 
+            lleventhost 
+            ${EVENT_HOST_SCRIPTS}
+            ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py)
+
+      add_custom_target(package ALL 
+          DEPENDS 
+            ${CMAKE_CFG_INTDIR}/touched.bat)
+            # temporarily disable packaging of event_host until hg subrepos get
+            # sorted out on the parabuild cluster...
+            #${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2)
       add_dependencies(package windows-updater windows-crash-logger)
+
+
     endif (PACKAGE)
 endif (WINDOWS)
 
@@ -1422,6 +1494,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
     ${WINDOWS_LIBRARIES}
     ${XMLRPCEPI_LIBRARIES}
     ${ELFIO_LIBRARIES}
+    ${LLLOGIN_LIBRARIES}
     ${GOOGLE_PERFTOOLS_LIBRARIES}
     )
 
@@ -1555,7 +1628,9 @@ include(LLAddBuildTest)
 SET(viewer_TEST_SOURCE_FILES
   llagentaccess.cpp
   lldateutil.cpp
+  llmediadataclient.cpp
   llviewerhelputil.cpp
+  lllogininstance.cpp
   )
 set_source_files_properties(
   ${viewer_TEST_SOURCE_FILES}
@@ -1572,6 +1647,7 @@ set(test_libs
   ${LLVFS_LIBRARIES}
   ${LLMATH_LIBRARIES}
   ${LLCOMMON_LIBRARIES} 
+  ${GOOGLEMOCK_LIBRARIES}
   )
 
 LL_ADD_INTEGRATION_TEST(llcapabilitylistener 
@@ -1586,6 +1662,16 @@ LL_ADD_INTEGRATION_TEST(llcapabilitylistener
 
 # Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py
 if (WINDOWS)
+  add_custom_command(
+      TARGET ${VIEWER_BINARY_NAME} POST_BUILD
+      COMMAND ${CMAKE_COMMAND}
+      ARGS
+        -E
+        make_directory
+        ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin
+      COMMENT "Creating llplugin dir."
+      )
+
   get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION)
   add_custom_command(
       TARGET ${VIEWER_BINARY_NAME} POST_BUILD
@@ -1621,5 +1707,72 @@ if (WINDOWS)
           ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin
         COMMENT "Copying Quicktime Plugin to the runtime folder."
         )
+
+  #*******************************
+  # Copy media plugin support dlls
+  # Debug config runtime files required for the plugins
+  set(plugins_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
+  set(plugins_debug_files
+    libeay32.dll
+    qtcored4.dll
+    qtguid4.dll
+    qtnetworkd4.dll
+    qtopengld4.dll
+    qtwebkitd4.dll
+    ssleay32.dll
+    )
+  copy_if_different(
+    ${plugins_debug_src_dir}
+    "${CMAKE_CURRENT_BINARY_DIR}/Debug/llplugin"
+    out_targets
+    ${plugins_debug_files}
+    )
+  set(media_plugin_targets ${media_plugin_targets} ${out_targets})
+  
+  # Release & ReleaseDebInfo config runtime files required for the plugins
+  set(plugins_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
+  set(plugins_release_files
+    libeay32.dll
+    qtcore4.dll
+    qtgui4.dll
+    qtnetwork4.dll
+    qtopengl4.dll
+    qtwebkit4.dll
+    ssleay32.dll
+    )
+  copy_if_different(
+    ${plugins_release_src_dir}
+    "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin"
+    out_targets
+    ${plugins_release_files}
+    )
+  set(media_plugin_targets ${media_plugin_targets} ${out_targets})
+
+  copy_if_different(
+    ${plugins_release_src_dir}
+    "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin"
+    out_targets
+    ${plugins_release_files}
+    )
+  set(media_plugin_targets ${media_plugin_targets} ${out_targets})
+  
+  add_custom_target(copy_media_plugin_libs ALL
+    DEPENDS 
+    ${media_plugin_targets}
+    )
+
+  add_custom_command(
+    TARGET ${VIEWER_BINARY_NAME} POST_BUILD
+    COMMAND ${CMAKE_COMMAND}
+    ARGS
+      -E
+      copy_directory
+      ${CMAKE_BINARY_DIR}/test_apps/llplugintest/${CMAKE_CFG_INTDIR}/imageformats
+      ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin/imageformats
+    COMMENT "Copying llpluging imageformat libs."
+    )
+
+  add_dependencies(${VIEWER_BINARY_NAME} llmediaplugintest copy_media_plugin_libs)
+
 endif (WINDOWS)
 
diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings
index 735424c64787ac02ecb5a4944adee4c8aab6efe2..dceaba9a4343eedec10fe62f2cff7fee2c1e8941 100644
--- a/indra/newview/English.lproj/InfoPlist.strings
+++ b/indra/newview/English.lproj/InfoPlist.strings
@@ -2,6 +2,6 @@
 
 CFBundleName = "Second Life";
 
-CFBundleShortVersionString = "Second Life version 2.0.0.0";
-CFBundleGetInfoString = "Second Life version 2.0.0.0, Copyright 2004-2009 Linden Research, Inc.";
+CFBundleShortVersionString = "Second Life version 2.0.0.3256";
+CFBundleGetInfoString = "Second Life version 2.0.0.3256, Copyright 2004-2009 Linden Research, Inc.";
 
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index 7264044d37c0a3c3bddc7a599cd99d43150fdd06..7aec8a343d60697b9e5d02297c8add0a4d6cd861 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -32,7 +32,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>2.0.0.0</string>
+	<string>2.0.0.3256</string>
 	<key>CSResourcesFileMapped</key>
 	<true/>
 </dict>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 073ea766fe787b5dded722adb63bf7cc979713b8..c10ac4e112cb751485e279da83366fdba93a4975 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -375,6 +375,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>AutoPlayMedia</key>
+    <map>
+      <key>Comment</key>
+      <string>Allow media objects to automatically play or navigate?</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>AutoSnapshot</key>
     <map>
       <key>Comment</key>
@@ -3620,6 +3631,17 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>IMShowControlPanel</key>
+    <map>
+      <key>Comment</key>
+      <string>Show IM Control Panel</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>IgnoreAllNotifications</key>
     <map>
       <key>Comment</key>
@@ -4864,7 +4886,7 @@
       <key>Value</key>
       <integer>10</integer>
     </map>
-    <key>ToastOpaqueTime</key>
+    <key>ToastFadingTime</key>
     <map>
       <key>Comment</key>
       <string>Number of seconds while a toast is fading </string>
@@ -4876,6 +4898,29 @@
       <integer>1</integer>
     </map>
     <key>StartUpToastLifeTime</key>
+    <key>NearbyToastFadingTime</key>
+    <map>
+      <key>Comment</key>
+      <string>Number of seconds while a nearby chat toast is fading </string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>3</integer>
+    </map>
+    <key>NearbyToastLifeTime</key>
+    <map>
+      <key>Comment</key>
+      <string>Number of seconds while a nearby chat toast exists</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>23</integer>
+    </map>
+    <key>StartUpToastLifeTime</key>
     <map>
       <key>Comment</key>
       <string>Number of seconds while a StartUp toast exist</string>
@@ -5316,6 +5361,17 @@
       <key>Value</key>
 	  <integer>13</integer>
     </map>
+    <key>PrimMediaMaxRetries</key>
+    <map>
+      <key>Comment</key>
+      <string>Maximum number of retries for media queries.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>4</integer>
+    </map>
     <key>PrimMediaRequestQueueDelay</key>
     <map>
       <key>Comment</key>
@@ -5404,6 +5460,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>QAModeEventHostPort</key>
+    <map>
+      <key>Comment</key>
+      <string>Enable Testing Features.</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>-1</integer>
+    </map>
     <key>QuietSnapshotsToDisk</key>
     <map>
       <key>Comment</key>
@@ -7319,17 +7386,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>ScriptErrorsAsChat</key>
-    <map>
-      <key>Comment</key>
-      <string>Display script errors and warning in chat history</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>0</integer>
-    </map>
     <key>ScriptHelpFollowsCursor</key>
     <map>
       <key>Comment</key>
@@ -7643,6 +7699,28 @@
       <string>Boolean</string>
       <key>Value</key>
       <integer>1</integer>   
+    </map>
+	<key>ShowScriptErrors</key>
+    <map>
+      <key>Comment</key>
+      <string>Show script errors</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+	<key>ShowScriptErrorsLocation</key>
+    <map>
+      <key>Comment</key>
+      <string>Show script error in chat or window</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>0</integer>
     </map>
     <key>ShowSnapshotButton</key>                
     <map>
@@ -7710,6 +7788,39 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>FriendsListShowIcons</key>
+    <map>
+      <key>Comment</key>
+      <string>Show/hide online and all friends icons in the friend list</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>NearbyListShowIcons</key>
+    <map>
+      <key>Comment</key>
+      <string>Show/hide people icons in nearby list</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>RecentListShowIcons</key>
+    <map>
+      <key>Comment</key>
+      <string>Show/hide people icons in recent list</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>FriendsSortOrder</key>
     <map>
       <key>Comment</key>
@@ -8747,13 +8858,13 @@
     <key>UICloseBoxFromTop</key>
     <map>
       <key>Comment</key>
-      <string>Size of UI floater close box from top</string>
+      <string>Distance from top of floater to top of close box icon, pixels</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
       <string>S32</string>
       <key>Value</key>
-      <real>1</real>
+      <real>5</real>
     </map>
     <key>UIExtraTriangleHeight</key>
     <map>
@@ -8788,17 +8899,6 @@
       <key>Value</key>
       <real>16</real>
     </map>
-    <key>UIFloaterHeaderSize</key>
-    <map>
-      <key>Comment</key>
-      <string>Size of UI floater header size</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>S32</string>
-      <key>Value</key>
-      <real>18</real>
-    </map>
     <key>UIFloaterHPad</key>
     <map>
       <key>Comment</key>
@@ -8821,16 +8921,16 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>UIFloaterVPad</key>
+    <key>UIFloaterTitleVPad</key>
     <map>
       <key>Comment</key>
-      <string>Size of UI floater vertical pad</string>
+      <string>Distance from top of floater to top of title string, pixels</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
       <string>S32</string>
       <key>Value</key>
-      <real>6</real>
+      <real>7</real>
     </map>
     <key>UIImgDefaultEyesUUID</key>
     <map>
@@ -8942,17 +9042,6 @@
       <key>Value</key>
       <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
     </map>
-    <key>UIImgDefaultTattooUUID</key>
-    <map>
-      <key>Comment</key>
-      <string />
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
-    </map>
     <key>UIImgDefaultUnderwearUUID</key>
     <map>
       <key>Comment</key>
@@ -10026,7 +10115,7 @@
       <key>Comment</key>
       <string>Versioning Channel Name.</string>
       <key>Persist</key>
-      <integer>1</integer>
+      <integer>0</integer>
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
@@ -10428,6 +10517,17 @@
       <key>Value</key>
       <real>90.0</real>
     </map>
+    <key>YouAreHereDistance</key>
+    <map>
+      <key>Comment</key>
+      <string>Radius of distance for banner that indicates if the resident is "on" the Place.(meters from avatar to requested place)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>10.0</real>
+    </map>
     <key>YieldTime</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/build_win32_appConfig.py b/indra/newview/build_win32_appConfig.py
index fb6a0258bcaad1ad0a286152cecea00f10ac95be..8eadf0068f559280908e40233d493301a1171846 100644
--- a/indra/newview/build_win32_appConfig.py
+++ b/indra/newview/build_win32_appConfig.py
@@ -31,11 +31,7 @@
 import sys, os, re
 from xml.dom.minidom import parse
 
-def main():
-    src_manifest_name = sys.argv[1]
-    src_config_name = sys.argv[2]
-    dst_config_name = sys.argv[3]
- 
+def munge_binding_redirect_version(src_manifest_name, src_config_name, dst_config_name):
     manifest_dom = parse(src_manifest_name)
     node = manifest_dom.getElementsByTagName('assemblyIdentity')[0]
     manifest_assm_ver = node.getAttribute('version')
@@ -47,11 +43,31 @@ def main():
     node.setAttribute('oldVersion', src_old_ver + manifest_assm_ver)
     comment = config_dom.createComment("This file is automatically generated by the build. see indra/newview/build_win32_appConfig.py")
     config_dom.insertBefore(comment, config_dom.childNodes[0])
-    
+
+    print "Writing: " + dst_config_name
     f = open(dst_config_name, 'w')
     config_dom.writexml(f)
     f.close()
+    
+    
+
+def main():
+    config = sys.argv[1]
+    src_dir = sys.argv[2]
+    dst_dir = sys.argv[3]
+    dst_name = sys.argv[4]
+    
+    if config.lower() == 'debug':
+        src_manifest_name = dst_dir + '/Microsoft.VC80.DebugCRT.manifest'
+        src_config_name = src_dir + '/SecondLifeDebug.exe.config'
+    else:
+        src_manifest_name = dst_dir + '/Microsoft.VC80.CRT.manifest'
+        src_config_name = src_dir + '/SecondLife.exe.config'
+
+    dst_config_name = dst_dir + '/' + dst_name
         
+    munge_binding_redirect_version(src_manifest_name, src_config_name, dst_config_name)
+    
     return 0
 
 if __name__ == "__main__":
diff --git a/indra/newview/character/avatar_eye.llm b/indra/newview/character/avatar_eye.llm
new file mode 100644
index 0000000000000000000000000000000000000000..8c6e74e1deb8379e7f7dbc3e01106dadaf295f44
Binary files /dev/null and b/indra/newview/character/avatar_eye.llm differ
diff --git a/indra/newview/character/avatar_eye_1.llm b/indra/newview/character/avatar_eye_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..7a3b0d6f289b1d864da66ab276653a5fc4395a15
Binary files /dev/null and b/indra/newview/character/avatar_eye_1.llm differ
diff --git a/indra/newview/character/avatar_eyelashes.llm b/indra/newview/character/avatar_eyelashes.llm
new file mode 100644
index 0000000000000000000000000000000000000000..99995b575825e1eb1c79dab31177b9734a0ad313
Binary files /dev/null and b/indra/newview/character/avatar_eyelashes.llm differ
diff --git a/indra/newview/character/avatar_hair.llm b/indra/newview/character/avatar_hair.llm
new file mode 100644
index 0000000000000000000000000000000000000000..df99de8db7b5515b06dc0ce19a92c3a5f125b1b0
Binary files /dev/null and b/indra/newview/character/avatar_hair.llm differ
diff --git a/indra/newview/character/avatar_hair_1.llm b/indra/newview/character/avatar_hair_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..6de31fdc23a3c8dc996deceae24e0ad82b0e53ee
Binary files /dev/null and b/indra/newview/character/avatar_hair_1.llm differ
diff --git a/indra/newview/character/avatar_hair_2.llm b/indra/newview/character/avatar_hair_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..47d02ba9ce03df5269c3119ef38c880599513a2a
Binary files /dev/null and b/indra/newview/character/avatar_hair_2.llm differ
diff --git a/indra/newview/character/avatar_hair_3.llm b/indra/newview/character/avatar_hair_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..107f9e2a532cc1da9aa6ce39ce8a79b483519969
Binary files /dev/null and b/indra/newview/character/avatar_hair_3.llm differ
diff --git a/indra/newview/character/avatar_hair_4.llm b/indra/newview/character/avatar_hair_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..1b9a12a0cac620df8bda2fd1188f0d907eb1914b
Binary files /dev/null and b/indra/newview/character/avatar_hair_4.llm differ
diff --git a/indra/newview/character/avatar_hair_5.llm b/indra/newview/character/avatar_hair_5.llm
new file mode 100644
index 0000000000000000000000000000000000000000..1b9a12a0cac620df8bda2fd1188f0d907eb1914b
Binary files /dev/null and b/indra/newview/character/avatar_hair_5.llm differ
diff --git a/indra/newview/character/avatar_head.llm b/indra/newview/character/avatar_head.llm
new file mode 100644
index 0000000000000000000000000000000000000000..8d8b5e0442bb98c795c4b9ab6c64c13ff9eee79d
Binary files /dev/null and b/indra/newview/character/avatar_head.llm differ
diff --git a/indra/newview/character/avatar_head_1.llm b/indra/newview/character/avatar_head_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..26291e6584b57080c6257de7884a32c55ec5e862
Binary files /dev/null and b/indra/newview/character/avatar_head_1.llm differ
diff --git a/indra/newview/character/avatar_head_2.llm b/indra/newview/character/avatar_head_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..c2b808b1a61282d52106684cd566dcb86988795a
Binary files /dev/null and b/indra/newview/character/avatar_head_2.llm differ
diff --git a/indra/newview/character/avatar_head_3.llm b/indra/newview/character/avatar_head_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..a0676b1f1ce64686913cb67701412054349b2089
Binary files /dev/null and b/indra/newview/character/avatar_head_3.llm differ
diff --git a/indra/newview/character/avatar_head_4.llm b/indra/newview/character/avatar_head_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..5035585770bfff0018608d552ea8f9e660c24fbb
Binary files /dev/null and b/indra/newview/character/avatar_head_4.llm differ
diff --git a/indra/newview/character/avatar_lower_body.llm b/indra/newview/character/avatar_lower_body.llm
new file mode 100644
index 0000000000000000000000000000000000000000..04208997399f46846dd4054c4890127155dbf070
Binary files /dev/null and b/indra/newview/character/avatar_lower_body.llm differ
diff --git a/indra/newview/character/avatar_lower_body_1.llm b/indra/newview/character/avatar_lower_body_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..1394eb848b3995d333906f293b870bd3b3310cc6
Binary files /dev/null and b/indra/newview/character/avatar_lower_body_1.llm differ
diff --git a/indra/newview/character/avatar_lower_body_2.llm b/indra/newview/character/avatar_lower_body_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..0da9c1249ea4bd0cd6fcf29d21e1dc151c5ec100
Binary files /dev/null and b/indra/newview/character/avatar_lower_body_2.llm differ
diff --git a/indra/newview/character/avatar_lower_body_3.llm b/indra/newview/character/avatar_lower_body_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..f3c49a1568d76ff16c454ff0b1fa4fafccd3b74a
Binary files /dev/null and b/indra/newview/character/avatar_lower_body_3.llm differ
diff --git a/indra/newview/character/avatar_lower_body_4.llm b/indra/newview/character/avatar_lower_body_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..e71721063ec39d799592c493b65706b76e2999c2
Binary files /dev/null and b/indra/newview/character/avatar_lower_body_4.llm differ
diff --git a/indra/newview/character/avatar_skirt.llm b/indra/newview/character/avatar_skirt.llm
new file mode 100644
index 0000000000000000000000000000000000000000..08ce3d170039ff5d2e099346ac95b128aec4866c
Binary files /dev/null and b/indra/newview/character/avatar_skirt.llm differ
diff --git a/indra/newview/character/avatar_skirt_1.llm b/indra/newview/character/avatar_skirt_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..88076c321f787d62eee2496d12510ed405c2a96d
Binary files /dev/null and b/indra/newview/character/avatar_skirt_1.llm differ
diff --git a/indra/newview/character/avatar_skirt_2.llm b/indra/newview/character/avatar_skirt_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..73b3effbc600a3e92ec695c3133aa92c2d8c528d
Binary files /dev/null and b/indra/newview/character/avatar_skirt_2.llm differ
diff --git a/indra/newview/character/avatar_skirt_3.llm b/indra/newview/character/avatar_skirt_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..ded546fdeadeaf9ce914dd05a9004cc88de25098
Binary files /dev/null and b/indra/newview/character/avatar_skirt_3.llm differ
diff --git a/indra/newview/character/avatar_skirt_4.llm b/indra/newview/character/avatar_skirt_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..b9d5cb945e3fc0b91cbf882a4df824223f7537c9
Binary files /dev/null and b/indra/newview/character/avatar_skirt_4.llm differ
diff --git a/indra/newview/character/avatar_upper_body.llm b/indra/newview/character/avatar_upper_body.llm
new file mode 100644
index 0000000000000000000000000000000000000000..da7d99054093854e6da5e0fd94e69c9d5e3a5800
Binary files /dev/null and b/indra/newview/character/avatar_upper_body.llm differ
diff --git a/indra/newview/character/avatar_upper_body_1.llm b/indra/newview/character/avatar_upper_body_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..31e104cc20b5c7bd6f7c2aae1880778eade1870e
Binary files /dev/null and b/indra/newview/character/avatar_upper_body_1.llm differ
diff --git a/indra/newview/character/avatar_upper_body_2.llm b/indra/newview/character/avatar_upper_body_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..c1f4199b9c943a4e3fb01dc4cb28ae8ccd0dcab5
Binary files /dev/null and b/indra/newview/character/avatar_upper_body_2.llm differ
diff --git a/indra/newview/character/avatar_upper_body_3.llm b/indra/newview/character/avatar_upper_body_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..9e89ed8b3e112cecf66e77de1f9dd14d5cb5267f
Binary files /dev/null and b/indra/newview/character/avatar_upper_body_3.llm differ
diff --git a/indra/newview/character/avatar_upper_body_4.llm b/indra/newview/character/avatar_upper_body_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..ec836d1dc3aebe9e570d6b33b421e87b4e9fda12
Binary files /dev/null and b/indra/newview/character/avatar_upper_body_4.llm differ
diff --git a/indra/newview/character/blush_alpha.tga b/indra/newview/character/blush_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..05be7e7e3d7f37dc76b90bee270e5597e8b2e322
Binary files /dev/null and b/indra/newview/character/blush_alpha.tga differ
diff --git a/indra/newview/character/body_skingrain.tga b/indra/newview/character/body_skingrain.tga
new file mode 100644
index 0000000000000000000000000000000000000000..7264baac144fd5d9fe8b4bbb47f97b0c4d5ff430
Binary files /dev/null and b/indra/newview/character/body_skingrain.tga differ
diff --git a/indra/newview/character/bodyfreckles_alpha.tga b/indra/newview/character/bodyfreckles_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..d30ab3d122607cf445420eb107c2457ee5ccb783
Binary files /dev/null and b/indra/newview/character/bodyfreckles_alpha.tga differ
diff --git a/indra/newview/character/bump_face_wrinkles.tga b/indra/newview/character/bump_face_wrinkles.tga
new file mode 100644
index 0000000000000000000000000000000000000000..54bf7a55be3fe90f306b454b18a7d7df18acac8c
Binary files /dev/null and b/indra/newview/character/bump_face_wrinkles.tga differ
diff --git a/indra/newview/character/bump_head_base.tga b/indra/newview/character/bump_head_base.tga
new file mode 100644
index 0000000000000000000000000000000000000000..fa3568573a4694b28dfce80e28ab6b4bca3a5d48
Binary files /dev/null and b/indra/newview/character/bump_head_base.tga differ
diff --git a/indra/newview/character/bump_lowerbody_base.tga b/indra/newview/character/bump_lowerbody_base.tga
new file mode 100644
index 0000000000000000000000000000000000000000..498ea3c721dc34f8768f16e8f5f824c8de066089
Binary files /dev/null and b/indra/newview/character/bump_lowerbody_base.tga differ
diff --git a/indra/newview/character/bump_pants_wrinkles.tga b/indra/newview/character/bump_pants_wrinkles.tga
new file mode 100644
index 0000000000000000000000000000000000000000..cca72415e808d0a760ba88041316659697d4df31
Binary files /dev/null and b/indra/newview/character/bump_pants_wrinkles.tga differ
diff --git a/indra/newview/character/bump_shirt_wrinkles.tga b/indra/newview/character/bump_shirt_wrinkles.tga
new file mode 100644
index 0000000000000000000000000000000000000000..9e0d757a48ac8f35985f27d04a66bcc42d585a1d
Binary files /dev/null and b/indra/newview/character/bump_shirt_wrinkles.tga differ
diff --git a/indra/newview/character/bump_upperbody_base.tga b/indra/newview/character/bump_upperbody_base.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e57d6352e6ad449d80690b82c920a9a33c37f32a
Binary files /dev/null and b/indra/newview/character/bump_upperbody_base.tga differ
diff --git a/indra/newview/character/eyebrows_alpha.tga b/indra/newview/character/eyebrows_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..c363e482e13e1c9437fdb7c11444e4b894aa34b4
Binary files /dev/null and b/indra/newview/character/eyebrows_alpha.tga differ
diff --git a/indra/newview/character/eyeliner_alpha.tga b/indra/newview/character/eyeliner_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..1611eb3355c07ce404223a42f081c749dc4ec3ff
Binary files /dev/null and b/indra/newview/character/eyeliner_alpha.tga differ
diff --git a/indra/newview/character/eyeshadow_inner_alpha.tga b/indra/newview/character/eyeshadow_inner_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..37d791939578dbacbe6a8768a46431406c5a0854
Binary files /dev/null and b/indra/newview/character/eyeshadow_inner_alpha.tga differ
diff --git a/indra/newview/character/eyeshadow_outer_alpha.tga b/indra/newview/character/eyeshadow_outer_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..00eef9d9f7cf40ab48ad7e941a99b9f03f0c7eb6
Binary files /dev/null and b/indra/newview/character/eyeshadow_outer_alpha.tga differ
diff --git a/indra/newview/character/eyewhite.tga b/indra/newview/character/eyewhite.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a720496988e33e69e4cedc05744dc0b3fb035b5a
Binary files /dev/null and b/indra/newview/character/eyewhite.tga differ
diff --git a/indra/newview/character/facehair_chincurtains_alpha.tga b/indra/newview/character/facehair_chincurtains_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..b10397063c08f084891baae79a24dfacc06f5964
Binary files /dev/null and b/indra/newview/character/facehair_chincurtains_alpha.tga differ
diff --git a/indra/newview/character/facehair_moustache_alpha.tga b/indra/newview/character/facehair_moustache_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..4068c4f2b139688c99ec444bc9fc58a1b2d3a3ba
Binary files /dev/null and b/indra/newview/character/facehair_moustache_alpha.tga differ
diff --git a/indra/newview/character/facehair_sideburns_alpha.tga b/indra/newview/character/facehair_sideburns_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..acddc2d9bddfcc242fc9bb7671bfa34177179983
Binary files /dev/null and b/indra/newview/character/facehair_sideburns_alpha.tga differ
diff --git a/indra/newview/character/facehair_soulpatch_alpha.tga b/indra/newview/character/facehair_soulpatch_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..687091a29f6a83761d1886828a26be70d52b108a
Binary files /dev/null and b/indra/newview/character/facehair_soulpatch_alpha.tga differ
diff --git a/indra/newview/character/freckles_alpha.tga b/indra/newview/character/freckles_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a9a4ec073531c19b3588bb7ad9531caf070d2694
Binary files /dev/null and b/indra/newview/character/freckles_alpha.tga differ
diff --git a/indra/newview/character/glove_length_alpha.tga b/indra/newview/character/glove_length_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..db89ad57e7c52a73e8801bd3b0597a596bb59a16
Binary files /dev/null and b/indra/newview/character/glove_length_alpha.tga differ
diff --git a/indra/newview/character/gloves_fingers_alpha.tga b/indra/newview/character/gloves_fingers_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..dba2eec2777c7021b2e897c728ac549a2ca50cad
Binary files /dev/null and b/indra/newview/character/gloves_fingers_alpha.tga differ
diff --git a/indra/newview/character/head_alpha.tga b/indra/newview/character/head_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..8164525353a764ff53aab784a2c6e1d8d0056607
Binary files /dev/null and b/indra/newview/character/head_alpha.tga differ
diff --git a/indra/newview/character/head_color.tga b/indra/newview/character/head_color.tga
new file mode 100644
index 0000000000000000000000000000000000000000..74b1b3078b3b60df9854086b839f8383cf4dea88
Binary files /dev/null and b/indra/newview/character/head_color.tga differ
diff --git a/indra/newview/character/head_hair.tga b/indra/newview/character/head_hair.tga
new file mode 100644
index 0000000000000000000000000000000000000000..5321f35204b09610a332c40486f47f19060561ff
Binary files /dev/null and b/indra/newview/character/head_hair.tga differ
diff --git a/indra/newview/character/head_highlights_alpha.tga b/indra/newview/character/head_highlights_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..8dc5239f977da36f8f36ce3bdb62b23f12aed758
Binary files /dev/null and b/indra/newview/character/head_highlights_alpha.tga differ
diff --git a/indra/newview/character/head_shading_alpha.tga b/indra/newview/character/head_shading_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e8ea490109d8c5401633ea33ad296aa507d8c9b3
Binary files /dev/null and b/indra/newview/character/head_shading_alpha.tga differ
diff --git a/indra/newview/character/head_skingrain.tga b/indra/newview/character/head_skingrain.tga
new file mode 100644
index 0000000000000000000000000000000000000000..b42dee08090b967ffe4db4fae19533a316cb030e
Binary files /dev/null and b/indra/newview/character/head_skingrain.tga differ
diff --git a/indra/newview/character/jacket_length_lower_alpha.tga b/indra/newview/character/jacket_length_lower_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..722bc192a832dd887ef7c90eee4055a6447cbcac
Binary files /dev/null and b/indra/newview/character/jacket_length_lower_alpha.tga differ
diff --git a/indra/newview/character/jacket_length_upper_alpha.tga b/indra/newview/character/jacket_length_upper_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e9db7e7b1fa8cc81c046200c2a497cf852d2cd5e
Binary files /dev/null and b/indra/newview/character/jacket_length_upper_alpha.tga differ
diff --git a/indra/newview/character/jacket_open_lower_alpha.tga b/indra/newview/character/jacket_open_lower_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..db0c2fb0e3ebc004b44a42168ecb9d0fd7a10ea7
Binary files /dev/null and b/indra/newview/character/jacket_open_lower_alpha.tga differ
diff --git a/indra/newview/character/jacket_open_upper_alpha.tga b/indra/newview/character/jacket_open_upper_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..71b8a0b805b0fcbb3cd17077a9624aee944d6228
Binary files /dev/null and b/indra/newview/character/jacket_open_upper_alpha.tga differ
diff --git a/indra/newview/character/lipgloss_alpha.tga b/indra/newview/character/lipgloss_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..78ceecaf85a5b157083f05973f65702ef45429bb
Binary files /dev/null and b/indra/newview/character/lipgloss_alpha.tga differ
diff --git a/indra/newview/character/lips_mask.tga b/indra/newview/character/lips_mask.tga
new file mode 100644
index 0000000000000000000000000000000000000000..ae1401c006adda76985ed7eeaa5336c471c40f87
Binary files /dev/null and b/indra/newview/character/lips_mask.tga differ
diff --git a/indra/newview/character/lipstick_alpha.tga b/indra/newview/character/lipstick_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..2795f1bd40f076eded229e25ecfdeba83a662a3d
Binary files /dev/null and b/indra/newview/character/lipstick_alpha.tga differ
diff --git a/indra/newview/character/lowerbody_color.tga b/indra/newview/character/lowerbody_color.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a63aa12fca04bb16b23f6f8bdc168371b6a7960b
Binary files /dev/null and b/indra/newview/character/lowerbody_color.tga differ
diff --git a/indra/newview/character/lowerbody_highlights_alpha.tga b/indra/newview/character/lowerbody_highlights_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..ae3413ac8bd98507416f565ebf9d9119342f62a2
Binary files /dev/null and b/indra/newview/character/lowerbody_highlights_alpha.tga differ
diff --git a/indra/newview/character/lowerbody_shading_alpha.tga b/indra/newview/character/lowerbody_shading_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..0242663a7db248b6e6af96fcc9168ee917067476
Binary files /dev/null and b/indra/newview/character/lowerbody_shading_alpha.tga differ
diff --git a/indra/newview/character/nailpolish_alpha.tga b/indra/newview/character/nailpolish_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..91af762902820acca0e0630438f7b19aef5136ed
Binary files /dev/null and b/indra/newview/character/nailpolish_alpha.tga differ
diff --git a/indra/newview/character/pants_length_alpha.tga b/indra/newview/character/pants_length_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..3c4f21c0f2ab5743e804179d792db45e69885b2e
Binary files /dev/null and b/indra/newview/character/pants_length_alpha.tga differ
diff --git a/indra/newview/character/pants_waist_alpha.tga b/indra/newview/character/pants_waist_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..35658c08968a9202710a82ba7d11b4f6c792f8cc
Binary files /dev/null and b/indra/newview/character/pants_waist_alpha.tga differ
diff --git a/indra/newview/character/rosyface_alpha.tga b/indra/newview/character/rosyface_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a0c8513da2f860da84825a17b980bdc2f963fc82
Binary files /dev/null and b/indra/newview/character/rosyface_alpha.tga differ
diff --git a/indra/newview/character/rouge_alpha.tga b/indra/newview/character/rouge_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a0c8513da2f860da84825a17b980bdc2f963fc82
Binary files /dev/null and b/indra/newview/character/rouge_alpha.tga differ
diff --git a/indra/newview/character/shirt_bottom_alpha.tga b/indra/newview/character/shirt_bottom_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..7cce03dbe040bc7cbe25a2b4f4be579327d12961
Binary files /dev/null and b/indra/newview/character/shirt_bottom_alpha.tga differ
diff --git a/indra/newview/character/shirt_collar_alpha.tga b/indra/newview/character/shirt_collar_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..f55f635473413cacd722c5e2b04c81e78f9a2c72
Binary files /dev/null and b/indra/newview/character/shirt_collar_alpha.tga differ
diff --git a/indra/newview/character/shirt_collar_back_alpha.tga b/indra/newview/character/shirt_collar_back_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..43a645310739931da7f9216cdde577c78a04445b
Binary files /dev/null and b/indra/newview/character/shirt_collar_back_alpha.tga differ
diff --git a/indra/newview/character/shirt_sleeve_alpha.tga b/indra/newview/character/shirt_sleeve_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e3b18f4fc69578f65c7dda9b675cc101fa389a60
Binary files /dev/null and b/indra/newview/character/shirt_sleeve_alpha.tga differ
diff --git a/indra/newview/character/shoe_height_alpha.tga b/indra/newview/character/shoe_height_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..d08dd750f308982b4200b04f1722814474412843
Binary files /dev/null and b/indra/newview/character/shoe_height_alpha.tga differ
diff --git a/indra/newview/character/skirt_length_alpha.tga b/indra/newview/character/skirt_length_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..c86799469d5fdadc6e0e614ab45060685b0e1695
Binary files /dev/null and b/indra/newview/character/skirt_length_alpha.tga differ
diff --git a/indra/newview/character/skirt_slit_back_alpha.tga b/indra/newview/character/skirt_slit_back_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..0e49688b146a55e7d776a80ddb65ff81bffa3202
Binary files /dev/null and b/indra/newview/character/skirt_slit_back_alpha.tga differ
diff --git a/indra/newview/character/skirt_slit_front_alpha.tga b/indra/newview/character/skirt_slit_front_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..888bbf71a1193cbc9ff4a564e6c0837f6affab5a
Binary files /dev/null and b/indra/newview/character/skirt_slit_front_alpha.tga differ
diff --git a/indra/newview/character/skirt_slit_left_alpha.tga b/indra/newview/character/skirt_slit_left_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..210feac1ea0e4014ddd8187e1460ef1781a5c8e0
Binary files /dev/null and b/indra/newview/character/skirt_slit_left_alpha.tga differ
diff --git a/indra/newview/character/skirt_slit_right_alpha.tga b/indra/newview/character/skirt_slit_right_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..ce11c64bf6763e517b16f4c0d70f02065132e4c2
Binary files /dev/null and b/indra/newview/character/skirt_slit_right_alpha.tga differ
diff --git a/indra/newview/character/underpants_trial_female.tga b/indra/newview/character/underpants_trial_female.tga
new file mode 100644
index 0000000000000000000000000000000000000000..96bf732351786a699ae30e74ef2fed61b14b87b6
Binary files /dev/null and b/indra/newview/character/underpants_trial_female.tga differ
diff --git a/indra/newview/character/underpants_trial_male.tga b/indra/newview/character/underpants_trial_male.tga
new file mode 100644
index 0000000000000000000000000000000000000000..095695ca1c47993db36460a35071b9f0a5c16fc9
Binary files /dev/null and b/indra/newview/character/underpants_trial_male.tga differ
diff --git a/indra/newview/character/undershirt_trial_female.tga b/indra/newview/character/undershirt_trial_female.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e17a30953154e0b135fda708c90eeddbd4189034
Binary files /dev/null and b/indra/newview/character/undershirt_trial_female.tga differ
diff --git a/indra/newview/character/upperbody_color.tga b/indra/newview/character/upperbody_color.tga
new file mode 100644
index 0000000000000000000000000000000000000000..85fcc41142102114244c28c9743d97b119e2f3e1
Binary files /dev/null and b/indra/newview/character/upperbody_color.tga differ
diff --git a/indra/newview/character/upperbody_highlights_alpha.tga b/indra/newview/character/upperbody_highlights_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..2d8102b583d3a8346afb6cb671b9b7f9f3d3780d
Binary files /dev/null and b/indra/newview/character/upperbody_highlights_alpha.tga differ
diff --git a/indra/newview/character/upperbody_shading_alpha.tga b/indra/newview/character/upperbody_shading_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..b420506b3e1407d0eb0b8bd07f63621dba6be557
Binary files /dev/null and b/indra/newview/character/upperbody_shading_alpha.tga differ
diff --git a/indra/newview/character/upperbodyfreckles_alpha.tga b/indra/newview/character/upperbodyfreckles_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..76c7ce8849f59a2355b55d7454af4c6703772050
Binary files /dev/null and b/indra/newview/character/upperbodyfreckles_alpha.tga differ
diff --git a/indra/newview/licenses-mac.txt b/indra/newview/licenses-mac.txt
index d488c7487e16f48e2a507c2013600079ec52f994..1324fa1a864edcc275b9e10e0d4c9241f1993685 100644
--- a/indra/newview/licenses-mac.txt
+++ b/indra/newview/licenses-mac.txt
@@ -315,6 +315,515 @@ This product includes cryptographic software written by Eric Young
 Hudson (tjh@cryptsoft.com).
 
 
+===========
+Pth License
+===========
+   ____  _   _
+  |  _ \| |_| |__               ``Ian Fleming was a UNIX fan!
+  | |_) | __| '_ \                How do I know? Well, James Bond
+  |  __/| |_| | | |               had the (license to kill) number 007,
+  |_|    \__|_| |_|               i.e., he could execute anyone!''
+
+  GNU Pth - The GNU Portable Threads
+
+  LICENSE
+  =======
+
+  This library is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+
+  For some people, it is not clear, what is the real intention of the
+  author by using the GNU Lesser General Public License (LGPL) as the
+  distribution license for GNU Pth. This is, because the LGPL and the
+  GPL can be (and are often) interpreted very differently and some
+  interpretations seem to be not compatible with others. So an explicit
+  clarification for the use of the LGPL for GNU Pth from the authors
+  point of view might be useful.
+
+  The author places this library under the LGPL to make sure that it
+  can be used both commercially and non-commercially provided that
+  modifications to the code base are always donated back to the official
+  code base under the same license conditions. Please keep in mind that
+  especially using this library in code not staying under the GPL or
+  the LGPL _is_ allowed and that any taint or license creap into code
+  that uses the library is not the authors intention. It is just the
+  case that _including_ this library into the source tree of other
+  applications is a little bit more inconvinient because of the LGPL.
+  But it has to be this way for good reasons. And keep in mind that
+  inconvinient doesn't mean not allowed or even impossible.
+
+  Even if you want to use this library in some BSD-style licensed
+  packages, this _is_ possible as long as you are a little bit
+  carefully. Usually this means you have to make sure that the code is
+  still clearly separated into the source tree and that modifications to
+  this source area are done under the conditions of the LGPL. Read below
+  for more details on the conditions. Contact the author if you have
+  more questions.
+
+  The license text of the GNU Lesser General Public License follows:
+  __________________________________________________________________________
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
 
 =======================
 Original SSLeay License
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 0fa3b1f04df573a0dc1997ba326f5b35ea923ea4..75a72e5b17c296a42ed9240cc87cf396e885fb0f 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -35,13 +35,14 @@
 #include "llagent.h" 
 #include "llagentwearables.h"
 
+#include "llagentlistener.h"
 #include "llanimationstates.h"
 #include "llcallingcard.h"
 #include "llconsole.h"
 #include "lldrawable.h"
 #include "llfirstuse.h"
 #include "llfloaterreg.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
 #include "llfloatercamera.h"
 #include "llfloatercustomize.h"
 
@@ -255,6 +256,7 @@ LLAgent::LLAgent() :
 	mHUDTargetZoom(1.f),
 	mHUDCurZoom(1.f),
 	mInitialized(FALSE),
+	mListener(),
 	mForceMouselook(FALSE),
 
 	mDoubleTapRunTimer(),
@@ -383,6 +385,8 @@ LLAgent::LLAgent() :
 	}
 
 	mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT );
+
+	mListener.reset(new LLAgentListener(*this));
 }
 
 // Requires gSavedSettings to be initialized.
@@ -5387,12 +5391,6 @@ void update_group_floaters(const LLUUID& group_id)
 	//*TODO Implement group update for Profile View 
 	// still actual as of July 31, 2009 (DZ)
 
-	if (gIMMgr)
-	{
-		// update the talk view
-		gIMMgr->refresh();
-	}
-
 	gAgent.fireEvent(new LLOldEvents::LLEvent(&gAgent, "new group"), "");
 }
 
@@ -5971,7 +5969,7 @@ bool LLAgent::teleportCore(bool is_local)
 	LLFloaterReg::hideInstance("about_land");
 
 	LLViewerParcelMgr::getInstance()->deselectLand();
-	LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL);
+	LLViewerMediaFocus::getInstance()->clearFocus();
 
 	// Close all pie menus, deselect land, etc.
 	// Don't change the camera until we know teleport succeeded. JC
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index b334874e6ebcca520f3a3c93800e51bdb120a875..99a9bdd8e636ec13c49e7b09999dd4e7f93b3387 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -105,6 +105,8 @@ struct LLGroupData
 	std::string mName;
 };
 
+class LLAgentListener;
+
 //------------------------------------------------------------------------
 // LLAgent
 //------------------------------------------------------------------------
@@ -142,6 +144,8 @@ class LLAgent : public LLOldEvents::LLObservable
 	BOOL			mInitialized;
 	BOOL			mFirstLogin;
 	std::string		mMOTD; 					// Message of the day
+private:
+	boost::shared_ptr<LLAgentListener> mListener;
 
 	//--------------------------------------------------------------------
 	// Session
diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0f00078b33ca0eef6e58e501774e1030fbfd6d13
--- /dev/null
+++ b/indra/newview/llagentlistener.cpp
@@ -0,0 +1,78 @@
+/**
+ * @file   llagentlistener.cpp
+ * @author Brad Kittenbrink
+ * @date   2009-07-10
+ * @brief  Implementation for llagentlistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagentlistener.h"
+
+#include "llagent.h"
+#include "llcommandhandler.h"
+#include "llslurl.h"
+#include "llurldispatcher.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+
+LLAgentListener::LLAgentListener(LLAgent &agent)
+  : LLDispatchListener("LLAgent", "op"),
+    mAgent(agent)
+{
+	add("requestTeleport", &LLAgentListener::requestTeleport);
+	add("requestSit", &LLAgentListener::requestSit);
+	add("requestStand", &LLAgentListener::requestStand);
+}
+
+void LLAgentListener::requestTeleport(LLSD const & event_data) const
+{
+	if(event_data["skip_confirmation"].asBoolean())
+	{
+		LLSD params(LLSD::emptyArray());
+		params.append(event_data["regionname"]);
+		params.append(event_data["x"]);
+		params.append(event_data["y"]);
+		params.append(event_data["z"]);
+		LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, true);
+		// *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "objectim", "parcel", "login", login_refresh", "balance", "chat"
+		// should we just compose LLCommandHandler and LLDispatchListener?
+	}
+	else
+	{
+		std::string url = LLSLURL::buildSLURL(event_data["regionname"], event_data["x"], event_data["y"], event_data["z"]);
+		LLURLDispatcher::dispatch(url, NULL, false);
+	}
+}
+
+void LLAgentListener::requestSit(LLSD const & event_data) const
+{
+	//mAgent.getAvatarObject()->sitOnObject();
+	// shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand()
+	// *TODO - find a permanent place to share this code properly.
+	LLViewerObject *object = gObjectList.findObject(event_data["obj_uuid"]);
+
+	if (object && object->getPCode() == LL_PCODE_VOLUME)
+	{
+		gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
+		gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+		gMessageSystem->addUUIDFast(_PREHASH_AgentID, mAgent.getID());
+		gMessageSystem->addUUIDFast(_PREHASH_SessionID, mAgent.getSessionID());
+		gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
+		gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID);
+		gMessageSystem->addVector3Fast(_PREHASH_Offset, LLVector3(0,0,0));
+
+		object->getRegion()->sendReliableMessage();
+	}
+}
+
+void LLAgentListener::requestStand(LLSD const & event_data) const
+{
+	mAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
+}
+
diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f0b5a54c5f0efd54b8bd116437b00779ae63879
--- /dev/null
+++ b/indra/newview/llagentlistener.h
@@ -0,0 +1,36 @@
+/**
+ * @file   llagentlistener.h
+ * @author Brad Kittenbrink
+ * @date   2009-07-09
+ * @brief  Event API for subset of LLViewerControl methods
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_LLAGENTLISTENER_H
+#define LL_LLAGENTLISTENER_H
+
+#include "lleventdispatcher.h"
+
+class LLAgent;
+class LLSD;
+
+class LLAgentListener : public LLDispatchListener
+{
+public:
+	LLAgentListener(LLAgent &agent);
+
+private:
+	void requestTeleport(LLSD const & event_data) const;
+	void requestSit(LLSD const & event_data) const;
+	void requestStand(LLSD const & event_data) const;
+
+private:
+	LLAgent & mAgent;
+};
+
+#endif // LL_LLAGENTLISTENER_H
+
diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp
index 1a69f1d975e81646c7ecab442fbdad06daee8081..09f7c49f23dbbc91c571aeb77af63488a6af9868 100644
--- a/indra/newview/llagentui.cpp
+++ b/indra/newview/llagentui.cpp
@@ -89,6 +89,11 @@ std::string LLAgentUI::buildSLURL(const bool escaped /*= true*/)
 	return slurl;
 }
 
+//static
+BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius)
+{
+	return  (gAgent.getPositionAgent() - pole).length() < radius;
+}
 BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region)
 {
 	LLViewerRegion* region = gAgent.getRegion();
diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h
index 47ecb04547a3eea58403d8752978f6b5ab22c447..c7aafb71e7b9db4f8b1c4c64c245963a37284df6 100644
--- a/indra/newview/llagentui.h
+++ b/indra/newview/llagentui.h
@@ -52,6 +52,11 @@ class LLAgentUI
 	static BOOL buildLocationString(std::string& str, ELocationFormat fmt = LOCATION_FORMAT_LANDMARK);
 	//build location string using a region position of the avatar. 
 	static BOOL buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region);
+	/**
+	 * @brief Check whether  the agent is in neighborhood of the pole  Within same region
+	 * @return true if the agent is in neighborhood.
+	 */
+	static BOOL checkAgentDistance(const LLVector3& local_pole, F32 radius);
 };
 
 #endif //LLAGENTUI_H
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index b9a0b4293ddd626eadabfb2abe26f5429bd95d0f..380469f5b361f2425315cb817bd9df4d30b61235 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1985,6 +1985,17 @@ bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const
 	return !(((type == WT_SHAPE) || (type == WT_SKIN) || (type == WT_HAIR) || (type == WT_EYES))
 			 && (getWearableCount(type) <= 1) );		  
 }
+void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL set_by_user)
+{
+	for( S32 type = 0; type < WT_COUNT; ++type )
+	{
+		for (S32 count = 0; count < (S32)getWearableCount((EWearableType)type); ++count)
+		{
+			LLWearable *wearable = getWearable((EWearableType)type,count);
+			wearable->animateParams(delta, set_by_user);
+		}
+	}
+}
 
 void LLAgentWearables::updateServer()
 {
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 667cb9455233e83aa21f7b76532288bb79219cfe..97de785c8716889a9187840fc318915a4bf3b46c 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -79,6 +79,8 @@ class LLAgentWearables
 	
 	// Note: False for shape, skin, eyes, and hair, unless you have MORE than 1.
 	bool			canWearableBeRemoved(const LLWearable* wearable) const;
+
+	void			animateAllWearableParams(F32 delta, BOOL set_by_user);
 	
 	//--------------------------------------------------------------------
 	// Accessors
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c673db2034f4c67b151d072a8dc60e01d0f9517d..873215169ee95b974d948ce0db2c0093cb642c64 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -49,7 +49,6 @@
 #include "llviewerstats.h"
 #include "llmd5.h"
 #include "llpumpio.h"
-#include "llimpanel.h"
 #include "llmimetypes.h"
 #include "llslurl.h"
 #include "llstartup.h"
@@ -73,8 +72,10 @@
 #include "llurlhistory.h"
 #include "llfirstuse.h"
 #include "llrender.h"
+#include "llteleporthistory.h"
 #include "lllocationhistory.h"
 #include "llfasttimerview.h"
+#include "llvoicechannel.h"
 
 #include "llweb.h"
 #include "llsecondlifeurls.h"
@@ -91,14 +92,15 @@
 
 #if LL_WINDOWS
 	#include "llwindebug.h"
-#endif
-
-#if LL_WINDOWS
 #	include <share.h> // For _SH_DENYWR in initMarkerFile
 #else
 #   include <sys/file.h> // For initMarkerFile support
 #endif
 
+#include "llapr.h"
+#include "apr_dso.h"
+#include <boost/lexical_cast.hpp>
+
 #include "llnotify.h"
 #include "llviewerkeyboard.h"
 #include "lllfsthread.h"
@@ -154,7 +156,6 @@
 #include "llfolderview.h"
 #include "lltoolbar.h"
 #include "llagentpilot.h"
-#include "llsrv.h"
 #include "llvovolume.h"
 #include "llflexibleobject.h" 
 #include "llvosurfacepatch.h"
@@ -192,7 +193,19 @@
 //----------------------------------------------------------------------------
 // llviewernetwork.h
 #include "llviewernetwork.h"
+// define a self-registering event API object
+#include "llappviewerlistener.h"
+
+#if (LL_LINUX || LL_SOLARIS) && LL_GTK
+#include "glib.h"
+#endif // (LL_LINUX || LL_SOLARIS) && LL_GTK
 
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
+static LLAppViewerListener sAppViewerListener("LLAppViewer", LLAppViewer::instance);
 
 ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
 //
@@ -214,13 +227,9 @@ const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; // time with no input before user fl
 F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
 F32 gSimFrames;
 
-BOOL gAllowTapTapHoldRun = TRUE;
 BOOL gShowObjectUpdates = FALSE;
 BOOL gUseQuickTime = TRUE;
 
-BOOL gAcceptTOS = FALSE;
-BOOL gAcceptCriticalMessage = FALSE;
-
 eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
 
 LLSD gDebugInfo;
@@ -229,8 +238,6 @@ U32	gFrameCount = 0;
 U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
 LLPumpIO* gServicePump = NULL;
 
-BOOL gPacificDaylightTime = FALSE;
-
 U64 gFrameTime = 0;
 F32 gFrameTimeSeconds = 0.f;
 F32 gFrameIntervalSeconds = 0.f;
@@ -411,7 +418,6 @@ static void settings_to_globals()
 	gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
 
 	gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
-	gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun");
 	gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
 	gMapScale = gSavedSettings.getF32("MapScale");
 
@@ -565,9 +571,9 @@ LLAppViewer::LLAppViewer() :
 	mYieldTime(-1),
 	mMainloopTimeout(NULL),
 	mAgentRegionLastAlive(false),
-	mFastTimerLogThread(NULL),
 	mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
-	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE))
+	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
+	mFastTimerLogThread(NULL)
 {
 	if(NULL != sInstance)
 	{
@@ -877,6 +883,11 @@ bool LLAppViewer::init()
 
 	LLViewerJoystick::getInstance()->init(false);
 	gGLActive = FALSE;
+	if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
+	{
+		loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort"));
+	}
+	
 	return true;
 }
 
@@ -1191,6 +1202,21 @@ bool LLAppViewer::mainLoop()
 
 bool LLAppViewer::cleanup()
 {
+	// workaround for DEV-35406 crash on shutdown
+	LLEventPumps::instance().reset();
+
+	// *TODO - generalize this and move DSO wrangling to a helper class -brad
+	std::set<struct apr_dso_handle_t *>::const_iterator i;
+	for(i = mPlugins.begin(); i != mPlugins.end(); ++i)
+	{
+		int (*ll_plugin_stop_func)(void) = NULL;
+		apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop");
+		ll_plugin_stop_func();
+
+		rv = apr_dso_unload(*i);
+	}
+	mPlugins.clear();
+
 	//----------------------------------------------
 	//this test code will be removed after the test
 	//test manual call stack tracer
@@ -1320,7 +1346,11 @@ bool LLAppViewer::cleanup()
 	// Destroy the UI
 	if( gViewerWindow)
 		gViewerWindow->shutdownViews();
-
+	
+	// Cleanup Inventory after the UI since it will delete any remaining observers
+	// (Deleted observers should have already removed themselves)
+	gInventory.cleanupInventory();
+	
 	// Clean up selection managers after UI is destroyed, as UI may be observing them.
 	// Clean up before GL is shut down because we might be holding on to objects with texture references
 	LLSelectMgr::cleanupGlobals();
@@ -1498,7 +1528,6 @@ bool LLAppViewer::cleanup()
 	//Note:
 	//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
 	//because some new image might be generated during cleaning up media. --bao
-	LLViewerMediaFocus::cleanupClass();
 	LLViewerMedia::cleanupClass();
 	LLViewerParcelMedia::cleanupClass();
 	gTextureList.shutdown(); // shutdown again in case a callback added something
@@ -2371,7 +2400,6 @@ void LLAppViewer::cleanupSavedSettings()
 
 	gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
 		
-	gSavedSettings.setBOOL("AllowTapTapHoldRun", gAllowTapTapHoldRun);
 	gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
 	
 	if (!gNoRender)
@@ -3694,6 +3722,17 @@ void LLAppViewer::idleShutdown()
 	{
 		return;
 	}
+	
+	// ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup()
+	// *TODO: ugly
+	static bool saved_teleport_history = false;
+	if (!saved_teleport_history)
+	{
+		saved_teleport_history = true;
+		LLTeleportHistory::getInstance()->dump();
+		LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this
+		return;
+	}
 
 	static bool saved_snapshot = false;
 	if (!saved_snapshot)
@@ -3988,7 +4027,7 @@ void LLAppViewer::forceErrorBadMemoryAccess()
     return;
 }
 
-void LLAppViewer::forceErrorInifiniteLoop()
+void LLAppViewer::forceErrorInfiniteLoop()
 {
     while(true)
     {
@@ -4109,3 +4148,198 @@ void LLAppViewer::handleLoginComplete()
 
 	writeDebugInfo();
 }
+
+// *TODO - generalize this and move DSO wrangling to a helper class -brad
+void LLAppViewer::loadEventHostModule(S32 listen_port)
+{
+	std::string dso_name =
+#if LL_WINDOWS
+	    "lleventhost.dll";
+#elif LL_DARWIN
+	    "liblleventhost.dylib";
+#else
+	    "liblleventhost.so";
+#endif
+
+	std::string dso_path = gDirUtilp->findFile(dso_name,
+		gDirUtilp->getAppRODataDir(),
+		gDirUtilp->getExecutableDir());
+
+	if(dso_path == "")
+	{
+		llwarns << "QAModeEventHost requested but module \"" << dso_name << "\" not found!" << llendl;
+		return;
+	}
+
+	apr_dso_handle_t * eventhost_dso_handle = NULL;
+	apr_pool_t * eventhost_dso_memory_pool = NULL;
+
+	//attempt to load the shared library
+	apr_pool_create(&eventhost_dso_memory_pool, NULL);
+	apr_status_t rv = apr_dso_load(&eventhost_dso_handle,
+		dso_path.c_str(),
+		eventhost_dso_memory_pool);
+	ll_apr_assert_status(rv);
+	llassert_always(eventhost_dso_handle != NULL);
+
+	int (*ll_plugin_start_func)(LLSD const &) = NULL;
+	rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start");
+
+	ll_apr_assert_status(rv);
+	llassert_always(ll_plugin_start_func != NULL);
+
+	LLSD args;
+	args["listen_port"] = listen_port;
+
+	int status = ll_plugin_start_func(args);
+
+	if(status != 0)
+	{
+		llwarns << "problem loading eventhost plugin, status: " << status << llendl;
+	}
+
+	mPlugins.insert(eventhost_dso_handle);
+}
+
+void LLAppViewer::launchUpdater()
+{
+		LLSD query_map = LLSD::emptyMap();
+	// *TODO place os string in a global constant
+#if LL_WINDOWS  
+	query_map["os"] = "win";
+#elif LL_DARWIN
+	query_map["os"] = "mac";
+#elif LL_LINUX
+	query_map["os"] = "lnx";
+#elif LL_SOLARIS
+	query_map["os"] = "sol";
+#endif
+	// *TODO change userserver to be grid on both viewer and sim, since
+	// userserver no longer exists.
+	query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel();
+	query_map["channel"] = gSavedSettings.getString("VersionChannelName");
+	// *TODO constantize this guy
+	// *NOTE: This URL is also used in win_setup/lldownloader.cpp
+	LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map);
+	
+	if(LLAppViewer::sUpdaterInfo)
+	{
+		delete LLAppViewer::sUpdaterInfo;
+	}
+	LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ;
+
+	// if a sim name was passed in via command line parameter (typically through a SLURL)
+	if ( LLURLSimString::sInstance.mSimString.length() )
+	{
+		// record the location to start at next time
+		gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); 
+	};
+
+#if LL_WINDOWS
+	LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename();
+	if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty())
+	{
+		delete LLAppViewer::sUpdaterInfo ;
+		LLAppViewer::sUpdaterInfo = NULL ;
+
+		// We're hosed, bail
+		LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL;
+		return;
+	}
+
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe";
+
+	std::string updater_source = gDirUtilp->getAppRODataDir();
+	updater_source += gDirUtilp->getDirDelimiter();
+	updater_source += "updater.exe";
+
+	LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source
+			<< " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath
+			<< LL_ENDL;
+
+
+	if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE))
+	{
+		delete LLAppViewer::sUpdaterInfo ;
+		LLAppViewer::sUpdaterInfo = NULL ;
+
+		LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL;
+
+		return;
+	}
+
+	LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\"";
+
+	LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL;
+
+	//Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird.
+	LLAppViewer::instance()->removeMarkerFile(); // In case updater fails
+
+	// *NOTE:Mani The updater is spawned as the last thing before the WinMain exit.
+	// see LLAppViewerWin32.cpp
+	
+#elif LL_DARWIN
+	LLAppViewer::sUpdaterInfo->mUpdateExePath = "'";
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir();
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \"";
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString();
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \"";
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle();
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &";
+
+	LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
+
+	// Run the auto-updater.
+	system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */
+
+#elif (LL_LINUX || LL_SOLARIS) && LL_GTK
+	// we tell the updater where to find the xml containing string
+	// translations which it can use for its own UI
+	std::string xml_strings_file = "strings.xml";
+	std::vector<std::string> xui_path_vec = LLUI::getXUIPaths();
+	std::string xml_search_paths;
+	std::vector<std::string>::const_iterator iter;
+	// build comma-delimited list of xml paths to pass to updater
+	for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); )
+	{
+		std::string this_skin_dir = gDirUtilp->getDefaultSkinDir()
+			+ gDirUtilp->getDirDelimiter()
+			+ (*iter);
+		llinfos << "Got a XUI path: " << this_skin_dir << llendl;
+		xml_search_paths.append(this_skin_dir);
+		++iter;
+		if (iter != xui_path_vec.end())
+			xml_search_paths.append(","); // comma-delimit
+	}
+	// build the overall command-line to run the updater correctly
+	LLAppViewer::sUpdaterInfo->mUpdateExePath = 
+		gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + 
+		" --url \"" + update_url.asString() + "\"" +
+		" --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" +
+		" --dest \"" + gDirUtilp->getAppRODataDir() + "\"" +
+		" --stringsdir \"" + xml_search_paths + "\"" +
+		" --stringsfile \"" + xml_strings_file + "\"";
+
+	LL_INFOS("AppInit") << "Calling updater: " 
+			    << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
+
+	// *TODO: we could use the gdk equivalent to ensure the updater
+	// gets started on the same screen.
+	GError *error = NULL;
+	if (!g_spawn_command_line_async(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), &error))
+	{
+		llerrs << "Failed to launch updater: "
+		       << error->message
+		       << llendl;
+	}
+	if (error) {
+		g_error_free(error);
+	}
+#else
+	OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK);
+#endif
+
+	// *REMOVE:Mani - Saving for reference...
+	// LLAppViewer::instance()->forceQuit();
+}
+
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 646b67726497c98d5f3e28a618fb12228436f51e..73256a8fe64cccedf55c8e9ca995e9351b7399c5 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -47,6 +47,8 @@ class LLVFS;
 class LLWatchdogTimeout;
 class LLWorkerThread;
 
+struct apr_dso_handle_t;
+
 
 class LLAppViewer : public LLApp
 {
@@ -124,7 +126,7 @@ class LLAppViewer : public LLApp
     virtual void forceErrorLLError();
     virtual void forceErrorBreakpoint();
     virtual void forceErrorBadMemoryAccess();
-    virtual void forceErrorInifiniteLoop();
+    virtual void forceErrorInfiniteLoop();
     virtual void forceErrorSoftwareException();
     virtual void forceErrorDriverCrash();
 
@@ -210,6 +212,8 @@ class LLAppViewer : public LLApp
     void sendLogoutRequest();
     void disconnectViewer();
 
+	void loadEventHostModule(S32 listen_port);
+	
 	// *FIX: the app viewer class should be some sort of singleton, no?
 	// Perhaps its child class is the singleton and this should be an abstract base.
 	static LLAppViewer* sInstance; 
@@ -255,6 +259,8 @@ class LLAppViewer : public LLApp
 
     LLAllocator mAlloc;
 
+	std::set<struct apr_dso_handle_t*> mPlugins;
+
 public:
 	//some information for updater
 	typedef struct
@@ -263,6 +269,8 @@ class LLAppViewer : public LLApp
 		std::ostringstream mParams;
 	}LLUpdaterInfo ;
 	static LLUpdaterInfo *sUpdaterInfo ;
+
+	void launchUpdater();
 };
 
 // consts from viewer.h
@@ -274,14 +282,8 @@ const S32 AGENT_UPDATES_PER_SECOND  = 10;
 // "// llstartup" indicates that llstartup is the only client for this global.
 
 extern LLSD gDebugInfo;
-
-extern BOOL	gAllowTapTapHoldRun;
 extern BOOL	gShowObjectUpdates;
 
-extern BOOL gAcceptTOS;
-extern BOOL gAcceptCriticalMessage;
-
-
 typedef enum 
 {
 	LAST_EXEC_NORMAL = 0,
@@ -299,10 +301,6 @@ extern U32 gForegroundFrameCount;
 
 extern LLPumpIO* gServicePump;
 
-// Is the Pacific time zone (aka server time zone)
-// currently in daylight savings time?
-extern BOOL gPacificDaylightTime;
-
 extern U64      gFrameTime;					// The timestamp of the most-recently-processed frame
 extern F32		gFrameTimeSeconds;			// Loses msec precision after ~4.5 hours...
 extern F32		gFrameIntervalSeconds;		// Elapsed time between current and previous gFrameTimeSeconds
diff --git a/indra/newview/llappviewerlistener.cpp b/indra/newview/llappviewerlistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3259309eee76872a69e8aa2b8cd16563c77dd10a
--- /dev/null
+++ b/indra/newview/llappviewerlistener.cpp
@@ -0,0 +1,40 @@
+/**
+ * @file   llappviewerlistener.cpp
+ * @author Nat Goodspeed
+ * @date   2009-06-23
+ * @brief  Implementation for llappviewerlistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llappviewerlistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llappviewer.h"
+
+LLAppViewerListener::LLAppViewerListener(const std::string& pumpname,
+                                         const LLAppViewerGetter& getter):
+    LLDispatchListener(pumpname, "op"),
+    mAppViewerGetter(getter)
+{
+    // add() every method we want to be able to invoke via this event API.
+    add("requestQuit", &LLAppViewerListener::requestQuit);
+    add("forceQuit", &LLAppViewerListener::forceQuit);
+}
+
+void LLAppViewerListener::requestQuit(const LLSD& event)
+{
+    mAppViewerGetter()->requestQuit();
+}
+
+void LLAppViewerListener::forceQuit(const LLSD& event)
+{
+    mAppViewerGetter()->forceQuit();
+}
diff --git a/indra/newview/llappviewerlistener.h b/indra/newview/llappviewerlistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..73227cb95a771e2a74092f3cf74197ae230a2c52
--- /dev/null
+++ b/indra/newview/llappviewerlistener.h
@@ -0,0 +1,37 @@
+/**
+ * @file   llappviewerlistener.h
+ * @author Nat Goodspeed
+ * @date   2009-06-18
+ * @brief  Wrap subset of LLAppViewer API in event API
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLAPPVIEWERLISTENER_H)
+#define LL_LLAPPVIEWERLISTENER_H
+
+#include "lleventdispatcher.h"
+#include <boost/function.hpp>
+
+class LLAppViewer;
+class LLSD;
+
+/// Listen on an LLEventPump with specified name for LLAppViewer request events.
+class LLAppViewerListener: public LLDispatchListener
+{
+public:
+    typedef boost::function<LLAppViewer*(void)> LLAppViewerGetter;
+    /// Specify the pump name on which to listen, and bind the LLAppViewer
+    /// instance to use (e.g. LLAppViewer::instance()).
+    LLAppViewerListener(const std::string& pumpname, const LLAppViewerGetter& getter);
+
+private:
+    void requestQuit(const LLSD& event);
+    void forceQuit(const LLSD& event);
+
+    LLAppViewerGetter mAppViewerGetter;
+};
+
+#endif /* ! defined(LL_LLAPPVIEWERLISTENER_H) */
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index 7ae1b5cd4a75647f082dd2e4ecb142a42da9f9cf..b56e8d1ec2546009a1dcf2d893cec0b5680dc9ef 100644
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -152,7 +152,11 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
 :	LLIconCtrl(p),
 	mDrawTooltip(p.draw_tooltip)
 {
+	mPriority = LLViewerFetchedTexture::BOOST_ICON;
+	
 	LLRect rect = p.rect;
+	mDrawWidth  = llmax(32, rect.getWidth()) ;
+	mDrawHeight = llmax(32, rect.getHeight()) ;
 
 	static LLUICachedControl<S32> llavatariconctrl_symbol_hpad("UIAvatariconctrlSymbolHPad", 2);
 	static LLUICachedControl<S32> llavatariconctrl_symbol_vpad("UIAvatariconctrlSymbolVPad", 2);
@@ -191,7 +195,6 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
 		LLIconCtrl::setValue("default_profile_picture.j2c");
 	}
 
-
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 
 	registrar.add("AvatarIcon.Action", boost::bind(&LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked, this, _2));
diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
index 426fcec5141b96532473ddd8f96d3a715bd73427..65b5c86ed54302a26fc203f113642d46fcd6cf33 100644
--- a/indra/newview/llavatariconctrl.h
+++ b/indra/newview/llavatariconctrl.h
@@ -103,6 +103,8 @@ class LLAvatarIconCtrl
 	const std::string&	getFirstName() const { return mFirstName; }
 	const std::string&	getLastName() const { return mLastName; }
 
+	void setDrawTooltip(bool value) { mDrawTooltip = value;}
+
 protected:
 	LLUUID				mAvatarId;
 	std::string			mFirstName;
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 3a07c6e5efdba952109910e04ef09337beddf496..7b2dc02864f5a4a2e33b77fd1da9133d0cb6ddf1 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -37,14 +37,34 @@
 // newview
 #include "llcallingcard.h" // for LLAvatarTracker
 #include "llcachename.h"
+#include "llrecentpeople.h"
 #include "llvoiceclient.h"
+#include "llviewercontrol.h"	// for gSavedSettings
 
 static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
 
+// Last interaction time update period.
+static const F32 LIT_UPDATE_PERIOD = 5;
+
 // Maximum number of avatars that can be added to a list in one pass.
 // Used to limit time spent for avatar list update per frame.
 static const unsigned ADD_LIMIT = 50;
 
+void LLAvatarList::toggleIcons()
+{
+	// Save the new value for new items to use.
+	mShowIcons = !mShowIcons;
+	gSavedSettings.setBOOL(mIconParamName, mShowIcons);
+	
+	// Show/hide icons for all existing items.
+	std::vector<LLPanel*> items;
+	getItems(items);
+	for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+	{
+		static_cast<LLAvatarListItem*>(*it)->setAvatarIconVisible(mShowIcons);
+	}
+}
+
 static bool findInsensitive(std::string haystack, const std::string& needle_upper)
 {
     LLStringUtil::toUpper(haystack);
@@ -58,28 +78,63 @@ static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_
 
 LLAvatarList::Params::Params()
 : ignore_online_status("ignore_online_status", false)
+, show_last_interaction_time("show_last_interaction_time", false)
+, show_info_btn("show_info_btn", true)
+, show_profile_btn("show_profile_btn", true)
 {
 }
 
 LLAvatarList::LLAvatarList(const Params& p)
 :	LLFlatListView(p)
 , mIgnoreOnlineStatus(p.ignore_online_status)
+, mShowLastInteractionTime(p.show_last_interaction_time)
 , mContextMenu(NULL)
 , mDirty(true) // to force initial update
+, mLITUpdateTimer(NULL)
+, mShowIcons(true)
+, mShowInfoBtn(p.show_info_btn)
+, mShowProfileBtn(p.show_profile_btn)
 {
 	setCommitOnSelectionChange(true);
 
 	// Set default sort order.
 	setComparator(&NAME_COMPARATOR);
+
+	if (mShowLastInteractionTime)
+	{
+		mLITUpdateTimer = new LLTimer();
+		mLITUpdateTimer->setTimerExpirySec(0); // zero to force initial update
+		mLITUpdateTimer->start();
+	}
+}
+
+LLAvatarList::~LLAvatarList()
+{
+	delete mLITUpdateTimer;
+}
+
+void LLAvatarList::setShowIcons(std::string param_name)
+{
+	mIconParamName= param_name;
+	mShowIcons = gSavedSettings.getBOOL(mIconParamName);
 }
 
 // virtual
 void LLAvatarList::draw()
 {
+	// *NOTE dzaporozhan
+	// Call refresh() after draw() to avoid flickering of avatar list items.
+
+	LLFlatListView::draw();
+
 	if (mDirty)
 		refresh();
 
-	LLFlatListView::draw();
+	if (mShowLastInteractionTime && mLITUpdateTimer->hasExpired())
+	{
+		updateLastInteractionTimes();
+		mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); // restart the timer
+	}
 }
 
 void LLAvatarList::setNameFilter(const std::string& filter)
@@ -193,15 +248,18 @@ void LLAvatarList::refresh()
 void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
 {
 	LLAvatarListItem* item = new LLAvatarListItem();
-	item->showStatus(false);
 	item->showInfoBtn(true);
 	item->showSpeakingIndicator(true);
 	item->setName(name);
 	item->setAvatarId(id, mIgnoreOnlineStatus);
 	item->setOnline(mIgnoreOnlineStatus ? true : is_online);
+	item->showLastInteractionTime(mShowLastInteractionTime);
 	item->setContextMenu(mContextMenu);
 
 	item->childSetVisible("info_btn", false);
+	item->setAvatarIconVisible(mShowIcons);
+	item->setShowInfoBtn(mShowInfoBtn);
+	item->setShowProfileBtn(mShowProfileBtn);
 
 	addItem(item, id, pos);
 }
@@ -253,6 +311,54 @@ void LLAvatarList::computeDifference(
 	vadded.erase(it, vadded.end());
 }
 
+static std::string format_secs(S32 secs)
+{
+	// *TODO: reinventing the wheel?
+	// *TODO: i18n
+	static const int LL_AL_MIN		= 60;
+	static const int LL_AL_HOUR		= LL_AL_MIN * 60;
+	static const int LL_AL_DAY		= LL_AL_HOUR * 24;
+	static const int LL_AL_WEEK		= LL_AL_DAY * 7;
+	static const int LL_AL_MONTH	= LL_AL_DAY * 31;
+	static const int LL_AL_YEAR		= LL_AL_DAY * 365;
+
+    std::string s;
+
+    if (secs >= LL_AL_YEAR)
+        s = llformat("%dy", secs / LL_AL_YEAR);
+    else if (secs >= LL_AL_MONTH)
+        s = llformat("%dmon", secs / LL_AL_MONTH);
+    else if (secs >= LL_AL_WEEK)
+        s = llformat("%dw", secs / LL_AL_WEEK);
+    else if (secs >= LL_AL_DAY)
+        s = llformat("%dd", secs / LL_AL_DAY);
+    else if (secs >= LL_AL_HOUR)
+        s = llformat("%dh", secs / LL_AL_HOUR);
+    else if (secs >= LL_AL_MIN)
+        s = llformat("%dm", secs / LL_AL_MIN);
+    else
+        s = llformat("%ds", secs);
+
+    return s;
+}
+
+// Refresh shown time of our last interaction with all listed avatars.
+void LLAvatarList::updateLastInteractionTimes()
+{
+	S32 now = (S32) LLDate::now().secondsSinceEpoch();
+	std::vector<LLPanel*> items;
+	getItems(items);
+
+	for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+	{
+		// *TODO: error handling
+		LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it);
+		S32 secs_since = now - (S32) LLRecentPeople::instance().getDate(item->getAvatarId()).secondsSinceEpoch();
+		if (secs_since >= 0)
+			item->setLastInteractionTime(format_secs(secs_since));
+	}
+}
+
 bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
 {
 	const LLAvatarListItem* avatar_item1 = dynamic_cast<const LLAvatarListItem*>(item1);
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index a83a72b26ca94ae48cd276b1a4c966c52ca0c4b1..51d3760d3937169ca6ed50e1c74644f65919a110 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -37,6 +37,8 @@
 
 #include "llavatarlistitem.h"
 
+class LLTimer;
+
 /**
  * Generic list of avatars.
  * 
@@ -56,11 +58,14 @@ class LLAvatarList : public LLFlatListView
 	struct Params : public LLInitParam::Block<Params, LLFlatListView::Params> 
 	{
 		Optional<bool> ignore_online_status; // show all items as online
+		Optional<bool> show_last_interaction_time; // show most recent interaction time. *HACK: move this to a derived class
+		Optional<bool> show_info_btn;
+		Optional<bool> show_profile_btn;
 		Params();
 	};
 
 	LLAvatarList(const Params&);
-	virtual	~LLAvatarList() {}
+	virtual	~LLAvatarList();
 
 	virtual void draw(); // from LLView
 
@@ -70,7 +75,11 @@ class LLAvatarList : public LLFlatListView
 
 	void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; }
 
+	void toggleIcons();
 	void sortByName();
+	void setShowIcons(std::string param_name);
+	bool getIconsVisible() const { return mShowIcons; }
+	const std::string getIconParamName() const{return mIconParamName;}
 	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
 
 protected:
@@ -81,12 +90,19 @@ class LLAvatarList : public LLFlatListView
 		const std::vector<LLUUID>& vnew,
 		std::vector<LLUUID>& vadded,
 		std::vector<LLUUID>& vremoved);
+	void updateLastInteractionTimes();
 
 private:
 
 	bool mIgnoreOnlineStatus;
+	bool mShowLastInteractionTime;
 	bool mDirty;
+	bool mShowIcons;
+	bool mShowInfoBtn;
+	bool mShowProfileBtn;
 
+	LLTimer*				mLITUpdateTimer; // last interaction time update timer
+	std::string				mIconParamName;
 	std::string				mNameFilter;
 	uuid_vector_t			mIDs;
 
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index ebc79aae48577fe33f41080fe673133cda1b5606..a7ac14c94862be1ce621247c6bbfd07fed892a7c 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -42,19 +42,26 @@
 #include "llavatariconctrl.h"
 #include "llbutton.h"
 
-
 LLAvatarListItem::LLAvatarListItem()
 :	LLPanel(),
 	mAvatarIcon(NULL),
 	mAvatarName(NULL),
-	mStatus(NULL),
+	mLastInteractionTime(NULL),
 	mSpeakingIndicator(NULL),
 	mInfoBtn(NULL),
 	mProfileBtn(NULL),
 	mContextMenu(NULL),
-	mOnlineStatus(E_UNKNOWN)
+	mOnlineStatus(E_UNKNOWN),
+	mShowInfoBtn(true),
+	mShowProfileBtn(true)
 {
 	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml");
+	// Remember avatar icon width including its padding from the name text box,
+	// so that we can hide and show the icon again later.
+
+	mIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft;
+	mInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight;
+	mProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight;
 }
 
 LLAvatarListItem::~LLAvatarListItem()
@@ -67,8 +74,8 @@ BOOL  LLAvatarListItem::postBuild()
 {
 	mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon");
 	mAvatarName = getChild<LLTextBox>("avatar_name");
-	mStatus = getChild<LLTextBox>("avatar_status");
-
+	mLastInteractionTime = getChild<LLTextBox>("last_interaction");
+	
 	mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator");
 	mInfoBtn = getChild<LLButton>("info_btn");
 	mProfileBtn = getChild<LLButton>("profile_btn");
@@ -90,12 +97,6 @@ BOOL  LLAvatarListItem::postBuild()
 		rect.setLeftTopAndSize(mName->getRect().mLeft, mName->getRect().mTop, mName->getRect().getWidth() + 30, mName->getRect().getHeight());
 		mName->setRect(rect);
 
-		if(mStatus)
-		{
-			rect.setLeftTopAndSize(mStatus->getRect().mLeft + 30, mStatus->getRect().mTop, mStatus->getRect().getWidth(), mStatus->getRect().getHeight());
-			mStatus->setRect(rect);
-		}
-
 		if(mLocator)
 		{
 			rect.setLeftTopAndSize(mLocator->getRect().mLeft + 30, mLocator->getRect().mTop, mLocator->getRect().getWidth(), mLocator->getRect().getHeight());
@@ -115,8 +116,8 @@ BOOL  LLAvatarListItem::postBuild()
 void LLAvatarListItem::onMouseEnter(S32 x, S32 y, MASK mask)
 {
 	childSetVisible("hovered_icon", true);
-	mInfoBtn->setVisible(true);
-	mProfileBtn->setVisible(true);
+	mInfoBtn->setVisible(mShowInfoBtn);
+	mProfileBtn->setVisible(mShowProfileBtn);
 
 	LLPanel::onMouseEnter(x, y, mask);
 }
@@ -130,11 +131,6 @@ void LLAvatarListItem::onMouseLeave(S32 x, S32 y, MASK mask)
 	LLPanel::onMouseLeave(x, y, mask);
 }
 
-void LLAvatarListItem::setStatus(const std::string& status)
-{
-	mStatus->setValue(status);
-}
-
 // virtual, called by LLAvatarTracker
 void LLAvatarListItem::changed(U32 mask)
 {
@@ -188,6 +184,67 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)
 	gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
 }
 
+void LLAvatarListItem::showLastInteractionTime(bool show)
+{
+	if (show)
+		return;
+
+	LLRect	name_rect	= mAvatarName->getRect();
+	LLRect	time_rect	= mLastInteractionTime->getRect();
+
+	mLastInteractionTime->setVisible(false);
+	name_rect.mRight += (time_rect.mRight - name_rect.mRight);
+	mAvatarName->setRect(name_rect);
+}
+
+void LLAvatarListItem::setLastInteractionTime(const std::string& val)
+{
+	mLastInteractionTime->setValue(val);
+}
+
+void LLAvatarListItem::setShowInfoBtn(bool show)
+{
+	// Already done? Then do nothing.
+	if(mShowInfoBtn == show)
+		return;
+	mShowInfoBtn = show;
+	S32 width_delta = show ? - mInfoBtnWidth : mInfoBtnWidth;
+
+	//Translating speaking indicator
+	mSpeakingIndicator->translate(width_delta, 0);
+	//Reshaping avatar name
+	mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight());
+}
+
+void LLAvatarListItem::setShowProfileBtn(bool show)
+{
+	// Already done? Then do nothing.
+	if(mShowProfileBtn == show)
+			return;
+	mShowProfileBtn = show;
+	S32 width_delta = show ? - mProfileBtnWidth : mProfileBtnWidth;
+
+	//Translating speaking indicator
+	mSpeakingIndicator->translate(width_delta, 0);
+	//Reshaping avatar name
+	mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight());
+}
+
+void LLAvatarListItem::setAvatarIconVisible(bool visible)
+{
+	// Already done? Then do nothing.
+	if (mAvatarIcon->getVisible() == (BOOL)visible)
+		return;
+
+	// Show/hide avatar icon.
+	mAvatarIcon->setVisible(visible);
+
+	// Move the avatar name horizontally by icon size + its distance from the avatar name.
+	LLRect name_rect = mAvatarName->getRect();
+	name_rect.mLeft += visible ? mIconWidth : -mIconWidth;
+	mAvatarName->setRect(name_rect);
+}
+
 void LLAvatarListItem::onInfoBtnClick()
 {
 	LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mAvatarId));
@@ -218,21 +275,6 @@ void LLAvatarListItem::onProfileBtnClick()
 	LLAvatarActions::showProfile(mAvatarId);
 }
 
-void LLAvatarListItem::showStatus(bool show_status)
-{
-	// *HACK: dirty hack until we can determine correct avatar status (EXT-1076).
-
-	if (show_status)
-		return;
-
-	LLRect	name_rect	= mAvatarName->getRect();
-	LLRect	status_rect	= mStatus->getRect();
-
-	mStatus->setVisible(show_status);
-	name_rect.mRight += (status_rect.mRight - name_rect.mRight);
-	mAvatarName->setRect(name_rect);
-}
-
 void LLAvatarListItem::setValue( const LLSD& value )
 {
 	if (!value.isMap()) return;;
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index b9cfed4b7baa52bc0536f74598ad060d0110c525..cd7a85c3dc5b4ca746df79c05067e027863b902d 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -60,10 +60,14 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 	virtual void setValue(const LLSD& value);
 	virtual void changed(U32 mask); // from LLFriendObserver
 
-	void setStatus(const std::string& status);
 	void setOnline(bool online);
 	void setName(const std::string& name);
 	void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
+	void setLastInteractionTime(const std::string& val);
+	//Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly
+	void setShowProfileBtn(bool hide);
+	void setShowInfoBtn(bool hide);
+	void setAvatarIconVisible(bool visible);
 	
 	const LLUUID& getAvatarId() const;
 	const std::string getAvatarName() const;
@@ -73,7 +77,7 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 
 	void showSpeakingIndicator(bool show) { mSpeakingIndicator->setVisible(show); }
 	void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); }
-	void showStatus(bool show_status);
+	void showLastInteractionTime(bool show);
 
 	void setContextMenu(ContextMenu* menu) { mContextMenu = menu; }
 
@@ -87,9 +91,9 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 
 	void onNameCache(const std::string& first_name, const std::string& last_name);
 
-	LLAvatarIconCtrl*mAvatarIcon;
+	LLAvatarIconCtrl* mAvatarIcon;
 	LLTextBox* mAvatarName;
-	LLTextBox* mStatus;
+	LLTextBox* mLastInteractionTime;
 	
 	LLOutputMonitorCtrl* mSpeakingIndicator;
 	LLButton* mInfoBtn;
@@ -98,6 +102,13 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 
 	LLUUID mAvatarId;
 	EOnlineStatus mOnlineStatus;
+	//Flag indicating that info/profile button shouldn't be shown at all.
+	//Speaker indicator and avatar name coords are translated accordingly
+	bool mShowInfoBtn;
+	bool mShowProfileBtn;
+	S32	 mIconWidth; // icon width + padding
+	S32  mInfoBtnWidth; //info btn width + padding
+	S32  mProfileBtnWidth; //profile btn width + padding
 };
 
 #endif //LL_LLAVATARLISTITEM_H
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 7a81d0c4a1d8e8d4213fb63a0fb23ad492da1675..e8812d87ee0501fe0be05c9fb99a68cbd65ef36a 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -62,7 +62,6 @@
 #include "llviewerwindow.h"
 #include "llvoavatar.h"
 #include "llimview.h"
-#include "llimpanel.h"
 
 ///----------------------------------------------------------------------------
 /// Local function declarations, constants, enums, and typedefs
@@ -719,18 +718,8 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
 
 			// If there's an open IM session with this agent, send a notification there too.
 			LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
-			LLFloaterIMPanel *floater = gIMMgr->findFloaterBySession(session_id);
-			if (floater)
-			{
-				std::string notifyMsg = notification->getMessage();
-				if (!notifyMsg.empty())
-				{
-					floater->addHistoryLine(notifyMsg,LLUIColorTable::instance().getColor("SystemChatColor"));
-				}
-			}
-
-			//*TODO instead of adding IM message about online/offline status
-			//do something like graying avatar icon on messages from a user that went offline, and  make it colored when online.
+			std::string notify_msg = notification->getMessage();
+			LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
 		}
 
 		mModifyMask |= LLFriendObserver::ONLINE;
diff --git a/indra/newview/llcapabilitylistener.cpp b/indra/newview/llcapabilitylistener.cpp
index 4a3e9aec9c14763ccd7c2ab6acb4535b8dafdf48..ed9613c1bccf2c69039490edfb700abf93874888 100644
--- a/indra/newview/llcapabilitylistener.cpp
+++ b/indra/newview/llcapabilitylistener.cpp
@@ -114,6 +114,7 @@ bool LLCapabilityListener::capListener(const LLSD& request)
         // This capability is supported by the region to which we're talking.
         LLHTTPClient::post(url, payload,
                            new LLSDMessage::EventResponder(LLEventPumps::instance(),
+                                                           request,
                                                            mProvider.getDescription(),
                                                            cap, reply, error),
                            LLSD(),  // headers
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index 77f941eef0ecdf72c0caf227225028f482da9abb..642742257264bbd1595b42b29c80ba9408f77b8f 100644
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -40,6 +40,8 @@
 #include "llbottomtray.h"
 #include "llviewerwindow.h"
 #include "llrootview.h"
+#include "llsyswellwindow.h"
+#include "llfloaterreg.h"
 
 #include <algorithm>
 
@@ -128,7 +130,7 @@ void LLChannelManager::onLoginCompleted()
 	S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
 	S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
 	mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
-	mStartUpChannel->setShowToasts(true);
+	mStartUpChannel->setMouseDownCallback(boost::bind(&LLSysWellWindow::onStartUpToastClick, LLFloaterReg::getTypedInstance<LLSysWellWindow>("syswell_window"), _2, _3, _4));
 
 	mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
 	mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime"));
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index ebf46a6e3ffb339c07301d9ff9c60e83b22d5fa6..e561507e69bc5324c317103b12056dac9ab9f37d 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -38,9 +38,251 @@
 #include "llscrollcontainer.h"
 #include "llavatariconctrl.h"
 
+#include "llimview.h"
+#include "llcallingcard.h" //for LLAvatarTracker
+#include "llagentdata.h"
+#include "llavataractions.h"
+#include "lltrans.h"
+#include "llfloaterreg.h"
+#include "llmutelist.h"
+
 static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
 static const std::string MESSAGE_USERNAME_DATE_SEPARATOR(" ----- ");
 
+std::string formatCurrentTime()
+{
+	time_t utc_time;
+	utc_time = time_corrected();
+	std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
+		+LLTrans::getString("TimeMin")+"] ";
+
+	LLSD substitution;
+
+	substitution["datetime"] = (S32) utc_time;
+	LLStringUtil::format (timeStr, substitution);
+
+	return timeStr;
+}
+
+class LLChatHistoryHeader: public LLPanel
+{
+public:
+	static LLChatHistoryHeader* createInstance(const std::string& file_name)
+	{
+		LLChatHistoryHeader* pInstance = new LLChatHistoryHeader;
+		LLUICtrlFactory::getInstance()->buildPanel(pInstance, file_name);	
+		return pInstance;
+	}
+
+	BOOL handleMouseUp(S32 x, S32 y, MASK mask)
+	{
+		return LLPanel::handleMouseUp(x,y,mask);
+	}
+
+	void onObjectIconContextMenuItemClicked(const LLSD& userdata)
+	{
+		std::string level = userdata.asString();
+
+		if (level == "profile")
+		{
+		}
+		else if (level == "block")
+		{
+			LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT));
+		}
+	}
+
+	void onAvatarIconContextMenuItemClicked(const LLSD& userdata)
+	{
+		std::string level = userdata.asString();
+
+		if (level == "profile")
+		{
+			LLAvatarActions::showProfile(getAvatarId());
+		}
+		else if (level == "im")
+		{
+			LLAvatarActions::startIM(getAvatarId());
+		}
+		else if (level == "add")
+		{
+			std::string name;
+			name.assign(getFirstName());
+			name.append(" ");
+			name.append(getLastName());
+
+			LLAvatarActions::requestFriendshipDialog(getAvatarId(), name);
+		}
+		else if (level == "remove")
+		{
+			LLAvatarActions::removeFriendDialog(getAvatarId());
+		}
+	}
+
+	BOOL postBuild()
+	{
+		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+		registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
+		registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));
+
+		LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+		mPopupMenuHandleAvatar = menu->getHandle();
+
+		menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+		mPopupMenuHandleObject = menu->getHandle();
+
+		LLPanel* visible_panel = getChild<LLPanel>("im_header");
+		visible_panel->setMouseDownCallback(boost::bind(&LLChatHistoryHeader::onHeaderPanelClick, this, _2, _3, _4));
+
+		return LLPanel::postBuild();
+	}
+
+	bool pointInChild(const std::string& name,S32 x,S32 y)
+	{
+		LLUICtrl* child = findChild<LLUICtrl>(name);
+		if(!child)
+			return false;
+		
+		LLView* parent = child->getParent();
+		if(parent!=this)
+		{
+			x-=parent->getRect().mLeft;
+			y-=parent->getRect().mBottom;
+		}
+
+		S32 local_x = x - child->getRect().mLeft ;
+		S32 local_y = y - child->getRect().mBottom ;
+		return 	child->pointInView(local_x, local_y);
+	}
+
+	BOOL handleRightMouseDown(S32 x, S32 y, MASK mask)
+	{
+		if(pointInChild("avatar_icon",x,y) || pointInChild("user_name",x,y))
+		{
+			showContextMenu(x,y);
+			return TRUE;
+		}
+
+		return LLPanel::handleRightMouseDown(x,y,mask);
+	}
+
+	void onHeaderPanelClick(S32 x, S32 y, MASK mask)
+	{
+		LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mAvatarID));
+	}
+
+	const LLUUID&		getAvatarId () const { return mAvatarID;}
+	const std::string&	getFirstName() const { return mFirstName; }
+	const std::string&	getLastName	() const { return mLastName; }
+
+	void setup(const LLChat& chat) 
+	{
+		mAvatarID = chat.mFromID;
+		mSourceType = chat.mSourceType;
+		gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4));
+		if(chat.mFromID.isNull())
+		{
+			mSourceType = CHAT_SOURCE_SYSTEM;
+		}
+
+
+		LLTextBox* userName = getChild<LLTextBox>("user_name");
+		
+		if(!chat.mFromName.empty())
+		{
+			userName->setValue(chat.mFromName);
+			mFrom = chat.mFromName;
+		}
+		else
+		{
+			std::string SL = LLTrans::getString("SECOND_LIFE");
+			userName->setValue(SL);
+		}
+		
+		LLTextBox* timeBox = getChild<LLTextBox>("time_box");
+		timeBox->setValue(formatCurrentTime());
+
+		LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+
+		if(mSourceType != CHAT_SOURCE_AGENT)
+			icon->setDrawTooltip(false);
+
+		if(!chat.mFromID.isNull())
+		{
+			icon->setValue(chat.mFromID);
+		}
+
+	} 
+
+	void nameUpdatedCallback(const LLUUID& id,const std::string& first,const std::string& last,BOOL is_group)
+	{
+		if (id != mAvatarID)
+			return;
+		mFirstName = first;
+		mLastName = last;
+	}
+protected:
+	void showContextMenu(S32 x,S32 y)
+	{
+		if(mSourceType == CHAT_SOURCE_SYSTEM)
+			showSystemContextMenu(x,y);
+		if(mSourceType == CHAT_SOURCE_AGENT)
+			showAvatarContextMenu(x,y);
+		if(mSourceType == CHAT_SOURCE_OBJECT)
+			showObjectContextMenu(x,y);
+	}
+
+	void showSystemContextMenu(S32 x,S32 y)
+	{
+	}
+	
+	void showObjectContextMenu(S32 x,S32 y)
+	{
+		LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleObject.get();
+		if(menu)
+			LLMenuGL::showPopup(this, menu, x, y);
+	}
+	
+	void showAvatarContextMenu(S32 x,S32 y)
+	{
+		LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleAvatar.get();
+
+		if(menu)
+		{
+			bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL;
+			
+			menu->setItemEnabled("Add Friend", !is_friend);
+			menu->setItemEnabled("Remove Friend", is_friend);
+
+			if(gAgentID == mAvatarID)
+			{
+				menu->setItemEnabled("Add Friend", false);
+				menu->setItemEnabled("Send IM", false);
+				menu->setItemEnabled("Remove Friend", false);
+			}
+
+			menu->buildDrawLabels();
+			menu->updateParent(LLMenuGL::sMenuContainer);
+			LLMenuGL::showPopup(this, menu, x, y);
+		}
+	}
+
+	
+
+protected:
+	LLHandle<LLView>	mPopupMenuHandleAvatar;
+	LLHandle<LLView>	mPopupMenuHandleObject;
+
+	LLUUID			    mAvatarID;
+	EChatSourceType		mSourceType;
+	std::string			mFirstName;
+	std::string			mLastName;
+	std::string			mFrom;
+
+};
+
+
 LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
 : LLTextEditor(p),
 mMessageHeaderFilename(p.message_header),
@@ -48,7 +290,7 @@ mMessageSeparatorFilename(p.message_separator),
 mLeftTextPad(p.left_text_pad),
 mRightTextPad(p.right_text_pad),
 mLeftWidgetPad(p.left_widget_pad),
-mRightWidgetPad(p.rigth_widget_pad)
+mRightWidgetPad(p.right_widget_pad)
 {
 }
 
@@ -78,49 +320,49 @@ LLView* LLChatHistory::getSeparator()
 	return separator;
 }
 
-LLView* LLChatHistory::getHeader(const LLUUID& avatar_id, std::string& from, std::string& time)
+LLView* LLChatHistory::getHeader(const LLChat& chat)
 {
-	LLPanel* header = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessageHeaderFilename, NULL, LLPanel::child_registry_t::instance());
-	LLTextBox* userName = header->getChild<LLTextBox>("user_name");
-	userName->setValue(from);
-	LLTextBox* timeBox = header->getChild<LLTextBox>("time_box");
-	timeBox->setValue(time);
-	if(!avatar_id.isNull())
-	{
-		LLAvatarIconCtrl* icon = header->getChild<LLAvatarIconCtrl>("avatar_icon");
-		icon->setValue(avatar_id);
-	}
+	LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename);
+	header->setup(chat);
 	return header;
 }
 
-void LLChatHistory::appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params)
+void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params)
 {
 	LLView* view = NULL;
 	std::string view_text;
 
-	if (mLastFromName == from)
+	if (mLastFromName == chat.mFromName)
 	{
 		view = getSeparator();
-		view_text = " ";
+		view_text = "\n";
 	}
 	else
 	{
-		view = getHeader(avatar_id, from, time);
-		view_text = "\n" + from + MESSAGE_USERNAME_DATE_SEPARATOR + time;
+		view = getHeader(chat);
+		view_text = chat.mFromName + MESSAGE_USERNAME_DATE_SEPARATOR + formatCurrentTime() + '\n';
 	}
 	//Prepare the rect for the view
 	LLRect target_rect = getDocumentView()->getRect();
-	target_rect.mLeft += mLeftWidgetPad;
+	// squeeze down the widget by subtracting padding off left and right
+	target_rect.mLeft += mLeftWidgetPad + mHPad;
 	target_rect.mRight -= mRightWidgetPad;
 	view->reshape(target_rect.getWidth(), view->getRect().getHeight());
 	view->setOrigin(target_rect.mLeft, view->getRect().mBottom);
 
-	appendWidget(view, view_text, FALSE, TRUE, mLeftWidgetPad, 0);
+	LLInlineViewSegment::Params p;
+	p.view = view;
+	p.force_newline = true;
+	p.left_pad = mLeftWidgetPad;
+	p.right_pad = mRightWidgetPad;
+
+	appendWidget(p, view_text, false);
 
 	//Append the text message
-	appendText(message, TRUE, style_params);
+	std::string message = chat.mText + '\n';
+	appendText(message, FALSE, style_params);
 
-	mLastFromName = from;
+	mLastFromName = chat.mFromName;
 	blockUndo();
 	setCursorAndScrollToEnd();
 }
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
index d6eccf896af9d987ca481363d96ccfb9c53ec396..92dcfdd958265b23a8fd86289a3420fba9543773 100644
--- a/indra/newview/llchathistory.h
+++ b/indra/newview/llchathistory.h
@@ -34,6 +34,7 @@
 #define LLCHATHISTORY_H_
 
 #include "lltexteditor.h"
+#include "llchat.h"
 
 //Chat log widget allowing addition of a message as a widget 
 class LLChatHistory : public LLTextEditor
@@ -52,7 +53,7 @@ class LLChatHistory : public LLTextEditor
 			//Widget left padding from the scroll rect
 			Optional<S32>			left_widget_pad;
 			//Widget right padding from the scroll rect
-			Optional<S32>			rigth_widget_pad;
+			Optional<S32>			right_widget_pad;
 
 			Params()
 			:	message_header("message_header"),
@@ -60,7 +61,7 @@ class LLChatHistory : public LLTextEditor
 				left_text_pad("left_text_pad"),
 				right_text_pad("right_text_pad"),
 				left_widget_pad("left_widget_pad"),
-				rigth_widget_pad("rigth_widget_pad")
+				right_widget_pad("right_widget_pad")
 				{
 				}
 
@@ -85,7 +86,7 @@ class LLChatHistory : public LLTextEditor
 		 * @param time time of a message.
 		 * @return pointer to LLView header object.
 		 */
-		LLView* getHeader(const LLUUID& avatar_id, std::string& from, std::string& time);
+		LLView* getHeader(const LLChat& chat);
 
 	public:
 		~LLChatHistory();
@@ -94,11 +95,11 @@ class LLChatHistory : public LLTextEditor
 		 * Appends a widget message.
 		 * If last user appended message, concurs with current user,
 		 * separator is added before the message, otherwise header is added.
-		 * @param from owner of a message.
+		 * @param chat - base chat message.
 		 * @param time time of a message.
 		 * @param message message itself.
 		 */
-		void appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params);
+		void appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params);
 
 	private:
 		std::string mLastFromName;
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 61a60a24be65fb6994289627704ec73db60911f4..bad61101c1bceda1f056cc080ed7a64bb81a4e82 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -37,7 +37,6 @@
 #include "llbottomtray.h"
 #include "llgroupactions.h"
 #include "lliconctrl.h"
-#include "llimpanel.h"				// LLFloaterIMPanel
 #include "llimfloater.h"
 #include "llimview.h"
 #include "llfloaterreg.h"
@@ -58,8 +57,6 @@ static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t4("chiclet_im_p2p");
 static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t5("chiclet_im_group");
 
 S32 LLNotificationChiclet::mUreadSystemNotifications = 0;
-S32 LLNotificationChiclet::mUreadIMNotifications = 0;
-
 
 boost::signals2::signal<LLChiclet* (const LLUUID&),
 		LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > >
@@ -100,7 +97,6 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p)
 	// connect counter handlers to the signals
 	connectCounterUpdatersToSignal("notify");
 	connectCounterUpdatersToSignal("groupnotify");
-	connectCounterUpdatersToSignal("notifytoast");
 }
 
 LLNotificationChiclet::~LLNotificationChiclet()
@@ -114,16 +110,8 @@ void LLNotificationChiclet::connectCounterUpdatersToSignal(std::string notificat
 	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type);
 	if(n_handler)
 	{
-		if(notification_type == "notifytoast")
-		{
-			n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this));
-			n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this));
-		}
-		else
-		{
-			n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this));
-			n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this));
-		}
+		n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this));
+		n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this));
 	}
 }
 
@@ -148,12 +136,6 @@ void LLNotificationChiclet::setToggleState(BOOL toggled) {
 	mButton->setToggleState(toggled);
 }
 
-void LLNotificationChiclet::updateUreadIMNotifications()
-{
-	mUreadIMNotifications = gIMMgr->getNumberOfUnreadIM();
-	setCounter(mUreadSystemNotifications + mUreadIMNotifications);
-}
-
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
@@ -1398,7 +1380,7 @@ void LLTalkButton::onClick_ShowBtn()
 
 
 	LLAvatarListItem* item = new LLAvatarListItem();
-	item->showStatus(true);
+	item->showLastInteractionTime(false);
 	item->showInfoBtn(true);
 	item->showSpeakingIndicator(true);
 	item->reshape(mPrivateCallPanel->getRect().getWidth(), item->getRect().getHeight(), FALSE);
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
index d1153a075db6011369176ee8479f6f12f8b778a1..6eefd9829f1139483cb392970e00271a0f084671 100644
--- a/indra/newview/llchiclet.h
+++ b/indra/newview/llchiclet.h
@@ -608,10 +608,9 @@ class LLNotificationChiclet : public LLChiclet
 
 	/*virtual*/ ~ LLNotificationChiclet();
 
-	// methods for updating a number of unread System or IM notifications
-	void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications + mUreadIMNotifications); }
-	void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications + mUreadIMNotifications); }
-	void updateUreadIMNotifications();
+	// methods for updating a number of unread System notifications
+	void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); }
+	void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); }
 	void setToggleState(BOOL toggled);
 
 protected:
@@ -622,7 +621,6 @@ class LLNotificationChiclet : public LLChiclet
 	friend class LLUICtrlFactory;
 
 	static S32 mUreadSystemNotifications;
-	static S32 mUreadIMNotifications;
 
 protected:
 	LLButton* mButton;
diff --git a/indra/newview/llclassifiedinfo.cpp b/indra/newview/llclassifiedinfo.cpp
index 5cf1579d0e0cc71616d80cadd6e93eb9545d1448..5fcafbeca6097461b41dbbcba25614fd140c1e22 100644
--- a/indra/newview/llclassifiedinfo.cpp
+++ b/indra/newview/llclassifiedinfo.cpp
@@ -38,35 +38,19 @@
 LLClassifiedInfo::cat_map LLClassifiedInfo::sCategories;
 
 // static
-void LLClassifiedInfo::loadCategories(LLUserAuth::options_t classified_options)
+void LLClassifiedInfo::loadCategories(const LLSD& options)
 {
-	LLUserAuth::options_t::iterator resp_it;
-	for (resp_it = classified_options.begin(); 
-		 resp_it != classified_options.end(); 
-		 ++resp_it)
+	for(LLSD::array_const_iterator resp_it = options.beginArray(),
+		end = options.endArray(); resp_it != end; ++resp_it)
 	{
-		const LLUserAuth::response_t& response = *resp_it;
-
-		LLUserAuth::response_t::const_iterator option_it;
-
-		S32 cat_id = 0;
-		option_it = response.find("category_id");
-		if (option_it != response.end())
+		LLSD name = (*resp_it)["category_name"];
+		if(name.isDefined())
 		{
-			cat_id = atoi(option_it->second.c_str());
+			LLSD id = (*resp_it)["category_id"];
+			if(id.isDefined())
+			{
+				LLClassifiedInfo::sCategories[id.asInteger()] = name.asString();
+			}
 		}
-		else
-		{
-			continue;
-		}
-
-		// Add the category id/name pair
-		option_it = response.find("category_name");
-		if (option_it != response.end())
-		{
-			LLClassifiedInfo::sCategories[cat_id] = option_it->second;
-		}
-
 	}
-
 }
diff --git a/indra/newview/llclassifiedinfo.h b/indra/newview/llclassifiedinfo.h
index cc5a6bf28fe341d4630c1afbaff91f3150060cca..37134c7e5bbd7cb7223f0d57c1c8b7f72bf05b9c 100644
--- a/indra/newview/llclassifiedinfo.h
+++ b/indra/newview/llclassifiedinfo.h
@@ -37,7 +37,6 @@
 
 #include "v3dmath.h"
 #include "lluuid.h"
-#include "lluserauth.h"
 
 class LLMessageSystem;
 
@@ -46,7 +45,7 @@ class LLClassifiedInfo
 public:
 	LLClassifiedInfo() {}
 
-	static void loadCategories(LLUserAuth::options_t event_options);
+	static void loadCategories(const LLSD& options);
 
 	typedef std::map<U32, std::string> cat_map;
 	static	cat_map sCategories;
diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index 979a1a9a60a2cbff7657518151475029aabede3c..c4bfd719991dffdbbbe1f732dd8b4b03ba87da72 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -35,6 +35,8 @@
 #include "lluictrlfactory.h"
 #include "lltextbox.h"
 #include "lllineeditor.h"
+#include "llviewercontrol.h"
+#include "llversionviewer.h"
 
 #include "llcurrencyuimanager.h"
 
@@ -156,6 +158,11 @@ void LLCurrencyUIManager::Impl::updateCurrencyInfo()
 		"secureSessionId",
 		gAgent.getSecureSessionID().asString());
 	keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
+	keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+	keywordArgs.appendInt("viewerMajorVersion", LL_VERSION_MAJOR);
+	keywordArgs.appendInt("viewerMinorVersion", LL_VERSION_MINOR);
+	keywordArgs.appendInt("viewerPatchVersion", LL_VERSION_PATCH);
+	keywordArgs.appendInt("viewerBuildVersion", LL_VERSION_BUILD);
 	
 	LLXMLRPCValue params = LLXMLRPCValue::createArray();
 	params.append(keywordArgs);
@@ -209,7 +216,12 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
 	{
 		keywordArgs.appendString("password", password);
 	}
-	
+	keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+	keywordArgs.appendInt("viewerMajorVersion", LL_VERSION_MAJOR);
+	keywordArgs.appendInt("viewerMinorVersion", LL_VERSION_MINOR);
+	keywordArgs.appendInt("viewerPatchVersion", LL_VERSION_PATCH);
+	keywordArgs.appendInt("viewerBuildVersion", LL_VERSION_BUILD);
+
 	LLXMLRPCValue params = LLXMLRPCValue::createArray();
 	params.append(keywordArgs);
 
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 976f02eeb7f8262b90ebbab32362a1ad59bcf876..d8c34581d5db20381eb4b087981a81d0805f03ec 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -442,6 +442,7 @@ void LLRenderPass::renderTexture(U32 type, U32 mask)
 
 void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture)
 {
+	llpushcallstacks ;
 	for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)	
 	{
 		LLDrawInfo* pparams = *i;
diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp
index 45f4b4fbd04c47edd184a1e806cca80d86eadbe8..527656ab6b87f36a88f691b8cf4138f6b78da8ea 100644
--- a/indra/newview/lldriverparam.cpp
+++ b/indra/newview/lldriverparam.cpp
@@ -224,6 +224,7 @@ void LLDriverParam::setAvatar(LLVOAvatar *avatarp)
 		}
 	}
 	*new_param = *this;
+	new_param->setIsDummy(FALSE);
 	return new_param;
 }
 
diff --git a/indra/newview/lleventinfo.cpp b/indra/newview/lleventinfo.cpp
index d4175b6c846a9f3ee9919c32e1868bafa8d6e565..aabd7ed997ba7da1f9340fd7e734f5cdc5948ed8 100644
--- a/indra/newview/lleventinfo.cpp
+++ b/indra/newview/lleventinfo.cpp
@@ -33,7 +33,6 @@
 #include "llviewerprecompiledheaders.h"
 #include "lleventinfo.h"
 
-#include "llappviewer.h"	// for gPacificDaylightTime
 #include "lluuid.h"
 #include "message.h"
 
@@ -87,35 +86,19 @@ void LLEventInfo::unpack(LLMessageSystem *msg)
 }
 
 // static
-void LLEventInfo::loadCategories(LLUserAuth::options_t event_options)
+void LLEventInfo::loadCategories(const LLSD& options)
 {
-	LLUserAuth::options_t::iterator resp_it;
-	for (resp_it = event_options.begin(); 
-		 resp_it != event_options.end(); 
-		 ++resp_it)
+	for(LLSD::array_const_iterator resp_it = options.beginArray(),
+		end = options.endArray(); resp_it != end; ++resp_it)
 	{
-		const LLUserAuth::response_t& response = *resp_it;
-
-		LLUserAuth::response_t::const_iterator option_it;
-
-		S32 cat_id = 0;
-		option_it = response.find("category_id");
-		if (option_it != response.end())
+		LLSD name = (*resp_it)["category_name"];
+		if(name.isDefined())
 		{
-			cat_id = atoi(option_it->second.c_str());
+			LLSD id = (*resp_it)["category_id"];
+			if(id.isDefined())
+			{
+				LLEventInfo::sCategories[id.asInteger()] = name.asString();
+			}
 		}
-		else
-		{
-			continue;
-		}
-
-		// Add the category id/name pair
-		option_it = response.find("category_name");
-		if (option_it != response.end())
-		{
-			LLEventInfo::sCategories[cat_id] = option_it->second;
-		}
-
 	}
-
 }
diff --git a/indra/newview/lleventinfo.h b/indra/newview/lleventinfo.h
index 880517a9f4b5f3cb3608348d19ea1d41b4da22ec..493c6599837bb97bdc5101b9686ac17fad1929d9 100644
--- a/indra/newview/lleventinfo.h
+++ b/indra/newview/lleventinfo.h
@@ -37,7 +37,6 @@
 
 #include "v3dmath.h"
 #include "lluuid.h"
-#include "lluserauth.h"
 
 class LLMessageSystem;
 
@@ -48,7 +47,7 @@ class LLEventInfo
 
 	void unpack(LLMessageSystem *msg);
 
-	static void loadCategories(LLUserAuth::options_t event_options);
+	static void loadCategories(const LLSD& options);
 
 public:
 	std::string mName;
diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp
index 867fb0255a2ed94b14531d2fe669b3b24187833a..da20766e7ee48d389bceb3bbcb4dfe85475627c2 100644
--- a/indra/newview/lleventnotifier.cpp
+++ b/indra/newview/lleventnotifier.cpp
@@ -94,18 +94,16 @@ void LLEventNotifier::update()
 	}
 }
 
-void LLEventNotifier::load(const LLUserAuth::options_t& event_options)
+void LLEventNotifier::load(const LLSD& event_options)
 {
-	LLUserAuth::options_t::const_iterator resp_it;
-	for (resp_it = event_options.begin(); 
-		 resp_it != event_options.end(); 
-		 ++resp_it)
+	for(LLSD::array_const_iterator resp_it = event_options.beginArray(),
+		end = event_options.endArray(); resp_it != end; ++resp_it)
 	{
-		const LLUserAuth::response_t& response = *resp_it;
+		LLSD response = *resp_it;
 
 		LLEventNotification *new_enp = new LLEventNotification();
 
-		if (!new_enp->load(response))
+		if(!new_enp->load(response))
 		{
 			delete new_enp;
 			continue;
@@ -208,49 +206,46 @@ bool LLEventNotification::handleResponse(const LLSD& notification, const LLSD& r
 	return false;
 }
 
-BOOL LLEventNotification::load(const LLUserAuth::response_t &response)
+BOOL LLEventNotification::load(const LLSD& response)
 {
-
-	LLUserAuth::response_t::const_iterator option_it;
 	BOOL event_ok = TRUE;
-	option_it = response.find("event_id");
-	if (option_it != response.end())
+	LLSD option = response.get("event_id");
+	if (option.isDefined())
 	{
-		mEventID = atoi(option_it->second.c_str());
+		mEventID = option.asInteger();
 	}
 	else
 	{
 		event_ok = FALSE;
 	}
 
-	option_it = response.find("event_name");
-	if (option_it != response.end())
+	option = response.get("event_name");
+	if (option.isDefined())
 	{
-		llinfos << "Event: " << option_it->second << llendl;
-		mEventName = option_it->second;
+		llinfos << "Event: " << option.asString() << llendl;
+		mEventName = option.asString();
 	}
 	else
 	{
 		event_ok = FALSE;
 	}
 
-
-	option_it = response.find("event_date");
-	if (option_it != response.end())
+	option = response.get("event_date");
+	if (option.isDefined())
 	{
-		llinfos << "EventDate: " << option_it->second << llendl;
-		mEventDateStr = option_it->second;
+		llinfos << "EventDate: " << option.asString() << llendl;
+		mEventDateStr = option.asString();
 	}
 	else
 	{
 		event_ok = FALSE;
 	}
 
-	option_it = response.find("event_date_ut");
-	if (option_it != response.end())
+	option = response.get("event_date_ut");
+	if (option.isDefined())
 	{
-		llinfos << "EventDate: " << option_it->second << llendl;
-		mEventDate = strtoul(option_it->second.c_str(), NULL, 10);
+		llinfos << "EventDate: " << option.asString() << llendl;
+		mEventDate = strtoul(option.asString().c_str(), NULL, 10);
 	}
 	else
 	{
@@ -262,44 +257,44 @@ BOOL LLEventNotification::load(const LLUserAuth::response_t &response)
 	S32 x_region = 0;
 	S32 y_region = 0;
 
-	option_it = response.find("grid_x");
-	if (option_it != response.end())
+	option = response.get("grid_x");
+	if (option.isDefined())
 	{
-		llinfos << "GridX: " << option_it->second << llendl;
-		grid_x= atoi(option_it->second.c_str());
+		llinfos << "GridX: " << option.asInteger() << llendl;
+		grid_x= option.asInteger();
 	}
 	else
 	{
 		event_ok = FALSE;
 	}
 
-	option_it = response.find("grid_y");
-	if (option_it != response.end())
+	option = response.get("grid_y");
+	if (option.isDefined())
 	{
-		llinfos << "GridY: " << option_it->second << llendl;
-		grid_y = atoi(option_it->second.c_str());
+		llinfos << "GridY: " << option.asInteger() << llendl;
+		grid_y = option.asInteger();
 	}
 	else
 	{
 		event_ok = FALSE;
 	}
 
-	option_it = response.find("x_region");
-	if (option_it != response.end())
+	option = response.get("x_region");
+	if (option.isDefined())
 	{
-		llinfos << "RegionX: " << option_it->second << llendl;
-		x_region = atoi(option_it->second.c_str());
+		llinfos << "RegionX: " << option.asInteger() << llendl;
+		x_region = option.asInteger();
 	}
 	else
 	{
 		event_ok = FALSE;
 	}
 
-	option_it = response.find("y_region");
-	if (option_it != response.end())
+	option = response.get("y_region");
+	if (option.isDefined())
 	{
-		llinfos << "RegionY: " << option_it->second << llendl;
-		y_region = atoi(option_it->second.c_str());
+		llinfos << "RegionY: " << option.asInteger() << llendl;
+		y_region = option.asInteger();
 	}
 	else
 	{
diff --git a/indra/newview/lleventnotifier.h b/indra/newview/lleventnotifier.h
index feb734948c2853428a3ecb608476199849c2a660..6fdde876465c3409fe5b1d6cc535ea3a1f2ab314 100644
--- a/indra/newview/lleventnotifier.h
+++ b/indra/newview/lleventnotifier.h
@@ -34,7 +34,6 @@
 #define LL_LLEVENTNOTIFIER_H
 
 #include "llframetimer.h"
-#include "lluserauth.h"
 #include "v3dmath.h"
 
 class LLEventInfo;
@@ -49,7 +48,7 @@ class LLEventNotifier
 
 	void update();	// Notify the user of the event if it's coming up
 
-	void load(const LLUserAuth::options_t& event_options);	// In the format that it comes in from LLUserAuth
+	void load(const LLSD& event_options);	// In the format that it comes in from login
 	void add(LLEventInfo &event_info);	// Add a new notification for an event
 	void remove(U32 event_id);
 
@@ -69,7 +68,7 @@ class LLEventNotification
 	LLEventNotification();
 	virtual ~LLEventNotification();
 
-	BOOL load(const LLUserAuth::response_t &en);		// In the format it comes in from LLUserAuth
+	BOOL load(const LLSD& en);		// In the format it comes in from login
 	BOOL load(const LLEventInfo &event_info);		// From existing event_info on the viewer.
 	//void setEventID(const U32 event_id);
 	//void setEventName(std::string &event_name);
diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index 48b5fc11b740f50dcac0260a81da129e164513b7..7bc48185e681190f308b7b007158497e6225a2ca 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -51,7 +51,7 @@ class LLExpanderSegment : public LLTextSegment
 	/*virtual*/ void	getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const 
 	{
 		// more label always spans width of text box
-		width = mEditor.getTextRect().getWidth(); 
+		width = mEditor.getTextRect().getWidth() - mEditor.getHPad(); 
 		height = llceil(mStyle->getFont()->getLineHeight());
 	}
 	/*virtual*/ S32		getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const 
@@ -153,6 +153,11 @@ void LLExpandableTextBox::LLTextBoxEx::showExpandText()
 {
 	if (!mExpanderVisible)
 	{
+		// make sure we're scrolled to top when collapsing
+		if (mScroller)
+		{
+			mScroller->goToTop();
+		}
 		// get fully visible lines
 		std::pair<S32, S32> visible_lines = getVisibleLines(true);
 		S32 last_line = visible_lines.second - 1;
diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h
index d45527aabb5f8b3d16fd0d628078aaae3762f58c..3fe646c29c6b7765dfbb875b6a6a939748ed58ee 100644
--- a/indra/newview/llexpandabletextbox.h
+++ b/indra/newview/llexpandabletextbox.h
@@ -68,16 +68,6 @@ class LLExpandableTextBox : public LLUICtrl
 		 */
 		virtual S32 getVerticalTextDelta();
 
-		/**
-		 * Returns text vertical padding
-		 */
-		virtual S32 getVPad() { return mVPad; }
-
-		/**
-		 * Returns text horizontal padding
-		 */
-		virtual S32 getHPad() { return mHPad; }
-
 		/**
 		 * Shows "More" link
 		 */
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index e49ef8b96998da0e7435ea3148b8f48470d2a47b..9daac60a7e84f2ded05d289886248faa173de48d 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -856,6 +856,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 								const LLMatrix4& mat_vert, const LLMatrix3& mat_normal,
 								const U16 &index_offset)
 {
+	llpushcallstacks ;
 	const LLVolumeFace &vf = volume.getVolumeFace(f);
 	S32 num_vertices = (S32)vf.mVertices.size();
 	S32 num_indices = (S32)vf.mIndices.size();
@@ -864,7 +865,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	{
 		if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices())
 		{
-			llwarns << "Index buffer overflow!" << llendl;
+			llwarns	<< "Index buffer overflow!" << llendl;
+			llwarns << "Indices Count: " << mIndicesCount
+					<< " VF Num Indices: " << num_indices
+					<< " Indices Index: " << mIndicesIndex
+					<< " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl;
+			llwarns	<< "Last Indices Count: " << mLastIndicesCount
+					<< " Last Indices Index: " << mLastIndicesIndex
+					<< " Face Index: " << f
+					<< " Pool Type: " << mPoolType << llendl;
 			return FALSE;
 		}
 
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index d734b327d95f86c7e90b69c573da4f82101d67ea..2b134c8c3148c4eac66a7258a3677aceb6407b66 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -246,7 +246,7 @@ class LLFace
 
 	//atlas
 	LLPointer<LLTextureAtlasSlot> mAtlasInfop ;
-	BOOL                              mUsingAtlas ;
+	BOOL                          mUsingAtlas ;
 	
 protected:
 	static BOOL	sSafeRenderSelect;
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index f44cdc1a989860c886c641eb361738335c45240e..2ab17d622005815fadde7d52321d089ffde26ada 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -996,8 +996,12 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is)
 			std::string label = iter->first;
 
 			F64 time = iter->second["Time"].asReal();
-			
-			total_time += time;
+
+			// Skip the total figure
+			if(label.compare("Total") != 0)
+			{
+				total_time += time;
+			}			
 
 			if (time > 0.0)
 			{
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 3b5b7f570ee839f0f0f2be8f924c894b17466289..a6afbc05bec83aca4861353577882e17b3042e38 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -503,13 +503,15 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
 		return;
 	}
 
+	LLPointer<LLViewerInventoryItem> viewer_item = new LLViewerInventoryItem(item);
+
 	if (dest)
 	{
-		insertBeforeItem(mItems, dest->getLandmarkId(), item->getUUID());
+		insertBeforeItem(mItems, dest->getLandmarkId(), viewer_item);
 	}
 	else
 	{
-		mItems.push_back(gInventory.getItem(item->getUUID()));
+		mItems.push_back(viewer_item);
 	}
 
 	int sortField = 0;
@@ -534,13 +536,22 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
 		}
 	}
 
-	copy_inventory_item(
-			gAgent.getID(),
-			item->getPermissions().getOwner(),
-			item->getUUID(),
-			favorites_id,
-			std::string(),
-			cb);
+	LLToolDragAndDrop* tool_dad = LLToolDragAndDrop::getInstance();
+	if (tool_dad->getSource() == LLToolDragAndDrop::SOURCE_NOTECARD)
+	{
+		viewer_item->setType(LLAssetType::AT_FAVORITE);
+		copy_inventory_from_notecard(tool_dad->getObjectID(), tool_dad->getSourceID(), viewer_item.get(), gInventoryCallbacks.registerCB(cb));
+	}
+	else
+	{
+		copy_inventory_item(
+				gAgent.getID(),
+				item->getPermissions().getOwner(),
+				item->getUUID(),
+				favorites_id,
+				std::string(),
+				cb);
+	}
 
 	llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl;
 }
@@ -1263,10 +1274,9 @@ void LLFavoritesBarCtrl::updateItemsOrder(LLInventoryModel::item_array_t& items,
 	items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
 }
 
-void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId)
+void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem)
 {
 	LLViewerInventoryItem* beforeItem = gInventory.getItem(beforeItemId);
-	LLViewerInventoryItem* insertedItem = gInventory.getItem(insertedItemId);
 
 	items.insert(findItemByUUID(items, beforeItem->getUUID()), insertedItem);
 }
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index ea2a3d08e22424482a754df9cc9318af613ed605..e90d13f9d5157c539590574d56d1416f426b4c11 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -141,7 +141,7 @@ class LLFavoritesBarCtrl : public LLUICtrl, public LLInventoryObserver
 	 * inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId.
 	 * this function assumes that an item identified by insertedItemId doesn't exist in items array.
 	 */
-	void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId);
+	void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem);
 
 	// finds an item by it's UUID in the items array
 	LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id);
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 2a8365b3f0d9c1bc9712ff0051b99f3e549ab159..fb724f30e072b604995307db09fa685d0d2fd723 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -44,6 +44,7 @@
 #include "llgl.h"
 #include "llsecondlifeurls.h"
 
+#include "llappviewer.h"
 #include "llviewercontrol.h"
 #include "llworld.h"
 #include "lldrawpoolterrain.h"
@@ -58,11 +59,6 @@
 #include "lldxhardware.h"
 #endif
 
-//
-// externs
-//
-extern LLMemoryInfo gSysMemory;
-extern LLCPUInfo gSysCPU;
 
 #if LL_DARWIN
 const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt";
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index 216bca8262ceb96bff83b02da00dcefa146f0771..fc8790c1722f664ce1a7235693a6cf735e6d1adb 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -704,7 +704,7 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
 	}
 
 	if (volume->mLODChanged || volume->mFaceMappingChanged ||
-		volume->mVolumeChanged)
+		volume->mVolumeChanged || drawable->isState(LLDrawable::REBUILD_MATERIAL))
 	{
 		volume->regenFaces();
 		volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME);
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index a4c38d03aa5e7180873b835b043b4ef88045abbd..88658f7b9f635581ffeb9973987d00ab18daec42 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -1,293 +1,343 @@
-/** 
- * @file llfloaterabout.cpp
- * @author James Cook
- * @brief The about box from Help->About
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
- * Copyright (c) 2001-2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- 
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterabout.h"
-
-// Viewer includes
-#include "llagent.h"
-#include "llappviewer.h" 
-#include "llsecondlifeurls.h"
-#include "lluictrlfactory.h"
-#include "llviewertexteditor.h"
-#include "llviewercontrol.h"
-#include "llviewerstats.h"
-#include "llviewerregion.h"
-#include "llversionviewer.h"
-#include "llviewerbuild.h"
-#include "llweb.h"
-
-// Linden library includes
-#include "llaudioengine.h"
-#include "llbutton.h"
-#include "llcurl.h"
-#include "llglheaders.h"
-#include "llfloater.h"
-#include "llfloaterreg.h"
-#include "llimagej2c.h"
-#include "llsys.h"
-#include "lltrans.h"
-#include "lluri.h"
-#include "v3dmath.h"
-#include "llwindow.h"
-
-#if LL_WINDOWS
-#include "lldxhardware.h"
-#endif
-
-extern LLCPUInfo gSysCPU;
-extern LLMemoryInfo gSysMemory;
-extern U32 gPacketsIn;
-
-static std::string get_viewer_release_notes_url();
-
-
-///----------------------------------------------------------------------------
-/// Class LLFloaterAbout
-///----------------------------------------------------------------------------
-class LLFloaterAbout 
-	: public LLFloater
-{
-	friend class LLFloaterReg;
-private:
-	LLFloaterAbout(const LLSD& key);
-	virtual ~LLFloaterAbout();
-
-public:
-	/*virtual*/ BOOL postBuild();
-	void onClickCopyToClipboard();
-};
-
-
-// Default constructor
-LLFloaterAbout::LLFloaterAbout(const LLSD& key) 
-:	LLFloater(key)
-{
-	//LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml");
-	
-}
-
-// Destroys the object
-LLFloaterAbout::~LLFloaterAbout()
-{
-}
-
-BOOL LLFloaterAbout::postBuild()
-{
-	center();
-	LLViewerTextEditor *support_widget = 
-		getChild<LLViewerTextEditor>("support_editor", true);
-
-	LLViewerTextEditor *credits_widget = 
-		getChild<LLViewerTextEditor>("credits_editor", true);
-
-	getChild<LLUICtrl>("copy_btn")->setCommitCallback(
-		boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
-
-	// Version string
-	std::string version = LLTrans::getString("APP_NAME")
-		+ llformat(" %d.%d.%d (%d) %s %s (%s)\n",
-				   LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD,
-				   __DATE__, __TIME__,
-				   gSavedSettings.getString("VersionChannelName").c_str());
-
-	std::string support;
-	support.append(version);
-	support.append("[" + get_viewer_release_notes_url() + " " +
-				   LLTrans::getString("ReleaseNotes") + "]");
-	support.append("\n\n");
-
-#if LL_MSVC
-    support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER));
-#endif
-
-#if LL_GNUC
-    support.append(llformat("Built with GCC version %d\n\n", GCC_VERSION));
-#endif
-
-	// Position
-	LLViewerRegion* region = gAgent.getRegion();
-	if (region)
-	{
-		const LLVector3d &pos = gAgent.getPositionGlobal();
-		LLUIString pos_text = getString("you_are_at");
-		pos_text.setArg("[POSITION]",
-						llformat("%.1f, %.1f, %.1f ", pos.mdV[VX], pos.mdV[VY], pos.mdV[VZ]));
-		support.append(pos_text);
-
-		LLUIString region_text = getString ("in_region") + " ";
-		region_text.setArg("[REGION]", llformat ("%s", gAgent.getRegion()->getName().c_str()));
-		support.append(region_text);
-
-		std::string buffer;
-		buffer = gAgent.getRegion()->getHost().getHostName();
-		support.append(buffer);
-		support.append(" (");
-		buffer = gAgent.getRegion()->getHost().getString();
-		support.append(buffer);
-		support.append(")\n");
-		support.append(gLastVersionChannel);
-		support.append("\n");
-		support.append("[" + LLWeb::escapeURL(region->getCapability("ServerReleaseNotes")) +
-					   " " + LLTrans::getString("ReleaseNotes") + "]");
-		support.append("\n\n");
-	}
-
-	// *NOTE: Do not translate text like GPU, Graphics Card, etc -
-	//  Most PC users that know what these mean will be used to the english versions,
-	//  and this info sometimes gets sent to support
-	
-	// CPU
-	support.append(getString("CPU") + " ");
-	support.append( gSysCPU.getCPUString() );
-	support.append("\n");
-
-	U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024;
-	// Moved hack adjustment to Windows memory size into llsys.cpp
-
-	LLStringUtil::format_map_t args;
-	args["[MEM]"] = llformat ("%u", memory);
-	support.append(getString("Memory", args) + "\n");
-
-	support.append(getString("OSVersion") + " ");
-	support.append( LLAppViewer::instance()->getOSInfo().getOSString() );
-	support.append("\n");
-
-	support.append(getString("GraphicsCardVendor") + " ");
-	support.append( (const char*) glGetString(GL_VENDOR) );
-	support.append("\n");
-
-	support.append(getString("GraphicsCard") + " ");
-	support.append( (const char*) glGetString(GL_RENDERER) );
-	support.append("\n");
-
-#if LL_WINDOWS
-    getWindow()->incBusyCount();
-    getWindow()->setCursor(UI_CURSOR_ARROW);
-    support.append("Windows Graphics Driver Version: ");
-    LLSD driver_info = gDXHardware.getDisplayInfo();
-    if (driver_info.has("DriverVersion"))
-    {
-        support.append(driver_info["DriverVersion"]);
-    }
-    support.append("\n");
-    getWindow()->decBusyCount();
-    getWindow()->setCursor(UI_CURSOR_ARROW);
-#endif
-
-	support.append(getString("OpenGLVersion") + " ");
-	support.append( (const char*) glGetString(GL_VERSION) );
-	support.append("\n");
-
-	support.append("\n");
-
-	support.append(getString("LibCurlVersion") + " ");
-	support.append( LLCurl::getVersionString() );
-	support.append("\n");
-
-	support.append(getString("J2CDecoderVersion") + " ");
-	support.append( LLImageJ2C::getEngineInfo() );
-	support.append("\n");
-
-	support.append(getString("AudioDriverVersion") + " ");
-	bool want_fullname = true;
-	support.append( gAudiop ? gAudiop->getDriverName(want_fullname) : getString("none") );
-	support.append("\n");
-
-	// TODO: Implement media plugin version query
-
-	support.append(getString("LLQtWebkitVersion") + " ");
-	support.append("\n");
-
-	if (gPacketsIn > 0)
-	{
-		args["[LOST]"] = llformat ("%.0f", LLViewerStats::getInstance()->mPacketsLostStat.getCurrent());
-		args["[IN]"] = llformat ("%.0f", F32(gPacketsIn));
-		args["[PCT]"] = llformat ("%.1f", 100.f*LLViewerStats::getInstance()->mPacketsLostStat.getCurrent() / F32(gPacketsIn) );
-		support.append(getString ("PacketsLost", args) + "\n");
-	}
-
-	support_widget->appendText(support, 
-								FALSE, 
-								LLStyle::Params()
-									.color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
-	support_widget->blockUndo();
-
-	// Fix views
-	support_widget->setCursorPos(0);
-	support_widget->setEnabled(FALSE);
-
-	credits_widget->setCursorPos(0);
-	credits_widget->setEnabled(FALSE);
-
-	return TRUE;
-}
-
-
-static std::string get_viewer_release_notes_url()
-{
-	std::ostringstream version;
-	version << LL_VERSION_MAJOR << "."
-		<< LL_VERSION_MINOR << "."
-		<< LL_VERSION_PATCH << "."
-		<< LL_VERSION_BUILD;
-
-	LLSD query;
-	query["channel"] = gSavedSettings.getString("VersionChannelName");
-	query["version"] = version.str();
-
-	std::ostringstream url;
-	url << LLTrans::getString("RELEASE_NOTES_BASE_URL") << LLURI::mapToQueryString(query);
-
-	return LLWeb::escapeURL(url.str());
-}
-
-void LLFloaterAbout::onClickCopyToClipboard()
-{
-	LLViewerTextEditor *support_widget = 
-		getChild<LLViewerTextEditor>("support_editor", true);
-	support_widget->selectAll();
-	support_widget->copy();
-	support_widget->deselect();
-}
-
-///----------------------------------------------------------------------------
-/// LLFloaterAboutUtil
-///----------------------------------------------------------------------------
-void LLFloaterAboutUtil::registerFloater()
-{
-	LLFloaterReg::add("sl_about", "floater_about.xml",
-		&LLFloaterReg::build<LLFloaterAbout>);
-
-}
+/** 
+ * @file llfloaterabout.cpp
+ * @author James Cook
+ * @brief The about box from Help->About
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+ 
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterabout.h"
+
+// Viewer includes
+#include "llagent.h"
+#include "llappviewer.h" 
+#include "llsecondlifeurls.h"
+#include "llvoiceclient.h"
+#include "lluictrlfactory.h"
+#include "llviewertexteditor.h"
+#include "llviewercontrol.h"
+#include "llviewerstats.h"
+#include "llviewerregion.h"
+#include "llversionviewer.h"
+#include "llviewerbuild.h"
+#include "llweb.h"
+
+// Linden library includes
+#include "llaudioengine.h"
+#include "llbutton.h"
+#include "llcurl.h"
+#include "llglheaders.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llimagej2c.h"
+#include "llsys.h"
+#include "lltrans.h"
+#include "lluri.h"
+#include "v3dmath.h"
+#include "llwindow.h"
+#include "stringize.h"
+#include "llsdutil_math.h"
+#include "lleventdispatcher.h"
+
+#if LL_WINDOWS
+#include "lldxhardware.h"
+#endif
+
+extern LLMemoryInfo gSysMemory;
+extern U32 gPacketsIn;
+
+static std::string get_viewer_release_notes_url();
+
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterAbout
+///----------------------------------------------------------------------------
+class LLFloaterAbout 
+	: public LLFloater
+{
+	friend class LLFloaterReg;
+private:
+	LLFloaterAbout(const LLSD& key);
+	virtual ~LLFloaterAbout();
+
+public:
+	/*virtual*/ BOOL postBuild();
+
+	/// Obtain the data used to fill out the contents string. This is
+	/// separated so that we can programmatically access the same info.
+	static LLSD getInfo();
+	void onClickCopyToClipboard();
+};
+
+
+// Default constructor
+LLFloaterAbout::LLFloaterAbout(const LLSD& key) 
+:	LLFloater(key)
+{
+	//LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml");
+	
+}
+
+// Destroys the object
+LLFloaterAbout::~LLFloaterAbout()
+{
+}
+
+BOOL LLFloaterAbout::postBuild()
+{
+	center();
+	LLViewerTextEditor *support_widget = 
+		getChild<LLViewerTextEditor>("support_editor", true);
+
+	LLViewerTextEditor *credits_widget = 
+		getChild<LLViewerTextEditor>("credits_editor", true);
+
+	getChild<LLUICtrl>("copy_btn")->setCommitCallback(
+		boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
+
+#if LL_WINDOWS
+	getWindow()->incBusyCount();
+	getWindow()->setCursor(UI_CURSOR_ARROW);
+#endif
+	LLSD info(getInfo());
+#if LL_WINDOWS
+	getWindow()->decBusyCount();
+	getWindow()->setCursor(UI_CURSOR_ARROW);
+#endif
+
+	std::ostringstream support;
+
+	// Render the LLSD from getInfo() as a format_map_t
+	LLStringUtil::format_map_t args;
+	// For reasons I don't yet understand, [ReleaseNotes] is not part of the
+	// default substitution strings whereas [APP_NAME] is. But it works to
+	// simply copy it into these specific args.
+	args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes");
+	for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap());
+		 ii != iend; ++ii)
+	{
+		if (! ii->second.isArray())
+		{
+			// Scalar value
+			if (ii->second.isUndefined())
+			{
+				args[ii->first] = getString("none");
+			}
+			else
+			{
+				// don't forget to render value asString()
+				args[ii->first] = ii->second.asString();
+			}
+		}
+		else
+		{
+			// array value: build KEY_0, KEY_1 etc. entries
+			for (LLSD::Integer n(0), size(ii->second.size()); n < size; ++n)
+			{
+				args[STRINGIZE(ii->first << '_' << n)] = ii->second[n].asString();
+			}
+		}
+	}
+
+	// Now build the various pieces
+	support << getString("AboutHeader", args);
+	if (info.has("COMPILER"))
+	{
+		support << "\n\n" << getString("AboutCompiler", args);
+	}
+	if (info.has("REGION"))
+	{
+		support << "\n\n" << getString("AboutPosition", args);
+	}
+	support << "\n\n" << getString("AboutSystem", args);
+	if (info.has("GRAPHICS_DRIVER_VERSION"))
+	{
+		support << "\n\n" << getString("AboutDriver", args);
+	}
+	support << "\n\n" << getString("AboutLibs", args);
+	if (info.has("PACKETS_IN"))
+	{
+		support << '\n' << getString("AboutTraffic", args);
+	}
+
+	support_widget->appendText(support.str(), 
+								FALSE, 
+								LLStyle::Params()
+									.color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
+	support_widget->blockUndo();
+
+	// Fix views
+	support_widget->setCursorPos(0);
+	support_widget->setEnabled(FALSE);
+
+	credits_widget->setCursorPos(0);
+	credits_widget->setEnabled(FALSE);
+
+	return TRUE;
+}
+
+// static
+LLSD LLFloaterAbout::getInfo()
+{
+	// The point of having one method build an LLSD info block and the other
+	// construct the user-visible About string is to ensure that the same info
+	// is available to a getInfo() caller as to the user opening
+	// LLFloaterAbout.
+	LLSD info;
+	LLSD version;
+	version.append(LL_VERSION_MAJOR);
+	version.append(LL_VERSION_MINOR);
+	version.append(LL_VERSION_PATCH);
+	version.append(LL_VERSION_BUILD);
+	info["VIEWER_VERSION"] = version;
+	info["VIEWER_VERSION_STR"] = STRINGIZE(version[0].asInteger() << '.' <<
+										   version[1].asInteger() << '.' <<
+										   version[2].asInteger() << '.' <<
+										   version[3].asInteger());
+	info["BUILD_DATE"] = __DATE__;
+	info["BUILD_TIME"] = __TIME__;
+	info["CHANNEL"] = gSavedSettings.getString("VersionChannelName");
+
+	info["VIEWER_RELEASE_NOTES_URL"] = get_viewer_release_notes_url();
+
+#if LL_MSVC
+	info["COMPILER"] = "MSVC";
+	info["COMPILER_VERSION"] = _MSC_VER;
+#elif LL_GNUC
+	info["COMPILER"] = "GCC";
+	info["COMPILER_VERSION"] = GCC_VERSION;
+#endif
+
+	// Position
+	LLViewerRegion* region = gAgent.getRegion();
+	if (region)
+	{
+		const LLVector3d &pos = gAgent.getPositionGlobal();
+		info["POSITION"] = ll_sd_from_vector3d(pos);
+		info["REGION"] = gAgent.getRegion()->getName();
+		info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName();
+		info["HOSTIP"] = gAgent.getRegion()->getHost().getString();
+		info["SERVER_VERSION"] = gLastVersionChannel;
+		info["SERVER_RELEASE_NOTES_URL"] = LLWeb::escapeURL(region->getCapability("ServerReleaseNotes"));
+	}
+
+	// CPU
+	info["CPU"] = gSysCPU.getCPUString();
+	info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB() / 1024);
+	// Moved hack adjustment to Windows memory size into llsys.cpp
+	info["OS_VERSION"] = LLAppViewer::instance()->getOSInfo().getOSString();
+	info["GRAPHICS_CARD_VENDOR"] = (const char*)(glGetString(GL_VENDOR));
+	info["GRAPHICS_CARD"] = (const char*)(glGetString(GL_RENDERER));
+
+#if LL_WINDOWS
+    LLSD driver_info = gDXHardware.getDisplayInfo();
+    if (driver_info.has("DriverVersion"))
+    {
+        info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
+    }
+#endif
+
+	info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION));
+	info["LIBCURL_VERSION"] = LLCurl::getVersionString();
+	info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
+	bool want_fullname = true;
+	info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
+	info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : "Unknown";
+
+	// TODO: Implement media plugin version query
+	info["QT_WEBKIT_VERSION"] = "4.5.2";
+
+	if (gPacketsIn > 0)
+	{
+		info["PACKETS_LOST"] = LLViewerStats::getInstance()->mPacketsLostStat.getCurrent();
+		info["PACKETS_IN"] = F32(gPacketsIn);
+		info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal();
+	}
+
+    return info;
+}
+
+static std::string get_viewer_release_notes_url()
+{
+	std::ostringstream version;
+	version << LL_VERSION_MAJOR << "."
+		<< LL_VERSION_MINOR << "."
+		<< LL_VERSION_PATCH << "."
+		<< LL_VERSION_BUILD;
+
+	LLSD query;
+	query["channel"] = gSavedSettings.getString("VersionChannelName");
+	query["version"] = version.str();
+
+	std::ostringstream url;
+	url << LLTrans::getString("RELEASE_NOTES_BASE_URL") << LLURI::mapToQueryString(query);
+
+	return LLWeb::escapeURL(url.str());
+}
+
+class LLFloaterAboutListener: public LLDispatchListener
+{
+public:
+	LLFloaterAboutListener():
+		LLDispatchListener("LLFloaterAbout", "op")
+	{
+		add("getInfo", &LLFloaterAboutListener::getInfo, LLSD().insert("reply", LLSD()));
+	}
+
+private:
+	void getInfo(const LLSD& request) const
+	{
+		LLReqID reqid(request);
+		LLSD reply(LLFloaterAbout::getInfo());
+		reqid.stamp(reply);
+		LLEventPumps::instance().obtain(request["reply"]).post(reply);
+	}
+};
+
+static LLFloaterAboutListener floaterAboutListener;
+
+void LLFloaterAbout::onClickCopyToClipboard()
+{
+	LLViewerTextEditor *support_widget = 
+		getChild<LLViewerTextEditor>("support_editor", true);
+	support_widget->selectAll();
+	support_widget->copy();
+	support_widget->deselect();
+}
+
+///----------------------------------------------------------------------------
+/// LLFloaterAboutUtil
+///----------------------------------------------------------------------------
+void LLFloaterAboutUtil::registerFloater()
+{
+	LLFloaterReg::add("sl_about", "floater_about.xml",
+		&LLFloaterReg::build<LLFloaterAbout>);
+
+}
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index cb0d304aa0624f78c9e2c1fb73eb13d69361f586..262dc1804d3b5e1e1c0c28b89b5c9a1b6d586eab 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -58,6 +58,7 @@
 #include "llui.h"
 #include "llrender.h"
 #include "llsdutil.h"
+#include "llsdutil_math.h"
 
 ///----------------------------------------------------------------------------
 /// Local function declarations, constants, enums, and typedefs
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index ccfe7d4b649cdbc895be8f983eb4ebe85e46af96..8ac7f3fd7e1f952ccaafca6c1fb7059edc0a2b8d 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -35,6 +35,7 @@
 
 // Viewer includes
 #include "llagent.h"
+#include "llcallingcard.h"
 #include "llfocusmgr.h"
 #include "llfloaterreg.h"
 #include "llviewercontrol.h"
@@ -76,6 +77,7 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key)
 	mCloseOnSelect(FALSE)
 {
 // 	LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml");
+	mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
 }
 
 BOOL LLFloaterAvatarPicker::postBuild()
@@ -95,7 +97,11 @@ BOOL LLFloaterAvatarPicker::postBuild()
 	LLScrollListCtrl* nearme = getChild<LLScrollListCtrl>("NearMe");
 	nearme->setDoubleClickCallback(onBtnSelect, this);
 	childSetCommitCallback("NearMe", onList, this);
-	
+
+	LLScrollListCtrl* friends = getChild<LLScrollListCtrl>("Friends");
+	friends->setDoubleClickCallback(onBtnSelect, this);
+	childSetCommitCallback("Friends", onList, this);
+
 	childSetAction("Select", onBtnSelect, this);
 	childDisable("Select");
 
@@ -119,6 +125,8 @@ BOOL LLFloaterAvatarPicker::postBuild()
 	
 	center();
 	
+	populateFriend();
+
 	return TRUE;
 }
 
@@ -159,25 +167,37 @@ void LLFloaterAvatarPicker::onBtnSelect(void* userdata)
 
 	if(self->mCallback)
 	{
+		std::string acvtive_panel_name;
+		LLScrollListCtrl* list =  NULL;
 		LLPanel* active_panel = self->childGetVisibleTab("ResidentChooserTabs");
-
-		if(active_panel == self->getChild<LLPanel>("SearchPanel"))
+		if(active_panel)
 		{
-			std::vector<std::string>	avatar_names;
-			std::vector<LLUUID>			avatar_ids;
-			getSelectedAvatarData(self->getChild<LLScrollListCtrl>("SearchResults"), avatar_names, avatar_ids);
-			self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata);
+			acvtive_panel_name = active_panel->getName();
+		}
+		if(acvtive_panel_name == "SearchPanel")
+		{
+			list = self->getChild<LLScrollListCtrl>("SearchResults");
+		}
+		else if(acvtive_panel_name == "NearMePanel")
+		{
+			list =self->getChild<LLScrollListCtrl>("NearMe");
+		}
+		else if (acvtive_panel_name == "FriendsPanel")
+		{
+			list =self->getChild<LLScrollListCtrl>("Friends");
 		}
-		else if(active_panel == self->getChild<LLPanel>("NearMePanel"))
+
+		if(list)
 		{
 			std::vector<std::string>	avatar_names;
 			std::vector<LLUUID>			avatar_ids;
-			getSelectedAvatarData(self->getChild<LLScrollListCtrl>("NearMe"), avatar_names, avatar_ids);
+			getSelectedAvatarData(list, avatar_names, avatar_ids);
 			self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata);
 		}
 	}
 	self->getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
 	self->getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE);
+	self->getChild<LLScrollListCtrl>("Friends")->deselectAllItems(TRUE);
 	if(self->mCloseOnSelect)
 	{
 		self->mCloseOnSelect = FALSE;
@@ -268,6 +288,26 @@ void LLFloaterAvatarPicker::populateNearMe()
 	}
 }
 
+void LLFloaterAvatarPicker::populateFriend()
+{
+	LLScrollListCtrl* friends_scroller = getChild<LLScrollListCtrl>("Friends");
+	friends_scroller->deleteAllItems();
+	LLCollectAllBuddies collector;
+	LLAvatarTracker::instance().applyFunctor(collector);
+	LLCollectAllBuddies::buddy_map_t::iterator it;
+	
+	
+	for(it = collector.mOnline.begin(); it!=collector.mOnline.end(); it++)
+	{
+		friends_scroller->addStringUUIDItem(it->first, it->second);
+	}
+	for(it = collector.mOffline.begin(); it!=collector.mOffline.end(); it++)
+	{
+			friends_scroller->addStringUUIDItem(it->first, it->second);
+	}
+	friends_scroller->sortByColumnIndex(0, TRUE);
+}
+
 void LLFloaterAvatarPicker::draw()
 {
 	LLFloater::draw();
@@ -289,6 +329,10 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
 	{
 		return getChild<LLScrollListCtrl>("NearMe")->getFirstSelectedIndex() >= 0;
 	}
+	else if(active_panel == getChild<LLPanel>("FriendsPanel"))
+	{
+		return getChild<LLScrollListCtrl>("Friends")->getFirstSelectedIndex() >= 0;
+	}
 	return FALSE;
 }
 
@@ -321,6 +365,7 @@ void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple)
 {
 	getChild<LLScrollListCtrl>("SearchResults")->setAllowMultipleSelection(allow_multiple);
 	getChild<LLScrollListCtrl>("NearMe")->setAllowMultipleSelection(allow_multiple);
+	getChild<LLScrollListCtrl>("Friends")->setAllowMultipleSelection(allow_multiple);
 }
 
 // static 
diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h
index 85aacb68a591b9abbba43fdd94cf5ecfc681dcfd..b8ace985d9fd10960cfde88f4f444b76496c499b 100644
--- a/indra/newview/llfloateravatarpicker.h
+++ b/indra/newview/llfloateravatarpicker.h
@@ -67,6 +67,7 @@ class LLFloaterAvatarPicker : public LLFloater
 		   void onTabChanged();
 	
 	void populateNearMe();
+	void populateFriend();
 	BOOL visibleItemsSelected() const; // Returns true if any items in the current tab are selected.
 
 	void find();
diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp
index 8b64f913e02b58fc70e5a930cd78a4d4245bcaf9..68f06b1e5b591231bdb5b8392c7232b06e6eb714 100644
--- a/indra/newview/llfloaterbump.cpp
+++ b/indra/newview/llfloaterbump.cpp
@@ -40,7 +40,6 @@
 #include "llsd.h"
 #include "lluictrlfactory.h"
 #include "llviewermessage.h"
-#include "llappviewer.h"		// gPacificDaylightTime
 
 ///----------------------------------------------------------------------------
 /// Class LLFloaterBump
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 2c2a5107f53c50071885b75572df695568073769..36f031579046d6201445598a96e5c12c82f6f5d8 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -81,6 +81,8 @@ class LLFloaterBuyLandUI
 	LLFloaterBuyLandUI(const LLSD& key);
 	virtual ~LLFloaterBuyLandUI();
 	
+	/*virtual*/ void onClose(bool app_quitting);
+	
 private:
 	class SelectionObserver : public LLParcelObserver
 	{
@@ -300,11 +302,21 @@ LLFloaterBuyLandUI::LLFloaterBuyLandUI(const LLSD& key)
 LLFloaterBuyLandUI::~LLFloaterBuyLandUI()
 {
 	LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver);
-	LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo);
+	LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
 	
 	delete mTransaction;
 }
 
+// virtual
+void LLFloaterBuyLandUI::onClose(bool app_quitting)
+{
+	// This object holds onto observer, transactions, and parcel state.
+	// Despite being single_instance, destroy it to call destructors and clean
+	// everything up.
+	setVisible(FALSE);
+	destroy();
+}
+
 void LLFloaterBuyLandUI::SelectionObserver::changed()
 {
 	if (LLViewerParcelMgr::getInstance()->selectionEmpty())
@@ -756,7 +768,7 @@ void LLFloaterBuyLandUI::sendBuyLand()
 	if (mParcelBuyInfo)
 	{
 		LLViewerParcelMgr::getInstance()->sendParcelBuy(mParcelBuyInfo);
-		LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo);
+		LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
 		mBought = true;
 	}
 }
diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp
index dca0773139bf03001499d14036135a821067d443..d1317f7c3681b84f3ca09b1583ed7b004b195bc6 100644
--- a/indra/newview/llfloatercamera.cpp
+++ b/indra/newview/llfloatercamera.cpp
@@ -268,8 +268,8 @@ void LLFloaterCamera::updateState()
 	LLRect controls_rect;
 	if (childGetRect(CONTROLS, controls_rect))
 	{
-		static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
-		static S32 height = controls_rect.getHeight() - floater_header_size;
+		S32 floater_header_size = getHeaderHeight();
+		S32 height = controls_rect.getHeight() - floater_header_size;
 		S32 newHeight = rect.getHeight();
 		
 		if (showControls)
diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp
index 6d2e9593520a836bc5e80f9024f7bd0c68ecb47c..ed14079ae91b93a841024845843160945622a042 100644
--- a/indra/newview/llfloaterchat.cpp
+++ b/indra/newview/llfloaterchat.cpp
@@ -182,13 +182,7 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
 
 void log_chat_text(const LLChat& chat)
 {
-		std::string histstr;
-		if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
-			histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + chat.mText;
-		else
-			histstr = chat.mText;
-
-		LLLogChat::saveHistory(std::string("chat"),histstr);
+	LLLogChat::saveHistory(std::string("chat"), chat.mFromName, chat.mFromID, chat.mText);
 }
 // static
 void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
@@ -204,12 +198,14 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
 
 	if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
 	{
-		LLFloaterScriptDebug::addScriptLine(chat.mText,
-											chat.mFromName, 
-											color, 
-											chat.mFromID);
-		if (!gSavedSettings.getBOOL("ScriptErrorsAsChat"))
+		if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
+			return;
+		if (gSavedSettings.getS32("ShowScriptErrorsLocation") == 1)
 		{
+			LLFloaterScriptDebug::addScriptLine(chat.mText,
+												chat.mFromName, 
+												color, 
+												chat.mFromID);
 			return;
 		}
 	}
@@ -315,9 +311,9 @@ void LLFloaterChat::addChat(const LLChat& chat,
 {
 	LLColor4 text_color = get_text_color(chat);
 
-	BOOL invisible_script_debug_chat = 
-			chat.mChatType == CHAT_TYPE_DEBUG_MSG
-			&& !gSavedSettings.getBOOL("ScriptErrorsAsChat");
+	BOOL invisible_script_debug_chat = ((gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) ||
+			(chat.mChatType == CHAT_TYPE_DEBUG_MSG
+			&& (gSavedSettings.getS32("ShowScriptErrorsLocation") == 1)));
 
 	if (!invisible_script_debug_chat 
 		&& !chat.mMuted 
@@ -474,7 +470,7 @@ void LLFloaterChat::loadHistory()
 }
 
 //static
-void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , std::string line, void* userdata)
+void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , const LLSD& line, void* userdata)
 {
 	switch (type)
 	{
@@ -483,9 +479,10 @@ void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , std::string l
 		// *TODO: nice message from XML file here
 		break;
 	case LLLogChat::LOG_LINE:
+	case LLLogChat::LOG_LLSD:
 		{
 			LLChat chat;					
-			chat.mText = line;
+			chat.mText = line["message"].asString();
 			get_text_color(chat);
 			addChatHistory(chat,  FALSE);
 		}
diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h
index 6ba3165d6a04ff697d118296954ebc18fa44e360..aed82a6781ec9f571b6a75b1164deac1bd7887d9 100644
--- a/indra/newview/llfloaterchat.h
+++ b/indra/newview/llfloaterchat.h
@@ -78,7 +78,7 @@ class LLFloaterChat : public LLFloater
 	static void onClickMute(void *data);
 	static void onClickToggleShowMute(LLUICtrl* caller, void *data);
 	static void onClickToggleActiveSpeakers(void* userdata);
-	static void chatFromLogFile(LLLogChat::ELogLineType type,std::string line, void* userdata);
+	static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& line, void* userdata);
 	static void loadHistory();
 	static void* createSpeakersPanel(void* data);
 	static void* createChatPanel(void* data);
diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp
index dea656b0e49d2caf2d0da56eb120188340eba1a5..fbf09207feaace624dd085a6d57f913752c249b7 100644
--- a/indra/newview/llfloaterchatterbox.cpp
+++ b/indra/newview/llfloaterchatterbox.cpp
@@ -42,7 +42,7 @@
 #include "llfloaterfriends.h"
 #include "llfloatergroups.h"
 #include "llviewercontrol.h"
-#include "llimview.h"
+#include "llvoicechannel.h"
 #include "llimpanel.h"
 
 //
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index 8e385fca784596d4cf78132b5b5f1d9909d3ceb3..73b79d8e132db5b1144a78e0beaab372a8f88017 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -561,7 +561,7 @@ void LLFloaterColorPicker::draw()
 	// create rgb area outline
 	gl_rect_2d ( mRGBViewerImageLeft,
 				 mRGBViewerImageTop - mRGBViewerImageHeight,
-				 mRGBViewerImageLeft + mRGBViewerImageWidth,
+				 mRGBViewerImageLeft + mRGBViewerImageWidth + 1,
 				 mRGBViewerImageTop,
 				 LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
 				 FALSE );
@@ -591,7 +591,7 @@ void LLFloaterColorPicker::draw()
 	// draw luminance slider outline
 	gl_rect_2d ( mLumRegionLeft,
 				 mLumRegionTop - mLumRegionHeight,
-				 mLumRegionLeft + mLumRegionWidth,
+				 mLumRegionLeft + mLumRegionWidth + 1,
 				 mLumRegionTop,
 				 LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
 				 FALSE );
@@ -607,7 +607,7 @@ void LLFloaterColorPicker::draw()
 	// draw selected color swatch outline
 	gl_rect_2d ( mSwatchRegionLeft,
 				 mSwatchRegionTop - mSwatchRegionHeight,
-				 mSwatchRegionLeft + mSwatchRegionWidth,
+				 mSwatchRegionLeft + mSwatchRegionWidth + 1,
 				 mSwatchRegionTop,
 				 LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
 				 FALSE );
diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h
index 9242f00c912177a8fc113fd23bbe6589df78a9e5..9c6660c0dc2abd55300827685ed115146ebed96a 100644
--- a/indra/newview/llfloaterfriends.h
+++ b/indra/newview/llfloaterfriends.h
@@ -74,6 +74,9 @@ class LLPanelFriends : public LLPanel, public LLEventTimer
 
 	virtual BOOL postBuild();
 
+	// *HACK Made public to remove friends from LLAvatarIconCtrl context menu
+	static bool handleRemove(const LLSD& notification, const LLSD& response);
+
 private:
 
 	enum FRIENDS_COLUMN_ORDER
diff --git a/indra/newview/llfloatergroupinvite.cpp b/indra/newview/llfloatergroupinvite.cpp
index 3598479305c5bdaa688952dc90949333b2e73f9e..bf484c63433605cfa1fdf3d4f3e58ce6141bcebf 100644
--- a/indra/newview/llfloatergroupinvite.cpp
+++ b/indra/newview/llfloatergroupinvite.cpp
@@ -81,7 +81,7 @@ void LLFloaterGroupInvite::impl::closeFloater(void* data)
 LLFloaterGroupInvite::LLFloaterGroupInvite(const LLUUID& group_id)
 :	LLFloater(group_id)
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	S32 floater_header_size = getHeaderHeight();
 	LLRect contents;
 
 	mImpl = new impl(group_id);
@@ -114,7 +114,8 @@ LLFloaterGroupInvite::~LLFloaterGroupInvite()
 // static
 void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, std::vector<LLUUID> *agent_ids)
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+	S32 floater_header_size = floater_params.header_height;
 	LLRect contents;
 
 	// Make sure group_id isn't null
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
index 364c79e3c1454e302a8b6b76f8e3f5095a06c36b..a90b2cfe7be97f657bc6afe216cc0dd36ff0459f 100644
--- a/indra/newview/llfloaterinventory.cpp
+++ b/indra/newview/llfloaterinventory.cpp
@@ -1441,7 +1441,11 @@ void LLInventoryPanel::modelChanged(U32 mask)
 						}
 
 						LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
-						if (view_item->getParentFolder() != new_parent)
+
+						// added check against NULL for cases when Inventory panel contains startFolder.
+						// in this case parent is LLFolderView (LLInventoryPanel::mFolders) itself.
+						// this check is a fix for bug EXT-1859.
+						if (NULL != new_parent && view_item->getParentFolder() != new_parent)
 						{
 							view_item->getParentFolder()->extractItem(view_item);
 							view_item->addToFolder(new_parent, mFolders);
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 488d71aa70a27237988009319126108ef32709e3..bdf9842b015ec8288cf50389062d7476d5626533 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -1054,9 +1054,9 @@ BOOL LLPanelLandObjects::postBuild()
 	mBtnReturnOwnerList = getChild<LLButton>("Return objects...");
 	mBtnReturnOwnerList->setClickedCallback(onClickReturnOwnerList, this);
 
-	mIconAvatarOnline = LLUIImageList::getInstance()->getUIImage("icon_avatar_online.tga");
-	mIconAvatarOffline = LLUIImageList::getInstance()->getUIImage("icon_avatar_offline.tga");
-	mIconGroup = LLUIImageList::getInstance()->getUIImage("icon_group.tga");
+	mIconAvatarOnline = LLUIImageList::getInstance()->getUIImage("icon_avatar_online.tga", 0);
+	mIconAvatarOffline = LLUIImageList::getInstance()->getUIImage("icon_avatar_offline.tga", 0);
+	mIconGroup = LLUIImageList::getInstance()->getUIImage("icon_group.tga", 0);
 
 	mOwnerList = getChild<LLNameListCtrl>("owner list");
 	mOwnerList->sortByColumnIndex(3, FALSE);
diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp
index aa457de2d87bb418784877e56f8bfbfb5248a9c3..d941f24f49e0ca81c338306eebb48b51f22974ca 100644
--- a/indra/newview/llfloatermediasettings.cpp
+++ b/indra/newview/llfloatermediasettings.cpp
@@ -118,6 +118,7 @@ BOOL LLFloaterMediaSettings::postBuild()
 	mTabContainer->addTabPanel( 
 			LLTabContainer::TabPanelParams().
 			panel(mPanelMediaSettingsSecurity));
+	mPanelMediaSettingsSecurity->setParent( this );
 		
 	// restore the last tab viewed from persistance variable storage
 	if (!mTabContainer->selectTab(gSavedSettings.getS32("LastMediaSettingsTab")))
@@ -248,3 +249,28 @@ void LLFloaterMediaSettings::enableOkApplyBtns( bool enable )
 	childSetEnabled( "OK", enable );
 	childSetEnabled( "Apply", enable );
 }
+
+////////////////////////////////////////////////////////////////////////////////
+//
+const std::string LLFloaterMediaSettings::getHomeUrl()
+{
+	if ( mPanelMediaSettingsGeneral )
+		return mPanelMediaSettingsGeneral->getHomeUrl();
+	else
+		return std::string( "" );
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLFloaterMediaSettings::passesWhiteList( const std::string& test_url )
+{
+	// sanity check - don't think this can happen
+	if ( mPanelMediaSettingsSecurity )
+		// version in security dialog code is specialized so we pass in 
+		// empty string for first parameter since it's not used
+		return mPanelMediaSettingsSecurity->passesWhiteList( "", test_url );
+	else
+		// this is all we can do
+		return false;
+}
diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h
index e2683039cc2ef30f59a560e59399fc4f3a0ac2e0..17a47cb0f5a4b04cd3846574261f251a9855fac8 100644
--- a/indra/newview/llfloatermediasettings.h
+++ b/indra/newview/llfloatermediasettings.h
@@ -56,6 +56,8 @@ class LLFloaterMediaSettings :
 	static void clearValues( bool editable);
 	void enableOkApplyBtns( bool enable );
 	LLPanelMediaSettingsSecurity* getPanelSecurity(){return mPanelMediaSettingsSecurity;};
+	const std::string getHomeUrl();
+	bool passesWhiteList( const std::string& test_url );
 
 	bool mIdenticalHasMediaInfo;
 	bool mMultipleMedia;
diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp
index f2dff55044aa831f8cf15524c22f7aeadc3f40d4..f20fca1258b8945b41957ce8605ff5666293540b 100644
--- a/indra/newview/llfloaternotificationsconsole.cpp
+++ b/indra/newview/llfloaternotificationsconsole.cpp
@@ -221,7 +221,8 @@ void LLFloaterNotificationConsole::removeChannel(const std::string& name)
 //static 
 void LLFloaterNotificationConsole::updateResizeLimits()
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+	S32 floater_header_size = floater_params.header_height;
 
 	LLLayoutStack& stack = getChildRef<LLLayoutStack>("notification_channels");
 	setResizeLimits(getMinWidth(), floater_header_size + HEADER_PADDING + ((NOTIFICATION_PANEL_HEADER_HEIGHT + 3) * stack.getNumPanels()));
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index dbee9ea30995885d233eff5cb2c541a905cdb492..8b3391726a7fab80e84b21a74ed38d2f7f666027 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -843,10 +843,7 @@ void LLFloaterPreference::refreshEnabledState()
 	bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
 	getChild<LLCheckBoxCtrl>("BumpShiny")->setEnabled(bumpshiny ? TRUE : FALSE);
 	
-	for (S32 i = 0; i < radio_reflection_detail->getItemCount(); ++i)
-	{
-		radio_reflection_detail->setIndexEnabled(i, ctrl_reflections->get() && reflections);
-	}
+	radio_reflection_detail->setEnabled(ctrl_reflections->get() && reflections);
 	
 	// Avatar Mode
 	// Enable Avatar Shaders
@@ -880,20 +877,10 @@ void LLFloaterPreference::refreshEnabledState()
 	{
 		mRadioTerrainDetail->setValue(1);
 		mRadioTerrainDetail->setEnabled(FALSE);
-		for (S32 i = 0; i < mRadioTerrainDetail->getItemCount(); ++i)
-		{
-			mRadioTerrainDetail->setIndexEnabled(i, FALSE);
-		}
 	}
 	else
 	{
-		mRadioTerrainDetail->setEnabled(TRUE);
-		
-		for (S32 i = 0; i < mRadioTerrainDetail->getItemCount(); ++i)
-		{
-			mRadioTerrainDetail->setIndexEnabled(i, TRUE);
-		}
-		
+		mRadioTerrainDetail->setEnabled(TRUE);		
 	}
 	
 	// WindLight
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index e15fdd3e3511be4598842357d2eb79c4eddd5e70..11544f5b7b58780180ce9022df5bd14c7ac5c5cc 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -442,52 +442,43 @@ LLPanelRegionInfo::LLPanelRegionInfo()
 {
 }
 
-// static
-void LLPanelRegionInfo::onBtnSet(void* user_data)
+void LLPanelRegionInfo::onBtnSet()
 {
-	LLPanelRegionInfo* panel = (LLPanelRegionInfo*)user_data;
-	if(!panel) return;
-	if (panel->sendUpdate())
+	if (sendUpdate())
 	{
-		panel->disableButton("apply_btn");
+		disableButton("apply_btn");
 	}
 }
 
-//static 
-void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl, void* user_data)
+void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl)
 {
-	if (ctrl)
-	{
-		LLPanelRegionInfo* panel = (LLPanelRegionInfo*) ctrl->getParent();
-		panel->updateChild(ctrl);
-	}
+	updateChild(ctrl); // virtual function
 }
 
-// static
 // Enables the "set" button if it is not already enabled
-void LLPanelRegionInfo::onChangeAnything(LLUICtrl* ctrl, void* user_data)
+void LLPanelRegionInfo::onChangeAnything()
 {
-	LLPanelRegionInfo* panel = (LLPanelRegionInfo*)user_data;
-	if(panel)
-	{
-		panel->enableButton("apply_btn");
-		panel->refresh();
-	}
+	enableButton("apply_btn");
+	refresh();
 }
 
 // static
 // Enables set button on change to line editor
 void LLPanelRegionInfo::onChangeText(LLLineEditor* caller, void* user_data)
 {
-	// reuse the previous method
-	onChangeAnything(0, user_data);
+	LLPanelRegionInfo* panel = dynamic_cast<LLPanelRegionInfo*>(caller->getParent());
+	if(panel)
+	{
+		panel->enableButton("apply_btn");
+		panel->refresh();
+	}
 }
 
 
 // virtual
 BOOL LLPanelRegionInfo::postBuild()
 {
-	childSetAction("apply_btn", onBtnSet, this);
+	getChild<LLUICtrl>("apply_btn")->setCommitCallback(boost::bind(&LLPanelRegionInfo::onBtnSet, this));
 	childDisable("apply_btn");
 	refresh();
 	return TRUE;
@@ -550,19 +541,17 @@ void LLPanelRegionInfo::disableButton(const std::string& btn_name)
 
 void LLPanelRegionInfo::initCtrl(const std::string& name)
 {
-	childSetCommitCallback(name, onChangeAnything, this);
+	getChild<LLUICtrl>(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onChangeAnything, this));
 }
 
 void LLPanelRegionInfo::initHelpBtn(const std::string& name, const std::string& xml_alert)
 {
-	childSetAction(name, onClickHelp, new std::string(xml_alert));
+	getChild<LLUICtrl>(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onClickHelp, this, xml_alert));
 }
 
-// static
-void LLPanelRegionInfo::onClickHelp(void* data)
+void LLPanelRegionInfo::onClickHelp(std::string xml_alert)
 {
-	std::string* xml_alert = (std::string*)data;
-	LLNotifications::instance().add(*xml_alert);
+	LLNotifications::instance().add(xml_alert);
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -1207,9 +1196,9 @@ BOOL LLPanelRegionTerrainInfo::postBuild()
 	initCtrl("terrain_lower_spin");
 
 	initCtrl("fixed_sun_check");
-	childSetCommitCallback("fixed_sun_check", onChangeFixedSun, this);
-	childSetCommitCallback("use_estate_sun_check", onChangeUseEstateTime, this);
-	childSetCommitCallback("sun_hour_slider", onChangeSunHour, this);
+	getChild<LLUICtrl>("fixed_sun_check")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeFixedSun, this));
+	getChild<LLUICtrl>("use_estate_sun_check")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeUseEstateTime, this));
+	getChild<LLUICtrl>("sun_hour_slider")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeSunHour, this));
 
 	childSetAction("download_raw_btn", onClickDownloadRaw, this);
 	childSetAction("upload_raw_btn", onClickUploadRaw, this);
@@ -1292,39 +1281,29 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
 	return TRUE;
 }
 
-// static 
-void LLPanelRegionTerrainInfo::onChangeUseEstateTime(LLUICtrl* ctrl, void* user_data)
+void LLPanelRegionTerrainInfo::onChangeUseEstateTime()
 {
-	LLPanelRegionTerrainInfo* panel = (LLPanelRegionTerrainInfo*) user_data;
-	if (!panel) return;
-	BOOL use_estate_sun = panel->childGetValue("use_estate_sun_check").asBoolean();
-	panel->childSetEnabled("fixed_sun_check", !use_estate_sun);
-	panel->childSetEnabled("sun_hour_slider", !use_estate_sun);
+	BOOL use_estate_sun = childGetValue("use_estate_sun_check").asBoolean();
+	childSetEnabled("fixed_sun_check", !use_estate_sun);
+	childSetEnabled("sun_hour_slider", !use_estate_sun);
 	if (use_estate_sun)
 	{
-		panel->childSetValue("fixed_sun_check", LLSD(FALSE));
-		panel->childSetValue("sun_hour_slider", LLSD(0.f));
+		childSetValue("fixed_sun_check", LLSD(FALSE));
+		childSetValue("sun_hour_slider", LLSD(0.f));
 	}
-	panel->childEnable("apply_btn");
+	childEnable("apply_btn");
 }
 
-// static 
-void LLPanelRegionTerrainInfo::onChangeFixedSun(LLUICtrl* ctrl, void* user_data)
+void LLPanelRegionTerrainInfo::onChangeFixedSun()
 {
-	LLPanelRegionTerrainInfo* panel = (LLPanelRegionTerrainInfo*) user_data;
-	if (!panel) return;
 	// Just enable the apply button.  We let the sun-hour slider be enabled
 	// for both fixed-sun and non-fixed-sun. JC
-	panel->childEnable("apply_btn");
+	childEnable("apply_btn");
 }
 
-// static 
-void LLPanelRegionTerrainInfo::onChangeSunHour(LLUICtrl* ctrl, void*)
+void LLPanelRegionTerrainInfo::onChangeSunHour()
 {
-	// can't use userdata to get panel, slider uses it internally
-	LLPanelRegionTerrainInfo* panel = (LLPanelRegionTerrainInfo*) ctrl->getParent();
-	if (!panel) return;
-	panel->childEnable("apply_btn");
+	childEnable("apply_btn");
 }
 
 // static
@@ -1420,32 +1399,23 @@ void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch)
 	estate_dispatch_initialized = true;
 }
 
-// static
 // Disables the sun-hour slider and the use fixed time check if the use global time is check
-void LLPanelEstateInfo::onChangeUseGlobalTime(LLUICtrl* ctrl, void* user_data)
+void LLPanelEstateInfo::onChangeUseGlobalTime()
 {
-	LLPanelEstateInfo* panel = (LLPanelEstateInfo*) user_data;
-	if (panel)
-	{
-		bool enabled = !panel->childGetValue("use_global_time_check").asBoolean();
-		panel->childSetEnabled("sun_hour_slider", enabled);
-		panel->childSetEnabled("fixed_sun_check", enabled);
-		panel->childSetValue("fixed_sun_check", LLSD(FALSE));
-		panel->enableButton("apply_btn");
-	}
+	bool enabled = !childGetValue("use_global_time_check").asBoolean();
+	childSetEnabled("sun_hour_slider", enabled);
+	childSetEnabled("fixed_sun_check", enabled);
+	childSetValue("fixed_sun_check", LLSD(FALSE));
+	enableButton("apply_btn");
 }
 
 // Enables the sun-hour slider if the fixed-sun checkbox is set
-void LLPanelEstateInfo::onChangeFixedSun(LLUICtrl* ctrl, void* user_data)
+void LLPanelEstateInfo::onChangeFixedSun()
 {
-	LLPanelEstateInfo* panel = (LLPanelEstateInfo*) user_data;
-	if (panel)
-	{
-		bool enabled = !panel->childGetValue("fixed_sun_check").asBoolean();
-		panel->childSetEnabled("use_global_time_check", enabled);
-		panel->childSetValue("use_global_time_check", LLSD(FALSE));
-		panel->enableButton("apply_btn");
-	}
+	bool enabled = !childGetValue("fixed_sun_check").asBoolean();
+	childSetEnabled("use_global_time_check", enabled);
+	childSetValue("use_global_time_check", LLSD(FALSE));
+	enableButton("apply_btn");
 }
 
 
@@ -2130,7 +2100,7 @@ BOOL LLPanelEstateInfo::postBuild()
 	initCtrl("limit_payment");
 	initCtrl("limit_age_verified");
 	initCtrl("voice_chat_check");
-	childSetCommitCallback("abuse_email_address", onChangeAnything, this);
+	getChild<LLUICtrl>("abuse_email_address")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeAnything, this));
 	getChild<LLLineEditor>("abuse_email_address")->setKeystrokeCallback(onChangeText, this);
 
 	initHelpBtn("estate_manager_help",			"HelpEstateEstateManager");
@@ -2144,15 +2114,15 @@ BOOL LLPanelEstateInfo::postBuild()
 	initHelpBtn("allow_resident_help",			"HelpEstateAllowResident");
 	initHelpBtn("allow_group_help",				"HelpEstateAllowGroup");
 	initHelpBtn("ban_resident_help",			"HelpEstateBanResident");
-	initHelpBtn("abuse_email_address_help",         "HelpEstateAbuseEmailAddress");
-	initHelpBtn("voice_chat_help",                  "HelpEstateVoiceChat");
+	initHelpBtn("abuse_email_address_help",     "HelpEstateAbuseEmailAddress");
+	initHelpBtn("voice_chat_help",              "HelpEstateVoiceChat");
 
 	// set up the use global time checkbox
-	childSetCommitCallback("use_global_time_check", onChangeUseGlobalTime, this);
-	childSetCommitCallback("fixed_sun_check", onChangeFixedSun, this);
-	childSetCommitCallback("sun_hour_slider", onChangeChildCtrl, this);
-
-	childSetCommitCallback("allowed_avatar_name_list", onChangeChildCtrl, this);
+	getChild<LLUICtrl>("use_global_time_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeUseGlobalTime, this));
+	getChild<LLUICtrl>("fixed_sun_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeFixedSun, this));
+	getChild<LLUICtrl>("sun_hour_slider")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
+	
+	getChild<LLUICtrl>("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));	
 	LLNameListCtrl *avatar_name_list = getChild<LLNameListCtrl>("allowed_avatar_name_list");
 	if (avatar_name_list)
 	{
@@ -2163,7 +2133,7 @@ BOOL LLPanelEstateInfo::postBuild()
 	childSetAction("add_allowed_avatar_btn", onClickAddAllowedAgent, this);
 	childSetAction("remove_allowed_avatar_btn", onClickRemoveAllowedAgent, this);
 
-	childSetCommitCallback("allowed_group_name_list", onChangeChildCtrl, this);
+	getChild<LLUICtrl>("allowed_group_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
 	LLNameListCtrl* group_name_list = getChild<LLNameListCtrl>("allowed_group_name_list");
 	if (group_name_list)
 	{
@@ -2174,7 +2144,7 @@ BOOL LLPanelEstateInfo::postBuild()
 	getChild<LLUICtrl>("add_allowed_group_btn")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onClickAddAllowedGroup, this));
 	childSetAction("remove_allowed_group_btn", onClickRemoveAllowedGroup, this);
 
-	childSetCommitCallback("banned_avatar_name_list", onChangeChildCtrl, this);
+	getChild<LLUICtrl>("banned_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
 	LLNameListCtrl* banned_name_list = getChild<LLNameListCtrl>("banned_avatar_name_list");
 	if (banned_name_list)
 	{
@@ -2185,7 +2155,7 @@ BOOL LLPanelEstateInfo::postBuild()
 	childSetAction("add_banned_avatar_btn", onClickAddBannedAgent, this);
 	childSetAction("remove_banned_avatar_btn", onClickRemoveBannedAgent, this);
 
-	childSetCommitCallback("estate_manager_name_list", onChangeChildCtrl, this);
+	getChild<LLUICtrl>("estate_manager_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
 	LLNameListCtrl* manager_name_list = getChild<LLNameListCtrl>("estate_manager_name_list");
 	if (manager_name_list)
 	{
@@ -2299,13 +2269,18 @@ void LLPanelEstateInfo::getEstateOwner()
 class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
 {
 public:
-	LLEstateChangeInfoResponder(void* userdata) : mpPanel((LLPanelEstateInfo*)userdata) {};
+	LLEstateChangeInfoResponder(LLPanelEstateInfo* panel)
+	{
+		mpPanel = panel->getHandle();
+	}
 	
 	// if we get a normal response, handle it here
 	virtual void result(const LLSD& content)
 	{
 	    // refresh the panel from the database
-		mpPanel->refresh();
+		LLPanelEstateInfo* panel = dynamic_cast<LLPanelEstateInfo*>(mpPanel.get());
+		if (panel)
+			panel->refresh();
 	}
 	
 	// if we get an error response
@@ -2315,7 +2290,7 @@ class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
 			<< status << ": " << reason << llendl;
 	}
 private:
-	LLPanelEstateInfo* mpPanel;
+	LLHandle<LLPanel> mpPanel;
 };
 
 // tries to send estate info using a cap; returns true if it succeeded
@@ -2353,7 +2328,7 @@ bool LLPanelEstateInfo::commitEstateInfoCaps()
 	body["owner_abuse_email"] = childGetValue("abuse_email_address").asString();
 
 	// we use a responder so that we can re-get the data after committing to the database
-	LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder((void*)this));
+	LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder(this));
     return true;
 }
 
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 68ed4e0c897ac71b70159bd62794ea2fe428b339..95833af8a107f3bf9c7c8e4a5c6468a421260073 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -109,9 +109,9 @@ class LLPanelRegionInfo : public LLPanel
 public:
 	LLPanelRegionInfo();
 	
-	static void onBtnSet(void* user_data);
-	static void onChangeChildCtrl(LLUICtrl* ctrl, void* user_data);
-	static void onChangeAnything(LLUICtrl* ctrl, void* user_data);
+	void onBtnSet();
+	void onChangeChildCtrl(LLUICtrl* ctrl);
+	void onChangeAnything();
 	static void onChangeText(LLLineEditor* caller, void* user_data);
 	
 	virtual bool refreshFromRegion(LLViewerRegion* region);
@@ -128,7 +128,7 @@ class LLPanelRegionInfo : public LLPanel
 	void initHelpBtn(const std::string& name, const std::string& xml_alert);
 
 	// Callback for all help buttons, data is name of XML alert to show.
-	static void onClickHelp(void* data);
+	void onClickHelp(std::string xml_alert);
 	
 	// Returns TRUE if update sent and apply button should be
 	// disabled.
@@ -239,9 +239,9 @@ class LLPanelRegionTerrainInfo : public LLPanelRegionInfo
 protected:
 	virtual BOOL sendUpdate();
 
-	static void onChangeUseEstateTime(LLUICtrl* ctrl, void* user_data);
-	static void onChangeFixedSun(LLUICtrl* ctrl, void* user_data);
-	static void onChangeSunHour(LLUICtrl* ctrl, void*);
+	void onChangeUseEstateTime();
+	void onChangeFixedSun();
+	void onChangeSunHour();
 
 	static void onClickDownloadRaw(void*);
 	static void onClickUploadRaw(void*);
@@ -256,8 +256,8 @@ class LLPanelEstateInfo : public LLPanelRegionInfo
 public:
 	static void initDispatch(LLDispatcher& dispatch);
 	
-	static void onChangeFixedSun(LLUICtrl* ctrl, void* user_data);
-	static void onChangeUseGlobalTime(LLUICtrl* ctrl, void* user_data);
+	void onChangeFixedSun();
+	void onChangeUseGlobalTime();
 	
 	static void onClickEditSky(void* userdata);
 	static void onClickEditSkyHelp(void* userdata);	
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 4c83530f43b9784de5a9efdbca99618f02a7dc9b..bd9798c18e144c33fd037dd05c30951c2dbca779 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -34,6 +34,7 @@
 #include "llviewerprecompiledheaders.h"
 #include "llfloatersearch.h"
 #include "llmediactrl.h"
+#include "llagent.h"
 
 
 LLFloaterSearch::LLFloaterSearch(const LLSD& key) :
@@ -117,6 +118,14 @@ void LLFloaterSearch::search(const LLSD &key)
 	std::string search_text = key.has("id") ? key["id"].asString() : "";
 	url += std::string("?q=") + search_text;
 
+	// append the maturity and teen capabilities for this agent
+	BOOL godlike = gAgent.isGodlike();
+	bool mature_enabled = gAgent.canAccessMature() || godlike;
+	bool adult_enabled = gAgent.canAccessAdult() || godlike;
+	std::string mature = (mature_enabled) ? "True" : "False";
+	std::string teen = (!adult_enabled) ? "True" : "False";
+	url += "&t=" + teen + "&m=" + mature;
+
 	// and load the URL in the web view
 	mBrowser->navigateTo(url);
 }
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index e00b352c9bd9da8963241cfef8278d65eddcfbc2..5fee84190b9b383402629167b54560fc0cfe95d5 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -49,6 +49,7 @@
 #include "llfloaterreg.h"
 #include "llfocusmgr.h"
 #include "llmediaentry.h"
+#include "llmediactrl.h"
 #include "llmenugl.h"
 #include "llpanelcontents.h"
 #include "llpanelface.h"
@@ -221,6 +222,7 @@ BOOL	LLFloaterTools::postBuild()
 	mRadioGroupMove		= getChild<LLRadioGroup>("move_radio_group");
 	mRadioGroupEdit		= getChild<LLRadioGroup>("edit_radio_group");
 	mBtnGridOptions		= getChild<LLButton>("Options...");
+	mTitleMedia			= getChild<LLMediaCtrl>("title_media");
 	
 	mCheckSelectIndividual	= getChild<LLCheckBoxCtrl>("checkbox edit linked parts");	
 	childSetValue("checkbox edit linked parts",(BOOL)gSavedSettings.getBOOL("EditLinkedParts"));
@@ -304,6 +306,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
 
 	mCheckSnapToGrid(NULL),
 	mBtnGridOptions(NULL),
+	mTitleMedia(NULL),
 	mTextGridMode(NULL),
 	mComboGridMode(NULL),
 	mCheckStretchUniform(NULL),
@@ -335,7 +338,8 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
 	mPanelLandInfo(NULL),
 
 	mTabLand(NULL),
-	mDirty(TRUE)
+	mDirty(TRUE),
+	mNeedMediaTitle(TRUE)
 {
 	gFloaterTools = this;
 	
@@ -440,6 +444,9 @@ void LLFloaterTools::draw()
 		mDirty = FALSE;
 	}
 
+	// grab media name/title and update the UI widget
+	updateMediaTitle();
+
 	//	mCheckSelectIndividual->set(gSavedSettings.getBOOL("EditLinkedParts"));
 	LLFloater::draw();
 }
@@ -736,6 +743,10 @@ void LLFloaterTools::onClose(bool app_quitting)
 
 	LLViewerJoystick::getInstance()->moveAvatar(false);
 
+	// destroy media source used to grab media title
+	if( mTitleMedia )
+		mTitleMedia->unloadMediaSource();
+
     // Different from handle_reset_view in that it doesn't actually 
 	//   move the camera if EditCameraMovement is not set.
 	gAgent.resetView(gSavedSettings.getBOOL("EditCameraMovement"));
@@ -1038,12 +1049,13 @@ void LLFloaterTools::getMediaState()
 		  &&first_object->permModify() 
 	      ))
 	{
-		childSetEnabled("media_tex", FALSE);
+		childSetEnabled("Add_Media",  FALSE);
+/*		childSetEnabled("media_tex", FALSE);
 		childSetEnabled("add_media", FALSE);
 		childSetEnabled("delete_media", FALSE);
 		childSetEnabled("edit_media", FALSE);
 		childSetEnabled("media_info", FALSE);
-		media_info->setEnabled(FALSE);
+		media_info->setEnabled(FALSE);*/
 		media_info->clear();
 		clearMediaSettings();
 		return;
@@ -1054,13 +1066,14 @@ void LLFloaterTools::getMediaState()
 	
 	if(!has_media_capability)
 	{
-		childSetEnabled("media_tex", FALSE);
+		childSetEnabled("Add_Media",  FALSE);
+	/*	childSetEnabled("media_tex", FALSE);
 		childSetEnabled("add_media", FALSE);
 		childSetEnabled("delete_media", FALSE);
 		childSetEnabled("edit_media", FALSE);
 		childSetEnabled("media_info", FALSE);
 		media_info->setEnabled(FALSE);
-		media_info->clear();	
+		media_info->clear();*/	
 		clearMediaSettings();
 		return;
 	}
@@ -1081,6 +1094,7 @@ void LLFloaterTools::getMediaState()
 	LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue( &func, has_media );
 	bool bool_has_media = (has_media & LLTextureEntry::MF_HAS_MEDIA);
 
+	
 	const LLMediaEntry default_media_data;
 	
 	struct functor_getter_media_data : public LLSelectedTEGetFunctor< LLMediaEntry>
@@ -1105,9 +1119,11 @@ void LLFloaterTools::getMediaState()
 	
 	std::string multi_media_info_str = LLTrans::getString("Multiple Media");
 	std::string media_title = "";
+	mNeedMediaTitle = false;
 	// update UI depending on whether "object" (prim or face) has media
 	// and whether or not you are allowed to edit it.
 	
+	childSetEnabled("Add_Media",  editable);
 	// IF all the faces have media (or all dont have media)
 	if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
 	{
@@ -1119,25 +1135,26 @@ void LLFloaterTools::getMediaState()
 			// Media data is valid
 			if(media_data_get!=default_media_data)
 			{
-				//TODO: get media title
-				//media_title =  media_data_get->getTile();
-				//LLFloaterMediaSettings::getInstance()->mIdenticalValidMedia = true;
+				// initial media title is the media URL (until we get the name)
 				media_title = media_data_get.getHomeURL();
+
+				// kick off a navigate and flag that we need to update the title
+				navigateToTitleMedia( media_data_get.getHomeURL() );
+				mNeedMediaTitle = true;
 			}
 			// else all faces might be empty. 
-			
-			
 		}
 		else // there' re Different Medias' been set on on the faces.
 		{
 			media_title = multi_media_info_str;
+			mNeedMediaTitle = false;
 		}
 		
 		childSetEnabled("media_tex",  bool_has_media & editable);
 		childSetEnabled( "edit_media", bool_has_media & editable );
 		childSetEnabled( "delete_media", bool_has_media & editable );
 		childSetEnabled( "add_media", ( ! bool_has_media ) & editable );
-		media_info->setEnabled(bool_has_media & editable);
+		media_info->setEnabled(false);
 			// TODO: display a list of all media on the face - use 'identical' flag
 	}
 	else // not all face has media but at least one does.
@@ -1148,20 +1165,23 @@ void LLFloaterTools::getMediaState()
 		if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
 		{
 			media_title = multi_media_info_str;
+			mNeedMediaTitle = false;
 		}
 		else
 		{
 			// Media data is valid
 			if(media_data_get!=default_media_data)
 			{
-				//TODO: get media title
-				//media_title =  media_data_get->getTile();
+				// initial media title is the media URL (until we get the name)
 				media_title = media_data_get.getHomeURL();
+
+				// kick off a navigate and flag that we need to update the title
+				navigateToTitleMedia( media_data_get.getHomeURL() );
+				mNeedMediaTitle = true;
 			}
-			
 		}
 		
-		media_info->setEnabled(TRUE);
+		media_info->setEnabled(false);
 		media_info->setTentative(true);
 		childSetEnabled("media_tex",  TRUE);
 		childSetEnabled( "edit_media", TRUE);
@@ -1249,12 +1269,63 @@ bool LLFloaterTools::deleteMediaConfirm(const LLSD& notification, const LLSD& re
 	return false;
 }
 
+//////////////////////////////////////////////////////////////////////////////
+//
 void LLFloaterTools::clearMediaSettings()
 {
 	LLFloaterMediaSettings::getInstance();
 	LLFloaterMediaSettings::clearValues(false);
 
 }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void LLFloaterTools::navigateToTitleMedia( const std::string url )
+{
+	if ( mTitleMedia )
+	{
+		LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin();
+		if ( media_plugin )
+		{
+			// if it's a movie, we don't want to hear it
+			media_plugin->setVolume( 0 );
+		};
+		mTitleMedia->navigateTo( url );
+	};
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void LLFloaterTools::updateMediaTitle()
+{
+	// only get the media name if we need it
+	if ( ! mNeedMediaTitle )
+		return;
+
+	// get plugin impl
+	LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin();
+	if ( media_plugin )
+	{
+		// get the media name (asynchronous - must call repeatedly)
+		std::string media_title = media_plugin->getMediaName();
+
+		// only replace the title if what we get contains something
+		if ( ! media_title.empty() )
+		{
+			// update the UI widget
+			LLLineEditor* media_title_field = getChild<LLLineEditor>("media_info");
+			if ( media_title_field )
+			{
+				media_title_field->setText( media_title );
+
+				// stop looking for a title when we get one
+				// FIXME: check this is the right approach
+				mNeedMediaTitle = false;
+			};
+		};
+	};
+}
+
 //////////////////////////////////////////////////////////////////////////////
 //
 void LLFloaterTools::updateMediaSettings()
diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h
index 59acef60712184b3ecf86955e0284c663b3130da..a3e0cac034241218c323cf53aae0f2173594aafd 100644
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -51,6 +51,7 @@ class LLRadioGroup;
 class LLSlider;
 class LLTabContainer;
 class LLTextBox;
+class LLMediaCtrl;
 class LLTool;
 class LLParcelSelection;
 class LLObjectSelection;
@@ -107,6 +108,8 @@ class LLFloaterTools
 	void onClickBtnAddMedia();
 	void onClickBtnEditMedia();
 	void clearMediaSettings();
+	void updateMediaTitle();
+	void navigateToTitleMedia( const std::string url );
 	bool selectedMediaEditable();
 
 private:
@@ -182,6 +185,9 @@ class LLFloaterTools
 	LLParcelSelectionHandle	mParcelSelection;
 	LLObjectSelectionHandle	mObjectSelection;
 
+	LLMediaCtrl				*mTitleMedia;
+	bool					mNeedMediaTitle;
+
 private:
 	BOOL					mDirty;
 
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index 1c3443ae809533dab69e185390e4148481727123..8d2d48f1af876bf5b4de26c5e7d36a23db3aaadb 100644
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -35,8 +35,6 @@
 #include "llfloatertos.h"
 
 // viewer includes
-#include "llappviewer.h"
-#include "llstartup.h"
 #include "llviewerstats.h"
 #include "llviewerwindow.h"
 
@@ -50,13 +48,15 @@
 #include "lluictrlfactory.h"
 #include "llvfile.h"
 #include "message.h"
+#include "llstartup.h"              // login_alert_done
 
 
-LLFloaterTOS::LLFloaterTOS(const LLSD& message)
-:	LLModalDialog( message ),
-	mMessage(message.asString()),
+LLFloaterTOS::LLFloaterTOS(const LLSD& data)
+:	LLModalDialog( data["message"].asString() ),
+	mMessage(data["message"].asString()),
 	mWebBrowserWindowId( 0 ),
-	mLoadCompleteCount( 0 )
+	mLoadCompleteCount( 0 ),
+	mReplyPumpName(data["reply_pump"].asString())
 {
 }
 
@@ -193,25 +193,12 @@ void LLFloaterTOS::onContinue( void* userdata )
 {
 	LLFloaterTOS* self = (LLFloaterTOS*) userdata;
 	llinfos << "User agrees with TOS." << llendl;
-	if (self->getInstanceName() == "message_tos")
-	{
-		gAcceptTOS = TRUE;
-	}
-	else
-	{
-		gAcceptCriticalMessage = TRUE;
-	}
 
-	// Testing TOS dialog
-	#if ! LL_RELEASE_FOR_DOWNLOAD		
-	if ( LLStartUp::getStartupState() == STATE_LOGIN_WAIT )
+	if(self->mReplyPumpName != "")
 	{
-		LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+		LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(true));
 	}
-	else 
-	#endif
 
-	LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );			// Go back and finish authentication
 	self->closeFloater(); // destroys this object
 }
 
@@ -221,7 +208,12 @@ void LLFloaterTOS::onCancel( void* userdata )
 	LLFloaterTOS* self = (LLFloaterTOS*) userdata;
 	llinfos << "User disagrees with TOS." << llendl;
 	LLNotifications::instance().add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done);
-	LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+
+	if(self->mReplyPumpName != "")
+	{
+		LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(false));
+	}
+
 	self->mLoadCompleteCount = 0;  // reset counter for next time we come to TOS
 	self->closeFloater(); // destroys this object
 }
@@ -241,3 +233,4 @@ void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev
 		}
 	}
 }
+
diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h
index 49f982aa80708001712a6293806dbd0a78eca3fb..1d573e817051b5bb5d977aea5b365063a2d3750c 100644
--- a/indra/newview/llfloatertos.h
+++ b/indra/newview/llfloatertos.h
@@ -36,6 +36,7 @@
 #include "llmodaldialog.h"
 #include "llassetstorage.h"
 #include "llmediactrl.h"
+#include <boost/function.hpp>
 
 class LLButton;
 class LLRadioGroup;
@@ -48,7 +49,7 @@ class LLFloaterTOS :
 	public LLViewerMediaObserver
 {
 public:
-	LLFloaterTOS(const LLSD& message);
+	LLFloaterTOS(const LLSD& data);
 	virtual ~LLFloaterTOS();
 
 	BOOL postBuild();
@@ -68,6 +69,7 @@ class LLFloaterTOS :
 	std::string		mMessage;
 	int				mWebBrowserWindowId;
 	int				mLoadCompleteCount;
+	std::string		mReplyPumpName;
 };
 
 #endif // LL_LLFLOATERTOS_H
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index ac743df4f1c1e5f91e1a94ae6f12940b4a5b3be1..2fe21f28de1b008563570233d9e15244dfdcd531 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -865,7 +865,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
 	}
 	else																// if it is a panel...
 	{
-		static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+		const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+		S32 floater_header_size = floater_params.header_height;
 
 		LLPanel::Params panel_params;
 		LLPanel* panel = LLUICtrlFactory::create<LLPanel>(panel_params);	// create a new panel
diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp
index b64257b11da752463cf8c58f869bb919ba0a4d56..aca9198f59ac152d0536bfa4f2e52d44d5d14bfc 100644
--- a/indra/newview/llfloatervoicedevicesettings.cpp
+++ b/indra/newview/llfloatervoicedevicesettings.cpp
@@ -43,7 +43,7 @@
 #include "llsliderctrl.h"
 #include "llviewercontrol.h"
 #include "llvoiceclient.h"
-#include "llimpanel.h"
+#include "llvoicechannel.h"
 
 // Library includes (after viewer)
 #include "lluictrlfactory.h"
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 3591daf92d379cbdaa736ef6e8c23bc565c9656c..f83a426cdab91b6802c7f2ebc58a09e8252c4215 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -71,6 +71,10 @@ LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style)
 	{
 		LLFontDescriptor labelfontdesc("SansSerif", "Small", style);
 		rtn = LLFontGL::getFont(labelfontdesc);
+		if (!rtn)
+		{
+			rtn = LLFontGL::getFontDefault();
+		}
 		sFonts[style] = rtn;
 	}
 	return rtn;
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index a20b5ea66c0ba1d015011477fabdcb135356738f..dee86f4a222504ac1f0e6192de6ddea54bb0f4ce 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -42,7 +42,6 @@
 #include "llchiclet.h"
 #include "llfloaterchat.h"
 #include "llfloaterreg.h"
-#include "llimview.h"
 #include "lllineeditor.h"
 #include "lllogchat.h"
 #include "llpanelimcontrolpanel.h"
@@ -50,7 +49,9 @@
 #include "lltrans.h"
 #include "llchathistory.h"
 #include "llviewerwindow.h"
+#include "llvoicechannel.h"
 #include "lltransientfloatermgr.h"
+#include "llinventorymodel.h"
 
 
 
@@ -61,7 +62,14 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
 	mLastMessageIndex(-1),
 	mDialog(IM_NOTHING_SPECIAL),
 	mChatHistory(NULL),
-	mInputEditor(NULL), 
+	mInputEditor(NULL),
+	mSavedTitle(),
+	mTypingStart(),
+	mShouldSendTypingState(false),
+	mMeTyping(false),
+	mOtherTyping(false),
+	mTypingTimer(),
+	mTypingTimeoutTimer(),
 	mPositioned(false),
 	mSessionInitialized(false)
 {
@@ -71,12 +79,15 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
 		mSessionInitialized = im_session->mSessionInitialized;
 		
 		mDialog = im_session->mType;
-		if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog)
-		{
+		switch(mDialog){
+		case IM_NOTHING_SPECIAL:
+		case IM_SESSION_P2P_INVITE:
 			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
-		}
-		else
-		{
+			break;
+		case IM_SESSION_CONFERENCE_START:
+			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
+			break;
+		default:
 			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
 		}
 	}
@@ -95,6 +106,7 @@ void LLIMFloater::onFocusReceived()
 // virtual
 void LLIMFloater::onClose(bool app_quitting)
 {
+	setTyping(false);
 	gIMMgr->leaveSession(mSessionID);
 }
 
@@ -141,6 +153,7 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )
 {
 	LLIMFloater* self = (LLIMFloater*) userdata;
 	self->sendMsg();
+	self->setTyping(false);
 }
 
 void LLIMFloater::sendMsg()
@@ -193,9 +206,10 @@ BOOL LLIMFloater::postBuild()
 	if (other_party_id.notNull())
 	{
 		mOtherParticipantUUID = other_party_id;
-		mControlPanel->setID(mOtherParticipantUUID);
 	}
 
+	mControlPanel->setSessionId(mSessionID);
+
 	LLButton* slide_left = getChild<LLButton>("slide_left_btn");
 	slide_left->setVisible(mControlPanel->getVisible());
 	slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
@@ -222,10 +236,16 @@ BOOL LLIMFloater::postBuild()
 		
 	setTitle(LLIMModel::instance().getName(mSessionID));
 	setDocked(true);
-	
-	if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+
+	mTypingStart = LLTrans::getString("IM_typing_start_string");
+
+	// Disable input editor if session cannot accept text
+	LLIMModel::LLIMSession* im_session =
+		LLIMModel::instance().findIMSession(mSessionID);
+	if( im_session && !im_session->mTextIMPossible )
 	{
-		LLLogChat::loadHistory(getTitle(), &chatFromLogFile, (void *)this);
+		mInputEditor->setEnabled(FALSE);
+		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
 	}
 
 	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
@@ -234,6 +254,20 @@ BOOL LLIMFloater::postBuild()
 	return LLDockableFloater::postBuild();
 }
 
+// virtual
+void LLIMFloater::draw()
+{
+	if ( mMeTyping )
+	{
+		// Time out if user hasn't typed for a while.
+		if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS )
+		{
+			setTyping(false);
+		}
+	}
+
+	LLTransientDockableFloater::draw();
+}
 
 
 // static
@@ -255,11 +289,22 @@ void* LLIMFloater::createPanelGroupControl(void* userdata)
 	return self->mControlPanel;
 }
 
+// static
+void* LLIMFloater::createPanelAdHocControl(void* userdata)
+{
+	LLIMFloater *self = (LLIMFloater*)userdata;
+	self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID);
+	self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml");
+	return self->mControlPanel;
+}
+
 void LLIMFloater::onSlide()
 {
 	LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
 	im_control_panel->setVisible(!im_control_panel->getVisible());
 
+	gSavedSettings.setBOOL("IMShowControlPanel", im_control_panel->getVisible());
+
 	getChild<LLButton>("slide_left_btn")->setVisible(im_control_panel->getVisible());
 	getChild<LLButton>("slide_right_btn")->setVisible(!im_control_panel->getVisible());
 }
@@ -302,6 +347,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
 				LLDockControl::TOP,  boost::bind(&LLIMFloater::getAllowedRect, floater, _1)));
 	}
 
+	floater->childSetVisible("panel_im_control_panel", gSavedSettings.getBOOL("IMShowControlPanel"));
+
 	return floater;
 }
 
@@ -363,8 +410,6 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
 	{
 		// ensure the list of messages is updated when floater is made visible
 		show(session_id);
-		// update number of unread notifications in the SysWell
-		LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications();
 		return true;
 	}
 }
@@ -379,10 +424,12 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
 {
 	mSessionInitialized = true;
 
+	//will be different only for an ad-hoc im session
 	if (mSessionID != im_session_id)
 	{
 		mSessionID = im_session_id;
 		setKey(im_session_id);
+		mControlPanel->setSessionId(im_session_id);
 	}
 	
 	//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
@@ -402,10 +449,8 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
 
 void LLIMFloater::updateMessages()
 {
-	std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1);
-	std::string agent_name;
-
-	gCacheName->getFullName(gAgentID, agent_name);
+	std::list<LLSD> messages;
+	LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1);
 
 	if (messages.size())
 	{
@@ -414,21 +459,22 @@ void LLIMFloater::updateMessages()
 		std::ostringstream message;
 		std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();
 		std::list<LLSD>::const_reverse_iterator iter_end = messages.rend();
-	    for (; iter != iter_end; ++iter)
+		for (; iter != iter_end; ++iter)
 		{
 			LLSD msg = *iter;
 
-			std::string from = msg["from"].asString();
 			std::string time = msg["time"].asString();
 			LLUUID from_id = msg["from_id"].asUUID();
+			std::string from = from_id != gAgentID ? msg["from"].asString() : LLTrans::getString("You");
 			std::string message = msg["message"].asString();
 			LLStyle::Params style_params;
 			style_params.color(chat_color);
 
-			if (from == agent_name)
-				from = LLTrans::getString("You");
+			LLChat chat(message);
+			chat.mFromID = from_id;
+			chat.mFromName = from;
 
-			mChatHistory->appendWidgetMessage(from_id, from, time, message, style_params);
+			mChatHistory->appendWidgetMessage(chat, style_params);
 
 			mLastMessageIndex = msg["index"].asInteger();
 		}
@@ -440,9 +486,14 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
 {
 	LLIMFloater* self= (LLIMFloater*) userdata;
 
-	//in disconnected state IM input editor should be disabled
-	self->mInputEditor->setEnabled(!gDisconnected);
-
+	// Allow enabling the LLIMFloater input editor only if session can accept text
+	LLIMModel::LLIMSession* im_session =
+		LLIMModel::instance().findIMSession(self->mSessionID);
+	if( im_session && im_session->mTextIMPossible )
+	{
+		//in disconnected state IM input editor should be disabled
+		self->mInputEditor->setEnabled(!gDisconnected);
+	}
 	self->mChatHistory->setCursorAndScrollToEnd();
 }
 
@@ -450,7 +501,7 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
 void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata)
 {
 	LLIMFloater* self = (LLIMFloater*) userdata;
-	self->setTyping(FALSE);
+	self->setTyping(false);
 }
 
 // static
@@ -460,53 +511,297 @@ void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata)
 	std::string text = self->mInputEditor->getText();
 	if (!text.empty())
 	{
-		self->setTyping(TRUE);
+		self->setTyping(true);
 	}
 	else
 	{
 		// Deleting all text counts as stopping typing.
-		self->setTyping(FALSE);
+		self->setTyping(false);
 	}
 }
 
+void LLIMFloater::setTyping(bool typing)
+{
+	if ( typing )
+	{
+		// Started or proceeded typing, reset the typing timeout timer
+		mTypingTimeoutTimer.reset();
+	}
 
-//just a stub for now
-void LLIMFloater::setTyping(BOOL typing)
+	if ( mMeTyping != typing )
+	{
+		// Typing state is changed
+		mMeTyping = typing;
+		// So, should send current state
+		mShouldSendTypingState = true;
+		// In case typing is started, send state after some delay
+		mTypingTimer.reset();
+	}
+
+	// Don't want to send typing indicators to multiple people, potentially too
+	// much network traffic. Only send in person-to-person IMs.
+	if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL )
+	{
+		if ( mMeTyping )
+		{
+			if ( mTypingTimer.getElapsedTimeF32() > 1.f )
+			{
+				// Still typing, send 'start typing' notification
+				LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE);
+				mShouldSendTypingState = false;
+			}
+		}
+		else
+		{
+			// Send 'stop typing' notification immediately
+			LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE);
+			mShouldSendTypingState = false;
+		}
+	}
+
+	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+	if (speaker_mgr)
+		speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
+
+}
+
+void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
 {
+	if ( typing )
+	{
+		// other user started typing
+		addTypingIndicator(im_info);
+	}
+	else
+	{
+		// other user stopped typing
+		removeTypingIndicator(im_info);
+	}
 }
 
-void LLIMFloater::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
+void LLIMFloater::processSessionUpdate(const LLSD& session_update)
 {
-	if (!userdata) return;
+	// *TODO : verify following code when moderated mode will be implemented
+	if ( false && session_update.has("moderated_mode") &&
+		 session_update["moderated_mode"].has("voice") )
+	{
+		BOOL voice_moderated = session_update["moderated_mode"]["voice"];
+		const std::string session_label = LLIMModel::instance().getName(mSessionID);
 
-	LLIMFloater* self = (LLIMFloater*) userdata;
-	std::string message = line;
-	S32 im_log_option =  gSavedPerAccountSettings.getS32("IMLogOptions");
-	switch (type)
+		if (voice_moderated)
+		{
+			setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label"));
+		}
+		else
+		{
+			setTitle(session_label);
+		}
+
+		// *TODO : uncomment this when/if LLPanelActiveSpeakers panel will be added
+		//update the speakers dropdown too
+		//mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
+	}
+}
+
+BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask,
+						   BOOL drop, EDragAndDropType cargo_type,
+						   void *cargo_data, EAcceptance *accept,
+						   std::string& tooltip_msg)
+{
+
+	if (mDialog == IM_NOTHING_SPECIAL)
+	{
+		LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop,
+												 cargo_type, cargo_data, accept);
+	}
+
+	// handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites
+	else if (isInviteAllowed())
+	{
+		*accept = ACCEPT_NO;
+
+		if (cargo_type == DAD_CALLINGCARD)
+		{
+			if (dropCallingCard((LLInventoryItem*)cargo_data, drop))
+			{
+				*accept = ACCEPT_YES_MULTI;
+			}
+		}
+		else if (cargo_type == DAD_CATEGORY)
+		{
+			if (dropCategory((LLInventoryCategory*)cargo_data, drop))
+			{
+				*accept = ACCEPT_YES_MULTI;
+			}
+		}
+	}
+	return TRUE;
+}
+
+BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop)
+{
+	BOOL rv = isInviteAllowed();
+	if(rv && item && item->getCreatorUUID().notNull())
 	{
-	case LLLogChat::LOG_EMPTY:
-		// add warning log enabled message
-		if (im_log_option!=LOG_CHAT)
+		if(drop)
 		{
-			message = LLTrans::getString("IM_logging_string");
+			std::vector<LLUUID> ids;
+			ids.push_back(item->getCreatorUUID());
+			inviteToSession(ids);
 		}
-		break;
-	case LLLogChat::LOG_END:
-		// add log end message
-		if (im_log_option!=LOG_CHAT)
+	}
+	else
+	{
+		// set to false if creator uuid is null.
+		rv = FALSE;
+	}
+	return rv;
+}
+
+BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop)
+{
+	BOOL rv = isInviteAllowed();
+	if(rv && category)
+	{
+		LLInventoryModel::cat_array_t cats;
+		LLInventoryModel::item_array_t items;
+		LLUniqueBuddyCollector buddies;
+		gInventory.collectDescendentsIf(category->getUUID(),
+										cats,
+										items,
+										LLInventoryModel::EXCLUDE_TRASH,
+										buddies);
+		S32 count = items.count();
+		if(count == 0)
 		{
-			message = LLTrans::getString("IM_logging_string");
+			rv = FALSE;
 		}
-		break;
-	case LLLogChat::LOG_LINE:
-		// just add normal lines from file
-		break;
-	default:
-		// nothing
-		break;
+		else if(drop)
+		{
+			std::vector<LLUUID> ids;
+			ids.reserve(count);
+			for(S32 i = 0; i < count; ++i)
+			{
+				ids.push_back(items.get(i)->getCreatorUUID());
+			}
+			inviteToSession(ids);
+		}
+	}
+	return rv;
+}
+
+BOOL LLIMFloater::isInviteAllowed() const
+{
+
+	return ( (IM_SESSION_CONFERENCE_START == mDialog)
+			 || (IM_SESSION_INVITE == mDialog) );
+}
+
+class LLSessionInviteResponder : public LLHTTPClient::Responder
+{
+public:
+	LLSessionInviteResponder(const LLUUID& session_id)
+	{
+		mSessionID = session_id;
+	}
+
+	void error(U32 statusNum, const std::string& reason)
+	{
+		llinfos << "Error inviting all agents to session" << llendl;
+		//throw something back to the viewer here?
 	}
 
-	self->mChatHistory->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
-	self->mChatHistory->blockUndo();
+private:
+	LLUUID mSessionID;
+};
+
+BOOL LLIMFloater::inviteToSession(const std::vector<LLUUID>& ids)
+{
+	LLViewerRegion* region = gAgent.getRegion();
+	if (!region)
+	{
+		return FALSE;
+	}
+
+	S32 count = ids.size();
+
+	if( isInviteAllowed() && (count > 0) )
+	{
+		llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl;
+
+		std::string url = region->getCapability("ChatSessionRequest");
+
+		LLSD data;
+
+		data["params"] = LLSD::emptyArray();
+		for (int i = 0; i < count; i++)
+		{
+			data["params"].append(ids[i]);
+		}
+
+		data["method"] = "invite";
+		data["session-id"] = mSessionID;
+		LLHTTPClient::post(
+			url,
+			data,
+			new LLSessionInviteResponder(
+					mSessionID));
+	}
+	else
+	{
+		llinfos << "LLIMFloater::inviteToSession -"
+				<< " no need to invite agents for "
+				<< mDialog << llendl;
+		// successful add, because everyone that needed to get added
+		// was added.
+	}
+
+	return TRUE;
+}
+
+void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)
+{
+	// We may have lost a "stop-typing" packet, don't add it twice
+	if ( im_info && !mOtherTyping )
+	{
+		mOtherTyping = true;
+
+		// Create typing is started title string
+		LLUIString typing_start(mTypingStart);
+		typing_start.setArg("[NAME]", im_info->mName);
+
+		// Save and set new title
+		mSavedTitle = getTitle();
+		setTitle (typing_start);
+
+		// Update speaker
+		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+		if ( speaker_mgr )
+		{
+			speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE);
+		}
+	}
+}
+
+void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)
+{
+	if ( mOtherTyping )
+	{
+		mOtherTyping = false;
+
+		// Revert the title to saved one
+		setTitle(mSavedTitle);
+
+		if ( im_info )
+		{
+			// Update speaker
+			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+			if ( speaker_mgr )
+			{
+				speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);
+			}
+		}
+
+	}
 }
 
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index 99810b6d6ddaf5de1a7c6d3090b024551c0f72c1..f5edb3188abb10cbb8c8dbbc0765fa4c2d604ae9 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -35,11 +35,13 @@
 
 #include "lltransientdockablefloater.h"
 #include "lllogchat.h"
+#include "lltooldraganddrop.h"
 
 class LLLineEditor;
 class LLPanelChatControlPanel;
 class LLChatHistory;
-
+class LLInventoryItem;
+class LLInventoryCategory;
 
 /**
  * Individual IM window that appears at the bottom of the screen,
@@ -55,6 +57,8 @@ class LLIMFloater : public LLTransientDockableFloater
 	// LLView overrides
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void setVisible(BOOL visible);
+	// Check typing timeout timer.
+	/*virtual*/ void draw();
 
 	// LLFloater overrides
 	/*virtual*/ void onClose(bool app_quitting);
@@ -85,24 +89,41 @@ class LLIMFloater : public LLTransientDockableFloater
 	void setPositioned(bool b) { mPositioned = b; };
 
 	void onVisibilityChange(const LLSD& new_visibility);
+	void processIMTyping(const LLIMInfo* im_info, BOOL typing);
+	void processSessionUpdate(const LLSD& session_update);
+
+	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
+							   BOOL drop, EDragAndDropType cargo_type,
+							   void *cargo_data, EAcceptance *accept,
+							   std::string& tooltip_msg);
 
 private:
 	// process focus events to set a currently active session
 	/* virtual */ void onFocusLost();
 	/* virtual */ void onFocusReceived();
+
+	BOOL dropCallingCard(LLInventoryItem* item, BOOL drop);
+	BOOL dropCategory(LLInventoryCategory* category, BOOL drop);
+
+	BOOL isInviteAllowed() const;
+	BOOL inviteToSession(const std::vector<LLUUID>& agent_ids);
 	
 	static void		onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata );
 	static void		onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);
 	static void		onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
-	void			setTyping(BOOL typing);
+	void			setTyping(bool typing);
 	void			onSlide();
 	static void*	createPanelIMControl(void* userdata);
 	static void*	createPanelGroupControl(void* userdata);
+	static void* 	createPanelAdHocControl(void* userdata);
 	// gets a rect that bounds possible positions for the LLIMFloater on a screen (EXT-1111)
 	void getAllowedRect(LLRect& rect);
 
-	static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
+	// Add the "User is typing..." indicator.
+	void addTypingIndicator(const LLIMInfo* im_info);
 
+	// Remove the "User is typing..." indicator.
+	void removeTypingIndicator(const LLIMInfo* im_info = NULL);
 
 	LLPanelChatControlPanel* mControlPanel;
 	LLUUID mSessionID;
@@ -114,6 +135,14 @@ class LLIMFloater : public LLTransientDockableFloater
 	LLLineEditor* mInputEditor;
 	bool mPositioned;
 
+	std::string mSavedTitle;
+	LLUIString mTypingStart;
+	bool mMeTyping;
+	bool mOtherTyping;
+	bool mShouldSendTypingState;
+	LLFrameTimer mTypingTimer;
+	LLFrameTimer mTypingTimeoutTimer;
+
 	bool mSessionInitialized;
 	LLSD mQueuedMsgsForInit;
 };
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 163984f7409a6977970d135458575fb384d56140..c4beb666ea7241549f65a57597790387d5efdf27 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -54,6 +54,7 @@
 #include "llconsole.h"
 #include "llgroupactions.h"
 #include "llfloater.h"
+#include "llfloateractivespeakers.h"
 #include "llfloatercall.h"
 #include "llavataractions.h"
 #include "llimview.h"
@@ -77,6 +78,7 @@
 #include "llviewercontrol.h"
 #include "lluictrlfactory.h"
 #include "llviewerwindow.h"
+#include "llvoicechannel.h"
 #include "lllogchat.h"
 #include "llweb.h"
 #include "llhttpclient.h"
@@ -90,7 +92,6 @@
 const S32 LINE_HEIGHT = 16;
 const S32 MIN_WIDTH = 200;
 const S32 MIN_HEIGHT = 130;
-const U32 DEFAULT_RETRIES_COUNT = 3;
 
 //
 // Statics
@@ -100,831 +101,6 @@ static std::string sTitleString = "Instant Message with [NAME]";
 static std::string sTypingStartString = "[NAME]: ...";
 static std::string sSessionStartString = "Starting session with [NAME] please wait.";
 
-LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
-LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
-LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
-LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
-
-BOOL LLVoiceChannel::sSuspended = FALSE;
-
-
-
-class LLVoiceCallCapResponder : public LLHTTPClient::Responder
-{
-public:
-	LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
-
-	virtual void error(U32 status, const std::string& reason);	// called with bad status codes
-	virtual void result(const LLSD& content);
-
-private:
-	LLUUID mSessionID;
-};
-
-
-void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
-{
-	llwarns << "LLVoiceCallCapResponder::error("
-		<< status << ": " << reason << ")"
-		<< llendl;
-	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
-	if ( channelp )
-	{
-		if ( 403 == status )
-		{
-			//403 == no ability
-			LLNotifications::instance().add(
-				"VoiceNotAllowed",
-				channelp->getNotifyArgs());
-		}
-		else
-		{
-			LLNotifications::instance().add(
-				"VoiceCallGenericError",
-				channelp->getNotifyArgs());
-		}
-		channelp->deactivate();
-	}
-}
-
-void LLVoiceCallCapResponder::result(const LLSD& content)
-{
-	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
-	if (channelp)
-	{
-		//*TODO: DEBUG SPAM
-		LLSD::map_const_iterator iter;
-		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
-		{
-			llinfos << "LLVoiceCallCapResponder::result got " 
-				<< iter->first << llendl;
-		}
-
-		channelp->setChannelInfo(
-			content["voice_credentials"]["channel_uri"].asString(),
-			content["voice_credentials"]["channel_credentials"].asString());
-	}
-}
-
-//
-// LLVoiceChannel
-//
-LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) : 
-	mSessionID(session_id), 
-	mState(STATE_NO_CHANNEL_INFO), 
-	mSessionName(session_name),
-	mIgnoreNextSessionLeave(FALSE)
-{
-	mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
-
-	if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
-	{
-		// a voice channel already exists for this session id, so this instance will be orphaned
-		// the end result should simply be the failure to make voice calls
-		llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
-	}
-
-	LLVoiceClient::getInstance()->addObserver(this);
-}
-
-LLVoiceChannel::~LLVoiceChannel()
-{
-	// Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
-	if(gVoiceClient)
-	{
-		gVoiceClient->removeObserver(this);
-	}
-	
-	sVoiceChannelMap.erase(mSessionID);
-	sVoiceChannelURIMap.erase(mURI);
-}
-
-void LLVoiceChannel::setChannelInfo(
-	const std::string& uri,
-	const std::string& credentials)
-{
-	setURI(uri);
-
-	mCredentials = credentials;
-
-	if (mState == STATE_NO_CHANNEL_INFO)
-	{
-		if (mURI.empty())
-		{
-			LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
-			llwarns << "Received empty URI for channel " << mSessionName << llendl;
-			deactivate();
-		}
-		else if (mCredentials.empty())
-		{
-			LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
-			llwarns << "Received empty credentials for channel " << mSessionName << llendl;
-			deactivate();
-		}
-		else
-		{
-			setState(STATE_READY);
-
-			// if we are supposed to be active, reconnect
-			// this will happen on initial connect, as we request credentials on first use
-			if (sCurrentVoiceChannel == this)
-			{
-				// just in case we got new channel info while active
-				// should move over to new channel
-				activate();
-			}
-		}
-	}
-}
-
-void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
-{
-	if (channelURI != mURI)
-	{
-		return;
-	}
-
-	if (type < BEGIN_ERROR_STATUS)
-	{
-		handleStatusChange(type);
-	}
-	else
-	{
-		handleError(type);
-	}
-}
-
-void LLVoiceChannel::handleStatusChange(EStatusType type)
-{
-	// status updates
-	switch(type)
-	{
-	case STATUS_LOGIN_RETRY:
-		//mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
-		LLNotifications::instance().add("VoiceLoginRetry");
-		break;
-	case STATUS_LOGGED_IN:
-		//if (!mLoginNotificationHandle.isDead())
-		//{
-		//	LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
-		//	if (notifyp)
-		//	{
-		//		notifyp->close();
-		//	}
-		//	mLoginNotificationHandle.markDead();
-		//}
-		break;
-	case STATUS_LEFT_CHANNEL:
-		if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
-		{
-			// if forceably removed from channel
-			// update the UI and revert to default channel
-			LLNotifications::instance().add("VoiceChannelDisconnected", mNotifyArgs);
-			deactivate();
-		}
-		mIgnoreNextSessionLeave = FALSE;
-		break;
-	case STATUS_JOINING:
-		if (callStarted())
-		{
-			setState(STATE_RINGING);
-		}
-		break;
-	case STATUS_JOINED:
-		if (callStarted())
-		{
-			setState(STATE_CONNECTED);
-		}
-	default:
-		break;
-	}
-}
-
-// default behavior is to just deactivate channel
-// derived classes provide specific error messages
-void LLVoiceChannel::handleError(EStatusType type)
-{
-	deactivate();
-	setState(STATE_ERROR);
-}
-
-BOOL LLVoiceChannel::isActive()
-{ 
-	// only considered active when currently bound channel matches what our channel
-	return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI; 
-}
-
-BOOL LLVoiceChannel::callStarted()
-{
-	return mState >= STATE_CALL_STARTED;
-}
-
-void LLVoiceChannel::deactivate()
-{
-	if (mState >= STATE_RINGING)
-	{
-		// ignore session leave event
-		mIgnoreNextSessionLeave = TRUE;
-	}
-
-	if (callStarted())
-	{
-		setState(STATE_HUNG_UP);
-		// mute the microphone if required when returning to the proximal channel
-		if (gSavedSettings.getBOOL("AutoDisengageMic") && sCurrentVoiceChannel == this)
-		{
-			gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
-		}
-	}
-
-	if (sCurrentVoiceChannel == this)
-	{
-		// default channel is proximal channel
-		sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
-		sCurrentVoiceChannel->activate();
-	}
-}
-
-void LLVoiceChannel::activate()
-{
-	if (callStarted())
-	{
-		return;
-	}
-
-	// deactivate old channel and mark ourselves as the active one
-	if (sCurrentVoiceChannel != this)
-	{
-		// mark as current before deactivating the old channel to prevent
-		// activating the proximal channel between IM calls
-		LLVoiceChannel* old_channel = sCurrentVoiceChannel;
-		sCurrentVoiceChannel = this;
-		if (old_channel)
-		{
-			old_channel->deactivate();
-		}
-	}
-
-	if (mState == STATE_NO_CHANNEL_INFO)
-	{
-		// responsible for setting status to active
-		getChannelInfo();
-	}
-	else
-	{
-		setState(STATE_CALL_STARTED);
-	}
-}
-
-void LLVoiceChannel::getChannelInfo()
-{
-	// pretend we have everything we need
-	if (sCurrentVoiceChannel == this)
-	{
-		setState(STATE_CALL_STARTED);
-	}
-}
-
-//static 
-LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
-{
-	voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
-	if (found_it == sVoiceChannelMap.end())
-	{
-		return NULL;
-	}
-	else
-	{
-		return found_it->second;
-	}
-}
-
-//static 
-LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
-{
-	voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
-	if (found_it == sVoiceChannelURIMap.end())
-	{
-		return NULL;
-	}
-	else
-	{
-		return found_it->second;
-	}
-}
-
-void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
-{
-	sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
-	mSessionID = new_session_id;
-	sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
-}
-
-void LLVoiceChannel::setURI(std::string uri)
-{
-	sVoiceChannelURIMap.erase(mURI);
-	mURI = uri;
-	sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
-}
-
-void LLVoiceChannel::setState(EState state)
-{
-	switch(state)
-	{
-	case STATE_RINGING:
-		gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
-		break;
-	case STATE_CONNECTED:
-		gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
-		break;
-	case STATE_HUNG_UP:
-		gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
-		break;
-	default:
-		break;
-	}
-
-	mState = state;
-}
-
-void LLVoiceChannel::toggleCallWindowIfNeeded(EState state)
-{
-	if (state == STATE_CONNECTED)
-	{
-		LLFloaterReg::showInstance("voice_call", mSessionID);
-	}
-	// By checking that current state is CONNECTED we make sure that the call window
-	// has been shown, hence there's something to hide. This helps when user presses
-	// the "End call" button right after initiating the call.
-	// *TODO: move this check to LLFloaterCall?
-	else if (state == STATE_HUNG_UP && mState == STATE_CONNECTED)
-	{
-		LLFloaterReg::hideInstance("voice_call", mSessionID);
-	}
-}
-
-//static
-void LLVoiceChannel::initClass()
-{
-	sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
-}
-
-
-//static 
-void LLVoiceChannel::suspend()
-{
-	if (!sSuspended)
-	{
-		sSuspendedVoiceChannel = sCurrentVoiceChannel;
-		sSuspended = TRUE;
-	}
-}
-
-//static 
-void LLVoiceChannel::resume()
-{
-	if (sSuspended)
-	{
-		if (gVoiceClient->voiceEnabled())
-		{
-			if (sSuspendedVoiceChannel)
-			{
-				sSuspendedVoiceChannel->activate();
-			}
-			else
-			{
-				LLVoiceChannelProximal::getInstance()->activate();
-			}
-		}
-		sSuspended = FALSE;
-	}
-}
-
-
-//
-// LLVoiceChannelGroup
-//
-
-LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) : 
-	LLVoiceChannel(session_id, session_name)
-{
-	mRetries = DEFAULT_RETRIES_COUNT;
-	mIsRetrying = FALSE;
-}
-
-void LLVoiceChannelGroup::deactivate()
-{
-	if (callStarted())
-	{
-		LLVoiceClient::getInstance()->leaveNonSpatialChannel();
-	}
-	LLVoiceChannel::deactivate();
-}
-
-void LLVoiceChannelGroup::activate()
-{
-	if (callStarted()) return;
-
-	LLVoiceChannel::activate();
-
-	if (callStarted())
-	{
-		// we have the channel info, just need to use it now
-		LLVoiceClient::getInstance()->setNonSpatialChannel(
-			mURI,
-			mCredentials);
-
-#if 0 // *TODO
-		if (!gAgent.isInGroup(mSessionID)) // ad-hoc channel
-		{
-			// Add the party to the list of people with which we've recently interacted.
-			for (/*people in the chat*/)
-				LLRecentPeople::instance().add(buddy_id);
-		}
-#endif
-	}
-}
-
-void LLVoiceChannelGroup::getChannelInfo()
-{
-	LLViewerRegion* region = gAgent.getRegion();
-	if (region)
-	{
-		std::string url = region->getCapability("ChatSessionRequest");
-		LLSD data;
-		data["method"] = "call";
-		data["session-id"] = mSessionID;
-		LLHTTPClient::post(url,
-						   data,
-						   new LLVoiceCallCapResponder(mSessionID));
-	}
-}
-
-void LLVoiceChannelGroup::setChannelInfo(
-	const std::string& uri,
-	const std::string& credentials)
-{
-	setURI(uri);
-
-	mCredentials = credentials;
-
-	if (mState == STATE_NO_CHANNEL_INFO)
-	{
-		if(!mURI.empty() && !mCredentials.empty())
-		{
-			setState(STATE_READY);
-
-			// if we are supposed to be active, reconnect
-			// this will happen on initial connect, as we request credentials on first use
-			if (sCurrentVoiceChannel == this)
-			{
-				// just in case we got new channel info while active
-				// should move over to new channel
-				activate();
-			}
-		}
-		else
-		{
-			//*TODO: notify user
-			llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
-			deactivate();
-		}
-	}
-	else if ( mIsRetrying )
-	{
-		// we have the channel info, just need to use it now
-		LLVoiceClient::getInstance()->setNonSpatialChannel(
-			mURI,
-			mCredentials);
-	}
-}
-
-void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
-{
-	// status updates
-	switch(type)
-	{
-	case STATUS_JOINED:
-		mRetries = 3;
-		mIsRetrying = FALSE;
-	default:
-		break;
-	}
-
-	LLVoiceChannel::handleStatusChange(type);
-}
-
-void LLVoiceChannelGroup::handleError(EStatusType status)
-{
-	std::string notify;
-	switch(status)
-	{
-	case ERROR_CHANNEL_LOCKED:
-	case ERROR_CHANNEL_FULL:
-		notify = "VoiceChannelFull";
-		break;
-	case ERROR_NOT_AVAILABLE:
-		//clear URI and credentials
-		//set the state to be no info
-		//and activate
-		if ( mRetries > 0 )
-		{
-			mRetries--;
-			mIsRetrying = TRUE;
-			mIgnoreNextSessionLeave = TRUE;
-
-			getChannelInfo();
-			return;
-		}
-		else
-		{
-			notify = "VoiceChannelJoinFailed";
-			mRetries = DEFAULT_RETRIES_COUNT;
-			mIsRetrying = FALSE;
-		}
-
-		break;
-
-	case ERROR_UNKNOWN:
-	default:
-		break;
-	}
-
-	// notification
-	if (!notify.empty())
-	{
-		LLNotificationPtr notification = LLNotifications::instance().add(notify, mNotifyArgs);
-		// echo to im window
-		gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
-	}
-
-	LLVoiceChannel::handleError(status);
-}
-
-void LLVoiceChannelGroup::setState(EState state)
-{
-	// HACK: Open/close the call window if needed.
-	toggleCallWindowIfNeeded(state);
-
-	switch(state)
-	{
-	case STATE_RINGING:
-		if ( !mIsRetrying )
-		{
-			gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
-		}
-
-		mState = state;
-		break;
-	default:
-		LLVoiceChannel::setState(state);
-	}
-}
-
-//
-// LLVoiceChannelProximal
-//
-LLVoiceChannelProximal::LLVoiceChannelProximal() : 
-	LLVoiceChannel(LLUUID::null, LLStringUtil::null)
-{
-	activate();
-}
-
-BOOL LLVoiceChannelProximal::isActive()
-{
-	return callStarted() && LLVoiceClient::getInstance()->inProximalChannel(); 
-}
-
-void LLVoiceChannelProximal::activate()
-{
-	if (callStarted()) return;
-
-	LLVoiceChannel::activate();
-
-	if (callStarted())
-	{
-		// this implicitly puts you back in the spatial channel
-		LLVoiceClient::getInstance()->leaveNonSpatialChannel();
-	}
-}
-
-void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
-{
-	if (!proximal)
-	{
-		return;
-	}
-
-	if (type < BEGIN_ERROR_STATUS)
-	{
-		handleStatusChange(type);
-	}
-	else
-	{
-		handleError(type);
-	}
-}
-
-void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
-{
-	// status updates
-	switch(status)
-	{
-	case STATUS_LEFT_CHANNEL:
-		// do not notify user when leaving proximal channel
-		return;
-	case STATUS_VOICE_DISABLED:
-		 gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
-		return;
-	default:
-		break;
-	}
-	LLVoiceChannel::handleStatusChange(status);
-}
-
-
-void LLVoiceChannelProximal::handleError(EStatusType status)
-{
-	std::string notify;
-	switch(status)
-	{
-	  case ERROR_CHANNEL_LOCKED:
-	  case ERROR_CHANNEL_FULL:
-		notify = "ProximalVoiceChannelFull";
-		break;
-	  default:
-		 break;
-	}
-
-	// notification
-	if (!notify.empty())
-	{
-		LLNotifications::instance().add(notify, mNotifyArgs);
-	}
-
-	LLVoiceChannel::handleError(status);
-}
-
-void LLVoiceChannelProximal::deactivate()
-{
-	if (callStarted())
-	{
-		setState(STATE_HUNG_UP);
-	}
-}
-
-
-//
-// LLVoiceChannelP2P
-//
-LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) : 
-		LLVoiceChannelGroup(session_id, session_name), 
-		mOtherUserID(other_user_id),
-		mReceivedCall(FALSE)
-{
-	// make sure URI reflects encoded version of other user's agent id
-	setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
-}
-
-void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
-{
-	// status updates
-	switch(type)
-	{
-	case STATUS_LEFT_CHANNEL:
-		if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
-		{
-			if (mState == STATE_RINGING)
-			{
-				// other user declined call
-				LLNotifications::instance().add("P2PCallDeclined", mNotifyArgs);
-			}
-			else
-			{
-				// other user hung up
-				LLNotifications::instance().add("VoiceChannelDisconnectedP2P", mNotifyArgs);
-			}
-			deactivate();
-		}
-		mIgnoreNextSessionLeave = FALSE;
-		return;
-	default:
-		break;
-	}
-
-	LLVoiceChannel::handleStatusChange(type);
-}
-
-void LLVoiceChannelP2P::handleError(EStatusType type)
-{
-	switch(type)
-	{
-	case ERROR_NOT_AVAILABLE:
-		LLNotifications::instance().add("P2PCallNoAnswer", mNotifyArgs);
-		break;
-	default:
-		break;
-	}
-
-	LLVoiceChannel::handleError(type);
-}
-
-void LLVoiceChannelP2P::activate()
-{
-	if (callStarted()) return;
-
-	LLVoiceChannel::activate();
-
-	if (callStarted())
-	{
-		// no session handle yet, we're starting the call
-		if (mSessionHandle.empty())
-		{
-			mReceivedCall = FALSE;
-			LLVoiceClient::getInstance()->callUser(mOtherUserID);
-		}
-		// otherwise answering the call
-		else
-		{
-			LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
-			
-			// using the session handle invalidates it.  Clear it out here so we can't reuse it by accident.
-			mSessionHandle.clear();
-		}
-
-		// Add the party to the list of people with which we've recently interacted.
-		LLRecentPeople::instance().add(mOtherUserID);
-	}
-}
-
-void LLVoiceChannelP2P::getChannelInfo()
-{
-	// pretend we have everything we need, since P2P doesn't use channel info
-	if (sCurrentVoiceChannel == this)
-	{
-		setState(STATE_CALL_STARTED);
-	}
-}
-
-// receiving session from other user who initiated call
-void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
-{ 
-	BOOL needs_activate = FALSE;
-	if (callStarted())
-	{
-		// defer to lower agent id when already active
-		if (mOtherUserID < gAgent.getID())
-		{
-			// pretend we haven't started the call yet, so we can connect to this session instead
-			deactivate();
-			needs_activate = TRUE;
-		}
-		else
-		{
-			// we are active and have priority, invite the other user again
-			// under the assumption they will join this new session
-			mSessionHandle.clear();
-			LLVoiceClient::getInstance()->callUser(mOtherUserID);
-			return;
-		}
-	}
-
-	mSessionHandle = handle;
-
-	// The URI of a p2p session should always be the other end's SIP URI.
-	if(!inURI.empty())
-	{
-		setURI(inURI);
-	}
-	else
-	{
-		setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
-	}
-	
-	mReceivedCall = TRUE;
-
-	if (needs_activate)
-	{
-		activate();
-	}
-}
-
-void LLVoiceChannelP2P::setState(EState state)
-{
-	// HACK: Open/close the call window if needed.
-	toggleCallWindowIfNeeded(state);
-
-	// you only "answer" voice invites in p2p mode
-	// so provide a special purpose message here
-	if (mReceivedCall && state == STATE_RINGING)
-	{
-		gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
-		mState = state;
-		return;
-	}
-	LLVoiceChannel::setState(state);
-}
-
 
 //
 // LLFloaterIMPanel
@@ -1005,13 +181,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
 	// enable line history support for instant message bar
 	mInputEditor->setEnableLineHistory(TRUE);
 
-	if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
-	{
-		LLLogChat::loadHistory(mSessionLabel,
-				       &chatFromLogFile,
-				       (void *)this);
-	}
-
 	//*TODO we probably need the same "awaiting message" thing in LLIMFloater
 	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionUUID);
 	if (!im_session)
@@ -1801,110 +970,8 @@ void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info)
 	}
 }
 
-//static
-void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
-{
-	LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata;
-	std::string message = line;
-	S32 im_log_option =  gSavedPerAccountSettings.getS32("IMLogOptions");
-	switch (type)
-	{
-	case LLLogChat::LOG_EMPTY:
-		// add warning log enabled message
-		if (im_log_option!=LOG_CHAT)
-		{
-			message = LLTrans::getString("IM_logging_string");
-		}
-		break;
-	case LLLogChat::LOG_END:
-		// add log end message
-		if (im_log_option!=LOG_CHAT)
-		{
-			message = LLTrans::getString("IM_logging_string");
-		}
-		break;
-	case LLLogChat::LOG_LINE:
-		// just add normal lines from file
-		break;
-	default:
-		// nothing
-		break;
-	}
-
-	//self->addHistoryLine(line, LLColor4::grey, FALSE);
-	self->mHistoryEditor->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
-	self->mHistoryEditor->blockUndo();
-}
-
-void LLFloaterIMPanel::showSessionStartError(
-	const std::string& error_string)
-{
-	LLSD args;
-	args["REASON"] = LLTrans::getString(error_string);
-	args["RECIPIENT"] = getTitle();
-
-	LLSD payload;
-	payload["session_id"] = mSessionUUID;
-
-	LLNotifications::instance().add(
-		"ChatterBoxSessionStartError",
-		args,
-		payload,
-		onConfirmForceCloseError);
-}
-
-void LLFloaterIMPanel::showSessionEventError(
-	const std::string& event_string,
-	const std::string& error_string)
-{
-	LLSD args;
-	args["REASON"] =
-		LLTrans::getString(error_string);
-	args["EVENT"] =
-		LLTrans::getString(event_string);
-	args["RECIPIENT"] = getTitle();
-
-	LLNotifications::instance().add(
-		"ChatterBoxSessionEventError",
-		args);
-}
-
-void LLFloaterIMPanel::showSessionForceClose(
-	const std::string& reason_string)
-{
-	LLSD args;
-
-	args["NAME"] = getTitle();
-	args["REASON"] = LLTrans::getString(reason_string);
-
-	LLSD payload;
-	payload["session_id"] = mSessionUUID;
-
-	LLNotifications::instance().add(
-		"ForceCloseChatterBoxSession",
-		args,
-		payload,
-		LLFloaterIMPanel::onConfirmForceCloseError);
-
-}
-
 //static 
 void LLFloaterIMPanel::onKickSpeaker(void* user_data)
 {
 
 }
-
-bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const LLSD& response)
-{
-	//only 1 option really
-	LLUUID session_id = notification["payload"]["session_id"];
-
-	if ( gIMMgr )
-	{
-		LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(
-			session_id);
-
-		if ( floaterp ) floaterp->closeFloater(FALSE);
-	}
-	return false;
-}
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index 4e306c7fabfeb5a882921a7c3d78788677ceacc3..b8f99d45c9daa880b71af698c88ce943cb6a99d5 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -50,133 +50,6 @@ class LLIMSpeakerMgr;
 class LLPanelActiveSpeakers;
 class LLPanelChatControlPanel;
 
-class LLVoiceChannel : public LLVoiceClientStatusObserver
-{
-public:
-	typedef enum e_voice_channel_state
-	{
-		STATE_NO_CHANNEL_INFO,
-		STATE_ERROR,
-		STATE_HUNG_UP,
-		STATE_READY,
-		STATE_CALL_STARTED,
-		STATE_RINGING,
-		STATE_CONNECTED
-	} EState;
-
-	LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
-	virtual ~LLVoiceChannel();
-
-	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
-
-	virtual void handleStatusChange(EStatusType status);
-	virtual void handleError(EStatusType status);
-	virtual void deactivate();
-	virtual void activate();
-	virtual void setChannelInfo(
-		const std::string& uri,
-		const std::string& credentials);
-	virtual void getChannelInfo();
-	virtual BOOL isActive();
-	virtual BOOL callStarted();
-	const std::string& getSessionName() const { return mSessionName; }
-
-	const LLUUID getSessionID() { return mSessionID; }
-	EState getState() { return mState; }
-
-	void updateSessionID(const LLUUID& new_session_id);
-	const LLSD& getNotifyArgs() { return mNotifyArgs; }
-
-	static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
-	static LLVoiceChannel* getChannelByURI(std::string uri);
-	static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
-	static void initClass();
-	
-	static void suspend();
-	static void resume();
-
-protected:
-	virtual void setState(EState state);
-	void toggleCallWindowIfNeeded(EState state);
-	void setURI(std::string uri);
-
-	std::string	mURI;
-	std::string	mCredentials;
-	LLUUID		mSessionID;
-	EState		mState;
-	std::string	mSessionName;
-	LLSD mNotifyArgs;
-	BOOL		mIgnoreNextSessionLeave;
-	LLHandle<LLPanel> mLoginNotificationHandle;
-
-	typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
-	static voice_channel_map_t sVoiceChannelMap;
-
-	typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
-	static voice_channel_map_uri_t sVoiceChannelURIMap;
-
-	static LLVoiceChannel* sCurrentVoiceChannel;
-	static LLVoiceChannel* sSuspendedVoiceChannel;
-	static BOOL sSuspended;
-};
-
-class LLVoiceChannelGroup : public LLVoiceChannel
-{
-public:
-	LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
-
-	/*virtual*/ void handleStatusChange(EStatusType status);
-	/*virtual*/ void handleError(EStatusType status);
-	/*virtual*/ void activate();
-	/*virtual*/ void deactivate();
-	/*vritual*/ void setChannelInfo(
-		const std::string& uri,
-		const std::string& credentials);
-	/*virtual*/ void getChannelInfo();
-
-protected:
-	virtual void setState(EState state);
-
-private:
-	U32 mRetries;
-	BOOL mIsRetrying;
-};
-
-class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
-{
-public:
-	LLVoiceChannelProximal();
-
-	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
-	/*virtual*/ void handleStatusChange(EStatusType status);
-	/*virtual*/ void handleError(EStatusType status);
-	/*virtual*/ BOOL isActive();
-	/*virtual*/ void activate();
-	/*virtual*/ void deactivate();
-
-};
-
-class LLVoiceChannelP2P : public LLVoiceChannelGroup
-{
-public:
-	LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
-
-	/*virtual*/ void handleStatusChange(EStatusType status);
-	/*virtual*/ void handleError(EStatusType status);
-    /*virtual*/ void activate();
-	/*virtual*/ void getChannelInfo();
-
-	void setSessionHandle(const std::string& handle, const std::string &inURI);
-
-protected:
-	virtual void setState(EState state);
-
-private:
-	std::string	mSessionHandle;
-	LLUUID		mOtherUserID;
-	BOOL		mReceivedCall;
-};
-
 class LLFloaterIMPanel : public LLFloater
 {
 public:
@@ -254,16 +127,6 @@ class LLFloaterIMPanel : public LLFloater
 
 	// Handle other participant in the session typing.
 	void processIMTyping(const LLIMInfo* im_info, BOOL typing);
-	static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
-
-	//show error statuses to the user
-	void showSessionStartError(const std::string& error_string);
-	void showSessionEventError(
-		const std::string& event_string,
-		const std::string& error_string);
-	void showSessionForceClose(const std::string& reason);
-
-	static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
 
 private:
 	// Called by UI methods.
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index ab6f50aaf30645f831913eab0a1c76cc71df0fdf..66a3e3e85c03df90ee9f53e379ffd983eb6e8beb 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -40,7 +40,7 @@
 #include "llerror.h"
 #include "llbutton.h"
 #include "llhttpclient.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
 #include "llstring.h"
 #include "lluictrlfactory.h"
 
@@ -70,6 +70,7 @@
 #include "llviewerwindow.h"
 #include "llnotify.h"
 #include "llviewerregion.h"
+#include "llvoicechannel.h"
 #include "lltrans.h"
 #include "llrecentpeople.h"
 
@@ -88,9 +89,6 @@ LLIMMgr* gIMMgr = NULL;
 
 const static std::string IM_SEPARATOR(": ");
 
-std::map<LLUUID, LLIMModel::LLIMSession*> LLIMModel::sSessionsMap;
-
-
 
 void toast_callback(const LLSD& msg){
 	// do not show toast in busy mode or it goes from agent
@@ -104,7 +102,13 @@ void toast_callback(const LLSD& msg){
 	{
 		return;
 	}
-	
+
+	// Skip toasting for system messages
+	if (msg["from_id"].asUUID() == LLUUID::null)
+	{
+		return;
+	}
+
 	LLSD args;
 	args["MESSAGE"] = msg["message"];
 	args["TIME"] = msg["time"];
@@ -134,7 +138,6 @@ LLIMModel::LLIMModel()
 	addNewMsgCallback(toast_callback);
 }
 
-
 LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
 :	mSessionID(session_id),
 	mName(name),
@@ -144,7 +147,10 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
 	mInitialTargetIDs(ids),
 	mVoiceChannel(NULL),
 	mSpeakers(NULL),
-	mSessionInitialized(false)
+	mSessionInitialized(false),
+	mCallBackEnabled(true),
+	mTextIMPossible(true),
+	mOtherParticipantIsAvatar(true)
 {
 	if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type)
 	{
@@ -168,6 +174,16 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
 		//so we're already initialized
 		mSessionInitialized = true;
 	}
+
+	if (IM_NOTHING_SPECIAL == type)
+	{
+		mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionID);
+		mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID);
+		mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID);
+	}
+
+	if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+		LLLogChat::loadHistory(mName, &chatFromLogFile, (void *)this);
 }
 
 LLIMModel::LLIMSession::~LLIMSession()
@@ -209,14 +225,47 @@ void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_
 	}
 }
 
+void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time)
+{
+	LLSD message;
+	message["from"] = from;
+	message["from_id"] = from_id;
+	message["message"] = utf8_text;
+	message["time"] = time; 
+	message["index"] = (LLSD::Integer)mMsgs.size(); 
+
+	mMsgs.push_front(message); 
+
+	if (mSpeakers && from_id.notNull())
+	{
+		mSpeakers->speakerChatted(from_id);
+		mSpeakers->setSpeakerTyping(from_id, FALSE);
+	}
+}
+
+void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata)
+{
+	if (!userdata) return;
+
+	LLIMSession* self = (LLIMSession*) userdata;
+
+	if (type == LLLogChat::LOG_LINE)
+	{
+		self->addMessage("", LLSD(), msg["message"].asString(), "");
+	}
+	else if (type == LLLogChat::LOG_LLSD)
+	{
+		self->addMessage(msg["from"].asString(), msg["from_id"].asUUID(), msg["message"].asString(), msg["time"].asString());
+	}
+}
+
 LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
 {
-	return get_if_there(LLIMModel::instance().sSessionsMap, session_id,
+	return get_if_there(mId2SessionMap, session_id,
 		(LLIMModel::LLIMSession*) NULL);
 }
 
-//*TODO change name to represent session initialization aspect (IB)
-void LLIMModel::updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id)
+void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)
 {
 	LLIMSession* session = findIMSession(old_session_id);
 	if (session)
@@ -225,8 +274,8 @@ void LLIMModel::updateSessionID(const LLUUID& old_session_id, const LLUUID& new_
 
 		if (old_session_id != new_session_id)
 		{
-			sSessionsMap.erase(old_session_id);
-			sSessionsMap[new_session_id] = session;
+			mId2SessionMap.erase(old_session_id);
+			mId2SessionMap[new_session_id] = session;
 
 			gIMMgr->notifyObserverSessionIDUpdated(old_session_id, new_session_id);
 		}
@@ -272,16 +321,17 @@ void LLIMModel::testMessages()
 }
 
 
-bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id, const std::vector<LLUUID>& ids)
+bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, 
+						   const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
 {
-	if (is_in_map(sSessionsMap, session_id))
+	if (findIMSession(session_id))
 	{
 		llwarns << "IM Session " << session_id << " already exists" << llendl;
 		return false;
 	}
 
 	LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids);
-	sSessionsMap[session_id] = session;
+	mId2SessionMap[session_id] = session;
 
 	LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, name, other_participant_id);
 
@@ -289,24 +339,21 @@ bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage
 
 }
 
-bool LLIMModel::clearSession(LLUUID session_id)
+bool LLIMModel::clearSession(const LLUUID& session_id)
 {
-	if (sSessionsMap.find(session_id) == sSessionsMap.end()) return false;
-	delete (sSessionsMap[session_id]);
-	sSessionsMap.erase(session_id);
+	if (mId2SessionMap.find(session_id) == mId2SessionMap.end()) return false;
+	delete (mId2SessionMap[session_id]);
+	mId2SessionMap.erase(session_id);
 	return true;
 }
 
-//*TODO remake it, instead of returing the list pass it as as parameter (IB)
-std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
+void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
 {
-	std::list<LLSD> return_list;
-
 	LLIMSession* session = findIMSession(session_id);
 	if (!session) 
 	{
 		llwarns << "session " << session_id << "does not exist " << llendl;
-		return return_list;
+		return;
 	}
 
 	int i = session->mMsgs.size() - start_index;
@@ -317,7 +364,7 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
 	{
 		LLSD msg;
 		msg = *iter;
-		return_list.push_back(*iter);
+		messages.push_back(*iter);
 		i--;
 	}
 
@@ -327,14 +374,9 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
 	arg["session_id"] = session_id;
 	arg["num_unread"] = 0;
 	mNoUnreadMsgsSignal(arg);
-
-    // TODO: in the future is there a more efficient way to return these
-	//of course there is - return as parameter (IB)
-	return return_list;
-
 }
 
-bool LLIMModel::addToHistory(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text) { 
+bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {
 	
 	LLIMSession* session = findIMSession(session_id);
 
@@ -344,47 +386,49 @@ bool LLIMModel::addToHistory(LLUUID session_id, std::string from, LLUUID from_id
 		return false;
 	}
 
-	LLSD message;
-	message["from"] = from;
-	message["from_id"] = from_id;
-	message["message"] = utf8_text;
-	message["time"] = LLLogChat::timestamp(false);  //might want to add date separately
-	message["index"] = (LLSD::Integer)session->mMsgs.size(); 
-
-	session->mMsgs.push_front(message); 
+	session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false)); //might want to add date separately
 
 	return true;
-
 }
 
-//*TODO rewrite chat history persistence using LLSD serialization (IB)
-bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const std::string& utf8_text)
+bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
 {
 	S32 im_log_option =  gSavedPerAccountSettings.getS32("IMLogOptions");
 	if (im_log_option != LOG_CHAT)
 	{
-		std::string histstr;
-		if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
-			histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + from + IM_SEPARATOR + utf8_text;
-		else
-			histstr = from + IM_SEPARATOR + utf8_text;
-
 		if(im_log_option == LOG_BOTH_TOGETHER)
 		{
-			LLLogChat::saveHistory(std::string("chat"), histstr);
+			LLLogChat::saveHistory(std::string("chat"), from, from_id, utf8_text);
 			return true;
 		}
 		else
 		{
-			LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), histstr);
+			LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), from, from_id, utf8_text);
 			return true;
 		}
 	}
 	return false;
 }
 
-//*TODO add const qualifier and pass by references (IB)
-bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text, bool log2file /* = true */) { 
+bool LLIMModel::proccessOnlineOfflineNotification(
+	const LLUUID& session_id, 
+	const std::string& utf8_text)
+{
+	// Add message to old one floater
+	LLFloaterIMPanel *floater = gIMMgr->findFloaterBySession(session_id);
+	if ( floater )
+	{
+		if ( !utf8_text.empty() )
+		{
+			floater->addHistoryLine(utf8_text, LLUIColorTable::instance().getColor("SystemChatColor"));
+		}
+	}
+	// Add system message to history
+	return addMessage(session_id, SYSTEM_FROM, LLUUID::null, utf8_text);
+}
+
+bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, 
+						   const std::string& utf8_text, bool log2file /* = true */) { 
 	LLIMSession* session = findIMSession(session_id);
 
 	if (!session) 
@@ -394,7 +438,7 @@ bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id,
 	}
 
 	addToHistory(session_id, from, from_id, utf8_text);
-	if (log2file) logToFile(session_id, from, utf8_text);
+	if (log2file) logToFile(session_id, from, from_id, utf8_text);
 
 	session->mNumUnread++;
 
@@ -506,7 +550,7 @@ void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id,
 	gAgent.sendReliableMessage();
 }
 
-void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id) 
+void LLIMModel::sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id)
 {
 	if(session_id.notNull())
 	{
@@ -527,8 +571,7 @@ void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id)
 	}
 }
 
-
-//*TODO update list of messages in a LLIMSession (IB)
+//*TODO this method is better be moved to the LLIMMgr
 void LLIMModel::sendMessage(const std::string& utf8_text,
 					 const LLUUID& im_session_id,
 					 const LLUUID& other_participant_id,
@@ -890,20 +933,11 @@ class LLViewerChatterBoxInvitationAcceptResponder :
 		{
 			gIMMgr->clearPendingAgentListUpdates(mSessionID);
 			gIMMgr->clearPendingInvitation(mSessionID);
-
-			LLFloaterIMPanel* floaterp =
-				gIMMgr->findFloaterBySession(mSessionID);
-
-			if ( floaterp )
+			if ( 404 == statusNum )
 			{
-				if ( 404 == statusNum )
-				{
-					std::string error_string;
-					error_string = "does not exist";
-
-					floaterp->showSessionStartError(
-						error_string);
-				}
+				std::string error_string;
+				error_string = "does not exist";
+				gIMMgr->showSessionStartError(error_string, mSessionID);
 			}
 		}
 	}
@@ -955,6 +989,106 @@ LLUUID LLIMMgr::computeSessionID(
 	return session_id;
 }
 
+inline LLFloater* getFloaterBySessionID(const LLUUID session_id)
+{
+	LLFloater* floater = NULL;
+	if ( gIMMgr )
+	{
+		floater = dynamic_cast < LLFloater* >
+			( gIMMgr->findFloaterBySession(session_id) );
+	}
+	if ( !floater )
+	{
+		floater = dynamic_cast < LLFloater* >
+			( LLIMFloater::findInstance(session_id) );
+	}
+	return floater;
+}
+
+void
+LLIMMgr::showSessionStartError(
+	const std::string& error_string,
+	const LLUUID session_id)
+{
+	const LLFloater* floater = getFloaterBySessionID (session_id);
+	if (!floater) return;
+
+	LLSD args;
+	args["REASON"] = LLTrans::getString(error_string);
+	args["RECIPIENT"] = floater->getTitle();
+
+	LLSD payload;
+	payload["session_id"] = session_id;
+
+	LLNotifications::instance().add(
+		"ChatterBoxSessionStartError",
+		args,
+		payload,
+		LLIMMgr::onConfirmForceCloseError);
+}
+
+void
+LLIMMgr::showSessionEventError(
+	const std::string& event_string,
+	const std::string& error_string,
+	const LLUUID session_id)
+{
+	const LLFloater* floater = getFloaterBySessionID (session_id);
+	if (!floater) return;
+
+	LLSD args;
+	args["REASON"] =
+		LLTrans::getString(error_string);
+	args["EVENT"] =
+		LLTrans::getString(event_string);
+	args["RECIPIENT"] = floater->getTitle();
+
+	LLNotifications::instance().add(
+		"ChatterBoxSessionEventError",
+		args);
+}
+
+void
+LLIMMgr::showSessionForceClose(
+	const std::string& reason_string,
+	const LLUUID session_id)
+{
+	const LLFloater* floater = getFloaterBySessionID (session_id);
+	if (!floater) return;
+
+	LLSD args;
+
+	args["NAME"] = floater->getTitle();
+	args["REASON"] = LLTrans::getString(reason_string);
+
+	LLSD payload;
+	payload["session_id"] = session_id;
+
+	LLNotifications::instance().add(
+		"ForceCloseChatterBoxSession",
+		args,
+		payload,
+		LLIMMgr::onConfirmForceCloseError);
+}
+
+//static
+bool
+LLIMMgr::onConfirmForceCloseError(
+	const LLSD& notification,
+	const LLSD& response)
+{
+	//only 1 option really
+	LLUUID session_id = notification["payload"]["session_id"];
+
+	LLFloater* floater = getFloaterBySessionID (session_id);
+	if ( floater )
+	{
+		floater->closeFloater(FALSE);
+	}
+	return false;
+}
+
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLIncomingCallDialog
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1114,29 +1248,6 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
 	}
 }
 
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLIMViewFriendObserver
-//
-// Bridge to suport knowing when the inventory has changed.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLIMViewFriendObserver : public LLFriendObserver
-{
-public:
-	LLIMViewFriendObserver(LLIMMgr* tv) : mTV(tv) {}
-	virtual ~LLIMViewFriendObserver() {}
-	virtual void changed(U32 mask)
-	{
-		if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
-		{
-			mTV->refresh();
-		}
-	}
-protected:
-	LLIMMgr* mTV;
-};
-
-
 bool inviteUserResponse(const LLSD& notification, const LLSD& response)
 {
 	const LLSD& payload = notification["payload"];
@@ -1237,7 +1348,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
 //
 
 LLIMMgr::LLIMMgr() :
-	mFriendObserver(NULL),
 	mIMReceived(FALSE)
 {
 	static bool registered_dialog = false;
@@ -1246,21 +1356,11 @@ LLIMMgr::LLIMMgr() :
 		LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
 		registered_dialog = true;
 	}
-		
-	mFriendObserver = new LLIMViewFriendObserver(this);
-	LLAvatarTracker::instance().addObserver(mFriendObserver);
 
 	mPendingInvitations = LLSD::emptyMap();
 	mPendingAgentListUpdates = LLSD::emptyMap();
 }
 
-LLIMMgr::~LLIMMgr()
-{
-	LLAvatarTracker::instance().removeObserver(mFriendObserver);
-	delete mFriendObserver;
-	// Children all cleaned up by default view destructor.
-}
-
 // Add a message to a session. 
 void LLIMMgr::addMessage(
 	const LLUUID& session_id,
@@ -1299,9 +1399,10 @@ void LLIMMgr::addMessage(
 		fixed_session_name = session_name;
 	}
 
-	if (!LLIMModel::getInstance()->findIMSession(new_session_id))
+	bool new_session = !hasSession(new_session_id);
+	if (new_session)
 	{
-		LLIMModel::getInstance()->newSession(session_id, fixed_session_name, dialog, other_participant_id);
+		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id);
 	}
 
 	floater = findFloaterBySession(new_session_id);
@@ -1318,15 +1419,16 @@ void LLIMMgr::addMessage(
 	// create IM window as necessary
 	if(!floater)
 	{
-
-		
 		floater = createFloater(
 			new_session_id,
 			other_participant_id,
 			fixed_session_name,
 			dialog,
 			FALSE);
+	}
 
+	if (new_session)
+	{
 		// When we get a new IM, and if you are a god, display a bit
 		// of information about the source. This is to help liaisons
 		// when answering questions.
@@ -1336,7 +1438,7 @@ void LLIMMgr::addMessage(
 			std::ostringstream bonus_info;
 			bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + ":" + " "
 				<< parent_estate_id
-			<< ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
+				<< ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
 				<< ((parent_estate_id == 5) ? "," + LLTrans::getString ("IMTeen") : "");
 
 			// once we have web-services (or something) which returns
@@ -1364,14 +1466,6 @@ void LLIMMgr::addMessage(
 	else
 	{
 		floater->addHistoryLine(msg, color, true, other_participant_id, from); // Insert linked name to front of message
-
-		//*TODO consider moving that speaker management stuff into model (IB)
-		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(new_session_id);
-		if (speaker_mgr)
-		{
-			speaker_mgr->speakerChatted(gAgentID);
-			speaker_mgr->setSpeakerTyping(gAgentID, FALSE);
-		}
 	}
 
 	LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
@@ -1437,12 +1531,9 @@ S32 LLIMMgr::getNumberOfUnreadIM()
 	std::map<LLUUID, LLIMModel::LLIMSession*>::iterator it;
 	
 	S32 num = 0;
-	for(it = LLIMModel::sSessionsMap.begin(); it != LLIMModel::sSessionsMap.end(); ++it)
+	for(it = LLIMModel::getInstance()->mId2SessionMap.begin(); it != LLIMModel::getInstance()->mId2SessionMap.end(); ++it)
 	{
-		if((*it).first != mBeingRemovedSessionID)
-		{
-			num += (*it).second->mNumUnread;
-		}
+		num += (*it).second->mNumUnread;
 	}
 
 	return num;
@@ -1458,15 +1549,6 @@ BOOL LLIMMgr::getIMReceived() const
 	return mIMReceived;
 }
 
-// This method returns TRUE if the local viewer has a session
-// currently open keyed to the uuid. 
-BOOL LLIMMgr::isIMSessionOpen(const LLUUID& uuid)
-{
-	LLFloaterIMPanel* floater = findFloaterBySession(uuid);
-	if(floater) return TRUE;
-	return FALSE;
-}
-
 LLUUID LLIMMgr::addP2PSession(const std::string& name,
 							const LLUUID& other_participant_id,
 							const std::string& voice_session_handle,
@@ -1515,7 +1597,9 @@ LLUUID LLIMMgr::addSession(
 
 	LLUUID session_id = computeSessionID(dialog,other_participant_id);
 
-	if (!LLIMModel::getInstance()->findIMSession(session_id))
+	bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);
+
+	if (new_session)
 	{
 		LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids);
 	}
@@ -1537,6 +1621,9 @@ LLUUID LLIMMgr::addSession(
 			ids);
 	}
 
+	//we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions
+	if (!new_session) return session_id;
+	
 	noteOfflineUsers(session_id, floater, ids);
 
 	// Only warn for regular IMs - not group IMs
@@ -1545,8 +1632,6 @@ LLUUID LLIMMgr::addSession(
 		noteMutedUsers(session_id, floater, ids);
 	}
 
-
-
 	return session_id;
 }
 
@@ -1560,41 +1645,25 @@ bool LLIMMgr::leaveSession(const LLUUID& session_id)
 	return true;
 }
 
-// This removes the panel referenced by the uuid, and then restores
-// internal consistency. The internal pointer is not deleted? Did you mean
-// a pointer to the corresponding LLIMSession? Session data is cleared now.
-// Put a copy of UUID to avoid problem when passed reference becames invalid
-// if it has been come from the object removed in observer.
-void LLIMMgr::removeSession(LLUUID session_id)
+// Removes data associated with a particular session specified by session_id
+void LLIMMgr::removeSession(const LLUUID& session_id)
 {
-	if (mBeingRemovedSessionID == session_id)
-	{
-		return;
-	}
+	llassert_always(hasSession(session_id));
 	
+	//*TODO remove this floater thing when Communicate Floater is being deleted (IB)
 	LLFloaterIMPanel* floater = findFloaterBySession(session_id);
 	if(floater)
 	{
 		mFloaters.erase(floater->getHandle());
 		LLFloaterChatterBox::getInstance()->removeFloater(floater);
-		//mTabContainer->removeTabPanel(floater);
-
-		clearPendingInvitation(session_id);
-		clearPendingAgentListUpdates(session_id);
 	}
 
-	// for some purposes storing ID of a sessios that is being removed
-	mBeingRemovedSessionID = session_id;
-	notifyObserverSessionRemoved(session_id);
+	clearPendingInvitation(session_id);
+	clearPendingAgentListUpdates(session_id);
 
-	//if we don't clear session data on removing the session
-	//we can't use LLBottomTray as observer of session creation/delettion and 
-	//creating chiclets only on session created even, we need to handle chiclets creation
-	//the same way as LLFloaterIMPanels were managed.
 	LLIMModel::getInstance()->clearSession(session_id);
 
-	// now this session is completely removed
-	mBeingRemovedSessionID.setNull();
+	notifyObserverSessionRemoved(session_id);
 }
 
 void LLIMMgr::inviteToSession(
@@ -1723,10 +1792,6 @@ void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::stri
 	}
 }
 
-void LLIMMgr::refresh()
-{
-}
-
 void LLIMMgr::disconnectAllSessions()
 {
 	LLFloaterIMPanel* floater = NULL;
@@ -1966,7 +2031,7 @@ void LLIMMgr::noteOfflineUsers(
 	{
 		const LLRelationship* info = NULL;
 		LLAvatarTracker& at = LLAvatarTracker::instance();
-		LLIMModel* im_model = LLIMModel::getInstance();
+		LLIMModel& im_model = LLIMModel::instance();
 		for(S32 i = 0; i < count; ++i)
 		{
 			info = at.getBuddyInfo(ids.get(i));
@@ -1977,13 +2042,7 @@ void LLIMMgr::noteOfflineUsers(
 				LLUIString offline = LLTrans::getString("offline_message");
 				offline.setArg("[FIRST]", first);
 				offline.setArg("[LAST]", last);
-
-				if (floater)
-				{
-					floater->addHistoryLine(offline, LLUIColorTable::instance().getColor("SystemChatColor"));
-				}
-
-				im_model->addMessage(session_id, SYSTEM_FROM, LLUUID::null, offline);
+				im_model.proccessOnlineOfflineNotification(session_id, offline);
 			}
 		}
 	}
@@ -2038,6 +2097,12 @@ void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)
 	{
 		floater->processIMTyping(im_info, typing);
 	}
+
+	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+	if ( im_floater )
+	{
+		im_floater->processIMTyping(im_info, typing);
+	}
 }
 
 class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
@@ -2069,7 +2134,7 @@ class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
 		{
 			session_id = body["session_id"].asUUID();
 
-			LLIMModel::getInstance()->updateSessionID(temp_session_id, session_id);
+			LLIMModel::getInstance()->processSessionInitializedReply(temp_session_id, session_id);
 
 			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
 			if (speaker_mgr)
@@ -2087,19 +2152,21 @@ class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
 				}
 			}
 
+			LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+			if ( im_floater )
+			{
+				if ( body.has("session_info") )
+				{
+					im_floater->processSessionUpdate(body["session_info"]);
+				}
+			}
+
 			gIMMgr->clearPendingAgentListUpdates(session_id);
 		}
 		else
 		{
-			//throw an error dialog and close the temp session's
-			//floater
-			LLFloaterIMPanel* floater = 
-				gIMMgr->findFloaterBySession(temp_session_id);
-
-			if ( floater )
-			{
-				floater->showSessionStartError(body["error"].asString());
-			}
+			//throw an error dialog and close the temp session's floater
+			gIMMgr->showSessionStartError(body["error"].asString(), temp_session_id);
 		}
 
 		gIMMgr->clearPendingAgentListUpdates(session_id);
@@ -2132,15 +2199,10 @@ class LLViewerChatterBoxSessionEventReply : public LLHTTPNode
 		if ( !success )
 		{
 			//throw an error dialog
-			LLFloaterIMPanel* floater = 
-				gIMMgr->findFloaterBySession(session_id);
-
-			if (floater)
-			{
-				floater->showSessionEventError(
-					body["event"].asString(),
-					body["error"].asString());
-			}
+			gIMMgr->showSessionEventError(
+				body["event"].asString(),
+				body["error"].asString(),
+				session_id);
 		}
 	}
 };
@@ -2158,13 +2220,7 @@ class LLViewerForceCloseChatterBoxSession: public LLHTTPNode
 		session_id = input["body"]["session_id"].asUUID();
 		reason = input["body"]["reason"].asString();
 
-		LLFloaterIMPanel* floater =
-			gIMMgr ->findFloaterBySession(session_id);
-
-		if ( floater )
-		{
-			floater->showSessionForceClose(reason);
-		}
+		gIMMgr->showSessionForceClose(reason, session_id);
 	}
 };
 
@@ -2202,11 +2258,17 @@ class LLViewerChatterBoxSessionUpdate : public LLHTTPNode
 		const LLSD& context,
 		const LLSD& input) const
 	{
-		LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
+		LLUUID session_id = input["body"]["session_id"].asUUID();
+		LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
 		if (floaterp)
 		{
 			floaterp->processSessionUpdate(input["body"]["info"]);
 		}
+		LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+		if ( im_floater )
+		{
+			im_floater->processSessionUpdate(input["body"]["info"]);
+		}
 	}
 };
 
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 68beb29034a15e7aca48bcf02a9ca28013b998d5..f986d9dcdbe07cf31c77b5f75a470dcb8665a9ac 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -34,12 +34,13 @@
 #define LL_LLIMVIEW_H
 
 #include "lldarray.h"
-#include "llfloateractivespeakers.h" //for LLIMSpeakerMgr
+#include "llspeakers.h" //for LLIMSpeakerMgr
 #include "llimpanel.h" //for voice channels
 #include "llmodaldialog.h"
 #include "llinstantmessage.h"
 #include "lluuid.h"
 #include "llmultifloater.h"
+#include "lllogchat.h"
 
 class LLFloaterChatterBox;
 class LLUUID;
@@ -57,6 +58,8 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 		virtual ~LLIMSession();
 
 		void sessionInitReplyReceived(const LLUUID& new_session_id);
+		void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time);
+		static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
 
 		LLUUID mSessionID;
 		std::string mName;
@@ -70,6 +73,13 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 		LLIMSpeakerMgr* mSpeakers;
 
 		bool mSessionInitialized;
+
+		//true if calling back the session URI after the session has closed is possible.
+		//Currently this will be false only for PSTN P2P calls.
+		bool mCallBackEnabled;
+
+		bool mTextIMPossible;
+		bool mOtherParticipantIsAvatar;
 	};
 	
 
@@ -82,8 +92,8 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 	void	resetActiveSessionID() { mActiveSessionID.setNull(); }
 	LLUUID	getActiveSessionID() { return mActiveSessionID; }
 
-	//*TODO make it non-static as LLIMMOdel is a singleton (IB)
-	static std::map<LLUUID, LLIMSession*> sSessionsMap;  //mapping session_id to session
+	/** Session id to session object */
+	std::map<LLUUID, LLIMSession*> mId2SessionMap;
 
 	typedef boost::signals2::signal<void(const LLSD&)> session_signal_t;
 	typedef boost::function<void(const LLSD&)> session_callback_t;
@@ -99,23 +109,45 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 	/**
 	 * Rebind session data to a new session id.
 	 */
-	void updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id);
+	void processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id);
 
 	boost::signals2::connection addNewMsgCallback( session_callback_t cb ) { return mNewMsgSignal.connect(cb); }
 	boost::signals2::connection addNoUnreadMsgsCallback( session_callback_t cb ) { return mNoUnreadMsgsSignal.connect(cb); }
 
-	bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id, 
+	/**
+	 * Create new session object in a model
+	 */
+	bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, 
 		const std::vector<LLUUID>& ids = std::vector<LLUUID>());
-	bool clearSession(LLUUID session_id);
-	std::list<LLSD> getMessages(LLUUID session_id, int start_index = 0);
 
-	bool addMessage(LLUUID session_id, std::string from, LLUUID other_participant_id, std::string utf8_text, bool log2file = true);
-	bool addToHistory(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text); 
+	/**
+	 * Remove all session data associated with a session specified by session_id
+	 */
+	bool clearSession(const LLUUID& session_id);
+
+	/**
+	 * Populate supplied std::list with messages starting from index specified by start_index
+	 */
+	void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0);
+
+	/**
+	 * Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id
+	 * and also saved into a file if log2file is specified.
+	 * It sends new message signal for each added message.
+	 */
+	bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true);
 
-	bool logToFile(const LLUUID& session_id, const std::string& from, const std::string& utf8_text);
+	/**
+	 * Add a system message to an IM Model
+	 */
+	bool proccessOnlineOfflineNotification(const LLUUID& session_id, const std::string& utf8_text);
 
-	//used to get the name of the session, for use as the title
-	//currently just the other avatar name
+	/**
+	 * Get a session's name. 
+	 * For a P2P chat - it's an avatar's name, 
+	 * For a group chat - it's a group's name
+	 * For an ad-hoc chat - is received from the server and is in a from of "<Avatar's name> conference"
+	 */
 	const std::string& getName(const LLUUID& session_id) const;
 
 	/** 
@@ -150,7 +182,7 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 	*/
 	LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const;
 
-	static void sendLeaveSession(LLUUID session_id, LLUUID other_participant_id);
+	static void sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id);
 	static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id,
 						  const std::vector<LLUUID>& ids, EInstantMessage dialog);
 	static void sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing);
@@ -158,6 +190,18 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 								const LLUUID& other_participant_id, EInstantMessage dialog);
 
 	void testMessages();
+
+private:
+	
+	/**
+	 * Add message to a list of message associated with session specified by session_id
+	 */
+	bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text); 
+
+	/**
+	 * Save an IM message into a file
+	 */
+	bool logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
 };
 
 class LLIMSessionObserver
@@ -183,7 +227,7 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	};
 
 	LLIMMgr();
-	virtual ~LLIMMgr();
+	virtual ~LLIMMgr() {};
 
 	// Add a message to a session. The session can keyed to sesion id
 	// or agent id.
@@ -200,11 +244,6 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 
 	void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args);
 
-	// This method returns TRUE if the local viewer has a session
-	// currently open keyed to the uuid. The uuid can be keyed by
-	// either session id or agent id.
-	BOOL isIMSessionOpen(const LLUUID& uuid);
-
 	// This adds a session to the talk view. The name is the local
 	// name of the session, dialog specifies the type of
 	// session. Since sessions can be keyed off of first recipient or
@@ -250,9 +289,6 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	void processIMTypingStart(const LLIMInfo* im_info);
 	void processIMTypingStop(const LLIMInfo* im_info);
 
-	// Rebuild stuff
-	void refresh();
-
 	void notifyNewIM();
 	void clearNewIMNotification();
 
@@ -268,10 +304,6 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	// good connection.
 	void disconnectAllSessions();
 
-	// This is a helper function to determine what kind of im session
-	// should be used for the given agent.
-	static EInstantMessage defaultIMTypeForAgent(const LLUUID& agent_id);
-
 	BOOL hasSession(const LLUUID& session_id);
 
 	// This method returns the im panel corresponding to the uuid
@@ -290,11 +322,18 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	void clearPendingAgentListUpdates(const LLUUID& session_id);
 
 	//HACK: need a better way of enumerating existing session, or listening to session create/destroy events
+	//@deprecated, is used only by LLToolBox, which is not used anywhere, right? (IB)
 	const std::set<LLHandle<LLFloater> >& getIMFloaterHandles() { return mFloaters; }
 
 	void addSessionObserver(LLIMSessionObserver *);
 	void removeSessionObserver(LLIMSessionObserver *);
 
+	//show error statuses to the user
+	void showSessionStartError(const std::string& error_string, const LLUUID session_id);
+	void showSessionEventError(const std::string& event_string, const std::string& error_string, const LLUUID session_id);
+	void showSessionForceClose(const std::string& reason, const LLUUID session_id);
+	static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
+
 	/**
 	 * Start call in a session
 	 * @return false if voice channel doesn't exist
@@ -308,10 +347,11 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	bool endCall(const LLUUID& session_id);
 
 private:
-	// This removes the panel referenced by the uuid, and then
-	// restores internal consistency. The internal pointer is not
-	// deleted.
-	void removeSession(LLUUID session_id);
+
+	/**
+	 * Remove data associated with a particular session specified by session_id
+	 */
+	void removeSession(const LLUUID& session_id);
 
 	// create a panel and update internal representation for
 	// consistency. Returns the pointer, caller (the class instance
@@ -340,8 +380,9 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
 
 private:
+	
+	//*TODO should be deleted when Communicate Floater is being deleted
 	std::set<LLHandle<LLFloater> > mFloaters;
-	LLFriendObserver* mFriendObserver;
 
 	typedef std::list <LLIMSessionObserver *> session_observers_list_t;
 	session_observers_list_t mSessionObservers;
@@ -351,9 +392,6 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 
 	LLSD mPendingInvitations;
 	LLSD mPendingAgentListUpdates;
-	// ID of a session that is being removed: observers are already told
-	// that this session is being removed, but it is still present in the sessions' map
-	LLUUID	mBeingRemovedSessionID;
 };
 
 class LLIncomingCallDialog : public LLModalDialog
diff --git a/indra/newview/llinspect.h b/indra/newview/llinspect.h
index 68accca3a322ec98cbc0c5f51e29e82d23bc0751..a461c2fa169826f25e9b984485d9b4378bfe0b6d 100644
--- a/indra/newview/llinspect.h
+++ b/indra/newview/llinspect.h
@@ -58,3 +58,4 @@ class LLInspect : public LLFloater
 };
 
 #endif
+
diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp
index 29cca14a7bbb3b74087efdd01a93ce8bbf345ca5..050a61c79b266f567f03f9cde619e865e52e7e0c 100644
--- a/indra/newview/llinspectobject.cpp
+++ b/indra/newview/llinspectobject.cpp
@@ -35,10 +35,12 @@
 
 // Viewer
 #include "llinspect.h"
+#include "llmediaentry.h"
 #include "llnotifications.h"	// *TODO: Eliminate, add LLNotificationsUtil wrapper
 #include "llselectmgr.h"
 #include "llslurl.h"
 #include "llviewermenu.h"		// handle_object_touch(), handle_buy()
+#include "llviewermedia.h"
 #include "llviewerobjectlist.h"	// to select the requested object
 
 // Linden libraries
@@ -92,8 +94,10 @@ class LLInspectObject : public LLInspect
 	void updateName(LLSelectNode* nodep);
 	void updateDescription(LLSelectNode* nodep);
 	void updatePrice(LLSelectNode* nodep);
-	
 	void updateCreator(LLSelectNode* nodep);
+	
+	void updateMediaCurrentURL();	
+	void updateSecureBrowsing();
 		
 	void onClickBuy();
 	void onClickPay();
@@ -106,13 +110,17 @@ class LLInspectObject : public LLInspect
 	
 private:
 	LLUUID				mObjectID;
+	S32					mObjectFace;
+	viewer_media_t		mMediaImpl;
 	LLSafeHandle<LLObjectSelection> mObjectSelection;
 };
 
 LLInspectObject::LLInspectObject(const LLSD& sd)
 :	LLInspect( LLSD() ),	// single_instance, doesn't really need key
-	mObjectID(),			// set in onOpen()
-	mObjectSelection()
+	mObjectID(NULL),			// set in onOpen()
+	mObjectFace(0),
+	mObjectSelection(NULL),
+	mMediaImpl(NULL)
 {
 	// can't make the properties request until the widgets are constructed
 	// as it might return immediately, so do it in postBuild.
@@ -139,7 +147,7 @@ BOOL LLInspectObject::postBuild(void)
 	getChild<LLUICtrl>("object_name")->setValue("");
 	getChild<LLUICtrl>("object_creator")->setValue("");
 	getChild<LLUICtrl>("object_description")->setValue("");
-
+	getChild<LLUICtrl>("object_media_url")->setValue("");
 	// Set buttons invisible until we know what this object can do
 	hideButtons();
 
@@ -182,7 +190,11 @@ void LLInspectObject::onOpen(const LLSD& data)
 
 	// Extract appropriate avatar id
 	mObjectID = data["object_id"];
-
+	
+	if(data.has("object_face"))
+	{
+		mObjectFace = data["object_face"];
+	}
 	// Position the inspector relative to the mouse cursor
 	// Similar to how tooltips are positioned
 	// See LLToolTipMgr::createToolTip
@@ -213,6 +225,17 @@ void LLInspectObject::onOpen(const LLSD& data)
 			}
 		} functor;
 		mObjectSelection->applyToNodes(&functor);
+		
+		// Does this face have media?
+		const LLTextureEntry* tep = obj->getTE(mObjectFace);
+		if (!tep)
+			return;
+		
+		const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+		if(!mep)
+			return;
+		
+		mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
 	}
 }
 
@@ -243,6 +266,30 @@ void LLInspectObject::update()
 	updateDescription(nodep);
 	updateCreator(nodep);
 	updatePrice(nodep);
+	
+	LLViewerObject* obj = nodep->getObject();
+	if(!obj)
+		return;
+	
+	if ( mObjectFace < 0 
+		||  mObjectFace >= obj->getNumTEs() )
+	{
+		return;
+	}
+	
+	// Does this face have media?
+	const LLTextureEntry* tep = obj->getTE(mObjectFace);
+	if (!tep)
+		return;
+	
+	const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+	if(!mep)
+		return;
+	
+	mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+	
+	updateMediaCurrentURL();
+	updateSecureBrowsing();
 }
 
 void LLInspectObject::hideButtons()
@@ -381,6 +428,40 @@ void LLInspectObject::updateDescription(LLSelectNode* nodep)
 	}
 }
 
+void LLInspectObject::updateMediaCurrentURL()
+{	
+	LLTextBox* textbox = getChild<LLTextBox>("object_media_url");
+	std::string media_url = "";
+	textbox->setValue(media_url);
+	textbox->setToolTip(media_url);
+	
+	if(mMediaImpl.notNull() && mMediaImpl->hasMedia())
+	{
+		LLStringUtil::format_map_t args;
+		LLPluginClassMedia* media_plugin = NULL;
+		media_plugin = mMediaImpl->getMediaPlugin();
+		if(media_plugin)
+		{
+			if(media_plugin->pluginSupportsMediaTime())
+			{
+				args["[CurrentURL]"] =  mMediaImpl->getMediaURL();
+			}
+			else
+			{
+				args["[CurrentURL]"] =  media_plugin->getLocation();
+			}
+			media_url = LLTrans::getString("CurrentURL", args);
+			textbox->setText(media_url);
+			textbox->setToolTip(media_url);
+		}
+	}
+	else
+	{
+		textbox->setText(media_url);
+		textbox->setToolTip(media_url);
+	}
+}
+
 void LLInspectObject::updateCreator(LLSelectNode* nodep)
 {
 	// final information for display
@@ -453,6 +534,40 @@ void LLInspectObject::updatePrice(LLSelectNode* nodep)
 	getChild<LLUICtrl>("price_icon")->setVisible(show_price_icon);
 }
 
+void LLInspectObject::updateSecureBrowsing()
+{
+	bool is_secure_browsing = false;
+	
+	if(mMediaImpl.notNull() 
+	   && mMediaImpl->hasMedia())
+	{
+		LLPluginClassMedia* media_plugin = NULL;
+		std::string current_url = "";
+		media_plugin = mMediaImpl->getMediaPlugin();
+		if(media_plugin)
+		{
+			if(media_plugin->pluginSupportsMediaTime())
+			{
+				current_url = mMediaImpl->getMediaURL();
+			}
+			else
+			{
+				current_url =  media_plugin->getLocation();
+			}
+		}
+		
+		std::string prefix =  std::string("https://");
+		std::string test_prefix = current_url.substr(0, prefix.length());
+		LLStringUtil::toLower(test_prefix);	
+		if(test_prefix == prefix)
+		{
+			is_secure_browsing = true;
+		}
+	}
+	getChild<LLUICtrl>("secure_browsing")->setVisible(is_secure_browsing);
+}
+
+
 void LLInspectObject::onClickBuy()
 {
 	handle_buy();
diff --git a/indra/newview/llinventoryactions.h b/indra/newview/llinventoryactions.h
new file mode 100644
index 0000000000000000000000000000000000000000..79247e3abb61864a128fcd749ed4171e1d0060a7
--- /dev/null
+++ b/indra/newview/llinventoryactions.h
@@ -0,0 +1,47 @@
+/** 
+ * @file llinventoryactions.h
+ * @brief inventory callback functions
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINVENTORYACTIONS_H
+#define LL_LLINVENTORYACTIONS_H
+
+#include "lluictrl.h"
+
+class LLPanelInventory;
+class LLInventoryView;
+class LLInventoryPanel;
+
+void init_object_inventory_panel_actions(LLPanelInventory *panel, LLUICtrl::CommitCallbackRegistry::Registrar& registrar);
+void init_inventory_actions(LLInventoryView *floater, LLUICtrl::CommitCallbackRegistry::Registrar& registrar);
+void init_inventory_panel_actions(LLInventoryPanel *panel, LLUICtrl::CommitCallbackRegistry::Registrar& registrar);
+
+#endif // LL_LLINVENTORYACTIONS_H
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 028505456bcefb3e49060d69db3f86e5fd6f4139..dcd1339ad098c3071796ce6dd2cd5c6c83530855 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1,11 +1,11 @@
-/** 
+/**
  * @file llinventorybridge.cpp
  * @brief Implementation of the Inventory-Folder-View-Bridge classes.
  *
  * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
+ *
  * Copyright (c) 2001-2009, Linden Research, Inc.
- * 
+ *
  * Second Life Viewer Source Code
  * The source code in this file ("Source Code") is provided by Linden Lab
  * to you under the terms of the GNU General Public License, version 2.0
@@ -13,17 +13,17 @@
  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
+ *
  * There are special exceptions to the terms and conditions of the GPL as
  * it is applied to this Source Code. View the full text of the exception
  * in the file doc/FLOSS-exception.txt in this software distribution, or
  * online at
  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
+ *
  * By copying, modifying or distributing this software, you acknowledge
  * that you have read and understood your obligations described above,
  * and agree to abide by those obligations.
- * 
+ *
  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  * COMPLETENESS OR PERFORMANCE.
@@ -83,7 +83,7 @@
 #include "llvoavatar.h"
 #include "llwearable.h"
 #include "llwearablelist.h"
-#include "llviewermessage.h" 
+#include "llviewermessage.h"
 #include "llviewerregion.h"
 #include "llvoavatarself.h"
 #include "lltabcontainer.h"
@@ -147,8 +147,8 @@ std::string ICON_NAME[ICON_NAME_COUNT] =
 	"Inv_Undershirt",
 	"Inv_Underpants",
 	"Inv_Skirt",
-	"inv_item_alpha.tga",
-	"inv_item_tattoo.tga",
+	"Inv_Alpha",
+	"Inv_Tattoo",
 
 	"Inv_Animation",
 	"Inv_Gesture",
@@ -239,7 +239,7 @@ void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string&
 	{
 		return;
 	}
-	
+
 	LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id);
 	for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
 		 iter != item_array.end();
@@ -247,7 +247,7 @@ void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string&
 	{
 		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);
@@ -292,7 +292,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
 	S32 count = batch.count();
 	S32 i,j;
 	for(i = 0; i < count; ++i)
-	{	
+	{
 		bridge = (LLInvFVBridge*)(batch.get(i));
 		if(!bridge || !bridge->isItemRemovable()) continue;
 		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
@@ -305,7 +305,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
 		}
 	}
 	for(i = 0; i < count; ++i)
-	{		
+	{
 		bridge = (LLInvFVBridge*)(batch.get(i));
 		if(!bridge || !bridge->isItemRemovable()) continue;
 		cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
@@ -508,7 +508,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
 	return TRUE;
 }
 
-void hideContextEntries(LLMenuGL& menu, 
+void hideContextEntries(LLMenuGL& menu,
 						const std::vector<std::string> &entries_to_show,
 						const std::vector<std::string> &disabled_entries)
 {
@@ -525,8 +525,8 @@ void hideContextEntries(LLMenuGL& menu,
 		{
 			hideContextEntries(*branchp->getBranch(), entries_to_show, disabled_entries);
 		}
-		
-		
+
+
 		bool found = false;
 		std::vector<std::string>::const_iterator itor2;
 		for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
@@ -554,8 +554,8 @@ void hideContextEntries(LLMenuGL& menu,
 }
 
 // Helper for commonly-used entries
-void LLInvFVBridge::getClipboardEntries(bool show_asset_id, 
-										std::vector<std::string> &items, 
+void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
+										std::vector<std::string> &items,
 										std::vector<std::string> &disabled_items, U32 flags)
 {
 	items.push_back(std::string("Rename"));
@@ -567,7 +567,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 	if (show_asset_id)
 	{
 		items.push_back(std::string("Copy Asset UUID"));
-		if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) 
+		if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
 			  || (flags & FIRST_SELECTED_ITEM) == 0)
 		{
 			disabled_items.push_back(std::string("Copy Asset UUID"));
@@ -640,7 +640,7 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
 		{
 			return FALSE;
 		}
-		
+
 		*id = obj->getUUID();
 		//object_ids.put(obj->getUUID());
 
@@ -810,7 +810,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
 			}
 			new_listener = new LLLandmarkBridge(inventory, uuid, flags);
 			break;
-		
+
 		case LLAssetType::AT_CALLINGCARD:
 			if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
 			{
@@ -1110,7 +1110,7 @@ PermissionMask LLItemBridge::getPermissionMask() const
 {
 	LLViewerInventoryItem* item = getItem();
 	PermissionMask perm_mask = 0;
-	if(item) 
+	if(item)
 	{
 		BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
 		BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
@@ -1136,9 +1136,9 @@ const std::string& LLItemBridge::getDisplayName() const
 
 void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
 {
-	if(item) 
+	if(item)
 	{
-		name.assign(item->getName());			
+		name.assign(item->getName());
 	}
 	else
 	{
@@ -1147,9 +1147,9 @@ void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
 }
 
 LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
-{ 
+{
 	U8 font = LLFontGL::NORMAL;
-	
+
 	if( gAgentWearables.isWearingItem( mUUID ) )
 	{
 		// llinfos << "BOLD" << llendl;
@@ -1175,7 +1175,7 @@ std::string LLItemBridge::getLabelSuffix() const
 	static std::string BROKEN_LINK = LLTrans::getString("broken_link");
 	std::string suffix;
 	LLInventoryItem* item = getItem();
-	if(item) 
+	if(item)
 	{
 		// it's a bit confusing to put nocopy/nomod/etc on calling cards.
 		if(LLAssetType::AT_CALLINGCARD != item->getType()
@@ -1304,9 +1304,9 @@ BOOL LLItemBridge::isItemCopyable() const
 		{
 			return FALSE;
 		}
-		
+
 		// 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 
+		// The only time an item can't be copied is if it's a link
 		// return (item->getPermissions().allowCopyBy(gAgent.getID()));
 		if (item->getIsLinkType())
 		{
@@ -1358,7 +1358,7 @@ BOOL LLItemBridge::isItemPermissive() const
 LLFolderBridge* LLFolderBridge::sSelf=NULL;
 
 // Can be moved to another folder
-BOOL LLFolderBridge::isItemMovable() const 
+BOOL LLFolderBridge::isItemMovable() const
 {
 	LLInventoryObject* obj = getInventoryObject();
 	if(obj)
@@ -1377,7 +1377,7 @@ void LLFolderBridge::selectItem()
 BOOL LLFolderBridge::isItemRemovable()
 {
 	LLInventoryModel* model = getInventoryModel();
-	if(!model) 
+	if(!model)
 	{
 		return FALSE;
 	}
@@ -1488,7 +1488,7 @@ BOOL LLFolderBridge::isClipboardPasteable() const
 		LLInventoryClipboard::instance().retrieve(objects);
 		const LLViewerInventoryCategory *current_cat = getCategory();
 
-		// Search for the direct descendent of current Friends subfolder among all pasted items, 
+		// Search for the direct descendent of current Friends subfolder among all pasted items,
 		// and return false if is found.
 		for(S32 i = objects.count() - 1; i >= 0; --i)
 		{
@@ -1510,7 +1510,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
 	{
 		return FALSE;
 	}
-	
+
 	const LLInventoryModel* model = getInventoryModel();
 	if (!model)
 	{
@@ -1533,7 +1533,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
 			{
 				const LLUUID &cat_id = cat->getUUID();
 				// Don't allow recursive pasting
-				if ((cat_id == current_cat_id) || 
+				if ((cat_id == current_cat_id) ||
 					model->isObjectDescendentOf(current_cat_id, cat_id))
 				{
 					return FALSE;
@@ -1559,7 +1559,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
 BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 											BOOL drop)
 {
-	// This should never happen, but if an inventory item is incorrectly parented, 
+	// This should never happen, but if an inventory item is incorrectly parented,
 	// the UI will get confused and pass in a NULL.
 	if(!inv_cat) return FALSE;
 
@@ -1621,7 +1621,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 					break;
 				}
 			}
-			
+
 			if( is_movable )
 			{
 				if( move_is_into_trash )
@@ -1652,7 +1652,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 			}
 		}
 
-		
+
 		accept =	is_movable
 					&& (mUUID != cat_id)								// Can't move a folder into itself
 					&& (mUUID != inv_cat->getParentUUID())				// Avoid moves that would change nothing
@@ -1673,7 +1673,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 				}
 			}
 			// if target is an outfit or current outfit folder we use link
-			if (move_is_into_current_outfit || move_is_into_outfit) 
+			if (move_is_into_current_outfit || move_is_into_outfit)
 			{
 #if SUPPORT_ENSEMBLES
 				// BAP - should skip if dup.
@@ -1696,7 +1696,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 			}
 			else
 			{
-				
+
 				// Reparent the folder and restamp children if it's moving
 				// into trash.
 				LLInvFVBridge::changeCategoryParent(
@@ -1733,7 +1733,7 @@ void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
 
 // Move/copy all inventory items from the Contents folder of an in-world
 // object to the agent's inventory, inside a given category.
-BOOL move_inv_category_world_to_agent(const LLUUID& object_id, 
+BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
 									  const LLUUID& category_id,
 									  BOOL drop,
 									  void (*callback)(S32, void*),
@@ -1760,7 +1760,7 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
 		llinfos << "Object contents not found for drop." << llendl;
 		return FALSE;
 	}
-	
+
 	BOOL accept = TRUE;
 	BOOL is_move = FALSE;
 
@@ -1846,7 +1846,7 @@ bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
 	{
 		LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
 		// BAP remove AT_NONE support after ensembles are fully working?
-		return (linked_category && 
+		return (linked_category &&
 				((linked_category->getPreferredType() == LLAssetType::AT_NONE) ||
 				 (LLAssetType::lookupIsEnsembleCategoryType(linked_category->getPreferredType()))));
 	}
@@ -1888,7 +1888,7 @@ class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
 		gInventory.removeObserver(this);
 		delete this;
 	}
-	
+
 
 protected:
 	LLUUID mCatID;
@@ -1983,7 +1983,7 @@ void LLRightClickInventoryFetchDescendentsObserver::done()
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLInventoryWearObserver
 //
-// Observer for "copy and wear" operation to support knowing 
+// Observer for "copy and wear" operation to support knowing
 // when the all of the contents have been added to inventory.
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 class LLInventoryCopyAndWearObserver : public LLInventoryObserver
@@ -2005,7 +2005,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
 {
 	if((mask & (LLInventoryObserver::ADD)) != 0)
 	{
-		if (!mFolderAdded) 
+		if (!mFolderAdded)
 		{
 			const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
 
@@ -2013,7 +2013,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
 			std::set<LLUUID>::const_iterator id_end = changed_items.end();
 			for (;id_it != id_end; ++id_it)
 			{
-				if ((*id_it) == mCatID) 
+				if ((*id_it) == mCatID)
 				{
 					mFolderAdded = TRUE;
 					break;
@@ -2021,7 +2021,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
 			}
 		}
 
-		if (mFolderAdded) 
+		if (mFolderAdded)
 		{
 			LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
 
@@ -2039,7 +2039,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
 					LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
 					delete this;
 				}
-			}		
+			}
 		}
 
 	}
@@ -2101,12 +2101,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
 		if(!model) return;
 		LLViewerInventoryCategory* cat = getCategory();
 		if(!cat) return;
-		
+
 		remove_inventory_category_from_avatar ( cat );
 		return;
-	}	
+	}
 	else if ("purge" == action)
-	{		
+	{
 		purgeItem(model, mUUID);
 		return;
 	}
@@ -2283,7 +2283,7 @@ void LLFolderBridge::pasteFromClipboard()
 			{
 				if(LLInventoryClipboard::instance().isCutMode())
 				{
-					// move_inventory_item() is not enough, 
+					// move_inventory_item() is not enough,
 					//we have to update inventory locally too
 					changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
 				}
@@ -2360,7 +2360,7 @@ void LLFolderBridge::folderOptionsMenu()
 	// BAP change once we're no longer treating regular categories as ensembles.
 	const bool is_ensemble = category && (type == LLAssetType::AT_NONE ||
 										  LLAssetType::lookupIsEnsembleCategoryType(type));
-	
+
 	// calling card related functionality for folders.
 
 	// Only enable calling-card related options for non-default folders.
@@ -2374,7 +2374,7 @@ void LLFolderBridge::folderOptionsMenu()
 			mItems.push_back(std::string("IM All Contacts In Folder"));
 		}
 	}
-	
+
 	// wearables related functionality for folders.
 	//is_wearable
 	LLFindWearables is_wearable;
@@ -2429,7 +2429,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
 
 	mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
-	mDisabledItems.clear(); //adding code to clear out disabled members from previous 
+	mDisabledItems.clear(); //adding code to clear out disabled members from previous
 	if (lost_and_found_id == mUUID)
 	  {
 		// This is the lost+found folder.
@@ -2471,13 +2471,13 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 			mItems.push_back(std::string("New Clothes"));
 			mItems.push_back(std::string("New Body Parts"));
 			mItems.push_back(std::string("Change Type"));
-			
+
 			LLViewerInventoryCategory *cat = getCategory();
 			if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
 			{
 				mDisabledItems.push_back(std::string("Change Type"));
 			}
-			
+
 			getClipboardEntries(false, mItems, mDisabledItems, flags);
 		}
 		else
@@ -2492,24 +2492,24 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 
 		//Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
 		mCallingCards = mWearables = FALSE;
-		
+
 		LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
 		if (checkFolderForContentsOfType(model, is_callingcard))
 		{
 			mCallingCards=TRUE;
 		}
-		
+
 		LLFindWearables is_wearable;
 		LLIsType is_object( LLAssetType::AT_OBJECT );
 		LLIsType is_gesture( LLAssetType::AT_GESTURE );
-		
+
 		if (checkFolderForContentsOfType(model, is_wearable)  ||
 			checkFolderForContentsOfType(model, is_object) ||
 			checkFolderForContentsOfType(model, is_gesture) )
 		{
 			mWearables=TRUE;
 		}
-		
+
 		mMenu = &menu;
 		sSelf = this;
 		LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
@@ -2723,7 +2723,7 @@ void LLFolderBridge::modifyOutfit(BOOL append)
 	if(!model) return;
 	LLViewerInventoryCategory* cat = getCategory();
 	if(!cat) return;
-	
+
 	// BAP - was:
 	// wear_inventory_category_on_avatar( cat, append );
 	LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
@@ -2749,8 +2749,8 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
 		}
 
 		two_uuids_list_t::iterator move_it;
-		for (move_it = move_inv->mMoveList.begin(); 
-			move_it != move_inv->mMoveList.end(); 
+		for (move_it = move_inv->mMoveList.begin();
+			move_it != move_inv->mMoveList.end();
 			++move_it)
 		{
 			object->moveInventory(move_it->first, move_it->second);
@@ -2859,7 +2859,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
 		BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
 		BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT);
-		
+
 		if(is_movable && move_is_into_trash)
 		{
 			switch(inv_item->getType())
@@ -2887,7 +2887,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			is_movable = ! LLFriendCardsManager::instance()
 				.isObjDirectDescendentOfCategory (inv_item, getCategory());
 		}
- 
+
 		LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
 
 		// we can move item inside a folder only if this folder is Favorites. See EXT-719
@@ -2993,7 +2993,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
 			&& perm.allowTransferTo(gAgent.getID())))
 //		   || gAgent.isGodlike())
-			
+
 		{
 			accept = TRUE;
 		}
@@ -3024,7 +3024,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 				LLNotifications::instance().forceResponse(params, 0);
 			}
 		}
-		
+
 	}
 	else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
 	{
@@ -3077,11 +3077,11 @@ LLUIImagePtr LLTextureBridge::getIcon() const
 {
 	return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
 }
-	
+
 void LLTextureBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3100,7 +3100,7 @@ LLUIImagePtr LLSoundBridge::getIcon() const
 void LLSoundBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3169,7 +3169,7 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 // +=================================================+
 
 LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
-LLItemBridge(inventory, uuid) 
+LLItemBridge(inventory, uuid)
 {
 	mVisited = FALSE;
 	if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
@@ -3258,7 +3258,7 @@ void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
 			LLSideTray::getInstance()->showPanel("panel_places", key);
 		}
 	}
-	else 
+	else
 	{
 		LLItemBridge::performAction(folder, model, action);
 	}
@@ -3282,7 +3282,7 @@ static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFro
 void LLLandmarkBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3390,7 +3390,7 @@ std::string LLCallingCardBridge::getLabelSuffix() const
 void LLCallingCardBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3530,7 +3530,7 @@ BOOL LLCallingCardBridge::removeItem()
 		LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
 		return FALSE;
 	}
-	else 
+	else
 	{
 		return LLItemBridge::removeItem();
 	}
@@ -3547,7 +3547,7 @@ LLUIImagePtr LLNotecardBridge::getIcon() const
 void LLNotecardBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3629,7 +3629,7 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode
 void LLGestureBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3731,7 +3731,7 @@ void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* mo
 			LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
 			if ("playworld" == action) activate = LLPreviewAnim::PLAY;
 			if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
-			
+
 			LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
 			if (preview)
 			{
@@ -3748,7 +3748,7 @@ void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* mo
 void LLAnimationBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3856,7 +3856,7 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
 void LLObjectBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3868,7 +3868,7 @@ void LLObjectBridge::openItem()
 }
 
 LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
-{ 
+{
 	U8 font = LLFontGL::NORMAL;
 
 	LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
@@ -3882,7 +3882,7 @@ LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
 	{
 		font |= LLFontGL::ITALIC;
 	}
-	
+
 	return (LLFontGL::StyleFlags)font;
 }
 
@@ -3893,7 +3893,10 @@ std::string LLObjectBridge::getLabelSuffix() const
 	{
 		std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
 		LLStringUtil::toLower(attachment_point_name);
-		return LLItemBridge::getLabelSuffix() + std::string(" (worn on ") + attachment_point_name + std::string(")");
+
+		LLStringUtil::format_map_t args;
+		args["[ATTACHMENT_POINT]"] =  attachment_point_name.c_str();
+		return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
 	}
 	else
 	{
@@ -3937,7 +3940,7 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
 bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
 {
 	LLVOAvatar *avatarp = gAgent.getAvatarObject();
-		
+
 	if (!avatarp->canAttachMoreObjects())
 	{
 		LLSD args;
@@ -3950,7 +3953,7 @@ bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& respon
 	if (option == 0/*YES*/)
 	{
 		LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
-		
+
 		if (itemp)
 		{
 			LLMessageSystem* msg = gMessageSystem;
@@ -4011,7 +4014,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 			{
 				return;
 			}
-			
+
 			if( avatarp->isWearingAttachment( mUUID ) )
 			{
 				items.push_back(std::string("Detach From Yourself"));
@@ -4035,13 +4038,13 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 				LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
 				LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
 				LLVOAvatar *avatarp = gAgent.getAvatarObject();
-				if (attach_menu 
-					&& (attach_menu->getChildCount() == 0) 
-					&& attach_hud_menu 
-					&& (attach_hud_menu->getChildCount() == 0) 
+				if (attach_menu
+					&& (attach_menu->getChildCount() == 0)
+					&& attach_hud_menu
+					&& (attach_hud_menu->getChildCount() == 0)
 					&& avatarp)
 				{
-					for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); 
+					for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
 						 iter != avatarp->mAttachmentPoints.end(); )
 					{
 						LLVOAvatar::attachment_map_t::iterator curiter = iter++;
@@ -4122,7 +4125,7 @@ LLUIImagePtr LLLSLTextBridge::getIcon() const
 void LLLSLTextBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -4158,7 +4161,7 @@ void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
 	{
 		lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
 				 << " )" << llendl;
-			
+
 		LLWearableList::instance().getAsset(item->getAssetUUID(),
 							   item->getName(),
 							   item->getType(),
@@ -4172,8 +4175,8 @@ void remove_inventory_category_from_avatar( LLInventoryCategory* category )
 	if(!category) return;
 	lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
 			 << " )" << llendl;
-			 
-	
+
+
 	if( gFloaterCustomize )
 	{
 		gFloaterCustomize->askToSaveIfDirty(
@@ -4248,8 +4251,8 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_
 				}
 			}
 		}
-		
-		
+
+
 		if (obj_count > 0)
 		{
 			for(i = 0; i  < obj_count; ++i)
@@ -4309,7 +4312,7 @@ std::string LLWearableBridge::getLabelSuffix() const
 {
 	if( gAgentWearables.isWearingItem( mUUID ) )
 	{
-		return LLItemBridge::getLabelSuffix() + " (worn)";
+		return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
 	}
 	else
 	{
@@ -4344,7 +4347,7 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
 		{
 			LLViewerInventoryItem* item = getItem();
 			if (item)
-			{	
+			{
 				LLWearableList::instance().getAsset(item->getAssetUUID(),
 													item->getName(),
 													item->getType(),
@@ -4359,7 +4362,7 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
 void LLWearableBridge::openItem()
 {
 	LLViewerInventoryItem* item = getItem();
-	
+
 	if (item)
 	{
 		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -4443,7 +4446,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 		getClipboardEntries(true, items, disabled_items, flags);
 
 		items.push_back(std::string("Wearable Separator"));
-		
+
 		items.push_back(std::string("Wearable Wear"));
 		items.push_back(std::string("Wearable Add"));
 		items.push_back(std::string("Wearable Edit"));
@@ -4474,7 +4477,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 						disabled_items.push_back(std::string("Wearable Add"));
 					}
 					else
-					{	
+					{
 						disabled_items.push_back(std::string("Take Off"));
 					}
 					break;
@@ -4513,7 +4516,7 @@ void LLWearableBridge::wearOnAvatar()
 {
 	// Don't wear anything until initial wearables are loaded, can
 	// destroy clothing items.
-	if (!gAgentWearables.areWearablesLoaded()) 
+	if (!gAgentWearables.areWearablesLoaded())
 	{
 		LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
 		return;
@@ -4544,7 +4547,7 @@ void LLWearableBridge::wearAddOnAvatar()
 {
 	// Don't wear anything until initial wearables are loaded, can
 	// destroy clothing items.
-	if (!gAgentWearables.areWearablesLoaded()) 
+	if (!gAgentWearables.areWearablesLoaded())
 	{
 		LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
 		return;
@@ -4632,7 +4635,7 @@ BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
 	return (gAgentWearables.isWearingItem(self->mUUID));
 }
 
-// static 
+// static
 void LLWearableBridge::onEditOnAvatar(void* user_data)
 {
 	LLWearableBridge* self = (LLWearableBridge*)user_data;
@@ -4670,7 +4673,7 @@ BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
 	return FALSE;
 }
 
-// static 
+// static
 void LLWearableBridge::onRemoveFromAvatar(void* user_data)
 {
 	LLWearableBridge* self = (LLWearableBridge*)user_data;
@@ -4701,7 +4704,7 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
 		if( gAgentWearables.isWearingItem( item_id ) )
 		{
 			EWearableType type = wearable->getType();
-	
+
 			if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&&
 				//!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
 			{
@@ -4804,7 +4807,7 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
 	case LLAssetType::AT_LANDMARK:
 		action = new LLLandmarkBridgeAction(uuid,model);
 		break;
-		
+
 	case LLAssetType::AT_CALLINGCARD:
 		action = new LLCallingCardBridgeAction(uuid,model);
 		break;
@@ -4847,7 +4850,7 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
 	return action;
 }
 
-//static 
+//static
 void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
 								   const LLUUID& uuid,LLInventoryModel* model)
 {
@@ -4859,7 +4862,7 @@ void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
 	}
 }
 
-//static 
+//static
 void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
 {
 	LLAssetType::EType asset_type = model->getItem(uuid)->getType();
@@ -4878,8 +4881,8 @@ LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
 	return NULL;
 }
 
-//virtual 
-void	LLTextureBridgeAction::doIt() 
+//virtual
+void	LLTextureBridgeAction::doIt()
 {
 	if (getItem())
 	{
@@ -4890,20 +4893,20 @@ void	LLTextureBridgeAction::doIt()
 }
 
 //virtual
-void	LLSoundBridgeAction::doIt() 
+void	LLSoundBridgeAction::doIt()
 {
 	LLViewerInventoryItem* item = getItem();
 	if(item)
 	{
 		LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
 	}
-	
+
 	LLInvFVBridgeAction::doIt();
 }
 
 
-//virtual 
-void	LLLandmarkBridgeAction::doIt() 
+//virtual
+void	LLLandmarkBridgeAction::doIt()
 {
 	LLViewerInventoryItem* item = getItem();
 	if( item )
@@ -4919,8 +4922,8 @@ void	LLLandmarkBridgeAction::doIt()
 }
 
 
-//virtual 
-void	LLCallingCardBridgeAction::doIt() 
+//virtual
+void	LLCallingCardBridgeAction::doIt()
 {
 	LLViewerInventoryItem* item = getItem();
 	if(item && item->getCreatorUUID().notNull())
@@ -4931,9 +4934,9 @@ void	LLCallingCardBridgeAction::doIt()
 	LLInvFVBridgeAction::doIt();
 }
 
-//virtual 
-void	
-LLNotecardBridgeAction::doIt() 
+//virtual
+void
+LLNotecardBridgeAction::doIt()
 {
 	LLViewerInventoryItem* item = getItem();
 	if (item)
@@ -4944,8 +4947,8 @@ LLNotecardBridgeAction::doIt()
 	LLInvFVBridgeAction::doIt();
 }
 
-//virtual 
-void	LLGestureBridgeAction::doIt() 
+//virtual
+void	LLGestureBridgeAction::doIt()
 {
 	LLViewerInventoryItem* item = getItem();
 	if (item)
@@ -4957,8 +4960,8 @@ void	LLGestureBridgeAction::doIt()
 	LLInvFVBridgeAction::doIt();
 }
 
-//virtual 
-void	LLAnimationBridgeAction::doIt() 
+//virtual
+void	LLAnimationBridgeAction::doIt()
 {
 	LLViewerInventoryItem* item = getItem();
 	if (item)
@@ -4970,7 +4973,7 @@ void	LLAnimationBridgeAction::doIt()
 }
 
 
-//virtual 
+//virtual
 void	LLObjectBridgeAction::doIt()
 {
 	LLFloaterReg::showInstance("properties", mUUID);
@@ -4979,8 +4982,8 @@ void	LLObjectBridgeAction::doIt()
 }
 
 
-//virtual 
-void	LLLSLTextBridgeAction::doIt() 
+//virtual
+void	LLLSLTextBridgeAction::doIt()
 {
 	LLViewerInventoryItem* item = getItem();
 	if (item)
@@ -5010,7 +5013,7 @@ void LLWearableBridgeAction::wearOnAvatar()
 {
 	// Don't wear anything until initial wearables are loaded, can
 	// destroy clothing items.
-	if (!gAgentWearables.areWearablesLoaded()) 
+	if (!gAgentWearables.areWearablesLoaded())
 	{
 		LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
 		return;
@@ -5037,7 +5040,7 @@ void LLWearableBridgeAction::wearOnAvatar()
 	}
 }
 
-//virtual 
+//virtual
 void LLWearableBridgeAction::doIt()
 {
 	if(isInTrash())
@@ -5125,7 +5128,7 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 		items.push_back(std::string("Restore Item"));
 	}
 	else
-	{	
+	{
 		items.push_back(std::string("Delete"));
 		if (!isItemRemovable())
 		{
@@ -5175,7 +5178,7 @@ void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 		items.push_back(std::string("Restore Item"));
 	}
 	else
-	{	
+	{
 		items.push_back(std::string("Goto Link"));
 		items.push_back(std::string("Delete"));
 		if (!isItemRemovable())
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 6009e8e61000339b387fd5b912d08b4a56e5f350..1d7cbde0d5655932477a1df6107a255fb4a2c956 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -175,13 +175,22 @@ LLInventoryModel::LLInventoryModel()
 
 // Destroys the object
 LLInventoryModel::~LLInventoryModel()
+{
+	cleanupInventory();
+}
+
+void LLInventoryModel::cleanupInventory()
 {
 	empty();
-	for (observer_list_t::iterator iter = mObservers.begin();
-		 iter != mObservers.end(); ++iter)
+	// Deleting one observer might erase others from the list, so always pop off the front
+	while (!mObservers.empty())
 	{
-		delete *iter;
+		observer_list_t::iterator iter = mObservers.begin();
+		LLInventoryObserver* observer = *iter;
+		mObservers.erase(iter);
+		delete observer;
 	}
+	mObservers.clear();
 }
 
 // This is a convenience function to check if one object has a parent
@@ -2010,63 +2019,56 @@ bool LLInventoryModel::isCategoryComplete(const LLUUID& cat_id) const
 }
 
 bool LLInventoryModel::loadSkeleton(
-	const LLInventoryModel::options_t& options,
+	const LLSD& options,
 	const LLUUID& owner_id)
 {
 	lldebugs << "importing inventory skeleton for " << owner_id << llendl;
 
 	typedef std::set<LLPointer<LLViewerInventoryCategory>, InventoryIDPtrLess> cat_set_t;
 	cat_set_t temp_cats;
-
-	update_map_t child_counts;
-
-	LLUUID id;
-	LLAssetType::EType preferred_type;
 	bool rv = true;
-	for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
-	{
-		LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id);
-		response_t::const_iterator no_response = (*it).end();
-		response_t::const_iterator skel;
-		skel = (*it).find("name");
-		if(skel == no_response) goto clean_cat;
-		cat->rename(std::string((*skel).second));
-		skel = (*it).find("folder_id");
-		if(skel == no_response) goto clean_cat;
-		id.set((*skel).second);
-		// if an id is null, it locks the viewer.
-		if(id.isNull()) goto clean_cat;
-		cat->setUUID(id);
-		skel = (*it).find("parent_id");
-		if(skel == no_response) goto clean_cat;
-		id.set((*skel).second);
-		cat->setParent(id);
-		skel = (*it).find("type_default");
-		if(skel == no_response)
-		{
-			preferred_type = LLAssetType::AT_NONE;
+
+	for(LLSD::array_const_iterator it = options.beginArray(),
+		end = options.endArray(); it != end; ++it)
+	{
+		LLSD name = (*it)["name"];
+		LLSD folder_id = (*it)["folder_id"];
+		LLSD parent_id = (*it)["parent_id"];
+		LLSD version = (*it)["version"];
+		if(name.isDefined()
+			&& folder_id.isDefined()
+			&& parent_id.isDefined()
+			&& version.isDefined()
+			&& folder_id.asUUID().notNull() // if an id is null, it locks the viewer.
+			) 		
+		{
+			LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id);
+			cat->rename(name.asString());
+			cat->setUUID(folder_id.asUUID());
+			cat->setParent(parent_id.asUUID());
+
+			LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
+			LLSD type_default = (*it)["type_default"];
+			if(type_default.isDefined())
+            {
+				preferred_type = (LLAssetType::EType)type_default.asInteger();
+            }
+            cat->setPreferredType(preferred_type);
+			cat->setVersion(version.asInteger());
+            temp_cats.insert(cat);
 		}
 		else
 		{
-			S32 t = atoi((*skel).second.c_str());
-			preferred_type = (LLAssetType::EType)t;
+			llwarns << "Unable to import near " << name.asString() << llendl;
+            rv = false;
 		}
-		cat->setPreferredType(preferred_type);
-		skel = (*it).find("version");
-		if(skel == no_response) goto clean_cat;
-		cat->setVersion(atoi((*skel).second.c_str()));
-		temp_cats.insert(cat);
-		continue;
-	clean_cat:
-		llwarns << "Unable to import near " << cat->getName() << llendl;
-		rv = false;
-		//delete cat; // automatic when cat is reasigned or destroyed
 	}
 
 	S32 cached_category_count = 0;
 	S32 cached_item_count = 0;
 	if(!temp_cats.empty())
 	{
+		update_map_t child_counts;
 		cat_array_t categories;
 		item_array_t items;
 		cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
@@ -2241,85 +2243,84 @@ bool LLInventoryModel::loadSkeleton(
 	return rv;
 }
 
-bool LLInventoryModel::loadMeat(
-	const LLInventoryModel::options_t& options, const LLUUID& owner_id)
+bool LLInventoryModel::loadMeat(const LLSD& options, const LLUUID& owner_id)
 {
 	llinfos << "importing inventory for " << owner_id << llendl;
-	LLPermissions default_perm;
-	default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null);
-	LLPointer<LLViewerInventoryItem> item;
-	LLUUID id;
-	LLAssetType::EType type;
-	LLInventoryType::EType inv_type;
 	bool rv = true;
-	for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
-	{
-		item = new LLViewerInventoryItem;
-		response_t::const_iterator no_response = (*it).end();
-		response_t::const_iterator meat;
-		meat = (*it).find("name");
-		if(meat == no_response) goto clean_item;
-		item->rename(std::string((*meat).second));
-		meat = (*it).find("item_id");
-		if(meat == no_response) goto clean_item;
-		id.set((*meat).second);
-		item->setUUID(id);
-		meat = (*it).find("parent_id");
-		if(meat == no_response) goto clean_item;
-		id.set((*meat).second);
-		item->setParent(id);
-		meat = (*it).find("type");
-		if(meat == no_response) goto clean_item;
-		type = (LLAssetType::EType)atoi((*meat).second.c_str());
-		item->setType(type);
-		meat = (*it).find("inv_type");
-		if(meat != no_response)
-		{
-			inv_type = (LLInventoryType::EType)atoi((*meat).second.c_str());
-			item->setInventoryType(inv_type);
-		}
-		meat = (*it).find("data_id");
-		if(meat == no_response) goto clean_item;
-		id.set((*meat).second);
-		if(LLAssetType::AT_CALLINGCARD == type)
-		{
-			LLPermissions perm;
-			perm.init(id, owner_id, LLUUID::null, LLUUID::null);
-			item->setPermissions(perm);
+	for(LLSD::array_const_iterator it = options.beginArray(),
+		end = options.endArray(); it != end; ++it)
+	{
+		LLSD name = (*it)["name"];
+		LLSD item_id = (*it)["item_id"];
+		LLSD parent_id = (*it)["parent_id"];
+		LLSD asset_type = (*it)["type"];
+		LLSD data_id = (*it)["data_id"];
+		if(name.isDefined() 
+			&& item_id.isDefined()
+			&& parent_id.isDefined()
+			&& asset_type.isDefined()
+			&& data_id.isDefined())
+		{
+			LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem;
+			item->rename(name.asString());
+			item->setUUID(item_id.asUUID());
+			item->setParent(parent_id.asUUID());
+			LLAssetType::EType type = (LLAssetType::EType)asset_type.asInteger();
+            item->setType(type);
+
+			LLSD llsd_inv_type = (*it)["inv_type"];
+			if(llsd_inv_type.isDefined())
+            {
+				LLInventoryType::EType inv_type = (LLInventoryType::EType)llsd_inv_type.asInteger();
+                item->setInventoryType(inv_type);
+            }
+
+            if(LLAssetType::AT_CALLINGCARD == type)
+            {
+                LLPermissions perm;
+				perm.init(data_id.asUUID(), owner_id, LLUUID::null, LLUUID::null);
+                item->setPermissions(perm);
+            }
+            else
+            {
+				LLPermissions default_perm;
+				default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null);
+				LLSD llsd_perm_mask = (*it)["perm_mask"];
+				if(llsd_perm_mask.isDefined())
+                {
+					PermissionMask perm_mask = llsd_perm_mask.asInteger();
+					default_perm.initMasks(
+						perm_mask, perm_mask, perm_mask, perm_mask, perm_mask);
+				}
+				else
+				{
+					default_perm.initMasks(
+						PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE);
+				}
+				item->setPermissions(default_perm);
+				item->setAssetUUID(data_id.asUUID());
+            }
+
+			LLSD flags = (*it)["flags"];
+			if(flags.isDefined())
+            {
+				// Not sure how well LLSD.asInteger() maps to 
+				// unsigned long - using strtoul()
+				item->setFlags(strtoul(flags.asString().c_str(), NULL, 0));
+            }
+
+			LLSD time = (*it)["time"];
+			if(time.isDefined())
+            {
+				item->setCreationDate(time.asInteger());
+            }
+            addItem(item);
 		}
 		else
 		{
-			meat = (*it).find("perm_mask");
-			if(meat != no_response)
-			{
-				PermissionMask perm_mask = atoi((*meat).second.c_str());
-				default_perm.initMasks(
-					perm_mask, perm_mask, perm_mask, perm_mask, perm_mask);
-			}
-			else
-			{
-				default_perm.initMasks(
-					PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE);
-			}
-			item->setPermissions(default_perm);
-			item->setAssetUUID(id);
-		}
-		meat = (*it).find("flags");
-		if(meat != no_response)
-		{
-			item->setFlags(strtoul((*meat).second.c_str(), NULL, 0));
-		}
-		meat = (*it).find("time");
-		if(meat != no_response)
-		{
-			item->setCreationDate(atoi((*meat).second.c_str()));
+			llwarns << "Unable to import near " << name.asString() << llendl;
+            rv = false;
 		}
-		addItem(item);
-		continue;
-	clean_item:
-		llwarns << "Unable to import near " << item->getName() << llendl;
-		rv = false;
-		//delete item; // automatic when item is reassigned or destroyed
 	}
 	return rv;
 }
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index c2d8717b709f4e310566e0b212a17172236ab5f7..d51460b374c67aea7144e8b287fa63c596189cc9 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -112,7 +112,9 @@ class LLInventoryModel
 	// construction & destruction
 	LLInventoryModel();
 	~LLInventoryModel();
-
+	
+	void cleanupInventory();
+	
 	class fetchInventoryResponder : public LLHTTPClient::Responder
 	{
 	public:
@@ -332,10 +334,8 @@ class LLInventoryModel
 
 	// methods to load up inventory skeleton & meat. These are used
 	// during authentication. return true if everything parsed.
-	typedef std::map<std::string, std::string> response_t;
-	typedef std::vector<response_t> options_t;
-	bool loadSkeleton(const options_t& options, const LLUUID& owner_id);
-	bool loadMeat(const options_t& options, const LLUUID& owner_id);
+	bool loadSkeleton(const LLSD& options, const LLUUID& owner_id);
+	bool loadMeat(const LLSD& options, const LLUUID& owner_id);
 
 	// This is a brute force method to rebuild the entire parent-child
 	// relations.
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index b36b7cf50ed3f137e46671aea4fcfd7a43c0f634..0b07dd4f21212785ed9eac924705c957aa27b592 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -133,6 +133,33 @@ use_substring(if_use_substring)
 	}
 };
 
+// Returns true if the given inventory item is a landmark pointing to the current parcel.
+// Used to find out if there is at least one landmark from current parcel.
+class LLFistAgentParcelLandmark : public LLInventoryCollectFunctor
+{
+private:	
+	bool mFounded;// to avoid unnecessary  check
+	
+public:
+	LLFistAgentParcelLandmark(): mFounded(false){}
+	
+	/*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+	{
+		if (mFounded || !item || item->getType() != LLAssetType::AT_LANDMARK)
+			return false;
+
+		LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
+		if (!landmark) // the landmark not been loaded yet
+			return false;
+
+		LLVector3d landmark_global_pos;
+		if (!landmark->getGlobalPos(landmark_global_pos))
+			return false;
+		mFounded = LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos);
+		return mFounded;
+	}
+};
+
 static void fetch_landmarks(LLInventoryModel::cat_array_t& cats,
 							LLInventoryModel::item_array_t& items,
 							LLInventoryCollectFunctor& add)
@@ -172,6 +199,16 @@ bool LLLandmarkActions::landmarkAlreadyExists()
 	return findLandmarkForAgentPos() != NULL;
 }
 
+//static
+bool LLLandmarkActions::hasParcelLandmark()
+{
+	LLFistAgentParcelLandmark get_first_agent_landmark;
+	LLInventoryModel::cat_array_t cats;
+	LLInventoryModel::item_array_t items;
+	fetch_landmarks(cats, items, get_first_agent_landmark);
+	return !items.empty();
+	
+}
 
 // *TODO: This could be made more efficient by only fetching the FIRST
 // landmark that meets the criteria
@@ -348,7 +385,7 @@ LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID
 {
 	LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
 	if (NULL == item)
-		return false;
+		return NULL;
 
 	const LLUUID& asset_id = item->getAssetUUID();
 	return gLandmarkList.getAsset(asset_id, NULL);
diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h
index d6512597908a67f8aa13a6f206a0fe5f26810713..312426cab01c4d0632348cbe5e935dd4370b3df3 100644
--- a/indra/newview/lllandmarkactions.h
+++ b/indra/newview/lllandmarkactions.h
@@ -50,9 +50,14 @@ class LLLandmarkActions
 	 */
 	static LLInventoryModel::item_array_t fetchLandmarksByName(std::string& name, BOOL if_use_substring);
 	/**
-	 * @brief Checks whether landmark exists for current parcel.
+	 * @brief Checks whether landmark exists for current agent position.
 	 */
 	static bool landmarkAlreadyExists();
+	
+	/**
+	 * @brief Checks whether landmark exists for current parcel.
+	 */
+	static bool hasParcelLandmark();
 
 	/**
 	 * @brief Searches landmark for global position.
@@ -108,7 +113,7 @@ class LLLandmarkActions
     /**
      * @brief Retrieve a landmark from gLandmarkList by inventory item's id
      * 
-     * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist.
+     * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist or wasn't loaded.
      */
     static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID);
 
diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index 2e8084759a2955ce74efd0acb6e07b6dbb5d8432..83e694951b56a0ba08a9cc63027f53bf517dc335 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -37,6 +37,7 @@
 #include "message.h"
 #include "llassetstorage.h"
 
+#include "llappviewer.h"
 #include "llagent.h"
 #include "llnotify.h"
 #include "llvfile.h"
@@ -63,20 +64,32 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
 	}
 	else
 	{
-	    if ( gLandmarkList.mBadList.find(asset_uuid) == gLandmarkList.mBadList.end() )
+	    if ( mBadList.find(asset_uuid) != mBadList.end() )
 		{
-			if (cb)
+			return NULL;
+		}
+		
+		landmark_requested_list_t::iterator iter = mRequestedList.find(asset_uuid);
+		if (iter != mRequestedList.end())
+		{
+			const F32 rerequest_time = 30.f; // 30 seconds between requests
+			if (gFrameTimeSeconds - iter->second < rerequest_time)
 			{
-				loaded_callback_map_t::value_type vt(asset_uuid, cb);
-				mLoadedCallbackMap.insert(vt);
+				return NULL;
 			}
-
-			gAssetStorage->getAssetData(
-				asset_uuid,
-				LLAssetType::AT_LANDMARK,
-				LLLandmarkList::processGetAssetReply,
-				NULL);
 		}
+		
+		if (cb)
+		{
+			loaded_callback_map_t::value_type vt(asset_uuid, cb);
+			mLoadedCallbackMap.insert(vt);
+		}
+
+		gAssetStorage->getAssetData(asset_uuid,
+									LLAssetType::AT_LANDMARK,
+									LLLandmarkList::processGetAssetReply,
+									NULL);
+		mRequestedList[asset_uuid] = gFrameTimeSeconds;
 	}
 	return NULL;
 }
@@ -103,7 +116,8 @@ void LLLandmarkList::processGetAssetReply(
 		if (landmark)
 		{
 			gLandmarkList.mList[ uuid ] = landmark;
-
+			gLandmarkList.mRequestedList.erase(uuid);
+			
 			LLVector3d pos;
 			if(!landmark->getGlobalPos(pos))
 			{
diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h
index ebf1b65e9755569e80407565b68d56234b88d406..d9c326714236d87263bd9abb3b4e8a4e677f508d 100644
--- a/indra/newview/lllandmarklist.h
+++ b/indra/newview/lllandmarklist.h
@@ -74,7 +74,10 @@ class LLLandmarkList
 
 	typedef std::set<LLUUID> landmark_bad_list_t;
 	landmark_bad_list_t mBadList;
-
+	
+	typedef std::map<LLUUID,F32> landmark_requested_list_t;
+	landmark_requested_list_t mRequestedList;
+	
 	// *TODO: make the callback multimap a template class and make use of it
 	// here and in LLLandmark.
 	typedef std::multimap<LLUUID, loaded_callback_t> loaded_callback_map_t;
diff --git a/indra/newview/lllocaltextureobject.cpp b/indra/newview/lllocaltextureobject.cpp
index 0bd3e425567b005c7cb036676f1a4d9396d894c7..6bcbe6f58ca1304797dcb7e2c3cbe010e2926633 100644
--- a/indra/newview/lllocaltextureobject.cpp
+++ b/indra/newview/lllocaltextureobject.cpp
@@ -47,7 +47,7 @@ LLLocalTextureObject::LLLocalTextureObject() :
 	mImage = NULL;
 }
 
-LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, LLUUID& id)
+LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id)
 {
 	mImage = image;
 	gGL.getTexUnit(0)->bind(mImage);
diff --git a/indra/newview/lllocaltextureobject.h b/indra/newview/lllocaltextureobject.h
index 461756ee461f0a8fe8a344574ea68c93ce5fae23..c8b8aa924be730320fd1376d7c619c2a8c3ab945 100644
--- a/indra/newview/lllocaltextureobject.h
+++ b/indra/newview/lllocaltextureobject.h
@@ -35,7 +35,8 @@
 
 #include <boost/shared_ptr.hpp>
 
-class LLViewerFetchedTexture;
+#include "llviewertexture.h"
+
 class LLUUID;
 class LLTexLayer;
 class LLTextureEntry;
@@ -49,7 +50,7 @@ class LLLocalTextureObject
 {
 public:
 	LLLocalTextureObject();
-	LLLocalTextureObject(LLViewerFetchedTexture* image, LLUUID& id);
+	LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id);
 	LLLocalTextureObject(const LLLocalTextureObject& lto);
 	~LLLocalTextureObject();
 
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 00f12ae2eb89bb63c29ca6e53f4ec0954645d500..8fe317a2921543a740dadb48aec5593526aa8773 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -294,6 +294,11 @@ void LLLocationInputCtrl::hideList()
 
 BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, MASK mask)
 {
+
+	if(mAddLandmarkBtn->parentPointInView(x,y))
+	{
+		updateAddLandmarkTooltip();
+	}
 	// Let the buttons show their tooltips.
 	if (LLUICtrl::handleToolTip(x, y, mask))
 	{
@@ -602,11 +607,12 @@ void LLLocationInputCtrl::enableAddLandmarkButton(bool val)
 // depending on whether current parcel has been landmarked.
 void LLLocationInputCtrl::updateAddLandmarkButton()
 {
-	bool landmark_exists = LLLandmarkActions::landmarkAlreadyExists();
-	enableAddLandmarkButton(!landmark_exists);
-
+	enableAddLandmarkButton(LLLandmarkActions::hasParcelLandmark());
+}
+void LLLocationInputCtrl::updateAddLandmarkTooltip()
+{
 	std::string tooltip;
-	if(landmark_exists)
+	if(LLLandmarkActions::landmarkAlreadyExists())
 	{
 		tooltip = mEditLandmarkTooltip;
 	}
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
index c74a294ca373a8ec12e484a850bbe1f425e13fcb..44dc0cb2510bf3abc96cfe87b7cb9d90dd5e0ee9 100644
--- a/indra/newview/lllocationinputctrl.h
+++ b/indra/newview/lllocationinputctrl.h
@@ -107,6 +107,7 @@ class LLLocationInputCtrl
 	bool 					findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter);
 	void					setText(const LLStringExplicit& text);
 	void					updateAddLandmarkButton();
+	void 					updateAddLandmarkTooltip();
 	void 					updateContextMenu();
 	void					updateWidgetlayout();
 	void					changeLocationPresentation();
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 69214b5cab565e3e499f092d226205de578173f0..a16ffe19c6de4bdaa4a381a2cd3c006370f7ae96 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -36,6 +36,8 @@
 #include "llappviewer.h"
 #include "llfloaterchat.h"
 #include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llsdserialize.h"
 
 const S32 LOG_RECALL_SIZE = 2048;
 
@@ -89,41 +91,53 @@ std::string LLLogChat::timestamp(bool withdate)
 
 
 //static
-void LLLogChat::saveHistory(std::string filename, std::string line)
+void LLLogChat::saveHistory(const std::string& filename,
+			    const std::string& from,
+			    const LLUUID& from_id,
+			    const std::string& line)
 {
+	if (!gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
+		return;
+
 	if(!filename.size())
 	{
 		llinfos << "Filename is Empty!" << llendl;
 		return;
 	}
 
-	LLFILE* fp = LLFile::fopen(LLLogChat::makeLogFileName(filename), "a"); 		/*Flawfinder: ignore*/
-	if (!fp)
+	llofstream file (LLLogChat::makeLogFileName(filename), std::ios_base::app);
+	if (!file.is_open())
 	{
 		llinfos << "Couldn't open chat history log!" << llendl;
+		return;
 	}
-	else
-	{
-		fprintf(fp, "%s\n", line.c_str());
-		
-		fclose (fp);
-	}
+
+	LLSD item;
+
+	if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
+		 item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
+
+	item["from"]	= from;
+	item["from_id"]	= from_id;
+	item["message"]	= line;
+
+	file << LLSDOStreamer <LLSDNotationFormatter>(item) << std::endl;
+
+	file.close();
 }
 
-void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType,std::string,void*), void* userdata)
+void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata)
 {
 	if(!filename.size())
 	{
 		llwarns << "Filename is Empty!" << llendl;
 		return ;
 	}
-
+        
 	LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r");		/*Flawfinder: ignore*/
 	if (!fptr)
 	{
-		//LLUIString message = LLTrans::getString("IM_logging_string");
-		//callback(LOG_EMPTY,"IM_logging_string",userdata);
-		callback(LOG_EMPTY,LLStringUtil::null,userdata);
+		callback(LOG_EMPTY, LLSD(), userdata);
 		return;			//No previous conversation with this name.
 	}
 	else
@@ -143,6 +157,9 @@ void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType
 			}
 		}
 
+		// the parser's destructor is protected so we cannot create in the stack.
+		LLPointer<LLSDParser> parser = new LLSDNotationParser();
+
 		while ( fgets(buffer, LOG_RECALL_SIZE, fptr)  && !feof(fptr) ) 
 		{
 			len = strlen(buffer) - 1;		/*Flawfinder: ignore*/
@@ -150,14 +167,25 @@ void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType
 			
 			if (!firstline)
 			{
-				callback(LOG_LINE,std::string(buffer),userdata);
+				LLSD item;
+				std::string line(buffer);
+				std::istringstream iss(line);
+				if (parser->parse(iss, item, line.length()) == LLSDParser::PARSE_FAILURE)
+				{
+					item["message"]	= line;
+					callback(LOG_LINE, item, userdata);
+				}
+				else
+				{
+					callback(LOG_LLSD, item, userdata);
+				}
 			}
 			else
 			{
 				firstline = FALSE;
 			}
 		}
-		callback(LOG_END,LLStringUtil::null,userdata);
+		callback(LOG_END, LLSD(), userdata);
 		
 		fclose(fptr);
 	}
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index ad903b66fe7ec1fc4c2f67f161a3217ec19b780b..e252cd7d41c87d82a818354c058c6912d1249b09 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -41,13 +41,18 @@ class LLLogChat
 	enum ELogLineType {
 		LOG_EMPTY,
 		LOG_LINE,
+		LOG_LLSD,
 		LOG_END
 	};
 	static std::string timestamp(bool withdate = false);
 	static std::string makeLogFileName(std::string(filename));
-	static void saveHistory(std::string filename, std::string line);
-	static void loadHistory(std::string filename, 
-		                    void (*callback)(ELogLineType,std::string,void*), 
+	static void saveHistory(const std::string& filename,
+				const std::string& from,
+				const LLUUID& from_id,
+				const std::string& line);
+
+	static void loadHistory(const std::string& filename, 
+		                    void (*callback)(ELogLineType, const LLSD&, void*), 
 							void* userdata);
 private:
 	static std::string cleanFileName(std::string filename);
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e5f347ddc404696933b6ccc7e78840d67268670d
--- /dev/null
+++ b/indra/newview/lllogininstance.cpp
@@ -0,0 +1,475 @@
+/** 
+ * @file lllogininstance.cpp
+ * @brief Viewer's host for a login connection.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lllogininstance.h"
+
+// llcommon
+#include "llevents.h"
+#include "llmd5.h"
+#include "stringize.h"
+
+// llmessage (!)
+#include "llfiltersd2xmlrpc.h" // for xml_escape_string()
+
+// login
+#include "lllogin.h"
+
+// newview
+#include "llviewernetwork.h"
+#include "llviewercontrol.h"
+#include "llurlsimstring.h"
+#include "llfloaterreg.h"
+#include "llnotifications.h"
+#include "llwindow.h"
+#if LL_LINUX || LL_SOLARIS
+#include "lltrans.h"
+#endif
+
+static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback";
+static const char * const TOS_LISTENER_NAME = "lllogininstance_tos";
+
+std::string construct_start_string();
+
+LLLoginInstance::LLLoginInstance() :
+	mLoginModule(new LLLogin()),
+	mNotifications(NULL),
+	mLoginState("offline"),
+	mUserInteraction(true),
+	mSkipOptionalUpdate(false),
+	mAttemptComplete(false),
+	mTransferRate(0.0f),
+	mDispatcher("LLLoginInstance", "change")
+{
+	mLoginModule->getEventPump().listen("lllogininstance", 
+		boost::bind(&LLLoginInstance::handleLoginEvent, this, _1));
+	mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1));
+	mDispatcher.add("connect",    boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1));
+	mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1));
+}
+
+LLLoginInstance::~LLLoginInstance()
+{
+}
+
+void LLLoginInstance::connect(const LLSD& credentials)
+{
+	std::vector<std::string> uris;
+	LLViewerLogin::getInstance()->getLoginURIs(uris);
+	connect(uris.front(), credentials);
+}
+
+void LLLoginInstance::connect(const std::string& uri, const LLSD& credentials)
+{
+	mAttemptComplete = false; // Reset attempt complete at this point!
+	constructAuthParams(credentials);
+	mLoginModule->connect(uri, mRequestData);
+}
+
+void LLLoginInstance::reconnect()
+{
+	// Sort of like connect, only using the pre-existing
+	// request params.
+	std::vector<std::string> uris;
+	LLViewerLogin::getInstance()->getLoginURIs(uris);
+	mLoginModule->connect(uris.front(), mRequestData);
+}
+
+void LLLoginInstance::disconnect()
+{
+	mAttemptComplete = false; // Reset attempt complete at this point!
+	mRequestData.clear();
+	mLoginModule->disconnect();
+}
+
+LLSD LLLoginInstance::getResponse() 
+{
+	return mResponseData; 
+}
+
+void LLLoginInstance::constructAuthParams(const LLSD& credentials)
+{
+	// Set up auth request options.
+//#define LL_MINIMIAL_REQUESTED_OPTIONS
+	LLSD requested_options;
+	// *Note: this is where gUserAuth used to be created.
+	requested_options.append("inventory-root");
+	requested_options.append("inventory-skeleton");
+	//requested_options.append("inventory-meat");
+	//requested_options.append("inventory-skel-targets");
+#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS)
+	if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary"))
+	{
+		requested_options.append("inventory-lib-root");
+		requested_options.append("inventory-lib-owner");
+		requested_options.append("inventory-skel-lib");
+	//	requested_options.append("inventory-meat-lib");
+	}
+
+	requested_options.append("initial-outfit");
+	requested_options.append("gestures");
+	requested_options.append("event_categories");
+	requested_options.append("event_notifications");
+	requested_options.append("classified_categories");
+	requested_options.append("adult_compliant"); 
+	//requested_options.append("inventory-targets");
+	requested_options.append("buddy-list");
+	requested_options.append("ui-config");
+#endif
+	requested_options.append("tutorial_setting");
+	requested_options.append("login-flags");
+	requested_options.append("global-textures");
+	if(gSavedSettings.getBOOL("ConnectAsGod"))
+	{
+		gSavedSettings.setBOOL("UseDebugMenus", TRUE);
+		requested_options.append("god-connect");
+	}
+
+	char hashed_mac_string[MD5HEX_STR_SIZE];		/* Flawfinder: ignore */
+	LLMD5 hashed_mac;
+	hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES );
+	hashed_mac.finalize();
+	hashed_mac.hex_digest(hashed_mac_string);
+
+	// prepend "$1$" to the password to indicate its the md5'd version.
+	std::string dpasswd("$1$");
+	dpasswd.append(credentials["passwd"].asString());
+
+	// (re)initialize the request params with creds.
+	LLSD request_params(credentials);
+	request_params["passwd"] = dpasswd;
+	request_params["start"] = construct_start_string();
+	request_params["skipoptional"] = mSkipOptionalUpdate;
+	request_params["agree_to_tos"] = false; // Always false here. Set true in 
+	request_params["read_critical"] = false; // handleTOSResponse
+	request_params["last_exec_event"] = mLastExecEvent;
+	request_params["mac"] = hashed_mac_string;
+	request_params["version"] = gCurrentVersion; // Includes channel name
+	request_params["channel"] = gSavedSettings.getString("VersionChannelName");
+	request_params["id0"] = mSerialNumber;
+
+	mRequestData.clear();
+	mRequestData["method"] = "login_to_simulator";
+	mRequestData["params"] = request_params;
+	mRequestData["options"] = requested_options;
+}
+
+bool LLLoginInstance::handleLoginEvent(const LLSD& event)
+{
+	std::cout << "LoginListener called!: \n";
+	std::cout << event << "\n";
+
+	if(!(event.has("state") && event.has("change") && event.has("progress")))
+	{
+		llerrs << "Unknown message from LLLogin: " << event << llendl;
+	}
+
+	mLoginState = event["state"].asString();
+	mResponseData = event["data"];
+	
+	if(event.has("transfer_rate"))
+	{
+		mTransferRate = event["transfer_rate"].asReal();
+	}
+
+	// Call the method registered in constructor, if any, for more specific
+	// handling
+	LLEventDispatcher::Callable method(mDispatcher.get(event["change"]));
+	if (! method.empty())
+	{
+		method(event);
+	}
+	return false;
+}
+
+void LLLoginInstance::handleLoginFailure(const LLSD& event)
+{
+	// Login has failed. 
+	// Figure out why and respond...
+	LLSD response = event["data"];
+	std::string reason_response = response["reason"].asString();
+	std::string message_response = response["message"].asString();
+	if(mUserInteraction)
+	{
+		// For the cases of critical message or TOS agreement,
+		// start the TOS dialog. The dialog response will be handled
+		// by the LLLoginInstance::handleTOSResponse() callback.
+		// The callback intiates the login attempt next step, either 
+		// to reconnect or to end the attempt in failure.
+		if(reason_response == "tos")
+		{
+			LLSD data(LLSD::emptyMap());
+			data["message"] = message_response;
+			data["reply_pump"] = TOS_REPLY_PUMP;
+			LLFloaterReg::showInstance("message_tos", data);
+			LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
+				.listen(TOS_LISTENER_NAME,
+						boost::bind(&LLLoginInstance::handleTOSResponse, 
+									this, _1, "agree_to_tos"));
+		}
+		else if(reason_response == "critical")
+		{
+			LLSD data(LLSD::emptyMap());
+			data["message"] = message_response;
+			data["reply_pump"] = TOS_REPLY_PUMP;
+			LLFloaterReg::showInstance("message_critical", data);
+			LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
+				.listen(TOS_LISTENER_NAME,
+						boost::bind(&LLLoginInstance::handleTOSResponse, 
+									this, _1, "read_critical"));
+		}
+		else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate"))
+		{
+			gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
+			updateApp(true, message_response);
+		}
+		else if(reason_response == "optional")
+		{
+			updateApp(false, message_response);
+		}
+		else
+		{	
+			attemptComplete();
+		}	
+	}
+	else // no user interaction
+	{
+		attemptComplete();
+	}
+}
+
+void LLLoginInstance::handleLoginSuccess(const LLSD& event)
+{
+	if(gSavedSettings.getBOOL("ForceMandatoryUpdate"))
+	{
+		LLSD response = event["data"];
+		std::string message_response = response["message"].asString();
+
+		// Testing update...
+		gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
+
+		// Don't confuse startup by leaving login "online".
+		mLoginModule->disconnect(); 
+		updateApp(true, message_response);
+	}
+	else
+	{
+		attemptComplete();
+	}
+}
+
+void LLLoginInstance::handleDisconnect(const LLSD& event)
+{
+    // placeholder
+}
+
+bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
+{
+	if(accepted)
+	{	
+		// Set the request data to true and retry login.
+		mRequestData["params"][key] = true; 
+		reconnect();
+	}
+	else
+	{
+		attemptComplete();
+	}
+
+	LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME);
+	return true;
+}
+
+
+void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)
+{
+	// store off config state, as we might quit soon
+	gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);	
+	LLUIColorTable::instance().saveUserSettings();
+
+	std::ostringstream message;
+	std::string msg;
+	if (!auth_msg.empty())
+	{
+		msg = "(" + auth_msg + ") \n";
+	}
+
+	LLSD args;
+	args["MESSAGE"] = msg;
+	
+	LLSD payload;
+	payload["mandatory"] = mandatory;
+
+/*
+ We're constructing one of the following 6 strings here:
+	 "DownloadWindowsMandatory"
+	 "DownloadWindowsReleaseForDownload"
+	 "DownloadWindows"
+	 "DownloadMacMandatory"
+	 "DownloadMacReleaseForDownload"
+	 "DownloadMac"
+ 
+ I've called them out explicitly in this comment so that they can be grepped for.
+ 
+ Also, we assume that if we're not Windows we're Mac. If we ever intend to support 
+ Linux with autoupdate, this should be an explicit #elif LL_DARWIN, but 
+ we'd rather deliver the wrong message than no message, so until Linux is supported
+ we'll leave it alone.
+ */
+	std::string notification_name = "Download";
+	
+#if LL_WINDOWS
+	notification_name += "Windows";
+#elif LL_DARWIN
+	notification_name += "Mac";
+#else
+	notification_name += "Linux";
+#endif
+	
+	if (mandatory)
+	{
+		notification_name += "Mandatory";
+	}
+	else
+	{
+#if LL_RELEASE_FOR_DOWNLOAD
+		notification_name += "ReleaseForDownload";
+#endif
+	}
+
+	if(mNotifications)
+	{
+		mNotifications->add(notification_name, args, payload, 
+			boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2));
+	}
+
+	/* *NOTE:Mani Experiment with Event API interface.
+	if(!mUpdateAppResponse)
+	{
+		bool make_unique = true;
+		mUpdateAppResponse.reset(new LLEventStream("logininstance_updateapp", make_unique));
+		mUpdateAppResponse->listen("diaupdateDialogCallback", 
+								   boost::bind(&LLLoginInstance::updateDialogCallback,
+								 			   this, _1
+											   )
+								   );
+	}
+
+	LLSD event;
+	event["op"] = "requestAdd";
+	event["name"] = notification_name;
+	event["substitutions"] = args;
+	event["payload"] = payload;
+	event["reply"] = mUpdateAppResponse->getName();
+
+	LLEventPumps::getInstance()->obtain("LLNotifications").post(event);
+	*/
+}
+
+bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotification::getSelectedOption(notification, response);
+	std::string update_exe_path;
+	bool mandatory = notification["payload"]["mandatory"].asBoolean();
+
+#if !LL_RELEASE_FOR_DOWNLOAD
+	if (option == 2)
+	{
+		// This condition attempts to skip the 
+		// update if using a dev build.
+		// The relog probably won't work if the 
+		// update is mandatory. :)
+
+	    // *REMOVE:Mani - Saving for reference...
+		//LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); 
+		mSkipOptionalUpdate = true;
+		reconnect();
+		return false;
+	}
+#endif
+
+	if (option == 1)
+	{
+		// ...user doesn't want to do it
+		if (mandatory)
+		{
+			// Mandatory update, user chose to not to update...
+			// The login attemp is complete, startup should 
+			// quit when detecting this.
+			attemptComplete();
+
+			// *REMOVE:Mani - Saving for reference...
+			//LLAppViewer::instance()->forceQuit();
+			// // Bump them back to the login screen.
+			// //reset_login();
+		}
+		else
+		{
+			// Optional update, user chose to skip
+			mSkipOptionalUpdate = true;
+			reconnect();
+		}
+		return false;
+	}
+	
+ 	if(mUpdaterLauncher)
+  	{
+ 		mUpdaterLauncher();
+  	}
+  
+ 	attemptComplete();
+
+	return false;
+}
+
+std::string construct_start_string()
+{
+	std::string start;
+	if (LLURLSimString::parse())
+	{
+		// a startup URL was specified
+		std::string unescaped_start = 
+			STRINGIZE(  "uri:" 
+						<< LLURLSimString::sInstance.mSimName << "&" 
+						<< LLURLSimString::sInstance.mX << "&" 
+						<< LLURLSimString::sInstance.mY << "&" 
+						<< LLURLSimString::sInstance.mZ);
+		start = xml_escape_string(unescaped_start);
+	}
+	else
+	{
+		start = gSavedSettings.getString("LoginLocation");
+	}
+	return start;
+}
+
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
new file mode 100644
index 0000000000000000000000000000000000000000..19d7449bc15bfc7eef3af996c3e7667e014ecbde
--- /dev/null
+++ b/indra/newview/lllogininstance.h
@@ -0,0 +1,114 @@
+/** 
+ * @file lllogininstance.h
+ * @brief A host for the viewer's login connection.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLLOGININSTANCE_H
+#define LL_LLLOGININSTANCE_H
+
+#include "lleventdispatcher.h"
+#include <boost/scoped_ptr.hpp>
+#include <boost/function.hpp>
+class LLLogin;
+class LLEventStream;
+class LLNotificationsInterface;
+
+// This class hosts the login module and is used to 
+// negotiate user authentication attempts.
+class LLLoginInstance : public LLSingleton<LLLoginInstance>
+{
+public:
+	LLLoginInstance();
+	~LLLoginInstance();
+
+	void connect(const LLSD& credential); // Connect to the current grid choice.
+	void connect(const std::string& uri, const LLSD& credential);	// Connect to the given uri.
+	void reconnect(); // reconnect using the current credentials.
+	void disconnect();
+
+	bool authFailure() { return mAttemptComplete && mLoginState == "offline"; }
+	bool authSuccess() { return mAttemptComplete && mLoginState == "online"; }
+
+	const std::string& getLoginState() { return mLoginState; }
+	LLSD getResponse(const std::string& key) { return getResponse()[key]; }
+	LLSD getResponse();
+
+	// Only valid when authSuccess == true.
+	const F64 getLastTransferRateBPS() { return mTransferRate; }
+
+		// Set whether this class will drive user interaction.
+	// If not, login failures like 'need tos agreement' will 
+	// end the login attempt.
+	void setUserInteraction(bool state) { mUserInteraction = state; } 
+	bool getUserInteraction() { return mUserInteraction; }
+
+	// Whether to tell login to skip optional update request.
+	// False by default.
+	void setSkipOptionalUpdate(bool state) { mSkipOptionalUpdate = state; }
+	void setSerialNumber(const std::string& sn) { mSerialNumber = sn; }
+	void setLastExecEvent(int lee) { mLastExecEvent = lee; }
+
+	void setNotificationsInterface(LLNotificationsInterface* ni) { mNotifications = ni; }
+
+	typedef boost::function<void()> UpdaterLauncherCallback;
+	void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; }
+
+private:
+	void constructAuthParams(const LLSD& credentials); 
+	void updateApp(bool mandatory, const std::string& message);
+	bool updateDialogCallback(const LLSD& notification, const LLSD& response);
+
+	bool handleLoginEvent(const LLSD& event);
+	void handleLoginFailure(const LLSD& event);
+	void handleLoginSuccess(const LLSD& event);
+	void handleDisconnect(const LLSD& event);
+
+	bool handleTOSResponse(bool v, const std::string& key);
+
+	void attemptComplete() { mAttemptComplete = true; } // In the future an event?
+
+	boost::scoped_ptr<LLLogin> mLoginModule;
+	LLNotificationsInterface* mNotifications;
+
+	std::string mLoginState;
+	LLSD mRequestData;
+	LLSD mResponseData;
+	bool mUserInteraction; 
+	bool mSkipOptionalUpdate;
+	bool mAttemptComplete;
+	F64 mTransferRate;
+	std::string mSerialNumber;
+	int mLastExecEvent;
+	UpdaterLauncherCallback mUpdaterLauncher;
+	boost::scoped_ptr<LLEventStream> mUpdateAppResponse;
+	LLEventDispatcher mDispatcher;
+};
+
+#endif
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 4fa7f62c68070f9020414da96d24b905179b0621..8f29f908e5c74c70ed77e4fcd08b98320c301871 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -51,6 +51,7 @@
 #include "llpluginclassmedia.h"
 #include "llslurl.h"
 #include "lluictrlfactory.h"	// LLDefaultChildRegistry
+#include "llkeyboard.h"
 
 // linden library includes
 #include "llfocusmgr.h"
@@ -193,7 +194,7 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
 
 	if (mMediaSource)
 	{
-		mMediaSource->mouseMove(x, y);
+		mMediaSource->mouseMove(x, y, mask);
 		gViewerWindow->setCursor(mMediaSource->getLastSetCursor());
 	}
 
@@ -205,7 +206,7 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
 BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
 {
 	if (mMediaSource && mMediaSource->hasMedia())
-		mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, MASK_NONE);
+		mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE));
 
 	return TRUE;
 }
@@ -218,7 +219,7 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
 
 	if (mMediaSource)
 	{
-		mMediaSource->mouseUp(x, y);
+		mMediaSource->mouseUp(x, y, mask);
 
 		// *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
 		// in addition to the onFocusReceived() call below.  Undo this. JC
@@ -241,7 +242,50 @@ BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask )
 	convertInputCoords(x, y);
 
 	if (mMediaSource)
-		mMediaSource->mouseDown(x, y);
+		mMediaSource->mouseDown(x, y, mask);
+	
+	gFocusMgr.setMouseCapture( this );
+
+	if (mTakeFocusOnClick)
+	{
+		setFocus( TRUE );
+	}
+
+	return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask )
+{
+	convertInputCoords(x, y);
+
+	if (mMediaSource)
+	{
+		mMediaSource->mouseUp(x, y, mask, 1);
+
+		// *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
+		// in addition to the onFocusReceived() call below.  Undo this. JC
+		if (!mTakeFocusOnClick)
+		{
+			mMediaSource->focus(false);
+			gViewerWindow->focusClient();
+		}
+	}
+	
+	gFocusMgr.setMouseCapture( NULL );
+
+	return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )
+{
+	convertInputCoords(x, y);
+
+	if (mMediaSource)
+		mMediaSource->mouseDown(x, y, mask, 1);
 	
 	gFocusMgr.setMouseCapture( this );
 
@@ -260,7 +304,7 @@ BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask )
 	convertInputCoords(x, y);
 
 	if (mMediaSource)
-		mMediaSource->mouseLeftDoubleClick( x, y );
+		mMediaSource->mouseDoubleClick( x, y, mask);
 
 	gFocusMgr.setMouseCapture( this );
 
@@ -321,36 +365,9 @@ BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
 {
 	BOOL result = FALSE;
 	
-	// FIXME: THIS IS SO WRONG.
-	// Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it...
-	
 	if (mMediaSource)
 	{
-		if( MASK_CONTROL & mask )
-		{
-			if( 'C' == key )
-			{
-				mMediaSource->copy();
-				result = TRUE;
-			}
-			else
-			if( 'V' == key )
-			{
-				mMediaSource->paste();
-				result = TRUE;
-			}
-			else
-			if( 'X' == key )
-			{
-				mMediaSource->cut();
-				result = TRUE;
-			}
-		}
-		
-		if(!result)
-		{
-			result = mMediaSource->handleKeyHere(key, mask);
-		}
+		result = mMediaSource->handleKeyHere(key, mask);
 	}
 		
 	return result;
@@ -373,12 +390,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
 {
 	BOOL result = FALSE;
 	
-	// only accept 'printable' characters, sigh...
-	if (uni_char >= 32 // discard 'control' characters
-	    && uni_char != 127) // SDL thinks this is 'delete' - yuck.
+	if (mMediaSource)
 	{
-		if (mMediaSource)
-			result = mMediaSource->handleUnicodeCharHere(uni_char);
+		result = mMediaSource->handleUnicodeCharHere(uni_char);
 	}
 
 	return result;
@@ -905,6 +919,18 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
 			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
 		};
 		break;
+
+		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+		{
+			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
+		};
+		break;
+		
+		case MEDIA_EVENT_NAME_CHANGED:
+		{
+			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
+		};
+		break;
 	};
 
 	// chain all events to any potential observers of this object.
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 5ea03f1e6c0fabae03edb15552255306e0af2272..76ddc61ebf28ec285f07f32b1f9e0a2d48362702 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -86,6 +86,8 @@ class LLMediaCtrl :
 		virtual BOOL handleHover( S32 x, S32 y, MASK mask );
 		virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );
 		virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
+		virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+		virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
 		virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
 		virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
 
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index 6a932d76bfd3645b88dfa6cfe1482a0cea7ac9c8..512104a2f420e0b43a14bfa7be77e852dc72ac0f 100755
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -34,15 +34,18 @@
 
 #include "llmediadataclient.h"
 
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
 #include <boost/lexical_cast.hpp>
 
 #include "llhttpstatuscodes.h"
-#include "llnotifications.h"
 #include "llsdutil.h"
 #include "llmediaentry.h"
 #include "lltextureentry.h"
 #include "llviewerregion.h"
-#include "llvovolume.h"
 
 //
 // When making a request
@@ -55,7 +58,9 @@
 // - Any request that gets a 503 still goes through the retry logic
 //
 
-// Some helpful logging macros
+const F32 LLMediaDataClient::QUEUE_TIMER_DELAY = 1.0; // seconds(s)
+const F32 LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY = 5.0; // secs
+const U32 LLMediaDataClient::MAX_RETRIES = 4;
 
 //////////////////////////////////////////////////////////////////////////////////////
 //
@@ -66,7 +71,7 @@
 
 LLMediaDataClient::Request::Request(const std::string &cap_name, 
 									const LLSD& sd_payload,
-									LLVOVolume *obj, 
+									LLMediaDataClientObject *obj, 
 									LLMediaDataClient *mdc)
 	: mCapName(cap_name), 
 	  mPayload(sd_payload), 
@@ -79,38 +84,39 @@ LLMediaDataClient::Request::Request(const std::string &cap_name,
 
 LLMediaDataClient::Request::~Request()
 {
+	LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL;
 	mMDC = NULL;
-    mObject = NULL;
+	mObject = NULL;
 }
 
 													  
 std::string LLMediaDataClient::Request::getCapability() const
 {
-	return getObject()->getRegion()->getCapability(getCapName());
+	return getObject()->getCapabilityUrl(getCapName());
 }
 
 // Helper function to get the "type" of request, which just pokes around to
 // discover it.
 LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const
 {
-    if (mCapName == "ObjectMediaNavigate")
-    {
-        return NAVIGATE;
-    }
-    else if (mCapName == "ObjectMedia")
-    {
-        const std::string &verb = mPayload["verb"];
-        if (verb == "GET")
-        {
-            return GET;
-        }
-        else if (verb == "UPDATE")
-        {
-            return UPDATE;
-        }
-    }
-    llassert(false);
-    return GET;
+	if (mCapName == "ObjectMediaNavigate")
+	{
+		return NAVIGATE;
+	}
+	else if (mCapName == "ObjectMedia")
+	{
+		const std::string &verb = mPayload["verb"];
+		if (verb == "GET")
+		{
+			return GET;
+		}
+		else if (verb == "UPDATE")
+		{
+			return UPDATE;
+		}
+	}
+	llassert(false);
+	return GET;
 }
 
 const char *LLMediaDataClient::Request::getTypeAsString() const
@@ -138,6 +144,17 @@ void LLMediaDataClient::Request::reEnqueue() const
 	mMDC->enqueue(this);
 }
 
+F32 LLMediaDataClient::Request::getRetryTimerDelay() const
+{
+	return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY :
+		mMDC->mRetryTimerDelay; 
+}
+
+U32 LLMediaDataClient::Request::getMaxNumRetries() const
+{
+	return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries;
+}
+
 std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r)
 {
 	s << "<request>" 
@@ -164,15 +181,21 @@ LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr)
 // virtual 
 LLMediaDataClient::Responder::RetryTimer::~RetryTimer() 
 {
+	LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL;
+
+	// XXX This is weird: Instead of doing the work in tick()  (which re-schedules
+	// a timer, which might be risky), do it here, in the destructor.  Yes, it is very odd.
+	// Instead of retrying, we just put the request back onto the queue
+	LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL;
+	mResponder->getRequest()->reEnqueue();
+
+	// Release the ref to the responder.
 	mResponder = NULL;
 }
 
 // virtual
 BOOL LLMediaDataClient::Responder::RetryTimer::tick()
 {
-	// Instead of retrying, we just put the request back onto the queue
-	LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL;
-	mResponder->getRequest()->reEnqueue();
 	// Don't fire again
 	return TRUE;
 }
@@ -191,35 +214,35 @@ LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
 
 LLMediaDataClient::Responder::~Responder()
 {
-    mRequest = NULL;
+	LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL;
+	mRequest = NULL;
 }
 
 /*virtual*/
 void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
 {
-	extern LLControlGroup gSavedSettings;
-
 	if (status == HTTP_SERVICE_UNAVAILABLE)
 	{
-		F32 retry_timeout = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
-		if (retry_timeout <= 0.0)
-		{
-			retry_timeout = (F32)UNAVAILABLE_RETRY_TIMER_DELAY;
-		}
-		LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
+		F32 retry_timeout = mRequest->getRetryTimerDelay();
 
 		mRequest->incRetryCount();
 		
-		// Start timer (instances are automagically tracked by
-		// InstanceTracker<> and LLEventTimer)
-		new RetryTimer(F32(retry_timeout/*secs*/), this);
+		if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) 
+		{
+			LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
+
+			// Start timer (instances are automagically tracked by
+			// InstanceTracker<> and LLEventTimer)
+			new RetryTimer(F32(retry_timeout/*secs*/), this);
+		}
+		else {
+			LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retry count " << 
+				mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
+		}
 	}
 	else {
 		std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason;
-		LL_INFOS("LLMediaDataClient") << *mRequest << " error(" << msg << ")" << LL_ENDL;
-		LLSD args;
-		args["ERROR"] = msg;
-		LLNotifications::instance().add("ObjectMediaFailure", args);
+		LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL;
 	}
 }
 
@@ -227,7 +250,7 @@ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
 /*virtual*/
 void LLMediaDataClient::Responder::result(const LLSD& content)
 {
-	LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_pretty_print_sd(content) << LL_ENDL;
+	LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_print_sd(content) << LL_ENDL;
 }
 
 
@@ -256,29 +279,25 @@ bool LLMediaDataClient::Comparator::operator() (const request_ptr_t &o1, const r
 	// Calculate the scores for each.  
 	F64 o1_score = Comparator::getObjectScore(o1->getObject());
 	F64 o2_score = Comparator::getObjectScore(o2->getObject());
-		
-	return ( o1_score > o2_score );
+
+    // XXX Weird: a higher score should go earlier, but by observation I notice
+    // that this causes further-away objects load first.  This is counterintuitive
+    // to the priority_queue Comparator, which states that this function should
+    // return 'true' if o1 should be *before* o2.
+    // In other words, I'd have expected that the following should return
+    // ( o1_score > o2_score).
+	return ( o1_score < o2_score );
 }
 	
 // static
-F64 LLMediaDataClient::Comparator::getObjectScore(const ll_vo_volume_ptr_t &obj)
+F64 LLMediaDataClient::Comparator::getObjectScore(const LLMediaDataClientObject::ptr_t &obj)
 {
 	// *TODO: make this less expensive?
-	F32 dist = obj->getRenderPosition().length() + 0.1;	 // avoids div by 0
+	F64 dist = obj->getDistanceFromAvatar() + 0.1;	 // avoids div by 0
 	// square the distance so that they are in the same "unit magnitude" as
 	// the interest (which is an area) 
 	dist *= dist;
-	F64 interest = (F64)1;
-	int i = 0;
-	int end = obj->getNumTEs();
-	for ( ; i < end; ++i)
-	{
-		const viewer_media_t &impl = obj->getMediaImpl(i);
-		if (!impl.isNull())
-		{
-			interest += impl->getInterest();
-		}
-	}
+	F64 interest = obj->getTotalMediaInterest() + 1.0;
 		
 	return interest/dist;	   
 }
@@ -286,7 +305,7 @@ F64 LLMediaDataClient::Comparator::getObjectScore(const ll_vo_volume_ptr_t &obj)
 //////////////////////////////////////////////////////////////////////////////////////
 //
 // LLMediaDataClient::PriorityQueue
-// Queue of LLVOVolume smart pointers to request media for.
+// Queue of LLMediaDataClientObject smart pointers to request media for.
 //
 //////////////////////////////////////////////////////////////////////////////////////
 
@@ -308,7 +327,7 @@ std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::PriorityQueue
 //////////////////////////////////////////////////////////////////////////////////////
 //
 // LLMediaDataClient::QueueTimer
-// Queue of LLVOVolume smart pointers to request media for.
+// Queue of LLMediaDataClientObject smart pointers to request media for.
 //
 //////////////////////////////////////////////////////////////////////////////////////
 
@@ -320,6 +339,7 @@ LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc)
 
 LLMediaDataClient::QueueTimer::~QueueTimer()
 {
+	LL_DEBUGS("LLMediaDataClient") << "~QueueTimer" << LL_ENDL;
 	mMDC->setIsRunning(false);
 	mMDC = NULL;
 }
@@ -342,15 +362,16 @@ BOOL LLMediaDataClient::QueueTimer::tick()
 		return TRUE;
 	}
 
-	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, queue is:	  " << queue << LL_ENDL;
+	LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, queue is:	  " << queue << LL_ENDL;
 
 	// Peel one off of the items from the queue, and execute request
 	request_ptr_t request = queue.top();
 	llassert(!request.isNull());
-	const ll_vo_volume_ptr_t &object = request->getObject();
+	const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject();
 	bool performed_request = false;
-	llassert(!object.isNull());
-	if (!object.isNull() && object->hasMedia())
+	bool error = false;
+	llassert(NULL != object);
+	if (NULL != object && object->hasMedia())
 	{
 		std::string url = request->getCapability();
 		if (!url.empty())
@@ -367,17 +388,27 @@ BOOL LLMediaDataClient::QueueTimer::tick()
 		}
 	}
 	else {
-		if (!object->hasMedia())
+		if (request.isNull()) 
+		{
+			LL_WARNS("LLMediaDataClient") << "Not Sending request: NULL request!" << LL_ENDL;
+		}
+		else if (NULL == object) 
 		{
-			LL_INFOS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL;
+			LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " NULL object!" << LL_ENDL;
 		}
+		else if (!object->hasMedia())
+		{
+			LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL;
+		}
+		error = true;
 	}
-	bool exceeded_retries = request->getRetryCount() > LLMediaDataClient::MAX_RETRIES;
-	if (performed_request || exceeded_retries) // Try N times before giving up 
+	bool exceeded_retries = request->getRetryCount() > mMDC->mMaxNumRetries;
+	if (performed_request || exceeded_retries || error) // Try N times before giving up 
 	{
 		if (exceeded_retries)
 		{
-			LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " << LLMediaDataClient::MAX_RETRIES << " tries...popping object id " << object->getID() << LL_ENDL; 
+			LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " 
+										  << mMDC->mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL; 
 			// XXX Should we bring up a warning dialog??
 		}
 		queue.pop();
@@ -394,15 +425,12 @@ void LLMediaDataClient::startQueueTimer()
 {
 	if (! mQueueTimerIsRunning)
 	{
-		extern LLControlGroup gSavedSettings;
-		F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
-		if (queue_timer_delay <= 0.0f)
-		{
-			queue_timer_delay = (F32)LLMediaDataClient::QUEUE_TIMER_DELAY;
-		}
-		LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << queue_timer_delay << " seconds)" << LL_ENDL;
+		LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL;
 		// LLEventTimer automagically takes care of the lifetime of this object
-		new QueueTimer(queue_timer_delay, this);
+		new QueueTimer(mQueueTimerDelay, this);
+	}
+	else { 
+		LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL;
 	}
 }
 	
@@ -411,9 +439,9 @@ void LLMediaDataClient::stopQueueTimer()
 	mQueueTimerIsRunning = false;
 }
 	
-void LLMediaDataClient::request(LLVOVolume *object, const LLSD &payload)
+void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload)
 {
-	if (NULL == object || ! object->hasMedia()) return; 
+	if (object.isNull() || ! object->hasMedia()) return; 
 
 	// Push the object on the priority queue
 	enqueue(new Request(getCapabilityName(), payload, object, this));
@@ -422,8 +450,8 @@ void LLMediaDataClient::request(LLVOVolume *object, const LLSD &payload)
 void LLMediaDataClient::enqueue(const Request *request)
 {
 	LL_INFOS("LLMediaDataClient") << "Queuing request for " << *request << LL_ENDL;
-    // Push the request on the priority queue
-    // Sadly, we have to const-cast because items put into the queue are not const
+	// Push the request on the priority queue
+	// Sadly, we have to const-cast because items put into the queue are not const
 	pRequestQueue->push(const_cast<LLMediaDataClient::Request*>(request));
 	LL_DEBUGS("LLMediaDataClient") << "Queue:" << (*pRequestQueue) << LL_ENDL;
 	// Start the timer if not already running
@@ -436,21 +464,31 @@ void LLMediaDataClient::enqueue(const Request *request)
 //
 //////////////////////////////////////////////////////////////////////////////////////
 
-LLMediaDataClient::LLMediaDataClient()
+LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay,
+									 F32 retry_timer_delay,
+									 U32 max_retries)
+	: mQueueTimerDelay(queue_timer_delay),
+	  mRetryTimerDelay(retry_timer_delay),
+	  mMaxNumRetries(max_retries),
+	  mQueueTimerIsRunning(false)
 {
 	pRequestQueue = new PriorityQueue();
 }
 
-
 LLMediaDataClient::~LLMediaDataClient()
 {
 	stopQueueTimer();
-	
+
 	// This should clear the queue, and hopefully call all the destructors.
-    while (! pRequestQueue->empty()) pRequestQueue->pop();
-	
+	LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " << 
+		(pRequestQueue->empty() ? "<empty> " : "<not empty> ") << (*pRequestQueue) << LL_ENDL;
 	delete pRequestQueue;
-    pRequestQueue = NULL;
+	pRequestQueue = NULL;
+}
+
+bool LLMediaDataClient::isEmpty() const
+{
+	return (NULL == pRequestQueue) ? true : pRequestQueue->empty();
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -462,79 +500,78 @@ LLMediaDataClient::~LLMediaDataClient()
 
 LLMediaDataClient::Responder *LLObjectMediaDataClient::createResponder(const request_ptr_t &request) const
 {
-    return new LLObjectMediaDataClient::Responder(request);
+	return new LLObjectMediaDataClient::Responder(request);
 }
 
 const char *LLObjectMediaDataClient::getCapabilityName() const 
 {
-    return "ObjectMedia";
+	return "ObjectMedia";
 }
 
-void LLObjectMediaDataClient::fetchMedia(LLVOVolume *object)
+void LLObjectMediaDataClient::fetchMedia(LLMediaDataClientObject *object)
 {
-    LLSD sd_payload;
-    sd_payload["verb"] = "GET";
-    sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
-    request(object, sd_payload);
+	LLSD sd_payload;
+	sd_payload["verb"] = "GET";
+	sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+	request(object, sd_payload);
 }
 
-void LLObjectMediaDataClient::updateMedia(LLVOVolume *object)
+void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object)
 {
-    LLSD sd_payload;
-    sd_payload["verb"] = "UPDATE";
-    sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
-    LLSD object_media_data;
-    for (int i=0; i < object->getNumTEs(); i++) {
-        LLTextureEntry *texture_entry = object->getTE(i);
-        llassert((texture_entry->getMediaData() != NULL) == texture_entry->hasMedia());
-        const LLSD &media_data =  
-            (texture_entry->getMediaData() == NULL) ? LLSD() : texture_entry->getMediaData()->asLLSD();
-        object_media_data.append(media_data);
-    }
-    sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data;
-        
-	LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_pretty_print_sd(sd_payload) << LL_ENDL;
-    
-    request(object, sd_payload);
+	LLSD sd_payload;
+	sd_payload["verb"] = "UPDATE";
+	sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+	LLSD object_media_data;
+	int i = 0;
+	int end = object->getMediaDataCount();
+	for ( ; i < end ; ++i) 
+	{
+		object_media_data.append(object->getMediaDataLLSD(i));
+	}
+	sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data;
+		
+	LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL;
+	
+	request(object, sd_payload);
 }
 
 /*virtual*/
 void LLObjectMediaDataClient::Responder::result(const LLSD& content)
 {
-    const LLMediaDataClient::Request::Type type = getRequest()->getType();
-    llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)
-    if (type == LLMediaDataClient::Request::GET)
-    {
-        LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_pretty_print_sd(content) << LL_ENDL;
-        
-        // Look for an error
-        if (content.has("error"))
-        {
-            const LLSD &error = content["error"];
-            LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" << 
+	const LLMediaDataClient::Request::Type type = getRequest()->getType();
+	llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)
+	if (type == LLMediaDataClient::Request::GET)
+	{
+		LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_print_sd(content) << LL_ENDL;
+		
+		// Look for an error
+		if (content.has("error"))
+		{
+			const LLSD &error = content["error"];
+			LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" << 
 				error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
-            
-            // XXX Warn user?
-        }
-        else {
-            // Check the data
-            const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY];
-            if (object_id != getRequest()->getObject()->getID()) 
-            {
-                // NOT good, wrong object id!!
-                LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
-                return;
-            }
-            
-            // Otherwise, update with object media data
-            getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]);
-        }
-    }
-    else if (type == LLMediaDataClient::Request::UPDATE)
-    {
-        // just do what our superclass does
-        LLMediaDataClient::Responder::result(content);
-    }
+			
+			// XXX Warn user?
+		}
+		else {
+			// Check the data
+			const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY];
+			if (object_id != getRequest()->getObject()->getID()) 
+			{
+				// NOT good, wrong object id!!
+				LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
+				return;
+			}
+			
+			// Otherwise, update with object media data
+			getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]);
+		}
+	}
+	else if (type == LLMediaDataClient::Request::UPDATE)
+	{
+		// just do what our superclass does
+		LLMediaDataClient::Responder::result(content);
+	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -545,21 +582,21 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)
 //////////////////////////////////////////////////////////////////////////////////////
 LLMediaDataClient::Responder *LLObjectMediaNavigateClient::createResponder(const request_ptr_t &request) const
 {
-    return new LLObjectMediaNavigateClient::Responder(request);
+	return new LLObjectMediaNavigateClient::Responder(request);
 }
 
 const char *LLObjectMediaNavigateClient::getCapabilityName() const 
 {
-    return "ObjectMediaNavigate";
+	return "ObjectMediaNavigate";
 }
 
-void LLObjectMediaNavigateClient::navigate(LLVOVolume *object, U8 texture_index, const std::string &url)
+void LLObjectMediaNavigateClient::navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url)
 {
-    LLSD sd_payload;
-    sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+	LLSD sd_payload;
+	sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
 	sd_payload[LLMediaEntry::CURRENT_URL_KEY] = url;
 	sd_payload[LLTextureEntry::TEXTURE_INDEX_KEY] = (LLSD::Integer)texture_index;
-    request(object, sd_payload);
+	request(object, sd_payload);
 }
 
 /*virtual*/
@@ -573,16 +610,18 @@ void LLObjectMediaNavigateClient::Responder::error(U32 status, const std::string
 	}
 	else {
 		// bounce the face back
-		bounceBack();
 		LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: http code=" << status << LL_ENDL;
+		const LLSD &payload = getRequest()->getPayload();
+		// bounce the face back
+		getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
 	}
 }
 
 /*virtual*/
 void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
 {
-    LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_pretty_print_sd(content) << LL_ENDL;
-    
+	LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_print_sd(content) << LL_ENDL;
+	
 	if (content.has("error"))
 	{
 		const LLSD &error = content["error"];
@@ -590,38 +629,19 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
 		
 		if (ERROR_PERMISSION_DENIED_CODE == error_code)
 		{
-            LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL;
+			LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL;
+			const LLSD &payload = getRequest()->getPayload();
 			// bounce the face back
-			bounceBack();
+			getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
 		}
 		else {
-            LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" << 
+			LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" << 
 				error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
-		}            
+		}			 
 		// XXX Warn user?
 	}
-    else {
-        // just do what our superclass does
-        LLMediaDataClient::Responder::result(content);
-    }
-}
-
-
-void LLObjectMediaNavigateClient::Responder::bounceBack()
-{
-	const LLSD &payload = getRequest()->getPayload();
-	U8 texture_index = (U8)(LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY];
-    viewer_media_t impl = getRequest()->getObject()->getMediaImpl(texture_index);
-    // Find the media entry for this navigate
-    LLMediaEntry* mep = NULL;
-    LLTextureEntry *te = getRequest()->getObject()->getTE(texture_index);
-    if(te)
-    {
-        mep = te->getMediaData();
-    }
-    
-    if (mep && impl)
-    {
-//        impl->navigateTo(mep->getCurrentURL());
-    }
+	else {
+		// just do what our superclass does
+		LLMediaDataClient::Responder::result(content);
+	}
 }
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
index 59c4334251fd3087b17b5d379bb4f906feb2a334..9d0aa0981e77cb9a651f2fbf259467374dd838ab 100755
--- a/indra/newview/llmediadataclient.h
+++ b/indra/newview/llmediadataclient.h
@@ -36,12 +36,36 @@
 #include "llhttpclient.h"
 #include <queue>
 #include "llrefcount.h"
+#include "llpointer.h"
 #include "lltimer.h"
 
-// Forward decls
-class LLVOVolume;
 
-typedef LLPointer<LLVOVolume> ll_vo_volume_ptr_t;
+// Link seam for LLVOVolume
+class LLMediaDataClientObject : public LLRefCount
+{
+public:
+	// Get the number of media data items
+	virtual U8 getMediaDataCount() const = 0;
+	// Get the media data at index, as an LLSD
+	virtual LLSD getMediaDataLLSD(U8 index) const = 0;
+	// Get this object's UUID
+	virtual LLUUID getID() const = 0;
+	// Navigate back to previous URL
+	virtual void mediaNavigateBounceBack(U8 index) = 0;
+	// Does this object have media?
+	virtual bool hasMedia() const = 0;
+	// Update the object's media data to the given array
+	virtual void updateObjectMediaData(LLSD const &media_data_array) = 0;
+	// Return the distance from the object to the avatar
+	virtual F64 getDistanceFromAvatar() const = 0;
+	// Return the total "interest" of the media (on-screen area)
+	virtual F64 getTotalMediaInterest() const = 0;
+	// Return the given cap url
+	virtual std::string getCapabilityUrl(const std::string &name) const = 0;
+
+	// smart pointer
+	typedef LLPointer<LLMediaDataClientObject> ptr_t;
+};
 
 // This object creates a priority queue for requests.
 // Abstracts the Cap URL, the request, and the responder
@@ -50,15 +74,23 @@ class LLMediaDataClient : public LLRefCount
 public:
     LOG_CLASS(LLMediaDataClient);
     
-    const static int QUEUE_TIMER_DELAY = 1; // seconds(s)
-	const static int MAX_RETRIES = 4;
+    const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s)
+	const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs
+	const static U32 MAX_RETRIES;// = 4;
 
 	// Constructor
-	LLMediaDataClient();
+	LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+					  F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+		              U32 max_retries = MAX_RETRIES);
 	
 	// Make the request
-	void request(LLVOVolume *object, const LLSD &payload);
-    
+	void request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload);
+
+	F32 getRetryTimerDelay() const { return mRetryTimerDelay; }
+	
+	// Returns true iff the queue is empty
+	bool isEmpty() const; 
+	
 protected:
 	// Destructor
 	virtual ~LLMediaDataClient(); // use unref
@@ -73,10 +105,10 @@ class LLMediaDataClient : public LLRefCount
             NAVIGATE
         };
         
-		Request(const std::string &cap_name, const LLSD& sd_payload, LLVOVolume *obj, LLMediaDataClient *mdc);
+		Request(const std::string &cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
 		const std::string &getCapName() const { return mCapName; }
 		const LLSD &getPayload() const { return mPayload; }
-		LLVOVolume *getObject() const { return mObject; }
+		LLMediaDataClientObject *getObject() const { return mObject; }
 
         U32 getNum() const { return mNum; }
 
@@ -92,6 +124,9 @@ class LLMediaDataClient : public LLRefCount
 		// Re-enqueue thyself
 		void reEnqueue() const;
 		
+		F32 getRetryTimerDelay() const;
+		U32 getMaxNumRetries() const;
+		
 	public:
 		friend std::ostream& operator<<(std::ostream &s, const Request &q);
 		
@@ -101,7 +136,7 @@ class LLMediaDataClient : public LLRefCount
 	private:
 		std::string mCapName;
 		LLSD mPayload;
-		ll_vo_volume_ptr_t mObject;
+		LLMediaDataClientObject::ptr_t mObject;
 		// Simple tracking
 		const U32 mNum;
 		static U32 sNum;
@@ -115,8 +150,6 @@ class LLMediaDataClient : public LLRefCount
 	// Responder
 	class Responder : public LLHTTPClient::Responder
 	{
-		static const int UNAVAILABLE_RETRY_TIMER_DELAY = 5; // secs
-
 	public:
 		Responder(const request_ptr_t &request);
 		//If we get back an error (not found, etc...), handle it here
@@ -163,9 +196,10 @@ class LLMediaDataClient : public LLRefCount
 	public:
 		bool operator() (const request_ptr_t &o1, const request_ptr_t &o2) const;
 	private:
-		static F64 getObjectScore(const ll_vo_volume_ptr_t &obj);
+		static F64 getObjectScore(const LLMediaDataClientObject::ptr_t &obj);
 	};
 	
+    // PriorityQueue
 	class PriorityQueue : public std::priority_queue<
 		request_ptr_t, 
 		std::vector<request_ptr_t>, 
@@ -193,6 +227,10 @@ class LLMediaDataClient : public LLRefCount
 	void startQueueTimer();
 	void stopQueueTimer();
 	void setIsRunning(bool val) { mQueueTimerIsRunning = val; }
+
+	const F32 mQueueTimerDelay;
+	const F32 mRetryTimerDelay;
+	const U32 mMaxNumRetries;
 	
 	bool mQueueTimerIsRunning;
 	
@@ -204,11 +242,15 @@ class LLMediaDataClient : public LLRefCount
 class LLObjectMediaDataClient : public LLMediaDataClient
 {
 public:
-    LLObjectMediaDataClient() {}
+    LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+							F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+							U32 max_retries = MAX_RETRIES)
+		: LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
+		{}
     ~LLObjectMediaDataClient() {}
     
-	void fetchMedia(LLVOVolume *object); 
-    void updateMedia(LLVOVolume *object);
+	void fetchMedia(LLMediaDataClientObject *object); 
+    void updateMedia(LLMediaDataClientObject *object);
     
 protected:
 	// Subclasses must override this factory method to return a new responder
@@ -230,14 +272,18 @@ class LLObjectMediaDataClient : public LLMediaDataClient
 // MediaDataResponder specific for the ObjectMediaNavigate cap
 class LLObjectMediaNavigateClient : public LLMediaDataClient
 {
+public:
 	// NOTE: from llmediaservice.h
 	static const int ERROR_PERMISSION_DENIED_CODE = 8002;
 	
-public:
-    LLObjectMediaNavigateClient() {}
+    LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+								F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+								U32 max_retries = MAX_RETRIES)
+		: LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
+		{}
     ~LLObjectMediaNavigateClient() {}
     
-    void navigate(LLVOVolume *object, U8 texture_index, const std::string &url);
+    void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url);
     
 protected:
 	// Subclasses must override this factory method to return a new responder
@@ -254,7 +300,7 @@ class LLObjectMediaNavigateClient : public LLMediaDataClient
 		virtual void error(U32 status, const std::string& reason);
         virtual void result(const LLSD &content);
     private:
-        void bounceBack();
+        void mediaNavigateBounceBack();
     };
 
 };
diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp
index 8dd09d5ec72f8a0904b6da70f6aec922182cfc3c..28ddaa61c4c811aba63f35168ad0a2b55d4c170b 100644
--- a/indra/newview/llmenucommands.cpp
+++ b/indra/newview/llmenucommands.cpp
@@ -66,7 +66,6 @@
 #include "llfocusmgr.h"
 #include "llnearbychatbar.h"
 
-
 void handle_mouselook(void*)
 {
 	gAgent.changeCameraToMouselook();
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 2b4e35208aec404873632ee99efd5863413289ef..14da35594fb358238a804dae207d4132cc9b95e6 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -280,6 +280,14 @@ void LLFloaterMove::setMovementMode(const EMovementMode mode)
 	mCurrentMode = mode;
 	gAgent.setFlying(MM_FLY == mode);
 
+	// attempts to set avatar flying can not set it real flying in some cases.
+	// For ex. when avatar fell down & is standing up.
+	// So, no need to continue processing FLY mode. See EXT-1079
+	if (MM_FLY == mode && !gAgent.getFlying())
+	{
+		return;
+	}
+
 	switch (mode)
 	{
 	case MM_RUN:
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index ff7f08bf9733886683c2bb05beffd0272b81f559..36cf2c1aa85b061815b03cf3e50419f284fa6ce0 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -65,7 +65,6 @@
 #include "llworld.h" //for particle system banning
 #include "llchat.h"
 #include "llfloaterchat.h"
-#include "llimpanel.h"
 #include "llimview.h"
 #include "llnotifications.h"
 #include "lluistring.h"
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index b91e23eace4ac9e0d6b63b1b4fef8f343864f7da..e63daac4afbff23efa2dedf7c59d47216eb0d1eb 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -164,17 +164,6 @@ void LLTeleportHistoryMenuItem::onMouseLeave(S32 x, S32 y, MASK mask)
 - Load navbar height from saved settings (as it's done for status bar) or think of a better way.
 */
 
-S32 NAVIGATION_BAR_HEIGHT = 60; // *HACK
-LLNavigationBar* LLNavigationBar::sInstance = 0;
-
-LLNavigationBar* LLNavigationBar::getInstance()
-{
-	if (!sInstance)
-		sInstance = new LLNavigationBar();
-
-	return sInstance;
-}
-
 LLNavigationBar::LLNavigationBar()
 :	mTeleportHistoryMenu(NULL),
 	mBtnBack(NULL),
@@ -198,8 +187,6 @@ LLNavigationBar::LLNavigationBar()
 LLNavigationBar::~LLNavigationBar()
 {
 	mTeleportFinishConnection.disconnect();
-	sInstance = 0;
-
 	LLSearchHistory::getInstance()->save();
 }
 
@@ -272,6 +259,15 @@ void LLNavigationBar::draw()
 		onTeleportHistoryChanged();
 		mPurgeTPHistoryItems = false;
 	}
+
+	if (isBackgroundVisible())
+	{
+		static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0);
+		static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
+		gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
+                           color_drop_shadow, drop_shadow_floater );
+	}
+
 	LLPanel::draw();
 }
 
@@ -521,8 +517,8 @@ void	LLNavigationBar::showTeleportHistoryMenu()
 	// *TODO: why to draw/update anything before showing the menu?
 	mTeleportHistoryMenu->buildDrawLabels();
 	mTeleportHistoryMenu->updateParent(LLMenuGL::sMenuContainer);
-	LLRect btnBackRect = mBtnBack->getRect();
-	LLMenuGL::showPopup(this, mTeleportHistoryMenu, btnBackRect.mLeft, btnBackRect.mBottom);
+	const S32 MENU_SPAWN_PAD = -1;
+	LLMenuGL::showPopup(mBtnBack, mTeleportHistoryMenu, 0, MENU_SPAWN_PAD);
 
 	// *HACK pass the mouse capturing to the drop-down menu
 	gFocusMgr.setMouseCapture( NULL );
@@ -547,6 +543,15 @@ void LLNavigationBar::clearHistoryCache()
 	mPurgeTPHistoryItems= true;
 }
 
+int LLNavigationBar::getDefNavBarHeight()
+{
+	return mDefaultNbRect.getHeight();
+}
+int LLNavigationBar::getDefFavBarHeight()
+{
+	return mDefaultFpRect.getHeight();
+}
+
 void LLNavigationBar::showNavigationPanel(BOOL visible)
 {
 	bool fpVisible = gSavedSettings.getBOOL("ShowNavbarFavoritesPanel");
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
index 8a65cd24face5adadc6dc55bef5f1c86d639e3f4..8b625e7fa62099b09e5c14477e7fda7025388fba 100644
--- a/indra/newview/llnavigationbar.h
+++ b/indra/newview/llnavigationbar.h
@@ -35,8 +35,6 @@
 
 #include "llpanel.h"
 
-extern S32 NAVIGATION_BAR_HEIGHT;
-
 class LLButton;
 class LLLocationInputCtrl;
 class LLMenuGL;
@@ -47,12 +45,12 @@ class LLSearchComboBox;
  * Web browser-like navigation bar.
  */ 
 class LLNavigationBar
-:	public LLPanel
+	:	public LLPanel, public LLSingleton<LLNavigationBar>
 {
 	LOG_CLASS(LLNavigationBar);
-
+	
 public:
-	static LLNavigationBar* getInstance();
+	LLNavigationBar();
 	virtual ~LLNavigationBar();
 	
 	/*virtual*/ void	draw();
@@ -63,9 +61,11 @@ class LLNavigationBar
 
 	void showNavigationPanel(BOOL visible);
 	void showFavoritesPanel(BOOL visible);
+
+	int getDefNavBarHeight();
+	int getDefFavBarHeight();
 	
 private:
-	LLNavigationBar();
 
 	void rebuildTeleportHistoryMenu();
 	void showTeleportHistoryMenu();
@@ -91,8 +91,6 @@ class LLNavigationBar
 
 	void fillSearchComboBox();
 
-	static LLNavigationBar *sInstance;
-	
 	LLMenuGL*					mTeleportHistoryMenu;
 	LLButton*					mBtnBack;
 	LLButton*					mBtnForward;
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index bbab9944f32b33c483eaf61588862a16d11769fd..12638ab8551b6c252c8d3145c58b6eb956db3a3d 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -170,22 +170,6 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat)
 	return text_color;
 }
 
-std::string formatCurrentTime()
-{
-	time_t utc_time;
-	utc_time = time_corrected();
-	std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
-		+LLTrans::getString("TimeMin")+"] ";
-
-	LLSD substitution;
-
-	substitution["datetime"] = (S32) utc_time;
-	LLStringUtil::format (timeStr, substitution);
-
-	return timeStr;
-}
-
-
 void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color)
 {
 	S32 font_size = gSavedSettings.getS32("ChatFontSize");
@@ -210,24 +194,24 @@ void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& colo
 	style_params.font(fontp);
 	LLUUID uuid = chat.mFromID;
 	std::string from = chat.mFromName;
-	std::string time = formatCurrentTime();
 	std::string message = chat.mText;
-	mChatHistory->appendWidgetMessage(uuid, from, time, message, style_params);
+	mChatHistory->appendWidgetMessage(chat, style_params);
 }
 
 void	LLNearbyChat::addMessage(const LLChat& chat)
 {
 	LLColor4 color = nearbychat_get_text_color(chat);
 	
-
 	if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
 	{
-		LLFloaterScriptDebug::addScriptLine(chat.mText,
-											chat.mFromName, 
-											color, 
-											chat.mFromID);
-		if (!gSavedSettings.getBOOL("ScriptErrorsAsChat"))
+		if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
+			return;
+		if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat"))
 		{
+			LLFloaterScriptDebug::addScriptLine(chat.mText,
+												chat.mFromName, 
+												color, 
+												chat.mFromID);
 			return;
 		}
 	}
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 5fa97926a5c02fd304dd66ce13e3a6ed21a5f05f..32dc5e59278e740073fcd570f8f9ee4d3b8c02df 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -45,6 +45,7 @@
 #include "llviewerstats.h"
 #include "llcommandhandler.h"
 #include "llviewercontrol.h"
+#include "llnavigationbar.h"
 
 S32 LLNearbyChatBar::sLastSpecialChatChannel = 0;
 
@@ -177,6 +178,31 @@ void LLGestureComboBox::draw()
 	LLComboBox::draw();
 }
 
+//virtual
+void LLGestureComboBox::showList()
+{
+	LLComboBox::showList();
+
+	// Calculating amount of space between the navigation bar and gestures combo
+	LLNavigationBar* nb = LLNavigationBar::getInstance();
+	S32 x, nb_bottom;
+	nb->localPointToScreen(0, 0, &x, &nb_bottom);
+	
+	S32 list_bottom;
+	mList->localPointToScreen(0, 0, &x, &list_bottom);
+
+	S32 max_height = nb_bottom - list_bottom;
+
+	LLRect rect = mList->getRect();
+	// List overlapped navigation bar, downsize it
+	if (rect.getHeight() > max_height) 
+	{
+		rect.setOriginAndSize(rect.mLeft, rect.mBottom, rect.getWidth(), max_height);
+		mList->setRect(rect);
+		mList->reshape(rect.getWidth(), rect.getHeight());
+	}
+}
+
 LLNearbyChatBar::LLNearbyChatBar() 
 	: LLPanel()
 	, mChatBox(NULL)
@@ -198,7 +224,6 @@ BOOL LLNearbyChatBar::postBuild()
 	mChatBox->setIgnoreTab(TRUE);
 	mChatBox->setPassDelete(TRUE);
 	mChatBox->setReplaceNewlinesWithSpaces(FALSE);
-	mChatBox->setMaxTextLength(1023);
 	mChatBox->setEnableLineHistory(TRUE);
 
 	mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator");
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index b902ff86cc36bf14a5967cd35518cf186dddf3a1..06204e6367b4a43f5c80c03b088255e064df02a0 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -40,7 +40,7 @@
 #include "llchiclet.h"
 #include "llvoiceclient.h"
 #include "lloutputmonitorctrl.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
 
 class LLGestureComboBox
 	: public LLComboBox
@@ -62,6 +62,9 @@ class LLGestureComboBox
 	virtual void changed() { refreshGestures(); }
 
 protected:
+
+	virtual void showList();
+
 	LLFrameTimer mGestureLabelTimer;
 	std::vector<LLMultiGesture*> mGestures;
 	std::string mLabel;
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index 4aefbd1a334fd5dc55f21f9d3492bd0060fafb47..8a8ad9d073fc65b9df128bed5f1f2949eb9a4b84 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -162,6 +162,8 @@ bool	LLNearbyChatScreenChannel::createPoolToast()
 	
 	LLToast::Params p;
 	p.panel = panel;
+	p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime");
+	p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime");
 
 	LLToast* toast = new LLToast(p); 
 	
@@ -188,6 +190,17 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
 		return;
 	}
 
+	int chat_type = notification["chat_type"].asInteger();
+	
+	if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG))
+	{
+		if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) 
+			return;
+		if(gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)
+			return;
+	}
+		
+
 	//take 1st element from pool, (re)initialize it, put it in active toasts
 
 	LLToast* toast = m_toast_pool.back();
@@ -249,8 +262,9 @@ void LLNearbyChatScreenChannel::showToastsBottom()
 			toast_rect.setLeftTopAndSize(getRect().mLeft , toast_top, toast_rect.getWidth() ,toast_rect.getHeight());
 		
 			toast->setRect(toast_rect);
-			
+			toast->setIsHidden(false);
 			toast->setVisible(TRUE);
+			
 			bottom = toast->getRect().mTop;
 		}		
 	}
@@ -315,6 +329,12 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg)
 		initChannel();
 	}
 
+	//only messages from AGENTS
+	if(CHAT_SOURCE_OBJECT == chat_msg.mSourceType)
+	{
+		return;//dn't show toast for messages from objects
+	}
+
 	LLUUID id;
 	id.generate();
 
@@ -330,6 +350,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg)
 		notification["from_id"] = chat_msg.mFromID;
 		notification["time"] = chat_msg.mTime;
 		notification["source"] = (S32)chat_msg.mSourceType;
+		notification["chat_type"] = (S32)chat_msg.mChatType;
 
 		channel->addNotification(notification);	
 	}
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index 7239f49b7f664cebd6b1960b1a879c4cab61a778..543198c1d2158c8aa62d92d54465b4a2b95c4f84 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -86,6 +86,20 @@ bool LLTipHandler::processNotification(const LLSD& notify)
 
 	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
 	{
+		// archive message in nearby chat
+		LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+		if(nearby_chat)
+		{
+			LLChat chat_msg(notification->getMessage());
+			nearby_chat->addMessage(chat_msg);
+
+			// don't show toast if Nearby Chat is opened
+			if (nearby_chat->getVisible())
+			{
+				return true;
+			}			
+		}
+
 		LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
 
 		LLToast::Params p;
@@ -99,14 +113,6 @@ bool LLTipHandler::processNotification(const LLSD& notify)
 		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
 		if(channel)
 			channel->addToast(p);
-
-		// archive message in nearby chat
-		LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
-		if(nearby_chat)
-		{
-			LLChat chat_msg(notification->getMessage());
-			nearby_chat->addMessage(chat_msg);
-		}
 	}
 	else if (notify["sigtype"].asString() == "delete")
 	{
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 6eed956eb840e11730e44340f2e05b3db13aea18..b54975b76b6392ea9ae9818e00e44acd5d058249 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -34,6 +34,7 @@
 
 #include "llpanelimcontrolpanel.h"
 
+#include "llagent.h"
 #include "llavataractions.h"
 #include "llavatariconctrl.h"
 #include "llbutton.h"
@@ -41,6 +42,61 @@
 #include "llavatarlist.h"
 #include "llparticipantlist.h"
 #include "llimview.h"
+#include "llvoicechannel.h"
+
+void LLPanelChatControlPanel::onCallButtonClicked()
+{
+	gIMMgr->startCall(mSessionId);
+}
+
+void LLPanelChatControlPanel::onEndCallButtonClicked()
+{
+	gIMMgr->endCall(mSessionId);
+}
+
+void LLPanelChatControlPanel::onOpenVoiceControlsClicked()
+{
+	// TODO: implement Voice Control Panel opening
+}
+
+BOOL LLPanelChatControlPanel::postBuild()
+{
+	childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this));
+	childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this));
+	childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this));
+
+	return TRUE;
+}
+
+void LLPanelChatControlPanel::draw()
+{
+	// hide/show start call and end call buttons
+	bool voice_enabled = LLVoiceClient::voiceEnabled();
+
+	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
+	if (!session) return;
+
+	LLVoiceChannel* voice_channel = session->mVoiceChannel;
+	if (voice_channel && voice_enabled)
+	{
+		bool is_call_started = ( voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED );
+		childSetVisible("end_call_btn", is_call_started);
+		childSetVisible("voice_ctrls_btn", is_call_started);
+		childSetVisible("call_btn", ! is_call_started);
+	}
+
+	bool session_initialized = session->mSessionInitialized;
+	bool callback_enabled = session->mCallBackEnabled;
+	LLViewerRegion* region = gAgent.getRegion();
+
+	BOOL enable_connect = (region && region->getCapability("ChatSessionRequest") != "")
+		&& session_initialized
+		&& voice_enabled
+		&& callback_enabled;
+	childSetEnabled("call_btn", enable_connect);
+
+	LLPanel::draw();
+}
 
 LLPanelIMControlPanel::LLPanelIMControlPanel()
 {
@@ -54,11 +110,11 @@ BOOL LLPanelIMControlPanel::postBuild()
 {
 	childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this));
 	childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this));
-	childSetAction("call_btn", boost::bind(&LLPanelIMControlPanel::onCallButtonClicked, this));
+
 	childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this));
 	childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId()));
-
-	return TRUE;
+	
+	return LLPanelChatControlPanel::postBuild();
 }
 
 void LLPanelIMControlPanel::onViewProfileButtonClicked()
@@ -73,22 +129,29 @@ void LLPanelIMControlPanel::onAddFriendButtonClicked()
 	LLAvatarActions::requestFriendshipDialog(avatar_icon->getAvatarId(), full_name);
 }
 
-void LLPanelIMControlPanel::onCallButtonClicked()
-{
-	// *TODO: Implement
-}
-
 void LLPanelIMControlPanel::onShareButtonClicked()
 {
 	// *TODO: Implement
 }
 
-void LLPanelIMControlPanel::setID(const LLUUID& avatar_id)
+void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
 {
+	LLPanelChatControlPanel::setSessionId(session_id);
+
+	LLIMModel& im_model = LLIMModel::instance();
+
+	LLUUID avatar_id = im_model.getOtherParticipantID(session_id);
+
 	// Disable "Add friend" button for friends.
 	childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(avatar_id));
 
 	getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(avatar_id);
+
+	// Disable profile button if participant is not realy SL avatar
+	LLIMModel::LLIMSession* im_session =
+		im_model.findIMSession(session_id);
+	if( im_session && !im_session->mOtherParticipantIsAvatar )
+		childSetEnabled("view_profile_btn", FALSE);
 }
 
 
@@ -100,12 +163,11 @@ LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id)
 BOOL LLPanelGroupControlPanel::postBuild()
 {
 	childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this));
-	childSetAction("call_btn", boost::bind(&LLPanelGroupControlPanel::onCallButtonClicked, this));
 
 	mAvatarList = getChild<LLAvatarList>("speakers_list");
 	mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList);
 
-	return TRUE;
+	return LLPanelChatControlPanel::postBuild();
 }
 
 LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
@@ -127,13 +189,23 @@ void LLPanelGroupControlPanel::onGroupInfoButtonClicked()
 }
 
 
-void LLPanelGroupControlPanel::onCallButtonClicked()
+void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
 {
-	// *TODO: Implement
+	LLPanelChatControlPanel::setSessionId(session_id);
+
+	mGroupID = LLIMModel::getInstance()->getOtherParticipantID(session_id);
 }
 
 
-void LLPanelGroupControlPanel::setID(const LLUUID& id)
+LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id)
 {
-	mGroupID = id;
 }
+
+BOOL LLPanelAdHocControlPanel::postBuild()
+{
+	mAvatarList = getChild<LLAvatarList>("speakers_list");
+	mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList);
+
+	return LLPanelChatControlPanel::postBuild();
+}
+
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index 138b1630c454d59e983d3ba7aa9e7d20b381ee81..d25f33935a3f58305cfb2c5146669c4d4c0e1ff8 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -45,8 +45,17 @@ class LLPanelChatControlPanel : public LLPanel
 	LLPanelChatControlPanel() {};
 	~LLPanelChatControlPanel() {};
 
-	// sets the group or avatar UUID
-	virtual void setID(const LLUUID& avatar_id)= 0;
+	virtual BOOL postBuild();
+	virtual void draw();
+
+	void onCallButtonClicked();
+	void onEndCallButtonClicked();
+	void onOpenVoiceControlsClicked();
+
+	virtual void setSessionId(const LLUUID& session_id) { mSessionId = session_id; }
+
+private:
+	LLUUID mSessionId;
 };
 
 
@@ -58,13 +67,14 @@ class LLPanelIMControlPanel : public LLPanelChatControlPanel
 
 	BOOL postBuild();
 
-	void setID(const LLUUID& avatar_id);
+	void setSessionId(const LLUUID& session_id);
 
 private:
 	void onViewProfileButtonClicked();
 	void onAddFriendButtonClicked();
-	void onCallButtonClicked();
 	void onShareButtonClicked();
+
+	LLUUID mAvatarID;
 };
 
 
@@ -76,19 +86,26 @@ class LLPanelGroupControlPanel : public LLPanelChatControlPanel
 
 	BOOL postBuild();
 
-	void setID(const LLUUID& id);
+	void setSessionId(const LLUUID& session_id);
 	/*virtual*/ void draw();
 
-private:
-	void onGroupInfoButtonClicked();
-	void onCallButtonClicked();
-
+protected:
 	LLUUID mGroupID;
 	LLSpeakerMgr* mSpeakerManager;
 	LLAvatarList* mAvatarList;
 	LLParticipantList* mParticipantList;
+
+private:
+	void onGroupInfoButtonClicked();
 };
 
+class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel
+{
+public:
+	LLPanelAdHocControlPanel(const LLUUID& session_id);
+
+	BOOL postBuild();
 
+};
 
 #endif // LL_LLPANELIMCONTROLPANEL_H
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index faa938c772a6ce987f2d3dc9b09e4ef470f7d2af..c9598a2576892f972a11802348289035b0e5b334 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -36,11 +36,14 @@
 #include "llbutton.h"
 #include "llfloaterreg.h"
 #include "llsdutil.h"
+#include "llsdutil_math.h"
 
+#include "llaccordionctrl.h"
 #include "llaccordionctrltab.h"
 #include "llagent.h"
 #include "llagentpicksinfo.h"
 #include "llagentui.h"
+#include "llcallbacklist.h"
 #include "lldndbutton.h"
 #include "llfloaterworldmap.h"
 #include "llfolderviewitem.h"
@@ -55,7 +58,7 @@
 //static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
 
 static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
-static const std::string ADD_LANDMARK_BUTTON_NAME = "add_landmark_btn";
+static const std::string ADD_BUTTON_NAME = "add_btn";
 static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
 static const std::string TRASH_BUTTON_NAME = "trash_btn";
 
@@ -74,6 +77,7 @@ LLLandmarksPanel::LLLandmarksPanel()
 	,	mListCommands(NULL)
 	,	mGearFolderMenu(NULL)
 	,	mGearLandmarkMenu(NULL)
+	,	mDirtyFilter(false)
 {
 	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");
 }
@@ -97,16 +101,40 @@ BOOL LLLandmarksPanel::postBuild()
 	initMyInventroyPanel();
 	initLibraryInventroyPanel();
 
+	gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this);
 	return TRUE;
 }
 
 // virtual
 void LLLandmarksPanel::onSearchEdit(const std::string& string)
 {
+	static std::string prev_string("");
+
+	if (prev_string == string) return;
+
+	// show all folders in Landmarks Accordion for empty filter
+	mLandmarksInventoryPanel->setShowFolderState(string.empty() ?
+		LLInventoryFilter::SHOW_ALL_FOLDERS :
+		LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
+		);
+
 	filter_list(mFavoritesInventoryPanel, string);
 	filter_list(mLandmarksInventoryPanel, string);
 	filter_list(mMyInventoryPanel, string);
 	filter_list(mLibraryInventoryPanel, string);
+
+	prev_string = string;
+	mDirtyFilter = true;
+
+	// give FolderView a chance to be refreshed. So, made all accordions visible
+	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
+	{
+		LLAccordionCtrlTab* tab = *iter;
+		tab->setVisible(true);
+
+		// expand accordion to see matched items in all ones. See EXT-2014.
+		tab->changeOpenClose(false);
+	}
 }
 
 // virtual
@@ -156,9 +184,9 @@ void LLLandmarksPanel::updateVerbs()
 	if (!isTabVisible()) 
 		return;
 
-	BOOL enabled = isLandmarkSelected();
-	mTeleportBtn->setEnabled(enabled);
-	mShowOnMapBtn->setEnabled(enabled);
+	bool landmark_selected = isLandmarkSelected();
+	mTeleportBtn->setEnabled(landmark_selected && isActionEnabled("teleport"));
+	mShowOnMapBtn->setEnabled(landmark_selected && isActionEnabled("show_on_map"));
 
 	// TODO: mantipov: Uncomment when mShareBtn is supported
 	// Share button should be enabled when neither a folder nor a landmark is selected
@@ -299,6 +327,8 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
 					panel_pick, panel_places,params));
 			panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
 				panel_pick, panel_places,params));
+			panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
+							panel_pick, panel_places,params));
 		}
 	}
 }
@@ -388,6 +418,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_lis
 void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list)
 {
 	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
+	mAccordionTabs.push_back(accordion_tab);
 	accordion_tab->setDropDownStateChangedCallback(
 		boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list));
 }
@@ -432,11 +463,11 @@ void LLLandmarksPanel::initListCommandsHandlers()
 	mListCommands = getChild<LLPanel>("bottom_panel");
 
 	mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
-	mListCommands->childSetAction(ADD_LANDMARK_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddLandmarkButtonClick, this));
-	mListCommands->childSetAction(ADD_FOLDER_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddFolderButtonClick, this));
 	mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
+	mListCommands->getChild<LLButton>(ADD_BUTTON_NAME)->setHeldDownCallback(boost::bind(&LLLandmarksPanel::onAddButtonHeldDown, this));
+	static const LLSD add_landmark_command("add_landmark");
+	mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddAction, this, add_landmark_command));
 
-	
 	LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
 	trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this
 			,	_4 // BOOL drop
@@ -452,6 +483,7 @@ void LLLandmarksPanel::initListCommandsHandlers()
 	mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
 	mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 }
 
 
@@ -487,52 +519,26 @@ void LLLandmarksPanel::onActionsButtonClick()
 		mGearFolderMenu->getChild<LLMenuItemCallGL>("collapse")->setVisible(cur_item->isOpen());
 		menu = mGearFolderMenu;
 	}
-	if(menu)
-	{
-		menu->buildDrawLabels();
-		menu->updateParent(LLMenuGL::sMenuContainer);
-		LLView* actions_btn  = getChild<LLView>(OPTIONS_BUTTON_NAME);
-		S32 menu_x, menu_y;
-		actions_btn->localPointToOtherView(0,actions_btn->getRect().getHeight(),&menu_x,&menu_y, this);
-		menu_y += menu->getRect().getHeight();
-		LLMenuGL::showPopup(this, menu, menu_x,menu_y);
-	}
+	showActionMenu(menu,OPTIONS_BUTTON_NAME);
 }
 
-void LLLandmarksPanel::onAddLandmarkButtonClick() const
+void LLLandmarksPanel::onAddButtonHeldDown()
 {
-	if(LLLandmarkActions::landmarkAlreadyExists())
-	{
-		std::string location;
-		LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL);
-		llwarns<<" Landmark already exists at location:  "<< location<<llendl;
-		return;
-	}
-	LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
+	showActionMenu(mMenuAdd,ADD_BUTTON_NAME);
 }
 
-void LLLandmarksPanel::onAddFolderButtonClick() const
+void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
 {
-	LLFolderViewItem*  item = getCurSelectedItem();
-	if(item &&  mCurrentSelectedList == mLandmarksInventoryPanel)
+	if (menu)
 	{
-		LLFolderViewEventListener* folder_bridge = NULL;
-		if(item-> getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
-		{
-			// for a landmark get parent folder bridge
-			folder_bridge = item->getParentFolder()->getListener();
-		}
-		else if (item-> getListener()->getInventoryType() == LLInventoryType::IT_CATEGORY) 
-		{
-			// for a folder get its own bridge
-			folder_bridge = item->getListener();
-		}
-
-		menu_create_inventory_item(mCurrentSelectedList->getRootFolder()
-			, dynamic_cast<LLFolderBridge*>(folder_bridge)
-			, LLSD("category")
-			, gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK)
-			);
+		menu->buildDrawLabels();
+		menu->updateParent(LLMenuGL::sMenuContainer);
+		LLView* spawning_view = getChild<LLView> (spawning_view_name);
+		S32 menu_x, menu_y;
+		//show menu in co-ordinates of panel
+		spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
+		menu_y += menu->getRect().getHeight();
+		LLMenuGL::showPopup(this, menu, menu_x, menu_y);
 	}
 }
 
@@ -546,11 +552,39 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 	std::string command_name = userdata.asString();
 	if("add_landmark" == command_name)
 	{
-		onAddLandmarkButtonClick();
+		if(LLLandmarkActions::landmarkAlreadyExists())
+		{
+			std::string location;
+			LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL);
+			llwarns<<" Landmark already exists at location:  "<< location<<llendl;
+			return;
+		}
+		LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
 	} 
 	else if ("category" == command_name)
 	{
-		onAddFolderButtonClick();
+		LLFolderViewItem* item = getCurSelectedItem();
+		if (item && mCurrentSelectedList == mLandmarksInventoryPanel)
+		{
+			LLFolderViewEventListener* folder_bridge = NULL;
+			if (item-> getListener()->getInventoryType()
+					== LLInventoryType::IT_LANDMARK)
+			{
+				// for a landmark get parent folder bridge
+				folder_bridge = item->getParentFolder()->getListener();
+			}
+			else if (item-> getListener()->getInventoryType()
+					== LLInventoryType::IT_CATEGORY)
+			{
+				// for a folder get its own bridge
+				folder_bridge = item->getListener();
+			}
+
+			menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),
+					dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD(
+							"category"), gInventory.findCategoryUUIDForType(
+							LLAssetType::AT_LANDMARK));
+		}
 	}
 }
 
@@ -852,6 +886,43 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg
 	return true;
 }
 
+// static
+void LLLandmarksPanel::doIdle(void* landmarks_panel)
+{
+	LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel;
+
+	if (panel->mDirtyFilter)
+	{
+		panel->updateFilteredAccordions();
+	}
+
+}
+
+void LLLandmarksPanel::updateFilteredAccordions()
+{
+	LLInventoryPanel* inventory_list = NULL;
+	LLAccordionCtrlTab* accordion_tab = NULL;
+	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
+	{
+		accordion_tab = *iter;
+		inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView());
+		if (NULL == inventory_list) continue;
+		LLFolderView* fv = inventory_list->getRootFolder();
+
+		bool has_visible_children = fv->hasVisibleChildren();
+
+		accordion_tab->setVisible(has_visible_children);
+	}
+
+	// we have to arrange accordion tabs for cases when filter string is less restrictive but 
+	// all items are still filtered.
+	static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
+	accordion->arrange();
+
+	// now filter state is applied to accordion tabs
+	mDirtyFilter = false;
+}
+
 
 //////////////////////////////////////////////////////////////////////////
 // HELPER FUNCTIONS
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 47c9f7647cd311c4abe0c9f4d5d421cd8b38f4de..0e7abb486501fbccc224c0e1c2235701f83f938e 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -41,6 +41,7 @@
 #include "llpanelpick.h"
 #include "llremoteparcelrequest.h"
 
+class LLAccordionCtrlTab;
 class LLFolderViewItem;
 class LLMenuGL;
 class LLInventoryPanel;
@@ -90,8 +91,8 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	void initListCommandsHandlers();
 	void updateListCommands();
 	void onActionsButtonClick();
-	void onAddLandmarkButtonClick() const;
-	void onAddFolderButtonClick() const;
+	void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+	void onAddButtonHeldDown();
 	void onTrashButtonClick() const;
 	void onAddAction(const LLSD& command_name) const;
 	void onClipboardAction(const LLSD& command_name) const;
@@ -114,6 +115,18 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	 */
 	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
 
+	/**
+	 * Static callback for gIdleCallbacks to perform actions out of drawing
+	 */
+	static void doIdle(void* landmarks_panel);
+
+	/**
+	 * Updates accordions according to filtered items in lists.
+	 *
+	 * It hides accordion for empty lists
+	 */
+	void updateFilteredAccordions();
+
 private:
 	LLInventorySubTreePanel*	mFavoritesInventoryPanel;
 	LLInventorySubTreePanel*	mLandmarksInventoryPanel;
@@ -121,10 +134,15 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	LLInventorySubTreePanel*	mLibraryInventoryPanel;
 	LLMenuGL*					mGearLandmarkMenu;
 	LLMenuGL*					mGearFolderMenu;
+	LLMenuGL*					mMenuAdd;
 	LLInventorySubTreePanel*	mCurrentSelectedList;
 
 	LLPanel*					mListCommands;
 	bool 						mSortByDate;
+	bool						mDirtyFilter;
+	
+	typedef	std::vector<LLAccordionCtrlTab*> accordion_tabs_t;
+	accordion_tabs_t			mAccordionTabs;
 };
 
 #endif //LL_LLPANELLANDMARKS_H
diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp
index 3177ef9a21c434c2ee2a2d3934dd6ba138fd291b..a198499b47ede597beb9122cb7e7abfe2bd49392 100644
--- a/indra/newview/llpanelmediasettingsgeneral.cpp
+++ b/indra/newview/llpanelmediasettingsgeneral.cpp
@@ -1,440 +1,453 @@
-/**
- * @file llpanelmediasettingsgeneral.cpp
- * @brief LLPanelMediaSettingsGeneral class implementation
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * 
- * Copyright (c) 2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llpanelmediasettingsgeneral.h"
-#include "llcombobox.h"
-#include "llcheckboxctrl.h"
-#include "llspinctrl.h"
-#include "lluictrlfactory.h"
-#include "llviewerwindow.h"
-#include "llviewermedia.h"
-#include "llsdutil.h"
-#include "llselectmgr.h"
-#include "llbutton.h"
-#include "lltexturectrl.h"
-#include "llurl.h"
-#include "llwindow.h"
-#include "llmediaentry.h"
-#include "llmediactrl.h"
-#include "llpanelcontents.h"
-#include "llpluginclassmedia.h"
-#include "llfloatermediasettings.h"
-#include "llfloatertools.h"
-#include "lltrans.h"
-
-////////////////////////////////////////////////////////////////////////////////
-//
-LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() :
-	mControls( NULL ),
-	mAutoLoop( NULL ),
-	mFirstClick( NULL ),
-	mAutoZoom( NULL ),
-	mAutoPlay( NULL ),
-	mAutoScale( NULL ),
-	mWidthPixels( NULL ),
-	mHeightPixels( NULL ),
-	mHomeURL( NULL ),
-	mCurrentURL( NULL ),
-	mAltImageEnable( NULL ),
-	mParent( NULL ),
-	mMediaEditable(false)
-{
-	// build dialog from XML
-	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml");
-//	mCommitCallbackRegistrar.add("Media.ResetCurrentUrl",		boost::bind(&LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl, this));
-//	mCommitCallbackRegistrar.add("Media.CommitHomeURL",			boost::bind(&LLPanelMediaSettingsGeneral::onCommitHomeURL, this));	
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-BOOL LLPanelMediaSettingsGeneral::postBuild()
-{
-	// connect member vars with UI widgets
-    mAltImageEnable = getChild< LLCheckBoxCtrl >( LLMediaEntry::ALT_IMAGE_ENABLE_KEY );
-	mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY );
-	mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY );
-	mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );
-	mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY );
-	mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY );
-	mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY );
-	mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
-	mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY );
-	mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY );
-	mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY );
-	mPreviewMedia = getChild<LLMediaCtrl>("preview_media");
-
-	// watch commit action for HOME URL
-	childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this);
-	childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this);
-	// interrogates controls and updates widgets as required
-	updateMediaPreview();
-	updateCurrentURL();
-
-	return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral()
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::draw()
-{
-	// housekeeping
-	LLPanel::draw();
-
-	// enable/disable pixel values image entry based on auto scale checkbox 
-	if ( mAutoScale->getValue().asBoolean() == false )
-	{
-		childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true );
-		childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true );
-	}
-	else
-	{
-		childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false );
-		childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false );
-	};
-
-	// enable/disable UI based on type of media
-	bool reset_button_is_active = true;
-	if( mPreviewMedia )
-	{
-		LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
-		if( media_plugin )
-		{
-			// some controls are only appropriate for time or browser type plugins
-			// so we selectively enable/disable them - need to do it in draw
-			// because the information from plugins arrives assynchronously
-			bool show_time_controls = media_plugin->pluginSupportsMediaTime();
-			if ( show_time_controls )
-			{
-				childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false );
-				reset_button_is_active = false;
-				childSetEnabled( "current_url_label", false );
-				childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true );
-			}
-			else
-			{
-				childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true );
-				reset_button_is_active = true;
-				childSetEnabled( "current_url_label", true );
-				childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false );
-			};
-		};
-	};
-
-	// current URL can change over time.
-//	updateCurrentURL();
-
-	// enable/disable RESRET button depending on permissions
-	// since this is the same as a navigate action
-	bool user_can_press_reset = mMediaEditable;
-
-	// several places modify this widget so we must collect states in one place
-	if ( reset_button_is_active )
-	{
-		// user has perms to press reset button and it is active
-		if ( user_can_press_reset )
-		{
-			childSetEnabled( "current_url_reset_btn", true );
-		}
-		// user does not has perms to press reset button and it is active
-		else
-		{
-			childSetEnabled( "current_url_reset_btn", false );
-		};
-	}
-	else
-	// reset button is inactive so we just slam it to off - other states don't matter
-	{
-		childSetEnabled( "current_url_reset_btn", false );
-	};
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static 
-void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
-{	
-	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
-	self->mAltImageEnable ->clear();
-	self->mAutoLoop->clear();
-	self->mAutoPlay->clear();
-	self->mAutoScale->clear();
-	self->mAutoZoom ->clear();
-	self->mControls->clear();
-	self->mCurrentURL->clear();
-	self->mFirstClick->clear();
-	self->mHeightPixels->clear();
-	self->mHomeURL->clear();
-	self->mWidthPixels->clear();
-	self->mAltImageEnable ->setEnabled(editable);
-	self->mAutoLoop ->setEnabled(editable);
-	self->mAutoPlay ->setEnabled(editable);
-	self->mAutoScale ->setEnabled(editable);
-	self->mAutoZoom  ->setEnabled(editable);
-	self->mControls ->setEnabled(editable);
-	self->mCurrentURL ->setEnabled(editable);
-	self->mFirstClick ->setEnabled(editable);
-	self->mHeightPixels ->setEnabled(editable);
-	self->mHomeURL ->setEnabled(editable);
-	self->mWidthPixels ->setEnabled(editable);
-	self->mPreviewMedia->unloadMediaSource(); 
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static 
-void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable)
-{
-	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
-	self->mMediaEditable = editable;
-
-	//llinfos << "---------------" << llendl;
-	//llinfos << ll_pretty_print_sd(media_settings) << llendl;
-	//llinfos << "---------------" << llendl;
-
-	// IF all the faces have media (or all dont have media)
-	if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
-	{
-		if(LLFloaterMediaSettings::getInstance()->mMultipleMedia) 
-		{
-			self->clearValues(self, self->mMediaEditable);
-			// only show multiple 
-			self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
-			return;
-		}
-		
-	}
-	else
-	{
-		if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) 
-		{
-			self->clearValues(self, self->mMediaEditable);
-			// only show multiple 
-			self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
-			return;
-		}			
-		
-	}
-	std::string base_key( "" );
-	std::string tentative_key( "" );
-
-	struct 
-	{
-		std::string key_name;
-		LLUICtrl* ctrl_ptr;
-		std::string ctrl_type;
-
-	} data_set [] = 
-	{ 
-        { LLMediaEntry::AUTO_LOOP_KEY,				self->mAutoLoop,		"LLCheckBoxCtrl" },
-		{ LLMediaEntry::AUTO_PLAY_KEY,				self->mAutoPlay,		"LLCheckBoxCtrl" },
-		{ LLMediaEntry::AUTO_SCALE_KEY,				self->mAutoScale,		"LLCheckBoxCtrl" },
-		{ LLMediaEntry::AUTO_ZOOM_KEY,				self->mAutoZoom,		"LLCheckBoxCtrl" },
-		{ LLMediaEntry::CONTROLS_KEY,				self->mControls,		"LLComboBox" },
-		{ LLMediaEntry::CURRENT_URL_KEY,			self->mCurrentURL,		"LLLineEditor" },
-		{ LLMediaEntry::HEIGHT_PIXELS_KEY,			self->mHeightPixels,	"LLSpinCtrl" },
-		{ LLMediaEntry::HOME_URL_KEY,				self->mHomeURL,			"LLLineEditor" },
-		{ LLMediaEntry::FIRST_CLICK_INTERACT_KEY,	self->mFirstClick,		"LLCheckBoxCtrl" },
-		{ LLMediaEntry::WIDTH_PIXELS_KEY,			self->mWidthPixels,		"LLSpinCtrl" },
-		{ LLMediaEntry::ALT_IMAGE_ENABLE_KEY,		self->mAltImageEnable,	"LLCheckBoxCtrl" },
-		{ "", NULL , "" }
-	};
-
-	for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
-	{
-		base_key = std::string( data_set[ i ].key_name );
-		tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
-		// TODO: CP - I bet there is a better way to do this using Boost
-		if ( media_settings[ base_key ].isDefined() )
-		{
-			if ( data_set[ i ].ctrl_type == "LLLineEditor" )
-			{
-				static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )->
-					setText( media_settings[ base_key ].asString() );
-			}
-			else
-			if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
-				static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
-					setValue( media_settings[ base_key ].asBoolean() );
-			else
-			if ( data_set[ i ].ctrl_type == "LLComboBox" )
-				static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
-					setCurrentByIndex( media_settings[ base_key ].asInteger() );
-			else
-			if ( data_set[ i ].ctrl_type == "LLSpinCtrl" )
-				static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )->
-					setValue( media_settings[ base_key ].asInteger() );
-
-			data_set[ i ].ctrl_ptr->setEnabled(self->mMediaEditable);
-			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
-		};
-	};
-	
-	// interrogates controls and updates widgets as required
-	self->updateMediaPreview();
-	self->updateCurrentURL();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Helper to set media control to media URL as required
-void LLPanelMediaSettingsGeneral::updateMediaPreview()
-{
-	if ( mHomeURL->getValue().asString().length() > 0 )
-	{
-		mPreviewMedia->navigateTo( mHomeURL->getValue().asString() );
-	}
-	else
-	// new home URL will be empty if media is deleted but
-	// we still need to clean out the preview.
-	{
-		mPreviewMedia->unloadMediaSource();
-	};
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Helper to set current URL
-void LLPanelMediaSettingsGeneral::updateCurrentURL()
-{
-	if( mCurrentURL->getText().empty() )
-	{
-		childSetText( "current_url", mHomeURL->getText() );
-	}
-	
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-// virtual
-void LLPanelMediaSettingsGeneral::onClose(bool app_quitting)
-{
-	if(mPreviewMedia)
-	{
-		mPreviewMedia->unloadMediaSource();
-	}
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata )
-{
-	LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
-	self->updateMediaPreview();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata)
-{
-	LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
-	self->navigateHomeSelectedFace();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::apply( void* userdata )
-{
-	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
-	self->mHomeURL->onCommit();
-	// build LLSD Fragment
-	LLSD media_data_general;
-	self->getValues(media_data_general);
-
-	// this merges contents of LLSD passed in with what's there so this is ok
-	LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in )
-{
-    fill_me_in[LLMediaEntry::ALT_IMAGE_ENABLE_KEY] = mAltImageEnable->getValue();
-    fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue();
-    fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue();
-    fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue();
-    fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue();
-    fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex();
-    // XXX Don't send current URL!
-    //fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
-    fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue();
-    fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue();
-    fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue();
-    fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent )
-{
-	mParent = parent;
-};
-
-bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace()
-{
-	// HACK: This is directly referencing an impl name.  BAD!
-	// This can be removed when we have a truly generic media browser that only 
-	// builds an impl based on the type of url it is passed.
-	struct functor_navigate_media : public LLSelectedTEGetFunctor< bool>
-	{
-		bool get( LLViewerObject* object, S32 face )
-		{
-			if ( object )
-				if ( object->getTE(face) )
-					if ( object->getTE(face)->getMediaData() )
-					{
-						if(object->permModify())
-						{
-							viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID());
-							if(media_impl)
-							{
-								media_impl->navigateHome();
-								return true;
-							}
-						}	
-					}
-		   return false;
-		 };
-				
-	} functor_navigate_media;
-	
-	bool all_face_media_navigated = false;
-	LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
-	selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated );
-	
-	return all_face_media_navigated;
-}
-
+/**
+ * @file llpanelmediasettingsgeneral.cpp
+ * @brief LLPanelMediaSettingsGeneral class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagent.h"
+#include "llpanelmediasettingsgeneral.h"
+#include "llcombobox.h"
+#include "llcheckboxctrl.h"
+#include "llspinctrl.h"
+#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+#include "llviewermedia.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llbutton.h"
+#include "lltexturectrl.h"
+#include "llurl.h"
+#include "llwindow.h"
+#include "llmediaentry.h"
+#include "llmediactrl.h"
+#include "llpanelcontents.h"
+#include "llpermissions.h"
+#include "llpluginclassmedia.h"
+#include "llfloatermediasettings.h"
+#include "llfloatertools.h"
+#include "lltrans.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() :
+	mControls( NULL ),
+	mAutoLoop( NULL ),
+	mFirstClick( NULL ),
+	mAutoZoom( NULL ),
+	mAutoPlay( NULL ),
+	mAutoScale( NULL ),
+	mWidthPixels( NULL ),
+	mHeightPixels( NULL ),
+	mHomeURL( NULL ),
+	mCurrentURL( NULL ),
+	mParent( NULL ),
+	mMediaEditable(false)
+{
+	// build dialog from XML
+	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsGeneral::postBuild()
+{
+	// connect member vars with UI widgets
+	mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY );
+	mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY );
+	mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );
+	mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY );
+	mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY );
+	mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY );
+	mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
+	mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY );
+	mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY );
+	mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY );
+	mPreviewMedia = getChild<LLMediaCtrl>("preview_media");
+
+	// watch commit action for HOME URL
+	childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this);
+	childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this);
+	// interrogates controls and updates widgets as required
+	updateMediaPreview();
+	updateCurrentURL();
+
+	return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::draw()
+{
+	// housekeeping
+	LLPanel::draw();
+
+	// enable/disable pixel values image entry based on auto scale checkbox 
+	if ( mAutoScale->getValue().asBoolean() == false )
+	{
+		childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true );
+		childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true );
+	}
+	else
+	{
+		childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false );
+		childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false );
+	};
+
+	// enable/disable UI based on type of media
+	bool reset_button_is_active = true;
+	if( mPreviewMedia )
+	{
+		LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
+		if( media_plugin )
+		{
+			// turn off volume (if we can) for preview. Note: this really only
+			// works for QuickTime movies right now - no way to control the 
+			// volume of a flash app embedded in a page for example
+			media_plugin->setVolume( 0 );
+
+			// some controls are only appropriate for time or browser type plugins
+			// so we selectively enable/disable them - need to do it in draw
+			// because the information from plugins arrives assynchronously
+			bool show_time_controls = media_plugin->pluginSupportsMediaTime();
+			if ( show_time_controls )
+			{
+				childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false );
+				reset_button_is_active = false;
+				childSetEnabled( "current_url_label", false );
+				childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true );
+			}
+			else
+			{
+				childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true );
+				reset_button_is_active = true;
+				childSetEnabled( "current_url_label", true );
+				childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false );
+			};
+		};
+	};
+
+	// current URL can change over time.
+//	updateCurrentURL();
+
+	LLPermissions perm;
+	bool user_can_press_reset = mMediaEditable;
+
+	// several places modify this widget so we must collect states in one place
+	if ( reset_button_is_active )
+	{
+		// user has perms to press reset button and it is active
+		if ( user_can_press_reset )
+		{
+			childSetEnabled( "current_url_reset_btn", true );
+		}
+		// user does not has perms to press reset button and it is active
+		else
+		{
+			childSetEnabled( "current_url_reset_btn", false );
+		};
+	}
+	else
+	// reset button is inactive so we just slam it to off - other states don't matter
+	{
+		childSetEnabled( "current_url_reset_btn", false );
+	};
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static 
+void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
+{	
+	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+	self->mAutoLoop->clear();
+	self->mAutoPlay->clear();
+	self->mAutoScale->clear();
+	self->mAutoZoom ->clear();
+	self->mControls->clear();
+	self->mCurrentURL->clear();
+	self->mFirstClick->clear();
+	self->mHeightPixels->clear();
+	self->mHomeURL->clear();
+	self->mWidthPixels->clear();
+	self->mAutoLoop ->setEnabled(editable);
+	self->mAutoPlay ->setEnabled(editable);
+	self->mAutoScale ->setEnabled(editable);
+	self->mAutoZoom  ->setEnabled(editable);
+	self->mControls ->setEnabled(editable);
+	self->mCurrentURL ->setEnabled(editable);
+	self->mFirstClick ->setEnabled(editable);
+	self->mHeightPixels ->setEnabled(editable);
+	self->mHomeURL ->setEnabled(editable);
+	self->mWidthPixels ->setEnabled(editable);
+	self->updateMediaPreview();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static 
+void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable)
+{
+	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+	self->mMediaEditable = editable;
+
+	//llinfos << "---------------" << llendl;
+	//llinfos << ll_pretty_print_sd(media_settings) << llendl;
+	//llinfos << "---------------" << llendl;
+
+	// IF all the faces have media (or all dont have media)
+	if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+	{
+		if(LLFloaterMediaSettings::getInstance()->mMultipleMedia) 
+		{
+			self->clearValues(self, self->mMediaEditable);
+			// only show multiple 
+			self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
+			return;
+		}
+		
+	}
+	else
+	{
+		if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) 
+		{
+			self->clearValues(self, self->mMediaEditable);
+			// only show multiple 
+			self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
+			return;
+		}			
+		
+	}
+	std::string base_key( "" );
+	std::string tentative_key( "" );
+
+	struct 
+	{
+		std::string key_name;
+		LLUICtrl* ctrl_ptr;
+		std::string ctrl_type;
+
+	} data_set [] = 
+	{ 
+        { LLMediaEntry::AUTO_LOOP_KEY,				self->mAutoLoop,		"LLCheckBoxCtrl" },
+		{ LLMediaEntry::AUTO_PLAY_KEY,				self->mAutoPlay,		"LLCheckBoxCtrl" },
+		{ LLMediaEntry::AUTO_SCALE_KEY,				self->mAutoScale,		"LLCheckBoxCtrl" },
+		{ LLMediaEntry::AUTO_ZOOM_KEY,				self->mAutoZoom,		"LLCheckBoxCtrl" },
+		{ LLMediaEntry::CONTROLS_KEY,				self->mControls,		"LLComboBox" },
+		{ LLMediaEntry::CURRENT_URL_KEY,			self->mCurrentURL,		"LLLineEditor" },
+		{ LLMediaEntry::HEIGHT_PIXELS_KEY,			self->mHeightPixels,	"LLSpinCtrl" },
+		{ LLMediaEntry::HOME_URL_KEY,				self->mHomeURL,			"LLLineEditor" },
+		{ LLMediaEntry::FIRST_CLICK_INTERACT_KEY,	self->mFirstClick,		"LLCheckBoxCtrl" },
+		{ LLMediaEntry::WIDTH_PIXELS_KEY,			self->mWidthPixels,		"LLSpinCtrl" },
+		{ "", NULL , "" }
+	};
+
+	for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+	{
+		base_key = std::string( data_set[ i ].key_name );
+		tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+		// TODO: CP - I bet there is a better way to do this using Boost
+		if ( media_settings[ base_key ].isDefined() )
+		{
+			if ( data_set[ i ].ctrl_type == "LLLineEditor" )
+			{
+				static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )->
+					setText( media_settings[ base_key ].asString() );
+			}
+			else
+			if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+				static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+					setValue( media_settings[ base_key ].asBoolean() );
+			else
+			if ( data_set[ i ].ctrl_type == "LLComboBox" )
+				static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
+					setCurrentByIndex( media_settings[ base_key ].asInteger() );
+			else
+			if ( data_set[ i ].ctrl_type == "LLSpinCtrl" )
+				static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )->
+					setValue( media_settings[ base_key ].asInteger() );
+
+			data_set[ i ].ctrl_ptr->setEnabled(self->mMediaEditable);
+			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+		};
+	};
+	
+	// interrogates controls and updates widgets as required
+	self->updateMediaPreview();
+	self->updateCurrentURL();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper to set media control to media URL as required
+void LLPanelMediaSettingsGeneral::updateMediaPreview()
+{
+	if ( mHomeURL->getValue().asString().length() > 0 )
+	{
+		mPreviewMedia->navigateTo( mHomeURL->getValue().asString() );
+	}
+	else
+	// new home URL will be empty if media is deleted so display a 
+	// "preview goes here" data url page
+	{
+		mPreviewMedia->navigateTo( "data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22100%%22 height=%22100%%22 %3E%3Cdefs%3E%3Cpattern id=%22checker%22 patternUnits=%22userSpaceOnUse%22 x=%220%22 y=%220%22 width=%22128%22 height=%22128%22 viewBox=%220 0 128 128%22 %3E%3Crect x=%220%22 y=%220%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3Crect x=%2264%22 y=%2264%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3C/pattern%3E%3C/defs%3E%3Crect x=%220%22 y=%220%22 width=%22100%%22 height=%22100%%22 fill=%22url(#checker)%22 /%3E%3C/svg%3E" );
+	};
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper to set current URL
+void LLPanelMediaSettingsGeneral::updateCurrentURL()
+{
+	if( mCurrentURL->getText().empty() )
+	{
+		childSetText( "current_url", mHomeURL->getText() );
+	}
+	
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// virtual
+void LLPanelMediaSettingsGeneral::onClose(bool app_quitting)
+{
+	if(mPreviewMedia)
+	{
+		mPreviewMedia->unloadMediaSource();
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata )
+{
+	LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
+
+	// check url user is trying to enter for home URL will pass whitelist 
+	// and decline to accept it if it doesn't.
+	std::string home_url = self->mHomeURL->getValue().asString();
+	if ( ! self->mParent->passesWhiteList( home_url ) )
+	{
+		LLNotifications::instance().add("WhiteListInvalidatesHomeUrl");		
+		return;
+	};
+	
+	self->updateMediaPreview();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata)
+{
+	LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
+	self->navigateHomeSelectedFace();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::apply( void* userdata )
+{
+	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+	self->mHomeURL->onCommit();
+	// build LLSD Fragment
+	LLSD media_data_general;
+	self->getValues(media_data_general);
+
+	// this merges contents of LLSD passed in with what's there so this is ok
+	LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in )
+{
+    fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue();
+    fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue();
+    fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue();
+    fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue();
+    fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex();
+    fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
+    fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue();
+    fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue();
+    fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue();
+    fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent )
+{
+	mParent = parent;
+};
+
+bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace()
+{
+	// HACK: This is directly referencing an impl name.  BAD!
+	// This can be removed when we have a truly generic media browser that only 
+	// builds an impl based on the type of url it is passed.
+	struct functor_navigate_media : public LLSelectedTEGetFunctor< bool>
+	{
+		bool get( LLViewerObject* object, S32 face )
+		{
+			if ( object )
+				if ( object->getTE(face) )
+					if ( object->getTE(face)->getMediaData() )
+					{
+						if(object->permModify())
+						{
+							viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID());
+							if(media_impl)
+							{
+								media_impl->navigateHome();
+								return true;
+							}
+						}	
+					}
+		   return false;
+		 };
+				
+	} functor_navigate_media;
+	
+	bool all_face_media_navigated = false;
+	LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
+	selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated );
+	
+	return all_face_media_navigated;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+const std::string LLPanelMediaSettingsGeneral::getHomeUrl()
+{
+	return mHomeURL->getValue().asString(); 
+}
+
diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h
index 1b60909786aee182d2baf2e775df37301a202f51..e82a31382ef6226e23da4513fe0b09d5a1959877 100644
--- a/indra/newview/llpanelmediasettingsgeneral.h
+++ b/indra/newview/llpanelmediasettingsgeneral.h
@@ -64,6 +64,8 @@ class LLPanelMediaSettingsGeneral : public LLPanel
 	bool navigateHomeSelectedFace();
 	void updateMediaPreview();
 	void updateCurrentURL();
+
+	const std::string getHomeUrl();
 	
 protected:
 	LLFloaterMediaSettings* mParent;
@@ -76,7 +78,6 @@ class LLPanelMediaSettingsGeneral : public LLPanel
 	LLComboBox* mControls;
 	LLCheckBoxCtrl* mAutoLoop;
 	LLCheckBoxCtrl* mFirstClick;
-//	LLTextureCtrl* mMediaPreview;
 	LLCheckBoxCtrl* mAutoZoom;
 	LLCheckBoxCtrl* mAutoPlay;
 	LLCheckBoxCtrl* mAutoScale;
@@ -84,7 +85,6 @@ class LLPanelMediaSettingsGeneral : public LLPanel
 	LLSpinCtrl* mHeightPixels;
 	LLLineEditor* mHomeURL;
 	LLLineEditor* mCurrentURL;
-	LLCheckBoxCtrl* mAltImageEnable;
 	LLMediaCtrl* mPreviewMedia;
 };
 
diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp
index cea105d7de3f5a8b35a2486f4439cf420cda9d47..f5607aa2874e03a6e21e62f84dfedfd907262792 100644
--- a/indra/newview/llpanelmediasettingssecurity.cpp
+++ b/indra/newview/llpanelmediasettingssecurity.cpp
@@ -1,255 +1,343 @@
-/**
- * @file llpanelmediasettingssecurity.cpp
- * @brief LLPanelMediaSettingsSecurity class implementation
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * 
- * Copyright (c) 2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-#include "llfloaterreg.h"
-#include "llpanelmediasettingssecurity.h"
-#include "llpanelcontents.h"
-#include "llcheckboxctrl.h"
-#include "llscrolllistctrl.h"
-#include "llscrolllistitem.h"
-#include "lluictrlfactory.h"
-#include "llwindow.h"
-#include "llviewerwindow.h"
-#include "llsdutil.h"
-#include "llselectmgr.h"
-#include "llmediaentry.h"
-#include "llfloaterwhitelistentry.h"
-#include "llfloatermediasettings.h"
-////////////////////////////////////////////////////////////////////////////////
-//
-LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity()
-{
-	// build dialog from XML
-	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml");
-	mCommitCallbackRegistrar.add("Media.whitelistAdd",		boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this));
-	mCommitCallbackRegistrar.add("Media.whitelistDelete",	boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this));	
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-BOOL LLPanelMediaSettingsSecurity::postBuild()
-{
-	mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY );
-	mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY );
-
-	childSetAction("whitelist_add", onBtnAdd, this);
-	childSetAction("whitelist_del", onBtnDel, this);
-
-	setDefaultBtn("whitelist_add");
-
-	return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity()
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 
-void LLPanelMediaSettingsSecurity::draw()
-{
-	// housekeeping
-	LLPanel::draw();
-
-	// if list is empty, disable DEL button and checkbox to enable use of list
-	if ( mWhiteListList->isEmpty() )
-	{
-		childSetEnabled( "whitelist_del", false );
-		childSetEnabled( LLMediaEntry::WHITELIST_KEY, false );
-		childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false );
-	}
-	else
-	{
-		childSetEnabled( "whitelist_del", true );
-		childSetEnabled( LLMediaEntry::WHITELIST_KEY, true );
-		childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true );
-	};
-
-	// if nothing is selected, disable DEL button
-	if ( mWhiteListList->getSelectedValue().asString().empty() )
-	{
-		childSetEnabled( "whitelist_del", false );
-	}
-	else
-	{
-		childSetEnabled( "whitelist_del", true );
-	};
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static 
-void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings , bool editable)
-{
-	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
-
-	if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
-	{
-		if(LLFloaterMediaSettings::getInstance()->mMultipleMedia) 
-		{
-			self->clearValues(self, editable);
-			// only show multiple 
-			return;
-		}
-		
-	}
-	else
-	{
-		if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) 
-		{
-			self->clearValues(self, editable);
-			// only show multiple 
-			return;
-		}			
-		
-	}
-	std::string base_key( "" );
-	std::string tentative_key( "" );
-
-	struct 
-	{
-		std::string key_name;
-		LLUICtrl* ctrl_ptr;
-		std::string ctrl_type;
-
-	} data_set [] = 
+/**
+ * @file llpanelmediasettingssecurity.cpp
+ * @brief LLPanelMediaSettingsSecurity class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfloaterreg.h"
+#include "llpanelmediasettingssecurity.h"
+#include "llpanelcontents.h"
+#include "llcheckboxctrl.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "lluictrlfactory.h"
+#include "llwindow.h"
+#include "llviewerwindow.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "llfloaterwhitelistentry.h"
+#include "llfloatermediasettings.h"
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity() :
+	mParent( NULL )
+{
+	// build dialog from XML
+	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml");
+	mCommitCallbackRegistrar.add("Media.whitelistAdd",		boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this));
+	mCommitCallbackRegistrar.add("Media.whitelistDelete",	boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this));	
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsSecurity::postBuild()
+{
+	mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY );
+	mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY );
+
+	childSetAction("whitelist_add", onBtnAdd, this);
+	childSetAction("whitelist_del", onBtnDel, this);
+
+	setDefaultBtn("whitelist_add");
+
+	return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 
+void LLPanelMediaSettingsSecurity::draw()
+{
+	// housekeeping
+	LLPanel::draw();
+
+	// if list is empty, disable DEL button and checkbox to enable use of list
+	if ( mWhiteListList->isEmpty() )
+	{
+		childSetEnabled( "whitelist_del", false );
+		childSetEnabled( LLMediaEntry::WHITELIST_KEY, false );
+		childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false );
+	}
+	else
+	{
+		childSetEnabled( "whitelist_del", true );
+		childSetEnabled( LLMediaEntry::WHITELIST_KEY, true );
+		childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true );
+	};
+
+	// if nothing is selected, disable DEL button
+	if ( mWhiteListList->getSelectedValue().asString().empty() )
+	{
+		childSetEnabled( "whitelist_del", false );
+	}
+	else
+	{
+		childSetEnabled( "whitelist_del", true );
+	};
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static 
+void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings , bool editable)
+{
+	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+	if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+	{
+		if(LLFloaterMediaSettings::getInstance()->mMultipleMedia) 
+		{
+			self->clearValues(self, editable);
+			// only show multiple 
+			return;
+		}
+		
+	}
+	else
+	{
+		if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) 
+		{
+			self->clearValues(self, editable);
+			// only show multiple 
+			return;
+		}			
+		
+	}
+	std::string base_key( "" );
+	std::string tentative_key( "" );
+
+	struct 
+	{
+		std::string key_name;
+		LLUICtrl* ctrl_ptr;
+		std::string ctrl_type;
+
+	} data_set [] = 
+	{
+		{ LLMediaEntry::WHITELIST_ENABLE_KEY,	self->mEnableWhiteList,		"LLCheckBoxCtrl" },
+		{ LLMediaEntry::WHITELIST_KEY,			self->mWhiteListList,		"LLScrollListCtrl" },
+		{ "", NULL , "" }
+	};
+
+	for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+	{
+		base_key = std::string( data_set[ i ].key_name );
+        tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+
+		// TODO: CP - I bet there is a better way to do this using Boost
+		if ( media_settings[ base_key ].isDefined() )
+		{
+			if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+			{
+				static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+					setValue( media_settings[ base_key ].asBoolean() );
+			}
+			else
+			if ( data_set[ i ].ctrl_type == "LLScrollListCtrl" )
+			{
+				// get control 
+				LLScrollListCtrl* list = static_cast< LLScrollListCtrl* >( data_set[ i ].ctrl_ptr );
+				list->deleteAllItems();
+
+				// points to list of white list URLs
+				LLSD url_list = media_settings[ base_key ];
+
+				// iterate over them and add to scroll list
+				LLSD::array_iterator iter = url_list.beginArray();
+				while( iter != url_list.endArray() )
+				{
+					// TODO: is iter guaranteed to be valid here?
+					std::string url = *iter;
+					list->addSimpleElement( url );
+					++iter;
+				};
+			};
+			data_set[ i ].ctrl_ptr->setEnabled(editable);
+			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+		};
+	};
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static 
+void LLPanelMediaSettingsSecurity::clearValues( void* userdata , bool editable)
+{
+	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+	self->mEnableWhiteList->clear();
+	self->mWhiteListList->deleteAllItems();
+	self->mEnableWhiteList->setEnabled(editable);
+	self->mWhiteListList->setEnabled(editable);
+}
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::apply( void* userdata )
+{
+	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+	// build LLSD Fragment
+	LLSD media_data_security;
+	self->getValues(media_data_security);
+	// this merges contents of LLSD passed in with what's there so this is ok
+	LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in )
+{
+    fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue();
+
+    // iterate over white list and extract items
+    std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
+    std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin();
+    fill_me_in[LLMediaEntry::WHITELIST_KEY].clear();
+    while( iter != white_list_items.end() )
+    {
+        std::string white_list_url = (*iter)->getValue().asString();
+        fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url );
+        ++iter;
+    };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Try to make a valid URL if a fragment (
+// white list list box widget and build a list to test against. Can also
+const std::string LLPanelMediaSettingsSecurity::makeValidUrl( const std::string& src_url )
+{
+	// use LLURI to determine if we have a valid scheme
+	LLURI candidate_url( src_url );
+	if ( candidate_url.scheme().empty() )
 	{
-		{ LLMediaEntry::WHITELIST_ENABLE_KEY,	self->mEnableWhiteList,		"LLCheckBoxCtrl" },
-		{ LLMediaEntry::WHITELIST_KEY,			self->mWhiteListList,		"LLScrollListCtrl" },
-		{ "", NULL , "" }
+		// build a URL comprised of default scheme and the original fragment 
+		const std::string default_scheme( "http://" );
+		return default_scheme + src_url;
 	};
 
-	for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
-	{
-		base_key = std::string( data_set[ i ].key_name );
-        tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
-
-		// TODO: CP - I bet there is a better way to do this using Boost
-		if ( media_settings[ base_key ].isDefined() )
-		{
-			if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
-			{
-				static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
-					setValue( media_settings[ base_key ].asBoolean() );
-			}
-			else
-			if ( data_set[ i ].ctrl_type == "LLScrollListCtrl" )
-			{
-				// get control 
-				LLScrollListCtrl* list = static_cast< LLScrollListCtrl* >( data_set[ i ].ctrl_ptr );
-				list->deleteAllItems();
-
-				// points to list of white list URLs
-				LLSD url_list = media_settings[ base_key ];
-
-				// iterate over them and add to scroll list
-				LLSD::array_iterator iter = url_list.beginArray();
-				while( iter != url_list.endArray() )
-				{
-					// TODO: is iter guaranteed to be valid here?
-					std::string url = *iter;
-					list->addSimpleElement( url );
-					++iter;
-				};
-			};
-			data_set[ i ].ctrl_ptr->setEnabled(editable);
-			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
-		};
-	};
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static 
-void LLPanelMediaSettingsSecurity::clearValues( void* userdata , bool editable)
-{
-	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
-	self->mEnableWhiteList->clear();
-	self->mWhiteListList->deleteAllItems();
-	self->mEnableWhiteList->setEnabled(editable);
-	self->mWhiteListList->setEnabled(editable);
-}
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsSecurity::apply( void* userdata )
-{
-	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
-
-	// build LLSD Fragment
-	LLSD media_data_security;
-	self->getValues(media_data_security);
-	// this merges contents of LLSD passed in with what's there so this is ok
-	LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security );
-}
-
+	// we *could* test the "default scheme" + "original fragment" URL again
+	// using LLURI to see if it's valid but I think the outcome is the same
+	// in either case - our only option is to return the original URL
+
+	// we *think* the original url passed in was valid
+	return src_url;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// wrapper for testing a URL against the whitelist. We grab entries from
+// white list list box widget and build a list to test against. Can also
+// optionally pass the URL that you are trying to add to the widget since
+// it won't be added until this call returns.
+bool LLPanelMediaSettingsSecurity::passesWhiteList( const std::string& added_url,
+													const std::string& test_url )
+{
+	// the checkUrlAgainstWhitelist(..) function works on a vector
+	// of strings for the white list entries - in this panel, the white list
+	// is stored in the widgets themselves so we need to build something compatible.
+	std::vector< std::string > whitelist_strings;
+	whitelist_strings.clear();	// may not be required - I forget what the spec says.
+
+	// step through whitelist widget entries and grab them as strings
+    std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
+    std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin(); 
+	while( iter != white_list_items.end()  )
+    {
+        const std::string whitelist_url = (*iter)->getValue().asString();
+		whitelist_strings.push_back( whitelist_url );
+
+		++iter;
+    };
+
+	// add in the URL that might be added to the whitelist so we can test that too
+	if ( added_url.length() )
+		whitelist_strings.push_back( added_url );
+
+	// possible the URL is just a fragment so we validize it
+	const std::string valid_url = makeValidUrl( test_url );
+
+	// indicate if the URL passes whitelist
+	return LLMediaEntry::checkUrlAgainstWhitelist( valid_url, whitelist_strings );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::addWhiteListItem(const std::string& url)
+{
+	// grab home URL from the general panel (via the parent floater)
+	std::string home_url( "" );
+	if ( mParent )
+		home_url = mParent->getHomeUrl();
+
+	// if the home URL is blank (user hasn't entered it yet) then
+	// don't bother to check if it passes the white list
+	if ( home_url.empty() )
+	{
+		mWhiteListList->addSimpleElement( url );
+		return;
+	};
+
+	// if the URL passes the white list, add it
+	if ( passesWhiteList( url, home_url ) )
+	{
+		mWhiteListList->addSimpleElement( url );
+	}
+	else
+	// display a message indicating you can't do that
+	{
+		LLNotifications::instance().add("WhiteListInvalidatesHomeUrl");
+	};
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata )
+{
+	LLFloaterReg::showInstance("whitelist_entry");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata )
+{
+	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+	self->mWhiteListList->deleteSelectedItems();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 //
-void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in )
-{
-    fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue();
-
-    // iterate over white list and extract items
-    std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
-    std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin();
-    fill_me_in[LLMediaEntry::WHITELIST_KEY].clear();
-    while( iter != white_list_items.end() )
-    {
-        std::string white_list_url = (*iter)->getValue().asString();
-        fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url );
-        ++iter;
-    };
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsSecurity::addWhiteListItem(const std::string& url)
-{
-	mWhiteListList->addSimpleElement( url );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata )
-{
-	LLFloaterReg::showInstance("whitelist_entry");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata )
+void LLPanelMediaSettingsSecurity::setParent( LLFloaterMediaSettings* parent )
 {
-	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+	mParent = parent;
+};
 
-	self->mWhiteListList->deleteSelectedItems();
-}
diff --git a/indra/newview/llpanelmediasettingssecurity.h b/indra/newview/llpanelmediasettingssecurity.h
index b7cf67c0391813749188108e4720b08573725496..b78ee921937e9829eb4ded4a7a62c1bda0be8ba4 100644
--- a/indra/newview/llpanelmediasettingssecurity.h
+++ b/indra/newview/llpanelmediasettingssecurity.h
@@ -37,6 +37,7 @@
 
 class LLCheckBoxCtrl;
 class LLScrollListCtrl;
+class LLFloaterMediaSettings;
 
 class LLPanelMediaSettingsSecurity : public LLPanel
 {
@@ -52,6 +53,12 @@ class LLPanelMediaSettingsSecurity : public LLPanel
 		static void initValues( void* userdata, const LLSD& media_settings,bool editable );
 		static void clearValues( void* userdata, bool editable);
 		void addWhiteListItem(const std::string& url);
+		void setParent( LLFloaterMediaSettings* parent );
+		const std::string makeValidUrl( const std::string& src_url );
+		bool passesWhiteList( const std::string& added_url, const std::string& test_url );
+
+	protected:
+		LLFloaterMediaSettings* mParent;
 
 	private:
 		LLCheckBoxCtrl* mEnableWhiteList;
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 61d66873ea564d7f36d5cc8c3ec68e6e42a5595d..4580eeb336af3591db99b8d0f7da2020ded7e0dd 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -413,13 +413,17 @@ BOOL LLPanelPeople::postBuild()
 	mOnlineFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_online");
 	mAllFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_all");
 	mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online"));
+	mOnlineFriendList->setShowIcons("FriendsListShowIcons");
 	mAllFriendList->setNoItemsCommentText(getString("no_friends"));
+	mAllFriendList->setShowIcons("FriendsListShowIcons");
 
 	mNearbyList = getChild<LLPanel>(NEARBY_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
 	mNearbyList->setNoItemsCommentText(getString("no_one_near"));
+	mNearbyList->setShowIcons("NearbyListShowIcons");
 
 	mRecentList = getChild<LLPanel>(RECENT_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
 	mRecentList->setNoItemsCommentText(getString("no_people"));
+	mRecentList->setShowIcons("RecentListShowIcons");
 
 	mGroupList = getChild<LLGroupList>("group_list");
 	mGroupList->setNoItemsCommentText(getString("no_groups"));
@@ -611,6 +615,10 @@ void LLPanelPeople::updateButtons()
 	bool recent_tab_active	= (cur_tab == RECENT_TAB_NAME);
 	LLUUID selected_id;
 
+	std::vector<LLUUID> selected_uuids;
+	getCurrentItemIDs(selected_uuids);
+	bool item_selected = (selected_uuids.size() == 1);
+
 	buttonSetVisible("group_info_btn",		group_tab_active);
 	buttonSetVisible("chat_btn",			group_tab_active);
 	buttonSetVisible("add_friend_btn",		nearby_tab_active || recent_tab_active);
@@ -621,7 +629,6 @@ void LLPanelPeople::updateButtons()
 
 	if (group_tab_active)
 	{
-		bool item_selected = mGroupList->getSelectedItem() != NULL;
 		bool cur_group_active = true;
 
 		if (item_selected)
@@ -629,7 +636,7 @@ void LLPanelPeople::updateButtons()
 			selected_id = mGroupList->getSelectedUUID();
 			cur_group_active = (gAgent.getGroupID() == selected_id);
 		}
-	
+
 		LLPanel* groups_panel = mTabContainer->getCurrentPanel();
 		groups_panel->childSetEnabled("activate_btn",	item_selected && !cur_group_active); // "none" or a non-active group selected
 		groups_panel->childSetEnabled("plus_btn",		item_selected);
@@ -640,18 +647,18 @@ void LLPanelPeople::updateButtons()
 		bool is_friend = true;
 
 		// Check whether selected avatar is our friend.
-		if ((selected_id = getCurrentItemID()).notNull())
+		if (item_selected)
 		{
+			selected_id = selected_uuids.front();
 			is_friend = LLAvatarTracker::instance().getBuddyInfo(selected_id) != NULL;
 		}
 
 		childSetEnabled("add_friend_btn",	!is_friend);
 	}
 
-	bool item_selected = selected_id.notNull();
 	buttonSetEnabled("teleport_btn",		friends_tab_active && item_selected);
 	buttonSetEnabled("view_profile_btn",	item_selected);
-	buttonSetEnabled("im_btn",				item_selected);
+	buttonSetEnabled("im_btn",				(selected_uuids.size() >= 1)); // allow starting the friends conference for multiple selection
 	buttonSetEnabled("call_btn",			item_selected && false); // not implemented yet
 	buttonSetEnabled("share_btn",			item_selected && false); // not implemented yet
 	buttonSetEnabled("group_info_btn",		item_selected);
@@ -877,7 +884,17 @@ void LLPanelPeople::onAddFriendWizButtonClicked()
 
 void LLPanelPeople::onDeleteFriendButtonClicked()
 {
-	LLAvatarActions::removeFriendDialog(getCurrentItemID());
+	std::vector<LLUUID> selected_uuids;
+	getCurrentItemIDs(selected_uuids);
+
+	if (selected_uuids.size() == 1)
+	{
+		LLAvatarActions::removeFriendDialog( selected_uuids.front() );
+	}
+	else if (selected_uuids.size() > 1)
+	{
+		LLAvatarActions::removeFriendsDialog( selected_uuids );
+	}
 }
 
 void LLPanelPeople::onGroupInfoButtonClicked()
@@ -963,6 +980,8 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)
 	}
 	else if (chosen_item == "view_icons")
 	{
+		mAllFriendList->toggleIcons();
+		mOnlineFriendList->toggleIcons();
 	}
 	else if (chosen_item == "organize_offline")
 	{
@@ -992,6 +1011,7 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)
 	}
 	else if (chosen_item == "view_icons")
 	{
+		mNearbyList->toggleIcons();
 	}
 	else if (chosen_item == "sort_distance")
 	{
@@ -1011,7 +1031,7 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)
 	}
 	else if (chosen_item == "view_icons")
 	{
-		// *TODO: implement showing/hiding icons
+		mRecentList->toggleIcons();
 	}
 }
 
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index aa6909560dd59a2372a609eed38f79b89a0af220..6181531f82e1968ed1b2109409527144e91360f1 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -73,10 +73,10 @@ LLPanelPicks::LLPanelPicks()
 	mPopupMenu(NULL),
 	mProfilePanel(NULL),
 	mPickPanel(NULL),
-	mPicksList(NULL)
-	, mPanelPickInfo(NULL)
-	, mPanelPickEdit(NULL)
-	, mOverflowMenu(NULL)
+	mPicksList(NULL),
+	mPanelPickInfo(NULL),
+	mPanelPickEdit(NULL),
+	mOverflowMenu(NULL)
 {
 }
 
diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp
index c6840721a31ba65d3748009196f798e8c70ce783..61e18195b83e700d0feeece8ddc9d3ea32b62b75 100644
--- a/indra/newview/llpanelplace.cpp
+++ b/indra/newview/llpanelplace.cpp
@@ -58,6 +58,7 @@
 //#include "llviewermenu.h"	// create_landmark()
 #include "llweb.h"
 #include "llsdutil.h"
+#include "llsdutil_math.h"
 
 LLPanelPlace::LLPanelPlace()
 :	LLPanel(),
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index 609b2059209f635a0b3fd4cf4c0ed7aaf91b5aab..34644cfe42d1bca8177db115f489214568c71f87 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -54,7 +54,10 @@
 #include "llaccordionctrltab.h"
 #include "llagent.h"
 #include "llagentui.h"
+#include "llappviewer.h"
 #include "llavatarpropertiesprocessor.h"
+#include "llcallbacklist.h"
+#include "llexpandabletextbox.h"
 #include "llfloaterworldmap.h"
 #include "llfloaterbuycurrency.h"
 #include "llinventorymodel.h"
@@ -65,8 +68,10 @@
 #include "llviewerinventory.h"
 #include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
+#include "llviewercontrol.h" 
 #include "llviewertexteditor.h"
 #include "llworldmap.h"
+#include "llsdutil_math.h"
 
 //----------------------------------------------------------------------------
 // Aux types and methods
@@ -75,7 +80,6 @@
 typedef std::pair<LLUUID, std::string> folder_pair_t;
 
 static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right);
-static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
 static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
 
 static LLRegisterPanelClassWrapper<LLPanelPlaceInfo> t_place_info("panel_place_info");
@@ -110,7 +114,7 @@ BOOL LLPanelPlaceInfo::postBuild()
 
 	mForSalePanel = getChild<LLPanel>("for_sale_panel");
 	mYouAreHerePanel = getChild<LLPanel>("here_panel");
-	LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLPanelPlaceInfo::updateYouAreHereBanner,this));
+	gIdleCallbacks.addFunction(&LLPanelPlaceInfo::updateYouAreHereBanner, this);
 	
 	//Icon value should contain sale price of last selected parcel. 
 	mForSalePanel->getChild<LLIconCtrl>("icon_for_sale")->
@@ -119,7 +123,7 @@ BOOL LLPanelPlaceInfo::postBuild()
 	mSnapshotCtrl = getChild<LLTextureCtrl>("logo");
 	mRegionName = getChild<LLTextBox>("region_title");
 	mParcelName = getChild<LLTextBox>("parcel_title");
-	mDescEditor = getChild<LLTextEditor>("description");
+	mDescEditor = getChild<LLExpandableTextBox>("description");
 
 	mMaturityRatingText = getChild<LLTextBox>("maturity_value");
 	mParcelOwner = getChild<LLTextBox>("owner_value");
@@ -455,13 +459,13 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
 		mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id);
 	}
 
-	if(!parcel_data.name.empty())
+	if(!parcel_data.sim_name.empty())
 	{
-		mParcelName->setText(parcel_data.name);
+		mRegionName->setText(parcel_data.sim_name);
 	}
 	else
 	{
-		mParcelName->setText(LLStringUtil::null);
+		mRegionName->setText(LLStringUtil::null);
 	}
 
 	if(!parcel_data.desc.empty())
@@ -508,19 +512,22 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
 		region_z = llround(mPosRegion.mV[VZ]);
 	}
 
-	std::string name = getString("not_available");
-	if (!parcel_data.sim_name.empty())
+	if (!parcel_data.name.empty())
 	{
-		name = llformat("%s (%d, %d, %d)",
-						parcel_data.sim_name.c_str(), region_x, region_y, region_z);
-		mRegionName->setText(name);
+		mParcelName->setText(llformat("%s (%d, %d, %d)",
+							 parcel_data.name.c_str(), region_x, region_y, region_z));
+	}
+	else
+	{
+		mParcelName->setText(getString("not_available"));
 	}
 
 	if (mInfoType == CREATE_LANDMARK)
 	{
 		if (parcel_data.name.empty())
 		{
-			mTitleEditor->setText(name);
+			mTitleEditor->setText(llformat("%s (%d, %d, %d)",
+								  parcel_data.sim_name.c_str(), region_x, region_y, region_z));
 		}
 		else
 		{
@@ -609,6 +616,9 @@ void LLPanelPlaceInfo::displaySelectedParcelInfo(LLParcel* parcel,
 	parcel_data.name = parcel->getName();
 	parcel_data.sim_name = region->getName();
 	parcel_data.snapshot_id = parcel->getSnapshotID();
+	mPosRegion.setVec((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
+					  (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
+					  (F32)pos_global.mdV[VZ]);
 	parcel_data.global_x = pos_global.mdV[VX];
 	parcel_data.global_y = pos_global.mdV[VY];
 	parcel_data.global_z = pos_global.mdV[VZ];
@@ -985,18 +995,24 @@ void LLPanelPlaceInfo::populateFoldersList()
 		mFolderCombo->add(it->second, LLSD(it->first));
 }
 
-void LLPanelPlaceInfo::updateYouAreHereBanner()
+//static
+void LLPanelPlaceInfo::updateYouAreHereBanner(void* userdata)
 {
 	//YouAreHere Banner should be displayed only for selected places, 
 	// If you want to display it for landmark or teleport history item, you should check by mParcelId
 	
-	bool is_you_are_here = false;
-	if (mSelectedParcelID != S32(-1) && !mLastSelectedRegionID.isNull())
+	LLPanelPlaceInfo* self  = static_cast<LLPanelPlaceInfo*>(userdata);
+	if(!self->getVisible())
+		return;
+	if(!gDisconnected)
 	{
-		is_you_are_here = gAgent.getRegion()->getRegionID()== mLastSelectedRegionID &&
-		mSelectedParcelID == LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID();
+		static F32 radius  = gSavedSettings.getF32("YouAreHereDistance");
+
+		BOOL display_banner = gAgent.getRegion()->getRegionID() == self->mLastSelectedRegionID && 
+			LLAgentUI::checkAgentDistance(self->mPosRegion, radius);
+
+		self->mYouAreHerePanel->setVisible(display_banner);
 	}
-	mYouAreHerePanel->setVisible(is_you_are_here);
 }
 
 void LLPanelPlaceInfo::onForSaleBannerClick()
@@ -1027,14 +1043,9 @@ void LLPanelPlaceInfo::onForSaleBannerClick()
 	
 	
 }
- 
 
-static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
-{
-	return left.second < right.second;
-}
-
-static std::string getFullFolderName(const LLViewerInventoryCategory* cat)
+/*static*/
+std::string LLPanelPlaceInfo::getFullFolderName(const LLViewerInventoryCategory* cat)
 {
 	std::string name = cat->getName();
 	LLUUID parent_id;
@@ -1056,6 +1067,11 @@ static std::string getFullFolderName(const LLViewerInventoryCategory* cat)
 	return name;
 }
 
+static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
+{
+	return left.second < right.second;
+}
+
 static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
 {
 	LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 7b3a8f050b98abde66539db5674e59930aac0b69..07a2434d59f598ded18f1baf63ae50cd3accbe06 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -43,6 +43,7 @@
 
 class LLButton;
 class LLComboBox;
+class LLExpandableTextBox;
 class LLInventoryItem;
 class LLLineEditor;
 class LLPanelPickEdit;
@@ -52,6 +53,7 @@ class LLTextBox;
 class LLTextEditor;
 class LLTextureCtrl;
 class LLViewerRegion;
+class LLViewerInventoryCategory;
 
 class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
 {
@@ -131,11 +133,13 @@ class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
 
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 	/*virtual*/ void handleVisibilityChange (BOOL new_visibility);
+	
+	 static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
 
 private:
 
 	void populateFoldersList();
-	void updateYouAreHereBanner();
+	static void updateYouAreHereBanner(void*);// added to gIdleCallbacks
 	void onForSaleBannerClick();
 
 	/**
@@ -161,7 +165,7 @@ class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
 	LLTextureCtrl*		mSnapshotCtrl;
 	LLTextBox*			mRegionName;
 	LLTextBox*			mParcelName;
-	LLTextEditor*		mDescEditor;
+	LLExpandableTextBox*mDescEditor;
 	LLTextBox*			mMaturityRatingText;
 	LLTextBox*			mParcelOwner;
 	LLTextBox*			mLastVisited;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 5ab823b6e53a49c77c54ada2c14cf33b091b562a..b2e9110e966311e287f2a29fea78bfbbb0de1efc 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -351,7 +351,16 @@ void LLPanelPlaces::setItem(LLInventoryItem* item)
 
 	if (is_landmark_editable)
 	{
-		mPlaceInfo->setLandmarkFolder(mItem->getParentUUID());
+		if(!mPlaceInfo->setLandmarkFolder(mItem->getParentUUID()) && !mItem->getParentUUID().isNull())
+		{
+			const LLViewerInventoryCategory* cat = gInventory.getCategory(mItem->getParentUUID());
+			if(cat)
+			{
+				std::string cat_fullname = LLPanelPlaceInfo::getFullFolderName(cat);
+				LLComboBox* folderList = mPlaceInfo->getChild<LLComboBox>("folder_combo");
+				folderList->add(cat_fullname, cat->getUUID(),ADD_TOP);
+			}
+		}
 	}
 
 	mPlaceInfo->displayItemInfo(mItem);
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e4b32c4820d379cbe98ddcc317995c6f03a88f01
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -0,0 +1,1102 @@
+/** 
+ * @file llpanelprimmediacontrols.cpp
+ * @brief media controls popup panel
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ * 
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+//LLPanelPrimMediaControls
+#include "llagent.h"
+#include "llparcel.h"
+#include "llpanel.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "llrender.h"
+#include "lldrawable.h"
+#include "llviewerwindow.h"
+#include "lluictrlfactory.h"
+#include "llbutton.h"
+#include "llface.h"
+#include "llcombobox.h"
+#include "llslider.h"
+#include "llhudview.h"
+#include "lliconctrl.h"
+#include "lltoolpie.h"
+#include "llviewercamera.h"
+#include "llviewerobjectlist.h"
+#include "llpanelprimmediacontrols.h"
+#include "llpluginclassmedia.h"
+#include "llprogressbar.h"
+#include "llviewercontrol.h"
+#include "llviewerparcelmgr.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
+#include "llvovolume.h"
+#include "llweb.h"
+#include "llwindow.h"
+
+glh::matrix4f glh_get_current_modelview();
+glh::matrix4f glh_get_current_projection();
+
+const F32 ZOOM_NEAR_PADDING		= 1.0f;
+const F32 ZOOM_MEDIUM_PADDING	= 1.15f;
+const F32 ZOOM_FAR_PADDING		= 1.5f;
+
+// Warning: make sure these two match!
+const LLPanelPrimMediaControls::EZoomLevel LLPanelPrimMediaControls::kZoomLevels[] = { ZOOM_NONE, ZOOM_MEDIUM };
+const int LLPanelPrimMediaControls::kNumZoomLevels = 2;
+
+//
+// LLPanelPrimMediaControls
+//
+
+LLPanelPrimMediaControls::LLPanelPrimMediaControls() : 
+	mAlpha(1.f),
+	mCurrentURL(""),
+	mPreviousURL(""),
+	mPauseFadeout(false),
+	mUpdateSlider(true),
+	mClearFaceOnFade(false),
+	mCurrentRate(0.0),
+	mMovieDuration(0.0),
+	mUpdatePercent(0)
+{
+	mCommitCallbackRegistrar.add("MediaCtrl.Close",		boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Back",		boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Forward",	boost::bind(&LLPanelPrimMediaControls::onClickForward, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Home",		boost::bind(&LLPanelPrimMediaControls::onClickHome, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Stop",		boost::bind(&LLPanelPrimMediaControls::onClickStop, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Reload",	boost::bind(&LLPanelPrimMediaControls::onClickReload, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Play",		boost::bind(&LLPanelPrimMediaControls::onClickPlay, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Pause",		boost::bind(&LLPanelPrimMediaControls::onClickPause, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Open",		boost::bind(&LLPanelPrimMediaControls::onClickOpen, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Zoom",		boost::bind(&LLPanelPrimMediaControls::onClickZoom, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.CommitURL",	boost::bind(&LLPanelPrimMediaControls::onCommitURL, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress",		boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp",	boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown",	boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.ToggleMute",		boost::bind(&LLPanelPrimMediaControls::onToggleMute, this));
+	
+	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_prim_media_controls.xml");
+	mInactivityTimer.reset();
+	mFadeTimer.stop();
+	mCurrentZoom = ZOOM_NONE;
+	mScrollState = SCROLL_NONE;
+
+	mPanelHandle.bind(this);
+}
+LLPanelPrimMediaControls::~LLPanelPrimMediaControls()
+{
+}
+
+BOOL LLPanelPrimMediaControls::postBuild()
+{
+	LLButton* scroll_up_ctrl = getChild<LLButton>("scrollup");
+	scroll_up_ctrl->setClickedCallback(onScrollUp, this);
+	scroll_up_ctrl->setHeldDownCallback(onScrollUpHeld, this);
+	scroll_up_ctrl->setMouseUpCallback(onScrollStop, this);
+	LLButton* scroll_left_ctrl = getChild<LLButton>("scrollleft");
+	scroll_left_ctrl->setClickedCallback(onScrollLeft, this);
+	scroll_left_ctrl->setHeldDownCallback(onScrollLeftHeld, this);
+	scroll_left_ctrl->setMouseUpCallback(onScrollStop, this);
+	LLButton* scroll_right_ctrl = getChild<LLButton>("scrollright");
+	scroll_right_ctrl->setClickedCallback(onScrollRight, this);
+	scroll_right_ctrl->setHeldDownCallback(onScrollRightHeld, this);
+	scroll_right_ctrl->setMouseUpCallback(onScrollStop, this);
+	LLButton* scroll_down_ctrl = getChild<LLButton>("scrolldown");
+	scroll_down_ctrl->setClickedCallback(onScrollDown, this);
+	scroll_down_ctrl->setHeldDownCallback(onScrollDownHeld, this);
+	scroll_down_ctrl->setMouseUpCallback(onScrollStop, this);
+	
+	LLUICtrl* media_address	= getChild<LLUICtrl>("media_address");
+	media_address->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this ));
+	mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout");
+	mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime");
+
+	mCurrentZoom = ZOOM_NONE;
+	// clicks on HUD buttons do not remove keyboard focus from media
+	setIsChrome(TRUE);
+	return TRUE;
+}
+
+void LLPanelPrimMediaControls::setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{
+	if (media_impl.notNull() && objectp.notNull())
+	{
+		mTargetImplID = media_impl->getMediaTextureID();
+		mTargetObjectID = objectp->getID();
+		mTargetObjectFace = face;
+		mTargetObjectNormal = pick_normal;
+		mClearFaceOnFade = false;
+	}
+	else
+	{
+		// This happens on a timer now.
+//		mTargetImplID = LLUUID::null;
+//		mTargetObjectID = LLUUID::null;
+//		mTargetObjectFace = 0;
+		mClearFaceOnFade = true;
+	}
+
+	updateShape();
+}
+
+void LLPanelPrimMediaControls::focusOnTarget()
+{
+	// Sets the media focus to the current target of the LLPanelPrimMediaControls.
+	// This is how we transition from hover to focus when the user clicks on a control.
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if(media_impl)
+	{
+		if(!media_impl->hasFocus())
+		{	
+			// The current target doesn't have media focus -- focus on it.
+			LLViewerObject* objectp = getTargetObject();
+			LLViewerMediaFocus::getInstance()->setFocusFace(objectp, mTargetObjectFace, media_impl, mTargetObjectNormal);
+		}
+	}	
+}
+
+LLViewerMediaImpl* LLPanelPrimMediaControls::getTargetMediaImpl()
+{
+	return LLViewerMedia::getMediaImplFromTextureID(mTargetImplID);
+}
+
+LLViewerObject* LLPanelPrimMediaControls::getTargetObject()
+{
+	return gObjectList.findObject(mTargetObjectID);
+}
+
+LLPluginClassMedia* LLPanelPrimMediaControls::getTargetMediaPlugin()
+{
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+	if(impl && impl->hasMedia())
+	{
+		return impl->getMediaPlugin();
+	}
+	
+	return NULL;
+}
+
+void LLPanelPrimMediaControls::updateShape()
+{
+	const S32 MIN_HUD_WIDTH=400;
+	const S32 MIN_HUD_HEIGHT=120;
+
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	LLViewerObject* objectp = getTargetObject();
+	
+	if(!media_impl)
+	{
+		setVisible(FALSE);
+		return;
+	}
+
+	LLPluginClassMedia* media_plugin = NULL;
+	if(media_impl->hasMedia())
+	{
+		media_plugin = media_impl->getMediaPlugin();
+	}
+	
+	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+	bool can_navigate = parcel->getMediaAllowNavigate();
+	bool enabled = false;
+	bool has_focus = media_impl->hasFocus();
+	setVisible(enabled);
+
+	if (objectp)
+	{
+		bool mini_controls = false;
+		LLMediaEntry *media_data = objectp->getTE(mTargetObjectFace)->getMediaData();
+		if (media_data && NULL != dynamic_cast<LLVOVolume*>(objectp))
+		{
+			// Don't show the media HUD if we do not have permissions
+			enabled = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
+			mini_controls = (LLMediaEntry::MINI == media_data->getControls());
+		}
+		
+		//
+		// Set the state of the buttons
+		//
+		LLUICtrl* back_ctrl					= getChild<LLUICtrl>("back");
+		LLUICtrl* fwd_ctrl					= getChild<LLUICtrl>("fwd");
+		LLUICtrl* reload_ctrl				= getChild<LLUICtrl>("reload");
+		LLUICtrl* play_ctrl					= getChild<LLUICtrl>("play");
+		LLUICtrl* pause_ctrl				= getChild<LLUICtrl>("pause");
+		LLUICtrl* stop_ctrl					= getChild<LLUICtrl>("stop");
+		LLUICtrl* media_stop_ctrl			= getChild<LLUICtrl>("media_stop");
+		LLUICtrl* home_ctrl					= getChild<LLUICtrl>("home");
+		LLUICtrl* close_ctrl				= getChild<LLUICtrl>("close");
+		LLUICtrl* open_ctrl					= getChild<LLUICtrl>("new_window");
+        LLUICtrl* zoom_ctrl					= getChild<LLUICtrl>("zoom_frame");
+		LLPanel* media_loading_panel		= getChild<LLPanel>("media_progress_indicator");
+		LLUICtrl* media_address_ctrl		= getChild<LLUICtrl>("media_address");
+		LLUICtrl* media_play_slider_panel	= getChild<LLUICtrl>("media_play_position");
+		LLUICtrl* media_play_slider_ctrl	= getChild<LLUICtrl>("media_play_slider");
+		LLUICtrl* volume_ctrl				= getChild<LLUICtrl>("media_volume");
+		LLButton* volume_btn				= getChild<LLButton>("media_volume_button");
+		LLUICtrl* volume_up_ctrl			= getChild<LLUICtrl>("volume_up");
+		LLUICtrl* volume_down_ctrl			= getChild<LLUICtrl>("volume_down");
+		LLIconCtrl* whitelist_icon			= getChild<LLIconCtrl>("media_whitelist_flag");
+		LLIconCtrl* secure_lock_icon		= getChild<LLIconCtrl>("media_secure_lock_flag");
+		
+		LLUICtrl* media_panel_scroll		= getChild<LLUICtrl>("media_panel_scroll");
+		LLUICtrl* scroll_up_ctrl			= getChild<LLUICtrl>("scrollup");
+		LLUICtrl* scroll_left_ctrl			= getChild<LLUICtrl>("scrollleft");
+		LLUICtrl* scroll_right_ctrl			= getChild<LLUICtrl>("scrollright");
+		LLUICtrl* scroll_down_ctrl			= getChild<LLUICtrl>("scrolldown");		
+				
+		// XXX RSP: TODO: FIXME: clean this up so that it is clearer what mode we are in,
+		// and that only the proper controls get made visible/enabled according to that mode. 
+		back_ctrl->setVisible(has_focus);
+		fwd_ctrl->setVisible(has_focus);
+		reload_ctrl->setVisible(has_focus);
+		stop_ctrl->setVisible(false);
+		home_ctrl->setVisible(has_focus);
+		close_ctrl->setVisible(has_focus);
+		open_ctrl->setVisible(true);
+		media_address_ctrl->setVisible(has_focus && !mini_controls);
+		media_play_slider_panel->setVisible(has_focus && !mini_controls);
+		volume_ctrl->setVisible(false);
+		volume_up_ctrl->setVisible(false);
+		volume_down_ctrl->setVisible(false);
+		
+		whitelist_icon->setVisible(!mini_controls && (media_data)?media_data->getWhiteListEnable():false);
+		// Disable zoom if HUD
+		zoom_ctrl->setEnabled(!objectp->isHUDAttachment());
+		secure_lock_icon->setVisible(false);
+		mCurrentURL = media_impl->getCurrentMediaURL();
+		
+		back_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate);
+		fwd_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateForward() && can_navigate);
+		stop_ctrl->setEnabled(has_focus && can_navigate);
+		home_ctrl->setEnabled(has_focus && can_navigate);
+		LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != NULL) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE;
+
+		if(media_plugin && media_plugin->pluginSupportsMediaTime())
+		{
+			reload_ctrl->setEnabled(FALSE);
+			reload_ctrl->setVisible(FALSE);
+			media_stop_ctrl->setVisible(has_focus);
+			home_ctrl->setVisible(FALSE);
+			back_ctrl->setEnabled(has_focus);
+			fwd_ctrl->setEnabled(has_focus);
+			media_address_ctrl->setVisible(false);
+			media_address_ctrl->setEnabled(false);
+			media_play_slider_panel->setVisible(!mini_controls);
+			media_play_slider_panel->setEnabled(!mini_controls);
+				
+			volume_ctrl->setVisible(has_focus);
+			volume_up_ctrl->setVisible(has_focus);
+			volume_down_ctrl->setVisible(has_focus);
+			volume_ctrl->setEnabled(has_focus);
+
+			whitelist_icon->setVisible(false);
+			secure_lock_icon->setVisible(false);
+			scroll_up_ctrl->setVisible(false);
+			scroll_left_ctrl->setVisible(false);
+			scroll_right_ctrl->setVisible(false);
+			scroll_down_ctrl->setVisible(false);
+			media_panel_scroll->setVisible(false);
+				
+			F32 volume = media_impl->getVolume();
+			// movie's url changed
+			if(mCurrentURL!=mPreviousURL)
+			{
+				mMovieDuration = media_plugin->getDuration();
+				mPreviousURL = mCurrentURL;
+			}
+				
+			if(mMovieDuration == 0) 
+			{
+				mMovieDuration = media_plugin->getDuration();
+				media_play_slider_ctrl->setValue(0);
+				media_play_slider_ctrl->setEnabled(false);
+			}
+			// TODO: What if it's not fully loaded
+					
+			if(mUpdateSlider && mMovieDuration!= 0)
+			{
+				F64 current_time =  media_plugin->getCurrentTime();
+				F32 percent = current_time / mMovieDuration;
+				media_play_slider_ctrl->setValue(percent);
+				media_play_slider_ctrl->setEnabled(true);
+			}
+				
+			// video vloume
+			if(volume <= 0.0)
+			{
+				volume_up_ctrl->setEnabled(TRUE);
+				volume_down_ctrl->setEnabled(FALSE);
+				media_impl->setVolume(0.0);
+				volume_btn->setToggleState(true);
+			}
+			else if (volume >= 1.0)
+			{
+				volume_up_ctrl->setEnabled(FALSE);
+				volume_down_ctrl->setEnabled(TRUE);
+				media_impl->setVolume(1.0);
+				volume_btn->setToggleState(false);
+			}
+			else
+			{
+				volume_up_ctrl->setEnabled(TRUE);
+				volume_down_ctrl->setEnabled(TRUE);
+			}
+				
+			switch(result)
+			{
+				case LLPluginClassMediaOwner::MEDIA_PLAYING:
+					play_ctrl->setEnabled(FALSE);
+					play_ctrl->setVisible(FALSE);
+					pause_ctrl->setEnabled(TRUE);
+					pause_ctrl->setVisible(has_focus);
+					media_stop_ctrl->setEnabled(TRUE);
+					
+					break;
+				case LLPluginClassMediaOwner::MEDIA_PAUSED:
+				default:
+					pause_ctrl->setEnabled(FALSE);
+					pause_ctrl->setVisible(FALSE);
+					play_ctrl->setEnabled(TRUE);
+					play_ctrl->setVisible(has_focus);
+					media_stop_ctrl->setEnabled(FALSE);
+					break;
+			}
+		}
+		else   // web based
+		{
+			if(media_plugin)
+			{
+				mCurrentURL = media_plugin->getLocation();
+			}
+			else
+			{
+				mCurrentURL.clear();
+			}
+				
+			play_ctrl->setVisible(FALSE);
+			pause_ctrl->setVisible(FALSE);
+			media_stop_ctrl->setVisible(FALSE);
+			media_address_ctrl->setVisible(has_focus && !mini_controls);
+			media_address_ctrl->setEnabled(has_focus && !mini_controls);
+			media_play_slider_panel->setVisible(FALSE);
+			media_play_slider_panel->setEnabled(FALSE);
+				
+			volume_ctrl->setVisible(FALSE);
+			volume_up_ctrl->setVisible(FALSE);
+			volume_down_ctrl->setVisible(FALSE);
+			volume_ctrl->setEnabled(FALSE);
+			volume_up_ctrl->setEnabled(FALSE);
+			volume_down_ctrl->setEnabled(FALSE);
+				
+			scroll_up_ctrl->setVisible(has_focus);
+			scroll_left_ctrl->setVisible(has_focus);
+			scroll_right_ctrl->setVisible(has_focus);
+			scroll_down_ctrl->setVisible(has_focus);
+			media_panel_scroll->setVisible(has_focus);
+			// TODO: get the secure lock bool from media plug in
+			std::string prefix =  std::string("https://");
+			std::string test_prefix = mCurrentURL.substr(0, prefix.length());
+			LLStringUtil::toLower(test_prefix);
+			if(test_prefix == prefix)
+			{
+				secure_lock_icon->setVisible(has_focus);
+			}
+				
+			if(mCurrentURL!=mPreviousURL)
+			{
+				setCurrentURL();
+				mPreviousURL = mCurrentURL;
+			}
+
+			if(result == LLPluginClassMediaOwner::MEDIA_LOADING)
+			{
+				reload_ctrl->setEnabled(FALSE);
+				reload_ctrl->setVisible(FALSE);
+				stop_ctrl->setEnabled(TRUE);
+				stop_ctrl->setVisible(has_focus);
+			}
+			else
+			{
+				reload_ctrl->setEnabled(TRUE);
+				reload_ctrl->setVisible(has_focus);
+				stop_ctrl->setEnabled(FALSE);
+				stop_ctrl->setVisible(FALSE);
+			}
+		}
+
+		
+		if(media_plugin)
+		{
+			//
+			// Handle progress bar
+			//
+			mUpdatePercent = media_plugin->getProgressPercent();
+			if(mUpdatePercent<100.0f)
+			{
+				media_loading_panel->setVisible(true);
+				getChild<LLProgressBar>("media_progress_bar")->setPercent(mUpdatePercent);
+				gFocusMgr.setTopCtrl(media_loading_panel);
+			}
+			else
+			{
+				media_loading_panel->setVisible(false);
+				gFocusMgr.setTopCtrl(NULL);
+			}
+		}
+
+		if(media_impl)
+		{
+			//
+			// Handle Scrolling
+			//
+			switch (mScrollState) 
+			{
+			case SCROLL_UP:
+				media_impl->scrollWheel(0, -1, MASK_NONE);
+				break;
+			case SCROLL_DOWN:
+				media_impl->scrollWheel(0, 1, MASK_NONE);
+				break;
+			case SCROLL_LEFT:
+				media_impl->scrollWheel(1, 0, MASK_NONE);
+//				media_impl->handleKeyHere(KEY_LEFT, MASK_NONE);
+				break;
+			case SCROLL_RIGHT:
+				media_impl->scrollWheel(-1, 0, MASK_NONE);
+//				media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
+				break;
+			case SCROLL_NONE:
+			default:
+				break;
+			}
+		}
+		
+		setVisible(enabled);
+
+		//
+		// Calculate position and shape of the controls
+		//
+		glh::matrix4f mat = glh_get_current_projection()*glh_get_current_modelview();
+		std::vector<LLVector3>::iterator vert_it;
+		std::vector<LLVector3>::iterator vert_end;
+		std::vector<LLVector3> vect_face;
+
+		LLVolume* volume = objectp->getVolume();
+
+		if (volume)
+		{
+			const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace);
+
+			const LLVector3* ext = vf.mExtents;
+
+			LLVector3 center = (ext[0]+ext[1])*0.5f;
+			LLVector3 size = (ext[1]-ext[0])*0.5f;
+			LLVector3 vert[] =
+			{
+				center + size.scaledVec(LLVector3(1,1,1)),
+				center + size.scaledVec(LLVector3(-1,1,1)),
+				center + size.scaledVec(LLVector3(1,-1,1)),
+				center + size.scaledVec(LLVector3(-1,-1,1)),
+				center + size.scaledVec(LLVector3(1,1,-1)),
+				center + size.scaledVec(LLVector3(-1,1,-1)),
+				center + size.scaledVec(LLVector3(1,-1,-1)),
+				center + size.scaledVec(LLVector3(-1,-1,-1)),
+			};
+
+			LLVOVolume* vo = (LLVOVolume*) objectp;
+
+			for (U32 i = 0; i < 8; i++)
+			{
+				vect_face.push_back(vo->volumePositionToAgent(vert[i]));	
+			}
+		}
+		vert_it = vect_face.begin();
+		vert_end = vect_face.end();
+
+		LLVector3 min = LLVector3(1,1,1);
+		LLVector3 max = LLVector3(-1,-1,-1);
+		for(; vert_it != vert_end; ++vert_it)
+		{
+			// project silhouette vertices into screen space
+			glh::vec3f screen_vert = glh::vec3f(vert_it->mV); 
+			mat.mult_matrix_vec(screen_vert);
+
+			// add to screenspace bounding box
+			update_min_max(min, max, LLVector3(screen_vert.v));
+		}
+
+        LLCoordGL screen_min;
+		screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidth() * (min.mV[VX] + 1.f) * 0.5f);
+		screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeight() * (min.mV[VY] + 1.f) * 0.5f);
+
+		LLCoordGL screen_max;
+		screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidth() * (max.mV[VX] + 1.f) * 0.5f);
+		screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeight() * (max.mV[VY] + 1.f) * 0.5f);
+
+		// grow panel so that screenspace bounding box fits inside "media_region" element of HUD
+		LLRect media_controls_rect;
+		getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_controls_rect);
+		LLView* media_region = getChild<LLView>("media_region");
+		media_controls_rect.mLeft -= media_region->getRect().mLeft;
+		media_controls_rect.mBottom -= media_region->getRect().mBottom;
+		media_controls_rect.mTop += getRect().getHeight() - media_region->getRect().mTop;
+		media_controls_rect.mRight += getRect().getWidth() - media_region->getRect().mRight;
+
+		LLRect old_hud_rect = media_controls_rect;
+		// keep all parts of HUD on-screen
+		media_controls_rect.intersectWith(getParent()->getLocalRect());
+
+		// clamp to minimum size, keeping centered
+		media_controls_rect.setCenterAndSize(media_controls_rect.getCenterX(), media_controls_rect.getCenterY(),
+			llmax(MIN_HUD_WIDTH, media_controls_rect.getWidth()), llmax(MIN_HUD_HEIGHT, media_controls_rect.getHeight()));
+
+		setShape(media_controls_rect, true);
+
+		// Test mouse position to see if the cursor is stationary
+		LLCoordWindow cursor_pos_window;
+		getWindow()->getCursorPosition(&cursor_pos_window);
+
+		// If last pos is not equal to current pos, the mouse has moved
+		// We need to reset the timer, and make sure the panel is visible
+		if(cursor_pos_window.mX != mLastCursorPos.mX ||
+			cursor_pos_window.mY != mLastCursorPos.mY ||
+			mScrollState != SCROLL_NONE)
+		{
+			mInactivityTimer.start();
+			mLastCursorPos = cursor_pos_window;
+		}
+		
+		if(isMouseOver() || hasFocus())
+		{
+			// Never fade the controls if the mouse is over them or they have keyboard focus.
+			mFadeTimer.stop();
+		}
+		else if(!mClearFaceOnFade && (mInactivityTimer.getElapsedTimeF32() < mInactiveTimeout))
+		{
+			// Mouse is over the object, but has not been stationary for long enough to fade the UI
+			mFadeTimer.stop();
+		}
+		else if(! mFadeTimer.getStarted() )
+		{
+			// we need to start fading the UI (and we have not already started)
+			mFadeTimer.reset();
+			mFadeTimer.start();
+		}
+		else
+		{
+			// I don't think this is correct anymore.  This is done in draw() after the fade has completed.
+//			setVisible(FALSE);
+		}
+	}
+}
+
+/*virtual*/
+void LLPanelPrimMediaControls::draw()
+{
+	F32 alpha = 1.f;
+	if(mFadeTimer.getStarted())
+	{
+		F32 time = mFadeTimer.getElapsedTimeF32();
+		alpha = llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f);
+
+		if(mFadeTimer.getElapsedTimeF32() >= mControlFadeTime)
+		{
+			if(mClearFaceOnFade)
+			{
+				// Hiding this object makes scroll events go missing after it fades out 
+				// (see DEV-41755 for a full description of the train wreck).
+				// Only hide the controls when we're untargeting.
+				setVisible(FALSE);
+
+				mClearFaceOnFade = false;
+				mTargetImplID = LLUUID::null;
+				mTargetObjectID = LLUUID::null;
+				mTargetObjectFace = 0;
+			}
+		}
+	}
+	
+	{
+		LLViewDrawContext context(alpha);
+		LLPanel::draw();
+	}
+}
+
+BOOL LLPanelPrimMediaControls::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+	mInactivityTimer.start();
+	return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
+}
+
+BOOL LLPanelPrimMediaControls::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+	mInactivityTimer.start();
+	return LLPanel::handleMouseDown(x, y, mask);
+}
+
+BOOL LLPanelPrimMediaControls::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+	mInactivityTimer.start();
+	return LLPanel::handleMouseUp(x, y, mask);
+}
+
+BOOL LLPanelPrimMediaControls::handleKeyHere( KEY key, MASK mask )
+{
+	mInactivityTimer.start();
+	return LLPanel::handleKeyHere(key, mask);
+}
+
+bool LLPanelPrimMediaControls::isMouseOver()
+{
+	bool result = false;
+	
+	if( getVisible() )
+	{
+		LLCoordWindow cursor_pos_window;
+		LLCoordScreen cursor_pos_screen;
+		LLCoordGL cursor_pos_gl;
+		S32 x, y;
+		getWindow()->getCursorPosition(&cursor_pos_window);
+		getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
+		
+		LLPanel* controls_panel = NULL;
+		controls_panel = getChild<LLPanel>("media_hover_controls");
+		if(controls_panel && !controls_panel->getVisible())
+		{
+			// The hover controls aren't visible -- use the focused controls instead.
+			controls_panel = getChild<LLPanel>("media_focused_controls");
+		}
+		
+		if(controls_panel && controls_panel->getVisible())
+		{
+			controls_panel->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &x, &y);
+
+			LLView *hit_child = controls_panel->childFromPoint(x, y);
+			if(hit_child)
+			{
+				// This was useful for debugging both coordinate translation and view hieararchy problems...
+//				llinfos << "mouse coords: " << x << ", " << y << " hit child " << hit_child->getName() << llendl;
+				result = true;
+			}
+		}
+	}
+
+	return result;
+}
+
+
+void LLPanelPrimMediaControls::onClickClose()
+{
+	close();
+}
+
+void LLPanelPrimMediaControls::close()
+{
+	LLViewerMediaFocus::getInstance()->clearFocus();
+	resetZoomLevel();
+	setVisible(FALSE);
+}
+
+
+void LLPanelPrimMediaControls::onClickBack()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl =getTargetMediaImpl();
+	
+	if (impl)
+	{
+		impl->navigateBack();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickForward()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+	
+	if (impl)
+	{
+		impl->navigateForward();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickHome()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->navigateHome();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickOpen()
+{
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+	if(impl)
+	{
+		LLWeb::loadURL(impl->getCurrentMediaURL());
+	}	
+}
+
+void LLPanelPrimMediaControls::onClickReload()
+{
+	focusOnTarget();
+
+	//LLViewerMedia::navigateHome();
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->navigateReload();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickPlay()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->play();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickPause()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->pause();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickStop()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->stop();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickZoom()
+{
+	focusOnTarget();
+
+	nextZoomLevel();
+}
+void LLPanelPrimMediaControls::nextZoomLevel()
+{
+	int index = 0;
+	while (index < kNumZoomLevels)
+	{
+		if (kZoomLevels[index] == mCurrentZoom) 
+		{
+			index++;
+			break;
+		}
+		index++;
+	}
+	mCurrentZoom = kZoomLevels[index % kNumZoomLevels];
+	updateZoom();
+}
+
+void LLPanelPrimMediaControls::resetZoomLevel()
+{
+	if(mCurrentZoom != ZOOM_NONE)
+	{
+		mCurrentZoom = ZOOM_NONE;
+		updateZoom();
+	}
+}
+
+void LLPanelPrimMediaControls::updateZoom()
+{
+	F32 zoom_padding = 0.0f;
+	switch (mCurrentZoom)
+	{
+	case ZOOM_NONE:
+		{
+			gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+			break;
+		}
+	case ZOOM_FAR:
+		{
+			zoom_padding = ZOOM_FAR_PADDING;
+			break;
+		}
+	case ZOOM_MEDIUM:
+		{
+			zoom_padding = ZOOM_MEDIUM_PADDING;
+			break;
+		}
+	case ZOOM_NEAR:
+		{
+			zoom_padding = ZOOM_NEAR_PADDING;
+			break;
+		}
+	default:
+		{
+			gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+			break;
+		}
+	}
+
+	if (zoom_padding > 0.0f)		
+		LLViewerMediaFocus::setCameraZoom(getTargetObject(), mTargetObjectNormal, zoom_padding);
+}
+void LLPanelPrimMediaControls::onScrollUp(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->focusOnTarget();
+
+	LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+	
+	if(impl)
+	{
+		impl->scrollWheel(0, -1, MASK_NONE);
+	}
+}
+void LLPanelPrimMediaControls::onScrollUpHeld(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_UP;
+}
+void LLPanelPrimMediaControls::onScrollRight(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->focusOnTarget();
+
+	LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->scrollWheel(-1, 0, MASK_NONE);
+//		impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
+	}
+}
+void LLPanelPrimMediaControls::onScrollRightHeld(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_RIGHT;
+}
+
+void LLPanelPrimMediaControls::onScrollLeft(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->focusOnTarget();
+
+	LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->scrollWheel(1, 0, MASK_NONE);
+//		impl->handleKeyHere(KEY_LEFT, MASK_NONE);
+	}
+}
+void LLPanelPrimMediaControls::onScrollLeftHeld(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_LEFT;
+}
+
+void LLPanelPrimMediaControls::onScrollDown(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->focusOnTarget();
+
+	LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+	
+	if(impl)
+	{
+		impl->scrollWheel(0, 1, MASK_NONE);
+	}
+}
+void LLPanelPrimMediaControls::onScrollDownHeld(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_DOWN;
+}
+
+void LLPanelPrimMediaControls::onScrollStop(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_NONE;
+}
+
+void LLPanelPrimMediaControls::onCommitURL()
+{
+	focusOnTarget();
+
+	LLUICtrl *media_address_ctrl = getChild<LLUICtrl>("media_address_url");
+	std::string url = media_address_ctrl->getValue().asString();
+	if(getTargetMediaImpl() && !url.empty())
+	{
+		getTargetMediaImpl()->navigateTo( url, "", true);
+
+		// Make sure keyboard focus is set to the media focus object.
+		gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
+			
+	}
+	mPauseFadeout = false;
+	mFadeTimer.start();
+}
+
+
+void LLPanelPrimMediaControls::onInputURL(LLFocusableElement* caller, void *userdata)
+{
+
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (userdata);
+	this_panel->focusOnTarget();
+
+	this_panel->mPauseFadeout = true;
+	this_panel->mFadeTimer.stop();
+	this_panel->mFadeTimer.reset();
+	
+}
+
+void LLPanelPrimMediaControls::setCurrentURL()
+{	
+#ifdef USE_COMBO_BOX_FOR_MEDIA_URL
+	LLComboBox* media_address_combo	= getChild<LLComboBox>("media_address_combo");
+	// redirects will navigate momentarily to about:blank, don't add to history
+	if (media_address_combo && mCurrentURL != "about:blank")
+	{
+		media_address_combo->remove(mCurrentURL);
+		media_address_combo->add(mCurrentURL, ADD_SORTED);
+		media_address_combo->selectByValue(mCurrentURL);
+	}
+#else   // USE_COMBO_BOX_FOR_MEDIA_URL
+	LLLineEditor* media_address_url = getChild<LLLineEditor>("media_address_url");
+	if (media_address_url && mCurrentURL != "about:blank")
+	{
+		media_address_url->setValue(mCurrentURL);
+	}
+#endif	// USE_COMBO_BOX_FOR_MEDIA_URL
+}
+
+void LLPanelPrimMediaControls::onCommitSlider()
+{
+	focusOnTarget();
+
+	LLSlider* media_play_slider_ctrl	= getChild<LLSlider>("media_play_slider");
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if (media_impl) 
+	{
+		// get slider value
+		F64 slider_value = media_play_slider_ctrl->getValue().asReal();
+		if(slider_value <= 0.0)
+		{	
+			media_impl->stop();
+		}
+		else 
+		{
+			media_impl->seek(slider_value*mMovieDuration);
+			//mUpdateSlider= false;
+		}
+	}
+}		
+
+void LLPanelPrimMediaControls::onCommitVolumeUp()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if (media_impl) 
+	{
+		F32 volume = media_impl->getVolume();
+		
+		volume += 0.1f;
+		if(volume >= 1.0f)
+		{
+			volume = 1.0f;
+		}
+		
+		media_impl->setVolume(volume);
+		getChild<LLButton>("media_volume")->setToggleState(false);
+	}
+}		
+
+void LLPanelPrimMediaControls::onCommitVolumeDown()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if (media_impl) 
+	{
+		F32 volume = media_impl->getVolume();
+		
+		volume -= 0.1f;
+		if(volume <= 0.0f)
+		{
+			volume = 0.0f;
+		}
+
+		media_impl->setVolume(volume);
+		getChild<LLButton>("media_volume")->setToggleState(false);
+	}
+}		
+
+
+void LLPanelPrimMediaControls::onToggleMute()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if (media_impl) 
+	{
+		F32 volume = media_impl->getVolume();
+		
+		if(volume > 0.0)
+		{
+			media_impl->setVolume(0.0);
+		}
+		else 
+		{
+			media_impl->setVolume(0.5);
+		}
+	}
+}
+
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ec7aa2356c14614ce919050ba8b1b9da5970580
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -0,0 +1,148 @@
+/** 
+ * @file llpanelprimmediacontrols.h
+ * @brief Pop-up media controls panel
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ * 
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_PANELPRIMMEDIACONTROLS_H
+#define LL_PANELPRIMMEDIACONTROLS_H
+
+#include "llpanel.h"
+#include "llviewermedia.h"
+
+class LLCoordWindow;
+class LLViewerMediaImpl;
+
+class LLPanelPrimMediaControls : public LLPanel
+{
+public:
+	LLPanelPrimMediaControls();
+	virtual ~LLPanelPrimMediaControls();
+	/*virtual*/ BOOL postBuild();
+	virtual void draw();
+	virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+
+	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+	virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+	virtual BOOL handleKeyHere(KEY key, MASK mask);
+	
+	void updateShape();
+	bool isMouseOver();
+	void nextZoomLevel();
+	void resetZoomLevel();
+	void close();
+
+	LLHandle<LLPanelPrimMediaControls>	getHandle() const { return mPanelHandle; }
+	void setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
+
+
+	enum EZoomLevel
+	{
+		ZOOM_NONE = 0,
+		ZOOM_FAR,
+		ZOOM_MEDIUM,
+		ZOOM_NEAR
+	};
+	static const EZoomLevel kZoomLevels[];
+	static const int kNumZoomLevels;
+	
+	enum EScrollDir
+	{
+		SCROLL_UP = 0,
+		SCROLL_DOWN,
+		SCROLL_LEFT,
+		SCROLL_RIGHT,
+		SCROLL_NONE
+	};
+
+private:
+	void onClickClose();
+	void onClickBack();
+	void onClickForward();
+	void onClickHome();
+	void onClickOpen();
+	void onClickReload();
+	void onClickPlay();
+	void onClickPause();
+	void onClickStop();
+	void onClickZoom();
+	void onCommitURL();
+	
+	void updateZoom();
+	void setCurrentURL();
+	void onCommitSlider();
+	
+	void onCommitVolumeUp();
+	void onCommitVolumeDown();
+	void onToggleMute();
+	
+	static void onScrollUp(void* user_data);
+	static void onScrollUpHeld(void* user_data);
+	static void onScrollLeft(void* user_data);
+	static void onScrollLeftHeld(void* user_data);
+	static void onScrollRight(void* user_data);
+	static void onScrollRightHeld(void* user_data);
+	static void onScrollDown(void* user_data);
+	static void onScrollDownHeld(void* user_data);
+	static void onScrollStop(void* user_data);
+	
+	static void onInputURL(LLFocusableElement* caller, void *userdata);
+	static bool hasControlsPermission(LLViewerObject *obj, const LLMediaEntry *media_entry);
+	
+	void focusOnTarget();
+	
+	LLViewerMediaImpl* getTargetMediaImpl();
+	LLViewerObject* getTargetObject();
+	LLPluginClassMedia* getTargetMediaPlugin();
+	bool mPauseFadeout;
+	bool mUpdateSlider;
+	bool mClearFaceOnFade;
+
+	LLMatrix4 mLastCameraMat;
+	EZoomLevel mCurrentZoom;
+	EScrollDir mScrollState;
+	LLCoordWindow mLastCursorPos;
+	LLFrameTimer mInactivityTimer;
+	LLFrameTimer mFadeTimer;
+	F32 mInactiveTimeout;
+	F32 mControlFadeTime;
+	LLRootHandle<LLPanelPrimMediaControls> mPanelHandle;
+	F32 mAlpha;
+	std::string mCurrentURL;
+	std::string mPreviousURL;
+	F64 mCurrentRate;
+	F64 mMovieDuration;
+	int mUpdatePercent;
+
+	LLUUID mTargetObjectID;
+	S32 mTargetObjectFace;
+	LLUUID mTargetImplID;
+	LLVector3 mTargetObjectNormal;
+};
+
+#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp
index 1d16c4ef5e8e746fb648791dd6cba20bc54a3f09..d4ab5013f9592dc4a54e667375d53441e7f6e903 100644
--- a/indra/newview/llpanelprofileview.cpp
+++ b/indra/newview/llpanelprofileview.cpp
@@ -32,10 +32,12 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "llavatarconstants.h"
 #include "lluserrelations.h"
 
 #include "llpanelprofileview.h"
 
+#include "llavatarpropertiesprocessor.h"
 #include "llcallingcard.h"
 #include "llpanelavatar.h"
 #include "llpanelpicks.h"
@@ -48,14 +50,46 @@ static std::string PANEL_NOTES = "panel_notes";
 static const std::string PANEL_PROFILE = "panel_profile";
 static const std::string PANEL_PICKS = "panel_picks";
 
+
+class AvatarStatusObserver : public LLAvatarPropertiesObserver
+{
+public:
+	AvatarStatusObserver(LLPanelProfileView* profile_view)
+	{
+		mProfileView = profile_view;
+	}
+
+	void processProperties(void* data, EAvatarProcessorType type)
+	{
+		if(APT_PROPERTIES != type) return;
+		const LLAvatarData* avatar_data = static_cast<const LLAvatarData*>(data);
+		if(avatar_data && mProfileView->getAvatarId() == avatar_data->avatar_id)
+		{
+			mProfileView->processOnlineStatus(avatar_data->flags & AVATAR_ONLINE);
+			LLAvatarPropertiesProcessor::instance().removeObserver(mProfileView->getAvatarId(), this);
+		}
+	}
+
+	void subscribe()
+	{
+		LLAvatarPropertiesProcessor::instance().addObserver(mProfileView->getAvatarId(), this);
+	}
+
+private:
+	LLPanelProfileView* mProfileView;
+};
+
 LLPanelProfileView::LLPanelProfileView()
 :	LLPanelProfile()
 ,	mStatusText(NULL)
+,	mAvatarStatusObserver(NULL)
 {
+	mAvatarStatusObserver = new AvatarStatusObserver(this);
 }
 
 LLPanelProfileView::~LLPanelProfileView(void)
 {
+	delete mAvatarStatusObserver;
 }
 
 /*virtual*/ 
@@ -66,6 +100,9 @@ void LLPanelProfileView::onOpen(const LLSD& key)
 	{
 		id = key["id"];
 	}
+
+	// subscribe observer to get online status. Request will be sent by LLPanelAvatarProfile itself
+	mAvatarStatusObserver->subscribe();
 	if(id.notNull() && getAvatarId() != id)
 	{
 		setAvatarId(id);
@@ -74,10 +111,12 @@ void LLPanelProfileView::onOpen(const LLSD& key)
 	// Update the avatar name.
 	gCacheName->get(getAvatarId(), FALSE,
 		boost::bind(&LLPanelProfileView::onAvatarNameCached, this, _1, _2, _3, _4));
-
+/*
+// disable this part of code according to EXT-2022. See processOnlineStatus
 	// status should only show if viewer has permission to view online/offline. EXT-453 
 	mStatusText->setVisible(isGrantedToSeeOnlineStatus());
 	updateOnlineStatus();
+*/
 
 	LLPanelProfile::onOpen(key);
 }
@@ -93,6 +132,7 @@ BOOL LLPanelProfileView::postBuild()
 	getTabContainer()[PANEL_PROFILE]->childSetVisible("status_combo", FALSE);
 
 	mStatusText = getChild<LLTextBox>("status");
+	mStatusText->setVisible(false);
 
 	childSetCommitCallback("back",boost::bind(&LLPanelProfileView::onBackBtnClick,this),NULL);
 	
@@ -135,13 +175,18 @@ void LLPanelProfileView::updateOnlineStatus()
 		return;
 
 	bool online = relationship->isOnline();
-//	std::string statusName();
 
 	std::string status = getString(online ? "status_online" : "status_offline");
 
 	mStatusText->setValue(status);
 }
 
+void LLPanelProfileView::processOnlineStatus(bool online)
+{
+	mAvatarIsOnline = online;
+	mStatusText->setVisible(online);
+}
+
 void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& first_name, const std::string& last_name, BOOL is_group)
 {
 	llassert(getAvatarId() == id);
@@ -155,7 +200,7 @@ void LLPanelProfileView::togglePanel(LLPanel* panel)
 	{
 		// LLPanelProfile::togglePanel shows/hides all children,
 		// we don't want to display online status for non friends, so re-hide it here
-		mStatusText->setVisible(isGrantedToSeeOnlineStatus());
+		mStatusText->setVisible(mAvatarIsOnline);
 	}
 }
 
diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h
index 07a6c3a9a08de8ee579485d7d5eeac5bf3858dc4..b59d1d42f31acbcda672ae1f9379829adb3d3bc5 100644
--- a/indra/newview/llpanelprofileview.h
+++ b/indra/newview/llpanelprofileview.h
@@ -40,6 +40,7 @@
 class LLPanelProfile;
 class LLPanelProfileTab;
 class LLTextBox;
+class AvatarStatusObserver;
 
 /**
 * Panel for displaying Avatar's profile. It consists of three sub panels - Profile,
@@ -49,6 +50,7 @@ class LLPanelProfileView : public LLPanelProfile
 {
 	LOG_CLASS(LLPanelProfileView);
 	friend class LLUICtrlFactory;
+	friend class AvatarStatusObserver;
 
 public:
 
@@ -65,8 +67,9 @@ class LLPanelProfileView : public LLPanelProfile
 protected:
 
 	void onBackBtnClick();
-	bool isGrantedToSeeOnlineStatus();
-	void updateOnlineStatus();
+	bool isGrantedToSeeOnlineStatus(); // deprecated after EXT-2022 is implemented
+	void updateOnlineStatus(); // deprecated after EXT-2022 is implemented
+	void processOnlineStatus(bool online);
 
 private:
 	// LLCacheName will call this function when avatar name is loaded from server.
@@ -78,6 +81,8 @@ class LLPanelProfileView : public LLPanelProfile
 		BOOL is_group);
 
 	LLTextBox* mStatusText;
+	AvatarStatusObserver* mAvatarStatusObserver;
+	bool mAvatarIsOnline;
 };
 
 #endif //LL_LLPANELPROFILEVIEW_H
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 25e773e8b8557ff590d75792eb46741269b5966d..e97eb1df2b66e8f1df7f4145e31f9c07acaf35bb 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -34,7 +34,7 @@
 
 #include "llparticipantlist.h"
 #include "llavatarlist.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
 
 //LLParticipantList retrieves add, clear and remove events and updates view accordingly 
 LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list):
@@ -48,6 +48,18 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
 	mSpeakerMgr->addListener(mSpeakerAddListener, "add");
 	mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
 	mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
+
+	//Lets fill avatarList with existing speakers
+	LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
+
+	LLSpeakerMgr::speaker_list_t speaker_list;
+	mSpeakerMgr->getSpeakerList(&speaker_list, true);
+	for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)
+	{
+		group_members.push_back((*it)->mID);
+	}
+	mAvatarList->setDirty();
+	mAvatarList->sortByName();
 }
 
 LLParticipantList::~LLParticipantList()
@@ -87,8 +99,12 @@ bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::L
 bool LLParticipantList::SpeakerRemoveListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
 {
 	LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
-	group_members.erase(std::find(group_members.begin(), group_members.end(), event->getValue().asUUID()));
-	mAvatarList->setDirty();
+	LLAvatarList::uuid_vector_t::iterator pos = std::find(group_members.begin(), group_members.end(), event->getValue().asUUID());
+	if(pos != group_members.end())
+	{
+		group_members.erase(pos);
+		mAvatarList->setDirty();
+	}
 	return true;
 }
 
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 1683d113a997638c8fe89d9b7397933d52728639..e4dbcbd21928875ac7b4242ed84ac1369bdb3337 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -44,7 +44,6 @@
 #include "lltrans.h"
 
 #include "lldockablefloater.h"
-#include "llimpanel.h"
 #include "llsyswellwindow.h"
 #include "llimfloater.h"
 
@@ -191,19 +190,22 @@ void LLScreenChannel::onToastFade(LLToast* toast)
 {	
 	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), static_cast<LLPanel*>(toast));
 		
-	bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
-	if(delete_toast)
-	{
-		mToastList.erase(it);
-		deleteToast(toast);
-	}
-	else
+	if(it != mToastList.end())
 	{
-		storeToast((*it));
-		mToastList.erase(it);
-	}	
+		bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
+		if(delete_toast)
+		{
+			mToastList.erase(it);
+			deleteToast(toast);
+		}
+		else
+		{
+			storeToast((*it));
+			mToastList.erase(it);
+		}	
 
-	redrawToasts();
+		redrawToasts();
+	}
 }
 
 //--------------------------------------------------------------------------
@@ -247,6 +249,7 @@ void LLScreenChannel::loadStoredToastsToChannel()
 
 	for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
 	{
+		(*it).toast->setIsHidden(false);
 		(*it).toast->resetTimer();
 		mToastList.push_back((*it));
 	}
@@ -266,6 +269,7 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
 	mOverflowToastHidden = false;
 
 	LLToast* toast = (*it).toast;
+	toast->setIsHidden(false);
 	toast->resetTimer();
 	mToastList.push_back((*it));
 	mStoredToastList.erase(it);
@@ -519,6 +523,7 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer)
 	LLRect toast_rect;
 	LLToast::Params p;
 	p.lifetime_secs = timer;
+	p.enable_hide_btn = false;
 	mStartUpToastPanel = new LLToast(p);
 
 	if(!mStartUpToastPanel)
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index a5e3a0492be59a98f3e9fc4d4259864fbbeb35ca..a2d0b71962ff8172196ba07b7cb27fa469c8f1a3 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -4904,7 +4904,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 		{
 			inspect_item_id = inspect_instance->getSelectedUUID();
 		}
-		LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getSelectedUUID();
 		for (S32 pass = 0; pass < 2; pass++)
 		{
 			for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
@@ -4918,11 +4917,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 				{
 					continue;
 				}
-				if (objectp->getID() == focus_item_id)
-				{
-					node->renderOneSilhouette(gFocusMgr.getFocusColor());
-				}
-				else if(objectp->getID() == inspect_item_id)
+				if(objectp->getID() == inspect_item_id)
 				{
 					node->renderOneSilhouette(sHighlightInspectColor);
 				}
@@ -4976,6 +4971,19 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 		}
 	}
 
+#if 0	
+	// Hilight focused media object
+	{
+		LLViewerObject* objectp = LLViewerMediaFocus::getInstance()->getFocusedObject();
+		if(objectp)
+		{
+			// FIXME: how do I construct a silhouette for an object that's not selected?
+			// Would we need to add another LLObjectSelectionHandle for this purpose?
+			node->renderOneSilhouette(gFocusMgr.getFocusColor());
+		}
+	}
+#endif
+
 	if (for_hud && avatar)
 	{
 		glMatrixMode(GL_PROJECTION);
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 329d7d26ee0aadc33fb30fdd9fc15ac244d3a46e..a11ee05532fe8e920607409696d943de7861e618 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -111,12 +111,72 @@ bool	LLSideTray::instanceCreated	()
 	return sInstance!=0;
 }
 
-LLSideTrayTab::LLSideTrayTab(const Params& params):mMainPanel(0)
+//////////////////////////////////////////////////////////////////////////////
+// LLSideTrayTab
+// Represents a single tab in the side tray, only used by LLSideTray
+//////////////////////////////////////////////////////////////////////////////
+
+class LLSideTrayTab: public LLPanel
 {
-	mImagePath = params.image_path;
-	mTabTitle = params.tab_title;
-	mDescription = params.description;
+	friend class LLUICtrlFactory;
+	friend class LLSideTray;
+public:
+	
+	struct Params 
+	:	public LLInitParam::Block<Params, LLPanel::Params>
+	{
+		// image name
+		Optional<std::string>		image;
+		Optional<std::string>		image_selected;
+		Optional<std::string>		tab_title;
+		Optional<std::string>		description;
+		Params()
+		:	image("image"),
+			image_selected("image_selected"),
+			tab_title("tab_title","no title"),
+			description("description","no description")
+		{};
+	};
+protected:
+	LLSideTrayTab(const Params& params);
+	
+	
+public:
+	virtual ~LLSideTrayTab();
+	
+    /*virtual*/ BOOL	postBuild	();
+	/*virtual*/ bool	addChild	(LLView* view, S32 tab_group);
+	
+	
+	void			arrange		(S32 width, S32 height);
+	void			reshape		(S32 width, S32 height, BOOL called_from_parent = TRUE);
+	
+	static LLSideTrayTab*  createInstance	();
+	
+	const std::string& getDescription () const { return mDescription;}
+	const std::string& getTabTitle() const { return mTabTitle;}
+	
+	void draw();
+	
+	void			onOpen		(const LLSD& key);
+	
+private:
+	std::string mTabTitle;
+	std::string mImage;
+	std::string mImageSelected;
+	std::string	mDescription;
+	
+	LLView*	mMainPanel;
+};
 
+LLSideTrayTab::LLSideTrayTab(const Params& p)
+:	LLPanel(),
+	mTabTitle(p.tab_title),
+	mImage(p.image),
+	mImageSelected(p.image_selected),
+	mDescription(p.description),
+	mMainPanel(NULL)
+{
 	// Necessary for focus movement among child controls
 	setFocusRoot(TRUE);
 }
@@ -221,6 +281,18 @@ LLSideTrayTab*  LLSideTrayTab::createInstance	()
 	return tab;
 }
 
+//////////////////////////////////////////////////////////////////////////////
+// LLSideTray
+//////////////////////////////////////////////////////////////////////////////
+
+LLSideTray::Params::Params()
+:	collapsed("collapsed",false),
+	tab_btn_image_normal("tab_btn_image","sidebar_tab_left.tga"),
+	tab_btn_image_selected("tab_btn_image_selected","button_enabled_selected_32x128.tga"),
+	default_button_width("tab_btn_width",32),
+	default_button_height("tab_btn_height",32),
+	default_button_margin("tab_btn_margin",0)
+{}
 
 //virtual 
 LLSideTray::LLSideTray(Params& params)
@@ -255,35 +327,6 @@ BOOL LLSideTray::postBuild()
 	setMouseOpaque(false);
 	return true;
 }
-    
-/**
- * add new panel to tab with tab_name name
- * @param tab_name - name of sidebar tab to add new panel
- * @param panel - pointer to panel 
- */
-bool        LLSideTray::addPanel        ( const std::string& tab_name
-										,LLPanel* panel )
-{
-	return false;
-}
-/**
- * Add new tab to side bar
- * @param tab_name - name of the new tab
- * @param image - image for new sidebar button
- * @param title -  title for new tab
- */
-bool        LLSideTray::addTab          ( const std::string& tab_name
-										,const std::string& image
-										,const std::string& title)
-{
-	LLSideTrayTab::Params params;
-	params.image_path = image;
-	params.tab_title = title;
-	LLSideTrayTab* tab = LLUICtrlFactory::create<LLSideTrayTab> (params);
-	addChild(tab,1);
-	return true;
-}
-
 
 LLSideTrayTab* LLSideTray::getTab(const std::string& name)
 {
@@ -291,15 +334,19 @@ LLSideTrayTab* LLSideTray::getTab(const std::string& name)
 }
 
 
-
-void LLSideTray::toggleTabButton	(LLSideTrayTab* tab)
+void LLSideTray::toggleTabButton(LLSideTrayTab* tab)
 {
 	if(tab == NULL)
 		return;
-	string name = tab->getName();
-	std::map<std::string,LLButton*>::iterator tIt = mTabButtons.find(name);
-	if(tIt!=mTabButtons.end())
-		tIt->second->setToggleState(!tIt->second->getToggleState());
+	std::string name = tab->getName();
+	std::map<std::string,LLButton*>::iterator it = mTabButtons.find(name);
+	if(it != mTabButtons.end())
+	{
+		LLButton* btn = it->second;
+		bool new_state = !btn->getToggleState();
+		btn->setToggleState(new_state); 
+		btn->setImageOverlay( new_state ? tab->mImageSelected : tab->mImage );
+	}
 }
 
 bool LLSideTray::selectTabByIndex(size_t index)
@@ -307,9 +354,7 @@ bool LLSideTray::selectTabByIndex(size_t index)
 	if(index>=mTabs.size())
 		return false;
 
-	LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(mTabs[index]);
-	if(sidebar_tab == NULL)
-		return false;
+	LLSideTrayTab* sidebar_tab = mTabs[index];
 	return selectTabByName(sidebar_tab->getName());
 }
 
@@ -338,9 +383,7 @@ bool LLSideTray::selectTabByName	(const std::string& name)
 	child_vector_const_iter_t child_it;
 	for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
 	{
-		LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
-		if(sidebar_tab == NULL)
-			continue;
+		LLSideTrayTab* sidebar_tab = *child_it;
 		sidebar_tab->setVisible(sidebar_tab  == mActiveTab);
 	}
 	return true;
@@ -393,25 +436,28 @@ bool LLSideTray::addChild(LLView* view, S32 tab_group)
 
 void	LLSideTray::createButtons	()
 {
-	//create show/hide button
-	mCollapseButton = createButton(EXPANDED_NAME,"",boost::bind(&LLSideTray::onToggleCollapse, this));
-
 	//create buttons for tabs
 	child_vector_const_iter_t child_it = mTabs.begin();
-	++child_it;
-
 	for ( ; child_it != mTabs.end(); ++child_it)
 	{
-		LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
-		if(sidebar_tab == NULL)
-			continue;
+		LLSideTrayTab* sidebar_tab = *child_it;
 
-		string name = sidebar_tab->getName();
+		std::string name = sidebar_tab->getName();
 		
-		LLButton* button = createButton("",sidebar_tab->mImagePath,boost::bind(&LLSideTray::onTabButtonClick, this, sidebar_tab->getName()));
-		mTabButtons[sidebar_tab->getName()] = button;
+		// The "home" button will open/close the whole panel, this will need to
+		// change if the home screen becomes its own tab.
+		if (name == "sidebar_home")
+		{
+			mCollapseButton = createButton("",sidebar_tab->mImage,
+				boost::bind(&LLSideTray::onToggleCollapse, this));
+		}
+		else
+		{
+			LLButton* button = createButton("",sidebar_tab->mImage,
+				boost::bind(&LLSideTray::onTabButtonClick, this, name));
+			mTabButtons[name] = button;
+		}
 	}
-	
 }
 
 void		LLSideTray::onTabButtonClick(string name)
@@ -480,9 +526,7 @@ void LLSideTray::arrange			()
 	int offset = (sidetray_params.default_button_height+sidetray_params.default_button_margin)*2;
 	for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)	
 	{
-		LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
-		if(sidebar_tab == NULL)
-			continue;
+		LLSideTrayTab* sidebar_tab = *child_it;
 		
 		ctrl_rect.setLeftTopAndSize(0,getRect().getHeight()-offset
 								,sidetray_params.default_button_width
@@ -505,34 +549,56 @@ void LLSideTray::arrange			()
 	//arrange tabs
 	for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
 	{
-		LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
-		if(sidebar_tab == NULL)
-			continue;
-		
+		LLSideTrayTab* sidebar_tab = *child_it;
 		sidebar_tab->setRect(ctrl_rect);
 		sidebar_tab->arrange(mMaxBarWidth,getRect().getHeight());
 	}
 }
 
-void LLSideTray::collapseSideBar	()
+void LLSideTray::collapseSideBar()
 {
 	mCollapsed = true;
-	mCollapseButton->setLabel(COLLAPSED_NAME);
+	// Reset all overlay images, because there is no "selected" tab when the
+	// whole side tray is hidden.
+	child_vector_const_iter_t it = mTabs.begin();
+	for ( ; it != mTabs.end(); ++it )
+	{
+		LLSideTrayTab* tab = *it;
+		std::string name = tab->getName();
+		std::map<std::string,LLButton*>::const_iterator btn_it =
+			mTabButtons.find(name);
+		if (btn_it != mTabButtons.end())
+		{
+			LLButton* btn = btn_it->second;
+			btn->setImageOverlay( tab->mImage );
+		}
+	}
+		
+	// Home tab doesn't put its button in mTabButtons
+	LLSideTrayTab* home_tab = getTab("sidebar_home");
+	if (home_tab)
+	{
+		mCollapseButton->setImageOverlay( home_tab->mImage );
+	}
 	mActiveTab->setVisible(FALSE);
 	reflectCollapseChange();
 	setFocus( FALSE );
 
 }
-void LLSideTray::expandSideBar	()
+
+void LLSideTray::expandSideBar()
 {
 	mCollapsed = false;
-	mCollapseButton->setLabel(EXPANDED_NAME);
+	LLSideTrayTab* home_tab = getTab("sidebar_home");
+	if (home_tab)
+	{
+		mCollapseButton->setImageOverlay( home_tab->mImageSelected );
+	}
 	LLSD key;//empty
 	mActiveTab->onOpen(key);
 	mActiveTab->setVisible(TRUE);
 
 	reflectCollapseChange();
-
 }
 
 void LLSideTray::highlightFocused()
@@ -588,9 +654,7 @@ void LLSideTray::reshape			(S32 width, S32 height, BOOL called_from_parent)
 	int offset = (sidetray_params.default_button_height+sidetray_params.default_button_margin)*2;
 	for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)	
 	{
-		LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
-		if(sidebar_tab == NULL)
-			continue;
+		LLSideTrayTab* sidebar_tab = *child_it;
 		
 		ctrl_rect.setLeftTopAndSize(0,getRect().getHeight()-offset
 								,sidetray_params.default_button_width
@@ -612,9 +676,7 @@ void LLSideTray::reshape			(S32 width, S32 height, BOOL called_from_parent)
 	
 	for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
 	{
-		LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
-		if(sidebar_tab == NULL)
-			continue;
+		LLSideTrayTab* sidebar_tab = *child_it;
 		sidebar_tab->reshape(mMaxBarWidth,getRect().getHeight());
 		ctrl_rect.setLeftTopAndSize(sidetray_params.default_button_width,getRect().getHeight(),mMaxBarWidth,getRect().getHeight());
 		sidebar_tab->setRect(ctrl_rect);
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
index 6ea6bafac95b40af2ca27a2db7e9d847377317af..b49251ec79b5535435d3311eedc8a71c4ec9a9b1 100644
--- a/indra/newview/llsidetray.h
+++ b/indra/newview/llsidetray.h
@@ -36,59 +36,9 @@
 #include "llpanel.h"
 #include "string"
 
-class LLSideTray;
+class LLSideTrayTab;
 class LLAccordionCtrl;
 
-class LLSideTrayTab: public LLPanel
-{
-	friend class LLUICtrlFactory;
-	friend class LLSideTray;
-public:
-
-	struct Params 
-	:	public LLInitParam::Block<Params, LLPanel::Params>
-	{
-		// image name
-		Optional<std::string>		image_path;
-		Optional<std::string>		tab_title;
-		Optional<std::string>		description;
-		Params()
-		:	image_path("image"),
-			tab_title("tab_title","no title"),
-			description("description","no description")
-		{};
-	};
-protected:
-	LLSideTrayTab(const Params& params);
-	
-
-public:
-	virtual ~LLSideTrayTab();
-
-    /*virtual*/ BOOL	postBuild	();
-	/*virtual*/ bool	addChild	(LLView* view, S32 tab_group);
-
-
-	void			arrange		(S32 width, S32 height);
-	void			reshape		(S32 width, S32 height, BOOL called_from_parent = TRUE);
-	
-	static LLSideTrayTab*  createInstance	();
-
-	const std::string& getDescription () const { return mDescription;}
-	const std::string& getTabTitle() const { return mTabTitle;}
-
-	void draw();
-
-	void			onOpen		(const LLSD& key);
-
-private:
-	std::string mTabTitle;
-	std::string mImagePath;
-	std::string	mDescription;
-
-	LLView*	mMainPanel;
-};
-
 // added inheritance from LLDestroyClass<LLSideTray> to enable Side Tray perform necessary actions 
 // while disconnecting viewer in LLAppViewer::disconnectViewer().
 // LLDestroyClassList::instance().fireCallbacks() calls destroyClass method. See EXT-245.
@@ -112,21 +62,14 @@ class LLSideTray : public LLPanel, private LLDestroyClass<LLSideTray>
 		Optional<S32>				default_button_height;
 		Optional<S32>				default_button_margin;
 		
-		Params()
-		:	collapsed("collapsed",false),
-			tab_btn_image_normal("tab_btn_image","sidebar_tab_left.tga"),
-			tab_btn_image_selected("tab_btn_image_selected","button_enabled_selected_32x128.tga"),
-			default_button_width("tab_btn_width",32),
-			default_button_height("tab_btn_height",32),
-			default_button_margin("tab_btn_margin",0)
-		{};
+		Params();
 	};
 
 	static LLSideTray*	getInstance		();
 	static bool			instanceCreated	();
 protected:
 	LLSideTray(Params& params);
-	typedef std::vector<LLView*> child_vector_t;
+	typedef std::vector<LLSideTrayTab*> child_vector_t;
 	typedef child_vector_t::iterator					child_vector_iter_t;
 	typedef child_vector_t::const_iterator  			child_vector_const_iter_t;
 	typedef child_vector_t::reverse_iterator 			child_vector_reverse_iter_t;
@@ -146,23 +89,6 @@ class LLSideTray : public LLPanel, private LLDestroyClass<LLSideTray>
      */
 	bool		selectTabByIndex(size_t index);
 
-    /**
-     * add new panel to tab with tab_name name
-     * @param tab_name - name of sidebar tab to add new panel
-     * @param panel - pointer to panel 
-     */
-    bool        addPanel        ( const std::string& tab_name
-                                 ,LLPanel* panel );
-    /**
-     * Add new tab to side bar
-     * @param tab_name - name of the new tab
-     * @param image - image for new sidebar button
-     * @param title -  title for new tab
-     */
-    bool        addTab          ( const std::string& tab_name
-                                 ,const std::string& image
-                                 ,const std::string& title);
-
 	/**
 	 * Activate tab with "panel_name" panel
 	 * if no such tab - return NULL, otherwise a pointer to the panel
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2341fcfc6d64cc2be9d3f747f0df3a57ac0db457
--- /dev/null
+++ b/indra/newview/llspeakers.cpp
@@ -0,0 +1,639 @@
+/** 
+ * @file llspeakers.cpp
+ * @brief Management interface for muting and controlling volume of residents currently speaking
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ * 
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llspeakers.h"
+
+#include "llagent.h"
+#include "llappviewer.h"
+#include "llmutelist.h"
+#include "llsdutil.h"
+#include "lluicolortable.h"
+#include "llviewerobjectlist.h"
+#include "llvoavatar.h"
+#include "llworld.h"
+
+const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers
+const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
+const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
+
+LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerType type) : 
+	mStatus(LLSpeaker::STATUS_TEXT_ONLY),
+	mLastSpokeTime(0.f), 
+	mSpeechVolume(0.f), 
+	mHasSpoken(FALSE),
+	mHasLeftCurrentCall(FALSE),
+	mDotColor(LLColor4::white),
+	mID(id),
+	mTyping(FALSE),
+	mSortIndex(0),
+	mType(type),
+	mIsModerator(FALSE),
+	mModeratorMutedVoice(FALSE),
+	mModeratorMutedText(FALSE)
+{
+	if (name.empty() && type == SPEAKER_AGENT)
+	{
+		lookupName();
+	}
+	else
+	{
+		mDisplayName = name;
+	}
+
+	gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));
+
+	mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+}
+
+
+void LLSpeaker::lookupName()
+{
+	gCacheName->get(mID, FALSE, boost::bind(&LLSpeaker::onAvatarNameLookup, this, _1, _2, _3, _4));
+}
+
+void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+{
+	mDisplayName = first + " " + last;
+}
+
+LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker text moderation event")
+{
+}
+
+LLSD LLSpeakerTextModerationEvent::getValue()
+{
+	return std::string("text");
+}
+
+
+LLSpeakerVoiceModerationEvent::LLSpeakerVoiceModerationEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker voice moderation event")
+{
+}
+
+LLSD LLSpeakerVoiceModerationEvent::getValue()
+{
+	return std::string("voice");
+}
+
+LLSpeakerListChangeEvent::LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id)
+: LLEvent(source, "Speaker added/removed from speaker mgr"),
+  mSpeakerID(speaker_id)
+{
+}
+
+LLSD LLSpeakerListChangeEvent::getValue()
+{
+	return mSpeakerID;
+}
+
+// helper sort class
+struct LLSortRecentSpeakers
+{
+	bool operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const;
+};
+
+bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const
+{
+	// Sort first on status
+	if (lhs->mStatus != rhs->mStatus) 
+	{
+		return (lhs->mStatus < rhs->mStatus);
+	}
+
+	// and then on last speaking time
+	if(lhs->mLastSpokeTime != rhs->mLastSpokeTime)
+	{
+		return (lhs->mLastSpokeTime > rhs->mLastSpokeTime);
+	}
+	
+	// and finally (only if those are both equal), on name.
+	return(	lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );
+}
+
+
+//
+// LLSpeakerMgr
+//
+
+LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) : 
+	mVoiceChannel(channelp)
+{
+}
+
+LLSpeakerMgr::~LLSpeakerMgr()
+{
+}
+
+LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
+{
+	if (id.isNull()) return NULL;
+
+	LLPointer<LLSpeaker> speakerp;
+	if (mSpeakers.find(id) == mSpeakers.end())
+	{
+		speakerp = new LLSpeaker(id, name, type);
+		speakerp->mStatus = status;
+		mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
+		mSpeakersSorted.push_back(speakerp);
+		fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
+	}
+	else
+	{
+		speakerp = findSpeaker(id);
+		if (speakerp.notNull())
+		{
+			// keep highest priority status (lowest value) instead of overriding current value
+			speakerp->mStatus = llmin(speakerp->mStatus, status);
+			speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+			// RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
+			// we need to override speakers that we think are objects when we find out they are really
+			// residents
+			if (type == LLSpeaker::SPEAKER_AGENT)
+			{
+				speakerp->mType = LLSpeaker::SPEAKER_AGENT;
+				speakerp->lookupName();
+			}
+		}
+	}
+
+	return speakerp;
+}
+
+void LLSpeakerMgr::update(BOOL resort_ok)
+{
+	if (!gVoiceClient)
+	{
+		return;
+	}
+	
+	LLColor4 speaking_color = LLUIColorTable::instance().getColor("SpeakingColor");
+	LLColor4 overdriven_color = LLUIColorTable::instance().getColor("OverdrivenColor");
+
+	if(resort_ok) // only allow list changes when user is not interacting with it
+	{
+		updateSpeakerList();
+	}
+
+	// update status of all current speakers
+	BOOL voice_channel_active = (!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
+	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();)
+	{
+		LLUUID speaker_id = speaker_it->first;
+		LLSpeaker* speakerp = speaker_it->second;
+		
+		speaker_map_t::iterator  cur_speaker_it = speaker_it++;
+
+		if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id))
+		{
+			speakerp->mSpeechVolume = gVoiceClient->getCurrentPower(speaker_id);
+			BOOL moderator_muted_voice = gVoiceClient->getIsModeratorMuted(speaker_id);
+			if (moderator_muted_voice != speakerp->mModeratorMutedVoice)
+			{
+				speakerp->mModeratorMutedVoice = moderator_muted_voice;
+				speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp));
+			}
+
+			if (gVoiceClient->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice)
+			{
+				speakerp->mStatus = LLSpeaker::STATUS_MUTED;
+			}
+			else if (gVoiceClient->getIsSpeaking(speaker_id))
+			{
+				// reset inactivity expiration
+				if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING)
+				{
+					speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
+					speakerp->mHasSpoken = TRUE;
+				}
+				speakerp->mStatus = LLSpeaker::STATUS_SPEAKING;
+				// interpolate between active color and full speaking color based on power of speech output
+				speakerp->mDotColor = speaking_color;
+				if (speakerp->mSpeechVolume > LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
+				{
+					speakerp->mDotColor = overdriven_color;
+				}
+			}
+			else
+			{
+				speakerp->mSpeechVolume = 0.f;
+				speakerp->mDotColor = ACTIVE_COLOR;
+
+				if (speakerp->mHasSpoken)
+				{
+					// have spoken once, not currently speaking
+					speakerp->mStatus = LLSpeaker::STATUS_HAS_SPOKEN;
+				}
+				else
+				{
+					// default state for being in voice channel
+					speakerp->mStatus = LLSpeaker::STATUS_VOICE_ACTIVE;
+				}
+			}
+		}
+		// speaker no longer registered in voice channel, demote to text only
+		else if (speakerp->mStatus != LLSpeaker::STATUS_NOT_IN_CHANNEL)
+		{
+			if(speakerp->mType == LLSpeaker::SPEAKER_EXTERNAL)
+			{
+				// external speakers should be timed out when they leave the voice channel (since they only exist via SLVoice)
+				speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+			}
+			else
+			{
+				speakerp->mStatus = LLSpeaker::STATUS_TEXT_ONLY;
+				speakerp->mSpeechVolume = 0.f;
+				speakerp->mDotColor = ACTIVE_COLOR;
+			}
+		}
+	}
+
+	if(resort_ok)  // only allow list changes when user is not interacting with it
+	{
+		// sort by status then time last spoken
+		std::sort(mSpeakersSorted.begin(), mSpeakersSorted.end(), LLSortRecentSpeakers());
+	}
+
+	// for recent speakers who are not currently speaking, show "recent" color dot for most recent
+	// fading to "active" color
+
+	S32 recent_speaker_count = 0;
+	S32 sort_index = 0;
+	speaker_list_t::iterator sorted_speaker_it;
+	for(sorted_speaker_it = mSpeakersSorted.begin(); 
+		sorted_speaker_it != mSpeakersSorted.end(); )
+	{
+		LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
+		
+		// color code recent speakers who are not currently speaking
+		if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN)
+		{
+			speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f));
+			recent_speaker_count++;
+		}
+
+		// stuff sort ordinal into speaker so the ui can sort by this value
+		speakerp->mSortIndex = sort_index++;
+
+		// remove speakers that have been gone too long
+		if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired())
+		{
+			fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "remove");
+
+			mSpeakers.erase(speakerp->mID);
+			sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it);
+		}
+		else
+		{
+			++sorted_speaker_it;
+		}
+	}
+}
+
+void LLSpeakerMgr::updateSpeakerList()
+{
+	// are we bound to the currently active voice channel?
+	if ((!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()))
+	{
+		LLVoiceClient::participantMap* participants = gVoiceClient->getParticipantList();
+		if(participants)
+		{
+			LLVoiceClient::participantMap::iterator participant_it;
+
+			// add new participants to our list of known speakers
+			for (participant_it = participants->begin(); participant_it != participants->end(); ++participant_it)
+			{
+				LLVoiceClient::participantState* participantp = participant_it->second;
+				setSpeaker(participantp->mAvatarID, participantp->mDisplayName, LLSpeaker::STATUS_VOICE_ACTIVE, (participantp->isAvatar()?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL));
+			}
+		}
+	}
+}
+
+LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
+{
+	speaker_map_t::iterator found_it = mSpeakers.find(speaker_id);
+	if (found_it == mSpeakers.end())
+	{
+		return NULL;
+	}
+	return found_it->second;
+}
+
+void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_text)
+{
+	speaker_list->clear();
+	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+	{
+		LLPointer<LLSpeaker> speakerp = speaker_it->second;
+		// what about text only muted or inactive?
+		if (include_text || speakerp->mStatus != LLSpeaker::STATUS_TEXT_ONLY)
+		{
+			speaker_list->push_back(speakerp);
+		}
+	}
+}
+
+const LLUUID LLSpeakerMgr::getSessionID() 
+{ 
+	return mVoiceChannel->getSessionID(); 
+}
+
+
+void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing)
+{
+	LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+	if (speakerp.notNull())
+	{
+		speakerp->mTyping = typing;
+	}
+}
+
+// speaker has chatted via either text or voice
+void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id)
+{
+	LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+	if (speakerp.notNull())
+	{
+		speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
+		speakerp->mHasSpoken = TRUE;
+	}
+}
+
+BOOL LLSpeakerMgr::isVoiceActive()
+{
+	// mVoiceChannel = NULL means current voice channel, whatever it is
+	return LLVoiceClient::voiceEnabled() && mVoiceChannel && mVoiceChannel->isActive();
+}
+
+
+//
+// LLIMSpeakerMgr
+//
+LLIMSpeakerMgr::LLIMSpeakerMgr(LLVoiceChannel* channel) : LLSpeakerMgr(channel)
+{
+}
+
+void LLIMSpeakerMgr::updateSpeakerList()
+{
+	// don't do normal updates which are pulled from voice channel
+	// rely on user list reported by sim
+	
+	// We need to do this to allow PSTN callers into group chats to show in the list.
+	LLSpeakerMgr::updateSpeakerList();
+	
+	return;
+}
+
+void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
+{
+	if ( !speakers.isMap() ) return;
+
+	if ( speakers.has("agent_info") && speakers["agent_info"].isMap() )
+	{
+		LLSD::map_const_iterator speaker_it;
+		for(speaker_it = speakers["agent_info"].beginMap();
+			speaker_it != speakers["agent_info"].endMap();
+			++speaker_it)
+		{
+			LLUUID agent_id(speaker_it->first);
+
+			LLPointer<LLSpeaker> speakerp = setSpeaker(
+				agent_id,
+				LLStringUtil::null,
+				LLSpeaker::STATUS_TEXT_ONLY);
+
+			if ( speaker_it->second.isMap() )
+			{
+				speakerp->mIsModerator = speaker_it->second["is_moderator"];
+				speakerp->mModeratorMutedText =
+					speaker_it->second["mutes"]["text"];
+			}
+		}
+	}
+	else if ( speakers.has("agents" ) && speakers["agents"].isArray() )
+	{
+		//older, more decprecated way.  Need here for
+		//using older version of servers
+		LLSD::array_const_iterator speaker_it;
+		for(speaker_it = speakers["agents"].beginArray();
+			speaker_it != speakers["agents"].endArray();
+			++speaker_it)
+		{
+			const LLUUID agent_id = (*speaker_it).asUUID();
+
+			LLPointer<LLSpeaker> speakerp = setSpeaker(
+				agent_id,
+				LLStringUtil::null,
+				LLSpeaker::STATUS_TEXT_ONLY);
+		}
+	}
+}
+
+void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
+{
+	if ( !update.isMap() ) return;
+
+	if ( update.has("agent_updates") && update["agent_updates"].isMap() )
+	{
+		LLSD::map_const_iterator update_it;
+		for(
+			update_it = update["agent_updates"].beginMap();
+			update_it != update["agent_updates"].endMap();
+			++update_it)
+		{
+			LLUUID agent_id(update_it->first);
+			LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
+
+			LLSD agent_data = update_it->second;
+
+			if (agent_data.isMap() && agent_data.has("transition"))
+			{
+				if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
+				{
+					speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+					speakerp->mDotColor = INACTIVE_COLOR;
+					speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+				}
+				else if (agent_data["transition"].asString() == "ENTER")
+				{
+					// add or update speaker
+					speakerp = setSpeaker(agent_id);
+				}
+				else
+				{
+					llwarns << "bad membership list update " << ll_print_sd(agent_data["transition"]) << llendl;
+				}
+			}
+
+			if (speakerp.isNull()) continue;
+
+			// should have a valid speaker from this point on
+			if (agent_data.isMap() && agent_data.has("info"))
+			{
+				LLSD agent_info = agent_data["info"];
+
+				if (agent_info.has("is_moderator"))
+				{
+					speakerp->mIsModerator = agent_info["is_moderator"];
+				}
+
+				if (agent_info.has("mutes"))
+				{
+					speakerp->mModeratorMutedText = agent_info["mutes"]["text"];
+				}
+			}
+		}
+	}
+	else if ( update.has("updates") && update["updates"].isMap() )
+	{
+		LLSD::map_const_iterator update_it;
+		for (
+			update_it = update["updates"].beginMap();
+			update_it != update["updates"].endMap();
+			++update_it)
+		{
+			LLUUID agent_id(update_it->first);
+			LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
+
+			std::string agent_transition = update_it->second.asString();
+			if (agent_transition == "LEAVE" && speakerp.notNull())
+			{
+				speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+				speakerp->mDotColor = INACTIVE_COLOR;
+				speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+			}
+			else if ( agent_transition == "ENTER")
+			{
+				// add or update speaker
+				speakerp = setSpeaker(agent_id);
+			}
+			else
+			{
+				llwarns << "bad membership list update "
+						<< agent_transition << llendl;
+			}
+		}
+	}
+}
+
+
+//
+// LLActiveSpeakerMgr
+//
+
+LLActiveSpeakerMgr::LLActiveSpeakerMgr() : LLSpeakerMgr(NULL)
+{
+}
+
+void LLActiveSpeakerMgr::updateSpeakerList()
+{
+	// point to whatever the current voice channel is
+	mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+
+	// always populate from active voice channel
+	if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel)
+	{
+		fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
+		mSpeakers.clear();
+		mSpeakersSorted.clear();
+		mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+	}
+	LLSpeakerMgr::updateSpeakerList();
+
+	// clean up text only speakers
+	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+	{
+		LLUUID speaker_id = speaker_it->first;
+		LLSpeaker* speakerp = speaker_it->second;
+		if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
+		{
+			// automatically flag text only speakers for removal
+			speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+		}
+	}
+
+}
+
+
+
+//
+// LLLocalSpeakerMgr
+//
+
+LLLocalSpeakerMgr::LLLocalSpeakerMgr() : LLSpeakerMgr(LLVoiceChannelProximal::getInstance())
+{
+}
+
+LLLocalSpeakerMgr::~LLLocalSpeakerMgr ()
+{
+}
+
+void LLLocalSpeakerMgr::updateSpeakerList()
+{
+	// pull speakers from voice channel
+	LLSpeakerMgr::updateSpeakerList();
+
+	if (gDisconnected)//the world is cleared.
+	{
+		return ;
+	}
+
+	// pick up non-voice speakers in chat range
+	std::vector<LLUUID> avatar_ids;
+	std::vector<LLVector3d> positions;
+	LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS);
+	for(U32 i=0; i<avatar_ids.size(); i++)
+	{
+		setSpeaker(avatar_ids[i]);
+	}
+
+	// check if text only speakers have moved out of chat range
+	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+	{
+		LLUUID speaker_id = speaker_it->first;
+		LLSpeaker* speakerp = speaker_it->second;
+		if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
+		{
+			LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id);
+			if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)
+			{
+				speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+				speakerp->mDotColor = INACTIVE_COLOR;
+				speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+			}
+		}
+	}
+}
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0f22bff4f421ba7f75dad8d595bcc19b6a02f4f
--- /dev/null
+++ b/indra/newview/llspeakers.h
@@ -0,0 +1,172 @@
+/** 
+ * @file llspeakers.h
+ * @brief Management interface for muting and controlling volume of residents currently speaking
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ * 
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSPEAKERS_H
+#define LL_LLSPEAKERS_H
+
+#include "llevent.h"
+#include "llspeakers.h"
+#include "llvoicechannel.h"
+
+class LLSpeakerMgr;
+
+// data for a given participant in a voice channel
+class LLSpeaker : public LLRefCount, public LLOldEvents::LLObservable, public LLHandleProvider<LLSpeaker>, public boost::signals2::trackable
+{
+public:
+	typedef enum e_speaker_type
+	{
+		SPEAKER_AGENT,
+		SPEAKER_OBJECT,
+		SPEAKER_EXTERNAL	// Speaker that doesn't map to an avatar or object (i.e. PSTN caller in a group)
+	} ESpeakerType;
+
+	typedef enum e_speaker_status
+	{
+		STATUS_SPEAKING,
+		STATUS_HAS_SPOKEN,
+		STATUS_VOICE_ACTIVE,
+		STATUS_TEXT_ONLY,
+		STATUS_NOT_IN_CHANNEL,
+		STATUS_MUTED
+	} ESpeakerStatus;
+
+
+	LLSpeaker(const LLUUID& id, const std::string& name = LLStringUtil::null, const ESpeakerType type = SPEAKER_AGENT);
+	~LLSpeaker() {};
+	void lookupName();
+
+	void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+
+	ESpeakerStatus	mStatus;			// current activity status in speech group
+	F32				mLastSpokeTime;		// timestamp when this speaker last spoke
+	F32				mSpeechVolume;		// current speech amplitude (timea average rms amplitude?)
+	std::string		mDisplayName;		// cache user name for this speaker
+	LLFrameTimer	mActivityTimer;	// time out speakers when they are not part of current voice channel
+	BOOL			mHasSpoken;			// has this speaker said anything this session?
+	BOOL			mHasLeftCurrentCall;	// has this speaker left the current voice call?
+	LLColor4		mDotColor;
+	LLUUID			mID;
+	BOOL			mTyping;
+	S32				mSortIndex;
+	ESpeakerType	mType;
+	BOOL			mIsModerator;
+	BOOL			mModeratorMutedVoice;
+	BOOL			mModeratorMutedText;
+};
+
+class LLSpeakerTextModerationEvent : public LLOldEvents::LLEvent
+{
+public:
+	LLSpeakerTextModerationEvent(LLSpeaker* source);
+	/*virtual*/ LLSD getValue();
+};
+
+class LLSpeakerVoiceModerationEvent : public LLOldEvents::LLEvent
+{
+public:
+	LLSpeakerVoiceModerationEvent(LLSpeaker* source);
+	/*virtual*/ LLSD getValue();
+};
+
+class LLSpeakerListChangeEvent : public LLOldEvents::LLEvent
+{
+public:
+	LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id);
+	/*virtual*/ LLSD getValue();
+
+private:
+	const LLUUID& mSpeakerID;
+};
+
+class LLSpeakerMgr : public LLOldEvents::LLObservable
+{
+public:
+	LLSpeakerMgr(LLVoiceChannel* channelp);
+	virtual ~LLSpeakerMgr();
+
+	LLPointer<LLSpeaker> findSpeaker(const LLUUID& avatar_id);
+	void update(BOOL resort_ok);
+	void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing);
+	void speakerChatted(const LLUUID& speaker_id);
+	LLPointer<LLSpeaker> setSpeaker(const LLUUID& id, 
+					const std::string& name = LLStringUtil::null, 
+					LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY, 
+					LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT);
+
+	BOOL isVoiceActive();
+
+	typedef std::vector<LLPointer<LLSpeaker> > speaker_list_t;
+	void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text);
+	LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; }
+	const LLUUID getSessionID();
+
+protected:
+	virtual void updateSpeakerList();
+
+	typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
+	speaker_map_t		mSpeakers;
+
+	speaker_list_t		mSpeakersSorted;
+	LLFrameTimer		mSpeechTimer;
+	LLVoiceChannel*		mVoiceChannel;
+};
+
+class LLIMSpeakerMgr : public LLSpeakerMgr
+{
+public:
+	LLIMSpeakerMgr(LLVoiceChannel* channel);
+	
+	void updateSpeakers(const LLSD& update);
+	void setSpeakers(const LLSD& speakers);
+protected:
+	virtual void updateSpeakerList();
+};
+
+class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr>
+{
+public:
+	LLActiveSpeakerMgr();
+protected:
+	virtual void updateSpeakerList();
+};
+
+class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr>
+{
+public:
+	LLLocalSpeakerMgr();
+	~LLLocalSpeakerMgr ();
+protected:
+	virtual void updateSpeakerList();
+};
+
+#endif // LL_LLSPEAKERS_H
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 8793d226464cfe4a344c03aa2ce97ccdfda57a37..9aa74e8b9f90c39ebdda57db4dc1ae8120d963d5 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -56,7 +56,6 @@
 #include "llcachename.h"
 #include "lldir.h"
 #include "llerrorcontrol.h"
-#include "llfiltersd2xmlrpc.h"
 #include "llfloaterreg.h"
 #include "llfocusmgr.h"
 #include "llhttpsender.h"
@@ -66,10 +65,11 @@
 #include "llmemorystream.h"
 #include "llmessageconfig.h"
 #include "llmoveview.h"
+#include "llteleporthistory.h"
 #include "llregionhandle.h"
 #include "llsd.h"
 #include "llsdserialize.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
 #include "llsecondlifeurls.h"
 #include "llstring.h"
 #include "lluserrelations.h"
@@ -103,7 +103,6 @@
 #include "llfloaterland.h"
 #include "llfloaterpreference.h"
 #include "llfloatertopobjects.h"
-#include "llfloatertos.h"
 #include "llfloaterworldmap.h"
 #include "llgesturemgr.h"
 #include "llgroupmgr.h"
@@ -116,6 +115,7 @@
 #include "llfriendcard.h"
 #include "llkeyboard.h"
 #include "llloginhandler.h"			// gLoginHandler, SLURL support
+#include "lllogininstance.h" // Host the login module.
 #include "llpanellogin.h"
 #include "llmutelist.h"
 #include "llnotify.h"
@@ -133,7 +133,6 @@
 #include "llsecondlifeurls.h"
 #include "llselectmgr.h"
 #include "llsky.h"
-#include "llsrv.h"
 #include "llstatview.h"
 #include "lltrans.h"
 #include "llstatusbar.h"		// sendMoneyBalanceRequest(), owns L$ balance
@@ -146,7 +145,6 @@
 #include "llurlsimstring.h"
 #include "llurlhistory.h"
 #include "llurlwhitelist.h"
-#include "lluserauth.h"
 #include "llvieweraudio.h"
 #include "llviewerassetstorage.h"
 #include "llviewercamera.h"
@@ -190,6 +188,9 @@
 #include "llappearancemgr.h"
 #include "llavatariconctrl.h"
 
+#include "lllogin.h"
+#include "llevents.h"
+
 #if LL_WINDOWS
 #include "llwindebug.h"
 #include "lldxhardware.h"
@@ -203,12 +204,12 @@
 // exported globals
 //
 bool gAgentMovementCompleted = false;
-std::string gInitialOutfit;
-std::string gInitialOutfitGender;
 
 std::string SCREEN_HOME_FILENAME = "screen_home.bmp";
 std::string SCREEN_LAST_FILENAME = "screen_last.bmp";
 
+LLPointer<LLViewerTexture> gStartTexture;
+
 //
 // Imported globals
 //
@@ -218,12 +219,6 @@ extern S32 gStartImageHeight;
 //
 // local globals
 //
-
-LLPointer<LLViewerTexture> gStartTexture;
-
-static LLHost gAgentSimHost;
-static BOOL gSkipOptionalUpdate = FALSE;
-
 static bool gGotUseCircuitCodeAck = false;
 static std::string sInitialOutfit;
 static std::string sInitialOutfitGender;	// "male" or "female"
@@ -232,6 +227,18 @@ static bool gUseCircuitCallbackCalled = false;
 
 EStartupState LLStartUp::gStartupState = STATE_FIRST;
 
+// *NOTE:Mani - to reconcile with giab changes...
+static std::string gFirstname;
+static std::string gLastname;
+static std::string gPassword;
+
+static U64 gFirstSimHandle = 0;
+static LLHost gFirstSim;
+static std::string gFirstSimSeedCap;
+static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f);
+static std::string gAgentStartLocation = "safe";
+
+static LLEventStream sStartupStateWatcher("StartupState");
 
 //
 // local function declaration
@@ -244,8 +251,6 @@ void show_first_run_dialog();
 bool first_run_dialog_callback(const LLSD& notification, const LLSD& response);
 void set_startup_status(const F32 frac, const std::string& string, const std::string& msg);
 bool login_alert_status(const LLSD& notification, const LLSD& response);
-void update_app(BOOL mandatory, const std::string& message);
-bool update_dialog_callback(const LLSD& notification, const LLSD& response);
 void login_packet_failed(void**, S32 result);
 void use_circuit_callback(void**, S32 result);
 void register_viewer_callbacks(LLMessageSystem* msg);
@@ -255,6 +260,8 @@ void init_start_screen(S32 location_id);
 void release_start_screen();
 void reset_login();
 void apply_udp_blacklist(const std::string& csv);
+bool process_login_success_response();
+void transition_back_to_login_panel(const std::string& emsg);
 
 void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group)
 {
@@ -314,9 +321,6 @@ void update_texture_fetch()
 	gTextureList.updateImages(0.10f);
 }
 
-static std::vector<std::string> sAuthUris;
-static S32 sAuthUriNum = -1;
-
 //Copies landmarks from the "Library" to "My Favorites"
 void populate_favorites_bar()
 {
@@ -388,23 +392,11 @@ bool idle_startup()
 	// auth/transform loop will do.
 	static F32 progress = 0.10f;
 
-	static std::string auth_method;
 	static std::string auth_desc;
 	static std::string auth_message;
-	static std::string firstname;
-	static std::string lastname;
-	static LLUUID web_login_key;
-	static std::string password;
-	static std::vector<const char*> requested_options;
-
-	static U64 first_sim_handle = 0;
-	static LLHost first_sim;
-	static std::string first_sim_seed_cap;
 
 	static LLVector3 initial_sun_direction(1.f, 0.f, 0.f);
 	static LLVector3 agent_start_position_region(10.f, 10.f, 10.f);		// default for when no space server
-	static LLVector3 agent_start_look_at(1.0f, 0.f, 0.f);
-	static std::string agent_start_location = "safe";
 
 	// last location by default
 	static S32  agent_location_id = START_LOCATION_ID_LAST;
@@ -412,7 +404,7 @@ bool idle_startup()
 
 	static bool show_connect_box = true;
 
-	static bool stipend_since_login = false;
+	//static bool stipend_since_login = false;
 
 	// HACK: These are things from the main loop that usually aren't done
 	// until initialization is complete, but need to be done here for things
@@ -433,12 +425,7 @@ bool idle_startup()
 
 	LLStringUtil::setLocale (LLTrans::getString(system));
 
-	if (gNoRender)
-	{
-		// HACK, skip optional updates if you're running drones
-		gSkipOptionalUpdate = TRUE;
-	}
-	else
+	if (!gNoRender)
 	{
 		//note: Removing this line will cause incorrect button size in the login screen. -- bao.
 		gTextureList.updateImages(0.01f) ;
@@ -754,24 +741,23 @@ bool idle_startup()
 			|| !gLoginHandler.getWebLoginKey().isNull() )
 		{
 			// We have at least some login information on a SLURL
-			firstname = gLoginHandler.getFirstName();
-			lastname = gLoginHandler.getLastName();
-			web_login_key = gLoginHandler.getWebLoginKey();
+			gFirstname = gLoginHandler.getFirstName();
+			gLastname = gLoginHandler.getLastName();
 
 			// Show the login screen if we don't have everything
 			show_connect_box = 
-				firstname.empty() || lastname.empty() || web_login_key.isNull();
+				gFirstname.empty() || gLastname.empty();
 		}
         else if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
         {
             LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
-			firstname = cmd_line_login[0].asString();
-			lastname = cmd_line_login[1].asString();
+			gFirstname = cmd_line_login[0].asString();
+			gLastname = cmd_line_login[1].asString();
 
 			LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str());
 			char md5pass[33];               /* Flawfinder: ignore */
 			pass.hex_digest(md5pass);
-			password = md5pass;
+			gPassword = md5pass;
 			
 #ifdef USE_VIEWER_AUTH
 			show_connect_box = true;
@@ -782,9 +768,9 @@ bool idle_startup()
         }
 		else if (gSavedSettings.getBOOL("AutoLogin"))
 		{
-			firstname = gSavedSettings.getString("FirstName");
-			lastname = gSavedSettings.getString("LastName");
-			password = LLStartUp::loadPasswordFromDisk();
+			gFirstname = gSavedSettings.getString("FirstName");
+			gLastname = gSavedSettings.getString("LastName");
+			gPassword = LLStartUp::loadPasswordFromDisk();
 			gSavedSettings.setBOOL("RememberPassword", TRUE);
 			
 #ifdef USE_VIEWER_AUTH
@@ -797,9 +783,9 @@ bool idle_startup()
 		{
 			// if not automatically logging in, display login dialog
 			// a valid grid is selected
-			firstname = gSavedSettings.getString("FirstName");
-			lastname = gSavedSettings.getString("LastName");
-			password = LLStartUp::loadPasswordFromDisk();
+			gFirstname = gSavedSettings.getString("FirstName");
+			gLastname = gSavedSettings.getString("LastName");
+			gPassword = LLStartUp::loadPasswordFromDisk();
 			show_connect_box = true;
 		}
 
@@ -835,7 +821,7 @@ bool idle_startup()
 			// Load all the name information out of the login view
 			// NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't
 			// show the login view until login_show() is called below.  
-			// LLPanelLogin::getFields(firstname, lastname, password);
+			// LLPanelLogin::getFields(gFirstname, gLastname, gPassword);
 
 			if (gNoRender)
 			{
@@ -847,7 +833,7 @@ bool idle_startup()
 			// Show the login dialog
 			login_show();
 			// connect dialog is already shown, so fill in the names
-			LLPanelLogin::setFields( firstname, lastname, password);
+			LLPanelLogin::setFields( gFirstname, gLastname, gPassword);
 
 			LLPanelLogin::giveFocus();
 
@@ -911,34 +897,34 @@ bool idle_startup()
 		//reset the values that could have come in from a slurl
 		if (!gLoginHandler.getWebLoginKey().isNull())
 		{
-			firstname = gLoginHandler.getFirstName();
-			lastname = gLoginHandler.getLastName();
-			web_login_key = gLoginHandler.getWebLoginKey();
+			gFirstname = gLoginHandler.getFirstName();
+			gLastname = gLoginHandler.getLastName();
+//			gWebLoginKey = gLoginHandler.getWebLoginKey();
 		}
 				
 		if (show_connect_box)
 		{
 			// TODO if not use viewer auth
 			// Load all the name information out of the login view
-			LLPanelLogin::getFields(&firstname, &lastname, &password);
+			LLPanelLogin::getFields(&gFirstname, &gLastname, &gPassword);
 			// end TODO
 	 
 			// HACK: Try to make not jump on login
 			gKeyboard->resetKeys();
 		}
 
-		if (!firstname.empty() && !lastname.empty())
+		if (!gFirstname.empty() && !gLastname.empty())
 		{
-			gSavedSettings.setString("FirstName", firstname);
-			gSavedSettings.setString("LastName", lastname);
+			gSavedSettings.setString("FirstName", gFirstname);
+			gSavedSettings.setString("LastName", gLastname);
 
-			LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << LL_ENDL;
-			gDebugInfo["LoginName"] = firstname + " " + lastname;	
+			LL_INFOS("AppInit") << "Attempting login as: " << gFirstname << " " << gLastname << LL_ENDL;
+			gDebugInfo["LoginName"] = gFirstname + " " + gLastname;	
 		}
 
 		// create necessary directories
 		// *FIX: these mkdir's should error check
-		gDirUtilp->setLindenUserDir(firstname, lastname);
+		gDirUtilp->setLindenUserDir(gFirstname, gLastname);
     	LLFile::mkdir(gDirUtilp->getLindenUserDir());
 
         // Set PerAccountSettingsFile to the default value.
@@ -972,7 +958,7 @@ bool idle_startup()
 			gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));		
 		}
 		
-		gDirUtilp->setPerAccountChatLogsDir(firstname, lastname);
+		gDirUtilp->setPerAccountChatLogsDir(gFirstname, gLastname);
 
 		LLFile::mkdir(gDirUtilp->getChatLogsDir());
 		LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir());
@@ -1000,13 +986,6 @@ bool idle_startup()
 
 		if (show_connect_box)
 		{
-			if ( LLPanelLogin::isGridComboDirty() )
-			{
-				// User picked a grid from the popup, so clear the 
-				// stored uris and they will be reacquired from the grid choice.
-				sAuthUris.clear();
-			}
-			
 			std::string location;
 			LLPanelLogin::getLocation( location );
 			LLURLSimString::setString( location );
@@ -1038,7 +1017,7 @@ bool idle_startup()
 			agent_location_id = START_LOCATION_ID_URL;
 
 			// doesn't really matter what location_which is, since
-			// agent_start_look_at will be overwritten when the
+			// gAgentStartLookAt will be overwritten when the
 			// UserLoginLocationReply arrives
 			location_which = START_LOCATION_ID_LAST;
 		}
@@ -1071,616 +1050,139 @@ bool idle_startup()
 
 		gVFS->pokeFiles();
 
-		// skipping over STATE_UPDATE_CHECK because that just waits for input
 		LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
 
 		return FALSE;
 	}
 
-	if (STATE_UPDATE_CHECK == LLStartUp::getStartupState())
-	{
-		// wait for user to give input via dialog box
-		return FALSE;
-	}
-
 	if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState())
 	{
-//#define LL_MINIMIAL_REQUESTED_OPTIONS
 		gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel();
 
-		// *Note: this is where gUserAuth used to be created.
-		requested_options.clear();
-		requested_options.push_back("inventory-root");
-		requested_options.push_back("inventory-skeleton");
-		//requested_options.push_back("inventory-meat");
-		//requested_options.push_back("inventory-skel-targets");
-#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS)
-		if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary"))
-		{
-			requested_options.push_back("inventory-lib-root");
-			requested_options.push_back("inventory-lib-owner");
-			requested_options.push_back("inventory-skel-lib");
-		//	requested_options.push_back("inventory-meat-lib");
-		}
-
-		requested_options.push_back("initial-outfit");
-		requested_options.push_back("gestures");
-		requested_options.push_back("event_categories");
-		requested_options.push_back("event_notifications");
-		requested_options.push_back("classified_categories");
-		requested_options.push_back("adult_compliant"); 
-		//requested_options.push_back("inventory-targets");
-		requested_options.push_back("buddy-list");
-		requested_options.push_back("ui-config");
-#endif
-		requested_options.push_back("tutorial_setting");
-		requested_options.push_back("login-flags");
-		requested_options.push_back("global-textures");
-		if(gSavedSettings.getBOOL("ConnectAsGod"))
-		{
-			gSavedSettings.setBOOL("UseDebugMenus", TRUE);
-			requested_options.push_back("god-connect");
-		}
-		std::vector<std::string> uris;
-		LLViewerLogin::getInstance()->getLoginURIs(uris);
-		std::vector<std::string>::const_iterator iter, end;
-		for (iter = uris.begin(), end = uris.end(); iter != end; ++iter)
-		{
-			std::vector<std::string> rewritten;
-			rewritten = LLSRV::rewriteURI(*iter);
-			sAuthUris.insert(sAuthUris.end(),
-							 rewritten.begin(), rewritten.end());
-		}
-		sAuthUriNum = 0;
-		auth_method = "login_to_simulator";
-		
+		// Update progress status and the display loop.
 		auth_desc = LLTrans::getString("LoginInProgress");
-		LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE );
-	}
-
-	if (STATE_LOGIN_AUTHENTICATE == LLStartUp::getStartupState())
-	{
-		LL_DEBUGS("AppInit") << "STATE_LOGIN_AUTHENTICATE" << LL_ENDL;
 		set_startup_status(progress, auth_desc, auth_message);
 		progress += 0.02f;
 		display_startup();
-		
-		std::stringstream start;
-		if (LLURLSimString::parse())
-		{
-			// a startup URL was specified
-			std::stringstream unescaped_start;
-			unescaped_start << "uri:" 
-							<< LLURLSimString::sInstance.mSimName << "&" 
-							<< LLURLSimString::sInstance.mX << "&" 
-							<< LLURLSimString::sInstance.mY << "&" 
-							<< LLURLSimString::sInstance.mZ;
-			start << xml_escape_string(unescaped_start.str());
-			
-		}
-		else
-		{
-			start << gSavedSettings.getString("LoginLocation");
-		}
-
-		char hashed_mac_string[MD5HEX_STR_SIZE];		/* Flawfinder: ignore */
-		LLMD5 hashed_mac;
-		hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES );
-		hashed_mac.finalize();
-		hashed_mac.hex_digest(hashed_mac_string);
-
-		// TODO if statement here to use web_login_key
-		sAuthUriNum = llclamp(sAuthUriNum, 0, (S32)sAuthUris.size()-1);
-		LLUserAuth::getInstance()->authenticate(
-			sAuthUris[sAuthUriNum],
-			auth_method,
-			firstname,
-			lastname,			
-			password, // web_login_key,
-			start.str(),
-			gSkipOptionalUpdate,
-			gAcceptTOS,
-			gAcceptCriticalMessage,
-			gLastExecEvent,
-			requested_options,
-			hashed_mac_string,
-			LLAppViewer::instance()->getSerialNumber());
-
-		// reset globals
-		gAcceptTOS = FALSE;
-		gAcceptCriticalMessage = FALSE;
-		LLStartUp::setStartupState( STATE_LOGIN_NO_DATA_YET );
-		return FALSE;
-	}
 
-	if(STATE_LOGIN_NO_DATA_YET == LLStartUp::getStartupState())
-	{
-		LL_DEBUGS("AppInit") << "STATE_LOGIN_NO_DATA_YET" << LL_ENDL;
-		// If we get here we have gotten past the potential stall
-		// in curl, so take "may appear frozen" out of progress bar. JC
-		auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
-		set_startup_status(progress, auth_desc, auth_message);
-		// Process messages to keep from dropping circuit.
-		LLMessageSystem* msg = gMessageSystem;
-		while (msg->checkAllMessages(gFrameCount, gServicePump))
-		{
-		}
-		msg->processAcks();
-		LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse();
-		if(LLUserAuth::E_NO_RESPONSE_YET == error)
+		// Setting initial values...
+		LLLoginInstance* login = LLLoginInstance::getInstance();
+		login->setNotificationsInterface(LLNotifications::getInstance());
+		if(gNoRender)
 		{
-			LL_DEBUGS("AppInit") << "waiting..." << LL_ENDL;
-			return FALSE;
+			// HACK, skip optional updates if you're running drones
+			login->setSkipOptionalUpdate(true);
 		}
-		LLStartUp::setStartupState( STATE_LOGIN_DOWNLOADING );
-		progress += 0.01f;
-		set_startup_status(progress, auth_desc, auth_message);
-		return FALSE;
-	}
 
-	if(STATE_LOGIN_DOWNLOADING == LLStartUp::getStartupState())
-	{
-		LL_DEBUGS("AppInit") << "STATE_LOGIN_DOWNLOADING" << LL_ENDL;
-		// Process messages to keep from dropping circuit.
-		LLMessageSystem* msg = gMessageSystem;
-		while (msg->checkAllMessages(gFrameCount, gServicePump))
-		{
-		}
-		msg->processAcks();
-		LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse();
-		if(LLUserAuth::E_DOWNLOADING == error)
-		{
-			LL_DEBUGS("AppInit") << "downloading..." << LL_ENDL;
-			return FALSE;
-		}
+		login->setUserInteraction(show_connect_box);
+		login->setSerialNumber(LLAppViewer::instance()->getSerialNumber());
+		login->setLastExecEvent(gLastExecEvent);
+		login->setUpdaterLauncher(boost::bind(&LLAppViewer::launchUpdater, LLAppViewer::instance()));
+
+		// This call to LLLoginInstance::connect() starts the 
+		// authentication process.
+		LLSD credentials;
+		credentials["first"] = gFirstname;
+		credentials["last"] = gLastname;
+		credentials["passwd"] = gPassword;
+		login->connect(credentials);
+
 		LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );
-		progress += 0.01f;
-		set_startup_status(progress, LLTrans::getString("LoginProcessingResponse"), auth_message);
 		return FALSE;
 	}
 
-	if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState())
+	if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) 
 	{
-		LL_DEBUGS("AppInit") << "STATE_LOGIN_PROCESS_RESPONSE" << LL_ENDL;
 		std::ostringstream emsg;
-		bool quit = false;
-		bool update = false;
-		std::string login_response;
-		std::string reason_response;
-		std::string message_response;
-		bool successful_login = false;
-		LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse();
-		// reset globals
-		gAcceptTOS = FALSE;
-		gAcceptCriticalMessage = FALSE;
-		switch(error)
-		{
-		case LLUserAuth::E_OK:
-			login_response = LLUserAuth::getInstance()->getResponse("login");
-			if(login_response == "true")
-			{
-				// Yay, login!
-				successful_login = true;
-			}
-			else if(login_response == "indeterminate")
+		emsg << "Login failed.\n";
+		if(LLLoginInstance::getInstance()->authFailure())
+		{
+			LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): "
+			                      << LLLoginInstance::getInstance()->getResponse() << LL_ENDL;
+			// Still have error conditions that may need some 
+			// sort of handling.
+			std::string reason_response = LLLoginInstance::getInstance()->getResponse("reason");
+			std::string message_response = LLLoginInstance::getInstance()->getResponse("message");
+	
+			if(!message_response.empty())
 			{
-				LL_INFOS("AppInit") << "Indeterminate login..." << LL_ENDL;
-				sAuthUris = LLSRV::rewriteURI(LLUserAuth::getInstance()->getResponse("next_url"));
-				sAuthUriNum = 0;
-				auth_method = LLUserAuth::getInstance()->getResponse("next_method");
-				auth_message = LLUserAuth::getInstance()->getResponse("message");
-				if(auth_method.substr(0, 5) == "login")
+				// XUI: fix translation for strings returned during login
+				// We need a generic table for translations
+				std::string big_reason = LLAgent::sTeleportErrorMessages[ message_response ];
+				if ( big_reason.size() == 0 )
 				{
-					auth_desc.assign(LLTrans::getString("LoginAuthenticating"));
+					emsg << message_response;
 				}
 				else
 				{
-					auth_desc.assign(LLTrans::getString("LoginMaintenance"));
+					emsg << big_reason;
 				}
-				// ignoring the duration & options array for now.
-				// Go back to authenticate.
-				LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE );
-				return FALSE;
-			}
-			else
-			{
-				emsg << "Login failed.\n";
-				reason_response = LLUserAuth::getInstance()->getResponse("reason");
-				message_response = LLUserAuth::getInstance()->getResponse("message");
-
-				if (!message_response.empty())
-				{
-					// XUI: fix translation for strings returned during login
-					// We need a generic table for translations
-					std::string big_reason = LLAgent::sTeleportErrorMessages[ message_response ];
-					if ( big_reason.size() == 0 )
-					{
-						emsg << message_response;
-					}
-					else
-					{
-						emsg << big_reason;
-					}
-				}
-
-				if(reason_response == "tos")
-				{
-					if (show_connect_box)
-					{
-						LL_DEBUGS("AppInit") << "Need tos agreement" << LL_ENDL;
-						LLStartUp::setStartupState( STATE_UPDATE_CHECK );
-						LLFloaterReg::showInstance("message_tos", LLSD(message_response));
-						// LLFloaterTOS deletes itself.
-						return false;
-					}
-					else
-					{
-						quit = true;
-					}
-				}
-				if(reason_response == "critical")
-				{
-					if (show_connect_box)
-					{
-						LL_DEBUGS("AppInit") << "Need critical message" << LL_ENDL;
-						LLStartUp::setStartupState( STATE_UPDATE_CHECK );
-						LLFloaterReg::showInstance("message_critical", LLSD(message_response));
-						// LLFloaterTOS deletes itself.
-						return false;
-					}
-					else
-					{
-						quit = true;
-					}
-				}
-				if(reason_response == "key")
-				{
-					// Couldn't login because user/password is wrong
-					// Clear the password
-					password = "";
-				}
-				if(reason_response == "update")
-				{
-					auth_message = LLUserAuth::getInstance()->getResponse("message");
-					update = true;
-				}
-				if(reason_response == "optional")
-				{
-					LL_DEBUGS("AppInit") << "Login got optional update" << LL_ENDL;
-					auth_message = LLUserAuth::getInstance()->getResponse("message");
-					if (show_connect_box)
-					{
-						update_app(FALSE, auth_message);
-						LLStartUp::setStartupState( STATE_UPDATE_CHECK );
-						gSkipOptionalUpdate = TRUE;
-						return false;
-					}
-				}
-			}
-			break;
-		case LLUserAuth::E_COULDNT_RESOLVE_HOST:
-		case LLUserAuth::E_SSL_PEER_CERTIFICATE:
-		case LLUserAuth::E_UNHANDLED_ERROR:
-		case LLUserAuth::E_SSL_CACERT:
-		case LLUserAuth::E_SSL_CONNECT_ERROR:
-		default:
-			if (sAuthUriNum >= (int) sAuthUris.size() - 1)
-			{
-				emsg << "Unable to connect to " << LLAppViewer::instance()->getSecondLifeTitle() << ".\n";
-				emsg << LLUserAuth::getInstance()->errorMessage();
-			} else {
-				sAuthUriNum++;
-				std::ostringstream s;
-				LLStringUtil::format_map_t args;
-				args["[NUMBER]"] = llformat("%d", sAuthUriNum + 1);
-				auth_desc = LLTrans::getString("LoginAttempt", args);
-				LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE );
-				return FALSE;
-			}
-			break;
-		}
-
-		if (update || gSavedSettings.getBOOL("ForceMandatoryUpdate"))
-		{
-			gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
-			update_app(TRUE, auth_message);
-			LLStartUp::setStartupState( STATE_UPDATE_CHECK );
-			return false;
-		}
-
-		// Version update and we're not showing the dialog
-		if(quit)
-		{
-			LLUserAuth::getInstance()->reset();
-			LLAppViewer::instance()->forceQuit();
-			return false;
-		}
-
-		if(successful_login)
-		{
-			std::string text;
-			text = LLUserAuth::getInstance()->getResponse("udp_blacklist");
-			if(!text.empty())
-			{
-				apply_udp_blacklist(text);
 			}
 
-			// unpack login data needed by the application
-			text = LLUserAuth::getInstance()->getResponse("agent_id");
-			if(!text.empty()) gAgentID.set(text);
-			gDebugInfo["AgentID"] = text;
-			
-			text = LLUserAuth::getInstance()->getResponse("session_id");
-			if(!text.empty()) gAgentSessionID.set(text);
-			gDebugInfo["SessionID"] = text;
-			
-			text = LLUserAuth::getInstance()->getResponse("secure_session_id");
-			if(!text.empty()) gAgent.mSecureSessionID.set(text);
-
-			text = LLUserAuth::getInstance()->getResponse("first_name");
-			if(!text.empty()) 
+			if(reason_response == "key")
 			{
-				// Remove quotes from string.  Login.cgi sends these to force
-				// names that look like numbers into strings.
-				firstname.assign(text);
-				LLStringUtil::replaceChar(firstname, '"', ' ');
-				LLStringUtil::trim(firstname);
+				// Couldn't login because user/password is wrong
+				// Clear the password
+				gPassword = "";
 			}
-			text = LLUserAuth::getInstance()->getResponse("last_name");
-			if(!text.empty()) lastname.assign(text);
-			gSavedSettings.setString("FirstName", firstname);
-			gSavedSettings.setString("LastName", lastname);
 
-			if (gSavedSettings.getBOOL("RememberPassword"))
+			if(reason_response == "update" 
+				|| reason_response == "optional")
 			{
-				// Successful login means the password is valid, so save it.
-				LLStartUp::savePasswordToDisk(password);
+				// In the case of a needed update, quit.
+				// Its either downloading or declined.
+				// If optional was skipped this case shouldn't 
+				// be reached.
+				LLLoginInstance::getInstance()->disconnect();
+				LLAppViewer::instance()->forceQuit();
 			}
 			else
 			{
-				// Don't leave password from previous session sitting around
-				// during this login session.
-				LLStartUp::deletePasswordFromDisk();
-			}
-
-			// this is the base used to construct help URLs
-			text = LLUserAuth::getInstance()->getResponse("help_url_format");
-			if (!text.empty())
-			{
-				// replace the default help URL format
-				gSavedSettings.setString("HelpURLFormat",text);
-				
-				// don't fall back to Nebraska's pre-connection static help
-				gSavedSettings.setBOOL("HelpUseLocal", false);
-			}
-			
-			// this is their actual ability to access content
-			text = LLUserAuth::getInstance()->getResponse("agent_access_max");
-			if (!text.empty())
-			{
-				// agent_access can be 'A', 'M', and 'PG'.
-				gAgent.setMaturity(text[0]);
-			}
-			
-			// this is the value of their preference setting for that content
-			// which will always be <= agent_access_max
-			text = LLUserAuth::getInstance()->getResponse("agent_region_access");
-			if (!text.empty())
-			{
-				int preferredMaturity = LLAgent::convertTextToMaturity(text[0]);
-				gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
-			}
-			// During the AO transition, this flag will be true. Then the flag will
-			// go away. After the AO transition, this code and all the code that
-			// uses it can be deleted.
-			text = LLUserAuth::getInstance()->getResponse("ao_transition");
-			if (!text.empty())
-			{
-				if (text == "1")
-				{
-					gAgent.setAOTransition();
-				}
-			}
-
-			text = LLUserAuth::getInstance()->getResponse("start_location");
-			if(!text.empty()) agent_start_location.assign(text);
-			text = LLUserAuth::getInstance()->getResponse("circuit_code");
-			if(!text.empty())
-			{
-				gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10);
-			}
-			std::string sim_ip_str = LLUserAuth::getInstance()->getResponse("sim_ip");
-			std::string sim_port_str = LLUserAuth::getInstance()->getResponse("sim_port");
-			if(!sim_ip_str.empty() && !sim_port_str.empty())
-			{
-				U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10);
-				first_sim.set(sim_ip_str, sim_port);
-				if (first_sim.isOk())
-				{
-					gMessageSystem->enableCircuit(first_sim, TRUE);
-				}
-			}
-			std::string region_x_str = LLUserAuth::getInstance()->getResponse("region_x");
-			std::string region_y_str = LLUserAuth::getInstance()->getResponse("region_y");
-			if(!region_x_str.empty() && !region_y_str.empty())
-			{
-				U32 region_x = strtoul(region_x_str.c_str(), NULL, 10);
-				U32 region_y = strtoul(region_y_str.c_str(), NULL, 10);
-				first_sim_handle = to_region_handle(region_x, region_y);
-			}
-			
-			const std::string look_at_str = LLUserAuth::getInstance()->getResponse("look_at");
-			if (!look_at_str.empty())
-			{
-				size_t len = look_at_str.size();
-				LLMemoryStream mstr((U8*)look_at_str.c_str(), len);
-				LLSD sd = LLSDSerialize::fromNotation(mstr, len);
-				agent_start_look_at = ll_vector3_from_sd(sd);
-			}
-
-			text = LLUserAuth::getInstance()->getResponse("seed_capability");
-			if (!text.empty()) first_sim_seed_cap = text;
-						
-			text = LLUserAuth::getInstance()->getResponse("seconds_since_epoch");
-			if(!text.empty())
-			{
-				U32 server_utc_time = strtoul(text.c_str(), NULL, 10);
-				if(server_utc_time)
+				// Don't pop up a notification in the TOS case because
+				// LLFloaterTOS::onCancel() already scolded the user.
+				if (reason_response != "tos")
 				{
-					time_t now = time(NULL);
-					gUTCOffset = (server_utc_time - now);
-				}
-			}
-
-			std::string home_location = LLUserAuth::getInstance()->getResponse("home");
-			if(!home_location.empty())
-			{
-				size_t len = home_location.size();
-				LLMemoryStream mstr((U8*)home_location.c_str(), len);
-				LLSD sd = LLSDSerialize::fromNotation(mstr, len);
-				S32 region_x = sd["region_handle"][0].asInteger();
-				S32 region_y = sd["region_handle"][1].asInteger();
-				U64 region_handle = to_region_handle(region_x, region_y);
-				LLVector3 position = ll_vector3_from_sd(sd["position"]);
-				gAgent.setHomePosRegion(region_handle, position);
-			}
-
-			gAgent.mMOTD.assign(LLUserAuth::getInstance()->getResponse("message"));
-			LLUserAuth::options_t options;
-			if(LLUserAuth::getInstance()->getOptions("inventory-root", options))
-			{
-				LLUserAuth::response_t::iterator it;
-				it = options[0].find("folder_id");
-				if(it != options[0].end())
-				{
-					gInventory.setRootFolderID( LLUUID( (*it).second ) );
-				}
-			}
-
-			options.clear();
-			if(LLUserAuth::getInstance()->getOptions("login-flags", options))
-			{
-				LLUserAuth::response_t::iterator it;
-				LLUserAuth::response_t::iterator no_flag = options[0].end();
-				it = options[0].find("ever_logged_in");
-				if(it != no_flag)
-				{
-					if((*it).second == "N") gAgent.setFirstLogin(TRUE);
-					else gAgent.setFirstLogin(FALSE);
-				}
-				it = options[0].find("stipend_since_login");
-				if(it != no_flag)
-				{
-					if((*it).second == "Y") stipend_since_login = true;
-				}
-				it = options[0].find("gendered");
-				if(it != no_flag)
-				{
-					if((*it).second == "Y") gAgent.setGenderChosen(TRUE);
-				}
-				it = options[0].find("daylight_savings");
-				if(it != no_flag)
-				{
-					if((*it).second == "Y")  gPacificDaylightTime = TRUE;
-					else gPacificDaylightTime = FALSE;
+					LLSD args;
+					args["ERROR_MESSAGE"] = emsg.str();
+					LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
+					LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
 				}
 
 				//setup map of datetime strings to codes and slt & local time offset from utc
-				LLStringOps::setupDatetimeInfo (gPacificDaylightTime);
-			}
-			options.clear();
-			if (LLUserAuth::getInstance()->getOptions("initial-outfit", options)
-				&& !options.empty())
-			{
-				LLUserAuth::response_t::iterator it;
-				LLUserAuth::response_t::iterator it_end = options[0].end();
-				it = options[0].find("folder_name");
-				if(it != it_end)
-				{
-					// Initial outfit is a folder in your inventory,
-					// must be an exact folder-name match.
-					sInitialOutfit = (*it).second;
-				}
-				it = options[0].find("gender");
-				if (it != it_end)
-				{
-					sInitialOutfitGender = (*it).second;
-				}
-			}
-
-			options.clear();
-			if(LLUserAuth::getInstance()->getOptions("global-textures", options))
-			{
-				// Extract sun and moon texture IDs.  These are used
-				// in the LLVOSky constructor, but I can't figure out
-				// how to pass them in.  JC
-				LLUserAuth::response_t::iterator it;
-				LLUserAuth::response_t::iterator no_texture = options[0].end();
-				it = options[0].find("sun_texture_id");
-				if(it != no_texture)
-				{
-					gSunTextureID.set((*it).second);
-				}
-				it = options[0].find("moon_texture_id");
-				if(it != no_texture)
-				{
-					gMoonTextureID.set((*it).second);
-				}
-				it = options[0].find("cloud_texture_id");
-				if(it != no_texture)
-				{
-					gCloudTextureID.set((*it).second);
-				}
+				// *TODO: Does this need to be here?
+				LLStringOps::setupDatetimeInfo (false);
+				transition_back_to_login_panel(emsg.str());
+				show_connect_box = true;
 			}
-
-
-			// JC: gesture loading done below, when we have an asset system
-			// in place.  Don't delete/clear user_credentials until then.
-
-			if(gAgentID.notNull()
-			   && gAgentSessionID.notNull()
-			   && gMessageSystem->mOurCircuitCode
-			   && first_sim.isOk()
-			   && gInventory.getRootFolderID().notNull())
+		}
+		else if(LLLoginInstance::getInstance()->authSuccess())
+		{
+			if(process_login_success_response())
 			{
-				LLStartUp::setStartupState( STATE_WORLD_INIT );
+				// Pass the user information to the voice chat server interface.
+				gVoiceClient->userAuthorized(gFirstname, gLastname, gAgentID);
+				LLStartUp::setStartupState( STATE_WORLD_INIT);
 			}
 			else
 			{
-				if (gNoRender)
-				{
-					LL_WARNS("AppInit") << "Bad login - missing return values" << LL_ENDL;
-					LL_WARNS("AppInit") << emsg << LL_ENDL;
-					exit(0);
-				}
-				// Bounce back to the login screen.
 				LLSD args;
 				args["ERROR_MESSAGE"] = emsg.str();
+				LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
 				LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
-				reset_login();
-				gSavedSettings.setBOOL("AutoLogin", FALSE);
+				transition_back_to_login_panel(emsg.str());
 				show_connect_box = true;
 			}
-			
-			// Pass the user information to the voice chat server interface.
-			gVoiceClient->userAuthorized(firstname, lastname, gAgentID);
 		}
-		else // if(successful_login)
+		else
 		{
-			if (gNoRender)
-			{
-				LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL;
-				LL_WARNS("AppInit") << emsg << LL_ENDL;
-				exit(0);
-			}
-			// Bounce back to the login screen.
-			LLSD args;
-			args["ERROR_MESSAGE"] = emsg.str();
-			LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
-			reset_login();
-			gSavedSettings.setBOOL("AutoLogin", FALSE);
-			show_connect_box = true;
+			// Still waiting for response.
+			// *TODO:Mani - Actually check for login progress.
+			// If we get here we have gotten past the potential stall
+			// in curl, so take "may appear frozen" out of progress bar. JC
+			auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
+			set_startup_status(progress, auth_desc, auth_message);
 		}
+
 		return FALSE;
 	}
 
@@ -1740,14 +1242,14 @@ bool idle_startup()
 		// This is necessary because creating objects before this is set will result in a
 		// bad mPositionAgent cache.
 
-		gAgent.initOriginGlobal(from_region_handle(first_sim_handle));
+		gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle));
 
-		LLWorld::getInstance()->addRegion(first_sim_handle, first_sim);
+		LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim);
 
-		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(first_sim_handle);
+		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle);
 		LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL;
 		
-		regionp->setSeedCapability(first_sim_seed_cap);
+		regionp->setSeedCapability(gFirstSimSeedCap);
 		LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL;
 		
 		// Set agent's initial region to be the one we just created.
@@ -1886,7 +1388,7 @@ bool idle_startup()
 		// the coordinates handed to us to fit in the local region.
 
 		gAgent.setPositionAgent(agent_start_position_region);
-		gAgent.resetAxes(agent_start_look_at);
+		gAgent.resetAxes(gAgentStartLookAt);
 		gAgent.stopCameraAnimation();
 		gAgent.resetCamera();
 
@@ -1925,18 +1427,18 @@ bool idle_startup()
 			LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL;
 		}
 
-		gUseCircuitCallbackCalled = FALSE;
+		gUseCircuitCallbackCalled = false;
 
-		msg->enableCircuit(first_sim, TRUE);
+		msg->enableCircuit(gFirstSim, TRUE);
 		// now, use the circuit info to tell simulator about us!
-		LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << first_sim << " with code " << msg->mOurCircuitCode << LL_ENDL;
+		LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL;
 		msg->newMessageFast(_PREHASH_UseCircuitCode);
 		msg->nextBlockFast(_PREHASH_CircuitCode);
 		msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode);
 		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 		msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
 		msg->sendReliable(
-			first_sim,
+			gFirstSim,
 			MAX_TIMEOUT_COUNT,
 			FALSE,
 			TIMEOUT_SECONDS,
@@ -2047,105 +1549,99 @@ bool idle_startup()
 		LLAgentLanguage::update();
 
 		// unpack thin inventory
-		LLUserAuth::options_t options;
-		options.clear();
+		LLSD response = LLLoginInstance::getInstance()->getResponse();
 		//bool dump_buffer = false;
-		
-		if(LLUserAuth::getInstance()->getOptions("inventory-lib-root", options)
-			&& !options.empty())
+
+		LLSD inv_lib_root = response["inventory-lib-root"];
+		if(inv_lib_root.isDefined())
 		{
 			// should only be one
-			LLUserAuth::response_t::iterator it;
-			it = options[0].find("folder_id");
-			if(it != options[0].end())
+			LLSD id = inv_lib_root[0]["folder_id"];
+			if(id.isDefined())
 			{
-				gInventory.setLibraryRootFolderID( LLUUID( (*it).second ) );
+				gInventory.setLibraryRootFolderID(id.asUUID());
 			}
 		}
- 		options.clear();
-		if(LLUserAuth::getInstance()->getOptions("inventory-lib-owner", options)
-			&& !options.empty())
+ 		
+		LLSD inv_lib_owner = response["inventory-lib-owner"];
+		if(inv_lib_owner.isDefined())
 		{
 			// should only be one
-			LLUserAuth::response_t::iterator it;
-			it = options[0].find("agent_id");
-			if(it != options[0].end())
+			LLSD id = inv_lib_owner[0]["agent_id"];
+			if(id.isDefined())
 			{
-				gInventory.setLibraryOwnerID( LLUUID( (*it).second ) );
+				gInventory.setLibraryOwnerID( LLUUID(id.asUUID()));
 			}
 		}
- 		options.clear();
- 		if(LLUserAuth::getInstance()->getOptions("inventory-skel-lib", options)
-			&& gInventory.getLibraryOwnerID().notNull())
+
+		LLSD inv_skel_lib = response["inventory-skel-lib"];
+ 		if(inv_skel_lib.isDefined() && gInventory.getLibraryOwnerID().notNull())
  		{
- 			if(!gInventory.loadSkeleton(options, gInventory.getLibraryOwnerID()))
+ 			if(!gInventory.loadSkeleton(inv_skel_lib, gInventory.getLibraryOwnerID()))
  			{
  				LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL;
  			}
  		}
- 		options.clear();
- 		if(LLUserAuth::getInstance()->getOptions("inventory-skeleton", options))
+
+		LLSD inv_skeleton = response["inventory-skeleton"];
+ 		if(inv_skeleton.isDefined())
  		{
- 			if(!gInventory.loadSkeleton(options, gAgent.getID()))
+ 			if(!gInventory.loadSkeleton(inv_skeleton, gAgent.getID()))
  			{
  				LL_WARNS("AppInit") << "Problem loading inventory-skel-targets" << LL_ENDL;
  			}
  		}
 
-		options.clear();
- 		if(LLUserAuth::getInstance()->getOptions("buddy-list", options))
+		LLSD buddy_list = response["buddy-list"];
+ 		if(buddy_list.isDefined())
  		{
-			LLUserAuth::options_t::iterator it = options.begin();
-			LLUserAuth::options_t::iterator end = options.end();
 			LLAvatarTracker::buddy_map_t list;
 			LLUUID agent_id;
 			S32 has_rights = 0, given_rights = 0;
-			for (; it != end; ++it)
+			for(LLSD::array_const_iterator it = buddy_list.beginArray(),
+				end = buddy_list.endArray(); it != end; ++it)
 			{
-				LLUserAuth::response_t::const_iterator option_it;
-				option_it = (*it).find("buddy_id");
-				if(option_it != (*it).end())
+				LLSD buddy_id = (*it)["buddy_id"];
+				if(buddy_id.isDefined())
 				{
-					agent_id.set((*option_it).second);
+					agent_id = buddy_id.asUUID();
 				}
-				option_it = (*it).find("buddy_rights_has");
-				if(option_it != (*it).end())
+
+				LLSD buddy_rights_has = (*it)["buddy_rights_has"];
+				if(buddy_rights_has.isDefined())
 				{
-					has_rights = atoi((*option_it).second.c_str());
+					has_rights = buddy_rights_has.asInteger();
 				}
-				option_it = (*it).find("buddy_rights_given");
-				if(option_it != (*it).end())
+
+				LLSD buddy_rights_given = (*it)["buddy_rights_given"];
+				if(buddy_rights_given.isDefined())
 				{
-					given_rights = atoi((*option_it).second.c_str());
+					given_rights = buddy_rights_given.asInteger();
 				}
+
 				list[agent_id] = new LLRelationship(given_rights, has_rights, false);
 			}
 			LLAvatarTracker::instance().addBuddyList(list);
  		}
 
-		options.clear();
-
 		bool show_hud = false;
-		if(LLUserAuth::getInstance()->getOptions("tutorial_setting", options))
+		LLSD tutorial_setting = response["tutorial_setting"];
+		if(tutorial_setting.isDefined())
 		{
-			LLUserAuth::options_t::iterator it = options.begin();
-			LLUserAuth::options_t::iterator end = options.end();
-			for (; it != end; ++it)
+			for(LLSD::array_const_iterator it = tutorial_setting.beginArray(),
+				end = tutorial_setting.endArray(); it != end; ++it)
 			{
-				LLUserAuth::response_t::const_iterator option_it;
-				option_it = (*it).find("tutorial_url");
-				if(option_it != (*it).end())
+				LLSD tutorial_url = (*it)["tutorial_url"];
+				if(tutorial_url.isDefined())
 				{
 					// Tutorial floater will append language code
-					gSavedSettings.setString("TutorialURL", option_it->second);
+					gSavedSettings.setString("TutorialURL", tutorial_url.asString());
 				}
-				option_it = (*it).find("use_tutorial");
-				if(option_it != (*it).end())
+				
+				LLSD use_tutorial = (*it)["use_tutorial"];
+				if(use_tutorial.asString() == "true")
 				{
-					if (option_it->second == "true")
-					{
-						show_hud = true;
-					}
+					show_hud = true;
 				}
 			}
 		}
@@ -2157,19 +1653,22 @@ bool idle_startup()
 			LLFloaterReg::showInstance("hud", LLSD(), FALSE);
 		}
 
-		options.clear();
-		if(LLUserAuth::getInstance()->getOptions("event_categories", options))
+		LLSD event_categories = response["event_categories"];
+		if(event_categories.isDefined())
 		{
-			LLEventInfo::loadCategories(options);
+			LLEventInfo::loadCategories(event_categories);
 		}
-		if(LLUserAuth::getInstance()->getOptions("event_notifications", options))
+
+		LLSD event_notifications = response["event_notifications"];
+		if(event_notifications.isDefined())
 		{
-			gEventNotifier.load(options);
+			gEventNotifier.load(event_notifications);
 		}
-		options.clear();
-		if(LLUserAuth::getInstance()->getOptions("classified_categories", options))
+
+		LLSD classified_categories = response["classified_categories"];
+		if(classified_categories.isDefined())
 		{
-			LLClassifiedInfo::loadCategories(options);
+			LLClassifiedInfo::loadCategories(classified_categories);
 		}
 
 
@@ -2233,7 +1732,7 @@ bool idle_startup()
 			// This is actually a pessimistic computation, because TCP may not have enough
 			// time to ramp up on the (small) default inventory file to truly measure max
 			// bandwidth. JC
-			F64 rate_bps = LLUserAuth::getInstance()->getLastTransferRateBPS();
+			F64 rate_bps = LLLoginInstance::getInstance()->getLastTransferRateBPS();
 			const F32 FAST_RATE_BPS = 600.f * 1024.f;
 			const F32 FASTER_RATE_BPS = 750.f * 1024.f;
 			F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
@@ -2281,34 +1780,20 @@ bool idle_startup()
 			// JC: Initialize "active" gestures.  This may also trigger
 			// many gesture downloads, if this is the user's first
 			// time on this machine or -purge has been run.
-			LLUserAuth::options_t gesture_options;
-			if (LLUserAuth::getInstance()->getOptions("gestures", gesture_options))
+			LLSD gesture_options 
+				= LLLoginInstance::getInstance()->getResponse("gestures");
+			if (gesture_options.isDefined())
 			{
 				LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size()
 					<< LL_ENDL;
 				std::vector<LLUUID> item_ids;
-				LLUserAuth::options_t::iterator resp_it;
-				for (resp_it = gesture_options.begin();
-					 resp_it != gesture_options.end();
-					 ++resp_it)
+				for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(),
+					end = gesture_options.endArray(); resp_it != end; ++resp_it)
 				{
-					const LLUserAuth::response_t& response = *resp_it;
-					LLUUID item_id;
-					LLUUID asset_id;
-					LLUserAuth::response_t::const_iterator option_it;
-
-					option_it = response.find("item_id");
-					if (option_it != response.end())
-					{
-						const std::string& uuid_string = (*option_it).second;
-						item_id.set(uuid_string);
-					}
-					option_it = response.find("asset_id");
-					if (option_it != response.end())
-					{
-						const std::string& uuid_string = (*option_it).second;
-						asset_id.set(uuid_string);
-					}
+					// If the id is not specifed in the LLSD,
+					// the LLSD operator[]() will return a null LLUUID. 
+					LLUUID item_id = (*resp_it)["item_id"];
+					LLUUID asset_id = (*resp_it)["asset_id"];
 
 					if (item_id.notNull() && asset_id.notNull())
 					{
@@ -2364,8 +1849,8 @@ bool idle_startup()
 		if (!gAgent.isFirstLogin())
 		{
 			bool url_ok = LLURLSimString::sInstance.parse();
-			if ((url_ok && agent_start_location == "url") ||
-				(!url_ok && ((agent_start_location == gSavedSettings.getString("LoginLocation")))))
+			if ((url_ok && gAgentStartLocation == "url") ||
+				(!url_ok && ((gAgentStartLocation == gSavedSettings.getString("LoginLocation")))))
 			{
 				// Start location is OK
 				// Disabled code to restore camera location and focus if logging in to default location
@@ -2578,8 +2063,10 @@ bool idle_startup()
 		// then the data is cached for the viewer's lifetime)
 		LLProductInfoRequestManager::instance();
 		
+		// *FIX:Mani - What do I do here?
+		// Need we really clear the Auth response data?
 		// Clean up the userauth stuff.
-		LLUserAuth::getInstance()->reset();
+		// LLUserAuth::getInstance()->reset();
 
 		LLStartUp::setStartupState( STATE_STARTED );
 
@@ -2869,230 +2356,6 @@ bool login_alert_status(const LLSD& notification, const LLSD& response)
 	return false;
 }
 
-void update_app(BOOL mandatory, const std::string& auth_msg)
-{
-	// store off config state, as we might quit soon
-	gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);	
-	LLUIColorTable::instance().saveUserSettings();
-	std::ostringstream message;
-
-	std::string msg;
-	if (!auth_msg.empty())
-	{
-		msg = "("+ auth_msg + ") \n";
-	}
-
-	LLSD args;
-	args["MESSAGE"] = msg;
-	
-	LLSD payload;
-	payload["mandatory"] = mandatory;
-
-/*
- We're constructing one of the following 6 strings here:
-	 "DownloadWindowsMandatory"
-	 "DownloadWindowsReleaseForDownload"
-	 "DownloadWindows"
-	 "DownloadMacMandatory"
-	 "DownloadMacReleaseForDownload"
-	 "DownloadMac"
- 
- I've called them out explicitly in this comment so that they can be grepped for.
- 
- Also, we assume that if we're not Windows we're Mac. If we ever intend to support 
- Linux with autoupdate, this should be an explicit #elif LL_DARWIN, but 
- we'd rather deliver the wrong message than no message, so until Linux is supported
- we'll leave it alone.
- */
-	std::string notification_name = "Download";
-	
-#if LL_WINDOWS
-	notification_name += "Windows";
-#elif LL_DARWIN
-	notification_name += "Mac";
-#else
-	notification_name += "Linux";	
-#endif
-
-	if (mandatory)
-	{
-		notification_name += "Mandatory";
-	}
-	else
-	{
-#if LL_RELEASE_FOR_DOWNLOAD
-		notification_name += "ReleaseForDownload";
-#endif
-	}
-	
-	LLNotifications::instance().add(notification_name, args, payload, update_dialog_callback);
-}
-
-bool update_dialog_callback(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotification::getSelectedOption(notification, response);
-	std::string update_exe_path;
-	bool mandatory = notification["payload"]["mandatory"].asBoolean();
-
-#if !LL_RELEASE_FOR_DOWNLOAD
-	if (option == 2)
-	{
-		LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); 
-		return false;
-	}
-#endif
-
-	if (option == 1)
-	{
-		// ...user doesn't want to do it
-		if (mandatory)
-		{
-			LLAppViewer::instance()->forceQuit();
-			// Bump them back to the login screen.
-			//reset_login();
-		}
-		else
-		{
-			LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
-		}
-		return false;
-	}
-
-	// if a sim name was passed in via command line parameter (typically through a SLURL)
-	if ( LLURLSimString::sInstance.mSimString.length() )
-	{
-		// record the location to start at next time
-		gSavedSettings.setString("NextLoginLocation", LLURLSimString::sInstance.mSimString);
-	}
-	
-	LLSD query_map = LLSD::emptyMap();
-	// *TODO place os string in a global constant
-#if LL_WINDOWS  
-	query_map["os"] = "win";
-#elif LL_DARWIN
-	query_map["os"] = "mac";
-#elif LL_LINUX
-	query_map["os"] = "lnx";
-#elif LL_SOLARIS
-	query_map["os"] = "sol";
-#endif
-	// *TODO change userserver to be grid on both viewer and sim, since
-	// userserver no longer exists.
-	query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel();
-	query_map["channel"] = gSavedSettings.getString("VersionChannelName");
-	// *TODO constantize this guy
-	// *NOTE: This URL is also used in win_setup/lldownloader.cpp
-	LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map);
-	
-	if(LLAppViewer::sUpdaterInfo)
-	{
-		delete LLAppViewer::sUpdaterInfo ;
-	}
-	LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ;
-	
-#if LL_WINDOWS
-	LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename();
-	if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty())
-	{
-		delete LLAppViewer::sUpdaterInfo ;
-		LLAppViewer::sUpdaterInfo = NULL ;
-
-		// We're hosed, bail
-		LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL;
-		LLAppViewer::instance()->forceQuit();
-		return false;
-	}
-
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe";
-
-	std::string updater_source = gDirUtilp->getAppRODataDir();
-	updater_source += gDirUtilp->getDirDelimiter();
-	updater_source += "updater.exe";
-
-	LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source
-			<< " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath
-			<< LL_ENDL;
-
-
-	if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE))
-	{
-		delete LLAppViewer::sUpdaterInfo ;
-		LLAppViewer::sUpdaterInfo = NULL ;
-
-		LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL;
-		LLAppViewer::instance()->forceQuit();
-		return false;
-	}
-
-	LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\"";
-
-	LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL;
-
-	//Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird.
-	LLAppViewer::instance()->removeMarkerFile(); // In case updater fails
-	
-#elif LL_DARWIN
-	LLAppViewer::sUpdaterInfo->mUpdateExePath = "'";
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir();
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \"";
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString();
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \"";
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle();
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &";
-
-	LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
-
-	// Run the auto-updater.
-	system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */
-
-#elif (LL_LINUX || LL_SOLARIS) && LL_GTK
-	// we tell the updater where to find the xml containing string
-	// translations which it can use for its own UI
-	std::string xml_strings_file = "strings.xml";
-	std::vector<std::string> xui_path_vec = LLUI::getXUIPaths();
-	std::string xml_search_paths;
-	std::vector<std::string>::const_iterator iter;
-	// build comma-delimited list of xml paths to pass to updater
-	for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); )
-	{
-		std::string this_skin_dir = gDirUtilp->getDefaultSkinDir()
-			+ gDirUtilp->getDirDelimiter()
-			+ (*iter);
-		llinfos << "Got a XUI path: " << this_skin_dir << llendl;
-		xml_search_paths.append(this_skin_dir);
-		++iter;
-		if (iter != xui_path_vec.end())
-			xml_search_paths.append(","); // comma-delimit
-	}
-	// build the overall command-line to run the updater correctly
-	update_exe_path = 
-		gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + 
-		" --url \"" + update_url.asString() + "\"" +
-		" --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" +
-		" --dest \"" + gDirUtilp->getAppRODataDir() + "\"" +
-		" --stringsdir \"" + xml_search_paths + "\"" +
-		" --stringsfile \"" + xml_strings_file + "\"";
-
-	LL_INFOS("AppInit") << "Calling updater: " 
-			    << update_exe_path << LL_ENDL;
-
-	// *TODO: we could use the gdk equivilant to ensure the updater
-	// gets started on the same screen.
-	GError *error = NULL;
-	if (!g_spawn_command_line_async(update_exe_path.c_str(), &error))
-	{
-		llerrs << "Failed to launch updater: "
-		       << error->message
-		       << llendl;
-	}
-	if (error)
-		g_error_free(error);
-#else
-	OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK);
-#endif
-	LLAppViewer::instance()->forceQuit();
-	return false;
-}
 
 void use_circuit_callback(void**, S32 result)
 {
@@ -3439,11 +2702,7 @@ std::string LLStartUp::startupStateToString(EStartupState state)
 		RTNENUM( STATE_LOGIN_SHOW );
 		RTNENUM( STATE_LOGIN_WAIT );
 		RTNENUM( STATE_LOGIN_CLEANUP );
-		RTNENUM( STATE_UPDATE_CHECK );
 		RTNENUM( STATE_LOGIN_AUTH_INIT );
-		RTNENUM( STATE_LOGIN_AUTHENTICATE );
-		RTNENUM( STATE_LOGIN_NO_DATA_YET );
-		RTNENUM( STATE_LOGIN_DOWNLOADING );
 		RTNENUM( STATE_LOGIN_PROCESS_RESPONSE );
 		RTNENUM( STATE_WORLD_INIT );
 		RTNENUM( STATE_SEED_GRANTED_WAIT );
@@ -3463,14 +2722,17 @@ std::string LLStartUp::startupStateToString(EStartupState state)
 #undef RTNENUM
 }
 
-
 // static
 void LLStartUp::setStartupState( EStartupState state )
 {
 	LL_INFOS("AppInit") << "Startup state changing from " <<  
-		startupStateToString(gStartupState) << " to " <<  
+		getStartupStateString() << " to " <<  
 		startupStateToString(state) << LL_ENDL;
 	gStartupState = state;
+	LLSD stateInfo;
+	stateInfo["str"] = getStartupStateString();
+	stateInfo["enum"] = state;
+	sStartupStateWatcher.post(stateInfo);
 }
 
 
@@ -3584,3 +2846,278 @@ void apply_udp_blacklist(const std::string& csv)
 	
 }
 
+bool process_login_success_response()
+{
+	LLSD response = LLLoginInstance::getInstance()->getResponse();
+
+	std::string text(response["udp_blacklist"]);
+	if(!text.empty())
+	{
+		apply_udp_blacklist(text);
+	}
+
+	// unpack login data needed by the application
+	text = response["agent_id"].asString();
+	if(!text.empty()) gAgentID.set(text);
+	gDebugInfo["AgentID"] = text;
+	
+	text = response["session_id"].asString();
+	if(!text.empty()) gAgentSessionID.set(text);
+	gDebugInfo["SessionID"] = text;
+	
+	text = response["secure_session_id"].asString();
+	if(!text.empty()) gAgent.mSecureSessionID.set(text);
+
+	text = response["first_name"].asString();
+	if(!text.empty()) 
+	{
+		// Remove quotes from string.  Login.cgi sends these to force
+		// names that look like numbers into strings.
+		gFirstname.assign(text);
+		LLStringUtil::replaceChar(gFirstname, '"', ' ');
+		LLStringUtil::trim(gFirstname);
+	}
+	text = response["last_name"].asString();
+	if(!text.empty()) 
+	{
+		gLastname.assign(text);
+	}
+	gSavedSettings.setString("FirstName", gFirstname);
+	gSavedSettings.setString("LastName", gLastname);
+
+	if (gSavedSettings.getBOOL("RememberPassword"))
+	{
+		// Successful login means the password is valid, so save it.
+		LLStartUp::savePasswordToDisk(gPassword);
+	}
+	else
+	{
+		// Don't leave password from previous session sitting around
+		// during this login session.
+		LLStartUp::deletePasswordFromDisk();
+	}
+
+	// this is their actual ability to access content
+	text = response["agent_access_max"].asString();
+	if (!text.empty())
+	{
+		// agent_access can be 'A', 'M', and 'PG'.
+		gAgent.setMaturity(text[0]);
+	}
+	
+	// this is the value of their preference setting for that content
+	// which will always be <= agent_access_max
+	text = response["agent_region_access"].asString();
+	if (!text.empty())
+	{
+		int preferredMaturity = LLAgent::convertTextToMaturity(text[0]);
+		gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
+	}
+	// During the AO transition, this flag will be true. Then the flag will
+	// go away. After the AO transition, this code and all the code that
+	// uses it can be deleted.
+	text = response["ao_transition"].asString();
+	if (!text.empty())
+	{
+		if (text == "1")
+		{
+			gAgent.setAOTransition();
+		}
+	}
+
+	text = response["start_location"].asString();
+	if(!text.empty()) 
+	{
+		gAgentStartLocation.assign(text);
+	}
+
+	text = response["circuit_code"].asString();
+	if(!text.empty())
+	{
+		gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10);
+	}
+	std::string sim_ip_str = response["sim_ip"];
+	std::string sim_port_str = response["sim_port"];
+	if(!sim_ip_str.empty() && !sim_port_str.empty())
+	{
+		U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10);
+		gFirstSim.set(sim_ip_str, sim_port);
+		if (gFirstSim.isOk())
+		{
+			gMessageSystem->enableCircuit(gFirstSim, TRUE);
+		}
+	}
+	std::string region_x_str = response["region_x"];
+	std::string region_y_str = response["region_y"];
+	if(!region_x_str.empty() && !region_y_str.empty())
+	{
+		U32 region_x = strtoul(region_x_str.c_str(), NULL, 10);
+		U32 region_y = strtoul(region_y_str.c_str(), NULL, 10);
+		gFirstSimHandle = to_region_handle(region_x, region_y);
+	}
+	
+	const std::string look_at_str = response["look_at"];
+	if (!look_at_str.empty())
+	{
+		size_t len = look_at_str.size();
+		LLMemoryStream mstr((U8*)look_at_str.c_str(), len);
+		LLSD sd = LLSDSerialize::fromNotation(mstr, len);
+		gAgentStartLookAt = ll_vector3_from_sd(sd);
+	}
+
+	text = response["seed_capability"].asString();
+	if (!text.empty()) gFirstSimSeedCap = text;
+				
+	text = response["seconds_since_epoch"].asString();
+	if(!text.empty())
+	{
+		U32 server_utc_time = strtoul(text.c_str(), NULL, 10);
+		if(server_utc_time)
+		{
+			time_t now = time(NULL);
+			gUTCOffset = (server_utc_time - now);
+		}
+	}
+
+	// this is the base used to construct help URLs
+	text = response["help_url_format"].asString();
+	if (!text.empty())
+	{
+		// replace the default help URL format
+		gSavedSettings.setString("HelpURLFormat",text);
+		
+		// don't fall back to Nebraska's pre-connection static help
+		gSavedSettings.setBOOL("HelpUseLocal", false);
+	}
+			
+	std::string home_location = response["home"];
+	if(!home_location.empty())
+	{
+		size_t len = home_location.size();
+		LLMemoryStream mstr((U8*)home_location.c_str(), len);
+		LLSD sd = LLSDSerialize::fromNotation(mstr, len);
+		S32 region_x = sd["region_handle"][0].asInteger();
+		S32 region_y = sd["region_handle"][1].asInteger();
+		U64 region_handle = to_region_handle(region_x, region_y);
+		LLVector3 position = ll_vector3_from_sd(sd["position"]);
+		gAgent.setHomePosRegion(region_handle, position);
+	}
+
+	gAgent.mMOTD.assign(response["message"]);
+
+	// Options...
+	// Each 'option' is an array of submaps. 
+	// It appears that we only ever use the first element of the array.
+	LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"];
+	if(inv_root_folder_id.notNull())
+	{
+		gInventory.setRootFolderID(inv_root_folder_id);
+		//gInventory.mock(gAgent.getInventoryRootID());
+	}
+
+	LLSD login_flags = response["login-flags"][0];
+	if(login_flags.size())
+	{
+		std::string flag = login_flags["ever_logged_in"];
+		if(!flag.empty())
+		{
+			gAgent.setFirstLogin((flag == "N") ? TRUE : FALSE);
+		}
+
+		/*  Flag is currently ignored by the viewer.
+		flag = login_flags["stipend_since_login"];
+		if(flag == "Y") 
+		{
+			stipend_since_login = true;
+		}
+		*/
+
+		flag = login_flags["gendered"].asString();
+		if(flag == "Y")
+		{
+			gAgent.setGenderChosen(TRUE);
+		}
+		
+		bool pacific_daylight_time = false;
+		flag = login_flags["daylight_savings"].asString();
+		if(flag == "Y")
+		{
+			pacific_daylight_time = (flag == "Y");
+		}
+
+		//setup map of datetime strings to codes and slt & local time offset from utc
+		LLStringOps::setupDatetimeInfo(pacific_daylight_time);
+	}
+
+	LLSD initial_outfit = response["initial-outfit"][0];
+	if(initial_outfit.size())
+	{
+		std::string flag = initial_outfit["folder_name"];
+		if(!flag.empty())
+		{
+			// Initial outfit is a folder in your inventory,
+			// must be an exact folder-name match.
+			sInitialOutfit = flag;
+		}
+
+		flag = initial_outfit["gender"].asString();
+		if(!flag.empty())
+		{
+			sInitialOutfitGender = flag;
+		}
+	}
+
+	LLSD global_textures = response["global-textures"][0];
+	if(global_textures.size())
+	{
+		// Extract sun and moon texture IDs.  These are used
+		// in the LLVOSky constructor, but I can't figure out
+		// how to pass them in.  JC
+		LLUUID id = global_textures["sun_texture_id"];
+		if(id.notNull())
+		{
+			gSunTextureID = id;
+		}
+
+		id = global_textures["moon_texture_id"];
+		if(id.notNull())
+		{
+			gMoonTextureID = id;
+		}
+
+		id = global_textures["cloud_texture_id"];
+		if(id.notNull())
+		{
+			gCloudTextureID = id;
+		}
+	}
+
+
+	bool success = false;
+	// JC: gesture loading done below, when we have an asset system
+	// in place.  Don't delete/clear user_credentials until then.
+	if(gAgentID.notNull()
+	   && gAgentSessionID.notNull()
+	   && gMessageSystem->mOurCircuitCode
+	   && gFirstSim.isOk()
+	   && gInventory.getRootFolderID().notNull())
+	{
+		success = true;
+	}
+
+	return success;
+}
+
+void transition_back_to_login_panel(const std::string& emsg)
+{
+	if (gNoRender)
+	{
+		LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL;
+		LL_WARNS("AppInit") << emsg << LL_ENDL;
+		exit(0);
+	}
+
+	// Bounce back to the login screen.
+	reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+	gSavedSettings.setBOOL("AutoLogin", FALSE);
+}
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index 4532c5e586c44acdbfcfe553b55e0376b37b3add..7f869d014f8d3098586255616eaebf094d5691e0 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -50,11 +50,7 @@ typedef enum {
 	STATE_LOGIN_SHOW,				// Show login screen
 	STATE_LOGIN_WAIT,				// Wait for user input at login screen
 	STATE_LOGIN_CLEANUP,			// Get rid of login screen and start login
-	STATE_UPDATE_CHECK,				// Wait for user at a dialog box (updates, term-of-service, etc)
 	STATE_LOGIN_AUTH_INIT,			// Start login to SL servers
-	STATE_LOGIN_AUTHENTICATE,		// Do authentication voodoo
-	STATE_LOGIN_NO_DATA_YET,		// Waiting for authentication replies to start
-	STATE_LOGIN_DOWNLOADING,		// Waiting for authentication replies to download
 	STATE_LOGIN_PROCESS_RESPONSE,	// Check authentication reply
 	STATE_WORLD_INIT,				// Start building the world
 	STATE_MULTIMEDIA_INIT,			// Init the rest of multimedia library
@@ -75,8 +71,6 @@ typedef enum {
 // exported symbols
 extern bool gAgentMovementCompleted;
 extern LLPointer<LLViewerTexture> gStartTexture;
-extern std::string gInitialOutfit;
-extern std::string gInitialOutfitGender;	// "male" or "female"
 
 class LLStartUp
 {
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 86290e66955a744f8f18552026cf04b21ee381a6..c25541842967c8dc7007672666eaede8d8b5f74d 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -112,6 +112,12 @@ void LLSysWellWindow::connectListUpdaterToSignal(std::string notification_type)
 	}
 }
 
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask)
+{
+	onChicletClick();
+}
+
 //---------------------------------------------------------------------------------
 void LLSysWellWindow::onChicletClick()
 {
@@ -403,7 +409,6 @@ bool LLSysWellWindow::isWindowEmpty()
 void LLSysWellWindow::sessionAdded(const LLUUID& session_id,
 		const std::string& name, const LLUUID& other_participant_id)
 {
-	//*TODO get rid of get_session_value, session_id's are unique, cause performance degradation with lots chiclets (IB)
 	if (mMessageList->getItemByValue(session_id) == NULL)
 	{
 		S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id);
@@ -421,7 +426,6 @@ void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId)
 {
 	delIMRow(sessionId);
 	reshapeWindow();
-	LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications();
 }
 
 void LLSysWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index fa6a1abea47ae7996b413e0229c6b545a752a5b5..cbc5f7358f0cf36e66b4cd7189ddb7d2ec6765f3 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -76,6 +76,7 @@ class LLSysWellWindow : public LLDockableFloater, LLIMSessionObserver
 	void onItemClose(LLSysWellItem* item);
 	void onStoreToast(LLPanel* info_panel, LLUUID id);
 	void onChicletClick();
+	void onStartUpToastClick(S32 x, S32 y, MASK mask);
 
 	// size constants for the window and for its elements
 	static const S32 MAX_WINDOW_HEIGHT		= 200;
diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp
index e1643af71de9054816695bc8903e1d986ef5f7e6..74e0fa077e397542cfbdb25148c4704ec1dd30ef 100644
--- a/indra/newview/lltexlayerparams.cpp
+++ b/indra/newview/lltexlayerparams.cpp
@@ -42,8 +42,7 @@
 //-----------------------------------------------------------------------------
 LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
 	mTexLayer(layer),
-	mAvatar(NULL),
-	mIsWearableParam(TRUE)
+	mAvatar(NULL)
 {
 	if (mTexLayer != NULL)
 	{
@@ -56,8 +55,7 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
 }
 
 LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) :
-	mTexLayer(NULL),
-	mIsWearableParam(FALSE)
+	mTexLayer(NULL)
 {
 	mAvatar = avatar;
 }
@@ -177,7 +175,7 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user)
 	{
 		mCurWeight = new_weight;
 
-		if ((mAvatar->getSex() & getSex()) && !mIsWearableParam) // only trigger a baked texture update if we're changing a wearable's visual param.
+		if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
 		{
 			if (gAgent.cameraCustomizeAvatar())
 			{
@@ -192,6 +190,13 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user)
 
 void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user)
 { 
+	// do not animate dummy parameters
+	if (mIsDummy)
+	{
+		setWeight(target_value, set_by_user);
+		return;
+	}
+
 	mTargetWeight = target_value; 
 	setWeight(target_value, set_by_user); 
 	mIsAnimating = TRUE;
@@ -468,7 +473,7 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL set_by_user)
 			return;
 		}
 
-		if ((mAvatar->getSex() & getSex()) && !mIsWearableParam) // only trigger a baked texture update if we're changing a wearable's visual param.
+		if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
 		{
 			onGlobalColorChanged(set_by_user);
 			if (mTexLayer)
diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h
index dcb108bbf63b7bc2fbf0266e3723772b0077b0bd..98365864f99eb46d52adee903ed952116777a2b8 100644
--- a/indra/newview/lltexlayerparams.h
+++ b/indra/newview/lltexlayerparams.h
@@ -49,7 +49,6 @@ class LLTexLayerParam : public LLViewerVisualParam
 protected:
 	LLTexLayerInterface*	mTexLayer;
 	LLVOAvatar*             mAvatar;
-	BOOL					mIsWearableParam;
 };
 
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index ae4ec75a1b4479c518ea1dbe3756761fd7502ddb..6391e5b8b2e96fec7f347b9f8d696885eed55b77 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -458,7 +458,7 @@ BOOL LLFloaterTexturePicker::postBuild()
 // virtual
 void LLFloaterTexturePicker::draw()
 {
-	static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+	S32 floater_header_size = getHeaderHeight();
 	if (mOwner)
 	{
 		// draw cone of context pointing back to texture swatch	
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index eba43d76a6b1a999694d35e47d659e4778f24373..903df21e785044ceb557eba7c05fd6332156737c 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -49,13 +49,15 @@ LLToast::Params::Params()
 	enable_hide_btn("enable_hide_btn", true),
 	force_show("force_show", false),
 	force_store("force_store", false),
+	fading_time_secs("fading_time_secs", gSavedSettings.getS32("ToastFadingTime")),
 	lifetime_secs("lifetime_secs", gSavedSettings.getS32("NotificationToastLifeTime"))
 {};
 
 LLToast::LLToast(const LLToast::Params& p) 
 :	LLModalDialog(LLSD(), p.is_modal),
 	mPanel(p.panel), 
-	mToastLifetime(p.lifetime_secs),  
+	mToastLifetime(p.lifetime_secs),
+	mToastFadingTime(p.fading_time_secs),
 	mNotificationID(p.notif_id),  
 	mSessionID(p.session_id),
 	mCanFade(p.can_fade),
@@ -63,6 +65,7 @@ LLToast::LLToast(const LLToast::Params& p)
 	mHideBtnEnabled(p.enable_hide_btn),
 	mHideBtn(NULL),
 	mNotification(p.notification),
+	mIsHidden(false),
 	mHideBtnPressed(false)
 {
 	LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL);
@@ -126,7 +129,7 @@ bool LLToast::lifetimeHasExpired()
 	if (mTimer.getStarted())
 	{
 		F32 elapsed_time = mTimer.getElapsedTimeF32();
-		if ((mToastLifetime - elapsed_time) <= gSavedSettings.getS32("ToastOpaqueTime")) 
+		if ((mToastLifetime - elapsed_time) <= mToastFadingTime) 
 		{
 			setBackgroundOpaque(FALSE);
 		}
@@ -143,7 +146,8 @@ void LLToast::hide()
 {
 	setVisible(FALSE);
 	mTimer.stop();
-	mOnFadeSignal(this);
+	mIsHidden = true;
+	mOnFadeSignal(this); 
 }
 
 //--------------------------------------------------------------------------
@@ -159,9 +163,7 @@ void LLToast::tick()
 {
 	if(mCanFade)
 	{
-		setVisible(FALSE);
-		mTimer.stop();
-		mOnFadeSignal(this); 
+		hide();
 	}
 }
 
@@ -206,6 +208,16 @@ void LLToast::draw()
 //--------------------------------------------------------------------------
 void LLToast::setVisible(BOOL show)
 {
+	if(mIsHidden)
+	{
+		// this toast is invisible after fade until its ScreenChannel will allow it
+		//
+		// (EXT-1849) according to this bug a toast can be resurrected from
+		// invisible state if it faded during a teleportation
+		// then it fades a second time and causes a crash
+		return;
+	}
+
 	if(show)
 	{
 		setBackgroundOpaque(TRUE);
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 1826c13ebc8bc69185319151c2099336a0f66ea3..b670f470452d4b1b1b38b5fbc07c7ab5fe97e342 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -63,7 +63,8 @@ class LLToast : public LLModalDialog
 		Optional<LLUUID>				notif_id,	 //notification ID
 										session_id;	 //im session ID
 		Optional<LLNotificationPtr>		notification;
-		Optional<F32>					lifetime_secs;
+		Optional<F32>					lifetime_secs,
+										fading_time_secs; // Number of seconds while a toast is fading
 		Optional<toast_callback_t>		on_delete_toast,
 										on_mouse_enter;
 		Optional<bool>					can_fade,
@@ -125,6 +126,8 @@ class LLToast : public LLModalDialog
 	void setCanBeStored(bool can_be_stored) { mCanBeStored = can_be_stored; }
 	//
 	bool getCanBeStored() { return mCanBeStored; }
+	// set whether this toast considered as hidden or not
+	void setIsHidden( bool is_toast_hidden ) { mIsHidden = is_toast_hidden; }
 
 
 	// Registers signals/callbacks for events
@@ -155,6 +158,7 @@ class LLToast : public LLModalDialog
 	// timer counts a lifetime of a toast
 	LLTimer		mTimer;
 	F32			mToastLifetime; // in seconds
+	F32			mToastFadingTime; // in seconds
 
 	LLPanel*	mPanel;
 	LLButton*	mHideBtn;
@@ -164,6 +168,7 @@ class LLToast : public LLModalDialog
 	bool		mCanBeStored;
 	bool		mHideBtnEnabled;
 	bool		mHideBtnPressed;
+	bool		mIsHidden;  // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849)
 };
 
 }
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index c2cd63900bd8a402a1d15e29aef3e66fb18af058..c02fd7a5eff956eccd2227ce82e48ed14d429150 100644
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -32,7 +32,6 @@
 
 #include "llviewerprecompiledheaders.h"
 #include "lltoastimpanel.h"
-#include "llimpanel.h"
 
 const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT	= 6;
 
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index b015f668e4a36485a2908402d076dc13c65c812d..304f1dffaf009f7a248b2f771cd4e6b9a13bb4b2 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -48,6 +48,7 @@
 #include "lltooltip.h"
 #include "llhudeffecttrail.h"
 #include "llhudmanager.h"
+#include "llkeyboard.h"
 #include "llmediaentry.h"
 #include "llmenugl.h"
 #include "llmutelist.h"
@@ -518,11 +519,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
 
 		if(!object)
 		{
-			// We need to clear media hover flag
-			if (LLViewerMediaFocus::getInstance()->getMouseOverFlag())
-			{
-				LLViewerMediaFocus::getInstance()->setMouseOverFlag(false);
-			}
+			LLViewerMediaFocus::getInstance()->clearHover();
 		}
 	}
 
@@ -735,7 +732,47 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
 				{
 					tooltip_msg.append( nodep->mName );
 				}
-
+				
+				bool is_time_based_media = false;
+				bool is_web_based_media = false;
+				bool is_media_playing = false;
+				
+				// Does this face have media?
+				const LLTextureEntry* tep = hover_object->getTE(mHoverPick.mObjectFace);
+				
+				if(tep)
+				{
+					const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+					if (mep)
+					{
+						viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL;
+						LLPluginClassMedia* media_plugin = NULL;
+				
+						if (media_impl.notNull() && (media_impl->hasMedia()))
+						{
+							LLStringUtil::format_map_t args;
+					
+							media_plugin = media_impl->getMediaPlugin();
+							if(media_plugin)
+							{	if(media_plugin->pluginSupportsMediaTime())
+								{
+									is_time_based_media = true;
+									is_web_based_media = false;
+									args["[CurrentURL]"] =  media_impl->getMediaURL();
+									is_media_playing = media_impl->isMediaPlaying();
+								}
+								else
+								{
+									is_time_based_media = false;
+									is_web_based_media = true;
+									args["[CurrentURL]"] =  media_plugin->getLocation();
+								}
+								//tooltip_msg.append(LLTrans::getString("CurrentURL", args));
+							}
+						}
+					}
+				}
+				
 				bool needs_tip = needs_tooltip(nodep);
 
 				if (show_all_object_tips || needs_tip)
@@ -744,8 +781,13 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
 					mPick = mHoverPick;
 					LLToolTipMgr::instance().show(LLToolTip::Params()
 						.message(tooltip_msg)
-						.image(LLUI::getUIImage("Info"))
-						.click_callback(boost::bind(showObjectInspector, hover_object->getID()))
+						.image(LLUI::getUIImage("Info_Off"))
+						.click_callback(boost::bind(showObjectInspector, hover_object->getID(), mHoverPick.mObjectFace))
+						.time_based_media(is_time_based_media)
+						.web_based_media(is_web_based_media)						  
+						.media_playing(is_media_playing)						  
+						.click_playmedia_callback(boost::bind(playCurrentMedia, mHoverPick))
+						.click_homepage_callback(boost::bind(VisitHomePage, mHoverPick))						
 						.visible_time_near(6.f)
 						.visible_time_far(3.f)
 						.wrap(false));
@@ -928,6 +970,20 @@ static void show_inspector(const char* inspector, const char* param, const LLUUI
 	LLFloaterReg::showInstance(inspector, params);
 }
 
+
+static void show_inspector(const char* inspector,  LLSD& params)
+{
+	if (LLToolTipMgr::instance().toolTipVisible())
+	{
+		LLRect rect = LLToolTipMgr::instance().getToolTipRect();
+		params["pos"]["x"] = rect.mLeft;
+		params["pos"]["y"] = rect.mTop;
+	}
+	
+	LLFloaterReg::showInstance(inspector, params);
+}
+
+
 // static
 void LLToolPie::showAvatarInspector(const LLUUID& avatar_id)
 {
@@ -940,6 +996,114 @@ void LLToolPie::showObjectInspector(const LLUUID& object_id)
 	show_inspector("inspect_object", "object_id", object_id);
 }
 
+
+// static
+void LLToolPie::showObjectInspector(const LLUUID& object_id, const S32& object_face)
+{
+	LLSD params;
+	params["object_id"] = object_id;
+	params["object_face"] = object_face;
+	show_inspector("inspect_object", params);
+}
+
+// static
+void LLToolPie::playCurrentMedia(const LLPickInfo& info)
+{
+	//FIXME: how do we handle object in different parcel than us?
+	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	if (!parcel) return;
+	
+	LLPointer<LLViewerObject> objectp = info.getObject();
+	
+	// Early out cases.  Must clear media hover. 
+	// did not hit an object or did not hit a valid face
+	if ( objectp.isNull() ||
+		info.mObjectFace < 0 || 
+		info.mObjectFace >= objectp->getNumTEs() )
+	{
+		return;
+	}
+	
+	// Does this face have media?
+	const LLTextureEntry* tep = objectp->getTE(info.mObjectFace);
+	if (!tep)
+		return;
+	
+	const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+	if(!mep)
+		return;
+	
+	LLPluginClassMedia* media_plugin = NULL;
+	
+//	if (gSavedSettings.getBOOL("MediaOnAPrimUI"))
+//	{		
+		viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+		
+		if(media_impl.notNull() && media_impl->hasMedia())
+		{
+			media_plugin = media_impl->getMediaPlugin();
+			
+			if (media_plugin && media_plugin->pluginSupportsMediaTime())
+			{
+				if(media_impl->isMediaPlaying())
+				{
+					media_impl->pause();
+				}
+				else //if(media_impl->isMediaPaused())
+				{
+					media_impl->play();
+				}
+				
+			}
+					
+		}
+//	 }
+
+}
+
+// static
+void LLToolPie::VisitHomePage(const LLPickInfo& info)
+{
+	//FIXME: how do we handle object in different parcel than us?
+	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	if (!parcel) return;
+	
+	LLPointer<LLViewerObject> objectp = info.getObject();
+	
+	// Early out cases.  Must clear media hover. 
+	// did not hit an object or did not hit a valid face
+	if ( objectp.isNull() ||
+		info.mObjectFace < 0 || 
+		info.mObjectFace >= objectp->getNumTEs() )
+	{
+		return;
+	}
+	
+	// Does this face have media?
+	const LLTextureEntry* tep = objectp->getTE(info.mObjectFace);
+	if (!tep)
+		return;
+	
+	const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+	if(!mep)
+		return;
+	
+	LLPluginClassMedia* media_plugin = NULL;
+	
+	viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+	
+	if(media_impl.notNull() && media_impl->hasMedia())
+	{
+		media_plugin = media_impl->getMediaPlugin();
+		
+		if (media_plugin && !(media_plugin->pluginSupportsMediaTime()))
+		{
+			media_impl->navigateHome();
+		}
+	}
+}
+
+
 void LLToolPie::handleDeselect()
 {
 	if(	hasMouseCapture() )
@@ -1029,7 +1193,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
 		pick.mObjectFace < 0 || 
 		pick.mObjectFace >= objectp->getNumTEs()) 
 	{
-		LLSelectMgr::getInstance()->deselect();
 		LLViewerMediaFocus::getInstance()->clearFocus();
 
 		return false;
@@ -1037,29 +1200,31 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
 
 
 
-	// HACK: This is directly referencing an impl name.  BAD!
-	// This can be removed when we have a truly generic media browser that only 
-	// builds an impl based on the type of url it is passed.
-
-	// is media playing on this face?
+	// Does this face have media?
 	const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
+	if(!tep)
+		return false;
+
 	LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
+	
+	if(!mep)
+		return false;
+	
 	viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL;
 
-	if (tep 
-		&& mep
-		&& gSavedSettings.getBOOL("MediaOnAPrimUI")
+	if (gSavedSettings.getBOOL("MediaOnAPrimUI")
 		&& media_impl.notNull())
 	{
-		// LLObjectSelectionHandle selection = /*LLViewerMediaFocus::getInstance()->getSelection()*/ LLSelectMgr::getInstance()->getSelection();
-		if (/*! selection->contains(pick.getObject(), pick.mObjectFace)*/
-			! LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) )
+		if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) )
 		{
-			LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl);
+			LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
 		}
 		else
 		{
-			media_impl->mouseDown(pick.mUVCoords);
+			// Make sure keyboard focus is set to the media focus object.
+			gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
+			
+			media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE));
 			mMediaMouseCaptureID = mep->getMediaID();
 			setMouseCapture(TRUE);  // This object will send a mouse-up to the media when it loses capture.
 		}
@@ -1067,7 +1232,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
 		return true;
 	}
 
-	LLSelectMgr::getInstance()->deselect();
 	LLViewerMediaFocus::getInstance()->clearFocus();
 
 	return false;
@@ -1081,50 +1245,53 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick)
 
 	LLPointer<LLViewerObject> objectp = pick.getObject();
 
-	// Early out cases.  Must clear mouse over media focus flag
+	// Early out cases.  Must clear media hover. 
 	// did not hit an object or did not hit a valid face
 	if ( objectp.isNull() ||
 		pick.mObjectFace < 0 || 
 		pick.mObjectFace >= objectp->getNumTEs() )
 	{
-		LLViewerMediaFocus::getInstance()->setMouseOverFlag(false);
+		LLViewerMediaFocus::getInstance()->clearHover();
 		return false;
 	}
 
-
-	// HACK: This is directly referencing an impl name.  BAD!
-	// This can be removed when we have a truly generic media browser that only 
-	// builds an impl based on the type of url it is passed.
-
-	// is media playing on this face?
+	// Does this face have media?
 	const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
+	if(!tep)
+		return false;
+	
 	const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
 	if (mep
 		&& gSavedSettings.getBOOL("MediaOnAPrimUI"))
 	{		
 		viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
-		if(LLViewerMediaFocus::getInstance()->getFocus() && media_impl.notNull())
-		{
-			media_impl->mouseMove(pick.mUVCoords);
-
-			gViewerWindow->setCursor(media_impl->getLastSetCursor());
-		}
-		else
+		
+		if(media_impl.notNull())
 		{
-			gViewerWindow->setCursor(UI_CURSOR_ARROW);
-		}
+			// Update media hover object
+			if (!LLViewerMediaFocus::getInstance()->isHoveringOverFace(objectp, pick.mObjectFace))
+			{
+				LLViewerMediaFocus::getInstance()->setHoverFace(objectp, pick.mObjectFace, media_impl, pick.mNormal);
+			}
+			
+			// If this is the focused media face, send mouse move events.
+			if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace))
+			{
+				media_impl->mouseMove(pick.mUVCoords, gKeyboard->currentMask(TRUE));
+				gViewerWindow->setCursor(media_impl->getLastSetCursor());
+			}
+			else
+			{
+				// This is not the focused face -- set the default cursor.
+				gViewerWindow->setCursor(UI_CURSOR_ARROW);
+			}
 
-		// Set mouse over flag if unset
-		if (! LLViewerMediaFocus::getInstance()->getMouseOverFlag())
-		{
-			LLSelectMgr::getInstance()->setHoverObject(objectp, pick.mObjectFace);
-			LLViewerMediaFocus::getInstance()->setMouseOverFlag(true, media_impl);
-			LLViewerMediaFocus::getInstance()->setPickInfo(pick);
+			return true;
 		}
-
-		return true;
 	}
-	LLViewerMediaFocus::getInstance()->setMouseOverFlag(false);
+	
+	// In all other cases, clear media hover.
+	LLViewerMediaFocus::getInstance()->clearHover();
 
 	return false;
 }
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 5faedbec5aae03f74508fb7cb8deed99030f1145..3660c685525d9436eaac30856acd182bb1d46708 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -78,6 +78,10 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
 
 	static void			showAvatarInspector(const LLUUID& avatar_id);
 	static void			showObjectInspector(const LLUUID& object_id);
+	static void			showObjectInspector(const LLUUID& object_id, const S32& object_face);
+	static void			playCurrentMedia(const LLPickInfo& info);
+	static void			VisitHomePage(const LLPickInfo& info);
+	
 private:
 	BOOL outsideSlop		(S32 x, S32 y, S32 start_x, S32 start_y);
 	BOOL pickLeftMouseDownCallback();
diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9c643e78dec9ee2fcd8f0833a7697ec3308a75f6
--- /dev/null
+++ b/indra/newview/lluilistener.cpp
@@ -0,0 +1,50 @@
+/**
+ * @file   lluilistener.cpp
+ * @author Nat Goodspeed
+ * @date   2009-08-18
+ * @brief  Implementation for lluilistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "lluilistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "lluictrl.h"
+#include "llerror.h"
+
+LLUIListener::LLUIListener(const std::string& name):
+    LLDispatchListener(name, "op")
+{
+    add("call", &LLUIListener::call, LLSD().insert("function", LLSD()));
+}
+
+void LLUIListener::call(const LLSD& event) const
+{
+    LLUICtrl::commit_callback_t* func =
+        LLUICtrl::CommitCallbackRegistry::getValue(event["function"]);
+    if (! func)
+    {
+        // This API is intended for use by a script. It's a fire-and-forget
+        // API: we provide no reply. Therefore, a typo in the script will
+        // provide no feedback whatsoever to that script. To rub the coder's
+        // nose in such an error, crump rather than quietly ignoring it.
+        LL_ERRS("LLUIListener") << "function '" << event["function"] << "' not found" << LL_ENDL;
+    }
+    else
+    {
+        // Interestingly, view_listener_t::addMenu() (addCommit(),
+        // addEnable()) constructs a commit_callback_t callable that accepts
+        // two parameters but discards the first. Only the second is passed to
+        // handleEvent(). Therefore we feel completely safe passing NULL for
+        // the first parameter.
+        (*func)(NULL, event["parameter"]);
+    }
+}
diff --git a/indra/newview/lluilistener.h b/indra/newview/lluilistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea904a99ff86b82bae69b85d79a920ad5d84cc9f
--- /dev/null
+++ b/indra/newview/lluilistener.h
@@ -0,0 +1,29 @@
+/**
+ * @file   lluilistener.h
+ * @author Nat Goodspeed
+ * @date   2009-08-18
+ * @brief  Engage named functions as specified by XUI
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLUILISTENER_H)
+#define LL_LLUILISTENER_H
+
+#include "lleventdispatcher.h"
+#include <string>
+
+class LLSD;
+
+class LLUIListener: public LLDispatchListener
+{
+public:
+    LLUIListener(const std::string& name);
+
+private:
+    void call(const LLSD& event) const;
+};
+
+#endif /* ! defined(LL_LLUILISTENER_H) */
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index b71291f834f5358f502ce3aa589a28cc8cde105e..35226a1632078d02db1f06fc4e78045096585e31 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -511,13 +511,34 @@ bool toggle_show_snapshot_button(const LLSD& newvalue)
 
 bool toggle_show_navigation_panel(const LLSD& newvalue)
 {
-	LLNavigationBar::getInstance()->showNavigationPanel(newvalue.asBoolean());
+	LLRect floater_view_rect = gFloaterView->getRect();
+	LLRect notify_view_rect = gNotifyBoxView->getRect();
+	LLNavigationBar* navbar = LLNavigationBar::getInstance();
+	
+	//if newvalue contains 0 => navbar should turn invisible, so floater_view_rect should get higher, 
+	//and to do this pm=1, else if navbar becomes visible pm=-1 so floater_view_rect gets lower.
+	int pm=newvalue.asBoolean()?-1:1;
+	floater_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight());
+	notify_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight());
+	gFloaterView->setRect(floater_view_rect);
+	floater_view_rect = gFloaterView->getRect();
+	navbar->showNavigationPanel(newvalue.asBoolean());
 	return true;
 }
 
 bool toggle_show_favorites_panel(const LLSD& newvalue)
 {
-	LLNavigationBar::getInstance()->showFavoritesPanel(newvalue.asBoolean());
+	LLRect floater_view_rect = gFloaterView->getRect();
+	LLRect notify_view_rect = gNotifyBoxView->getRect();
+	LLNavigationBar* navbar = LLNavigationBar::getInstance();
+	
+	//if newvalue contains 0 => favbar should turn invisible, so floater_view_rect should get higher, 
+	//and to do this pm=1, else if favbar becomes visible pm=-1 so floater_view_rect gets lower.
+	int pm=newvalue.asBoolean()?-1:1;
+	floater_view_rect.mTop += pm*navbar->getDefFavBarHeight();
+	notify_view_rect.mTop += pm*navbar->getDefFavBarHeight();
+	gFloaterView->setRect(floater_view_rect);
+	navbar->showFavoritesPanel(newvalue.asBoolean());
 	return true;
 }
 
diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h
index b1f14eca7b68205f297ca77d6e86a64128faa278..9b4e80cae06f0994776d696f9228ff8ee5774f86 100644
--- a/indra/newview/llviewercontrol.h
+++ b/indra/newview/llviewercontrol.h
@@ -43,6 +43,9 @@
 extern BOOL gHackGodmode;
 #endif
 
+bool toggle_show_navigation_panel(const LLSD& newvalue);
+bool toggle_show_favorites_panel(const LLSD& newvalue);
+
 // These functions found in llcontroldef.cpp *TODO: clean this up!
 //setting variables are declared in this function
 void settings_setup_listeners();
diff --git a/indra/newview/llviewercontrollistener.cpp b/indra/newview/llviewercontrollistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ecba1b8eb0a3ea26dc4aa33eb24d1856f96ecf6b
--- /dev/null
+++ b/indra/newview/llviewercontrollistener.cpp
@@ -0,0 +1,102 @@
+/**
+ * @file   llviewercontrollistener.cpp
+ * @author Brad Kittenbrink
+ * @date   2009-07-09
+ * @brief  Implementation for llviewercontrollistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewercontrollistener.h"
+
+#include "llviewercontrol.h"
+
+LLViewerControlListener gSavedSettingsListener;
+
+LLViewerControlListener::LLViewerControlListener()
+	: LLDispatchListener("LLViewerControl",  "group")
+{
+	add("Global", boost::bind(&LLViewerControlListener::set, &gSavedSettings, _1));
+	add("PerAccount", boost::bind(&LLViewerControlListener::set, &gSavedPerAccountSettings, _1));
+	add("Warning", boost::bind(&LLViewerControlListener::set, &gWarningSettings, _1));
+	add("Crash", boost::bind(&LLViewerControlListener::set, &gCrashSettings, _1));
+
+#if 0
+	add(/*"toggleControl",*/ "Global", boost::bind(&LLViewerControlListener::toggleControl, &gSavedSettings, _1));
+	add(/*"toggleControl",*/ "PerAccount", boost::bind(&LLViewerControlListener::toggleControl, &gSavedPerAccountSettings, _1));
+	add(/*"toggleControl",*/ "Warning", boost::bind(&LLViewerControlListener::toggleControl, &gWarningSettings, _1));
+	add(/*"toggleControl",*/ "Crash", boost::bind(&LLViewerControlListener::toggleControl, &gCrashSettings, _1));
+
+	add(/*"setDefault",*/ "Global", boost::bind(&LLViewerControlListener::setDefault, &gSavedSettings, _1));
+	add(/*"setDefault",*/ "PerAccount", boost::bind(&LLViewerControlListener::setDefault, &gSavedPerAccountSettings, _1));
+	add(/*"setDefault",*/ "Warning", boost::bind(&LLViewerControlListener::setDefault, &gWarningSettings, _1));
+	add(/*"setDefault",*/ "Crash", boost::bind(&LLViewerControlListener::setDefault, &gCrashSettings, _1));
+#endif // 0
+}
+
+//static
+void LLViewerControlListener::set(LLControlGroup * controls, LLSD const & event_data)
+{
+	if(event_data.has("key"))
+	{
+		std::string key(event_data["key"]);
+
+		if(controls->controlExists(key))
+		{
+			controls->setUntypedValue(key, event_data["value"]);
+		}
+		else
+		{
+			llwarns << "requested unknown control: \"" << key << '\"' << llendl;
+		}
+	}
+}
+
+//static
+void LLViewerControlListener::toggleControl(LLControlGroup * controls, LLSD const & event_data)
+{
+	if(event_data.has("key"))
+	{
+		std::string key(event_data["key"]);
+
+		if(controls->controlExists(key))
+		{
+			LLControlVariable * control = controls->getControl(key);
+			if(control->isType(TYPE_BOOLEAN))
+			{
+				control->set(!control->get().asBoolean());
+			}
+			else
+			{
+				llwarns << "requested toggle of non-boolean control: \"" << key << "\", type is " << control->type() << llendl;
+			}
+		}
+		else
+		{
+			llwarns << "requested unknown control: \"" << key << '\"' << llendl;
+		}
+	}
+}
+
+//static
+void LLViewerControlListener::setDefault(LLControlGroup * controls, LLSD const & event_data)
+{
+	if(event_data.has("key"))
+	{
+		std::string key(event_data["key"]);
+
+		if(controls->controlExists(key))
+		{
+			LLControlVariable * control = controls->getControl(key);
+			control->resetToDefault();
+		}
+		else
+		{
+			llwarns << "requested unknown control: \"" << key << '\"' << llendl;
+		}
+	}
+}
diff --git a/indra/newview/llviewercontrollistener.h b/indra/newview/llviewercontrollistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..cacf97e908e8f6784339e155b20267b718acfbdf
--- /dev/null
+++ b/indra/newview/llviewercontrollistener.h
@@ -0,0 +1,33 @@
+/**
+ * @file   llviewercontrollistener.h
+ * @author Brad Kittenbrink
+ * @date   2009-07-09
+ * @brief  Event API for subset of LLViewerControl methods
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERCONTROLLISTENER_H
+#define LL_LLVIEWERCONTROLLISTENER_H
+
+#include "lleventdispatcher.h"
+
+class LLControlGroup;
+class LLSD;
+
+class  LLViewerControlListener : public LLDispatchListener
+{
+public:
+	LLViewerControlListener();
+
+private:
+	static void set(LLControlGroup *controls, LLSD const & event_data);
+	static void toggleControl(LLControlGroup *controls, LLSD const & event_data);
+	static void setDefault(LLControlGroup *controls, LLSD const & event_data);
+};
+
+extern LLViewerControlListener gSavedSettingsListener;
+
+#endif // LL_LLVIEWERCONTROLLISTENER_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 7c5f5e8b2f9e48ca3ab35a267b23ee7b7aef0a70..4ff1e6c7032b6cab5db8fb082661a3766adfea5c 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -80,6 +80,7 @@
 #include "llfloatermap.h"
 #include "llfloatermemleak.h"
 #include "llfloaternamedesc.h"
+#include "llfloaternearbymedia.h"
 #include "llfloaternotificationsconsole.h"
 #include "llfloateropenobject.h"
 #include "llfloaterpay.h"
@@ -189,6 +190,8 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);
 	LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
 	LLFloaterReg::add("syswell_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSysWellWindow>);
+
+	LLFloaterReg::add("nearby_media", "floater_nearby_media.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNearbyMedia>);
 	
 	LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
 
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 57a4117d5d561a59f96dab90760b57b5cf21e77c..366e5602bd8696ab0b2e19134aca2193e08db8f9 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -42,7 +42,6 @@
 #include "llconsole.h"
 #include "llinventorymodel.h"
 #include "llnotify.h"
-#include "llimview.h"
 #include "llgesturemgr.h"
 
 #include "llinventorybridge.h"
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index 2dc317e067f9e0cbed7b714c3f740088720b6d1c..8fd646ee932a9a808805f801e0c41d02cc782e09 100644
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -99,7 +99,7 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m
 			gAgent.sendWalkRun(gAgent.getRunning());
 		}
 	}
-	else if (gAllowTapTapHoldRun &&
+	else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") &&
 		 KEYSTATE_DOWN == s &&
 		 !gAgent.getRunning())
 	{
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index b8e945a7b827df1e8d373b5a87469483ef3ad944..55e4f28e75f5c97c9af1d8a3be1842f5bb0ee238 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -48,6 +48,8 @@
 #include "llevent.h"		// LLSimpleListener
 #include "llnotifications.h"
 #include "lluuid.h"
+#include "llkeyboard.h"
+#include "llmutelist.h"
 
 #include <boost/bind.hpp>	// for SkinFolder listener
 #include <boost/signals2.hpp>
@@ -154,10 +156,10 @@ LOG_CLASS(LLMimeDiscoveryResponder);
 	{
 		if(!mInitialized && ! mime_type.empty())
 		{
-			if (mMediaImpl->initializeMedia(mime_type))
+			if(mMediaImpl->initializeMedia(mime_type))
 			{
 				mInitialized = true;
-				mMediaImpl->play();
+				mMediaImpl->loadURI();
 			}
 		}
 	}
@@ -166,10 +168,10 @@ LOG_CLASS(LLMimeDiscoveryResponder);
 		viewer_media_t mMediaImpl;
 		bool mInitialized;
 };
-typedef std::vector<LLViewerMediaImpl*> impl_list;
-static impl_list sViewerMediaImplList;
+static LLViewerMedia::impl_list sViewerMediaImplList;
 static LLTimer sMediaCreateTimer;
 static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;
+static F32 sGlobalVolume = 1.0f;
 
 //////////////////////////////////////////////////////////////////////////////////////////
 static void add_media_impl(LLViewerMediaImpl* media)
@@ -180,8 +182,8 @@ static void add_media_impl(LLViewerMediaImpl* media)
 //////////////////////////////////////////////////////////////////////////////////////////
 static void remove_media_impl(LLViewerMediaImpl* media)
 {
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
+	LLViewerMedia::impl_list::iterator iter = sViewerMediaImplList.begin();
+	LLViewerMedia::impl_list::iterator end = sViewerMediaImplList.end();
 	
 	for(; iter != end; iter++)
 	{
@@ -193,6 +195,15 @@ static void remove_media_impl(LLViewerMediaImpl* media)
 	}
 }
 
+class LLViewerMediaMuteListObserver : public LLMuteListObserver
+{
+	/* virtual */ void onChange()  { LLViewerMedia::muteListChanged();}
+};
+
+static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver;
+static bool sViewerMediaMuteListObserverInitialized = false;
+static bool sInWorldMediaDisabled = false;
+
 
 //////////////////////////////////////////////////////////////////////////////////////////
 // LLViewerMedia
@@ -250,16 +261,12 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
 			media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
 		}
 		
-		if((was_loaded || media_entry->getAutoPlay()) && !update_from_self)
+		if((was_loaded || (media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia"))) && !update_from_self)
 		{
 			if(!media_entry->getCurrentURL().empty())
 			{
 				needs_navigate = (media_entry->getCurrentURL() != previous_url);
 			}
-			else if(!media_entry->getHomeURL().empty())
-			{
-				needs_navigate = (media_entry->getHomeURL() != previous_url);
-			}
 		}
 	}
 	else
@@ -273,7 +280,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
 		
 		media_impl->setHomeURL(media_entry->getHomeURL());
 		
-		if(media_entry->getAutoPlay())
+		if(media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia"))
 		{
 			needs_navigate = true;
 		}
@@ -282,8 +289,6 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
 	if(media_impl && needs_navigate)
 	{
 		std::string url = media_entry->getCurrentURL();
-		if(url.empty())
-			url = media_entry->getHomeURL();
 			
 		media_impl->navigateTo(url, "", true, true);
 	}
@@ -387,20 +392,75 @@ bool LLViewerMedia::textureHasMedia(const LLUUID& texture_id)
 // static
 void LLViewerMedia::setVolume(F32 volume)
 {
+	if(volume != sGlobalVolume)
+	{
+		sGlobalVolume = volume;
+		impl_list::iterator iter = sViewerMediaImplList.begin();
+		impl_list::iterator end = sViewerMediaImplList.end();
+
+		for(; iter != end; iter++)
+		{
+			LLViewerMediaImpl* pimpl = *iter;
+			pimpl->updateVolume();
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+F32 LLViewerMedia::getVolume()
+{
+	return sGlobalVolume;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::muteListChanged()
+{
+	// When the mute list changes, we need to check mute status on all impls.
 	impl_list::iterator iter = sViewerMediaImplList.begin();
 	impl_list::iterator end = sViewerMediaImplList.end();
 
 	for(; iter != end; iter++)
 	{
 		LLViewerMediaImpl* pimpl = *iter;
-		pimpl->setVolume(volume);
+		pimpl->mNeedsMuteCheck = true;
 	}
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setInWorldMediaDisabled(bool disabled)
+{
+	sInWorldMediaDisabled = disabled;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::getInWorldMediaDisabled()
+{
+	return sInWorldMediaDisabled;
+}
+
+LLViewerMedia::impl_list &LLViewerMedia::getPriorityList()
+{
+	return sViewerMediaImplList;
+}
+
 // This is the predicate function used to sort sViewerMediaImplList by priority.
-static inline bool compare_impl_interest(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
+bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
 {
-	if(i1->hasFocus())
+	if(i1->isForcedUnloaded())
+	{
+		// Muted or failed items always go to the end of the list, period.
+		return false;
+	}
+	else if(i2->isForcedUnloaded())
+	{
+		// Muted or failed items always go to the end of the list, period.
+		return true;
+	}
+	else if(i1->hasFocus())
 	{
 		// The item with user focus always comes to the front of the list, period.
 		return true;
@@ -442,7 +502,7 @@ void LLViewerMedia::updateMedia()
 	}
 		
 	// Sort the static instance list using our interest criteria
-	std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), compare_impl_interest);
+	std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), priorityComparitor);
 
 	// Go through the list again and adjust according to priority.
 	iter = sViewerMediaImplList.begin();
@@ -452,6 +512,7 @@ void LLViewerMedia::updateMedia()
 	int impl_count_total = 0;
 	int impl_count_interest_low = 0;
 	int impl_count_interest_normal = 0;
+	int i = 0;
 
 #if 0	
 	LL_DEBUGS("PluginPriority") << "Sorted impls:" << llendl;
@@ -474,8 +535,9 @@ void LLViewerMedia::updateMedia()
 		
 		LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
 
-		if(impl_count_total > (int)max_instances)
+		if(pimpl->isForcedUnloaded() || (impl_count_total > (int)max_instances))
 		{
+			// Never load muted or failed impls.
 			// Hard limit on the number of instances that will be loaded at one time
 			new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
 		}
@@ -535,7 +597,23 @@ void LLViewerMedia::updateMedia()
 			}
 		}
 		
+		if(new_priority != LLPluginClassMedia::PRIORITY_UNLOADED)
+		{
+			impl_count_total++;
+		}
+		
 		pimpl->setPriority(new_priority);
+		
+		if(pimpl->getUsedInUI())
+		{
+			// Any impls used in the UI should not be in the proximity list.
+			pimpl->mProximity = -1;
+		}
+		else
+		{
+			// Other impls just get the same ordering as the priority list (for now).
+			pimpl->mProximity = i;
+		}
 
 #if 0		
 		LL_DEBUGS("PluginPriority") << "    " << pimpl 
@@ -548,7 +626,8 @@ void LLViewerMedia::updateMedia()
 #endif
 
 		total_cpu += pimpl->getCPUUsage();
-		impl_count_total++;
+		
+		i++;
 	}
 	
 	LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl;
@@ -587,10 +666,25 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 	mUsedInUI(false),
 	mHasFocus(false),
 	mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
-	mDoNavigateOnLoad(false),
-	mDoNavigateOnLoadServerRequest(false),
+	mNavigateRediscoverType(false),
+	mNavigateServerRequest(false),
+	mMediaSourceFailed(false),
+	mRequestedVolume(1.0f),
+	mIsMuted(false),
+	mNeedsMuteCheck(false),
+	mPreviousMediaState(MEDIA_NONE),
+	mPreviousMediaTime(0.0f),
+	mIsDisabled(false),
+	mProximity(-1),
 	mIsUpdated(false)
 { 
+
+	// Set up the mute list observer if it hasn't been set up already.
+	if(!sViewerMediaMuteListObserverInitialized)
+	{
+		LLMuteList::getInstance()->addObserver(&sViewerMediaMuteListObserver);
+		sViewerMediaMuteListObserverInitialized = true;
+	}
 	
 	add_media_impl(this);
 	
@@ -638,16 +732,20 @@ void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObser
 //////////////////////////////////////////////////////////////////////////////////////////
 bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
 {
-	if((mMediaSource == NULL) || (mMimeType != mime_type))
+	bool mimeTypeChanged = (mMimeType != mime_type);
+	bool pluginChanged = (LLMIMETypes::implType(mMimeType) != LLMIMETypes::implType(mime_type));
+	
+	if(!mMediaSource || pluginChanged)
 	{
-		if(! initializePlugin(mime_type))
-		{
-			// This may be the case where the plugin's priority is PRIORITY_UNLOADED
-			return false;
-		}
+		// We don't have a plugin at all, or the new mime type is handled by a different plugin than the old mime type.
+		(void)initializePlugin(mime_type);
+	}
+	else if(mimeTypeChanged)
+	{
+		// The same plugin should be able to handle the new media -- just update the stored mime type.
+		mMimeType = mime_type;
 	}
 
-	// play();
 	return (mMediaSource != NULL);
 }
 
@@ -660,16 +758,13 @@ void LLViewerMediaImpl::createMediaSource()
 		return;
 	}
 	
-	if(mDoNavigateOnLoad)
+	if(! mMediaURL.empty())
 	{
-		if(! mMediaURL.empty())
-		{
-			navigateTo(mMediaURL, mMimeType, false, mDoNavigateOnLoadServerRequest);
-		}
-		else if(! mMimeType.empty())
-		{
-			initializeMedia(mMimeType);
-		}
+		navigateInternal();
+	}
+	else if(! mMimeType.empty())
+	{
+		initializeMedia(mMimeType);
 	}
 }
 
@@ -703,7 +798,7 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type)
 LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height)
 {
 	std::string plugin_basename = LLMIMETypes::implType(media_type);
-
+	
 	if(plugin_basename.empty())
 	{
 		LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
@@ -774,6 +869,9 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
 		return false;
 	}
 
+	// If we got here, we want to ignore previous init failures.
+	mMediaSourceFailed = false;
+
 	LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight);
 	
 	if (media_source)
@@ -782,14 +880,61 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
 		media_source->setLoop(mMediaLoop);
 		media_source->setAutoScale(mMediaAutoScale);
 		media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent());
+		media_source->focus(mHasFocus);
 		
 		mMediaSource = media_source;
+
+		updateVolume();
+
 		return true;
 	}
 
+	// Make sure the timer doesn't try re-initing this plugin repeatedly until something else changes.
+	mMediaSourceFailed = true;
+
 	return false;
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::loadURI()
+{
+	if(mMediaSource)
+	{
+		mMediaSource->loadURI( mMediaURL );
+
+		if(mPreviousMediaState == MEDIA_PLAYING)
+		{
+			// This media was playing before this instance was unloaded.
+
+			if(mPreviousMediaTime != 0.0f)
+			{
+				// Seek back to where we left off, if possible.
+				seek(mPreviousMediaTime);
+			}
+			
+			start();
+		}
+		else if(mPreviousMediaState == MEDIA_PAUSED)
+		{
+			// This media was paused before this instance was unloaded.
+
+			if(mPreviousMediaTime != 0.0f)
+			{
+				// Seek back to where we left off, if possible.
+				seek(mPreviousMediaTime);
+			}
+			
+			pause();
+		}
+		else
+		{
+			// No relevant previous media play state -- if we're loading the URL, we want to start playing.
+			start();
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::setSize(int width, int height)
 {
 	mMediaWidth = width;
@@ -803,24 +948,21 @@ void LLViewerMediaImpl::setSize(int width, int height)
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::play()
 {
-	// first stop any previously playing media
-	// stop();
-
-	// mMediaSource->addObserver( this );
+	// If the media source isn't there, try to initialize it and load an URL.
 	if(mMediaSource == NULL)
 	{
-	 	if(!initializePlugin(mMimeType))
+	 	if(!initializeMedia(mMimeType))
 		{
 			// This may be the case where the plugin's priority is PRIORITY_UNLOADED
 			return;
 		}
+		
+		// Only do this if the media source was just loaded.
+		loadURI();
 	}
 	
-	mMediaSource->loadURI( mMediaURL );
-	if(/*mMediaSource->pluginSupportsMediaTime()*/ true)
-	{
-		start();
-	}
+	// always start the media
+	start();
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -828,7 +970,15 @@ void LLViewerMediaImpl::stop()
 {
 	if(mMediaSource)
 	{
-		mMediaSource->stop();
+		if(mMediaSource->pluginSupportsMediaBrowser())
+		{
+			mMediaSource->browse_stop();
+		}
+		else
+		{
+			mMediaSource->stop();
+		}
+
 		// destroyMediaSource();
 	}
 }
@@ -862,13 +1012,26 @@ void LLViewerMediaImpl::seek(F32 time)
 
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::setVolume(F32 volume)
+{
+	mRequestedVolume = volume;
+	updateVolume();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::updateVolume()
 {
 	if(mMediaSource)
 	{
-		mMediaSource->setVolume(volume);
+		mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume());
 	}
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+F32 LLViewerMediaImpl::getVolume()
+{
+	return mRequestedVolume;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::focus(bool focus)
 {
@@ -895,8 +1058,18 @@ bool LLViewerMediaImpl::hasFocus() const
 	return mHasFocus;
 }
 
+std::string LLViewerMediaImpl::getCurrentMediaURL()
+{
+	if(!mCurrentMediaURL.empty())
+	{
+		return mCurrentMediaURL;
+	}
+	
+	return mMediaURL;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseDown(S32 x, S32 y)
+void LLViewerMediaImpl::mouseDown(S32 x, S32 y, MASK mask, S32 button)
 {
 	scaleMouse(&x, &y);
 	mLastMouseX = x;
@@ -904,12 +1077,12 @@ void LLViewerMediaImpl::mouseDown(S32 x, S32 y)
 //	llinfos << "mouse down (" << x << ", " << y << ")" << llendl;
 	if (mMediaSource)
 	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, x, y, 0);
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, button, x, y, mask);
 	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseUp(S32 x, S32 y)
+void LLViewerMediaImpl::mouseUp(S32 x, S32 y, MASK mask, S32 button)
 {
 	scaleMouse(&x, &y);
 	mLastMouseX = x;
@@ -917,12 +1090,12 @@ void LLViewerMediaImpl::mouseUp(S32 x, S32 y)
 //	llinfos << "mouse up (" << x << ", " << y << ")" << llendl;
 	if (mMediaSource)
 	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, x, y, 0);
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, button, x, y, mask);
 	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseMove(S32 x, S32 y)
+void LLViewerMediaImpl::mouseMove(S32 x, S32 y, MASK mask)
 {
     scaleMouse(&x, &y);
 	mLastMouseX = x;
@@ -930,50 +1103,65 @@ void LLViewerMediaImpl::mouseMove(S32 x, S32 y)
 //	llinfos << "mouse move (" << x << ", " << y << ")" << llendl;
 	if (mMediaSource)
 	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, x, y, 0);
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, x, y, mask);
 	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords)
+void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords, MASK mask, S32 button)
 {
 	if(mMediaSource)
 	{		
 		mouseDown(
 			llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
-			llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+			llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()),
+			mask, button);
 	}
 }
 
-void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords)
+void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords, MASK mask, S32 button)
 {
 	if(mMediaSource)
 	{		
 		mouseUp(
 			llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
-			llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+			llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()),
+			mask, button);
 	}
 }
 
-void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords)
+void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask)
 {
 	if(mMediaSource)
 	{		
 		mouseMove(
 			llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
-			llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+			llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()),
+			mask);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
+{
+	scaleMouse(&x, &y);
+	mLastMouseX = x;
+	mLastMouseY = y;
+	if (mMediaSource)
+	{
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, button, x, y, mask);
 	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y)
+void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask)
 {
 	scaleMouse(&x, &y);
 	mLastMouseX = x;
 	mLastMouseY = y;
 	if (mMediaSource)
 	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, x, y, 0);
+		mMediaSource->scrollEvent(x, y, mask);
 	}
 }
 
@@ -982,7 +1170,7 @@ void LLViewerMediaImpl::onMouseCaptureLost()
 {
 	if (mMediaSource)
 	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, mLastMouseX, mLastMouseY, 0);
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 0, mLastMouseX, mLastMouseY, 0);
 	}
 }
 
@@ -1002,48 +1190,144 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateHome()
-{
-	mMediaURL = mHomeURL;
-	mDoNavigateOnLoad = !mMediaURL.empty();
-	mDoNavigateOnLoadServerRequest = false;
+std::string LLViewerMediaImpl::getName() const 
+{ 
+	if (mMediaSource)
+	{
+		return mMediaSource->getMediaName();
+	}
 	
-	if(mMediaSource)
+	return LLStringUtil::null; 
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateBack()
+{
+	if (mMediaSource)
 	{
-		mMediaSource->loadURI( mHomeURL );
+		if(mMediaSource->pluginSupportsMediaTime())
+		{
+			F64 step_scale = 0.02; // temp , can be changed
+			F64 back_step = mMediaSource->getCurrentTime() - (mMediaSource->getDuration()*step_scale);
+			if(back_step < 0.0)
+			{
+				back_step = 0.0;
+			}
+			mMediaSource->seek(back_step);
+			//mMediaSource->start(-2.0);
+		}
+		else
+		{
+			mMediaSource->browse_back();
+		}
 	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type,  bool rediscover_type, bool server_request)
+void LLViewerMediaImpl::navigateForward()
 {
-	if(server_request)
+	if (mMediaSource)
 	{
-		setNavState(MEDIANAVSTATE_SERVER_SENT);
+		if(mMediaSource->pluginSupportsMediaTime())
+		{
+			F64 step_scale = 0.02; // temp , can be changed
+			F64 forward_step = mMediaSource->getCurrentTime() + (mMediaSource->getDuration()*step_scale);
+			if(forward_step > mMediaSource->getDuration())
+			{
+				forward_step = mMediaSource->getDuration();
+			}
+			mMediaSource->seek(forward_step);
+			//mMediaSource->start(2.0);
+		}
+		else
+		{
+			mMediaSource->browse_forward();
+		}
 	}
-	else
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateReload()
+{
+	navigateTo(getCurrentMediaURL(), "", true, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateHome()
+{
+	navigateTo(mHomeURL, "", true, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type,  bool rediscover_type, bool server_request)
+{
+	if(mMediaURL != url)
 	{
-		setNavState(MEDIANAVSTATE_NONE);
+		// Don't carry media play state across distinct URLs.
+		resetPreviousMediaState();
 	}
 	
-	// Always set the current URL.
+	// Always set the current URL and MIME type.
 	mMediaURL = url;
+	mMimeType = mime_type;
+	
+	// Clear the current media URL, since it will no longer be correct.
+	mCurrentMediaURL.clear();
+	
+	// if mime type discovery was requested, we'll need to do it when the media loads
+	mNavigateRediscoverType = rediscover_type;
 	
-	// If the current URL is not null, make the instance do a navigate on load.
-	mDoNavigateOnLoad = !mMediaURL.empty();
-
 	// and if this was a server request, the navigate on load will also need to be one.
-	mDoNavigateOnLoadServerRequest = server_request;
+	mNavigateServerRequest = server_request;
+	
+	// An explicit navigate resets the "failed" flag.
+	mMediaSourceFailed = false;
 
 	if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
 	{
+		// Helpful to have media urls in log file. Shouldn't be spammy.
+		llinfos << "NOT LOADING media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
+
 		// This impl should not be loaded at this time.
 		LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
 		
 		return;
 	}
 
-	if(rediscover_type)
+	navigateInternal();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateInternal()
+{
+	// Helpful to have media urls in log file. Shouldn't be spammy.
+	llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl;
+
+	if(mNavigateServerRequest)
+	{
+		setNavState(MEDIANAVSTATE_SERVER_SENT);
+	}
+	else
+	{
+		setNavState(MEDIANAVSTATE_NONE);
+	}
+			
+	// If the caller has specified a non-empty MIME type, look that up in our MIME types list.
+	// If we have a plugin for that MIME type, use that instead of attempting auto-discovery.
+	// This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type
+	// but the parcel owner has correctly set the MIME type in the parcel media settings.
+	
+	if(!mMimeType.empty() && (mMimeType != "none/none"))
+	{
+		std::string plugin_basename = LLMIMETypes::implType(mMimeType);
+		if(!plugin_basename.empty())
+		{
+			// We have a plugin for this mime type
+			mNavigateRediscoverType = false;
+		}
+	}
+
+	if(mNavigateRediscoverType)
 	{
 
 		LLURI uri(mMediaURL);
@@ -1059,7 +1343,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
 			// We use "data" internally for a text/html url for loading the login screen
 			if(initializeMedia("text/html"))
 			{
-				mMediaSource->loadURI( mMediaURL );
+				loadURI();
 			}
 		}
 		else
@@ -1067,24 +1351,18 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
 			// This catches 'rtsp://' urls
 			if(initializeMedia(scheme))
 			{
-				mMediaSource->loadURI( mMediaURL );
+				loadURI();
 			}
 		}
 	}
-	else if (mMediaSource)
+	else if(initializeMedia(mMimeType))
 	{
-		mMediaSource->loadURI( mMediaURL );
-	}
-	else if(initializeMedia(mime_type) && mMediaSource)
-	{
-		mMediaSource->loadURI( mMediaURL );
+		loadURI();
 	}
 	else
 	{
-		LL_WARNS("Media") << "Couldn't navigate to: " << url << " as there is no media type for: " << mime_type << LL_ENDL;
-		return;
+		LL_WARNS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL;
 	}
-
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1101,10 +1379,43 @@ void LLViewerMediaImpl::navigateStop()
 bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
 {
 	bool result = false;
+	// *NOTE:Mani - if this doesn't exist llmozlib goes crashy in the debug build.
+	// LLMozlib::init wants to write some files to <exe_dir>/components
+	std::string debug_init_component_dir( gDirUtilp->getExecutableDir() );
+	debug_init_component_dir += "/components";
+	LLAPRFile::makeDir(debug_init_component_dir.c_str()); 
 	
 	if (mMediaSource)
 	{
-		result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask);
+		// FIXME: THIS IS SO WRONG.
+		// Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it...
+		if( MASK_CONTROL & mask )
+		{
+			if( 'C' == key )
+			{
+				mMediaSource->copy();
+				result = true;
+			}
+			else
+			if( 'V' == key )
+			{
+				mMediaSource->paste();
+				result = true;
+			}
+			else
+			if( 'X' == key )
+			{
+				mMediaSource->cut();
+				result = true;
+			}
+		}
+		
+		if(!result)
+		{
+			result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask);
+			// Since the viewer internal event dispatching doesn't give us key-up events, simulate one here.
+			(void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask);
+		}
 	}
 	
 	return result;
@@ -1117,7 +1428,12 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char)
 	
 	if (mMediaSource)
 	{
-		mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)));
+		// only accept 'printable' characters, sigh...
+		if (uni_char >= 32 // discard 'control' characters
+			&& uni_char != 127) // SDL thinks this is 'delete' - yuck.
+		{
+			mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE));
+		}
 	}
 	
 	return result;
@@ -1175,6 +1491,7 @@ void LLViewerMediaImpl::update()
 	
 	if(mMediaSource->isPluginExited())
 	{
+		resetPreviousMediaState();
 		destroyMediaSource();
 		return;
 	}
@@ -1291,7 +1608,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
 
 
 //////////////////////////////////////////////////////////////////////////////////////////
-LLUUID LLViewerMediaImpl::getMediaTextureID()
+LLUUID LLViewerMediaImpl::getMediaTextureID() const
 {
 	return mTextureId;
 }
@@ -1370,13 +1687,64 @@ bool LLViewerMediaImpl::hasMedia()
 	return mMediaSource != NULL;
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaImpl::resetPreviousMediaState()
+{
+	mPreviousMediaState = MEDIA_NONE;
+	mPreviousMediaTime = 0.0f;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isForcedUnloaded() const
+{
+	if(mIsMuted || mMediaSourceFailed || mIsDisabled)
+	{
+		return true;
+	}
+	
+	if(sInWorldMediaDisabled)
+	{
+		// When inworld media is disabled, all instances that aren't marked as "used in UI" will not be loaded.
+		if(!mUsedInUI)
+		{
+			return true;
+		}
+	}
+	
+	return false;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event)
 {
 	switch(event)
 	{
+		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+		{
+			// The plugin failed to load properly.  Make sure the timer doesn't retry.
+			// TODO: maybe mark this plugin as not loadable somehow?
+			mMediaSourceFailed = true;
+
+			// Reset the last known state of the media to defaults.
+			resetPreviousMediaState();
+			
+			// TODO: may want a different message for this case?
+			LLSD args;
+			args["PLUGIN"] = LLMIMETypes::implType(mMimeType);
+			LLNotifications::instance().add("MediaPluginFailed", args);
+		}
+		break;
+
 		case MEDIA_EVENT_PLUGIN_FAILED:
 		{
+			// The plugin crashed.
+			mMediaSourceFailed = true;
+
+			// Reset the last known state of the media to defaults.
+			resetPreviousMediaState();
+
 			LLSD args;
 			args["PLUGIN"] = LLMIMETypes::implType(mMimeType);
 			// SJB: This is getting called every frame if the plugin fails to load, continuously respawining the alert!
@@ -1423,7 +1791,21 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
 		case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
 		{
 			LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL;
-			setNavState(MEDIANAVSTATE_NONE);
+
+			if(getNavState() == MEDIANAVSTATE_BEGUN)
+			{
+				mCurrentMediaURL = plugin->getNavigateURI();
+				setNavState(MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED);
+			}
+			else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
+			{
+				mCurrentMediaURL = plugin->getNavigateURI();
+				setNavState(MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED);
+			}
+			else
+			{
+				// all other cases need to leave the state alone.
+			}
 		}
 		break;
 		
@@ -1433,10 +1815,12 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
 
 			if(getNavState() == MEDIANAVSTATE_BEGUN)
 			{
+				mCurrentMediaURL = plugin->getLocation();
 				setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED);
 			}
 			else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
 			{
+				mCurrentMediaURL = plugin->getLocation();
 				setNavState(MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED);
 			}
 			else
@@ -1536,10 +1920,35 @@ void LLViewerMediaImpl::calculateInterest()
 	}
 	else
 	{
-		// I don't think this case should ever be hit.
-		LL_WARNS("Plugin") << "no texture!" << LL_ENDL;
+		// This will be a relatively common case now, since it will always be true for unloaded media.
 		mInterest = 0.0f;
 	}
+	
+	if(mNeedsMuteCheck)
+	{
+		// Check all objects this instance is associated with, and those objects' owners, against the mute list
+		mIsMuted = false;
+		
+		std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+		for(; iter != mObjectList.end() ; ++iter)
+		{
+			LLVOVolume *obj = *iter;
+			if(LLMuteList::getInstance()->isMuted(obj->getID()))
+				mIsMuted = true;
+			else
+			{
+				// We won't have full permissions data for all objects.  Attempt to mute objects when we can tell their owners are muted.
+				LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(obj);
+				if(obj_perm)
+				{
+					if(LLMuteList::getInstance()->isMuted(obj_perm->getOwner()))
+						mIsMuted = true;
+				}
+			}
+		}
+		
+		mNeedsMuteCheck = false;
+	}
 }
 
 F64 LLViewerMediaImpl::getApproximateTextureInterest()
@@ -1565,11 +1974,11 @@ void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
 	{
 		if(getVisible())
 		{
-			mPriority = LLPluginClassMedia::PRIORITY_NORMAL;
+			setPriority(LLPluginClassMedia::PRIORITY_NORMAL);
 		}
 		else
 		{
-			mPriority = LLPluginClassMedia::PRIORITY_HIDDEN;
+			setPriority(LLPluginClassMedia::PRIORITY_HIDDEN);
 		}
 
 		createMediaSource();
@@ -1590,6 +1999,15 @@ F64 LLViewerMediaImpl::getCPUUsage() const
 
 void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
 {
+	if(mPriority != priority)
+	{
+		LL_INFOS("PluginPriority")
+			<< "changing priority of media id " << mTextureId
+			<< " from " << LLPluginClassMedia::priorityToString(mPriority)
+			<< " to " << LLPluginClassMedia::priorityToString(priority)
+			<< LL_ENDL;
+	}
+	
 	mPriority = priority;
 	
 	if(priority == LLPluginClassMedia::PRIORITY_UNLOADED)
@@ -1597,6 +2015,11 @@ void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
 		if(mMediaSource)
 		{
 			// Need to unload the media source
+			
+			// First, save off previous media state
+			mPreviousMediaState = mMediaSource->getStatus();
+			mPreviousMediaTime = mMediaSource->getCurrentTime();
+			
 			destroyMediaSource();
 		}
 	}
@@ -1626,9 +2049,11 @@ void LLViewerMediaImpl::setNavState(EMediaNavState state)
 		case MEDIANAVSTATE_NONE: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_NONE" << llendl; break;
 		case MEDIANAVSTATE_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_BEGUN" << llendl; break;
 		case MEDIANAVSTATE_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED" << llendl; break;
+		case MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
 		case MEDIANAVSTATE_SERVER_SENT: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_SENT" << llendl; break;
 		case MEDIANAVSTATE_SERVER_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_BEGUN" << llendl; break;
 		case MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED" << llendl; break;
+		case MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
 	}
 }
 
@@ -1645,11 +2070,13 @@ void LLViewerMediaImpl::addObject(LLVOVolume* obj)
 	}
 
 	mObjectList.push_back(obj) ;
+	mNeedsMuteCheck = true;
 }
 	
 void LLViewerMediaImpl::removeObject(LLVOVolume* obj) 
 {
 	mObjectList.remove(obj) ;	
+	mNeedsMuteCheck = true;
 }
 	
 const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const 
@@ -1657,6 +2084,19 @@ const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const
 	return &mObjectList ;
 }
 
+LLVOVolume *LLViewerMediaImpl::getSomeObject()
+{
+	LLVOVolume *result = NULL;
+	
+	std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+	if(iter != mObjectList.end())
+	{
+		result = *iter;
+	}
+	
+	return result;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 //static
 void LLViewerMedia::toggleMusicPlay(void*)
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index c9ba5841e9391368ce150202265b588787e75ee8..517a76ce3dd6aa4c9b06677a19c25ce48d4bba6c 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -66,10 +66,15 @@ class LLViewerMediaEventEmitter
 	observerListType mObservers;
 };
 
+class LLViewerMediaImpl;
+
 class LLViewerMedia
 {
 	LOG_CLASS(LLViewerMedia);
 	public:
+
+		typedef std::vector<LLViewerMediaImpl*> impl_list;
+
 		// Special case early init for just web browser component
 		// so we can show login screen.  See .cpp file for details. JC
 
@@ -95,6 +100,16 @@ class LLViewerMedia
 		static void toggleMusicPlay(void*);
 		static void toggleMediaPlay(void*);
 		static void mediaStop(void*);
+		static F32 getVolume();	
+		static void muteListChanged();
+		static void setInWorldMediaDisabled(bool disabled);
+		static bool getInWorldMediaDisabled();
+				
+		// Returns the priority-sorted list of all media impls.
+		static impl_list &getPriorityList();
+		
+		// This is the comparitor used to sort the list.
+		static bool priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2);
 };
 
 // Implementation functions not exported into header file
@@ -121,6 +136,7 @@ class LLViewerMediaImpl
 	void setMediaType(const std::string& media_type);
 	bool initializeMedia(const std::string& mime_type);
 	bool initializePlugin(const std::string& media_type);
+	void loadURI();
 	LLPluginClassMedia* getMediaPlugin() { return mMediaSource; }
 	void setSize(int width, int height);
 
@@ -130,26 +146,34 @@ class LLViewerMediaImpl
 	void start();
 	void seek(F32 time);
 	void setVolume(F32 volume);
+	void updateVolume();
+	F32 getVolume();
 	void focus(bool focus);
 	// True if the impl has user focus.
 	bool hasFocus() const;
-	void mouseDown(S32 x, S32 y);
-	void mouseUp(S32 x, S32 y);
-	void mouseMove(S32 x, S32 y);
-	void mouseDown(const LLVector2& texture_coords);
-	void mouseUp(const LLVector2& texture_coords);
-	void mouseMove(const LLVector2& texture_coords);
-	void mouseLeftDoubleClick(S32 x,S32 y );
+	void mouseDown(S32 x, S32 y, MASK mask, S32 button = 0);
+	void mouseUp(S32 x, S32 y, MASK mask, S32 button = 0);
+	void mouseMove(S32 x, S32 y, MASK mask);
+	void mouseDown(const LLVector2& texture_coords, MASK mask, S32 button = 0);
+	void mouseUp(const LLVector2& texture_coords, MASK mask, S32 button = 0);
+	void mouseMove(const LLVector2& texture_coords, MASK mask);
+	void mouseDoubleClick(S32 x,S32 y, MASK mask, S32 button = 0);
+	void scrollWheel(S32 x, S32 y, MASK mask);
 	void mouseCapture();
-
+	
+	void navigateBack();
+	void navigateForward();
+	void navigateReload();
 	void navigateHome();
 	void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false);
+	void navigateInternal();
 	void navigateStop();
 	bool handleKeyHere(KEY key, MASK mask);
 	bool handleUnicodeCharHere(llwchar uni_char);
 	bool canNavigateForward();
 	bool canNavigateBack();
-	std::string getMediaURL() { return mMediaURL; }
+	std::string getMediaURL() const { return mMediaURL; }
+	std::string getCurrentMediaURL();
 	std::string getHomeURL() { return mHomeURL; }
     void setHomeURL(const std::string& home_url) { mHomeURL = home_url; };
 	std::string getMimeType() { return mMimeType; }
@@ -157,7 +181,7 @@ class LLViewerMediaImpl
 
 	void update();
 	void updateImagesMediaStreams();
-	LLUUID getMediaTextureID();
+	LLUUID getMediaTextureID() const;
 	
 	void suspendUpdates(bool suspend) { mSuspendUpdates = suspend; };
 	void setVisible(bool visible);
@@ -166,6 +190,14 @@ class LLViewerMediaImpl
 	bool isMediaPlaying();
 	bool isMediaPaused();
 	bool hasMedia();
+	bool isMediaFailed() { return mMediaSourceFailed; };
+	void resetPreviousMediaState();
+	
+	void setDisabled(bool disabled) { mIsDisabled = disabled; };
+	bool isMediaDisabled() { return mIsDisabled; };
+
+	// returns true if this instance should not be loaded (disabled, muted object, crashed, etc.)
+	bool isForcedUnloaded() const;
 
 	ECursorType getLastSetCursor() { return mLastSetCursor; };
 	
@@ -196,7 +228,7 @@ class LLViewerMediaImpl
 	/*virtual*/ BOOL	handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; };
 	/*virtual*/ BOOL	handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
 	/*virtual*/ BOOL	handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; };
-	/*virtual*/ std::string getName() const { return LLStringUtil::null; };
+	/*virtual*/ std::string getName() const;
 
 	/*virtual*/ void	screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {};
 	/*virtual*/ void	localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {};
@@ -218,6 +250,7 @@ class LLViewerMediaImpl
 	void addObject(LLVOVolume* obj) ;
 	void removeObject(LLVOVolume* obj) ;
 	const std::list< LLVOVolume* >* getObjectList() const ;
+	LLVOVolume *getSomeObject();
 	void setUpdated(BOOL updated) ;
 	BOOL isUpdated() ;
 	
@@ -225,6 +258,7 @@ class LLViewerMediaImpl
 	void calculateInterest();
 	F64 getInterest() const { return mInterest; };
 	F64 getApproximateTextureInterest();
+	S32 getProximity() { return mProximity; };
 	
 	// Mark this object as being used in a UI panel instead of on a prim
 	// This will be used as part of the interest sorting algorithm.
@@ -240,12 +274,14 @@ class LLViewerMediaImpl
 	
 	typedef enum 
 	{
-		MEDIANAVSTATE_NONE,								// State is outside what we need to track for navigation.
-		MEDIANAVSTATE_BEGUN,							// a MEDIA_EVENT_NAVIGATE_BEGIN has been received which was not server-directed
-		MEDIANAVSTATE_FIRST_LOCATION_CHANGED,			// first LOCATION_CHANGED event after a non-server-directed BEGIN
-		MEDIANAVSTATE_SERVER_SENT,						// server-directed nav has been requested, but MEDIA_EVENT_NAVIGATE_BEGIN hasn't been received yet
-		MEDIANAVSTATE_SERVER_BEGUN,						// MEDIA_EVENT_NAVIGATE_BEGIN has been received which was server-directed
-		MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED		// first LOCATION_CHANGED event after a server-directed BEGIN
+		MEDIANAVSTATE_NONE,										// State is outside what we need to track for navigation.
+		MEDIANAVSTATE_BEGUN,									// a MEDIA_EVENT_NAVIGATE_BEGIN has been received which was not server-directed
+		MEDIANAVSTATE_FIRST_LOCATION_CHANGED,					// first LOCATION_CHANGED event after a non-server-directed BEGIN
+		MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED,			// we received a NAVIGATE_COMPLETE event before the first LOCATION_CHANGED
+		MEDIANAVSTATE_SERVER_SENT,								// server-directed nav has been requested, but MEDIA_EVENT_NAVIGATE_BEGIN hasn't been received yet
+		MEDIANAVSTATE_SERVER_BEGUN,								// MEDIA_EVENT_NAVIGATE_BEGIN has been received which was server-directed
+		MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED,			// first LOCATION_CHANGED event after a server-directed BEGIN
+		MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED	// we received a NAVIGATE_COMPLETE event before the first LOCATION_CHANGED
 		
 	}EMediaNavState;
     
@@ -259,9 +295,10 @@ class LLViewerMediaImpl
 	LLPluginClassMedia* mMediaSource;
 	LLUUID mTextureId;
 	bool  mMovieImageHasMips;
-	std::string mMediaURL;
+	std::string mMediaURL;			// The last media url set with NavigateTo
 	std::string mHomeURL;
 	std::string mMimeType;
+	std::string mCurrentMediaURL;	// The most current media url from the plugin (via the "location changed" or "navigate complete" events).
 	S32 mLastMouseX;	// save the last mouse coord we get, so when we lose capture we can simulate a mouseup at that point.
 	S32 mLastMouseY;
 	S32 mMediaWidth;
@@ -277,9 +314,16 @@ class LLViewerMediaImpl
 	bool mUsedInUI;
 	bool mHasFocus;
 	LLPluginClassMedia::EPriority mPriority;
-	bool mDoNavigateOnLoad;
-	bool mDoNavigateOnLoadServerRequest;
-
+	bool mNavigateRediscoverType;
+	bool mNavigateServerRequest;
+	bool mMediaSourceFailed;
+	F32 mRequestedVolume;
+	bool mIsMuted;
+	bool mNeedsMuteCheck;
+	int mPreviousMediaState;
+	F64 mPreviousMediaTime;
+	bool mIsDisabled;
+	S32 mProximity;
 
 private:
 	BOOL mIsUpdated ;
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index f9377ab37bb821f6e06b0d07c88cbbf3fb51d5b2..2f7040aaa30b19ccb054c2e70e3019cf2c7299aa 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -35,7 +35,7 @@
 
 //LLViewerMediaFocus
 #include "llviewerobjectlist.h"
-#include "llpanelmediahud.h"
+#include "llpanelprimmediacontrols.h"
 #include "llpluginclassmedia.h"
 #include "llagent.h"
 #include "lltoolpie.h"
@@ -48,12 +48,17 @@
 #include "llviewerparcelmgr.h"
 #include "llweb.h"
 #include "llmediaentry.h"
+#include "llkeyboard.h"
+#include "lltoolmgr.h"
+#include "llvovolume.h"
+
 //
 // LLViewerMediaFocus
 //
 
 LLViewerMediaFocus::LLViewerMediaFocus()
-: mMouseOverFlag(false)
+:	mFocusedObjectFace(0),
+	mHoverObjectFace(0)
 {
 }
 
@@ -63,110 +68,103 @@ LLViewerMediaFocus::~LLViewerMediaFocus()
 	// Clean up in cleanupClass() instead.
 }
 
-void LLViewerMediaFocus::cleanupClass()
-{
-	LLViewerMediaFocus *self = LLViewerMediaFocus::getInstance();
-	
-	if(self)
-	{
-		// mMediaHUD will have been deleted by this point -- don't try to delete it.
-
-		/* Richard says:
-			all widgets are supposed to be destroyed at the same time
-			you shouldn't hold on to pointer to them outside of ui code		
-			you can use the LLHandle approach
-			if you want to be type safe, you'll need to add a LLRootHandle to whatever derived class you are pointing to
-			look at llview::gethandle
-			its our version of a weak pointer			
-		*/
-		if(self->mMediaHUD.get())
-		{
-			self->mMediaHUD.get()->setMediaImpl(NULL);
-		}
-		self->mMediaImpl = NULL;
-	}
-	
-}
-
-
-void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl )
-{
+void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{	
 	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-
-	if(mMediaImpl.notNull())
+	
+	LLViewerMediaImpl *old_media_impl = getFocusedMediaImpl();
+	if(old_media_impl)
 	{
-		mMediaImpl->focus(false);
+		old_media_impl->focus(false);
 	}
 
-	if (b && media_impl.notNull())
+	if (media_impl.notNull() && objectp.notNull())
 	{
 		bool face_auto_zoom = false;
-		mMediaImpl = media_impl;
-		mMediaImpl->focus(true);
 
-		LLSelectMgr::getInstance()->deselectAll();
-		LLSelectMgr::getInstance()->selectObjectOnly(objectp, face);
+		mFocusedImplID = media_impl->getMediaTextureID();
+		mFocusedObjectID = objectp->getID();
+		mFocusedObjectFace = face;
+		mFocusedObjectNormal = pick_normal;
 
-		if(objectp.notNull())
+		LLTextureEntry* tep = objectp->getTE(face);
+		if(tep->hasMedia())
 		{
-			LLTextureEntry* tep = objectp->getTE(face);
-			if(! tep->hasMedia())
-			{
-				// Error condition
-			}
 			LLMediaEntry* mep = tep->getMediaData();
 			face_auto_zoom = mep->getAutoZoom();
-			if(! mep->getAutoPlay())
+			if(!media_impl->hasMedia())
 			{
 				std::string url = mep->getCurrentURL().empty() ? mep->getHomeURL() : mep->getCurrentURL();
 				media_impl->navigateTo(url, "", true);
 			}
 		}
-		mFocus = LLSelectMgr::getInstance()->getSelection();
-		if(mMediaHUD.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
-		{
-			mMediaHUD.get()->resetZoomLevel();
-			mMediaHUD.get()->nextZoomLevel();
-		}
-		if (!mFocus->isEmpty())
+		else
 		{
-			gFocusMgr.setKeyboardFocus(this);
+			// This should never happen.
+			llwarns << "Can't find media entry for focused face" << llendl;
 		}
-		mObjectID = objectp->getID();
-		mObjectFace = face;
-		// LLViewerMedia::addObserver(this, mObjectID);
 
+		media_impl->focus(true);
+		gFocusMgr.setKeyboardFocus(this);
+		
+		// We must do this before  processing the media HUD zoom, or it may zoom to the wrong face. 
+		update();
 
+		if(mMediaControls.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
+		{
+			mMediaControls.get()->resetZoomLevel();
+			mMediaControls.get()->nextZoomLevel();
+		}
 	}
 	else
 	{
-		gFocusMgr.setKeyboardFocus(NULL);
-		if(! parcel->getMediaPreventCameraZoom())
+		if(mFocusedImplID.notNull())
 		{
-			if (!mFocus->isEmpty())
+			if(mMediaControls.get())
 			{
-				gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+				mMediaControls.get()->resetZoomLevel();
 			}
 		}
-		mFocus = NULL;
-		// LLViewerMedia::remObserver(this, mObjectID);
-		
-		// Null out the media hud media pointer
-		if(mMediaHUD.get())
+
+		if(hasFocus())
 		{
-			mMediaHUD.get()->setMediaImpl(NULL);
+			gFocusMgr.setKeyboardFocus(NULL);
 		}
+		
+		mFocusedImplID = LLUUID::null;
+		mFocusedObjectID = LLUUID::null;
+		mFocusedObjectFace = 0;
+	}
+}
+
+void LLViewerMediaFocus::clearFocus()
+{
+	setFocusFace(NULL, 0, NULL);
+}
 
-		// and null out the media impl
-		mMediaImpl = NULL;
-		mObjectID = LLUUID::null;
-		mObjectFace = 0;
+void LLViewerMediaFocus::setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{
+	if (media_impl.notNull())
+	{
+		mHoverImplID = media_impl->getMediaTextureID();
+		mHoverObjectID = objectp->getID();
+		mHoverObjectFace = face;
+		mHoverObjectNormal = pick_normal;
 	}
-	if(mMediaHUD.get())
+	else
 	{
-		mMediaHUD.get()->setMediaFocus(b);
+		mHoverObjectID = LLUUID::null;
+		mHoverObjectFace = 0;
+		mHoverImplID = LLUUID::null;
 	}
 }
+
+void LLViewerMediaFocus::clearHover()
+{
+	setHoverFace(NULL, 0, NULL);
+}
+
+
 bool LLViewerMediaFocus::getFocus()
 {
 	if (gFocusMgr.getKeyboardFocus() == this)
@@ -176,22 +174,15 @@ bool LLViewerMediaFocus::getFocus()
 	return false;
 }
 
-// This function selects an ideal viewing distance given a selection bounding box, normal, and padding value
-void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
+// This function selects an ideal viewing distance based on the focused object, pick normal, and padding value
+void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor)
 {
-	LLPickInfo& pick = LLToolPie::getInstance()->getPick();
-
-	if(LLSelectMgr::getInstance()->getSelection()->isEmpty())
-	{
-		pick = mPickInfo;
-		setFocusFace(true, pick.getObject(), pick.mObjectFace, mMediaImpl);
-	}
-
-	if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
+	if (object)
 	{
 		gAgent.setFocusOnAvatar(FALSE, ANIMATE);
 
-		LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
+		LLBBox bbox = object->getBoundingBoxAgent();
+		LLVector3d center = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
 		F32 height;
 		F32 width;
 		F32 depth;
@@ -199,7 +190,7 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
 		F32 distance;
 
 		// We need the aspect ratio, and the 3 components of the bbox as height, width, and depth.
-		F32 aspect_ratio = getBBoxAspectRatio(selection_bbox, pick.mNormal, &height, &width, &depth);
+		F32 aspect_ratio = getBBoxAspectRatio(bbox, normal, &height, &width, &depth);
 		F32 camera_aspect = LLViewerCamera::getInstance()->getAspect();
 
 		// We will normally use the side of the volume aligned with the short side of the screen (i.e. the height for 
@@ -227,84 +218,96 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
 		distance += depth * 0.5;
 
 		// Finally animate the camera to this new position and focal point
-		gAgent.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(pick.mNormal * distance), 
-			LLSelectMgr::getInstance()->getSelectionCenterGlobal(), LLSelectMgr::getInstance()->getSelection()->getFirstObject()->mID );
+		LLVector3d camera_pos, target_pos;
+		// The target lookat position is the center of the selection (in global coords)
+		target_pos = center;
+		// Target look-from (camera) position is "distance" away from the target along the normal 
+		LLVector3d pickNormal = LLVector3d(normal);
+		pickNormal.normalize();
+        camera_pos = target_pos + pickNormal * distance;
+        if (pickNormal == LLVector3d::z_axis || pickNormal == LLVector3d::z_axis_neg)
+        {
+			// If the normal points directly up, the camera will "flip" around.
+			// We try to avoid this by adjusting the target camera position a 
+			// smidge towards current camera position
+			// *NOTE: this solution is not perfect.  All it attempts to solve is the
+			// "looking down" problem where the camera flips around when it animates
+			// to that position.  You still are not guaranteed to be looking at the
+			// media in the correct orientation.  What this solution does is it will
+			// put the camera into position keeping as best it can the current 
+			// orientation with respect to the face.  In other words, if before zoom
+			// the media appears "upside down" from the camera, after zooming it will
+			// still be upside down, but at least it will not flip.
+            LLVector3d cur_camera_pos = LLVector3d(gAgent.getCameraPositionGlobal());
+            LLVector3d delta = (cur_camera_pos - camera_pos);
+            F64 len = delta.length();
+            delta.normalize();
+            // Move 1% of the distance towards original camera location
+            camera_pos += 0.01 * len * delta;
+        }
+
+		gAgent.setCameraPosAndFocusGlobal(camera_pos, target_pos, object->getID() );
+	}
+	else
+	{
+		// If we have no object, focus back on the avatar.
+		gAgent.setFocusOnAvatar(TRUE, ANIMATE);
 	}
 }
 void LLViewerMediaFocus::onFocusReceived()
 {
-	if(mMediaImpl.notNull())
-		mMediaImpl->focus(true);
+	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+	if(media_impl)
+		media_impl->focus(true);
 
 	LLFocusableElement::onFocusReceived();
 }
 
 void LLViewerMediaFocus::onFocusLost()
 {
-	if(mMediaImpl.notNull())
-		mMediaImpl->focus(false);
+	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+	if(media_impl)
+		media_impl->focus(false);
+
 	gViewerWindow->focusClient();
-	mFocus = NULL;
 	LLFocusableElement::onFocusLost();
 }
-void LLViewerMediaFocus::setMouseOverFlag(bool b, viewer_media_t media_impl)
+
+BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)
 {
-	if (b && media_impl.notNull())
+	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+	if(media_impl)
 	{
-		if(! mMediaHUD.get())
-		{
-			LLPanelMediaHUD* media_hud = new LLPanelMediaHUD(mMediaImpl);
-			mMediaHUD = media_hud->getHandle();
-			gHUDView->addChild(media_hud);	
-		}
-		mMediaHUD.get()->setMediaImpl(media_impl);
+		media_impl->handleKeyHere(key, mask);
 
-		if(mMediaImpl.notNull() && (mMediaImpl != media_impl))
+		if (key == KEY_ESCAPE)
 		{
-			mMediaImpl->focus(false);
+			clearFocus();
 		}
-
-		mMediaImpl = media_impl;
 	}
-	mMouseOverFlag = b;
-}
-LLUUID LLViewerMediaFocus::getSelectedUUID() 
-{ 
-	LLViewerObject* object = mFocus->getFirstObject();
-	return object ? object->getID() : LLUUID::null; 
-}
-#if 0 // Must re-implement when the new media api event system is ready
-void LLViewerMediaFocus::onNavigateComplete( const EventType& event_in )
-{
-	if (hasFocus() && mLastURL != event_in.getStringValue())
-	{
-		LLViewerMedia::focus(true, mObjectID);
-		// spoof mouse event to reassert focus
-		LLViewerMedia::mouseDown(1,1, mObjectID);
-		LLViewerMedia::mouseUp(1,1, mObjectID);
-	}
-	mLastURL = event_in.getStringValue();
-}
-#endif
-BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)
-{
-	if(mMediaImpl.notNull())
-		mMediaImpl->handleKeyHere(key, mask);
+	
 	return true;
 }
 
 BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
 {
-	if(mMediaImpl.notNull())
-		mMediaImpl->handleUnicodeCharHere(uni_char);
+	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+	if(media_impl)
+		media_impl->handleUnicodeCharHere(uni_char);
 	return true;
 }
 BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
 {
 	BOOL retval = FALSE;
-	if(mFocus.notNull() && mMediaImpl.notNull() && mMediaImpl->hasMedia())
+	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+	if(media_impl && media_impl->hasMedia())
 	{
-		mMediaImpl->getMediaPlugin()->scrollEvent(x, y, clicks);
+        // the scrollEvent() API's x and y are not the same as handleScrollWheel's x and y.
+        // The latter is the position of the mouse at the time of the event
+        // The former is the 'scroll amount' in x and y, respectively.
+        // All we have for 'scroll amount' here is 'clicks'.
+		// We're also not passed the keyboard modifier mask, but we can get that from gKeyboard.
+		media_impl->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE));
 		retval = TRUE;
 	}
 	return retval;
@@ -312,19 +315,69 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
 
 void LLViewerMediaFocus::update()
 {
-	if (mMediaHUD.get())
+	if(mFocusedImplID.notNull() || mFocusedObjectID.notNull())
 	{
-		if(mFocus.notNull() || mMouseOverFlag || mMediaHUD.get()->isMouseOver())
+		// We have a focused impl/face.
+		if(!getFocus())
 		{
-			// mMediaHUD.get()->setVisible(true);
-			mMediaHUD.get()->updateShape();
+			// We've lost keyboard focus -- check to see whether the media controls have it
+			if(mMediaControls.get() && mMediaControls.get()->hasFocus())
+			{
+				// the media controls have focus -- don't clear.
+			}
+			else
+			{
+				// Someone else has focus -- back off.
+				clearFocus();
+			}
 		}
-		else
+		else if(LLToolMgr::getInstance()->inBuildMode())
 		{
-			mMediaHUD.get()->setVisible(false);
+			// Build tools are selected -- clear focus.
+			clearFocus();
+		}
+	}
+	
+	
+	LLViewerMediaImpl *media_impl = getFocusedMediaImpl();
+	LLViewerObject *viewer_object = getFocusedObject();
+	S32 face = mFocusedObjectFace;
+	LLVector3 normal = mFocusedObjectNormal;
+	bool focus = true;
+	
+	if(!media_impl || !viewer_object)
+	{
+		focus = false;
+		media_impl = getHoverMediaImpl();
+		viewer_object = getHoverObject();
+		face = mHoverObjectFace;
+		normal = mHoverObjectNormal;
+	}
+	
+	if(media_impl && viewer_object)
+	{
+		// We have an object and impl to point at.
+		
+		// Make sure the media HUD object exists.
+		if(! mMediaControls.get())
+		{
+			LLPanelPrimMediaControls* media_controls = new LLPanelPrimMediaControls();
+			mMediaControls = media_controls->getHandle();
+			gHUDView->addChild(media_controls);	
+		}
+		mMediaControls.get()->setMediaFace(viewer_object, face, media_impl, normal);
+	}
+	else
+	{
+		// The media HUD is no longer needed.
+		if(mMediaControls.get())
+		{
+			mMediaControls.get()->setMediaFace(NULL, 0, NULL);
 		}
 	}
 }
+
+
 // This function calculates the aspect ratio and the world aligned components of a selection bounding box.
 F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth)
 {
@@ -393,5 +446,74 @@ F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3&
 
 bool LLViewerMediaFocus::isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face)
 {
-	return objectp->getID() == mObjectID && face == mObjectFace;
+	return objectp->getID() == mFocusedObjectID && face == mFocusedObjectFace;
+}
+
+bool LLViewerMediaFocus::isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face)
+{
+	return objectp->getID() == mHoverObjectID && face == mHoverObjectFace;
+}
+
+
+LLViewerMediaImpl* LLViewerMediaFocus::getFocusedMediaImpl()
+{
+	return LLViewerMedia::getMediaImplFromTextureID(mFocusedImplID);
+}
+
+LLViewerObject* LLViewerMediaFocus::getFocusedObject()
+{
+	return gObjectList.findObject(mFocusedObjectID);
+}
+
+LLViewerMediaImpl* LLViewerMediaFocus::getHoverMediaImpl()
+{
+	return LLViewerMedia::getMediaImplFromTextureID(mHoverImplID);
+}
+
+LLViewerObject* LLViewerMediaFocus::getHoverObject()
+{
+	return gObjectList.findObject(mHoverObjectID);
+}
+
+void LLViewerMediaFocus::focusZoomOnMedia(LLUUID media_id)
+{
+	LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(media_id);
+	
+	if(impl)
+	{	
+		// Get the first object from the media impl's object list.  This is completely arbitrary, but should suffice.
+		LLVOVolume *obj = impl->getSomeObject();
+		if(obj)
+		{
+			// This media is attached to at least one object.  Figure out which face it's on.
+			S32 face = obj->getFaceIndexWithMediaImpl(impl, -1);
+			
+			// We don't have a proper pick normal here, and finding a face's real normal is... complicated.
+			// For now, use +z to look at the top of the object.
+			LLVector3 normal(0.0f, 0.0f, 1.0f);
+			
+			// Attempt to focus/zoom on that face.
+			setFocusFace(obj, face, impl, normal);
+			
+			if(mMediaControls.get())
+			{
+				mMediaControls.get()->resetZoomLevel();
+				mMediaControls.get()->nextZoomLevel();
+			}
+		}
+	}
+}
+
+LLUUID LLViewerMediaFocus::getControlsMediaID()
+{
+	if(getFocusedMediaImpl())
+	{
+		return mFocusedImplID;
+	}
+	else if(getHoverMediaImpl())
+	{
+		return mHoverImplID;
+	}
+	
+	return LLUUID::null;
 }
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index 2688a8b7087d6827fa70283b0ab1591ca18feaab..e5f36d341c482f9b00250ea2e82d7498ed56c6fa 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -40,7 +40,7 @@
 #include "llselectmgr.h"
 
 class LLViewerMediaImpl;
-class LLPanelMediaHUD;
+class LLPanelPrimMediaControls;
 
 class LLViewerMediaFocus : 
 	public LLFocusableElement, 
@@ -50,44 +50,61 @@ class LLViewerMediaFocus :
 	LLViewerMediaFocus();
 	~LLViewerMediaFocus();
 	
-	static void cleanupClass();
-
-	void setFocusFace(BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl);
-	void clearFocus() { setFocusFace(false, NULL, 0, NULL); }
+	// Set/clear the face that has media focus (takes keyboard input and has the full set of controls)
+	void setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
+	void clearFocus();
+	
+	// Set/clear the face that has "media hover" (has the mimimal set of controls to zoom in or pop out into a media browser).
+	// If a media face has focus, the media hover will be ignored.
+	void setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
+	void clearHover();
+	
 	/*virtual*/ bool	getFocus();
-	/*virtual*/ // void onNavigateComplete( const EventType& event_in );
-
 	/*virtual*/ BOOL	handleKey(KEY key, MASK mask, BOOL called_from_parent);
 	/*virtual*/ BOOL	handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
 	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
 
-	LLUUID getSelectedUUID();
-	LLObjectSelectionHandle getSelection() { return mFocus; }
-
 	void update();
+	
+	static void setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor);
+	static F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth);
 
-	void setCameraZoom(F32 padding_factor);
-	void setMouseOverFlag(bool b, viewer_media_t media_impl = NULL);
-	bool getMouseOverFlag() { return mMouseOverFlag; }
-	void setPickInfo(LLPickInfo pick_info) { mPickInfo = pick_info; }
-	F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth);
-
-	// TODO: figure out why selection mgr hates me
 	bool isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face);
+	bool isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face);
+	
+	// These look up (by uuid) and return the values that were set with setFocusFace.  They will return null if the objects have been destroyed.
+	LLViewerMediaImpl* getFocusedMediaImpl();
+	LLViewerObject* getFocusedObject();
+	S32 getFocusedFace() { return mFocusedObjectFace; }
+	
+	// These look up (by uuid) and return the values that were set with setHoverFace.  They will return null if the objects have been destroyed.
+	LLViewerMediaImpl* getHoverMediaImpl();
+	LLViewerObject* getHoverObject();
+	S32 getHoverFace() { return mHoverObjectFace; }
+	
+	// Try to focus/zoom on the specified media (if it's on an object in world).
+	void focusZoomOnMedia(LLUUID media_id);
+	
+	// Return the ID of the media instance the controls are currently attached to (either focus or hover).
+	LLUUID getControlsMediaID();
 
 protected:
 	/*virtual*/ void	onFocusReceived();
 	/*virtual*/ void	onFocusLost();
 
 private:
-	LLObjectSelectionHandle mFocus;
-	std::string mLastURL;
-	bool mMouseOverFlag;
-	LLPickInfo mPickInfo;
-	LLHandle<LLPanelMediaHUD> mMediaHUD;
-	LLUUID mObjectID;
-	S32 mObjectFace;
-	viewer_media_t mMediaImpl;
+	
+	LLHandle<LLPanelPrimMediaControls> mMediaControls;
+	
+	LLUUID mFocusedObjectID;
+	S32 mFocusedObjectFace;
+	LLUUID mFocusedImplID;
+	LLVector3 mFocusedObjectNormal;
+	
+	LLUUID mHoverObjectID;
+	S32 mHoverObjectFace;
+	LLUUID mHoverImplID;
+	LLVector3 mHoverObjectNormal;
 };
 
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 56f70e0f5dde1b02a19e9d559e55760db027ac20..ef4569c08e70ae6ddd17e4be5e412e41d8425a63 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -206,6 +206,7 @@
 #include "llwaterparammanager.h"
 #include "llfloaternotificationsconsole.h"
 #include "llfloatercamera.h"
+#include "lluilistener.h"
 
 #include "lltexlayer.h"
 #include "llappearancemgr.h"
@@ -412,6 +413,8 @@ class LLMenuParcelObserver : public LLParcelObserver
 
 static LLMenuParcelObserver* gMenuParcelObserver = NULL;
 
+static LLUIListener sUIListener("UI");
+
 LLMenuParcelObserver::LLMenuParcelObserver()
 {
 	LLViewerParcelMgr::getInstance()->addObserver(this);
@@ -1675,34 +1678,6 @@ class LLAdvancedTogglePG : public view_listener_t
 };
 
 
-
-////////////////////////////
-// ALLOW TAP-TAP-HOLD RUN //
-////////////////////////////
-
-
-class LLAdvancedToggleAllowTapTapHoldRun : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gAllowTapTapHoldRun = !(gAllowTapTapHoldRun);
-		return true;
-	}
-};
-
-class LLAdvancedCheckAllowTapTapHoldRun : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gAllowTapTapHoldRun;
-		return new_value;
-	}
-};
-
-
-
-
-
 class LLAdvancedForceParamsToDefault : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -3508,7 +3483,6 @@ void set_god_level(U8 god_level)
 {
 	U8 old_god_level = gAgent.getGodLevel();
 	gAgent.setGodLevel( god_level );
-	gIMMgr->refresh();
 	LLViewerParcelMgr::getInstance()->notifyObservers();
 
 	// God mode changes sim visibility
@@ -7064,7 +7038,7 @@ void force_error_bad_memory_access(void *)
 
 void force_error_infinite_loop(void *)
 {
-    LLAppViewer::instance()->forceErrorInifiniteLoop();
+    LLAppViewer::instance()->forceErrorInfiniteLoop();
 }
 
 void force_error_software_exception(void *)
@@ -7963,8 +7937,6 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLAdvancedTogglePG(), "Advanced.TogglePG");
 	
 	// Advanced > Character (toplevel)
-	view_listener_t::addMenu(new LLAdvancedToggleAllowTapTapHoldRun(), "Advanced.ToggleAllowTapTapHoldRun");
-	view_listener_t::addMenu(new LLAdvancedCheckAllowTapTapHoldRun(), "Advanced.CheckAllowTapTapHoldRun");
 	view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault");
 	view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader");
 	view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo");
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index f16465acba0234bf9e029456df7d196fe81660bd..9840017bd6969091240eb959a28864bb350eca76 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -72,7 +72,6 @@
 #include "llviewercontrol.h"
 #include "lldrawpool.h"
 #include "llfirstuse.h"
-#include "llfloateractivespeakers.h"
 #include "llfloateranimpreview.h"
 #include "llfloaterbuycurrency.h"
 #include "llfloaterbuyland.h"
@@ -89,7 +88,6 @@
 #include "llhudeffect.h"
 #include "llhudeffecttrail.h"
 #include "llhudmanager.h"
-#include "llimpanel.h"
 #include "llinventorymodel.h"
 #include "llfloaterinventory.h"
 #include "llmenugl.h"
@@ -1597,8 +1595,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 			// Claim to be from a local agent so it doesn't go into
 			// console.
 			chat.mText = name + separator_string + message.substr(message_offset);
-			BOOL local_agent = TRUE;
-			LLFloaterChat::addChat(chat, FALSE, local_agent);
+
+			LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+			if(nearby_chat)
+			{
+				nearby_chat->addMessage(chat);
+			}
 		}
 		else
 		{
@@ -2378,7 +2380,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 			switch(chat.mChatType)
 			{
 			case CHAT_TYPE_WHISPER:
-				verb = "(" + LLTrans::getString("whisper") + ")";
+				verb = LLTrans::getString("whisper") + " ";
 				break;
 			case CHAT_TYPE_DEBUG_MSG:
 			case CHAT_TYPE_OWNER:
@@ -2386,7 +2388,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 				verb = "";
 				break;
 			case CHAT_TYPE_SHOUT:
-				verb = "(" + LLTrans::getString("shout") + ")";
+				verb = LLTrans::getString("shout") + " ";
 				break;
 			case CHAT_TYPE_START:
 			case CHAT_TYPE_STOP:
@@ -5681,7 +5683,7 @@ void onCovenantLoadComplete(LLVFS *vfs,
 	LLPanelLandCovenant::updateCovenantText(covenant_text);
 	LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid);
 
-	LLPanelPlaceInfo* panel = dynamic_cast<LLPanelPlaceInfo*>(LLSideTray::getInstance()->showPanel("panel_place_info", LLSD()));
+	LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
 	if (panel)
 	{
 		panel->updateCovenantText(covenant_text);
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index 918b15ef09dc5a211b4ecb64c42bc16ebe740e0e..801c46035a20e2c438d23c9b8c70ba2edb67cd54 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -35,6 +35,8 @@
 
 #include "llviewernetwork.h"
 #include "llviewercontrol.h"
+#include "llevents.h"
+#include "lllogin.h"
 
 struct LLGridData
 {
@@ -155,6 +157,10 @@ LLViewerLogin::LLViewerLogin() :
 {
 }
 
+ LLViewerLogin::~LLViewerLogin() 
+ {
+ }
+
 void LLViewerLogin::setGridChoice(EGridInfo grid)
 {	
 	if(grid < 0 || grid >= GRID_INFO_COUNT)
diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h
index 4001ed05c1e5f25eb09cf7f2edbc5db20992e598..edae6dc47b56b87f1770269bf2fde8b61261de56 100644
--- a/indra/newview/llviewernetwork.h
+++ b/indra/newview/llviewernetwork.h
@@ -34,7 +34,10 @@
 #ifndef LL_LLVIEWERNETWORK_H
 #define LL_LLVIEWERNETWORK_H
 
+#include <boost/scoped_ptr.hpp>
+
 class LLHost;
+class LLLogin;
 
 enum EGridInfo
 {
@@ -74,6 +77,7 @@ class LLViewerLogin : public LLSingleton<LLViewerLogin>
 {
 public:
 	LLViewerLogin();
+	~LLViewerLogin();
 
 	void setGridChoice(EGridInfo grid);
 	void setGridChoice(const std::string& grid_name);
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index a3f9c839a0dff6be3b54ac2df0e5413bc8c11011..6233a337a663ff8b2b7971fce0705e3379e01af4 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -226,11 +226,13 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
 				media_height, 
 				media_auto_scale,
 				media_loop);
-			sMediaImpl->navigateTo(media_url);
+			sMediaImpl->navigateTo(media_url, mime_type, true);
 		}
 	}
 	else
 	{
+		LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL;
+
 		// There is no media impl, make a new one
 		sMediaImpl = LLViewerMedia::newMediaImpl(
 			placeholder_texture_id,
@@ -238,7 +240,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
 			media_height, 
 			media_auto_scale,
 			media_loop);
-		sMediaImpl->navigateTo(media_url);
+		sMediaImpl->navigateTo(media_url, mime_type, true);
 	}
 
 	LLFirstUse::useMedia();
@@ -544,6 +546,18 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
 			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
 		};
 		break;
+		
+		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+		{
+			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
+		};
+		break;
+		
+		case MEDIA_EVENT_NAME_CHANGED:
+		{
+			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
+		};
+		break;
 	};
 }
 
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 7ca11d83642c0a41fd87ab380fb9ffdf1ddbba53..aa0987aa7d1223635a663a09366f20d002f12302 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -56,6 +56,7 @@
 #include "llparcelselection.h"
 #include "llresmgr.h"
 #include "llsdutil.h"
+#include "llsdutil_math.h"
 #include "llstatusbar.h"
 #include "llui.h"
 #include "llviewertexture.h"
@@ -842,8 +843,11 @@ void LLViewerParcelMgr::renderParcelCollision()
 	if (mRenderCollision && gSavedSettings.getBOOL("ShowBanLines"))
 	{
 		LLViewerRegion* regionp = gAgent.getRegion();
-		BOOL use_pass = mCollisionParcel->getParcelFlag(PF_USE_PASS_LIST);
-		renderCollisionSegments(mCollisionSegments, use_pass, regionp);
+		if (regionp)
+		{
+			BOOL use_pass = mCollisionParcel->getParcelFlag(PF_USE_PASS_LIST);
+			renderCollisionSegments(mCollisionSegments, use_pass, regionp);
+		}
 	}
 }
 
@@ -1161,10 +1165,11 @@ void LLViewerParcelMgr::sendParcelBuy(ParcelBuyInfo* info)
 	msg->sendReliable(info->mHost);
 }
 
-void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo*& info)
+void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo* *info)
 {
-	delete info;
-	info = NULL;
+	// Must be here because ParcelBuyInfo is local to this .cpp file
+	delete *info;
+	*info = NULL;
 }
 
 void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id)
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 3964a56bf60b3450ff0ce5cb5d43b67f2656fd6d..1c8fe23dba125ed08ca0414935d84988f68ae7f3 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -246,7 +246,7 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
 								  BOOL remove_contribution);
 		// callers responsibility to call deleteParcelBuy() on return value
 	void sendParcelBuy(ParcelBuyInfo*);
-	void deleteParcelBuy(ParcelBuyInfo*&);
+	void deleteParcelBuy(ParcelBuyInfo* *info);
 					   
 	void sendParcelDeed(const LLUUID& group_id);
 
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index ed8d82084444eeb50ba05baaffbfe908f767e8d0..8fad9e09cba202ee194165f5a169a9fe1107369f 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -44,6 +44,9 @@
 #include "llinventory.h"
 #include "llinventorybridge.h"
 #include "llinventorymodel.h"
+#include "lllandmark.h"
+#include "lllandmarkactions.h"
+#include "lllandmarklist.h"
 #include "llmemorystream.h"
 #include "llmenugl.h"
 #include "llnotecard.h"
@@ -64,10 +67,47 @@
 #include "llviewertexturelist.h"
 #include "llviewerwindow.h"
 
-#include "llappviewer.h" // for gPacificDaylightTime
-
 static LLDefaultChildRegistry::Register<LLViewerTextEditor> r("text_editor");
 
+///-----------------------------------------------------------------------
+///  Class LLEmbeddedLandmarkCopied
+///-----------------------------------------------------------------------
+class LLEmbeddedLandmarkCopied: public LLInventoryCallback
+{
+public:
+
+	LLEmbeddedLandmarkCopied(){}
+	void fire(const LLUUID& inv_item)
+	{
+		showInfo(inv_item);
+	}
+	static void showInfo(const LLUUID& landmark_inv_id)
+	{
+		LLSD key;
+		key["type"] = "landmark";
+		key["id"] = landmark_inv_id;
+		LLSideTray::getInstance()->showPanel("panel_places", key);
+	}
+	static void processForeignLandmark(LLLandmark* landmark,
+			const LLUUID& object_id, const LLUUID& notecard_inventory_id,
+			LLInventoryItem* item)
+	{
+		LLVector3d global_pos;
+		landmark->getGlobalPos(global_pos);
+		LLViewerInventoryItem* agent_lanmark =
+				LLLandmarkActions::findLandmarkForGlobalPos(global_pos);
+
+		if (agent_lanmark)
+		{
+			showInfo(agent_lanmark->getUUID());
+		}
+		else
+		{
+			LLPointer<LLEmbeddedLandmarkCopied> cb = new LLEmbeddedLandmarkCopied();
+			copy_inventory_from_notecard(object_id, notecard_inventory_id, item, gInventoryCallbacks.registerCB(cb));
+		}
+	}
+};
 ///----------------------------------------------------------------------------
 /// Class LLEmbeddedNotecardOpener
 ///----------------------------------------------------------------------------
@@ -1100,14 +1140,12 @@ void LLViewerTextEditor::openEmbeddedLandmark( LLInventoryItem* item, llwchar wc
 	if (!item)
 		return;
 
-	LLSD key;
-	key["type"] = "landmark";
-	key["id"] = item->getUUID();
-
-	LLPanelPlaces *panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", key));
-	if (panel)
+	LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID(),
+			boost::bind(&LLEmbeddedLandmarkCopied::processForeignLandmark, _1, mObjectID, mNotecardInventoryID, item));
+	if (landmark)
 	{
-		panel->setItem(item);
+		LLEmbeddedLandmarkCopied::processForeignLandmark(landmark, mObjectID,
+				mNotecardInventoryID, item);
 	}
 }
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 32baa29afbe94991edcf2196b5d10a0723550536..1cda1769c34e64a621db3027abdbb7fbfd9df73a 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -93,6 +93,7 @@ BOOL LLViewerTexture::sUseTextureAtlas        = FALSE ;
 
 const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
 const F32 desired_discard_bias_max = 1.5f; // max number of levels to reduce image quality by
+const F64 log_2 = log(2.0);
 
 //----------------------------------------------------------------------------------------------
 //namespace: LLViewerTextureAccess
@@ -134,7 +135,7 @@ LLViewerMediaTexture*  LLViewerTextureManager::getMediaTexture(const LLUUID& id,
 	return tex ;
 }
 
-LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLViewerTexture* tex, BOOL report_error)
+LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error)
 {
 	if(!tex)
 	{
@@ -191,25 +192,25 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid
 LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(
 	                                               const LLUUID &image_id,											       
 												   BOOL usemipmaps,
-												   BOOL level_immediate,
+												   S32 boost_priority,
 												   S8 texture_type,
 												   LLGLint internal_format,
 												   LLGLenum primary_format,
 												   LLHost request_from_host)
 {
-	return gTextureList.getImage(image_id, usemipmaps, level_immediate, texture_type, internal_format, primary_format, request_from_host) ;
+	return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ;
 }
 	
 LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile(
 	                                               const std::string& filename,												   
 												   BOOL usemipmaps,
-												   BOOL level_immediate,
+												   S32 boost_priority,
 												   S8 texture_type,
 												   LLGLint internal_format,
 												   LLGLenum primary_format, 
 												   const LLUUID& force_id)
 {
-	return gTextureList.getImageFromFile(filename, usemipmaps, level_immediate, texture_type, internal_format, primary_format, force_id) ;
+	return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ;
 }
 
 LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) 
@@ -415,6 +416,7 @@ void LLViewerTexture::init(bool firstinit)
 	mDontDiscard = FALSE;
 	mMaxVirtualSize = 0.f;
 	mNeedsResetMaxVirtualSize = FALSE ;
+	mParcelMedia = NULL ;
 }
 
 //virtual 
@@ -522,6 +524,12 @@ F32 LLViewerTexture::getMaxVirtualSize()
 	return mMaxVirtualSize ;
 }
 
+//virtual 
+void LLViewerTexture::setKnownDrawSize(S32 width, S32 height)
+{
+	//nothing here.
+}
+
 //virtual
 void LLViewerTexture::addFace(LLFace* facep) 
 {
@@ -852,6 +860,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
 
 	mKnownDrawWidth = 0;
 	mKnownDrawHeight = 0;
+	mKnownDrawSizeChanged = FALSE ;
 
 	if (firstinit)
 	{
@@ -1084,10 +1093,17 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
 }
 
 // Call with 0,0 to turn this feature off.
+//virtual
 void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
 {
-	mKnownDrawWidth = width;
-	mKnownDrawHeight = height;
+	if(mKnownDrawWidth != width || mKnownDrawHeight != height)
+	{
+		mKnownDrawWidth = width;
+		mKnownDrawHeight = height;
+
+		mKnownDrawSizeChanged = TRUE ;
+		mFullyLoaded = FALSE ;
+	}
 	addTextureStats((F32)(width * height));
 }
 
@@ -1104,13 +1120,26 @@ void LLViewerFetchedTexture::processTextureStats()
 		mDesiredDiscardLevel = 	getMaxDiscardLevel() ;
 	}
 	else
-	{
-		mDesiredDiscardLevel = 0;
-		if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
+	{	
+		if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight)
 		{
-			mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+			if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
+			{
+				mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+			}
+			else
+			{
+				mDesiredDiscardLevel = 0;
+			}
 		}
-
+		else if(mKnownDrawSizeChanged)//known draw size is set
+		{			
+			mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, 
+					                             log((F32)mFullHeight / mKnownDrawHeight) / log_2) ;
+			mDesiredDiscardLevel = 	llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ;
+		}
+		mKnownDrawSizeChanged = FALSE ;
+		
 		if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel))
 		{
 			mFullyLoaded = TRUE ;
@@ -1121,8 +1150,6 @@ void LLViewerFetchedTexture::processTextureStats()
 //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32.
 F32 LLViewerFetchedTexture::calcDecodePriorityForUnknownTexture(F32 pixel_priority)
 {
-	static const F64 log_2 = log(2.0);
-
 	F32 desired = (F32)(log(32.0/pixel_priority) / log_2);
 	S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired + 1;
 	ddiscard = llclamp(ddiscard, 1, 9);
@@ -1169,7 +1196,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
 		// Don't decode anything we don't need
 		priority = -1.0f;
 	}
-	else if (mBoostLevel == LLViewerTexture::BOOST_UI && !have_all_data)
+	else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data)
 	{
 		priority = 1.f;
 	}
@@ -2121,22 +2148,29 @@ void LLViewerMediaTexture::updateClass()
 {
 	static const F32 MAX_INACTIVE_TIME = 30.f ;
 
+#if 0
+	//force to play media.
+	gSavedSettings.setBOOL("AudioSteamingMedia", true) ;
+	gSavedSettings.setBOOL("AudioStreamingVideo", true) ;
+#endif
+
 	for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); )
 	{
 		LLViewerMediaTexture* mediap = iter->second;	
-
-		//
-		//Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture.
-		//
-		if(mediap->getNumRefs() == 1 && mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) //one by sMediaMap
-		{
-			media_map_t::iterator cur = iter++ ;
-			sMediaMap.erase(cur) ;
-		}
-		else
+		
+		if(mediap->getNumRefs() == 1) //one reference by sMediaMap
 		{
-			++iter ;
+			//
+			//Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture.
+			//
+			if(mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME)
+			{
+				media_map_t::iterator cur = iter++ ;
+				sMediaMap.erase(cur) ;
+				continue ;
+			}
 		}
+		++iter ;
 	}
 }
 
@@ -2189,11 +2223,22 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL
 	mIsPlaying = FALSE ;
 
 	setMediaImpl() ;
+
+	LLViewerTexture* tex = gTextureList.findImage(mID) ;
+	if(tex) //this media is a parcel media for tex.
+	{
+		tex->setParcelMedia(this) ;
+	}
 }
 
 //virtual 
 LLViewerMediaTexture::~LLViewerMediaTexture() 
 {	
+	LLViewerTexture* tex = gTextureList.findImage(mID) ;
+	if(tex) //this media is a parcel media for tex.
+	{
+		tex->setParcelMedia(NULL) ;
+	}
 }
 
 void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */)
@@ -2244,10 +2289,9 @@ BOOL LLViewerMediaTexture::findFaces()
 	mMediaFaceList.clear() ;
 
 	BOOL ret = TRUE ;
-
-	//for parcel media
-	LLViewerTexture* tex = gTextureList.findImage(mID) ;	
-	if(tex)
+	
+	LLViewerTexture* tex = gTextureList.findImage(mID) ;
+	if(tex) //this media is a parcel media for tex.
 	{
 		const ll_face_list_t* face_list = tex->getFaceList() ;
 		for(ll_face_list_t::const_iterator iter = face_list->begin(); iter != face_list->end(); ++iter)
@@ -2358,7 +2402,7 @@ void LLViewerMediaTexture::addFace(LLFace* facep)
 		mTextureList.push_back(facep->getTexture()) ; //a parcel media.
 		return ;
 	}
-
+	
 	llerrs << "The face does not have a valid texture before media texture." << llendl ;
 }
 
@@ -2434,10 +2478,11 @@ void LLViewerMediaTexture::removeFace(LLFace* facep)
 
 void LLViewerMediaTexture::stopPlaying()
 {
-	if(mMediaImplp)
-	{
-		mMediaImplp->stop() ;
-	}
+	// Don't stop the media impl playing here -- this breaks non-inworld media (login screen, search, and media browser).
+//	if(mMediaImplp)
+//	{
+//		mMediaImplp->stop() ;
+//	}
 	mIsPlaying = FALSE ;			
 }
 
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 596bfea670b33b91fa42b5dfdc31dc9c259e009f..020478beef2c6026ebebe3a9d694df1ff1236f82 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -118,10 +118,10 @@ class LLViewerTexture : public LLTexture
 		BOOST_SELECTED		= 12,
 		BOOST_HUD			= 13,
 		BOOST_AVATAR_BAKED_SELF	= 14,
-		BOOST_UI			= 15,
-		BOOST_PREVIEW		= 16,
-		BOOST_MAP			= 17,
-		BOOST_MAP_LAYER		= 18,
+		BOOST_ICON			= 15,
+		BOOST_UI			= 16,
+		BOOST_PREVIEW		= 17,
+		BOOST_MAP			= 18,
 		BOOST_AVATAR_SELF	= 19, // needed for baking avatar
 		BOOST_MAX_LEVEL
 	};
@@ -163,6 +163,7 @@ class LLViewerTexture : public LLTexture
 	
 	S32 getFullWidth() const { return mFullWidth; }
 	S32 getFullHeight() const { return mFullHeight; }	
+	/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
 
 	virtual void addFace(LLFace* facep) ;
 	virtual void removeFace(LLFace* facep) ; 
@@ -220,6 +221,10 @@ class LLViewerTexture : public LLTexture
 	BOOL getDontDiscard() const { return mDontDiscard; }
 	//-----------------	
 	
+	void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;}
+	BOOL hasParcelMedia() const { return mParcelMedia != NULL;}
+	LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;}
+
 	/*virtual*/ void updateBindStatsForTester() ;
 protected:
 	void cleanup() ;
@@ -246,6 +251,9 @@ class LLViewerTexture : public LLTexture
 	LLPointer<LLImageGL> mGLTexturep ;
 	S8 mDontDiscard;			// Keep full res version of this image (for UI, etc)
 
+	//do not use LLPointer here.
+	LLViewerMediaTexture* mParcelMedia ;
+
 protected:
 	typedef enum 
 	{
@@ -357,7 +365,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	// Override the computation of discard levels if we know the exact output
 	// size of the image.  Used for UI textures to not decode, even if we have
 	// more data.
-	void setKnownDrawSize(S32 width, S32 height);
+	/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
 
 	void setIsMissingAsset();
 	/*virtual*/ BOOL isMissingAsset()	const		{ return mIsMissingAsset; }
@@ -406,6 +414,8 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	BOOL  mFullyLoaded;
 
 protected:		
+	std::string mLocalFileName;
+
 	S32 mOrigWidth;
 	S32 mOrigHeight;
 
@@ -413,8 +423,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	// Used for UI textures to not decode, even if we have more data.
 	S32 mKnownDrawWidth;
 	S32	mKnownDrawHeight;
-
-	std::string mLocalFileName;
+	BOOL mKnownDrawSizeChanged ;
 
 	S8  mDesiredDiscardLevel;			// The discard level we'd LIKE to have - if we have it and there's space	
 	S8  mMinDesiredDiscardLevel;	// The minimum discard level we'd like to have
@@ -570,7 +579,7 @@ class LLViewerTextureManager
 	static LLTexturePipelineTester* sTesterp ;
 
 	//returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture.
-	static LLViewerFetchedTexture*    staticCastToFetchedTexture(LLViewerTexture* tex, BOOL report_error = FALSE) ;
+	static LLViewerFetchedTexture*    staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ;
 
 	//
 	//"find-texture" just check if the texture exists, if yes, return it, otherwise return null.
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 4ad4c8e1ea1dc8dd1f41dce300f98f14c50a0e8a..b5986c70f589069618e7adede346fcaf5aeba637 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -111,10 +111,10 @@ void LLViewerTextureList::doPreloadImages()
 	LL_DEBUGS("ViewerImages") << "Preloading images..." << LL_ENDL;
 	
 	// Set the "missing asset" image
-	LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, IMMEDIATE_YES);
+	LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI);
 	
 	// Set the "white" image
-	LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, IMMEDIATE_YES);
+	LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI);
 	
 	LLUIImageList* image_list = LLUIImageList::getInstance();
 
@@ -131,31 +131,31 @@ void LLViewerTextureList::doPreloadImages()
 	// prefetch specific UUIDs
 	LLViewerTextureManager::getFetchedTexture(IMG_SHOT, TRUE);
 	LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF, TRUE);
-	LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", MIPMAP_YES, IMMEDIATE_YES);
+	LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
 	if (image) 
 	{
 		image->setAddressMode(LLTexUnit::TAM_WRAP);
 		mImagePreloads.insert(image);
 	}
-	image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", MIPMAP_YES, IMMEDIATE_YES);
+	image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
 	if (image) 
 	{
 		image->setAddressMode(LLTexUnit::TAM_WRAP);	
 		mImagePreloads.insert(image);
 	}
-	image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", MIPMAP_YES, IMMEDIATE_YES);
+	image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
 	if (image) 
 	{
 		image->setAddressMode(LLTexUnit::TAM_WRAP);
 		mImagePreloads.insert(image);
 	}
-	image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, MIPMAP_YES, IMMEDIATE_YES);
+	image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
 	if (image) 
 	{
 		image->setAddressMode(LLTexUnit::TAM_WRAP);	
 		mImagePreloads.insert(image);
 	}
-	image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, IMMEDIATE_YES, LLViewerTexture::FETCHED_TEXTURE,
+	image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE,
 		0,0,LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"));
 	if (image) 
 	{
@@ -315,7 +315,7 @@ void LLViewerTextureList::restoreGL()
 
 LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename,												   
 												   BOOL usemipmaps,
-												   BOOL level_immediate,
+												   S32 boost_priority,
 												   S8 texture_type,
 												   LLGLint internal_format,
 												   LLGLenum primary_format, 
@@ -369,10 +369,14 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
 
 		addImage(imagep);
 		
-		if (level_immediate)
+		if (boost_priority != 0)
 		{
-			imagep->dontDiscard();
-			imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_UI);
+			if (boost_priority == LLViewerFetchedTexture::BOOST_UI ||
+				boost_priority == LLViewerFetchedTexture::BOOST_ICON)
+			{
+				imagep->dontDiscard();
+			}
+			imagep->setBoostLevel(boost_priority);
 		}
 	}
 
@@ -384,7 +388,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
 
 LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,											       
 												   BOOL usemipmaps,
-												   BOOL level_immediate,
+												   S32 boost_priority,
 												   S8 texture_type,
 												   LLGLint internal_format,
 												   LLGLenum primary_format,
@@ -403,7 +407,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
 	
 	if (imagep.isNull())
 	{
-		imagep = createImage(image_id, usemipmaps, level_immediate, texture_type, internal_format, primary_format, request_from_host) ;
+		imagep = createImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ;
 	}
 
 	imagep->setGLTextureCreated(true);
@@ -414,7 +418,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
 //when this function is called, there is no such texture in the gTextureList with image_id.
 LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,											       
 												   BOOL usemipmaps,
-												   BOOL level_immediate,
+												   S32 boost_priority,
 												   S8 texture_type,
 												   LLGLint internal_format,
 												   LLGLenum primary_format,
@@ -443,16 +447,20 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
 	
 	addImage(imagep);
 	
-	if (level_immediate)
+	if (boost_priority != 0)
 	{
-		imagep->dontDiscard();
-		imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_UI);
+		if (boost_priority == LLViewerFetchedTexture::BOOST_UI ||
+			boost_priority == LLViewerFetchedTexture::BOOST_ICON)
+		{
+			imagep->dontDiscard();
+		}
+		imagep->setBoostLevel(boost_priority);
 	}
 	else
 	{
 		//by default, the texure can not be removed from memory even if it is not used.
 		//here turn this off
-		//if this texture should be set to NO_DELETE, either pass level_immediate == TRUE here, or call setNoDelete() afterwards.
+		//if this texture should be set to NO_DELETE, call setNoDelete() afterwards.
 		imagep->forceActive() ;
 	}
 
@@ -1286,7 +1294,7 @@ void LLUIImageList::cleanUp()
 	mUITextureList.clear() ;
 }
 
-LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id)
+LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id, S32 priority)
 {
 	// use id as image name
 	std::string image_name = image_id.asString();
@@ -1298,10 +1306,12 @@ LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id)
 		return found_it->second;
 	}
 
-	return loadUIImageByID(image_id);
+	const BOOL use_mips = FALSE;
+	const LLRect scale_rect = LLRect::null;
+	return loadUIImageByID(image_id, use_mips, scale_rect, priority);
 }
 
-LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name)
+LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priority)
 {
 	// look for existing image
 	uuid_ui_image_map_t::iterator found_it = mUIImages.find(image_name);
@@ -1310,18 +1320,24 @@ LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name)
 		return found_it->second;
 	}
 
-	return loadUIImageByName(image_name, image_name);
+	const BOOL use_mips = FALSE;
+	const LLRect scale_rect = LLRect::null;
+	return loadUIImageByName(image_name, image_name, use_mips, scale_rect, priority);
 }
 
-LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect)
+LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename,
+											  BOOL use_mips, const LLRect& scale_rect, S32 boost_priority )
 {
-	LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, IMMEDIATE_YES);
+	if (boost_priority == 0) boost_priority = LLViewerFetchedTexture::BOOST_UI;
+	LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, boost_priority);
 	return loadUIImage(imagep, name, use_mips, scale_rect);
 }
 
-LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, BOOL use_mips, const LLRect& scale_rect)
+LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id,
+											BOOL use_mips, const LLRect& scale_rect, S32 boost_priority)
 {
-	LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, IMMEDIATE_YES);
+	if (boost_priority == 0) boost_priority = LLViewerFetchedTexture::BOOST_UI;
+	LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, boost_priority);
 	return loadUIImage(imagep, id.asString(), use_mips, scale_rect);
 }
 
@@ -1332,11 +1348,11 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st
 	imagep->setAddressMode(LLTexUnit::TAM_CLAMP);
 
 	//all UI images are non-deletable
-	imagep->setNoDelete() ;
+	imagep->setNoDelete();
 
 	LLUIImagePtr new_imagep = new LLUIImage(name, imagep);
 	mUIImages.insert(std::make_pair(name, new_imagep));
-	mUITextureList.push_back(imagep) ;
+	mUITextureList.push_back(imagep);
 
 	LLUIImageLoadData* datap = new LLUIImageLoadData;
 	datap->mImageName = name;
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 11d1dd855fab40ae2be32bc7ce6e7fff8b6c62da..fda57ce981bd5fe6e3bf90684bc31c955660b9b9 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -202,8 +202,8 @@ class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIIm
 {
 public:
 	// LLImageProviderInterface
-	LLUIImagePtr getUIImageByID(const LLUUID& id);
-	LLUIImagePtr getUIImage(const std::string& name);
+	/*virtual*/ LLUIImagePtr getUIImageByID(const LLUUID& id, S32 priority);
+	/*virtual*/ LLUIImagePtr getUIImage(const std::string& name, S32 priority);
 	void cleanUp();
 
 	bool initFromFile();
@@ -212,8 +212,10 @@ class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIIm
 	
 	static void onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
 private:
-	LLUIImagePtr loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null);
-	LLUIImagePtr loadUIImageByID(const LLUUID& id, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null);
+	LLUIImagePtr loadUIImageByName(const std::string& name, const std::string& filename,
+								   BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, S32 boost_priority = 0);
+	LLUIImagePtr loadUIImageByID(const LLUUID& id,
+								 BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, S32 boost_priority = 0);
 
 	LLUIImagePtr loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null);
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 72e40e30302025d3b4c6741a516edc0d22a57496..c1535b48dc4154511ce958460fd30adf8b9cb3ff 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -32,6 +32,10 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
 // system library includes
 #include <stdio.h>
 #include <iostream>
@@ -138,7 +142,6 @@
 #include "llstatview.h"
 #include "llsurface.h"
 #include "llsurfacepatch.h"
-#include "llimview.h"
 #include "lltexlayer.h"
 #include "lltextbox.h"
 #include "lltexturecache.h"
@@ -195,6 +198,7 @@
 #include "llfloaternotificationsconsole.h"
 
 #include "llnearbychat.h"
+#include "llviewerwindowlistener.h"
 
 #if LL_WINDOWS
 #include <tchar.h> // For Unicode conversion methods
@@ -1204,7 +1208,8 @@ LLViewerWindow::LLViewerWindow(
 	mResDirty(false),
 	mStatesDirty(false),
 	mIsFullscreenChecked(false),
-	mCurrResolutionIndex(0)
+	mCurrResolutionIndex(0),
+    mViewerWindowListener(new LLViewerWindowListener("LLViewerWindow", this))
 {
 	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
 	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
@@ -1513,11 +1518,12 @@ void LLViewerWindow::initWorldUI()
 	getRootView()->addChild(gMorphView);
 
 	// Make space for nav bar.
+	LLNavigationBar* navbar = LLNavigationBar::getInstance();
 	LLRect floater_view_rect = gFloaterView->getRect();
 	LLRect notify_view_rect = gNotifyBoxView->getRect();
-	floater_view_rect.mTop -= NAVIGATION_BAR_HEIGHT;
+	floater_view_rect.mTop -= navbar->getDefNavBarHeight();
 	floater_view_rect.mBottom += LLBottomTray::getInstance()->getRect().getHeight();
-	notify_view_rect.mTop -= NAVIGATION_BAR_HEIGHT;
+	notify_view_rect.mTop -= navbar->getDefNavBarHeight();
 	notify_view_rect.mBottom += LLBottomTray::getInstance()->getRect().getHeight();
 	gFloaterView->setRect(floater_view_rect);
 	gNotifyBoxView->setRect(notify_view_rect);
@@ -1544,20 +1550,19 @@ void LLViewerWindow::initWorldUI()
 	gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
 
 	// Navigation bar
-
-	LLNavigationBar* navbar = LLNavigationBar::getInstance();
 	navbar->reshape(root_rect.getWidth(), navbar->getRect().getHeight(), TRUE); // *TODO: redundant?
 	navbar->translate(0, root_rect.getHeight() - menu_bar_height - navbar->getRect().getHeight()); // FIXME
 	navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
+
 	
 	if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
 	{
-		navbar->showNavigationPanel(FALSE);
+		toggle_show_navigation_panel(LLSD(0));
 	}
 
 	if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"))
 	{
-		navbar->showFavoritesPanel(FALSE);
+		toggle_show_favorites_panel(LLSD(0));
 	}
 
 	if (!gSavedSettings.getBOOL("ShowCameraButton"))
@@ -1627,6 +1632,14 @@ void LLViewerWindow::shutdownViews()
 	{
 		gMorphView->setVisible(FALSE);
 	}
+
+	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
+	// will crump with LL_ERRS.
+	LLModalDialog::shutdownModals();
+	
+	// destroy the nav bar, not currently part of gViewerWindow
+	// *TODO: Make LLNavigationBar part of gViewerWindow
+	delete LLNavigationBar::getInstance();
 	
 	// Delete all child views.
 	delete mRootView;
@@ -2411,19 +2424,35 @@ void LLViewerWindow::updateUI()
 	BOOL handled_by_top_ctrl = FALSE;
 	LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
 	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+	LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
+
+	//FIXME: only include captor and captor's ancestors if mouse is truly over them --RN
 
 	//build set of views containing mouse cursor by traversing UI hierarchy and testing 
 	//screen rect against mouse cursor
 	view_handle_set_t mouse_hover_set;
 
-	// start at current mouse captor (if is a view) or UI root
-	LLView* root_view = NULL;
-	root_view = dynamic_cast<LLView*>(mouse_captor);
+	// constraint mouse enter events to children of mouse captor
+	LLView* root_view = captor_view;
+
+	// if mouse captor doesn't exist or isn't a LLView
+	// then allow mouse enter events on entire UI hierarchy
 	if (!root_view)
 	{
 		root_view = mRootView;
 	}
 
+	// include all ancestors of captor_view as automatically having mouse
+	if (captor_view)
+	{
+		LLView* captor_parent_view = captor_view->getParent();
+		while(captor_parent_view)
+		{
+			mouse_hover_set.insert(captor_parent_view->getHandle());
+			captor_parent_view = captor_parent_view->getParent();
+		}
+	}
+
 	// aggregate visible views that contain mouse cursor in display order
 
 	// while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 231b857d1f0497420c99e48b4f88f9900de9c9e1..d7c403739e492047131fa101ea03da2db3aad9e9 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -53,6 +53,8 @@
 
 #include <boost/function.hpp>
 #include <boost/signals2.hpp>
+#include <boost/scoped_ptr.hpp>
+
 
 class LLView;
 class LLViewerObject;
@@ -65,6 +67,7 @@ class LLImageRaw;
 class LLHUDIcon;
 class LLWindow;
 class LLRootView;
+class LLViewerWindowListener;
 
 #define PICK_HALF_WIDTH 5
 #define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1)
@@ -456,6 +459,8 @@ class LLViewerWindow : public LLWindowCallbacks
 	bool			mIsFullscreenChecked; // Did the user check the fullscreen checkbox in the display settings
 	U32			mCurrResolutionIndex;
 
+    boost::scoped_ptr<LLViewerWindowListener> mViewerWindowListener;
+
 protected:
 	static std::string sSnapshotBaseName;
 	static std::string sSnapshotDir;
diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..317e361c804d5ca93d16fe880f42307973bfe248
--- /dev/null
+++ b/indra/newview/llviewerwindowlistener.cpp
@@ -0,0 +1,87 @@
+/**
+ * @file   llviewerwindowlistener.cpp
+ * @author Nat Goodspeed
+ * @date   2009-06-30
+ * @brief  Implementation for llviewerwindowlistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llviewerwindowlistener.h"
+// STL headers
+#include <map>
+// std headers
+// external library headers
+// other Linden headers
+#include "llviewerwindow.h"
+
+LLViewerWindowListener::LLViewerWindowListener(const std::string& pumpname, LLViewerWindow* llviewerwindow):
+    LLDispatchListener(pumpname, "op"),
+    mViewerWindow(llviewerwindow)
+{
+    // add() every method we want to be able to invoke via this event API.
+    LLSD saveSnapshotArgs;
+    saveSnapshotArgs["filename"] = LLSD::String();
+    saveSnapshotArgs["reply"] = LLSD::String();
+    // The following are optional, so don't build them into required prototype.
+//  saveSnapshotArgs["width"] = LLSD::Integer();
+//  saveSnapshotArgs["height"] = LLSD::Integer();
+//  saveSnapshotArgs["showui"] = LLSD::Boolean();
+//  saveSnapshotArgs["rebuild"] = LLSD::Boolean();
+//  saveSnapshotArgs["type"] = LLSD::String();
+    add("saveSnapshot", &LLViewerWindowListener::saveSnapshot, saveSnapshotArgs);
+    add("requestReshape", &LLViewerWindowListener::requestReshape);
+}
+
+void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
+{
+    LLReqID reqid(event);
+    typedef std::map<LLSD::String, LLViewerWindow::ESnapshotType> TypeMap;
+    TypeMap types;
+#define tp(name) types[#name] = LLViewerWindow::SNAPSHOT_TYPE_##name
+    tp(COLOR);
+    tp(DEPTH);
+    tp(OBJECT_ID);
+#undef  tp
+    // Our add() call should ensure that the incoming LLSD does in fact
+    // contain our required arguments. Deal with the optional ones.
+    S32 width (mViewerWindow->getWindowDisplayWidth());
+    S32 height(mViewerWindow->getWindowDisplayHeight());
+    if (event.has("width"))
+        width = event["width"].asInteger();
+    if (event.has("height"))
+        height = event["height"].asInteger();
+    // showui defaults to true, requiring special treatment
+    bool showui = true;
+    if (event.has("showui"))
+        showui = event["showui"].asBoolean();
+    bool rebuild(event["rebuild"]); // defaults to false
+    LLViewerWindow::ESnapshotType type(LLViewerWindow::SNAPSHOT_TYPE_COLOR);
+    if (event.has("type"))
+    {
+        TypeMap::const_iterator found = types.find(event["type"]);
+        if (found == types.end())
+        {
+            LL_ERRS("LLViewerWindowListener") << "LLViewerWindowListener::saveSnapshot(): "
+                                              << "unrecognized type " << event["type"] << LL_ENDL;
+        }
+        type = found->second;
+    }
+    bool ok = mViewerWindow->saveSnapshot(event["filename"], width, height, showui, rebuild, type);
+    LLSD response(reqid.makeResponse());
+    response["ok"] = ok;
+    LLEventPumps::instance().obtain(event["reply"]).post(response);
+}
+
+void LLViewerWindowListener::requestReshape(LLSD const & event_data) const
+{
+	if(event_data.has("w") && event_data.has("h"))
+	{
+		mViewerWindow->reshape(event_data["w"].asInteger(), event_data["h"].asInteger());
+	}
+}
diff --git a/indra/newview/llviewerwindowlistener.h b/indra/newview/llviewerwindowlistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..59c636ecec85b5b683019d3d7475b45dbe7673d4
--- /dev/null
+++ b/indra/newview/llviewerwindowlistener.h
@@ -0,0 +1,35 @@
+/**
+ * @file   llviewerwindowlistener.h
+ * @author Nat Goodspeed
+ * @date   2009-06-30
+ * @brief  Event API for subset of LLViewerWindow methods
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLVIEWERWINDOWLISTENER_H)
+#define LL_LLVIEWERWINDOWLISTENER_H
+
+#include "lleventdispatcher.h"
+
+class LLViewerWindow;
+class LLSD;
+
+/// Listen on an LLEventPump with specified name for LLViewerWindow request events.
+class LLViewerWindowListener: public LLDispatchListener
+{
+public:
+    /// Specify the pump name on which to listen, and bind the LLViewerWindow
+    /// instance to use (e.g. gViewerWindow).
+    LLViewerWindowListener(const std::string& pumpname, LLViewerWindow* llviewerwindow);
+
+private:
+    void saveSnapshot(const LLSD& event) const;
+    void requestReshape(LLSD const & event_data) const;
+
+    LLViewerWindow* mViewerWindow;
+};
+
+#endif /* ! defined(LL_LLVIEWERWINDOWLISTENER_H) */
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 469aef62093d0ac7fe952ec5acbb33cb7833a5d6..4bf66ba17e08ea1230766c3a56ad18e91092c072 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -30,6 +30,12 @@
  * $/LicenseInfo$
  */
 
+#if LL_MSVC
+// disable warning about boost::lexical_cast returning uninitialized data
+// when it fails to parse the string
+#pragma warning (disable:4701)
+#endif
+
 #include "llviewerprecompiledheaders.h"
 
 #include "llvoavatar.h"
@@ -87,7 +93,12 @@
 #include "llvoiceclient.h"
 #include "llvoicevisualizer.h" // Ventrella
 
-#include "boost/lexical_cast.hpp"
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
+#include <boost/lexical_cast.hpp>
 
 using namespace LLVOAvatarDefines;
 
@@ -2437,28 +2448,20 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
 		}
 		else
 		{
-			F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME);
-			F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME);
-			F32 morph_amt;
-			if (last_blend_frac == 1.f)
-			{
-				morph_amt = 1.f;
-			}
-			else
-			{
-				morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac);
-			}
-
+			F32 morph_amt = calcMorphAmount();
 			LLVisualParam *param;
 
-			// animate only top level params
-			for (param = getFirstVisualParam();
-				 param;
-				 param = getNextVisualParam())
+			if (!isSelf())
 			{
-				if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
+				// animate only top level params for non-self avatars
+				for (param = getFirstVisualParam();
+					 param;
+					 param = getNextVisualParam())
 				{
-					param->animate(morph_amt, mAppearanceAnimSetByUser);
+					if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
+					{
+						param->animate(morph_amt, mAppearanceAnimSetByUser);
+					}
 				}
 			}
 
@@ -2476,6 +2479,25 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
 	}
 }
 
+F32 LLVOAvatar::calcMorphAmount()
+{
+	F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32();
+	F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME);
+	F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME);
+
+	F32 morph_amt;
+	if (last_blend_frac == 1.f)
+	{
+		morph_amt = 1.f;
+	}
+	else
+	{
+		morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac);
+	}
+
+	return morph_amt;
+}
+
 void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
 {
 	// Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync
@@ -6389,6 +6411,11 @@ LLBBox LLVOAvatar::getHUDBBox() const
 				 ++attachment_iter)
 			{
 				const LLViewerObject* attached_object = (*attachment_iter);
+				if (attached_object == NULL)
+				{
+					llwarns << "HUD attached object is NULL!" << llendl;
+					continue;
+				}
 				// initialize bounding box to contain identity orientation and center point for attached object
 				bbox.addPointLocal(attached_object->getPosition());
 				// add rotated bounding box for attached object
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index e3add8aa78f2dcd3d802d87133dcaa7e0adbbc94..f7c794defeb48da8f521cc2e6f927d982d29b65e 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -205,7 +205,7 @@ class LLVOAvatar :
 	virtual BOOL 	updateCharacter(LLAgent &agent);
 	void 			idleUpdateVoiceVisualizer(bool voice_enabled);
 	void 			idleUpdateMisc(bool detailed_update);
-	void 			idleUpdateAppearanceAnimation();
+	virtual void	idleUpdateAppearanceAnimation();
 	void 			idleUpdateLipSync(bool voice_enabled);
 	void 			idleUpdateLoadingEffect();
 	void 			idleUpdateWindEffect();
@@ -250,6 +250,7 @@ class LLVOAvatar :
 	virtual BOOL	updateIsFullyLoaded();
 	BOOL			processFullyLoadedChange(bool loading);
 	void			updateRuthTimer(bool loading);
+	F32 			calcMorphAmount();
 private:
 	BOOL			mFullyLoaded;
 	BOOL			mPreviousFullyLoaded;
@@ -276,7 +277,7 @@ class LLVOAvatar :
 protected:
 	static BOOL			parseSkeletonFile(const std::string& filename);
 	void				buildCharacter();
-	BOOL				loadAvatar();
+	virtual BOOL		loadAvatar();
 
 	BOOL				setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
 	BOOL				buildSkeleton(const LLVOAvatarSkeletonInfo *info);
diff --git a/indra/newview/llvoavatardefines.cpp b/indra/newview/llvoavatardefines.cpp
index 17b502ae80e9c51f914fd99948a2c79b0648a638..5624f19c8d040fffc9e74db8387f8949c699a68c 100644
--- a/indra/newview/llvoavatardefines.cpp
+++ b/indra/newview/llvoavatardefines.cpp
@@ -68,9 +68,9 @@ LLVOAvatarDictionary::Textures::Textures()
 	addEntry(TEX_EYES_ALPHA,                  new TextureEntry("eyes_alpha",       TRUE,  BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID",     WT_ALPHA));
 	addEntry(TEX_HAIR_ALPHA,                  new TextureEntry("hair_alpha",       TRUE,  BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID",     WT_ALPHA));
 
-	addEntry(TEX_HEAD_TATTOO,                 new TextureEntry("head_tattoo",      TRUE,  BAKED_NUM_INDICES, "UIImgDefaultTattooUUID",     WT_TATTOO));
-	addEntry(TEX_UPPER_TATTOO,                new TextureEntry("upper_tattoo",     TRUE,  BAKED_NUM_INDICES, "UIImgDefaultTattooUUID",     WT_TATTOO));
-	addEntry(TEX_LOWER_TATTOO,                new TextureEntry("lower_tattoo",     TRUE,  BAKED_NUM_INDICES, "UIImgDefaultTattooUUID",     WT_TATTOO));
+	addEntry(TEX_HEAD_TATTOO,                 new TextureEntry("head_tattoo",      TRUE,  BAKED_NUM_INDICES, "",     WT_TATTOO));
+	addEntry(TEX_UPPER_TATTOO,                new TextureEntry("upper_tattoo",     TRUE,  BAKED_NUM_INDICES, "",     WT_TATTOO));
+	addEntry(TEX_LOWER_TATTOO,                new TextureEntry("lower_tattoo",     TRUE,  BAKED_NUM_INDICES, "",     WT_TATTOO));
 
 	addEntry(TEX_HEAD_BAKED,                  new TextureEntry("head-baked",       FALSE, BAKED_HEAD));
 	addEntry(TEX_UPPER_BAKED,                 new TextureEntry("upper-baked",      FALSE, BAKED_UPPER));
@@ -248,8 +248,6 @@ EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name)
 //static
 const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index)
 {
-	/* switch( index )
-		case TEX_UPPER_SHIRT:		return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") ); */
 	const TextureEntry *texture_dict = getInstance()->getTexture(index);
 	const std::string &default_image_name = texture_dict->mDefaultImageName;
 	if (default_image_name == "")
@@ -265,9 +263,6 @@ const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index)
 // static
 EWearableType LLVOAvatarDictionary::getTEWearableType(ETextureIndex index )
 {
-	/* switch(index)
-		case TEX_UPPER_SHIRT:
-			return WT_SHIRT; */
 	return getInstance()->getTexture(index)->mWearableType;
 }
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 964b16df046e761d65237a9fed6ae723e29565e2..758db538a28f4cbddb991e7908c9fa91b726d9a1 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -30,6 +30,12 @@
  * $/LicenseInfo$
  */
 
+#if LL_MSVC
+// disable warning about boost::lexical_cast returning uninitialized data
+// when it fails to parse the string
+#pragma warning (disable:4701)
+#endif
+
 #include "llviewerprecompiledheaders.h"
 
 #include "llvoavatarself.h"
@@ -84,7 +90,12 @@
 #include "llvoicevisualizer.h" // Ventrella
 #include "llappearancemgr.h"
 
-#include "boost/lexical_cast.hpp"
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
+#include <boost/lexical_cast.hpp>
 
 using namespace LLVOAvatarDefines;
 
@@ -182,6 +193,25 @@ void LLVOAvatarSelf::markDead()
 	LLVOAvatar::markDead();
 }
 
+/*virtual*/ BOOL LLVOAvatarSelf::loadAvatar()
+{
+	BOOL success = LLVOAvatar::loadAvatar();
+
+	// set all parameters sotred directly in the avatar to have
+	// the isSelfParam to be TRUE - this is used to prevent
+	// them from being animated or trigger accidental rebakes
+	// when we copy params from the wearable to the base avatar.
+	for (LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam(); 
+		 param;
+		 param = (LLViewerVisualParam*) getNextVisualParam())
+	{
+		param->setIsDummy(TRUE);
+	}
+
+	return success;
+}
+
+
 BOOL LLVOAvatarSelf::loadAvatarSelf()
 {
 	BOOL success = TRUE;
@@ -693,16 +723,23 @@ void LLVOAvatarSelf::updateVisualParams()
 		}
 	}
 
-	LLWearable *shape = gAgentWearables.getWearable(WT_SHAPE,0);
-	if (shape)
-	{
-		F32 gender = shape->getVisualParamWeight(80); // param 80 == gender
-		setVisualParamWeight("male",gender ,TRUE);
-	}
-
 	LLVOAvatar::updateVisualParams();
 }
 
+/*virtual*/
+void LLVOAvatarSelf::idleUpdateAppearanceAnimation()
+{
+	// Animate all top-level wearable visual parameters
+	gAgentWearables.animateAllWearableParams(calcMorphAmount(), mAppearanceAnimSetByUser);
+
+	// apply wearable visual params to avatar
+	updateVisualParams();
+
+	//allow avatar to process updates
+	LLVOAvatar::idleUpdateAppearanceAnimation();
+
+}
+
 // virtual
 void LLVOAvatarSelf::requestStopMotion(LLMotion* motion)
 {
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index a555d04a6331d4105725ec4171e044b4924a0e37..6e52b336348848c5307a2446963b49cd2fc9e845 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -57,6 +57,7 @@ class LLVOAvatarSelf :
 	virtual void			markDead();
 	virtual void 		initInstance(); // Called after construction to initialize the class.
 protected:
+	/*virtual*/ BOOL		loadAvatar();
 	BOOL					loadAvatarSelf();
 	BOOL					buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info);
 	BOOL					buildMenus();
@@ -89,6 +90,7 @@ class LLVOAvatarSelf :
 	/*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE );
 	/*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE );
 	/*virtual*/ void updateVisualParams();
+	/*virtual*/ void idleUpdateAppearanceAnimation();
 
 private:
 	// helper function. Passed in param is assumed to be in avatar's parameter list.
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..96fcf61e62899c2b41bce022335a8eb435f3e531
--- /dev/null
+++ b/indra/newview/llvoicechannel.cpp
@@ -0,0 +1,872 @@
+/** 
+ * @file llvoicechannel.cpp
+ * @brief Voice Channel related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagent.h"
+#include "llfloaterreg.h"
+#include "llimview.h"
+#include "llnotifications.h"
+#include "llpanel.h"
+#include "llrecentpeople.h"
+#include "llviewercontrol.h"
+#include "llvoicechannel.h"
+
+
+LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
+LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
+LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
+LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
+
+BOOL LLVoiceChannel::sSuspended = FALSE;
+
+//
+// Constants
+//
+const U32 DEFAULT_RETRIES_COUNT = 3;
+
+
+class LLVoiceCallCapResponder : public LLHTTPClient::Responder
+{
+public:
+	LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
+
+	virtual void error(U32 status, const std::string& reason);	// called with bad status codes
+	virtual void result(const LLSD& content);
+
+private:
+	LLUUID mSessionID;
+};
+
+
+void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
+{
+	llwarns << "LLVoiceCallCapResponder::error("
+		<< status << ": " << reason << ")"
+		<< llendl;
+	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
+	if ( channelp )
+	{
+		if ( 403 == status )
+		{
+			//403 == no ability
+			LLNotifications::instance().add(
+				"VoiceNotAllowed",
+				channelp->getNotifyArgs());
+		}
+		else
+		{
+			LLNotifications::instance().add(
+				"VoiceCallGenericError",
+				channelp->getNotifyArgs());
+		}
+		channelp->deactivate();
+	}
+}
+
+void LLVoiceCallCapResponder::result(const LLSD& content)
+{
+	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
+	if (channelp)
+	{
+		//*TODO: DEBUG SPAM
+		LLSD::map_const_iterator iter;
+		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
+		{
+			llinfos << "LLVoiceCallCapResponder::result got " 
+				<< iter->first << llendl;
+		}
+
+		channelp->setChannelInfo(
+			content["voice_credentials"]["channel_uri"].asString(),
+			content["voice_credentials"]["channel_credentials"].asString());
+	}
+}
+
+//
+// LLVoiceChannel
+//
+LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) : 
+	mSessionID(session_id), 
+	mState(STATE_NO_CHANNEL_INFO), 
+	mSessionName(session_name),
+	mIgnoreNextSessionLeave(FALSE)
+{
+	mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
+
+	if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
+	{
+		// a voice channel already exists for this session id, so this instance will be orphaned
+		// the end result should simply be the failure to make voice calls
+		llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
+	}
+
+	LLVoiceClient::getInstance()->addObserver(this);
+}
+
+LLVoiceChannel::~LLVoiceChannel()
+{
+	// Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
+	if(gVoiceClient)
+	{
+		gVoiceClient->removeObserver(this);
+	}
+	
+	sVoiceChannelMap.erase(mSessionID);
+	sVoiceChannelURIMap.erase(mURI);
+}
+
+void LLVoiceChannel::setChannelInfo(
+	const std::string& uri,
+	const std::string& credentials)
+{
+	setURI(uri);
+
+	mCredentials = credentials;
+
+	if (mState == STATE_NO_CHANNEL_INFO)
+	{
+		if (mURI.empty())
+		{
+			LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
+			llwarns << "Received empty URI for channel " << mSessionName << llendl;
+			deactivate();
+		}
+		else if (mCredentials.empty())
+		{
+			LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
+			llwarns << "Received empty credentials for channel " << mSessionName << llendl;
+			deactivate();
+		}
+		else
+		{
+			setState(STATE_READY);
+
+			// if we are supposed to be active, reconnect
+			// this will happen on initial connect, as we request credentials on first use
+			if (sCurrentVoiceChannel == this)
+			{
+				// just in case we got new channel info while active
+				// should move over to new channel
+				activate();
+			}
+		}
+	}
+}
+
+void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
+{
+	if (channelURI != mURI)
+	{
+		return;
+	}
+
+	if (type < BEGIN_ERROR_STATUS)
+	{
+		handleStatusChange(type);
+	}
+	else
+	{
+		handleError(type);
+	}
+}
+
+void LLVoiceChannel::handleStatusChange(EStatusType type)
+{
+	// status updates
+	switch(type)
+	{
+	case STATUS_LOGIN_RETRY:
+		//mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
+		LLNotifications::instance().add("VoiceLoginRetry");
+		break;
+	case STATUS_LOGGED_IN:
+		//if (!mLoginNotificationHandle.isDead())
+		//{
+		//	LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
+		//	if (notifyp)
+		//	{
+		//		notifyp->close();
+		//	}
+		//	mLoginNotificationHandle.markDead();
+		//}
+		break;
+	case STATUS_LEFT_CHANNEL:
+		if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
+		{
+			// if forceably removed from channel
+			// update the UI and revert to default channel
+			LLNotifications::instance().add("VoiceChannelDisconnected", mNotifyArgs);
+			deactivate();
+		}
+		mIgnoreNextSessionLeave = FALSE;
+		break;
+	case STATUS_JOINING:
+		if (callStarted())
+		{
+			setState(STATE_RINGING);
+		}
+		break;
+	case STATUS_JOINED:
+		if (callStarted())
+		{
+			setState(STATE_CONNECTED);
+		}
+	default:
+		break;
+	}
+}
+
+// default behavior is to just deactivate channel
+// derived classes provide specific error messages
+void LLVoiceChannel::handleError(EStatusType type)
+{
+	deactivate();
+	setState(STATE_ERROR);
+}
+
+BOOL LLVoiceChannel::isActive()
+{ 
+	// only considered active when currently bound channel matches what our channel
+	return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI; 
+}
+
+BOOL LLVoiceChannel::callStarted()
+{
+	return mState >= STATE_CALL_STARTED;
+}
+
+void LLVoiceChannel::deactivate()
+{
+	if (mState >= STATE_RINGING)
+	{
+		// ignore session leave event
+		mIgnoreNextSessionLeave = TRUE;
+	}
+
+	if (callStarted())
+	{
+		setState(STATE_HUNG_UP);
+		// mute the microphone if required when returning to the proximal channel
+		if (gSavedSettings.getBOOL("AutoDisengageMic") && sCurrentVoiceChannel == this)
+		{
+			gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
+		}
+	}
+
+	if (sCurrentVoiceChannel == this)
+	{
+		// default channel is proximal channel
+		sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
+		sCurrentVoiceChannel->activate();
+	}
+}
+
+void LLVoiceChannel::activate()
+{
+	if (callStarted())
+	{
+		return;
+	}
+
+	// deactivate old channel and mark ourselves as the active one
+	if (sCurrentVoiceChannel != this)
+	{
+		// mark as current before deactivating the old channel to prevent
+		// activating the proximal channel between IM calls
+		LLVoiceChannel* old_channel = sCurrentVoiceChannel;
+		sCurrentVoiceChannel = this;
+		if (old_channel)
+		{
+			old_channel->deactivate();
+		}
+	}
+
+	if (mState == STATE_NO_CHANNEL_INFO)
+	{
+		// responsible for setting status to active
+		getChannelInfo();
+	}
+	else
+	{
+		setState(STATE_CALL_STARTED);
+	}
+}
+
+void LLVoiceChannel::getChannelInfo()
+{
+	// pretend we have everything we need
+	if (sCurrentVoiceChannel == this)
+	{
+		setState(STATE_CALL_STARTED);
+	}
+}
+
+//static 
+LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
+{
+	voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
+	if (found_it == sVoiceChannelMap.end())
+	{
+		return NULL;
+	}
+	else
+	{
+		return found_it->second;
+	}
+}
+
+//static 
+LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
+{
+	voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
+	if (found_it == sVoiceChannelURIMap.end())
+	{
+		return NULL;
+	}
+	else
+	{
+		return found_it->second;
+	}
+}
+
+void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
+{
+	sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
+	mSessionID = new_session_id;
+	sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
+}
+
+void LLVoiceChannel::setURI(std::string uri)
+{
+	sVoiceChannelURIMap.erase(mURI);
+	mURI = uri;
+	sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
+}
+
+void LLVoiceChannel::setState(EState state)
+{
+	switch(state)
+	{
+	case STATE_RINGING:
+		gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
+		break;
+	case STATE_CONNECTED:
+		gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
+		break;
+	case STATE_HUNG_UP:
+		gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
+		break;
+	default:
+		break;
+	}
+
+	mState = state;
+}
+
+void LLVoiceChannel::toggleCallWindowIfNeeded(EState state)
+{
+	if (state == STATE_CONNECTED)
+	{
+		LLFloaterReg::showInstance("voice_call", mSessionID);
+	}
+	// By checking that current state is CONNECTED we make sure that the call window
+	// has been shown, hence there's something to hide. This helps when user presses
+	// the "End call" button right after initiating the call.
+	// *TODO: move this check to LLFloaterCall?
+	else if (state == STATE_HUNG_UP && mState == STATE_CONNECTED)
+	{
+		LLFloaterReg::hideInstance("voice_call", mSessionID);
+	}
+}
+
+//static
+void LLVoiceChannel::initClass()
+{
+	sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
+}
+
+
+//static 
+void LLVoiceChannel::suspend()
+{
+	if (!sSuspended)
+	{
+		sSuspendedVoiceChannel = sCurrentVoiceChannel;
+		sSuspended = TRUE;
+	}
+}
+
+//static 
+void LLVoiceChannel::resume()
+{
+	if (sSuspended)
+	{
+		if (gVoiceClient->voiceEnabled())
+		{
+			if (sSuspendedVoiceChannel)
+			{
+				sSuspendedVoiceChannel->activate();
+			}
+			else
+			{
+				LLVoiceChannelProximal::getInstance()->activate();
+			}
+		}
+		sSuspended = FALSE;
+	}
+}
+
+
+//
+// LLVoiceChannelGroup
+//
+
+LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) : 
+	LLVoiceChannel(session_id, session_name)
+{
+	mRetries = DEFAULT_RETRIES_COUNT;
+	mIsRetrying = FALSE;
+}
+
+void LLVoiceChannelGroup::deactivate()
+{
+	if (callStarted())
+	{
+		LLVoiceClient::getInstance()->leaveNonSpatialChannel();
+	}
+	LLVoiceChannel::deactivate();
+}
+
+void LLVoiceChannelGroup::activate()
+{
+	if (callStarted()) return;
+
+	LLVoiceChannel::activate();
+
+	if (callStarted())
+	{
+		// we have the channel info, just need to use it now
+		LLVoiceClient::getInstance()->setNonSpatialChannel(
+			mURI,
+			mCredentials);
+
+#if 0 // *TODO
+		if (!gAgent.isInGroup(mSessionID)) // ad-hoc channel
+		{
+			// Add the party to the list of people with which we've recently interacted.
+			for (/*people in the chat*/)
+				LLRecentPeople::instance().add(buddy_id);
+		}
+#endif
+	}
+}
+
+void LLVoiceChannelGroup::getChannelInfo()
+{
+	LLViewerRegion* region = gAgent.getRegion();
+	if (region)
+	{
+		std::string url = region->getCapability("ChatSessionRequest");
+		LLSD data;
+		data["method"] = "call";
+		data["session-id"] = mSessionID;
+		LLHTTPClient::post(url,
+						   data,
+						   new LLVoiceCallCapResponder(mSessionID));
+	}
+}
+
+void LLVoiceChannelGroup::setChannelInfo(
+	const std::string& uri,
+	const std::string& credentials)
+{
+	setURI(uri);
+
+	mCredentials = credentials;
+
+	if (mState == STATE_NO_CHANNEL_INFO)
+	{
+		if(!mURI.empty() && !mCredentials.empty())
+		{
+			setState(STATE_READY);
+
+			// if we are supposed to be active, reconnect
+			// this will happen on initial connect, as we request credentials on first use
+			if (sCurrentVoiceChannel == this)
+			{
+				// just in case we got new channel info while active
+				// should move over to new channel
+				activate();
+			}
+		}
+		else
+		{
+			//*TODO: notify user
+			llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
+			deactivate();
+		}
+	}
+	else if ( mIsRetrying )
+	{
+		// we have the channel info, just need to use it now
+		LLVoiceClient::getInstance()->setNonSpatialChannel(
+			mURI,
+			mCredentials);
+	}
+}
+
+void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
+{
+	// status updates
+	switch(type)
+	{
+	case STATUS_JOINED:
+		mRetries = 3;
+		mIsRetrying = FALSE;
+	default:
+		break;
+	}
+
+	LLVoiceChannel::handleStatusChange(type);
+}
+
+void LLVoiceChannelGroup::handleError(EStatusType status)
+{
+	std::string notify;
+	switch(status)
+	{
+	case ERROR_CHANNEL_LOCKED:
+	case ERROR_CHANNEL_FULL:
+		notify = "VoiceChannelFull";
+		break;
+	case ERROR_NOT_AVAILABLE:
+		//clear URI and credentials
+		//set the state to be no info
+		//and activate
+		if ( mRetries > 0 )
+		{
+			mRetries--;
+			mIsRetrying = TRUE;
+			mIgnoreNextSessionLeave = TRUE;
+
+			getChannelInfo();
+			return;
+		}
+		else
+		{
+			notify = "VoiceChannelJoinFailed";
+			mRetries = DEFAULT_RETRIES_COUNT;
+			mIsRetrying = FALSE;
+		}
+
+		break;
+
+	case ERROR_UNKNOWN:
+	default:
+		break;
+	}
+
+	// notification
+	if (!notify.empty())
+	{
+		LLNotificationPtr notification = LLNotifications::instance().add(notify, mNotifyArgs);
+		// echo to im window
+		gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
+	}
+
+	LLVoiceChannel::handleError(status);
+}
+
+void LLVoiceChannelGroup::setState(EState state)
+{
+	// HACK: Open/close the call window if needed.
+	toggleCallWindowIfNeeded(state);
+
+	switch(state)
+	{
+	case STATE_RINGING:
+		if ( !mIsRetrying )
+		{
+			gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
+		}
+
+		mState = state;
+		break;
+	default:
+		LLVoiceChannel::setState(state);
+	}
+}
+
+//
+// LLVoiceChannelProximal
+//
+LLVoiceChannelProximal::LLVoiceChannelProximal() : 
+	LLVoiceChannel(LLUUID::null, LLStringUtil::null)
+{
+	activate();
+}
+
+BOOL LLVoiceChannelProximal::isActive()
+{
+	return callStarted() && LLVoiceClient::getInstance()->inProximalChannel(); 
+}
+
+void LLVoiceChannelProximal::activate()
+{
+	if (callStarted()) return;
+
+	LLVoiceChannel::activate();
+
+	if (callStarted())
+	{
+		// this implicitly puts you back in the spatial channel
+		LLVoiceClient::getInstance()->leaveNonSpatialChannel();
+	}
+}
+
+void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
+{
+	if (!proximal)
+	{
+		return;
+	}
+
+	if (type < BEGIN_ERROR_STATUS)
+	{
+		handleStatusChange(type);
+	}
+	else
+	{
+		handleError(type);
+	}
+}
+
+void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
+{
+	// status updates
+	switch(status)
+	{
+	case STATUS_LEFT_CHANNEL:
+		// do not notify user when leaving proximal channel
+		return;
+	case STATUS_VOICE_DISABLED:
+		 gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
+		return;
+	default:
+		break;
+	}
+	LLVoiceChannel::handleStatusChange(status);
+}
+
+
+void LLVoiceChannelProximal::handleError(EStatusType status)
+{
+	std::string notify;
+	switch(status)
+	{
+	  case ERROR_CHANNEL_LOCKED:
+	  case ERROR_CHANNEL_FULL:
+		notify = "ProximalVoiceChannelFull";
+		break;
+	  default:
+		 break;
+	}
+
+	// notification
+	if (!notify.empty())
+	{
+		LLNotifications::instance().add(notify, mNotifyArgs);
+	}
+
+	LLVoiceChannel::handleError(status);
+}
+
+void LLVoiceChannelProximal::deactivate()
+{
+	if (callStarted())
+	{
+		setState(STATE_HUNG_UP);
+	}
+}
+
+
+//
+// LLVoiceChannelP2P
+//
+LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) : 
+		LLVoiceChannelGroup(session_id, session_name), 
+		mOtherUserID(other_user_id),
+		mReceivedCall(FALSE)
+{
+	// make sure URI reflects encoded version of other user's agent id
+	setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
+}
+
+void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
+{
+	// status updates
+	switch(type)
+	{
+	case STATUS_LEFT_CHANNEL:
+		if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
+		{
+			if (mState == STATE_RINGING)
+			{
+				// other user declined call
+				LLNotifications::instance().add("P2PCallDeclined", mNotifyArgs);
+			}
+			else
+			{
+				// other user hung up
+				LLNotifications::instance().add("VoiceChannelDisconnectedP2P", mNotifyArgs);
+			}
+			deactivate();
+		}
+		mIgnoreNextSessionLeave = FALSE;
+		return;
+	default:
+		break;
+	}
+
+	LLVoiceChannel::handleStatusChange(type);
+}
+
+void LLVoiceChannelP2P::handleError(EStatusType type)
+{
+	switch(type)
+	{
+	case ERROR_NOT_AVAILABLE:
+		LLNotifications::instance().add("P2PCallNoAnswer", mNotifyArgs);
+		break;
+	default:
+		break;
+	}
+
+	LLVoiceChannel::handleError(type);
+}
+
+void LLVoiceChannelP2P::activate()
+{
+	if (callStarted()) return;
+
+	LLVoiceChannel::activate();
+
+	if (callStarted())
+	{
+		// no session handle yet, we're starting the call
+		if (mSessionHandle.empty())
+		{
+			mReceivedCall = FALSE;
+			LLVoiceClient::getInstance()->callUser(mOtherUserID);
+		}
+		// otherwise answering the call
+		else
+		{
+			LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
+			
+			// using the session handle invalidates it.  Clear it out here so we can't reuse it by accident.
+			mSessionHandle.clear();
+		}
+
+		// Add the party to the list of people with which we've recently interacted.
+		LLRecentPeople::instance().add(mOtherUserID);
+	}
+}
+
+void LLVoiceChannelP2P::getChannelInfo()
+{
+	// pretend we have everything we need, since P2P doesn't use channel info
+	if (sCurrentVoiceChannel == this)
+	{
+		setState(STATE_CALL_STARTED);
+	}
+}
+
+// receiving session from other user who initiated call
+void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
+{ 
+	BOOL needs_activate = FALSE;
+	if (callStarted())
+	{
+		// defer to lower agent id when already active
+		if (mOtherUserID < gAgent.getID())
+		{
+			// pretend we haven't started the call yet, so we can connect to this session instead
+			deactivate();
+			needs_activate = TRUE;
+		}
+		else
+		{
+			// we are active and have priority, invite the other user again
+			// under the assumption they will join this new session
+			mSessionHandle.clear();
+			LLVoiceClient::getInstance()->callUser(mOtherUserID);
+			return;
+		}
+	}
+
+	mSessionHandle = handle;
+
+	// The URI of a p2p session should always be the other end's SIP URI.
+	if(!inURI.empty())
+	{
+		setURI(inURI);
+	}
+	else
+	{
+		setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
+	}
+	
+	mReceivedCall = TRUE;
+
+	if (needs_activate)
+	{
+		activate();
+	}
+}
+
+void LLVoiceChannelP2P::setState(EState state)
+{
+	// HACK: Open/close the call window if needed.
+	toggleCallWindowIfNeeded(state);
+
+	// you only "answer" voice invites in p2p mode
+	// so provide a special purpose message here
+	if (mReceivedCall && state == STATE_RINGING)
+	{
+		gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
+		mState = state;
+		return;
+	}
+	LLVoiceChannel::setState(state);
+}
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
new file mode 100644
index 0000000000000000000000000000000000000000..9966bdd5abff75798ab693808e037dae5196801b
--- /dev/null
+++ b/indra/newview/llvoicechannel.h
@@ -0,0 +1,168 @@
+/** 
+ * @file llvoicechannel.h
+ * @brief Voice channel related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_VOICECHANNEL_H
+#define LL_VOICECHANNEL_H
+
+#include "llhandle.h"
+#include "llvoiceclient.h"
+
+class LLPanel;
+
+class LLVoiceChannel : public LLVoiceClientStatusObserver
+{
+public:
+	typedef enum e_voice_channel_state
+	{
+		STATE_NO_CHANNEL_INFO,
+		STATE_ERROR,
+		STATE_HUNG_UP,
+		STATE_READY,
+		STATE_CALL_STARTED,
+		STATE_RINGING,
+		STATE_CONNECTED
+	} EState;
+
+	LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
+	virtual ~LLVoiceChannel();
+
+	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
+	virtual void handleStatusChange(EStatusType status);
+	virtual void handleError(EStatusType status);
+	virtual void deactivate();
+	virtual void activate();
+	virtual void setChannelInfo(
+		const std::string& uri,
+		const std::string& credentials);
+	virtual void getChannelInfo();
+	virtual BOOL isActive();
+	virtual BOOL callStarted();
+	const std::string& getSessionName() const { return mSessionName; }
+
+	const LLUUID getSessionID() { return mSessionID; }
+	EState getState() { return mState; }
+
+	void updateSessionID(const LLUUID& new_session_id);
+	const LLSD& getNotifyArgs() { return mNotifyArgs; }
+
+	static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
+	static LLVoiceChannel* getChannelByURI(std::string uri);
+	static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
+	static void initClass();
+	
+	static void suspend();
+	static void resume();
+
+protected:
+	virtual void setState(EState state);
+	void toggleCallWindowIfNeeded(EState state);
+	void setURI(std::string uri);
+
+	std::string	mURI;
+	std::string	mCredentials;
+	LLUUID		mSessionID;
+	EState		mState;
+	std::string	mSessionName;
+	LLSD mNotifyArgs;
+	BOOL		mIgnoreNextSessionLeave;
+	LLHandle<LLPanel> mLoginNotificationHandle;
+
+	typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
+	static voice_channel_map_t sVoiceChannelMap;
+
+	typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
+	static voice_channel_map_uri_t sVoiceChannelURIMap;
+
+	static LLVoiceChannel* sCurrentVoiceChannel;
+	static LLVoiceChannel* sSuspendedVoiceChannel;
+	static BOOL sSuspended;
+};
+
+class LLVoiceChannelGroup : public LLVoiceChannel
+{
+public:
+	LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
+
+	/*virtual*/ void handleStatusChange(EStatusType status);
+	/*virtual*/ void handleError(EStatusType status);
+	/*virtual*/ void activate();
+	/*virtual*/ void deactivate();
+	/*vritual*/ void setChannelInfo(
+		const std::string& uri,
+		const std::string& credentials);
+	/*virtual*/ void getChannelInfo();
+
+protected:
+	virtual void setState(EState state);
+
+private:
+	U32 mRetries;
+	BOOL mIsRetrying;
+};
+
+class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
+{
+public:
+	LLVoiceChannelProximal();
+
+	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+	/*virtual*/ void handleStatusChange(EStatusType status);
+	/*virtual*/ void handleError(EStatusType status);
+	/*virtual*/ BOOL isActive();
+	/*virtual*/ void activate();
+	/*virtual*/ void deactivate();
+
+};
+
+class LLVoiceChannelP2P : public LLVoiceChannelGroup
+{
+public:
+	LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
+
+	/*virtual*/ void handleStatusChange(EStatusType status);
+	/*virtual*/ void handleError(EStatusType status);
+    /*virtual*/ void activate();
+	/*virtual*/ void getChannelInfo();
+
+	void setSessionHandle(const std::string& handle, const std::string &inURI);
+
+protected:
+	virtual void setState(EState state);
+
+private:
+	std::string	mSessionHandle;
+	LLUUID		mOtherUserID;
+	BOOL		mReceivedCall;
+};
+
+#endif  // LL_VOICECHANNEL_H
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index ca028269feacf7c84fbc0196513917a6e866ea76..df5481c874c91240e1cf862a65507c373cf522f1 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -57,13 +57,13 @@
 #include "llagent.h"
 #include "llcachename.h"
 #include "llimview.h" // for LLIMMgr
-#include "llimpanel.h" // for LLVoiceChannel
 #include "llparcel.h"
 #include "llviewerparcelmgr.h"
 #include "llfirstuse.h"
 #include "llviewerwindow.h"
 #include "llviewercamera.h"
 #include "llvoavatarself.h"
+#include "llvoicechannel.h"
 
 #include "llfloaterfriends.h"  //VIVOX, inorder to refresh communicate panel
 #include "llfloaterchat.h"		// for LLFloaterChat::addChat()
@@ -254,6 +254,7 @@ class LLVivoxProtocolParser : public LLIOPipe
 	std::string		nameString;
 	std::string		audioMediaString;
 	std::string		displayNameString;
+	std::string		deviceString;
 	int				participantType;
 	bool			isLocallyMuted;
 	bool			isModeratorMuted;
@@ -485,6 +486,14 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
 			{
 				gVoiceClient->clearRenderDevices();
 			}
+			else if (!stricmp("CaptureDevice", tag))
+			{
+				deviceString.clear();
+			}
+			else if (!stricmp("RenderDevice", tag))
+			{
+				deviceString.clear();
+			}
 			else if (!stricmp("Buddies", tag))
 			{
 				gVoiceClient->deleteAllBuddies();
@@ -508,7 +517,6 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
 void LLVivoxProtocolParser::EndTag(const char *tag)
 {
 	const std::string& string = textBuffer;
-	bool clearbuffer = true;
 
 	responseDepth--;
 
@@ -580,6 +588,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
 			nameString = string;
 		else if (!stricmp("DisplayName", tag))
 			displayNameString = string;
+		else if (!stricmp("Device", tag))
+			deviceString = string;
 		else if (!stricmp("AccountName", tag))
 			nameString = string;
 		else if (!stricmp("ParticipantType", tag))
@@ -596,18 +606,13 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
 			uriString = string;
 		else if (!stricmp("Presence", tag))
 			statusString = string;
-		else if (!stricmp("Device", tag))
-		{
-			// This closing tag shouldn't clear the accumulated text.
-			clearbuffer = false;
-		}
 		else if (!stricmp("CaptureDevice", tag))
 		{
-			gVoiceClient->addCaptureDevice(textBuffer);
+			gVoiceClient->addCaptureDevice(deviceString);
 		}
 		else if (!stricmp("RenderDevice", tag))
 		{
-			gVoiceClient->addRenderDevice(textBuffer);
+			gVoiceClient->addRenderDevice(deviceString);
 		}
 		else if (!stricmp("Buddy", tag))
 		{
@@ -648,12 +653,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
 		else if (!stricmp("SubscriptionType", tag))
 			subscriptionType = string;
 		
-
-		if(clearbuffer)
-		{
-			textBuffer.clear();
-			accumulateText= false;
-		}
+		textBuffer.clear();
+		accumulateText= false;
 		
 		if (responseDepth == 0)
 		{
@@ -1160,7 +1161,8 @@ LLVoiceClient::LLVoiceClient() :
 	mVoiceEnabled(false),
 	mWriteInProgress(false),
 	
-	mLipSyncEnabled(false)
+	mLipSyncEnabled(false),
+	mAPIVersion("Unknown")
 {	
 	gVoiceClient = this;
 	
@@ -3749,6 +3751,7 @@ void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusS
 	{
 		// Connector created, move forward.
 		LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
+		mAPIVersion = versionID;
 		mConnectorHandle = connectorHandle;
 		if(getState() == stateConnectorStarting)
 		{
@@ -6921,7 +6924,8 @@ void LLVoiceClient::notifyFriendObservers()
 
 void LLVoiceClient::lookupName(const LLUUID &id)
 {
-	gCacheName->get(id, FALSE, &LLVoiceClient::onAvatarNameLookup);
+	BOOL is_group = FALSE;
+	gCacheName->get(id, is_group, &LLVoiceClient::onAvatarNameLookup);
 }
 
 //static
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index bddd18dee89c1e16b7985df808f344e20d2306db..9df96d9a5215a2db6f0edf23f9427556e8d09fd5 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -204,6 +204,9 @@ static	void updatePosition(void);
 		void keyDown(KEY key, MASK mask);
 		void keyUp(KEY key, MASK mask);
 		void middleMouseState(bool down);
+
+		// Return the version of the Vivox library
+		std::string getAPIVersion() const { return mAPIVersion; }
 		
 		/////////////////////////////
 		// Accessors for data related to nearby speakers
@@ -739,6 +742,8 @@ static	std::string nameFromsipURI(const std::string &uri);
 		
 		BOOL		mLipSyncEnabled;
 
+		std::string	mAPIVersion;
+
 		typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
 		observer_set_t mParticipantObservers;
 
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 7585842623bee5b7886487e6473cf9db12ff07c3..143cd2d9c63a3d5540041c0884f428ada43d2418 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -249,6 +249,12 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
 		facep->mCenterLocal = part->mPosAgent;
 		facep->setFaceColor(part->mColor);
 		facep->setTexture(part->mImagep);
+			
+		//check if this particle texture is replaced by a parcel media texture.
+		if(part->mImagep.notNull() && part->mImagep->hasParcelMedia()) 
+		{
+			part->mImagep->getParcelMedia()->addMediaToFace(facep) ;
+		}
 
 		mPixelArea = tot_area * pixel_meter_ratio;
 		const F32 area_scale = 10.f; // scale area to increase priority a bit
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index ef3244b199ad3340eaf384f8b3e7c2a035b35da7..78fd3710875f041bc0c1c85eb90e152aac80c86f 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -100,6 +100,57 @@ static LLFastTimer::DeclareTimer FTM_MESH_FACES("Faces");
 static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures");
 
 
+// Implementation class of LLMediaDataClientObject.  See llmediadataclient.h
+class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
+{
+public:
+	LLMediaDataClientObjectImpl(LLVOVolume *obj) : mObject(obj) {}
+	LLMediaDataClientObjectImpl() { mObject = NULL; }
+	
+	virtual U8 getMediaDataCount() const 
+		{ return mObject->getNumTEs(); }
+
+	virtual LLSD getMediaDataLLSD(U8 index) const 
+		{
+			LLSD result;
+			LLTextureEntry *te = mObject->getTE(index); 
+			if (NULL != te)
+			{
+				llassert((te->getMediaData() != NULL) == te->hasMedia());
+				if (te->getMediaData() != NULL)
+				{
+					result = te->getMediaData()->asLLSD();
+				}
+			}
+			return result;
+		}
+
+	virtual LLUUID getID() const
+		{ return mObject->getID(); }
+
+	virtual void mediaNavigateBounceBack(U8 index)
+		{ mObject->mediaNavigateBounceBack(index); }
+	
+	virtual bool hasMedia() const
+		{ return mObject->hasMedia(); }
+	
+	virtual void updateObjectMediaData(LLSD const &data) 
+		{ mObject->updateObjectMediaData(data); }
+
+	virtual F64 getDistanceFromAvatar() const
+		{ return mObject->getRenderPosition().length(); }
+	
+	virtual F64 getTotalMediaInterest() const 
+		{ return mObject->getTotalMediaInterest(); }
+
+	virtual std::string getCapabilityUrl(const std::string &name) const
+		{ return mObject->getRegion()->getCapability(name); }
+	
+private:
+	LLPointer<LLVOVolume> mObject;
+};
+
+
 LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
 	: LLViewerObject(id, pcode, regionp),
 	  mVolumeImpl(NULL)
@@ -143,8 +194,12 @@ LLVOVolume::~LLVOVolume()
 // static
 void LLVOVolume::initClass()
 {
-    sObjectMediaClient = new LLObjectMediaDataClient();
-    sObjectMediaNavigateClient = new LLObjectMediaNavigateClient();
+	// gSavedSettings better be around
+	const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
+	const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
+	const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries");
+    sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries);
+    sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, max_retries);
 }
 
 // static
@@ -328,13 +383,23 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
 			}
 		}
 	}
-	if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) {
-		// If the media changed at all, request new media data
-		if(mMedia)
+	if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) 
+	{
+		// If only the media URL changed, and it isn't a media version URL,
+		// ignore it
+		if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) &&
+				 mMedia && ! mMedia->mMediaURL.empty() &&
+				 ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) )
 		{
-			llinfos << "Media URL: " << mMedia->mMediaURL << llendl;
+			// If the media changed at all, request new media data
+			LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " <<
+                ((mMedia) ?  mMedia->mMediaURL : std::string("")) << LL_ENDL;
+			requestMediaDataUpdate();
 		}
-		requestMediaDataUpdate();
+        else {
+            LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " <<
+                ((mMedia) ?  mMedia->mMediaURL : std::string("")) << LL_ENDL;
+        }
 	}
 	// ...and clean up any media impls
 	cleanUpMediaImpls();
@@ -1695,7 +1760,7 @@ bool LLVOVolume::hasMedia() const
 
 void LLVOVolume::requestMediaDataUpdate()
 {
-    sObjectMediaClient->fetchMedia(this);
+    sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this));
 }
 
 void LLVOVolume::cleanUpMediaImpls()
@@ -1774,6 +1839,119 @@ void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool m
 	//	<< ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl;
 }
 
+void LLVOVolume::mediaNavigateBounceBack(U8 texture_index)
+{
+	// Find the media entry for this navigate
+	const LLMediaEntry* mep = NULL;
+	viewer_media_t impl = getMediaImpl(texture_index);
+	LLTextureEntry *te = getTE(texture_index);
+	if(te)
+	{
+		mep = te->getMediaData();
+	}
+	
+	if (mep && impl)
+	{
+        std::string url = mep->getCurrentURL();
+        if (url.empty())
+        {
+            url = mep->getHomeURL();
+        }
+        if (! url.empty())
+        {
+            LL_INFOS("LLMediaDataClient") << "bouncing back to URL: " << url << LL_ENDL;
+            impl->navigateTo(url, "", false, true);
+        }
+    }
+}
+
+bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type)
+{
+    // NOTE: This logic duplicates the logic in the server (in particular, in llmediaservice.cpp).
+    if (NULL == media_entry ) return false; // XXX should we assert here?
+    
+    // The agent has permissions to navigate if:
+    // - agent has edit permissions, or
+    // - world permissions are on, or
+    // - group permissions are on, and agent_id is in the group, or
+    // - agent permissions are on, and agent_id is the owner
+    
+    if (permModify()) 
+    {
+        return true;
+    }
+    
+    U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl();
+    
+    // World permissions
+    if (0 != (media_perms & LLMediaEntry::PERM_ANYONE)) 
+    {
+        return true;
+    }
+    
+    // Group permissions
+    else if (0 != (media_perms & LLMediaEntry::PERM_GROUP) && permGroupOwner())
+    {
+        return true;
+    }
+    
+    // Owner permissions
+    else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner()) 
+    {
+        return true;
+    }
+    
+    return false;
+    
+}
+
+void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location)
+{
+	bool block_navigation = false;
+	// FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed
+	// to deal with multiple face indices.
+	int face_index = getFaceIndexWithMediaImpl(impl, -1);
+	
+	// Find the media entry for this navigate
+	LLMediaEntry* mep = NULL;
+	LLTextureEntry *te = getTE(face_index);
+	if(te)
+	{
+		mep = te->getMediaData();
+	}
+	
+	if(mep)
+	{
+		if(!mep->checkCandidateUrl(new_location))
+		{
+			block_navigation = true;
+		}
+		if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT))
+		{
+			block_navigation = true;
+		}
+	}
+	else
+	{
+		llwarns << "Couldn't find media entry!" << llendl;
+	}
+						
+	if(block_navigation)
+	{
+		llinfos << "blocking navigate to URI " << new_location << llendl;
+
+		// "bounce back" to the current URL from the media entry
+		mediaNavigateBounceBack(face_index);
+	}
+	else
+	{
+		
+		llinfos << "broadcasting navigate with URI " << new_location << llendl;
+
+		sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this), face_index, new_location);
+	}
+}
+
 void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
 {
 	switch(event)
@@ -1785,49 +1963,8 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
 			{
 				case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED:
 				{
-					// This is the first location changed event after the start of a non-server-directed nav.  It may need to be broadcast.
-
-					bool block_navigation = false;
-					// FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed
-					// to deal with multiple face indices.
-					int face_index = getFaceIndexWithMediaImpl(impl, -1);
-					std::string new_location = plugin->getLocation();
-					
-					// Find the media entry for this navigate
-					LLMediaEntry* mep = NULL;
-					LLTextureEntry *te = getTE(face_index);
-					if(te)
-					{
-						mep = te->getMediaData();
-					}
-					
-					if(mep)
-					{
-						if(!mep->checkCandidateUrl(new_location))
-						{
-							block_navigation = true;
-						}
-					}
-					else
-					{
-						llwarns << "Couldn't find media entry!" << llendl;
-					}
-										
-					if(block_navigation)
-					{
-						llinfos << "blocking navigate to URI " << new_location << llendl;
-
-						// "bounce back" to the current URL from the media entry
-						// NOTE: the only way block_navigation can be true is if we found the media entry, so we're guaranteed here that mep is not NULL.
-						impl->navigateTo(mep->getCurrentURL());
-					}
-					else
-					{
-						
-						llinfos << "broadcasting navigate with URI " << new_location << llendl;
-
-						sObjectMediaNavigateClient->navigate(this, face_index, new_location);
-					}
+					// This is the first location changed event after the start of a non-server-directed nav.  It may need to be broadcast or bounced back.
+					mediaNavigated(impl, plugin, plugin->getLocation());
 				}
 				break;
 				
@@ -1844,6 +1981,29 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
 		}
 		break;
 		
+		case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
+		{
+			switch(impl->getNavState())
+			{
+				case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED:
+				{
+					// This is the first location changed event after the start of a non-server-directed nav.  It may need to be broadcast or bounced back.
+					mediaNavigated(impl, plugin, plugin->getNavigateURI());
+				}
+				break;
+				
+				case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED:
+					// This is the the navigate complete event from a server-directed nav.  Don't broadcast it.
+					llinfos << "	NOT broadcasting navigate (server-directed)" << llendl;
+				break;
+				
+				default:
+					// For all other states, the navigate should have been handled by LOCATION_CHANGED events already.
+				break;
+			}
+		}
+		break;
+		
 		default:
 		break;
 	}
@@ -1852,7 +2012,7 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
 
 void LLVOVolume::sendMediaDataUpdate()
 {
-    sObjectMediaClient->updateMedia(this);
+    sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this));
 }
 
 void LLVOVolume::removeMediaImpl(S32 texture_index)
@@ -1945,6 +2105,22 @@ viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const
 	return NULL;
 }
 
+F64 LLVOVolume::getTotalMediaInterest() const
+{
+	F64 interest = (F64)0.0;
+    int i = 0;
+	const int end = getNumTEs();
+	for ( ; i < end; ++i)
+	{
+		const viewer_media_t &impl = getMediaImpl(i);
+		if (!impl.isNull())
+		{
+			interest += impl->getInterest();
+		}
+	}
+	return interest;
+}
+
 S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id)
 {
 	S32 end = (S32)mMediaImplList.size() ;
@@ -2924,6 +3100,7 @@ static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
 
 void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 {
+	llpushcallstacks ;
 	if (group->changeLOD())
 	{
 		group->mLastUpdateDistance = group->mDistance;
@@ -3154,6 +3331,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry");
 void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 {
+	llpushcallstacks ;
 	if (group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY))
 	{
 		LLFastTimer tm(FTM_VOLUME_GEOM);
@@ -3249,6 +3427,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 
 void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort)
 {
+	llpushcallstacks ;
 	//calculate maximum number of vertices to store in a single buffer
 	U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask);
 	max_vertices = llmin(max_vertices, (U32) 65535);
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 6aaf5b2fddb8cf01246ad0e31723cfebb91094fe..9253b1b16e5bc1ee888baafbf846e4e3bfe0b918 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -239,7 +239,23 @@ class LLVOVolume : public LLViewerObject
 	BOOL canBeFlexible() const;
 	BOOL setIsFlexible(BOOL is_flexible);
 
-	void updateObjectMediaData(const LLSD &media_data_duples);
+    // Functions that deal with media, or media navigation
+    
+    // Update this object's media data with the given media data array
+    // (typically this is only called upon a response from a server request)
+	void updateObjectMediaData(const LLSD &media_data_array);
+    
+    // Bounce back media at the given index to its current URL (or home URL, if current URL is empty)
+	void mediaNavigateBounceBack(U8 texture_index);
+    
+    // Returns whether or not this object has permission to navigate or control 
+	// the given media entry
+	enum MediaPermType {
+		MEDIA_PERM_INTERACT, MEDIA_PERM_CONTROL
+	};
+    bool hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type);
+    
+	void mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location);
 	void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event);
 			
 
@@ -251,6 +267,7 @@ class LLVOVolume : public LLViewerObject
 
 	viewer_media_t getMediaImpl(U8 face_id) const;
 	S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id);
+	F64 getTotalMediaInterest() const;
    
 	bool hasMedia() const;
 
diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp
index 3fe02088c4c04fb2d658696352425f4c4a057ba4..4cd29bb83866a8365a1ba2c4fc450cb908b704ae 100644
--- a/indra/newview/llwearable.cpp
+++ b/indra/newview/llwearable.cpp
@@ -35,6 +35,7 @@
 #include "llagent.h"
 #include "llagentwearables.h"
 #include "llfloatercustomize.h"
+#include "lllocaltextureobject.h"
 #include "llviewertexturelist.h"
 #include "llinventorymodel.h"
 #include "llviewerregion.h"
@@ -184,7 +185,9 @@ void LLWearable::createVisualParams()
 			{
 				delete mVisualParamIndexMap[param->getID()];
 			}
-			mVisualParamIndexMap[param->getID()] = param->cloneParam(this);
+			LLViewerVisualParam *new_param = param->cloneParam(this);
+			new_param->setIsDummy(FALSE);
+			mVisualParamIndexMap[param->getID()] = new_param;
 		}
 	}
 
@@ -667,21 +670,7 @@ void LLWearable::writeToAvatar( BOOL set_by_user, BOOL update_customize_floater
 
 	if( gFloaterCustomize && update_customize_floater )
 	{
-		LLViewerInventoryItem* item;
-		// MULTI_WEARABLE:
-		item = (LLViewerInventoryItem*)gInventory.getItem(gAgentWearables.getWearableItemID(mType,0));
-		U32 perm_mask = PERM_NONE;
-		BOOL is_complete = FALSE;
-		if(item)
-		{
-			perm_mask = item->getPermissions().getMaskOwner();
-			is_complete = item->isComplete();
-			if(!is_complete)
-			{
-				item->fetchFromServer();
-			}
-		}
-		gFloaterCustomize->setWearable(mType, this, perm_mask, is_complete);
+		gFloaterCustomize->setWearable(mType, 0);
 		gFloaterCustomize->setCurrentWearableType( mType );
 	}
 
@@ -934,6 +923,17 @@ void LLWearable::getVisualParams(visual_param_vec_t &list)
 	}
 }
 
+void LLWearable::animateParams(F32 delta, BOOL set_by_user)
+{
+	for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
+		 iter != mVisualParamIndexMap.end();
+		 ++iter)
+	{
+		LLVisualParam *param = (LLVisualParam*) iter->second;
+		param->animate(delta, set_by_user);
+	}
+}
+
 LLColor4 LLWearable::getClothesColor(S32 te) const
 {
 	LLColor4 color;
diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h
index 01bd9652a5cc15923fb5f680d00240f37488ef9e..96631811c58cdec770637de31e049343d16d2cdb 100644
--- a/indra/newview/llwearable.h
+++ b/indra/newview/llwearable.h
@@ -119,6 +119,7 @@ class LLWearable
 	F32					getVisualParamWeight(S32 index) const;
 	LLVisualParam*		getVisualParam(S32 index) const;
 	void				getVisualParams(visual_param_vec_t &list);
+	void				animateParams(F32 delta, BOOL set_by_user);
 
 	LLColor4			getClothesColor(S32 te) const;
 	void 				setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user );
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index 829d631473b3c43b0426ad6ada28ff7e383f4615..f198f3a0cf531b8984cd0004aca2f3fc17a8ab7a 100644
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -37,7 +37,6 @@
 #include "llregionhandle.h"
 #include "message.h"
 
-#include "llappviewer.h"	// for gPacificDaylightTime
 #include "llagent.h"
 #include "llmapresponders.h"
 #include "llviewercontrol.h"
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 3aad5c7378b7ee322cf56e8fdbe177366a0d5514..823db027eeb872e0a1f9f3927200c37b4910e3a8 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -368,7 +368,7 @@ void LLWorldMapView::draw()
 			continue;
 		}
 		
-		current_image->setBoostLevel(LLViewerTexture::BOOST_MAP_LAYER);
+		current_image->setBoostLevel(LLViewerTexture::BOOST_MAP);
 		current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY]));
 		
 		if (!current_image->hasGLTexture())
diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..af8cb6b9fb87868e5801d38daff5376bb520e725
--- /dev/null
+++ b/indra/newview/llxmlrpclistener.cpp
@@ -0,0 +1,496 @@
+/**
+ * @file   llxmlrpclistener.cpp
+ * @author Nat Goodspeed
+ * @date   2009-03-18
+ * @brief  Implementation for llxmlrpclistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llxmlrpclistener.h"
+// STL headers
+#include <map>
+#include <set>
+// std headers
+// external library headers
+#include <boost/scoped_ptr.hpp>
+#include <boost/range.hpp>          // boost::begin(), boost::end()
+// other Linden headers
+#include "llerror.h"
+#include "stringize.h"
+#include "llxmlrpctransaction.h"
+
+#include <xmlrpc-epi/xmlrpc.h>
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+template <typename STATUS>
+class StatusMapperBase
+{
+    typedef std::map<STATUS, std::string> MapType;
+
+public:
+    StatusMapperBase(const std::string& desc):
+        mDesc(desc)
+    {}
+
+    std::string lookup(STATUS status) const
+    {
+        typename MapType::const_iterator found = mMap.find(status);
+        if (found != mMap.end())
+        {
+            return found->second;
+        }
+        return STRINGIZE("<unknown " << mDesc << " " << status << ">");
+    }
+
+protected:
+    std::string mDesc;
+    MapType mMap;
+};
+
+class StatusMapper: public StatusMapperBase<LLXMLRPCTransaction::EStatus>
+{
+public:
+    StatusMapper(): StatusMapperBase<LLXMLRPCTransaction::EStatus>("Status")
+    {
+		mMap[LLXMLRPCTransaction::StatusNotStarted]  = "NotStarted";
+		mMap[LLXMLRPCTransaction::StatusStarted]     = "Started";
+		mMap[LLXMLRPCTransaction::StatusDownloading] = "Downloading";
+		mMap[LLXMLRPCTransaction::StatusComplete]    = "Complete";
+		mMap[LLXMLRPCTransaction::StatusCURLError]   = "CURLError";
+		mMap[LLXMLRPCTransaction::StatusXMLRPCError] = "XMLRPCError";
+		mMap[LLXMLRPCTransaction::StatusOtherError]  = "OtherError";
+    }
+};
+
+static const StatusMapper sStatusMapper;
+
+class CURLcodeMapper: public StatusMapperBase<CURLcode>
+{
+public:
+    CURLcodeMapper(): StatusMapperBase<CURLcode>("CURLcode")
+    {
+        // from curl.h
+// skip the "CURLE_" prefix for each of these strings
+#define def(sym) (mMap[sym] = #sym + 6)
+        def(CURLE_OK);
+        def(CURLE_UNSUPPORTED_PROTOCOL);    /* 1 */
+        def(CURLE_FAILED_INIT);             /* 2 */
+        def(CURLE_URL_MALFORMAT);           /* 3 */
+        def(CURLE_URL_MALFORMAT_USER);      /* 4 - NOT USED */
+        def(CURLE_COULDNT_RESOLVE_PROXY);   /* 5 */
+        def(CURLE_COULDNT_RESOLVE_HOST);    /* 6 */
+        def(CURLE_COULDNT_CONNECT);         /* 7 */
+        def(CURLE_FTP_WEIRD_SERVER_REPLY);  /* 8 */
+        def(CURLE_FTP_ACCESS_DENIED);       /* 9 a service was denied by the FTP server
+                                          due to lack of access - when login fails
+                                          this is not returned. */
+        def(CURLE_FTP_USER_PASSWORD_INCORRECT); /* 10 - NOT USED */
+        def(CURLE_FTP_WEIRD_PASS_REPLY);    /* 11 */
+        def(CURLE_FTP_WEIRD_USER_REPLY);    /* 12 */
+        def(CURLE_FTP_WEIRD_PASV_REPLY);    /* 13 */
+        def(CURLE_FTP_WEIRD_227_FORMAT);    /* 14 */
+        def(CURLE_FTP_CANT_GET_HOST);       /* 15 */
+        def(CURLE_FTP_CANT_RECONNECT);      /* 16 */
+        def(CURLE_FTP_COULDNT_SET_BINARY);  /* 17 */
+        def(CURLE_PARTIAL_FILE);            /* 18 */
+        def(CURLE_FTP_COULDNT_RETR_FILE);   /* 19 */
+        def(CURLE_FTP_WRITE_ERROR);         /* 20 */
+        def(CURLE_FTP_QUOTE_ERROR);         /* 21 */
+        def(CURLE_HTTP_RETURNED_ERROR);     /* 22 */
+        def(CURLE_WRITE_ERROR);             /* 23 */
+        def(CURLE_MALFORMAT_USER);          /* 24 - NOT USED */
+        def(CURLE_UPLOAD_FAILED);           /* 25 - failed upload "command" */
+        def(CURLE_READ_ERROR);              /* 26 - could open/read from file */
+        def(CURLE_OUT_OF_MEMORY);           /* 27 */
+        /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
+                 instead of a memory allocation error if CURL_DOES_CONVERSIONS
+                 is defined
+        */
+        def(CURLE_OPERATION_TIMEOUTED);     /* 28 - the timeout time was reached */
+        def(CURLE_FTP_COULDNT_SET_ASCII);   /* 29 - TYPE A failed */
+        def(CURLE_FTP_PORT_FAILED);         /* 30 - FTP PORT operation failed */
+        def(CURLE_FTP_COULDNT_USE_REST);    /* 31 - the REST command failed */
+        def(CURLE_FTP_COULDNT_GET_SIZE);    /* 32 - the SIZE command failed */
+        def(CURLE_HTTP_RANGE_ERROR);        /* 33 - RANGE "command" didn't work */
+        def(CURLE_HTTP_POST_ERROR);         /* 34 */
+        def(CURLE_SSL_CONNECT_ERROR);       /* 35 - wrong when connecting with SSL */
+        def(CURLE_BAD_DOWNLOAD_RESUME);     /* 36 - couldn't resume download */
+        def(CURLE_FILE_COULDNT_READ_FILE);  /* 37 */
+        def(CURLE_LDAP_CANNOT_BIND);        /* 38 */
+        def(CURLE_LDAP_SEARCH_FAILED);      /* 39 */
+        def(CURLE_LIBRARY_NOT_FOUND);       /* 40 */
+        def(CURLE_FUNCTION_NOT_FOUND);      /* 41 */
+        def(CURLE_ABORTED_BY_CALLBACK);     /* 42 */
+        def(CURLE_BAD_FUNCTION_ARGUMENT);   /* 43 */
+        def(CURLE_BAD_CALLING_ORDER);       /* 44 - NOT USED */
+        def(CURLE_INTERFACE_FAILED);        /* 45 - CURLOPT_INTERFACE failed */
+        def(CURLE_BAD_PASSWORD_ENTERED);    /* 46 - NOT USED */
+        def(CURLE_TOO_MANY_REDIRECTS );     /* 47 - catch endless re-direct loops */
+        def(CURLE_UNKNOWN_TELNET_OPTION);   /* 48 - User specified an unknown option */
+        def(CURLE_TELNET_OPTION_SYNTAX );   /* 49 - Malformed telnet option */
+        def(CURLE_OBSOLETE);                /* 50 - NOT USED */
+        def(CURLE_SSL_PEER_CERTIFICATE);    /* 51 - peer's certificate wasn't ok */
+        def(CURLE_GOT_NOTHING);             /* 52 - when this is a specific error */
+        def(CURLE_SSL_ENGINE_NOTFOUND);     /* 53 - SSL crypto engine not found */
+        def(CURLE_SSL_ENGINE_SETFAILED);    /* 54 - can not set SSL crypto engine as
+                                          default */
+        def(CURLE_SEND_ERROR);              /* 55 - failed sending network data */
+        def(CURLE_RECV_ERROR);              /* 56 - failure in receiving network data */
+        def(CURLE_SHARE_IN_USE);            /* 57 - share is in use */
+        def(CURLE_SSL_CERTPROBLEM);         /* 58 - problem with the local certificate */
+        def(CURLE_SSL_CIPHER);              /* 59 - couldn't use specified cipher */
+        def(CURLE_SSL_CACERT);              /* 60 - problem with the CA cert (path?) */
+        def(CURLE_BAD_CONTENT_ENCODING);    /* 61 - Unrecognized transfer encoding */
+        def(CURLE_LDAP_INVALID_URL);        /* 62 - Invalid LDAP URL */
+        def(CURLE_FILESIZE_EXCEEDED);       /* 63 - Maximum file size exceeded */
+        def(CURLE_FTP_SSL_FAILED);          /* 64 - Requested FTP SSL level failed */
+        def(CURLE_SEND_FAIL_REWIND);        /* 65 - Sending the data requires a rewind
+                                          that failed */
+        def(CURLE_SSL_ENGINE_INITFAILED);   /* 66 - failed to initialise ENGINE */
+        def(CURLE_LOGIN_DENIED);            /* 67 - user); password or similar was not
+                                          accepted and we failed to login */
+        def(CURLE_TFTP_NOTFOUND);           /* 68 - file not found on server */
+        def(CURLE_TFTP_PERM);               /* 69 - permission problem on server */
+        def(CURLE_TFTP_DISKFULL);           /* 70 - out of disk space on server */
+        def(CURLE_TFTP_ILLEGAL);            /* 71 - Illegal TFTP operation */
+        def(CURLE_TFTP_UNKNOWNID);          /* 72 - Unknown transfer ID */
+        def(CURLE_TFTP_EXISTS);             /* 73 - File already exists */
+        def(CURLE_TFTP_NOSUCHUSER);         /* 74 - No such user */
+        def(CURLE_CONV_FAILED);             /* 75 - conversion failed */
+        def(CURLE_CONV_REQD);               /* 76 - caller must register conversion
+                                          callbacks using curl_easy_setopt options
+                                          CURLOPT_CONV_FROM_NETWORK_FUNCTION);
+                                          CURLOPT_CONV_TO_NETWORK_FUNCTION); and
+                                          CURLOPT_CONV_FROM_UTF8_FUNCTION */
+        def(CURLE_SSL_CACERT_BADFILE);      /* 77 - could not load CACERT file); missing
+                                          or wrong format */
+        def(CURLE_REMOTE_FILE_NOT_FOUND);   /* 78 - remote file not found */
+        def(CURLE_SSH);                     /* 79 - error from the SSH layer); somewhat
+                                          generic so the error message will be of
+                                          interest when this has happened */
+
+        def(CURLE_SSL_SHUTDOWN_FAILED);     /* 80 - Failed to shut down the SSL
+                                          connection */
+#undef  def
+    }
+};
+
+static const CURLcodeMapper sCURLcodeMapper;
+
+LLXMLRPCListener::LLXMLRPCListener(const std::string& pumpname):
+    mBoundListener(LLEventPumps::instance().
+                   obtain(pumpname).
+                   listen("LLXMLRPCListener", boost::bind(&LLXMLRPCListener::process, this, _1)))
+{
+}
+
+/**
+ * Capture an outstanding LLXMLRPCTransaction and poll it periodically until
+ * done.
+ *
+ * The sequence is:
+ * # Instantiate Poller, which instantiates, populates and initiates an
+ *   LLXMLRPCTransaction. Poller self-registers on the LLEventPump named
+ *   "mainloop".
+ * # "mainloop" is conventionally pumped once per frame. On each such call,
+ *   Poller checks its LLXMLRPCTransaction for completion.
+ * # When the LLXMLRPCTransaction completes, Poller collects results (if any)
+ *   and sends notification.
+ * # The tricky part: Poller frees itself (and thus its LLXMLRPCTransaction)
+ *   when done. The only external reference to it is the connection to the
+ *   "mainloop" LLEventPump.
+ */
+class Poller
+{
+public:
+    /// Validate the passed request for required fields, then use it to
+    /// populate an XMLRPC_REQUEST and an associated LLXMLRPCTransaction. Send
+    /// the request.
+    Poller(const LLSD& command):
+        mReqID(command),
+        mUri(command["uri"]),
+        mMethod(command["method"]),
+        mReplyPump(command["reply"])
+    {
+        // LL_ERRS if any of these are missing
+        const char* required[] = { "uri", "method", "reply" };
+        // optional: "options" (array of string)
+        // Validate the request
+        std::set<std::string> missing;
+        for (const char** ri = boost::begin(required); ri != boost::end(required); ++ri)
+        {
+            // If the command does not contain this required entry, add it to 'missing'.
+            if (! command.has(*ri))
+            {
+                missing.insert(*ri);
+            }
+        }
+        if (! missing.empty())
+        {
+            LL_ERRS("LLXMLRPCListener") << mMethod << " request missing params: ";
+            const char* separator = "";
+            for (std::set<std::string>::const_iterator mi(missing.begin()), mend(missing.end());
+                 mi != mend; ++mi)
+            {
+                LL_CONT << separator << *mi;
+                separator = ", ";
+            }
+            LL_CONT << LL_ENDL;
+        }
+
+        // Build the XMLRPC request.
+        XMLRPC_REQUEST request = XMLRPC_RequestNew();
+        XMLRPC_RequestSetMethodName(request, mMethod.c_str());
+        XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
+        XMLRPC_VALUE xparams = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
+        LLSD params(command["params"]);
+        if (params.isMap())
+        {
+            for (LLSD::map_const_iterator pi(params.beginMap()), pend(params.endMap());
+                 pi != pend; ++pi)
+            {
+                std::string name(pi->first);
+                LLSD param(pi->second);
+                if (param.isString())
+                {
+                    XMLRPC_VectorAppendString(xparams, name.c_str(), param.asString().c_str(), 0);
+                }
+                else if (param.isInteger() || param.isBoolean())
+                {
+                    XMLRPC_VectorAppendInt(xparams, name.c_str(), param.asInteger());
+                }
+                else if (param.isReal())
+                {
+                    XMLRPC_VectorAppendDouble(xparams, name.c_str(), param.asReal());
+                }
+                else
+                {
+                    LL_ERRS("LLXMLRPCListener") << mMethod << " request param "
+                                                << name << " has unknown type: " << param << LL_ENDL;
+                }
+            }
+        }
+        LLSD options(command["options"]);
+        if (options.isArray())
+        {
+            XMLRPC_VALUE xoptions = XMLRPC_CreateVector("options", xmlrpc_vector_array);
+            for (LLSD::array_const_iterator oi(options.beginArray()), oend(options.endArray());
+                 oi != oend; ++oi)
+            {
+                XMLRPC_VectorAppendString(xoptions, NULL, oi->asString().c_str(), 0);
+            }
+            XMLRPC_AddValueToVector(xparams, xoptions);
+        }
+        XMLRPC_RequestSetData(request, xparams);
+
+        mTransaction.reset(new LLXMLRPCTransaction(mUri, request));
+		mPreviousStatus = mTransaction->status(NULL);
+
+        // Free the XMLRPC_REQUEST object and the attached data values.
+        XMLRPC_RequestFree(request, 1);
+
+        // Now ensure that we get regular callbacks to poll for completion.
+        mBoundListener =
+            LLEventPumps::instance().
+            obtain("mainloop").
+            listen(LLEventPump::inventName(), boost::bind(&Poller::poll, this, _1));
+
+        LL_INFOS("LLXMLRPCListener") << mMethod << " request sent to " << mUri << LL_ENDL;
+    }
+
+    /// called by "mainloop" LLEventPump
+    bool poll(const LLSD&)
+    {
+        bool done = mTransaction->process();
+
+        CURLcode curlcode;
+        LLXMLRPCTransaction::EStatus status;
+        {
+            // LLXMLRPCTransaction::status() is defined to accept int* rather
+            // than CURLcode*. I don't feel the urge to fix the signature, but
+            // we want a CURLcode rather than an int. So fetch it as a local
+            // int, but then assign to a CURLcode for the remainder of this
+            // method.
+            int curlint;
+            status = mTransaction->status(&curlint);
+            curlcode = CURLcode(curlint);
+        }
+
+        LLSD data(mReqID.makeResponse());
+        data["status"] = sStatusMapper.lookup(status);
+        data["errorcode"] = sCURLcodeMapper.lookup(curlcode);
+        data["error"] = "";
+        data["transfer_rate"] = 0.0;
+        LLEventPump& replyPump(LLEventPumps::instance().obtain(mReplyPump));
+		if (! done)
+        {
+            // Not done yet, carry on.
+			if (status == LLXMLRPCTransaction::StatusDownloading
+				&& status != mPreviousStatus)
+			{
+				// If a response has been received, send the 
+				// 'downloading' status if it hasn't been sent.
+				replyPump.post(data);
+			}
+
+			mPreviousStatus = status;
+            return false;
+        }
+
+        // Here the transaction is complete. Check status.
+        data["error"] = mTransaction->statusMessage();
+		data["transfer_rate"] = mTransaction->transferRate();
+        LL_INFOS("LLXMLRPCListener") << mMethod << " result from " << mUri << ": status "
+                                     << data["status"].asString() << ", errorcode "
+                                     << data["errorcode"].asString()
+                                     << " (" << data["error"].asString() << ")"
+                                     << LL_ENDL;
+        // In addition to CURLE_OK, LLUserAuth distinguishes different error
+        // values of 'curlcode':
+        // CURLE_COULDNT_RESOLVE_HOST,
+        // CURLE_SSL_PEER_CERTIFICATE,
+        // CURLE_SSL_CACERT,
+        // CURLE_SSL_CONNECT_ERROR.
+        // Given 'message', need we care?
+        if (status == LLXMLRPCTransaction::StatusComplete)
+        {
+            // Success! Parse data.
+            std::string status_string(data["status"]);
+            data["responses"] = parseResponse(status_string);
+            data["status"] = status_string;
+        }
+
+        // whether successful or not, send reply on requested LLEventPump
+        replyPump.post(data);
+
+        // Because mTransaction is a boost::scoped_ptr, deleting this object
+        // frees our LLXMLRPCTransaction object.
+        // Because mBoundListener is an LLTempBoundListener, deleting this
+        // object disconnects it from "mainloop".
+        // *** MUST BE LAST ***
+        delete this;
+        return false;
+    }
+
+private:
+    /// Derived from LLUserAuth::parseResponse() and parseOptionInto()
+    LLSD parseResponse(std::string& status_string)
+    {
+        // Extract every member into data["responses"] (a map of string
+        // values).
+        XMLRPC_REQUEST response = mTransaction->response();
+        if (! response)
+        {
+            LL_DEBUGS("LLXMLRPCListener") << "No response" << LL_ENDL;
+            return LLSD();
+        }
+
+        XMLRPC_VALUE param = XMLRPC_RequestGetData(response);
+        if (! param)
+        {
+            LL_DEBUGS("LLXMLRPCListener") << "Response contains no data" << LL_ENDL;
+            return LLSD();
+        }
+
+        // Now, parse everything
+        return parseValues(status_string, "", param);
+    }
+
+    /**
+     * Parse key/value pairs from a given XMLRPC_VALUE into an LLSD map.
+     * @param key_pfx Used to describe a given key in log messages. At top
+     * level, pass "". When parsing an options array, pass the top-level key
+     * name of the array plus the index of the array entry; to this we'll
+     * append the subkey of interest.
+     * @param param XMLRPC_VALUE iterator. At top level, pass
+     * XMLRPC_RequestGetData(XMLRPC_REQUEST).
+     */
+    LLSD parseValues(std::string& status_string, const std::string& key_pfx, XMLRPC_VALUE param)
+    {
+        LLSD responses;
+        for (XMLRPC_VALUE current = XMLRPC_VectorRewind(param); current;
+             current = XMLRPC_VectorNext(param))
+        {
+            std::string key(XMLRPC_GetValueID(current));
+            LL_DEBUGS("LLXMLRPCListener") << "key: " << key_pfx << key << LL_ENDL;
+            XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(current);
+            if (xmlrpc_type_string == type)
+            {
+                LLSD::String val(XMLRPC_GetValueString(current));
+                LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
+                responses.insert(key, val);
+            }
+            else if (xmlrpc_type_int == type)
+            {
+                LLSD::Integer val(XMLRPC_GetValueInt(current));
+                LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
+                responses.insert(key, val);
+            }
+            else if (xmlrpc_type_double == type)
+            {
+                LLSD::Real val(XMLRPC_GetValueDouble(current));
+                LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
+                responses.insert(key, val);
+            }
+            else if (xmlrpc_type_array == type)
+            {
+                // We expect this to be an array of submaps. Walk the array,
+                // recursively parsing each submap and collecting them.
+                LLSD array;
+                int i = 0;          // for descriptive purposes
+                for (XMLRPC_VALUE row = XMLRPC_VectorRewind(current); row;
+                     row = XMLRPC_VectorNext(current), ++i)
+                {
+                    // Recursive call. For the lower-level key_pfx, if 'key'
+                    // is "foo", pass "foo[0]:", then "foo[1]:", etc. In the
+                    // nested call, a subkey "bar" will then be logged as
+                    // "foo[0]:bar", and so forth.
+                    // Parse the scalar subkey/value pairs from this array
+                    // entry into a temp submap. Collect such submaps in 'array'.
+                    array.append(parseValues(status_string,
+                                             STRINGIZE(key_pfx << key << '[' << i << "]:"),
+                                             row));
+                }
+                // Having collected an 'array' of 'submap's, insert that whole
+                // 'array' as the value of this 'key'.
+                responses.insert(key, array);
+            }
+            else
+            {
+                // whoops - unrecognized type
+                LL_WARNS("LLXMLRPCListener") << "Unhandled xmlrpc type " << type << " for key "
+                                             << key_pfx << key << LL_ENDL;
+                responses.insert(key, STRINGIZE("<bad XMLRPC type " << type << '>'));
+                status_string = "BadType";
+            }
+        }
+        return responses;
+    }
+
+    const LLReqID mReqID;
+    const std::string mUri;
+    const std::string mMethod;
+    const std::string mReplyPump;
+    LLTempBoundListener mBoundListener;
+    boost::scoped_ptr<LLXMLRPCTransaction> mTransaction;
+	LLXMLRPCTransaction::EStatus mPreviousStatus; // To detect state changes.
+};
+
+bool LLXMLRPCListener::process(const LLSD& command)
+{
+    // Allocate a new heap Poller, but do not save a pointer to it. Poller
+    // will check its own status and free itself on completion of the request.
+    (new Poller(command));
+    // conventional event listener return
+    return false;
+}
diff --git a/indra/newview/llxmlrpclistener.h b/indra/newview/llxmlrpclistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..120c2b329be5413c6279fb546e3b16ef819c6844
--- /dev/null
+++ b/indra/newview/llxmlrpclistener.h
@@ -0,0 +1,35 @@
+/**
+ * @file   llxmlrpclistener.h
+ * @author Nat Goodspeed
+ * @date   2009-03-18
+ * @brief  LLEventPump API for LLXMLRPCTransaction. This header doesn't
+ *         actually define the API; the API is defined by the pump name on
+ *         which this class listens, and by the expected content of LLSD it
+ *         receives.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLXMLRPCLISTENER_H)
+#define LL_LLXMLRPCLISTENER_H
+
+#include "llevents.h"
+
+/// Listen on an LLEventPump with specified name for LLXMLRPCTransaction
+/// request events.
+class LLXMLRPCListener
+{
+public:
+    /// Specify the pump name on which to listen
+    LLXMLRPCListener(const std::string& pumpname);
+
+    /// Handle request events on the event pump specified at construction time
+    bool process(const LLSD& command);
+
+private:
+    LLTempBoundListener mBoundListener;
+};
+
+#endif /* ! defined(LL_LLXMLRPCLISTENER_H) */
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 58ff84a8a69a332df0686f7e4ed73ebf90fb3d53..70859e8ea51da3368cee182a4f67cd678fdfad4a 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -33,6 +33,7 @@
 #include "llviewerprecompiledheaders.h"
 
 #include "llxmlrpctransaction.h"
+#include "llxmlrpclistener.h"
 
 #include "llcurl.h"
 #include "llviewercontrol.h"
@@ -42,6 +43,13 @@
 
 #include "llappviewer.h"
 
+// Static instance of LLXMLRPCListener declared here so that every time we
+// bring in this code, we instantiate a listener. If we put the static
+// instance of LLXMLRPCListener into llxmlrpclistener.cpp, the linker would
+// simply omit llxmlrpclistener.o, and shouting on the LLEventPump would do
+// nothing.
+static LLXMLRPCListener listener("LLXMLRPCTransaction");
+
 LLXMLRPCValue LLXMLRPCValue::operator[](const char* id) const
 {
 	return LLXMLRPCValue(XMLRPC_VectorGetValueWithID(mV, id));
@@ -213,6 +221,11 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
 	XMLRPC_RequestSetData(request, params.getValue());
 	
 	init(request, useGzip);
+    // DEV-28398: without this XMLRPC_RequestFree() call, it looks as though
+    // the 'request' object is simply leaked. It's less clear to me whether we
+    // should also ask to free request value data (second param 1), since the
+    // data come from 'params'.
+    XMLRPC_RequestFree(request, 1);
 }
 
 
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 7cf5cf75ad23cf1a9b1db458ef1d75587d01059d..dcc2b7dd22db5a8dbac77960df9834fbfee0e184 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1806,6 +1806,7 @@ void LLPipeline::rebuildPriorityGroups()
 		
 void LLPipeline::rebuildGroups()
 {
+	llpushcallstacks ;
 	// Iterate through some drawables on the non-priority build queue
 	S32 size = (S32) mGroupQ2.size();
 	S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size);
diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc
index 38570e1a7ed06f8d85044b729b6e299bf859a758..433070ce343994999732af519451ce2f844d5c6a 100644
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
@@ -134,8 +134,8 @@ TOOLMEDIAOPEN           CURSOR                  "toolmediaopen.cur"
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,0,0,0
- PRODUCTVERSION 2,0,0,0
+ FILEVERSION 2,0,0,3256
+ PRODUCTVERSION 2,0,0,3256
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -152,12 +152,12 @@ BEGIN
         BEGIN
             VALUE "CompanyName", "Linden Lab"
             VALUE "FileDescription", "Second Life"
-            VALUE "FileVersion", "2.0.0.0"
+            VALUE "FileVersion", "2.0.0.3256"
             VALUE "InternalName", "Second Life"
             VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc."
             VALUE "OriginalFilename", "SecondLife.exe"
             VALUE "ProductName", "Second Life"
-            VALUE "ProductVersion", "2.0.0.0"
+            VALUE "ProductVersion", "2.0.0.3256"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 287c997c65cc2c371f52fa8b7cd39772532f0d50..1e0da1316285f7e2e48bde1a9247f9f126c79788 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -65,6 +65,9 @@
 	<color
 	 name="Blue"
 	 value="0 0 1 1" />
+	<color
+	 name="Yellow"
+	 value="1 1 0 1" />
 	<color
 	 name="Unused?"
 	 value="1 0 1 1" />
@@ -408,10 +411,10 @@
      reference="White" />
     <color
      name="MapAvatarColor"
-     reference="White" />
+     reference="Green" />
     <color
      name="MapAvatarFriendColor"
-     reference="Unused?" />
+     reference="Yellow" />
     <color
      name="MapAvatarSelfColor"
      value="0.53125 0 0.498047 1" />
diff --git a/indra/newview/skins/default/textures/containers/Accordion_Selected.png b/indra/newview/skins/default/textures/containers/Accordion_Selected.png
new file mode 100644
index 0000000000000000000000000000000000000000..0616dea6a349f790fe633bac125da58867ace1de
Binary files /dev/null and b/indra/newview/skins/default/textures/containers/Accordion_Selected.png differ
diff --git a/indra/newview/skins/default/textures/icons/ForSale_Badge.png b/indra/newview/skins/default/textures/icons/ForSale_Badge.png
new file mode 100644
index 0000000000000000000000000000000000000000..5bee570ceec1a244255e9ae06fb6370bca1fe3f1
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/ForSale_Badge.png differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Object.png b/indra/newview/skins/default/textures/icons/Generic_Object.png
new file mode 100644
index 0000000000000000000000000000000000000000..e3a80b2aef90ee5749fdadc4438055b98211d86e
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Generic_Object.png differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Object_Small.png b/indra/newview/skins/default/textures/icons/Generic_Object_Small.png
new file mode 100644
index 0000000000000000000000000000000000000000..223874e631ad021ce7617e6dcb4399d171081b09
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Generic_Object_Small.png differ
diff --git a/indra/newview/skins/default/textures/icons/Info_Over.png b/indra/newview/skins/default/textures/icons/Info_Over.png
new file mode 100644
index 0000000000000000000000000000000000000000..be1cd0706feb09f985bc7801fb92b308abdab95a
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Info_Over.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Animation.png b/indra/newview/skins/default/textures/icons/Inv_Animation.png
index 8b69434066379f3b462290712a01721ba00ee4d7..ab42c61a92498c9b270384547ba0f4c0bcdb2a23 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Animation.png and b/indra/newview/skins/default/textures/icons/Inv_Animation.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_BodyShape.png b/indra/newview/skins/default/textures/icons/Inv_BodyShape.png
index 9d98bfaa7d6865191f392a6969b9b69698ca09c5..97e874d70d27c6caeb77275aeb35ae0b49210bcd 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_BodyShape.png and b/indra/newview/skins/default/textures/icons/Inv_BodyShape.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Clothing.png b/indra/newview/skins/default/textures/icons/Inv_Clothing.png
index 49a54b82e13676619e1fa1e7fec24352ada81d76..e8d246c6faf0aeaa4b4ff49b8f28e79cf8c92d52 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Clothing.png and b/indra/newview/skins/default/textures/icons/Inv_Clothing.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Eye.png b/indra/newview/skins/default/textures/icons/Inv_Eye.png
index 6d0321dde967c31385482fb6812d324ae1d53f7f..e619f56c2b57fa714d8f4cfdfa0bf3ca8f616195 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Eye.png and b/indra/newview/skins/default/textures/icons/Inv_Eye.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png b/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png
index 30aa6e04ac059d5aedeaac4da403442a749d8b62..342a973d006cbc7702a30778cc585a695b0177db 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png and b/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png b/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png
index 792ef446e8bcd42fdc330067cd5ccb68db594164..0507c2cbaf0be26ddf84914baf084aebe4e0225a 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png and b/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Gesture.png b/indra/newview/skins/default/textures/icons/Inv_Gesture.png
index c49ae523c810eae8be4520357c4014fc2cce7c33..52695ec19bf8e494e4d3e42e6a6d140f812aacd8 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Gesture.png and b/indra/newview/skins/default/textures/icons/Inv_Gesture.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Gloves.png b/indra/newview/skins/default/textures/icons/Inv_Gloves.png
index d81bc961d42a9ee67b70abb2447370928c50781f..d6a2113aafb9d520176ae4ffbb4cb803ffeb9400 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Gloves.png and b/indra/newview/skins/default/textures/icons/Inv_Gloves.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Hair.png b/indra/newview/skins/default/textures/icons/Inv_Hair.png
index 5e68f1ffea67682dea5202fb7537bd2ca50a083b..ae941b0dd537461395329102b31b5d0a5d9a61de 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Hair.png and b/indra/newview/skins/default/textures/icons/Inv_Hair.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Jacket.png b/indra/newview/skins/default/textures/icons/Inv_Jacket.png
index 0e28f45f1903a5d62298a0c2944a78e0228a66eb..3859666f7cc9be0ba9e57579b0f2d305e6a4605c 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Jacket.png and b/indra/newview/skins/default/textures/icons/Inv_Jacket.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Landmark.png b/indra/newview/skins/default/textures/icons/Inv_Landmark.png
index 6648a233935ff5b7e2e58b87ff2e57fd1f68277a..f8ce765c501f57cc29993d6a0a90e59c8c6c0cae 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Landmark.png and b/indra/newview/skins/default/textures/icons/Inv_Landmark.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.png b/indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.png
new file mode 100644
index 0000000000000000000000000000000000000000..f2ae828efce3a91bf2b53d792f8c696ad6e16657
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.png b/indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.png
new file mode 100644
index 0000000000000000000000000000000000000000..d454d4cd4813337daca2cf0286be8f5111cfa8d4
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Notecard.png b/indra/newview/skins/default/textures/icons/Inv_Notecard.png
index 830a71311fd750d7f6fb1395edcfd10b5db35870..4645ab8e910312d59c734c27f739621016cda6fa 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Notecard.png and b/indra/newview/skins/default/textures/icons/Inv_Notecard.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Object.png b/indra/newview/skins/default/textures/icons/Inv_Object.png
index a88d0dc4b3163007148fdca717e5b485aa35c12a..f883696a8226eb9cf91b02dcde14a6ea5f86b9ec 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Object.png and b/indra/newview/skins/default/textures/icons/Inv_Object.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Pants.png b/indra/newview/skins/default/textures/icons/Inv_Pants.png
index 2527f7f9c3221999c21eb8dad3cd037ef2f0d560..fe2389f074d63273cf444d31d230f725098924df 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Pants.png and b/indra/newview/skins/default/textures/icons/Inv_Pants.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Script.png b/indra/newview/skins/default/textures/icons/Inv_Script.png
index e9c9b163fdc7f8d352d801551f4e06fada3f3975..0fba27a7aa6ae211567bb492660a765efdb05a33 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Script.png and b/indra/newview/skins/default/textures/icons/Inv_Script.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Shirt.png b/indra/newview/skins/default/textures/icons/Inv_Shirt.png
index 7cc880a124cf145b7cf2b9b97c1fcab8eb19f88d..81c1538dd2f55e08a9c08b00d4ecead1b370405f 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Shirt.png and b/indra/newview/skins/default/textures/icons/Inv_Shirt.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Shoe.png b/indra/newview/skins/default/textures/icons/Inv_Shoe.png
index 0b148647eb99feff7a94bb14373d533e973f63b6..51e1c7bbb7b7def6b136580c21b8be006bc89108 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Shoe.png and b/indra/newview/skins/default/textures/icons/Inv_Shoe.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Skin.png b/indra/newview/skins/default/textures/icons/Inv_Skin.png
index 8e20638bba7be5da883d1316a39cd2d7c04cf4d6..b7da922046aa82c6da161c88e8000f067372fdfa 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Skin.png and b/indra/newview/skins/default/textures/icons/Inv_Skin.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Skirt.png b/indra/newview/skins/default/textures/icons/Inv_Skirt.png
index 40860a35992799a83d155d6ae2913664aa09e4bc..246e9a87aa03373b9185876027dc11a67c4046ec 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Skirt.png and b/indra/newview/skins/default/textures/icons/Inv_Skirt.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Snapshot.png b/indra/newview/skins/default/textures/icons/Inv_Snapshot.png
index 17e710a84366f51782f96164c77f634952690bd1..39efd2be1b575f21b36267961a1b9904b7cb65f5 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Snapshot.png and b/indra/newview/skins/default/textures/icons/Inv_Snapshot.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Socks.png b/indra/newview/skins/default/textures/icons/Inv_Socks.png
index b8169dcb36cf179b68cf92fe9fbeb30938bd080a..30d7d7c2393945e4deac5999d88109a9414e17ae 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Socks.png and b/indra/newview/skins/default/textures/icons/Inv_Socks.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Sound.png b/indra/newview/skins/default/textures/icons/Inv_Sound.png
index 1a50dd17daf1dfb12884d873b1bf4bfc03545490..44c271c868f2024ba5346b89374e72f11f207498 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Sound.png and b/indra/newview/skins/default/textures/icons/Inv_Sound.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Texture.png b/indra/newview/skins/default/textures/icons/Inv_Texture.png
index 2d6d1b54bbd0f172864b674f1e578e08be714191..dbc41c5e995b6ff7d74fc91333b849deeca2817d 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Texture.png and b/indra/newview/skins/default/textures/icons/Inv_Texture.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Underpants.png b/indra/newview/skins/default/textures/icons/Inv_Underpants.png
index 77f56c574f462da534de23ce795243052f1a248e..b1e7c2a55f432c3640219245c017a00285b04878 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Underpants.png and b/indra/newview/skins/default/textures/icons/Inv_Underpants.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Undershirt.png b/indra/newview/skins/default/textures/icons/Inv_Undershirt.png
index 954eab766021800d2f6222369251bb01ddf16af5..9340dbb9758af3d146c1b1adef17e85e649d9612 100644
Binary files a/indra/newview/skins/default/textures/icons/Inv_Undershirt.png and b/indra/newview/skins/default/textures/icons/Inv_Undershirt.png differ
diff --git a/indra/newview/skins/default/textures/icons/YouAreHere_Badge.png b/indra/newview/skins/default/textures/icons/YouAreHere_Badge.png
new file mode 100644
index 0000000000000000000000000000000000000000..c057e9743d08febb5beb3a5a80f46a4db2aeed56
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/YouAreHere_Badge.png differ
diff --git a/indra/newview/skins/default/textures/map_avatar_8.tga b/indra/newview/skins/default/textures/map_avatar_8.tga
index 47c8cbed6fb1ed51b998a909ae37b65daf493eef..28552f223798d1a1d4c0c04a50af38cee77b9e24 100644
Binary files a/indra/newview/skins/default/textures/map_avatar_8.tga and b/indra/newview/skins/default/textures/map_avatar_8.tga differ
diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png
index 7c10aaaead1808fd51ef64406ce9dcc366e874d9..41cb88628a683d13d420d13feaa24f465ebbfca5 100644
Binary files a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png and b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png differ
diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png
index 9d7716c6de6f91933a8886547b9e067623b7815a..a02675502a9ef97a7a5085c8b34ca5b38cc690b0 100644
Binary files a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png and b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 26b0b39a68fb31bbcbf606ea996b9bc3aeaf0fc1..fa65c760fd9cc7d151dc526c8712d7550557084f 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -6,6 +6,8 @@
   <texture name="Accordion_ArrowOpened_Press" file_name="containers/Accordion_ArrowOpened_Press.png" preload="false" />
   <texture name="Accordion_Off" file_name="containers/Accordion_Off.png" preload="false" />
   <texture name="Accordion_Press" file_name="containers/Accordion_Press.png" preload="false" />
+  <texture name="Accordion_Over" file_name="containers/Accordion_Over.png" preload="false" />
+  <texture name="Accordion_Selected" file_name="containers/Accordion_Selected.png" preload="false" />
 
 <texture name="Activate_Checkmark" file_name="taskpanel/Activate_Checkmark.png" preload="false" />
 
@@ -27,9 +29,9 @@
 
   <texture name="BottomTray_BG" file_name="bottomtray/BottomTray_BG.png" preload="false" />
 
-  <texture name="BuyArrow_Off" file_name="navbar/BuyArrow_Off.png" preload="false" />
-  <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="false" />
-  <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="false" />
+  <texture name="BuyArrow_Off" file_name="navbar/BuyArrow_Off.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0"  />
+  <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0"  />
+  <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0"  />
 
   <texture name="Cam_Avatar_Disabled" file_name="bottomtray/Cam_Avatar_Disabled.png" preload="false" />
   <texture name="Cam_Avatar_Over" file_name="bottomtray/Cam_Avatar_Over.png" preload="false" />
@@ -54,11 +56,6 @@
   <texture name="CameraView_Off" file_name="bottomtray/CameraView_Off.png" preload="false" />
   <texture name="CameraView_Over" file_name="bottomtray/CameraView_Over.png" preload="false" />
 
-  <texture name="CameraPreset_Rear" file_name="camera_presets/camera_presets_rear.png" preload="false" />
-  <texture name="CameraPreset_3_4" file_name="camera_presets/camera_presets_3_4.png" preload="false" />
-  <texture name="CameraPreset_Front" file_name="camera_presets/camera_presets_front.png" preload="false" />
-  <texture name="CameraPreset_Mouselook" file_name="camera_presets/camera_presets_mouselook.png" preload="false" />
-
   <texture name="Checkbox_Off_Disabled" file_name="widgets/Checkbox_Disabled.png" preload="true" />
   <texture name="Checkbox_On_Disabled" file_name="widgets/Checkbox_On_Disabled.png" preload="true" />
   <texture name="Checkbox_Off" file_name="widgets/Checkbox_Off.png" preload="true" />
@@ -71,7 +68,6 @@
   <texture name="ComboButton_Press" file_name="widgets/ComboButton_Press.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
   <texture name="ComboButton_Selected" file_name="widgets/ComboButton_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
   <texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
-
   <texture name="Container" file_name="containers/Container.png" preload="false" />
 
   <texture name="DisclosureArrow_Closed_Off" file_name="widgets/DisclosureArrow_Closed_Off.png" preload="true" />
@@ -94,14 +90,18 @@
   <texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" />
   <texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" />
 
-  <texture name="FileMenu_BarSelect" file_name="navbar/FileMenu_BarSelect.png" preload="false" />
+  <texture name="FileMenu_BarSelect" file_name="navbar/FileMenu_BarSelect.png" preload="false" scale.left="2" scale.top="0" scale.right="2" scale.bottom="0" />
   <texture name="FileMenu_BG" file_name="navbar/FileMenu_BG.png" preload="false" />
 
+  <texture name="ForSale_Badge" file_name="icons/ForSale_Badge.png" preload="false" />
   <texture name="ForwardArrow_Off" file_name="icons/ForwardArrow_Off.png" preload="false" />
   <texture name="ForwardArrow_Press" file_name="icons/ForwardArrow_Press.png" preload="false" />
 
   <texture name="Generic_Group" file_name="icons/Generic_Group.png" preload="false" />
   <texture name="Generic_Group_Large" file_name="icons/Generic_Group_Large.png" preload="false" />
+  <texture name="Generic_Object_Medium" file_name="icons/Generic_Object_Medium.png" preload="false" />
+  <texture name="Generic_Object_Small" file_name="icons/ Generic_Object_Small.png" preload="false" />
+  <texture name="Generic_Object_Large" file_name="icons/Generic_Object_Large.png" preload="false" />
   <texture name="Generic_Person" file_name="icons/Generic_Person.png" preload="false" />
   <texture name="Generic_Person_Large" file_name="icons/Generic_Person_Large.png" preload="false" />
 
@@ -123,8 +123,6 @@
   <texture name="Icon_Dock_Press" file_name="windows/Icon_Dock_Press.png" preload="true" />
 
   <texture name="Icon_For_Sale" file_name="icons/Icon_For_sale.png" preload="false" />
-  <texture name="Banner_ForSale" file_name="Banner_ForSale.png" preload="false" />
-  <texture name="Banner_YouAreHere" file_name="Banner_YouAreHere.png" preload="false" />
 
   <texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" />
   <texture name="Icon_Gear_Foreground" file_name="windows/Icon_Gear_Foreground.png" preload="false" />
@@ -146,12 +144,15 @@
   <texture name="Info" file_name="icons/Info.png" preload="false" />
   <texture name="Info_Small" file_name="icons/Info_Small.png" preload="false" />
   <texture name="Info_Off" file_name="navbar/Info_Off.png" preload="false" />
+  <texture name="Info_Over" file_name="icons/Info_Over.png" preload="false" />
   <texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false" />
 
-  <texture name="Inspector_Background" file_name="windows/Inspector_Background.png" preload="false" />
+  <texture name="Inspector_Background" file_name="windows/Inspector_Background.png" preload="false"
+           scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" />
   <texture name="Inspector_Hover" file_name="windows/Inspector_Hover.png" preload="false" />
 
-  <texture name="Inv_Acessories" file_name="icons/Inv_Acessories.png" preload="false" />
+  <texture name="Inv_Acessories" file_name="icons/Inv_Accessories.png" preload="false" />
+  <texture name="Inv_Alpha" file_name="icons/Inv_Alpha.png" preload="false" />
   <texture name="Inv_Animation" file_name="icons/Inv_Animation.png" preload="false" />
   <texture name="Inv_BodyShape" file_name="icons/Inv_BodyShape.png" preload="false" />
   <texture name="Inv_CallingCard" file_name="icons/Inv_CallingCard.png" preload="false" />
@@ -164,6 +165,8 @@
   <texture name="Inv_Gloves" file_name="icons/Inv_Gloves.png" preload="false" />
   <texture name="Inv_Hair" file_name="icons/Inv_Hair.png" preload="false" />
   <texture name="Inv_Jacket" file_name="icons/Inv_Jacket.png" preload="false" />
+  <texture name="Inv_LookFolderOpen" file_name="icons/Inv_LookFolderOpen.png" preload="false" />
+  <texture name="Inv_LookFolderClosed" file_name="icons/Inv_LookFolderClosed.png" preload="false" />
   <texture name="Inv_Landmark" file_name="icons/Inv_Landmark.png" preload="false" />
   <texture name="Inv_Notecard" file_name="icons/Inv_Notecard.png" preload="false" />
   <texture name="Inv_Object" file_name="icons/Inv_Object.png" preload="false" />
@@ -176,6 +179,7 @@
   <texture name="Inv_Snapshot" file_name="icons/Inv_Snapshot.png" preload="false" />
   <texture name="Inv_Socks" file_name="icons/Inv_Socks.png" preload="false" />
   <texture name="Inv_Sound" file_name="icons/Inv_Sound.png" preload="false" />
+  <texture name="Inv_Tattoo" file_name="icons/Inv_Tattoo.png" preload="false" />
   <texture name="Inv_Texture" file_name="icons/Inv_Texture.png" preload="false" />
   <texture name="Inv_Trash" file_name="icons/Inv_Trash.png" preload="false" />
   <texture name="Inv_Underpants" file_name="icons/Inv_Underpants.png" preload="false" />
@@ -256,6 +260,42 @@
   <texture name="Overhead_M" file_name="world/Overhead_M.png" preload="false" />
   <texture name="Overhead_S" file_name="world/Overhead_S.png" preload="false" />
 
+  <texture name="parcel_drk_Build" file_name="icons/parcel_drk_Build.png" preload="false" />
+ <texture name="parcel_drk_BuildNo" file_name="icons/parcel_drk_BuildNo.png" preload="false" />
+ <texture name="parcel_drk_Damage" file_name="icons/parcel_drk_Damage.png" preload="false" />
+ <texture name="parcel_drk_DamageNo" file_name="icons/parcel_drk_DamageNo.png" preload="false" />
+ <texture name="parcel_drk_Fly" file_name="icons/parcel_drk_Fly.png" preload="false" />
+ <texture name="parcel_drk_FlyNo" file_name="icons/parcel_drk_FlyNo.png" preload="false" />
+ <texture name="parcel_drk_ForSale" file_name="icons/parcel_drk_ForSale.png" preload="false" />
+ <texture name="parcel_drk_ForSaleNo" file_name="icons/parcel_drk_ForSaleNo.png" preload="false" />
+ <texture name="parcel_drk_M" file_name="icons/parcel_drk_M.png" preload="false" />
+ <texture name="parcel_drk_PG" file_name="icons/parcel_drk_PG.png" preload="false" />
+ <texture name="parcel_drk_Push" file_name="icons/parcel_drk_Push.png" preload="false" />
+ <texture name="parcel_drk_PushNo" file_name="icons/parcel_drk_PushNo.png" preload="false" />
+ <texture name="parcel_drk_R" file_name="icons/parcel_drk_R.png" preload="false" />
+ <texture name="parcel_drk_Scripts" file_name="icons/parcel_drk_Scripts.png" preload="false" />
+ <texture name="parcel_drk_ScriptsNo" file_name="icons/parcel_drk_ScriptsNo.png" preload="false" />
+ <texture name="parcel_drk_Voice" file_name="icons/parcel_drk_Voice.png" preload="false" />
+ <texture name="parcel_drk_VoiceNo" file_name="icons/parcel_drk_VoiceNo.png" preload="false" />
+
+ <texture name="parcel_lght_Build" file_name="icons/parcel_lght_Build.png" preload="false" />
+ <texture name="parcel_lght_BuildNo" file_name="icons/parcel_lght_BuildNo.png" preload="false" />
+ <texture name="parcel_lght_Damage" file_name="icons/parcel_lght_Damage.png" preload="false" />
+ <texture name="parcel_lght_DamageNo" file_name="icons/parcel_lght_DamageNo.png" preload="false" />
+ <texture name="parcel_lght_Fly" file_name="icons/parcel_lght_Fly.png" preload="false" />
+ <texture name="parcel_lght_FlyNo" file_name="icons/parcel_lght_FlyNo.png" preload="false" />
+ <texture name="parcel_lght_ForSale" file_name="icons/parcel_lght_ForSale.png" preload="false" />
+ <texture name="parcel_lght_ForSaleNo" file_name="icons/parcel_lght_ForSaleNo.png" preload="false" />
+ <texture name="parcel_lght_M" file_name="icons/parcel_lght_M.png" preload="false" />
+ <texture name="parcel_lght_PG" file_name="icons/parcel_lght_PG.png" preload="false" />
+ <texture name="parcel_lght_Push" file_name="icons/parcel_lght_Push.png" preload="false" />
+ <texture name="parcel_lght_PushNo" file_name="icons/parcel_lght_PushNo.png" preload="false" />
+ <texture name="parcel_lght_R" file_name="icons/parcel_lght_R.png" preload="false" />
+ <texture name="parcel_lght_Scripts" file_name="icons/parcel_lght_Scripts.png" preload="false" />
+ <texture name="parcel_lght_ScriptsNo" file_name="icons/parcel_lght_ScriptsNo.png" preload="false" />
+ <texture name="parcel_lght_Voice" file_name="icons/parcel_lght_Voice.png" preload="false" />
+ <texture name="parcel_lght_VoiceNo" file_name="icons/parcel_lght_VoiceNo.png" preload="false" />
+
   <texture name="Progress_1" file_name="icons/Progress_1.png" preload="false" />
   <texture name="Progress_2" file_name="icons/Progress_2.png" preload="false" />
   <texture name="Progress_3" file_name="icons/Progress_3.png" preload="false" />
@@ -336,7 +376,7 @@
   <texture name="SliderThumb_Disabled" file_name="widgets/SliderThumb_Disabled.png" />
   <texture name="SliderThumb_Press" file_name="widgets/SliderThumb_Press.png" />
 
-  <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="false" />
+  <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
   <texture name="Snapshot_Over" file_name="bottomtray/Snapshot_Over.png" preload="false" />
   <texture name="Snapshot_Press" file_name="bottomtray/Snapshot_Press.png" preload="false" />
 
@@ -399,7 +439,8 @@
   <texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
 
   <texture name="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" />
-  <texture name="Toast" file_name="windows/Toast.png" preload="true" />
+  <texture name="Toast_Background" file_name="windows/Toast_Background.png" preload="true"
+           scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" />
 
   <texture name="Tool_Create" file_name="build/Tool_Create.png" preload="false" />
   <texture name="Tool_Dozer" file_name="build/Tool_Dozer.png" preload="false" />
@@ -432,16 +473,24 @@
   <texture name="VoicePTT_On" file_name="bottomtray/VoicePTT_On.png" preload="false" />
 
   <texture name="Widget_DownArrow" file_name="icons/Widget_DownArrow.png" preload="true" />
+  <texture name="Widget_UpArrow" file_name="icons/Widget_UpArrow.png" preload="true" />
 
-  <texture name="Window_Background" file_name="windows/Window_Background.png" preload="true" />
-  <texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true" />
-
-
-
+  <texture name="Window_Background" file_name="windows/Window_Background.png" preload="true"
+           scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+  <texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true"
+           scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+  <texture name="Window_NoTitle_Background" file_name="windows/Window_NoTitle_Background.png" preload="true"
+           scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+  <texture name="Window_NoTitle_Foreground" file_name="windows/Window_NoTitle_Foreground.png" preload="true"
+           scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
 
+  <texture name="YouAreHere_Badge" file_name="icons/YouAreHere_Badge.png" preload="false" />
 
   <!--WARNING OLD ART *do not use*-->
 
+ <texture name="Banner_ForSale" file_name="Banner_ForSale.png" preload="false" />
+  <texture name="Banner_YouAreHere" file_name="Banner_YouAreHere.png" preload="false" />
+
   <texture name="btn_chatbar.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" />
   <texture name="btn_chatbar_selected.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" />
 
diff --git a/indra/newview/skins/default/textures/windows/Inspector_Background.png b/indra/newview/skins/default/textures/windows/Inspector_Background.png
index 807e8e553c3169ae8b721498d0522a2523ef7c75..4c2a728ac5980df9e2feaf27cb4d0d9af1767325 100644
Binary files a/indra/newview/skins/default/textures/windows/Inspector_Background.png and b/indra/newview/skins/default/textures/windows/Inspector_Background.png differ
diff --git a/indra/newview/skins/default/textures/windows/Toast_Background.png b/indra/newview/skins/default/textures/windows/Toast_Background.png
new file mode 100644
index 0000000000000000000000000000000000000000..f27d1a12ec9cef1bb2695afb4edaf6127af5f885
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/Toast_Background.png differ
diff --git a/indra/newview/skins/default/textures/windows/Window_Background.png b/indra/newview/skins/default/textures/windows/Window_Background.png
index e9f15e76b967b997a0ca3be09ee1ede4aae91290..db253900afb18e6ae5f9db931bbaa2679c8cd3f0 100644
Binary files a/indra/newview/skins/default/textures/windows/Window_Background.png and b/indra/newview/skins/default/textures/windows/Window_Background.png differ
diff --git a/indra/newview/skins/default/textures/windows/Window_Foreground.png b/indra/newview/skins/default/textures/windows/Window_Foreground.png
index e76e9f3c799415efd57341c41ea10bae22106177..b81ec5b43c39428ce2af1906ad2b0062edeec1b7 100644
Binary files a/indra/newview/skins/default/textures/windows/Window_Foreground.png and b/indra/newview/skins/default/textures/windows/Window_Foreground.png differ
diff --git a/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png b/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png
new file mode 100644
index 0000000000000000000000000000000000000000..a570ac06bd87ce5ac82ddef4c595a5ffd35ae36b
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png differ
diff --git a/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png b/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..d573e8c69abf0b3df895028843d7a02816749be0
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png differ
diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml
index 6d64d13db7ee991751886436a12a5a74f02a5856..3789369e7437ef6d2b2e90b99b049460fee0082a 100644
--- a/indra/newview/skins/default/xui/en/floater_aaa.xml
+++ b/indra/newview/skins/default/xui/en/floater_aaa.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="440"
  layout="topleft"
  name="floater_aaa"
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 09240a3e27639ac5d391c97d4e507e9e146c6a73..e168f964b7402638c1a13fc5c1c3572b5b800f1f 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="440"
  layout="topleft"
  name="floater_about"
@@ -7,66 +8,57 @@
  save_rect="true"
  title="About [APP_NAME]"
  width="470">
-    <floater.string
-     name="you_are_at">
-        You are at [POSITION]
-    </floater.string>
-    <floater.string
-     name="in_region">
-        in [REGION] located at
-    </floater.string>
-    <floater.string
-     name="CPU">
-        CPU:
-    </floater.string>
-    <floater.string
-     name="Memory">
-        Memory: [MEM] MB
-    </floater.string>
-    <floater.string
-     name="OSVersion">
-        OS Version:
-    </floater.string>
-    <floater.string
-     name="GraphicsCardVendor">
-        Graphics Card Vendor:
-    </floater.string>
-    <floater.string
-     name="GraphicsCard">
-        Graphics Card:
-    </floater.string>
-    <floater.string
-     name="OpenGLVersion">
-        OpenGL Version:
-    </floater.string>
-    <floater.string
-     name="LibCurlVersion">
-        libcurl Version:
-    </floater.string>
-    <floater.string
-     name="J2CDecoderVersion">
-        J2C Decoder Version:
-    </floater.string>
-    <floater.string
-     name="AudioDriverVersion">
-        Audio Driver Version:
-    </floater.string>
-    <floater.string
-     name="none">
-        (none)
-    </floater.string>
-    <floater.string
-     name="LLMozLibVersion">
-        LLMozLib Version:
-    </floater.string>
   <floater.string
-     name="LLQtWebkitVersion">
-        Qt Webkit Version: 4.5.2
+     name="AboutHeader">
+[APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
+[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
+
+</floater.string>
+  <floater.string
+     name="AboutCompiler">
+Built with [COMPILER] version [COMPILER_VERSION]
+
+</floater.string>
+  <floater.string
+     name="AboutPosition">
+You are at [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] located at [HOSTNAME] ([HOSTIP])
+[SERVER_VERSION]
+[[SERVER_RELEASE_NOTES_URL] [ReleaseNotes]]
+
+</floater.string>
+  <!-- *NOTE: Do not translate text like GPU, Graphics Card, etc -
+       Most PC users who know what these mean will be used to the English versions,
+       and this info sometimes gets sent to support. -->
+  <floater.string
+     name="AboutSystem">
+CPU: [CPU]
+Memory: [MEMORY_MB] MB
+OS Version: [OS_VERSION]
+Graphics Card Vendor: [GRAPHICS_CARD_VENDOR]
+Graphics Card: [GRAPHICS_CARD]
+</floater.string>
+  <floater.string
+     name="AboutDriver">
+Windows Graphics Driver Version: [GRAPHICS_DRIVER_VERSION]
+</floater.string>
+  <floater.string
+     name="AboutLibs">
+OpenGL Version: [OPENGL_VERSION]
+
+libcurl Version: [LIBCURL_VERSION]
+J2C Decoder Version: [J2C_VERSION]
+Audio Driver Version: [AUDIO_DRIVER_VERSION]
+Qt Webkit Version: [QT_WEBKIT_VERSION]
+Vivox Version: [VIVOX_VERSION]
+</floater.string>
+  <floater.string
+     name="none">
+      (none)
   </floater.string>
   <floater.string
-     name="PacketsLost">
-        Packets Lost: [LOST]/[IN] ([PCT]%)
-    </floater.string>
+     name="AboutTraffic">
+Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)
+</floater.string>
   <tab_container
     follows="all" 
     top="25"
@@ -159,12 +151,14 @@ expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
 FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
 GL Copyright (C) 1999-2004 Brian Paul.
   GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
+google-perftools Copyright (c) 2005, Google Inc.
 Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
 jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
 jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
 ogg/vorbis Copyright (C) 2001, Xiphophorus
 OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
   PCRE Copyright (c) 1997-2008 University of Cambridge
+Pth Copyright (C) 1999-2006 Ralf S. Engelschall &lt;rse@gnu.org&gt;
 SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
 SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 072fafd06e3b3de087e214ae1cf70f50759622ad..e13aa610e535d118259e86ce2d530297267e765b 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_tear_off="false"
  height="420"
  layout="topleft"
@@ -25,24 +26,28 @@
         remaining
     </floater.string>
     <tab_container
-     follows="left|top|right|bottom"
+     follows="all"
      height="400"
+   halign="center"
      layout="topleft"
+     font="SansSerifSmall"
      left="1"
+      tab_padding_right="5"
+      tab_height="20"
      name="landtab"
      tab_position="top"
      top="20"
      width="459">
-        <panel
+   <panel
          border="true"
-         follows="left|top|right|bottom"
+         follows="all"
          height="380"
          label="General"
          layout="topleft"
          left="1"
          help_topic="land_general_tab"
          name="land_general_panel"
-         top="-31"
+         top="0"
          width="458">
             <panel.string
              name="new users only">
@@ -531,7 +536,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
         </panel>
         <panel
          border="true"
-         follows="left|top|right|bottom"
+         follows="all"
          height="380"
          label="Covenant"
          layout="topleft"
@@ -627,7 +632,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
              length="1"
              enabled="false"
              follows="left|top|right|bottom"
-             handle_edit_keys_directly="true" 
+             handle_edit_keys_directly="true"
              height="115"
              layout="topleft"
              left_delta="0"
@@ -798,7 +803,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
         </panel>
         <panel
          border="true"
-         follows="left|top|right|bottom"
+         follows="all"
          height="380"
          label="Objects"
          layout="topleft"
@@ -1164,7 +1169,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
         </panel>
         <panel
          border="true"
-         follows="left|top|right|bottom"
+         follows="all"
          height="333"
          label="Options"
          layout="topleft"
@@ -1600,16 +1605,15 @@ Only large parcels can be listed in search.
                  value="Anywhere" />
             </combo_box>
         </panel>
-        <panel
+     <panel
          border="true"
-         follows="left|top|right|bottom"
+         follows="all"
          height="363"
          label="Media"
          layout="topleft"
          left_delta="0"
          help_topic="land_media_tab"
          name="land_media_panel"
-         top_delta="1"
          width="458">
             <text
              type="string"
@@ -1620,24 +1624,22 @@ Only large parcels can be listed in search.
              left="10"
              name="with media:"
              top="9"
-             width="65">
+             width="100">
                 Type:
             </text>
             <combo_box
-             height="18"
+            height="20"
              layout="topleft"
-             left_pad="5"
+             left_pad="10"
              name="media type"
              tool_tip="Specify if the URL is a movie, web page, or other media"
-             top_delta="-2"
-             width="120" />
+             width="150" />
             <text
              follows="left|top"
              height="16"
              layout="topleft"
              left_pad="10"
              name="mime_type"
-             top_delta="2"
              width="200" />
             <text
              type="string"
@@ -1647,32 +1649,30 @@ Only large parcels can be listed in search.
              layout="topleft"
              left="10"
              name="at URL:"
-             top="29"
-             width="65">
+             top_pad="10"
+             width="100">
                 Home URL:
             </text>
             <line_editor
-             bottom_delta="0"
              follows="left|top"
-             height="16"
+             height="20"
              layout="topleft"
-             left="80"
+             left_pad="10"
              max_length="255"
              name="media_url"
-             right="-80"
              select_on_focus="true"
-             text_readonly_color="0.576471 0.662745 0.835294 1" />
+             width="270"
+            />
             <button
              follows="left|top"
              font="SansSerifSmall"
-             height="16"
-             label="Set..."
-             label_selected="Set..."
+             height="20"
+             label="Set"
+             label_selected="Set"
              layout="topleft"
-             left_pad="8"
+             left_pad="5"
              name="set_media_url"
-             top_delta="0"
-             width="60" />
+             width="50" />
             <text
              type="string"
              length="1"
@@ -1681,37 +1681,34 @@ Only large parcels can be listed in search.
              layout="topleft"
              left="10"
              name="CurrentURL:"
-             top="49"
-             width="65">
+             top_pad="10"
+             width="100">
                 Current URL:
             </text>
             <text
              follows="left|top"
              height="16"
              layout="topleft"
-             left_pad="5"
+             left_pad="10"
              name="current_url"
-             top_delta="0"
-             width="300" />
+             width="260">http://</text>
             <button
              follows="left|top"
-             font="SansSerifSmall"
-             height="16"
-             label="Reset..."
-             label_selected="Reset..."
+             height="20"
+             label="Reset"
+             label_selected="Reset"
              layout="topleft"
              left_pad="6"
              name="reset_media_url"
-             top_delta="0"
              width="60" />
             <check_box
              height="16"
              label="Hide URL"
              layout="topleft"
-             left="100"
+             left="120"
              name="hide_media_url"
              tool_tip="Checking this option will hide the media url to any non-authorized viewers of this parcel information. Note this is not available for HTML types."
-             top="89"
+             top_pad="2"
              width="200" />
             <text
              type="string"
@@ -1721,23 +1718,20 @@ Only large parcels can be listed in search.
              layout="topleft"
              left="10"
              name="Description:"
-             top="49"
-             width="364">
+             top_pad="10"
+             width="100">
                 Description:
             </text>
             <line_editor
-             border_style="line"
-             border_thickness="1"
-             bottom_delta="0"
              follows="left|top"
-             height="16"
+             height="35"
              layout="topleft"
-             left="80"
-             max_length="255"
              name="url_description"
-             right="-80"
+             left_pad="10"
              select_on_focus="true"
-             tool_tip="Text displayed next to play/load button" />
+             tool_tip="Text displayed next to play/load button"
+             top_delta="0"
+             width="270" />
             <text
              type="string"
              length="1"
@@ -1746,10 +1740,9 @@ Only large parcels can be listed in search.
              layout="topleft"
              left="10"
              name="Media texture:"
-             top="69"
-             width="364">
-                Replace
-Texture:
+             top_pad="10"
+             width="100">
+                Replace Texture:
             </text>
             <texture_picker
              allow_no_texture="true"
@@ -1757,7 +1750,7 @@ Texture:
              follows="left|top"
              height="80"
              layout="topleft"
-             left_delta="70"
+             left_pad="10"
              name="media texture"
              tool_tip="Click to choose a picture"
              top_delta="0"
@@ -1766,25 +1759,22 @@ Texture:
              type="string"
              length="1"
              follows="left|top"
-             height="16"
+             height="50"
              layout="topleft"
-             left_delta="75"
+             left_pad="10"
              name="replace_texture_help"
-             top="85"
-             width="270">
-                Objects using this texture will show the movie or
-        web page after you click the play arrow.
-
-        Select the thumbnail to choose a different texture.
+             top_delta="0"
+             word_wrap="true"
+             width="240">
+                Objects using this texture will show the movie or  web page after you click the play arrow.
             </text>
             <check_box
              height="16"
              label="Auto scale"
              layout="topleft"
-             left_delta="70"
              name="media_auto_scale"
              tool_tip="Checking this option will scale the content for this parcel automatically. It may be slightly slower and lower quality visually but no other texture scaling or alignment will be required."
-             top_delta="0"
+             top_pad="3"
              width="200" />
             <text
              type="string"
@@ -1792,11 +1782,11 @@ Texture:
              follows="left|top"
              height="16"
              layout="topleft"
-             left="85"
+             left="10"
+             top_pad="10"
              name="media_size"
              tool_tip="Size to render Web media, leave 0 for default."
-             top="185"
-             width="85">
+             width="100">
                 Size:
             </text>
             <spinner
@@ -1808,12 +1798,22 @@ Texture:
              increment="1"
              initial_value="0"
              layout="topleft"
-             left_delta="65"
+             left_pad="10"
              max_val="1024"
              name="media_size_width"
              tool_tip="Size to render Web media, leave 0 for default."
              top_delta="0"
              width="64" />
+                         <text
+             type="string"
+             length="1"
+             follows="left|top"
+             height="16"
+             layout="topleft"
+             left_pad="5"
+             name="pixels">
+                px wide
+            </text>
             <spinner
              decimal_digits="0"
              enabled="false"
@@ -1823,23 +1823,21 @@ Texture:
              increment="1"
              initial_value="0"
              layout="topleft"
-             left_pad="16"
+             left="120"
+             top_pad="3"
              max_val="1024"
              name="media_size_height"
              tool_tip="Size to render Web media, leave 0 for default."
-             top_delta="0"
              width="64" />
             <text
              type="string"
              length="1"
-             bottom_delta="0"
              follows="left|top"
              height="16"
              layout="topleft"
-             left_delta="70"
-             name="pixels"
-             right="-10">
-                pixels
+             left_pad="5"
+             name="pixels">
+                px high
             </text>
             <text
              type="string"
@@ -1849,15 +1847,15 @@ Texture:
              layout="topleft"
              left="10"
              name="Options:"
-             top="237"
-             width="292">
+             top_pad="10"
+             width="100">
                 Options:
             </text>
             <check_box
              height="16"
              label="Loop"
              layout="topleft"
-             left_delta="70"
+             left_pad="10"
              name="media_loop"
              tool_tip="Play media in a loop.  When the media has finished playing, it will restart from the beginning."
              top_delta="0"
@@ -1865,9 +1863,9 @@ Texture:
         </panel>
         <panel
          border="true"
-         follows="left|top|right|bottom"
+         follows="all"
          height="363"
-         label="Audio"
+         label="Sound"
          layout="topleft"
          left_delta="0"
          help_topic="land_audio_tab"
@@ -1969,7 +1967,7 @@ Texture:
         </panel>
         <panel
          border="true"
-         follows="left|top|right|bottom"
+         follows="all"
          height="333"
          label="Access"
          layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_activeim.xml b/indra/newview/skins/default/xui/en/floater_activeim.xml
index f81250e7b9936bcf3b6958d40cb81849c5a43203..1bc9cde044257f33a1f1488dacd088cbea8b1e08 100644
--- a/indra/newview/skins/default/xui/en/floater_activeim.xml
+++ b/indra/newview/skins/default/xui/en/floater_activeim.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
 	name="floater_activeim"
 	help_topic="floater_activeim"
 	title="ACTIVE IM"
diff --git a/indra/newview/skins/default/xui/en/floater_animation_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_preview.xml
index 11773c34dc30675413eed25fab5bc74365a82fb7..ab3d5722f0a174e89bc2f89934034e7d872ad2e1 100644
--- a/indra/newview/skins/default/xui/en/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_animation_preview.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="556"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_auction.xml b/indra/newview/skins/default/xui/en/floater_auction.xml
index fb0994b4cda5ea0fe3d947c19ff2b3072523b708..aae6508041f3079e3e137d4c80b699d5d38c661c 100644
--- a/indra/newview/skins/default/xui/en/floater_auction.xml
+++ b/indra/newview/skins/default/xui/en/floater_auction.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="412"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
index 0542d4509e1e0da9ee52d2eeeca16817bbdcaea8..1fd9b9531873f45bf164b84663a3fa1a24cc3cb0 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="350"
  layout="topleft"
@@ -85,6 +86,52 @@
              top="52"
              width="132" />
         </panel>
+        <panel
+         border="none"
+         height="150"
+         label="Friends"
+         layout="topleft"
+         left="6"
+         help_topic="avatarpicker_friends_tab"
+         name="FriendsPanel"
+         top="150"
+         width="132">
+            <text
+             type="string"
+             length="1"
+             follows="left|top"
+             height="16"
+             layout="topleft"
+             left="10"
+             name="InstructSelectFriend"
+             top="5"
+             width="200">
+                Select a person:
+            </text>
+            <button
+             follows="top|right"
+             layout="topleft"
+             right="-5"
+             top ="5"
+             height="20"
+             width="20"
+             name="RefreshFriends"
+             picture_style="true"
+             image_overlay="Refresh_Off">
+             <button.commit_callback 
+              function="Refresh.FriendList"/>
+            </button>
+            <scroll_list
+             follows="all"
+             height="100"
+             border="false"
+             layout="topleft"
+             left="0"
+             name="Friends"
+             sort_column="0"
+             top_pad="5"
+             width="132" />
+        </panel>
 
         <panel
          border="none"
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
index e677426ee5167fd0e4293e1d6801b84113583026..4f2a36e5182f7628ac75e503a7d40e39ab097c9d 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="950"
  layout="topleft"
  name="avatar_texture_debug"
diff --git a/indra/newview/skins/default/xui/en/floater_beacons.xml b/indra/newview/skins/default/xui/en/floater_beacons.xml
index a60064fb377ba798535466472b24ad3b61b3f010..1c83799e72145a7928328cdc257a021ab7657fc1 100644
--- a/indra/newview/skins/default/xui/en/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/en/floater_beacons.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="225"
  layout="topleft"
  name="beacons"
diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml
index 3e6845cfa5c633ea66a9fc2a7118733a07867334..bddbbdd3b2f902578ad80a280b714da56bebc42d 100644
--- a/indra/newview/skins/default/xui/en/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_build_options.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  follows="right"
  height="170"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
index ef6af287866fc868c440e08a3d83c580fd809f60..02958bee743927d49d26c32a7de12cce39a0f3e7 100644
--- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_tear_off="false"
  height="310"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml
index d1f67068759824e774732faac9ac886d62aa9fa6..2917096f3cec2ad2ff7ae85e9d8d4a3b98a65c3d 100644
--- a/indra/newview/skins/default/xui/en/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/en/floater_bumps.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="180"
  layout="topleft"
  name="floater_bumps"
diff --git a/indra/newview/skins/default/xui/en/floater_buy_contents.xml b/indra/newview/skins/default/xui/en/floater_buy_contents.xml
index 718f83c9a2926dddeab033ed8024bda63be417ad..aacc3ad8d0c9eb6c11b402f718b3b2da0642e50f 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_contents.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="290"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 9b0b56d9cf5ab27decf52c2a2cd212d5f9073455..88712bda5e6aa6e4a1eb1a8ecc320cfb0a0b556f 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -1,12 +1,13 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="275"
  layout="topleft"
+ title="Buy L$"
  name="buy currency"
  help_topic="buy_linden_dollars"
  single_instance="true"
- title="Buy L$"
  width="350">
     <floater.string
      name="buy_currency">
diff --git a/indra/newview/skins/default/xui/en/floater_buy_land.xml b/indra/newview/skins/default/xui/en/floater_buy_land.xml
index 6d1c2c1cb915d1d22cba86a3c621c207f376b670..83145491324b207533278e491338dc7ed355995f 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="484"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml
index 7930622e54cc6e4b4eebb18ee2ed46dd623f19b9..49ea3f5dd15179dd9bb7ad48654170421a762291 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="290"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml
index 520249c2a2136a56891e22cf72a39b5b7b5cc8dc..1b694180130cf6dff0e59b91fbf8c5201c47eb91 100644
--- a/indra/newview/skins/default/xui/en/floater_camera.xml
+++ b/indra/newview/skins/default/xui/en/floater_camera.xml
@@ -1,17 +1,18 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_dock="true"
- can_minimize="true"
- can_close="true" 
+ can_minimize="false"
+ can_close="true"
  center_horiz="true"
- follows="top"
- height="110"
+ follows="bottom"
+ height="152"
  layout="topleft"
  name="camera_floater"
  help_topic="camera_floater"
  save_rect="true"
  save_visibility="true"
- width="105">
+ width="150">
     <floater.string
      name="rotate_tooltip">
         Rotate Camera Around Focus
@@ -25,69 +26,71 @@
         Move Camera Up and Down, Left and Right
     </floater.string>
     <panel
-     border="true"
-     height="79"
+     border="false"
+     height="110"
      layout="topleft"
-     left="0"
+     left="2"
      top="0"
-     mouse_opaque="false" 
+     mouse_opaque="false"
      name="controls"
-     width="105">
-        <joystick_rotate
-         follows="top|left"
-         height="64"
-         image_selected="cam_rotate_in.tga"
-         image_unselected="cam_rotate_out.tga"
-         layout="topleft"
-         left="2"
-         name="cam_rotate_stick"
-         picture_style="true"
-         quadrant="left"
-         scale_image="false"
-         sound_flags="3"
-         tool_tip="Orbit camera around focus"
-         top="15"
-         width="64" />
+     width="148">
         <joystick_track
          follows="top|left"
-         height="64"
-         image_selected="cam_tracking_in.tga"
-         image_unselected="cam_tracking_out.tga"
+         height="78"
+         image_selected="Cam_Tracking_In"
+         image_unselected="Cam_Tracking_Out"
          layout="topleft"
-         left="2"
+         left="45"
          name="cam_track_stick"
          picture_style="true"
          quadrant="left"
          scale_image="false"
          sound_flags="3"
          tool_tip="Move camera up and down, left and right"
-         top="15"
+         top="22"
          visible="false"
-         width="64" />
+         width="78" />
+         <!--TODO: replace with slider, + - images -->
         <joystick_zoom
          follows="top|left"
-         height="64"
-         image_unselected="cam_zoom_out.tga"
+         height="78"
+         image_unselected="ScrollThumb_Vert"
          layout="topleft"
-         left_delta="70"
-         minus_image="cam_zoom_minus_in.tga"
+         left="7"
+         minus_image="ScrollThumb_Vert"
          name="zoom"
          picture_style="true"
-         plus_image="cam_zoom_plus_in.tga"
+         plus_image="ScrollThumb_Vert"
          quadrant="left"
          scale_image="false"
          sound_flags="3"
          tool_tip="Zoom camera toward focus"
-         top_delta="0"
-         width="16" />
+         top="22"
+         width="20" />
+         <joystick_rotate
+         follows="top|left"
+         height="78"
+         image_selected="Cam_Rotate_In"
+         image_unselected="Cam_Rotate_Out"
+         layout="topleft"
+         left="45"
+         name="cam_rotate_stick"
+         picture_style="true"
+         quadrant="left"
+         scale_image="false"
+         sound_flags="3"
+         visible="true"
+         tool_tip="Orbit camera around focus"
+         top="22"
+         width="78" />
         <panel
-         height="70"
+         height="78"
          layout="topleft"
-         left="15"
+         left="36"
          name="camera_presets"
-         top="15"
+         top="30"
          visible="false"
-         width="75">
+         width="78">
             <button
              height="30"
              image_selected="CameraPreset_Rear"
@@ -127,7 +130,7 @@
              name="front_view"
              picture_style="true"
              tool_tip="Front View"
-             top_pad="2"
+             top_pad="5"
              width="30">
                 <click_callback
                  function="CameraPresets.ChangeView"
@@ -151,21 +154,21 @@
         </panel>
     </panel>
     <panel
-     border="true"
-     height="25"
+     border="false"
+     height="42"
      layout="topleft"
-     left="0"
-     top_pad="1"
+     left="2"
+     top_pad="0"
      name="buttons"
-     width="105">
+     width="148">
         <button
          height="23"
          label=""
          layout="topleft"
-         left="2"
+         left="23"
          is_toggle="true"
          image_overlay="Cam_Orbit_Off"
-         image_selected="PushButton_Selected_Press" 
+         image_selected="PushButton_Selected_Press"
          name="orbit_btn"
          tab_stop="false"
          tool_tip="Orbit camera"
@@ -179,7 +182,7 @@
          left_pad="0"
          is_toggle="true"
          image_overlay="Cam_Pan_Off"
-         image_selected="PushButton_Selected_Press" 
+         image_selected="PushButton_Selected_Press"
          name="pan_btn"
          tab_stop="false"
          tool_tip="Pan camera"
@@ -191,7 +194,7 @@
          layout="topleft"
          left_pad="0"
          image_overlay="Cam_Avatar_Off"
-         image_selected="PushButton_Selected_Press" 
+         image_selected="PushButton_Selected_Press"
          name="avatarview_btn"
          tab_stop="false"
          tool_tip="See as avatar"
@@ -204,12 +207,11 @@
          left_pad="0"
          is_toggle="true"
          image_overlay="Cam_FreeCam_Off"
-         image_selected="PushButton_Selected_Press" 
+         image_selected="PushButton_Selected_Press"
          name="freecamera_btn"
          tab_stop="false"
          tool_tip="View object"
          width="25">
         </button>
-        
     </panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_choose_group.xml b/indra/newview/skins/default/xui/en/floater_choose_group.xml
index 371e239fdb3131a0cb2935ebec8a1042ceff6562..8b34fda96c64934ab05a8fabbe5c9b8bbadf0f2f 100644
--- a/indra/newview/skins/default/xui/en/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/en/floater_choose_group.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="258"
  layout="topleft"
  name="groups"
diff --git a/indra/newview/skins/default/xui/en/floater_color_picker.xml b/indra/newview/skins/default/xui/en/floater_color_picker.xml
index f2146339a7799383550460bfe31b550d9c53bd5a..686b8dc40fb808c54fa848941b86c41d7efd79d7 100644
--- a/indra/newview/skins/default/xui/en/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_color_picker.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  follows="left|top"
  height="380"
diff --git a/indra/newview/skins/default/xui/en/floater_critical.xml b/indra/newview/skins/default/xui/en/floater_critical.xml
index 5475a1cf6a56d712b9c235e24496a1da873a2ed1..7b5451553ff282fecd4a80ef8885d9569598096a 100644
--- a/indra/newview/skins/default/xui/en/floater_critical.xml
+++ b/indra/newview/skins/default/xui/en/floater_critical.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_close="false"
  can_minimize="false"
  height="500"
diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml
index 57f5800f2c6c1ce659ee61f2751198d28779b20b..07d76f4810025e8d62a59d9b3d4d4d0b9b7869ee 100644
--- a/indra/newview/skins/default/xui/en/floater_customize.xml
+++ b/indra/newview/skins/default/xui/en/floater_customize.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  follows="left|top"
  height="540"
diff --git a/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml
index b044cd41e644bec6ffd2072ca0ebf8a1efd920e7..b8fa104352a362b0b196bd12a1f88c003fb80ee9 100644
--- a/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="275"
  layout="topleft"
  name="Day Cycle Floater"
diff --git a/indra/newview/skins/default/xui/en/floater_device_settings.xml b/indra/newview/skins/default/xui/en/floater_device_settings.xml
index 8901608374326938da2c86a7b668bd2e67295cd3..2b23980423c0eac007abc17bb4dafda19e628f6c 100644
--- a/indra/newview/skins/default/xui/en/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/en/floater_device_settings.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="260"
  layout="topleft"
  name="floater_device_settings"
diff --git a/indra/newview/skins/default/xui/en/floater_env_settings.xml b/indra/newview/skins/default/xui/en/floater_env_settings.xml
index cecd6c4ef78847428818cb7785be8264fac409ba..7c22311f66a6cf2002da42d6373601ce57383d8a 100644
--- a/indra/newview/skins/default/xui/en/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/en/floater_env_settings.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="150"
  layout="topleft"
  name="Environment Editor Floater"
diff --git a/indra/newview/skins/default/xui/en/floater_first_time_tip.xml b/indra/newview/skins/default/xui/en/floater_first_time_tip.xml
index 49751111116da07407f62cdf7f80a1619e688e9d..e4ac8fed77afc45e1bb354b80c0b06145582b916 100644
--- a/indra/newview/skins/default/xui/en/floater_first_time_tip.xml
+++ b/indra/newview/skins/default/xui/en/floater_first_time_tip.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_close="true"
  can_minimize="false"
  height="250"
diff --git a/indra/newview/skins/default/xui/en/floater_font_test.xml b/indra/newview/skins/default/xui/en/floater_font_test.xml
index 66c207603b81e7f8bca8797ae271305b73b30f82..8b14f691d682a74eea8f482be2c9c3c4a3b0bf37 100644
--- a/indra/newview/skins/default/xui/en/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/en/floater_font_test.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="800"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_gesture.xml b/indra/newview/skins/default/xui/en/floater_gesture.xml
index 7346c81e79f64869596c8e9f1b5ac6523f64b9a8..128d518e12a07a04dc61022a5dbe82d46080106e 100644
--- a/indra/newview/skins/default/xui/en/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/en/floater_gesture.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="465"
  name="gestures"
diff --git a/indra/newview/skins/default/xui/en/floater_god_tools.xml b/indra/newview/skins/default/xui/en/floater_god_tools.xml
index 02754b25ddc64afe2d911eb261bee0aa47f1db38..97cb6e259c4c966f6c456a66ecac74e832d3bd55 100644
--- a/indra/newview/skins/default/xui/en/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_god_tools.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="384"
  layout="topleft"
  name="godtools floater"
diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml
index fe04d1f6271fe56b54aeae8dab6bead6b392303b..cd98f21918488ae18dac9759501e68250037f19a 100644
--- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="224"
  layout="topleft"
  name="Hardware Settings Floater"
@@ -131,7 +132,7 @@
      layout="topleft"
      left="10"
      max_val="4096"
-     name="GrapicsCardTextureMemory"
+     name="GraphicsCardTextureMemory"
      tool_tip="Amount of memory to allocate for textures. Defaults to video card memory. Reducing this may improve performance but may also make textures blurry."
      top_pad="10"
      width="300" />
diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml
index 512b4c85a1321c53933500c4c8c41de5a07068f1..d2fe8d0e6d71630bf8642f53825230fb1520b68b 100644
--- a/indra/newview/skins/default/xui/en/floater_help_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_hud.xml b/indra/newview/skins/default/xui/en/floater_hud.xml
index 23e0ef50fdd081b642d62d86ba39164ba743d27b..6e8950c49a49d9a4bf91871ffb41b6d08354e872 100644
--- a/indra/newview/skins/default/xui/en/floater_hud.xml
+++ b/indra/newview/skins/default/xui/en/floater_hud.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="292"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 0037c6ef0417ee8a30b44fdb32f3f5ab9a8a0692..26d2f4e497f707eb7cc6dd9647a4a9fe664d002f 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  background_visible="true"
  follows="left|top|right|bottom"
- height="250"
+ height="270"
  layout="topleft"
  left="0"
  name="panel_im"
@@ -16,7 +17,7 @@
  min_width="200"
  min_height="150">
   <layout_stack follows="left|top|right|bottom"
-                height="235"
+                height="255"
                 width="365"
                 layout="topleft"
                 orientation="horizontal"
@@ -28,11 +29,11 @@
       layout="topleft"
       top_delta="-3"
       width="146"
-      height="225"
+      height="255"
       follows="left"
       label="IM Control Panel"
       user_resize="false" />
-    <layout_panel height="235"
+    <layout_panel height="255"
                   width="200"
                   left_delta="146" 
                   top="0"
@@ -55,7 +56,7 @@
        length="1"
        follows="left|top|right|bottom"
        font="SansSerif"
-       height="185"
+       height="205"
        layout="topleft"
        name="chat_history"
        parse_highlights="true"
diff --git a/indra/newview/skins/default/xui/en/floater_image_preview.xml b/indra/newview/skins/default/xui/en/floater_image_preview.xml
index 4e4fe97e6276a8f4b8b67e40a4c61c3e6a896695..2562daf4b3d8f23abe9a80a94e913d37c7285d1e 100644
--- a/indra/newview/skins/default/xui/en/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_image_preview.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="440"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
index 95e4247a0580055be5dcabd3f259a181c909c34c..dcb93c6e2fa8d6aaff12d4059fc10871ab279ff2 100644
--- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_close="false"
  can_minimize="false"
  can_tear_off="false"
diff --git a/indra/newview/skins/default/xui/en/floater_inspect.xml b/indra/newview/skins/default/xui/en/floater_inspect.xml
index 339604e658db526b77b70febf3d24d7ed67f4680..9f7723c51bff9a3b9aa261da1ad0bdcd3a4a1789 100644
--- a/indra/newview/skins/default/xui/en/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/en/floater_inspect.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="300"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml
index 6afeb4e82d27b553973f9cee9f8e9e3c99441016..c7fcacab8bcf7b87cebf639be26254e867c6e4d8 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  can_resize="true"
  height="563"
@@ -41,13 +42,15 @@
      top="34"
      width="455" />
     <tab_container
-     follows="left|top|right|bottom"
+     follows="all"
      height="508"
+     halign="center"
      layout="topleft"
      left_delta="-4"
      name="inventory filter tabs"
      tab_position="top"
-     top_pad="4"
+     tab_height="20"
+     top_pad="5"
      width="463">
         <inventory_panel
          follows="left|top|right|bottom"
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
index e3e2decef7e322665750be4d7b6a911dc5cd44fe..4f0609c7f8ae68705ae1a0b0395206f8a22a4e3b 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  height="340"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
index 6556a147308db59af65b4dddb2f393f5047b808e..0042f97a8ee77d129454c47a039c2764ccdde637 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="408"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml
index c0bcfd2271c7962cac676511b742290422d4c375..e2da059ace18d682c145653caad527b0671a5679 100644
--- a/indra/newview/skins/default/xui/en/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/en/floater_joystick.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="500"
  layout="topleft"
  name="Joystick"
diff --git a/indra/newview/skins/default/xui/en/floater_lagmeter.xml b/indra/newview/skins/default/xui/en/floater_lagmeter.xml
index 2966b47232856dc41b1c208c685c19a2830ade1c..d98fdc5118be58d3176bcdc6a2c0c3397a5ffb4a 100644
--- a/indra/newview/skins/default/xui/en/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/en/floater_lagmeter.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="150"
  layout="topleft"
  name="floater_lagmeter"
diff --git a/indra/newview/skins/default/xui/en/floater_land_holdings.xml b/indra/newview/skins/default/xui/en/floater_land_holdings.xml
index dbafa560352acd09e197bae02ae1c32c57c5c041..46d74b6aff8a258eb284285f1cb31f650791c42e 100644
--- a/indra/newview/skins/default/xui/en/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/en/floater_land_holdings.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="400"
  layout="topleft"
  name="land holdings floater"
diff --git a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml
index dc6c8302a0a3b59ca88f326cb6a568d9c7e99021..93bbb0107eee8d437decbe3cc563bc6cb62c85c5 100644
--- a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  bevel_style="none"
  border_style="line"
  can_resize="true"
diff --git a/indra/newview/skins/default/xui/en/floater_lsl_guide.xml b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml
index fd2ee6ce5cab9c8b8e4385bfed3b3aa9220fd2b4..4dcf1686053701e0f280a42fd56a80b6f0d2f172 100644
--- a/indra/newview/skins/default/xui/en/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  follows="left|top"
  height="400"
diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml
index a2b2e1ddf37941896fb8ede4c987fc90e44d0826..7b4c5f38a18e2f506a665dcf1e5458ca922e760f 100644
--- a/indra/newview/skins/default/xui/en/floater_map.xml
+++ b/indra/newview/skins/default/xui/en/floater_map.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  follows="top|right"
  height="225"
diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml
index ad2c50c6d9ab1fb75037bf5008efa05d11250a23..b11892be74ca4d229af3e8b4156665b5db4ac71b 100644
--- a/indra/newview/skins/default/xui/en/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="440"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml
index 6ba26f938d9d501975c5f2c2be65a66e51642c76..4218c15408150e88c936d6899c6430c8f9813330 100644
--- a/indra/newview/skins/default/xui/en/floater_media_settings.xml
+++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml
@@ -1,20 +1,75 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater bottom="-666" can_close="true" can_drag_on_left="false" can_minimize="true"
-     can_resize="false" can_tear_off="true" default_tab_group="1" enabled="true"
-      width="365" height="535" left="330" min_height="430" min_width="620"
-     mouse_opaque="true" name="Medis Settings" title="Media Settings">
-	<button bottom="-525" enabled="true" follows="right|bottom" font="SansSerif"
-	     halign="center" height="20" label="OK" label_selected="OK" left="75"
-	     mouse_opaque="true" name="OK" scale_image="true" width="90" />
-	<button bottom_delta="0" enabled="true" follows="right|bottom" font="SansSerif"
-	     halign="center" height="20" label="Cancel" label_selected="Cancel"
-	     left_delta="93" mouse_opaque="true" name="Cancel" scale_image="true"
-	     width="90" />
-	<button bottom_delta="0" enabled="true" follows="right|bottom" font="SansSerif"
-	     halign="center" height="20" label="Apply" label_selected="Apply"
-	     left_delta="93" mouse_opaque="true" name="Apply" scale_image="true"
-	     width="90" />
-	<tab_container bottom="-500" enabled="true" follows="left|top|right|bottom" height="485"
-	     left="0" mouse_opaque="false" name="tab_container" tab_group="1"
-	     tab_position="top" tab_width="80" width="365" />
+<floater
+ legacy_header_height="18"
+ bottom="-666" 
+ can_close="true" 
+ can_drag_on_left="false" 
+ can_minimize="true"
+ can_resize="false" 
+ can_tear_off="true" 
+ default_tab_group="1" 
+ enabled="true"
+ width="365" 
+ height="535" 
+ left="330" 
+ min_height="430" 
+ min_width="620"
+ mouse_opaque="true" 
+ name="Medis Settings" 
+ help_topic = "media_settings"
+ title="Media Settings">
+	<button 
+	 bottom="-525" 
+	 enabled="true" 
+	 follows="right|bottom" 
+	 font="SansSerif"
+	 halign="center" 
+	 height="20" 
+	 label="OK" 
+	 label_selected="OK" 
+	 left="75"
+	 mouse_opaque="true" 
+	 name="OK" 
+	 scale_image="true" 
+	 width="90" />
+	<button 
+	 bottom_delta="0" 
+	 enabled="true" 
+	 follows="right|bottom" 
+	 font="SansSerif"
+	 halign="center" 
+	 height="20" 
+	 label="Cancel" 
+	 label_selected="Cancel"
+	 left_delta="93" 
+	 mouse_opaque="true" 
+	 name="Cancel" 
+	 scale_image="true"
+	 width="90" />
+	<button 
+	 bottom_delta="0" 
+	 enabled="true" 
+	 follows="right|bottom" 
+	 font="SansSerif"
+	 halign="center" 
+	 height="20" 
+	 label="Apply" 
+	 label_selected="Apply"
+	 left_delta="93" 
+	 mouse_opaque="true" 
+	 name="Apply" 
+	 scale_image="true"
+	 width="90" />
+	<tab_container 
+	 bottom="-500" 
+	 enabled="true" 
+	 follows="left|top|right|bottom" 
+	 height="485"
+	 left="0" 
+	 mouse_opaque="false" 
+	 name="tab_container" 
+	 tab_group="1"
+	 tab_position="top" 
+	 tab_width="80" 
+	 width="365" />
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml
index bd83da02aa8e0aada2c37a51e0e949ac25053ed0..560acafd4f8f65e74c0751e947b9e1724e982994 100644
--- a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  follows="left|top"
  height="175"
diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml
index 745385f153b93e203b38928c5e508769df9d3504..02cbef5987e3591121b3dfb15fe3a77ca6fe39a6 100644
--- a/indra/newview/skins/default/xui/en/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/en/floater_moveview.xml
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_dock="true"
  can_close="true"
- can_minimize="true"
+ can_minimize="false"
  center_horiz="true"
  follows="bottom"
  height="110"
@@ -37,7 +38,7 @@
         Fly Backwards (press Down Arrow or S)
     </string>
     <panel
-     border="true" 
+     border="false" 
      height="83"
      follows="left|top" 
      layout="topleft"
@@ -135,7 +136,7 @@
     </panel>
 <!-- Width and height of this panel should be synchronized with panel_stand_stop_flying.xml -->
     <panel
-     border="true" 
+     border="false" 
      height="27"
      layout="topleft"
      left="0"
diff --git a/indra/newview/skins/default/xui/en/floater_mute_object.xml b/indra/newview/skins/default/xui/en/floater_mute_object.xml
index 06a03ff340358ba35b21f3340e894c8ddc5b198b..33b1dac8a559c3bdf3159a0e4994ad3654e66f00 100644
--- a/indra/newview/skins/default/xui/en/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_mute_object.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="130"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_my_friends.xml b/indra/newview/skins/default/xui/en/floater_my_friends.xml
index 0ca4fc825a8267350d7e4b1c16a5b2a03ff82eca..689221b9c791954198c5d90b14e8182d7af2d4a8 100644
--- a/indra/newview/skins/default/xui/en/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/en/floater_my_friends.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_close="false"
  can_resize="true"
  height="390"
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 25d337ccec457be62e2f0d131d93ccff25e49beb..e7c5bf85857f34e08b37a4b02f176e6b0f2cc6fd 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater 
+<floater
+ legacy_header_height="18"
  can_minimize="true"
  can_tear_off="false"
  can_resize="false"
@@ -13,7 +14,9 @@
  help_topic="nearby_chat"
  save_rect="true"
  title="Nearby Chat"
+ save_dock_state="true"
  save_visibility="true"
+ single_instance="true"
  width="320">
             <chat_history
              allow_html="true" 
diff --git a/indra/newview/skins/default/xui/en/floater_notification.xml b/indra/newview/skins/default/xui/en/floater_notification.xml
index cd88ec2f3f13b884a6428206030b4e2685a0298e..f9cb22055ae67db6bc0aa78c01d0c2f5ad107a3b 100644
--- a/indra/newview/skins/default/xui/en/floater_notification.xml
+++ b/indra/newview/skins/default/xui/en/floater_notification.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="200"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_notifications_console.xml b/indra/newview/skins/default/xui/en/floater_notifications_console.xml
index 3783417cdb646c27ff349d45b80c06fac18a6506..03a2aad96d48c1906d6ef1f4088ecf3a26ce77dc 100644
--- a/indra/newview/skins/default/xui/en/floater_notifications_console.xml
+++ b/indra/newview/skins/default/xui/en/floater_notifications_console.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="500"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml
index 17f7e9bf67b8971432d20e1807c339f66830fb8a..cc50f43339c9d02152577f10eeed1a2061021c0a 100644
--- a/indra/newview/skins/default/xui/en/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/en/floater_openobject.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  default_tab_group="1"
  height="350"
diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml
index 5f70f09a344b4a7104fa46f0eb3bec9bea27b4e5..b4becfa0225e606ae3f597a868f7d2d2a7b0c947 100644
--- a/indra/newview/skins/default/xui/en/floater_pay.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="185"
  layout="topleft"
@@ -34,7 +35,7 @@
      type="string"
      length="1"
      follows="left|top"
-     font="SansSerif"
+     font="SansSerifSmall"
      height="16"
      layout="topleft"
      left_pad="7"
@@ -44,6 +45,7 @@
     </text>
     <button
      height="23"
+     font="SansSerifSmall"  
      label="L$1"
      label_selected="L$1"
      layout="topleft"
@@ -53,7 +55,8 @@
      width="80" />
     <button
      height="23"
-     label="L$5"
+     label="L$1"
+     font="SansSerif"  
      label_selected="L$5"
      layout="topleft"
      left_pad="15"
@@ -62,6 +65,7 @@
     <button
      height="23"
      label="L$10"
+     font="SansSerifHuge"  
      label_selected="L$10"
      layout="topleft"
      left="25"
diff --git a/indra/newview/skins/default/xui/en/floater_pay_object.xml b/indra/newview/skins/default/xui/en/floater_pay_object.xml
index acff55386bd0a6c9a49d3bf06e61b98f33978fcb..8d230023cc85296bbb37009efaa23bba248674de 100644
--- a/indra/newview/skins/default/xui/en/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay_object.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="220"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
index f65bb6f32f876c5c6dcaaed3afc454594f93358c..eb0c22b9c493e92725cfdace4751950093a7abb4 100644
--- a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="180"
  layout="topleft"
  name="perm prefs"
diff --git a/indra/newview/skins/default/xui/en/floater_post_process.xml b/indra/newview/skins/default/xui/en/floater_post_process.xml
index 571f4149f08e28590bf101ed2f3f13f30b7d748b..46554beedea917db56d691744d4631aa3eab0a7f 100644
--- a/indra/newview/skins/default/xui/en/floater_post_process.xml
+++ b/indra/newview/skins/default/xui/en/floater_post_process.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="400"
  layout="topleft"
  name="Post-Process Floater"
diff --git a/indra/newview/skins/default/xui/en/floater_postcard.xml b/indra/newview/skins/default/xui/en/floater_postcard.xml
index d93cad6dbd04e34970a4fc2585269232e7157de9..b13bd1740cd5adbd77458ea3da7186a1e99d7ab8 100644
--- a/indra/newview/skins/default/xui/en/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/en/floater_postcard.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  can_minimize="false"
  can_resize="true"
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 285045f2c8a216e2ad03b098d919cfd62649f792..d2a2a7ce023e1c0fb6b5951ed80d9fc10ab8a422 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  center_horiz="true"
  center_vert="true"
  default_tab_group="1"
@@ -12,32 +13,32 @@
  width="620">
     <button
      follows="right|bottom"
-     height="20"
+     height="23"
      label="OK"
      label_selected="OK"
      layout="topleft"
-     left="427"
+     right="-105"
      name="OK"
-     top="435"
+     top="433"
      width="90">
         <button.commit_callback
          function="Pref.OK" />
     </button>
     <button
      follows="right|bottom"
-     height="20"
+     height="23"
      label="Cancel"
      label_selected="Cancel"
      layout="topleft"
-     left_pad="3"
+     left_pad="5"
      name="Cancel"
-     top_delta="0"
+     right="-10"
      width="90" >
         <button.commit_callback
          function="Pref.Cancel" />
     </button>
     <tab_container
-     follows="left|top|right|bottom"
+     follows="all"
      height="410"
      layout="topleft"
      left="0"
@@ -48,14 +49,14 @@
      top="21"
      width="620">
         <panel
-		 class="panel_preference"
+	 class="panel_preference"
          filename="panel_preferences_general.xml"
          label="General"
          layout="topleft"
          help_topic="preferences_general_tab"
          name="general" />
         <panel
-		 class="panel_preference"
+	 class="panel_preference"
          filename="panel_preferences_graphics1.xml"
          label="Graphics"
          layout="topleft"
@@ -103,13 +104,6 @@
          layout="topleft"
          help_topic="preferences_advanced1_tab"
          name="advanced1" />
-        <panel
-		 class="panel_preference"
-         filename="panel_preferences_advanced2.xml"
-         label="Move or Kill"
-         layout="topleft"
-         help_topic="preferences_advanced2_tab"
-         name="advanced2" />
     </tab_container>
 
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_animation.xml b/indra/newview/skins/default/xui/en/floater_preview_animation.xml
index e34b87dbbae34ccb66f1ec51c9c20cfa03d2394a..3b843584845237deb79394191a5da4cf57fe3221 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_animation.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  height="85"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_classified.xml b/indra/newview/skins/default/xui/en/floater_preview_classified.xml
index 07167c3ae449d7bcd2629458b4bb7faf7fe3694e..7c8c6d72077d8a16d2bfdc307f3cb60e788b61ef 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_classified.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  height="510"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_event.xml b/indra/newview/skins/default/xui/en/floater_preview_event.xml
index 77fbe7c060ef3f1d169498b4c82838e0ea06112a..f5ab8c95d710c8f044f8824daeecfc9a4f080d22 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_event.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  height="510"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
index a523f40bb821b1af80cf0dbc665f8ae00833c59e..4f3978a5e37e1f5deca63f8fbd718f5a2eb123f0 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
- height="800"
+ height="460"
  layout="topleft"
  name="gesture_preview"
  help_topic="gesture_preview"
@@ -46,10 +47,11 @@
      height="10"
      layout="topleft"
      left="10"
-     name="Name"
+     name="desc_label"
      top="25"
+     font.style="BOLD"
      width="100">
-        Name (not working yet):
+        Description:
     </text>
     <line_editor
      follows="left|top"
@@ -67,70 +69,270 @@
      height="10"
      layout="topleft"
      left="10"
-     name="desc_label"
+     font.style="BOLD"
+     name="trigger_label"
      top_pad="10"
      width="100">
-        Description:
+        Trigger:
     </text>
     <line_editor
      follows="left|top"
-     height="40"
+     height="20"
+     layout="topleft"
+     left_delta="84"
+     max_length="31"
+     name="trigger_editor"
+     top_delta="-4"
+     width="180" />
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifSmall"
+     height="10"
+     layout="topleft"
+     left="10"
+     font.style="BOLD"
+     name="replace_text"
+     tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture!"
+     top_pad="10"
+     width="200">
+        Replace with:
+    </text>
+    <line_editor
+     follows="left|top"
+     height="20"
+     layout="topleft"
+     left_delta="84"
+     max_length="31"
+     name="replace_editor"
+     tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture"
+     top_delta="-4"
+     width="180" />
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifSmall"
+     height="10"
+     layout="topleft"
+     left="10"
+     font.style="BOLD"
+     name="key_label"
+     top_pad="10"
+     width="100">
+        Shortcut Key:
+    </text>
+    <combo_box
+     height="20"
+     label="None"
      layout="topleft"
      left_delta="84"
-     name="desc2"
+     name="modifier_combo"
      top_delta="-4"
+     width="75" />
+    <combo_box
+     height="20"
+     label="None"
+     layout="topleft"
+     left_pad="10"
+     name="key_combo"
+     top_delta="0"
+     width="75" />
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifSmall"
+     height="10"
+     layout="topleft"
+     left="10"
+     font.style="BOLD"
+     name="library_label"
+     top="135"
+     width="100">
+        Library:
+    </text>
+    <scroll_list
+     follows="top|left"
+     height="60"
+     layout="topleft"
+     left="10"
+     name="library_list"
+     top="150"
+     width="180">
+        <scroll_list.rows
+         value="Animation" />
+        <scroll_list.rows
+         value="Sound" />
+        <scroll_list.rows
+         value="Chat" />
+        <scroll_list.rows
+         value="Wait" />
+    </scroll_list>
+    <button
+     follows="top|left"
+     height="20"
+     font="SansSerifSmall"
+     label="Add &gt;&gt;"
+     layout="topleft"
+     left_pad="10"
+     name="add_btn"
+     top_delta="0"
+     width="70" />
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifSmall"
+     height="10"
+     layout="topleft"
+     left="10"
+     font.style="BOLD"
+     name="steps_label"
+     top_pad="50"
+     width="100">
+        Steps:
+    </text>
+    <scroll_list
+     follows="top|left"
+     height="85"
+     layout="topleft"
+     left="10"
+     name="step_list"
+     top_pad="5"
      width="180" />
-    
-    <accordion
-     layout="topleft"
-     left="2"
-     width="276"
-     top="95"
-     height="580"
-     follows="all"
-     name="group_accordion">
-    <accordion_tab
-     min_height="90"
-     title="Shortcuts"
-     name="snapshot_destination_tab" 
-     an_resize="false">
-    <panel
-     class="floater_preview_shortcut"
-     filename="floater_preview_gesture_shortcut.xml"
-     name="floater_preview_shortcut"/>
-    </accordion_tab>
-    <accordion_tab
-     min_height="400"
-     title="Steps"
-     name="snapshot_file_settings_tab"
-     can_resize="false">
-    <panel
-     class="floater_preview_steps"
-     filename="floater_preview_gesture_steps.xml"
-     name="floater_preview_steps"/> 
-    </accordion_tab>
-    <accordion_tab
-     min_height="155"
-     title="Info"
-     name="snapshot_capture_tab"
-     can_resize="false">
-    <panel
-     class="floater_preview_info"
-     filename="floater_preview_gesture_info.xml"
-     name="floater_preview_info"/> 
-    </accordion_tab>
-    <!--accordion_tab
-     min_height="100"
-     title="Permissions"
-     name="snapshot_capture_tab2"
-     can_resize="false">
-    <panel
-     class="floater_snapshot_capture"
-     filename="floater_snapshot_Permissions.xml"
-     name="snapshot_capture_panel2"/> 
-    </accordion_tab-->
-    </accordion>
-    <!--check_box
+    <button
+     follows="top|left"
+     height="20"
+     font="SansSerifSmall"
+     label="Up"
+     layout="topleft"
+     left_pad="10"
+     name="up_btn"
+     top_delta="0"
+     width="70" />
+    <button
+     follows="top|left"
+     height="20"
+     font="SansSerifSmall"
+     label="Down"
+     layout="topleft"
+     left_delta="0"
+     name="down_btn"
+     top_pad="10"
+     width="70" />
+    <button
+     follows="top|left"
+     height="20"
+     font="SansSerifSmall"
+     label="Remove"
+     layout="topleft"
+     left_delta="0"
+     name="delete_btn"
+     top_pad="10"
+     width="70" />
+    <text
+     follows="top|left"
+     height="60"
+     layout="topleft"
+     left="15"
+     name="options_text"
+     top="330"
+     width="205" />
+    <combo_box
+     follows="top|left"
+     height="20"
+     layout="topleft"
+     left_delta="15"
+     name="animation_list"
+     top="345"
+     width="100" />
+    <combo_box
+     follows="top|left"
+     height="20"
+     layout="topleft"
+     left_delta="0"
+     name="sound_list"
+     top_delta="0"
+     width="100" />
+    <line_editor
+     follows="top|left"
+     height="20"
+     layout="topleft"
+     left_delta="0"
+     max_length="127"
+     name="chat_editor"
+     top_delta="0"
+     width="100" />
+    <radio_group
+     draw_border="false"
+     follows="top|left"
+     height="40"
+     layout="topleft"
+     left_pad="8"
+     name="animation_trigger_type"
+     top_delta="0"
+     width="80">
+        <radio_item
+         height="16"
+         label="Start"
+         layout="topleft"
+         left="3"
+         name="start"
+         top="-11"
+         width="80" />
+        <radio_item
+         height="16"
+         label="Stop"
+         layout="topleft"
+         left_delta="0"
+         name="stop"
+         top_pad="10"
+         width="80" />
+    </radio_group>
+    <check_box
+     follows="top|left"
+     height="20"
+     label="until animations are done"
+     layout="topleft"
+     left="16"
+     name="wait_anim_check"
+     top="340"
+     width="100" />
+    <check_box
+     follows="top|left"
+     height="20"
+     label="time in seconds"
+     layout="topleft"
+     left_delta="0"
+     name="wait_time_check"
+     top_delta="20"
+     width="100" />
+    <line_editor
+     follows="top|left"
+     height="20"
+     layout="topleft"
+     left_pad="5"
+     max_length="15"
+     name="wait_time_editor"
+     top_delta="0"
+     width="50" />
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifSmall"
+     height="30"
+     layout="topleft"
+     left="10"
+     name="help_label"
+     top_pad="20"
+     word_wrap="true"
+     width="265">
+        All steps happen simultaneously, unless you add wait steps.
+    </text>
+    <check_box
      follows="top|left"
      height="20"
      label="Active"
@@ -138,35 +340,24 @@
      left="20"
      name="active_check"
      tool_tip="Active gestures can be triggered by chatting their trigger phrases or pressing their hot keys.  Gestures usually become inactive when there is a key binding conflict."
-     top="365"
-     width="100" /-->  
-    
+     top_pad="0"
+     width="100" />
     <button
-     follows="bottom|left"
+     follows="top|left"
      height="20"
      label="Preview"
      layout="topleft"
-     left="20"
+     left_delta="75"
      name="preview_btn"
-     top_pad="30"
+     top_delta="2"
      width="80" />
     <button
      follows="top|left"
      height="20"
      label="Save"
      layout="topleft"
-     left_pad="5"
+     left_pad="10"
      name="save_btn"
      top_delta="0"
      width="80" />
-    <button
-     follows="top|left"
-     height="20"
-     label="Cancel (not working)"
-     layout="topleft"
-     left_pad="5"
-     name="cancel_btn"
-     top_delta="0"
-     width="80" />   
-
 </floater>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml
index 43e4f8a3489d1a1b95d80e43aa6963c952c36bd7..fc838f27b4ba30b4e9c071a3ec780c8da7db1be3 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  follows="left|top"
  height="155"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml
index 606ae1a82a0ef20ba2e675669a17b503d5635821..b489ae2e771ffdf0343326109bff58c21b09a5ef 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  follows="left|top"
  height="90"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml
index 4b4f611b598f4cf464d457645dfdbe99c784d8dd..8a07f3ad1ed84c6059f64ece762092413a90faf9 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  follows="left|top"
  height="155"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
index 8cdafe110a79acba7d98ce8edcd102d2edaec618..3797055054863f87ed92372093f4c0851efee938 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  can_resize="true"
  default_tab_group="1"
@@ -83,7 +84,7 @@
         Loading...
     </text_editor>
     <button
-     follows="left|bottom"
+     follows="right|bottom"
      height="22"
      label="Save"
      label_selected="Save"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_sound.xml b/indra/newview/skins/default/xui/en/floater_preview_sound.xml
index 7a868a1fe9ce01fe71f60a610d222896df876f41..95347f0dff60a92c90d6286102d87785daa63788 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_sound.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_sound.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  height="85"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_texture.xml b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
index 32f71da61abdbb19957c63025775c0ba1071d83f..e7abfb075af419bb3d92da1130e0606fc97fe7ea 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  can_resize="true"
  follows="left|bottom"
diff --git a/indra/newview/skins/default/xui/en/floater_region_info.xml b/indra/newview/skins/default/xui/en/floater_region_info.xml
index 3fadc156162a4dab8295db17d10d3f46e0318c9d..ae01d0bdf43feb31cd05cc728599c7a4654446fc 100644
--- a/indra/newview/skins/default/xui/en/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/en/floater_region_info.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="512"
  help_topic="regioninfo"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index abde4ba5fad6e541578000b1faefe9c60999185f..88f09b521cc87f7139a70ba0d6d984460173b44f 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="580"
  layout="topleft"
  name="floater_report_abuse"
@@ -14,19 +15,19 @@
      allow_no_texture="true"
      default_image_name="None"
      follows="left|top"
-     height="125"
+     height="150"
      layout="topleft"
-     left="10"
-     name="screenshot"
-     top="23"
-     width="160" />
+     left="60"
+     name=""
+     top="15"
+     width="220" />
     <check_box
      height="15"
      label="Use this screenshot"
      layout="topleft"
-     left_pad="5"
+     left="8"
      name="screen_check"
-     top="120"
+     top_pad="-12"
      width="116" />
     <text
      type="string"
@@ -38,8 +39,8 @@
      layout="topleft"
      left="10"
      name="reporter_title"
-     top="140"
-     width="60">
+     top_pad="0"
+     width="100">
         Reporter:
     </text>
     <text
@@ -48,24 +49,25 @@
      follows="left|top"
      height="16"
      layout="topleft"
-     left_pad="10"
+     left_pad="5"
      name="reporter_field"
      top_delta="0"
-     width="193">
-        Loremipsum Dolorsitamut
+     use_ellipses="true"
+     width="200">
+        Loremipsum Dolorsitamut Longnamez
     </text>
     <text
      type="string"
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="10"
      name="sim_title"
-     top_pad="5"
-     width="60">
+     top_pad="2"
+     width="100">
         Region:
     </text>
     <text
@@ -74,10 +76,11 @@
      follows="left|top"
      height="16"
      layout="topleft"
-     left_pad="2"
+     left_pad="5"
      name="sim_field"
      top_delta="0"
-     width="193">
+     use_ellipses="true"
+     width="200">
         Region Name
     </text>
     <text
@@ -85,13 +88,13 @@
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="10"
      name="pos_title"
-     top_pad="5"
-     width="50">
+     top_pad="2"
+     width="100">
         Position:
     </text>
     <text
@@ -100,10 +103,10 @@
      follows="left|top"
      height="16"
      layout="topleft"
-     left_pad="12"
+     left_pad="5"
      name="pos_field"
      top_delta="0"
-     width="193">
+     width="200">
         {128.1, 128.1, 15.4}
     </text>
  <text
@@ -114,7 +117,7 @@
      layout="topleft"
      left="10"
      name="select_object_label"
-     top_pad="5"
+     top_pad="2"
      width="310">
         Click the button, then the abusive object:
     </text>
@@ -133,13 +136,13 @@
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="48"
      name="object_name_label"
      top_delta="0"
-     width="60">
+     width="80">
         Object:
     </text>
     <text
@@ -151,7 +154,8 @@
      left_pad="6"
      name="object_name"
      top_delta="0"
-     width="157">
+     use_ellipses="true"
+     width="185">
         Consetetur Sadipscing
     </text>
     <text
@@ -159,13 +163,13 @@
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="48"
      name="owner_name_label"
      top_pad="0"
-     width="60">
+     width="80">
         Owner:
     </text>
     <text
@@ -177,8 +181,9 @@
      left_pad="6"
      name="owner_name"
      top_delta="0"
-     width="157">
-        Hendrerit Vulputate
+     use_ellipses="true"
+     width="185">
+        Hendrerit Vulputate Kamawashi Longname
     </text>
     <combo_box
      height="23"
@@ -349,8 +354,8 @@
      type="string"
      length="1"
      follows="left|top"
-     height="16"
-     font.name="SansSerif" 
+     height="14"
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left_delta="0"
@@ -368,11 +373,10 @@
      left_delta="0"
      max_length="32"
      name="abuser_name_edit"
-     top_pad="2"
+     top_pad="0"
      width="195" />
     <button
      height="23"
-     font="SansSerifSmall"
      label="Choose"
      layout="topleft"
      left_pad="5"
@@ -394,13 +398,13 @@
      type="string"
      length="1"
      follows="left|top"
-     height="16"
-     font.name="SansSerif" 
+     height="14"
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="10"
      name="abuser_name_title2"
-     top_pad="5"
+     top_pad="2"
      width="313">
         Location of Abuse:
     </text>
@@ -413,19 +417,19 @@
      left="10"
      max_length="256"
      name="abuse_location_edit"
-     top_pad="2"
+     top_pad="0"
      width="313" />
     <text
      type="string"
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left_delta="0"
      name="sum_title"
-     top_pad="5"
+     top_pad="2"
      width="313">
         Summary:
     </text>
@@ -438,14 +442,14 @@
      left_delta="0"
      max_length="64"
      name="summary_edit"
-     top_pad="2"
+     top_pad="0"
      width="313" />
     <text
      type="string"
      length="1"
      follows="left|top"
-     height="16"
-     font.name="SansSerif" 
+     height="14"
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left_delta="0"
@@ -461,9 +465,9 @@
      height="16"
      layout="topleft"
      name="bug_aviso"
-     left_pad="0"
+     left_pad="10"
      width="200">
-        Please be as specific as possible.
+        Please be as specific as possible
     </text>
     <text_editor
      follows="left|top"
@@ -479,16 +483,15 @@
      type="string"
      length="1"
      follows="left|top"
-     height="50"
+     height="30"
      layout="topleft"
      left="10"
-     font.name="SansSerif" 
-     font.style="BOLD"
+     font.name="SansSerifSmall"
      name="incomplete_title"
-     top_pad="5"
+     top_pad="2"
      word_wrap="true"
      width="313">
-        Note: Incomplete reports won't be investigated.
+        * Incomplete reports won't be investigated
     </text>
      <button
      left="80"
diff --git a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
index 2085b74a55488cb43fad9ea5a8c5ec548b6a7e42..0029fcb09b5a79154cb009244ea1fb6fa4df8706 100644
--- a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  follows="left|top|right|bottom"
  height="200"
diff --git a/indra/newview/skins/default/xui/en/floater_script_preview.xml b/indra/newview/skins/default/xui/en/floater_script_preview.xml
index a4152398675915a03576a9e6250914684ee4ebb4..c29a2f4516c8ef6c4610a037258cb1e66ed2f7ec 100644
--- a/indra/newview/skins/default/xui/en/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_preview.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  can_resize="true"
  height="550"
diff --git a/indra/newview/skins/default/xui/en/floater_script_queue.xml b/indra/newview/skins/default/xui/en/floater_script_queue.xml
index 467dcfae20a08ea065c22aa008194b5b00aff141..8a442524266268d8c7a738dbfd46ecd959e30853 100644
--- a/indra/newview/skins/default/xui/en/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_queue.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  auto_tile="true"
  can_resize="true"
  height="400"
diff --git a/indra/newview/skins/default/xui/en/floater_script_search.xml b/indra/newview/skins/default/xui/en/floater_script_search.xml
index 545abc39a25385547872a8fd48ef0168efc07ccb..79c4438dd6b06c58c47bdd26c5f3843de11416b6 100644
--- a/indra/newview/skins/default/xui/en/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_search.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  default_tab_group="1"
  height="120"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml
index 296cde92e3487ba531b78026123da2b0e2bed024..2f4d7c50a161c19bb4188c53b2fa47c0c4b99290 100644
--- a/indra/newview/skins/default/xui/en/floater_search.xml
+++ b/indra/newview/skins/default/xui/en/floater_search.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_select_key.xml b/indra/newview/skins/default/xui/en/floater_select_key.xml
index b89af0ef3e68bc0a0f50e90b73b2d28dcef92f5e..31d133ff9b96345a3f759fa3a1cb0127edaf6bf7 100644
--- a/indra/newview/skins/default/xui/en/floater_select_key.xml
+++ b/indra/newview/skins/default/xui/en/floater_select_key.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  border="true"
  can_close="false"
  can_minimize="false"
diff --git a/indra/newview/skins/default/xui/en/floater_sell_land.xml b/indra/newview/skins/default/xui/en/floater_sell_land.xml
index 652ed96192782806290c1c569acc0a797508f7a7..8fedd0a89f0cfead5a933fc073c8c05f69805a66 100644
--- a/indra/newview/skins/default/xui/en/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_sell_land.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="450"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_settings_debug.xml b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
index b7779687ec39a3e81fe5f0c8c263d6e2db1e53cf..02b3cee97c25ac2c1249eecb652e2ddb95cf0e87 100644
--- a/indra/newview/skins/default/xui/en/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="215"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index 551f570b52f993735eace403034c6e7829c7f766..4f2be37ade687b2166acfc179706bb656590ed04 100644
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  follows="left|top"
  height="526"
diff --git a/indra/newview/skins/default/xui/en/floater_sound_preview.xml b/indra/newview/skins/default/xui/en/floater_sound_preview.xml
index 3b1eae9293568a78ffffb95cb875a66f2761562a..6145b722f1c062902e02f47528244b35bfd2b6ef 100644
--- a/indra/newview/skins/default/xui/en/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_sound_preview.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="190"
  layout="topleft"
  name="Sound Preview"
diff --git a/indra/newview/skins/default/xui/en/floater_statistics.xml b/indra/newview/skins/default/xui/en/floater_statistics.xml
index 653bc942e59023361c5c1241c393eaca7697e4f7..ab783b0735a7778db1477567a9c73e58444cc472 100644
--- a/indra/newview/skins/default/xui/en/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/en/floater_statistics.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  follows="right|top"
  height="392"
diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml
index 205e6efe700ae48c176a1c7e8ac7d4afd4e8eeab..bdc287428149e690481412986e1412a0258302d7 100644
--- a/indra/newview/skins/default/xui/en/floater_stats.xml
+++ b/indra/newview/skins/default/xui/en/floater_stats.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  follows="top|right"
  height="400"
diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml
index aef5707fd4efeeac34ee1710e61619362d14277f..e1f07a49e78604691e765280b13e720a995145be 100644
--- a/indra/newview/skins/default/xui/en/floater_sys_well.xml
+++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater 
+<floater
+ legacy_header_height="18"
  bevel_style="in"
  left="0"
  top="0" 
diff --git a/indra/newview/skins/default/xui/en/floater_telehub.xml b/indra/newview/skins/default/xui/en/floater_telehub.xml
index 95de27e0ea8f9ea105d5a3488baf7245bf2796e2..faf1a378f259a8fb84a54e43f14fafc6f00e6d46 100644
--- a/indra/newview/skins/default/xui/en/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/en/floater_telehub.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="250"
  layout="topleft"
  name="telehub"
diff --git a/indra/newview/skins/default/xui/en/floater_test_button.xml b/indra/newview/skins/default/xui/en/floater_test_button.xml
index ce17873a6763c1e24aab59bfed1ca958d557901d..89a1ddda99ee8c793d58bc1b318c1a47e5d51613 100644
--- a/indra/newview/skins/default/xui/en/floater_test_button.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_button.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="500"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_checkbox.xml b/indra/newview/skins/default/xui/en/floater_test_checkbox.xml
index 66a5b9267dfabe11aacbf265a79d34b942873861..9977e85a9d19f533983a9e03325e375755b6d846 100644
--- a/indra/newview/skins/default/xui/en/floater_test_checkbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_checkbox.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
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 956d5669b8c3b6813cab275492ea3996dac56d0a..317d8f5ba86460ae08e0f7b940fa8d896f8f5ffb 100644
--- a/indra/newview/skins/default/xui/en/floater_test_combobox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_combobox.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
index ce20b03919f8d8195755fe4f3900e345d81cd51b..c954607ffe7e82bf69f765b43ed99c15c2e854ac 100644
--- a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="false"
  height="400"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_layout.xml b/indra/newview/skins/default/xui/en/floater_test_layout.xml
index 209859bb298a8da4d6ef9e07418c82715e09b376..c6acb7c96e57337de339dd134939eb7abac49b09 100644
--- a/indra/newview/skins/default/xui/en/floater_test_layout.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_layout.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="500"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
index 251ca4c9bf5894ef4bdcc2b2f419a58640b234d8..e017d404c61a1b62f2bff133c1c3c1de4b3e9dd2 100644
--- a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_list_view.xml b/indra/newview/skins/default/xui/en/floater_test_list_view.xml
index 98d6d5bda773b14a8736cec8ecc0420ba8c82b4d..1d2086d9bc60fc854e202521244e00536f7703ed 100644
--- a/indra/newview/skins/default/xui/en/floater_test_list_view.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_list_view.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml b/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml
index dd551b6d5146456ee4fde662e94e6b830dbe0f97..c6b4cca6b9f6797040d440644efd83b38795d36b 100644
--- a/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="200"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml b/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml
index 35190c0e1abd6bcd9a71d6fc6d23f1e76704eda8..7ef2d97cdc93eb6d0e6cf633e53329bf0e57e018 100644
--- a/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_slider.xml b/indra/newview/skins/default/xui/en/floater_test_slider.xml
index 3545f88df7fd3d27938284521cae07435b1d6972..57d8e686ce3d5235a2a9003a90d6d00b86c8071a 100644
--- a/indra/newview/skins/default/xui/en/floater_test_slider.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_slider.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_spinner.xml b/indra/newview/skins/default/xui/en/floater_test_spinner.xml
index c4e5bc9e99d79972efb6c3e3ad9d75584e918e84..3c44a4884d8a589c787cf76d521898d863c040a9 100644
--- a/indra/newview/skins/default/xui/en/floater_test_spinner.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_spinner.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
index 8305452c850b968c296282dad8939c005b6f237c..f39d27761cdf94e811a8069ea198f5d23af50df8 100644
--- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="400"
  layout="topleft"
@@ -114,16 +115,59 @@
         Escaped greater than &gt;
     </text>
     <text
-     type="string"
-     length="1"
-     bottom="390"
-     label="N"
-     layout="topleft"
-     left="10"
-     name="floater_map_north"
-     right="30"
-     text_color="1 1 1 0.7"
-     top="370">
-        N
-    </text>
+   type="string"
+   length="1"
+   bottom="390"
+   label="N"
+   layout="topleft"
+   left="10"
+   name="right_aligned_text"
+   width="380"
+   halign="right" 
+   text_color="1 1 1 0.7"
+   top_pad="10">
+    Right aligned text
+  </text>
+  <text
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="centered_text"
+ width="380"
+ halign="center"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+    Centered text
+  </text>
+  <text
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="centered_text"
+ width="380"
+ halign="left"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+    Left aligned text
+  </text>
+  <text
+   type="string"
+   length="1"
+   bottom="390"
+   label="N"
+   layout="topleft"
+   left="10"
+   name="floater_map_north"
+   right="30"
+   text_color="1 1 1 0.7"
+   top="370">
+    N
+  </text>
+
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_widgets.xml b/indra/newview/skins/default/xui/en/floater_test_widgets.xml
index cc0fc34dd5939f9466fa2d10378e5dfa07730c14..129fd863dd4da93d59e45e441020136d29ee449d 100644
--- a/indra/newview/skins/default/xui/en/floater_test_widgets.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<!-- Sample "floater" window with examples of common widgets. 
+<!-- Sample "floater" window with examples of common widgets.
 
     Notes:
     XML UI (XUI) files use spaces for indentation, not tabs.
@@ -15,17 +15,18 @@
     Otherwise specify location with left and top attributes.
 -->
 <floater
- can_dock="true" 
+ legacy_header_height="18"
+ can_dock="true"
  can_resize="true"
  title="Test Floater"
  height="500"
- min_width="850" 
- min_height="500" 
+ min_width="850"
+ min_height="500"
  layout="topleft"
  name="floater_test_widgets"
  help_topic="floater_test_widgets"
  width="850">
- 
+
   <!-- Strings are used by C++ code for localization.  They are not visible
        unless the C++ code uses them to fill in another widget. -->
   <floater.string
@@ -34,15 +35,15 @@
   <floater.string
    name="other_string"
    value="Other String" />
-   
+
   <!-- Floaters can contain drop-down menus.
        The menu_bar widget contains the inividual menus.
        The width is automatically computed to fit the labels. -->
   <menu_bar
    height="18"
    layout="topleft"
-   follows="top|left" 
-   tool_tip="menu" 
+   follows="top|left"
+   tool_tip="menu"
    left="2"
    name="test_menu_bar"
    top="16">
@@ -70,7 +71,7 @@
        name="test_menu_item_2" />
     </menu>
   </menu_bar>
-  
+
   <!-- "text" is one or more read-only lines of text.
        It can be made clickable but this requires C++ code
        support.  URLs are not automatically underlined. -->
@@ -84,27 +85,27 @@
   </text>
 
   <!-- First column -->
-  
+
   <button
    height="20"
-   follows="top|left" 
+   follows="top|left"
    label="Button"
    layout="topleft"
    left_delta="0"
    name="test_button"
-   tool_tip="button" 
+   tool_tip="button"
    top="80"
-   width="100" />  
+   width="100" />
   <!-- "flyout_button" is a button that can spawn a menu -->
   <flyout_button
-   follows="top|left" 
+   follows="top|left"
    height="20"
    label="Flyout"
    layout="topleft"
    left_delta="0"
    name="fly_btn"
    top_pad="15"
-   tool_tip="flyout button" 
+   tool_tip="flyout button"
    width="100">
     <flyout_button.item
      label="Item 1"
@@ -120,19 +121,19 @@
    bottom_delta="35"
    label="Checkbox"
    layout="topleft"
-   tool_tip="checkbox" 
+   tool_tip="checkbox"
    name="test_checkbox" />
   <!-- "combo_box" is a pop-menu of items.  Optionally the box itself can
        contain a general purpose line input editor, allowing the user to
        provide input that is not a list item. -->
   <combo_box
    bottom_delta="35"
-   follows="top|left" 
+   follows="top|left"
    height="16"
    width="150"
    label="Combobox"
    layout="topleft"
-   tool_tip="combo box" 
+   tool_tip="combo box"
    name="test_combo_box">
     <combo_box.item
      name="item1"
@@ -148,21 +149,21 @@
    image_name="icon_avatar_online.tga"
    layout="topleft"
    left_delta="0"
-   tool_tip="icon" 
+   tool_tip="icon"
    name="test_icon"
    top_pad="40"
    width="16" />
-  <!-- "line_editor" allows a single line of editable text input. 
+  <!-- "line_editor" allows a single line of editable text input.
         The contents of this XML node are used as the initial value for
         the text. -->
   <line_editor
    height="20"
-   follows="top|left" 
+   follows="top|left"
    layout="topleft"
    left_delta="0"
    name="test_line_editor"
    top_pad="20"
-   tool_tip="line editor" 
+   tool_tip="line editor"
    width="200">
     Line Editor Sample Text
   </line_editor>
@@ -175,18 +176,18 @@
    layout="topleft"
    left_delta="0"
    name="search editor"
-   tool_tip="search editor" 
+   tool_tip="search editor"
    top_pad="30"
    width="200" />
   <!-- "progress_bar" percent completed gets set in C++ code -->
   <progress_bar
    height="16"
-   follows="top|left" 
+   follows="top|left"
    layout="topleft"
    left_delta="0"
    name="test_progress_bar"
    top_pad="30"
-   tool_tip="progress bar" 
+   tool_tip="progress bar"
    width="200" />
   <!-- "stat_view" is a container for statistics graphs.  It is only used
        for debugging/diagnostic displays. -->
@@ -198,10 +199,10 @@
    name="axis_view"
    show_label="true"
    top_pad="30"
-   tool_tip="stat view" 
+   tool_tip="stat view"
    width="200">
     <stat_bar
-     width="100" 
+     width="100"
      bar_max="100"
      bottom_delta="30"
      label="Test Stat"
@@ -210,9 +211,9 @@
      bar_min="20"
      name="test_stat_bar" />
   </stat_view>
-  
+
   <!-- New column -->
-  
+
   <!-- "radio_group" is a set of mutually exclusive choices, like the buttons
        on a car radio that allow a single radio station to be chosen. -->
   <radio_group
@@ -220,7 +221,7 @@
    layout="topleft"
    left_pad="90"
    name="size_radio_group"
-   tool_tip="radio group" 
+   tool_tip="radio group"
    top="80"
    width="200">
     <radio_item
@@ -236,10 +237,10 @@
   <!-- "scroll_list" is a scrolling list of columnar data. -->
   <scroll_list
    bottom_delta="100"
-   follows="top|left" 
+   follows="top|left"
    height="80"
    draw_heading="true"
-   tool_tip="scroll list" 
+   tool_tip="scroll list"
    layout="topleft">
     <scroll_list.columns
      dynamic_width="true"
@@ -261,29 +262,29 @@
   <!-- "slider" is a horizontal input widget for numerical data. -->
   <slider
    bottom_delta="45"
-   follows="top|left" 
+   follows="top|left"
    layout="topleft"
    min_val="0"
    max_val="100"
    initial_value="20"
    label="Slider"
    name="test_slider"
-   tool_tip="slider" 
+   tool_tip="slider"
    width="200" />
   <!-- "spinner" is a numerical input widget with an up and down arrow to
        change the value. -->
   <spinner
    bottom_delta="35"
-   follows="top|left" 
+   follows="top|left"
    label="Spinner"
    layout="topleft"
-   label_width="45" 
-   name="test_spinner" 
+   label_width="45"
+   name="test_spinner"
    tool_tip="spinner"/>
   <text
    bottom_delta="50"
-   follows="top|left" 
-   font.name="SansSerifSmall" 
+   follows="top|left"
+   font.name="SansSerifSmall"
    font.style = "UNDERLINE"
    layout="topleft"
    name="test_text"
@@ -292,23 +293,23 @@
   </text>
   <text
    top_pad="10"
-   follows="top|left" 
+   follows="top|left"
    layout="topleft"
-   width="60" 
-   use_ellipses="true" 
+   width="60"
+   use_ellipses="true"
    name="test_text"
    tool_tip="text">
     Truncated text here
   </text>
-  <!-- "text_editor" is a multi-line text input widget, similar to 
+  <!-- "text_editor" is a multi-line text input widget, similar to
        textarea in HTML. -->
   <text_editor
    height="40"
-   follows="top|left|bottom" 
+   follows="top|left|bottom"
    layout="topleft"
    left_delta="0"
    name="test_text_editor"
-   tool_tip="text editor" 
+   tool_tip="text editor"
    top_pad="25"
    width="200">
     Text Editor
@@ -329,17 +330,19 @@ many
 line to actually fit
   </text>
   <!-- And a third column -->
-  
+
   <!-- "tab_container" is a holder for multiple panels of UI widgets.
        Tabs can appear at the top, bottom, or left of the container. -->
   <tab_container
    follows="all"
    height="400"
+   halign="center"
    layout="topleft"
    left="575"
    name="group_tab_container"
    tab_position="top"
-   tool_tip="tab container" 
+   tab_height="20"
+   tool_tip="tab container"
    top="80"
    width="250">
     <!-- "panel" is a container for widgets.  It is automatically resized to
diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
index f2b701b88d33ad76ee4e5c3e82e35888a412e9d5..0a1f6e0e2973d6b07e0ea0f644f8f6afccc42804 100644
--- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  can_resize="true"
  height="290"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index c15811f0e8e74b879d9a22256054f782937cefb3..4da424b89c989c9d39c2213c48b32ba83178fde7 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -1,8 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  follows="left|top|right"
  height="570"
  layout="topleft"
+ bg_opaque_image="Window_NoTitle_Foreground"
+ bg_alpha_image="Window_NoTitle_Background"
  name="toolbox floater"
  help_topic="toolbox_floater"
  save_rect="true"
@@ -207,71 +210,71 @@
      layout="topleft"
      name="move_radio_group">
         <radio_item
-      top_pad="6"
+         top_pad="6"
          label="Move"
          layout="topleft"
          name="radio move" />
         <radio_item
-      top_pad="6"
+		 top_pad="6"
          label="Lift (Ctrl)"
          layout="topleft"
          name="radio lift" />
         <radio_item
-      top_pad="6"
+         top_pad="6"
          label="Spin (Ctrl+Shift)"
          layout="topleft"
          name="radio spin" />
 		 <radio_group.commit_callback
-	     function="BuildTool.commitRadioMove"/>
-   </radio_group>
-    <radio_group
+			function="BuildTool.commitRadioMove"/>
+	</radio_group>
+	<radio_group
      follows="left|top"
-      left="10"
-      top="54"
-      height="70"
+	 left="10"
+	 top="54"
+	 height="70"
      layout="topleft"
-     name="edit_radio_group">
+	 name="edit_radio_group">
         <radio_item
-         label="Move"
-         layout="topleft"
-         name="radio position" />
+		 label="Move"
+		 layout="topleft"
+		 name="radio position" />
         <radio_item
-      top_pad="6"
+		 top_pad="6"
          label="Rotate (Ctrl)"
          layout="topleft"
          name="radio rotate" />
         <radio_item
-      top_pad="6"
+		 top_pad="6"
          label="Stretch (Ctrl+Shift)"
          layout="topleft"
          name="radio stretch" />
         <radio_item
-      top_pad="6"
-         label="Select Texture"
+		 top_pad="6"
+         label="Select Face"
          layout="topleft"
          name="radio select face" />
-		  <radio_group.commit_callback
-	     function="BuildTool.commitRadioEdit"/>
+			<radio_group.commit_callback
+			function="BuildTool.commitRadioEdit"/>
     </radio_group>
     <check_box
      left="10"
      follows="left|top"
      height="16"
-      control_name="EditLinkedParts"
+	 control_name="EditLinkedParts"
      label="Edit linked"
      layout="topleft"
      name="checkbox edit linked parts" >
 		  <check_box.commit_callback
-	     function="BuildTool.selectComponent"/>
+			function="BuildTool.selectComponent"/>
 	</check_box>
-        <check_box
+	<check_box
      control_name="ScaleUniform"
      height="19"
      label="Stretch Both Sides"
      layout="topleft"
      left="143"
      name="checkbox uniform"
-      top="50"
+	 top="50"
      width="134" />
     <check_box
      control_name="ScaleStretchTextures"
@@ -312,7 +315,7 @@
 		 <combo_box.commit_callback
 	     function="BuildTool.gridMode"/>
     </combo_box>
-   <button
+    <button
      left_pad="0"
      image_disabled="ForwardArrow_Disabled"
      image_selected="ForwardArrow_Press"
@@ -746,6 +749,7 @@
     <tab_container
      follows="left|top"
      height="400"
+     halign="center"
      left="0"
      name="Object Info Tabs"
      tab_max_width="55"
@@ -754,24 +758,24 @@
      tab_height="25"
      top="170"
      width="280">
-        <panel
-         border="false"
-         follows="all"
-         label="General"
-         layout="topleft"
-         mouse_opaque="false"
-         help_topic="toolbox_general_tab"
-         name="General"
-         top="16"
-         width="280">
-            <panel.string
-             name="text deed continued">
-                Deed
-            </panel.string>
-            <panel.string
-             name="text deed">
-                Deed
-            </panel.string>
+	<panel
+	 border="false"
+	 follows="all"
+	 label="General"
+	 layout="topleft"
+	 mouse_opaque="false"
+	 help_topic="toolbox_general_tab"
+	 name="General"
+	 top="16"
+	 width="280">
+	 <panel.string
+	  name="text deed continued">
+		Deed
+	 </panel.string>
+	<panel.string
+	 name="text deed">
+		Deed
+	</panel.string>
             <panel.string
              name="text modify info 1">
                 You can modify this object
@@ -912,21 +916,21 @@
              width="75">
                 Group:
             </text>
-           <button
-     follows="top|left"
-     height="10"
-     image_disabled="Activate_Checkmark"
-     image_selected="Activate_Checkmark"
-     image_unselected="Activate_Checkmark"
-     image_color="White_50"
-     layout="topleft"
-     left_pad="0"
-     top_delta="0"
-     name="button set group"
-     picture_style="true"
-     tab_stop="false"
-     tool_tip="Choose a group to share this object's permissions"
-     width="10" />
+            <button
+			 follows="top|left"
+			 height="10"
+			 image_disabled="Activate_Checkmark"
+			 image_selected="Activate_Checkmark"
+			 image_unselected="Activate_Checkmark"
+			 image_color="White_50"
+			 layout="topleft"
+			 left_pad="0"
+			 top_delta="0"
+			 name="button set group"
+			 picture_style="true"
+			 tab_stop="false"
+			 tool_tip="Choose a group to share this object's permissions"
+			 width="10" />
             <name_box
              follows="left|top"
              height="18"
@@ -1046,15 +1050,15 @@
         height="20"
         max_val="999999999" />
       <check_box
-             height="15"
-             width="110"
-             top_pad="3"
-             label="Show in search"
+	   height="15"
+	   width="110"
+	   top_pad="3"
+	   label="Show in search"
        layout="topleft"
-        left="100"
+	   left="100"
        name="search_check"
        tool_tip="Let people see this object in search results" />
-<panel
+		<panel
          border="false"
          follows="left|top"
          layout="topleft"
@@ -2356,7 +2360,7 @@
              left_delta="0"
              name="combobox texgen"
              top_pad="4"
-             width="87">
+             width="60">
                 <combo_box.item
                  label="Default"
                  name="Default"
@@ -2375,7 +2379,7 @@
              name="label shininess"
              left_pad="5"
              top_pad="-36"
-             width="80">
+             width="60">
                 Shininess
             </text>
             <combo_box
@@ -2384,7 +2388,7 @@
              left_delta="0"
              name="combobox shininess"
              top_pad="4"
-             width="80">
+             width="60">
                 <combo_box.item
                  label="None"
                  name="None"
@@ -2587,9 +2591,9 @@
              height="19"
              increment="1"
              initial_value="0"
-	    label="RotationËš"
+			 label="RotationËš"
              layout="topleft"
-	    label_width="100"
+			 label_width="100"
              left="10"
              max_val="9999"
              min_val="-9999"
@@ -2602,9 +2606,9 @@
              follows="left|top"
              height="19"
              initial_value="1"
-	    label="Repeats / Meter"
+			 label="Repeats / Meter"
              layout="topleft"
-	    label_width="100"
+			 label_width="100"
              left="10"
              max_val="10"
              min_val="0.1"
@@ -2657,7 +2661,7 @@
              name="TexOffsetV"
              top_pad="1"
              width="160" />
-      <panel
+        <panel
          border="false"
          follows="left|top"
          layout="topleft"
@@ -2670,88 +2674,99 @@
          height="75"
          width="278">
             <text
-           type="string"
-           length="1"
-           follows="left|top"
-           height="12"
-           layout="topleft"
-           left="10"
-           top_pad="5"
-           name="media_tex"
-           width="260">
-            Media URL
-	    </text>
-	    <line_editor
-             follows="left|top|right"
-             height="18"
-             layout="topleft"
-             left="10"
-	    read_only="true"
-             name="media_info"
-             select_on_focus="true"
-             width="220" />
-            <button
-            follows="top|left"
-            height="18"
-            image_selected="AddItem_Press"
-            image_unselected="AddItem_Off"
-            image_disabled="AddItem_Disabled"
-            layout="topleft"
-            left_pad="0"
-            name="add_media"
-            picture_style="true"
-            tab_stop="false"
-            top_delta="0"
-            tool_tip="Add media"
-            width="18">
-            <button.commit_callback
-		function="BuildTool.AddMedia"/>
-	</button>
-            <button
-                 follows="bottom|left"
-                 height="18"
-                 image_selected="TrashItem_Press"
-                 image_unselected="TrashItem_Off"
-                 layout="topleft"
-                 left_pad="5"
-                 name="delete_media"
-                 picture_style="true"
-                 right="-10"
-                 tool_tip="Delete this media texture"
-                 top_delta="0"
-                 width="18">
-	    <button.commit_callback
-		function="BuildTool.DeleteMedia"/>
-	     </button>
-         <button
+             type="string"
+             length="1"
              follows="left|top"
-             font="SansSerifSmall"
-             height="19"
-             label="Align"
-             label_selected="Align Media"
+             height="12"
              layout="topleft"
              left="10"
-             name="button align"
              top_pad="5"
-             width="100" />
-              <button
-               follows="bottom|left"
-               tool_tip="Change sort and view of recent residents list"
-               height="18"
-               image_disabled="OptionsMenu_Disabled"
-               image_selected="OptionsMenu_Press"
-               image_unselected="OptionsMenu_Off"
-               layout="topleft"
-               left_pad="10"
-               name="edit_media"
-               picture_style="true"
-               top_delta="0"
-               width="18">
-               <button.commit_callback
-		function="BuildTool.EditMedia"/>
-	       </button>
-            </panel>
-        </panel>
+             name="media_tex"
+             width="260">
+              Media URL
+			</text>
+			<line_editor
+			 follows="left|top|right"
+			 height="18"
+			 layout="topleft"
+			 left="10"
+			 read_only="true"
+			 name="media_info"
+			 select_on_focus="true"
+			 width="180" />
+			<button
+			 follows="top|left"
+			 height="18"
+			 image_selected="AddItem_Press"
+			 image_unselected="AddItem_Off"
+			 image_disabled="AddItem_Disabled"
+			 layout="topleft"
+			 left_pad="0"
+			 name="add_media"
+			 picture_style="true"
+			 tab_stop="false"
+			 top_delta="0"
+			 tool_tip="Add Media"
+			 width="18">
+				<button.commit_callback
+				function="BuildTool.AddMedia"/>
+			</button>
+			<button
+			 follows="top|left"
+			 height="18"
+			 image_selected="TrashItem_Press"
+			 image_unselected="TrashItem_Off"
+			 layout="topleft"
+			 left_pad="5"
+			 name="delete_media"
+			 picture_style="true"
+			 tool_tip="Delete this media texture"
+			 top_delta="0"
+			 width="18">
+				<button.commit_callback
+				function="BuildTool.DeleteMedia"/>
+			</button>
+			<button
+			 follows="top|left"
+			 tool_tip="Edit this Media"
+			 height="18"
+			 image_disabled="OptionsMenu_Disabled"
+			 image_selected="OptionsMenu_Press"
+			 image_unselected="OptionsMenu_Off"
+			 layout="topleft"
+			 left_pad="10"
+			 name="edit_media"
+			 picture_style="true"
+			 top_delta="0"
+			 width="18">
+				<button.commit_callback
+				function="BuildTool.EditMedia"/>
+			</button>
+      <web_browser
+        visible="false"
+        enabled="false"
+        border_visible="true"
+        bottom_delta="0"
+        follows="top|left"
+        left="0"
+        name="title_media"
+        width="4"
+        height="4"
+        start_url="about:blank"
+        decouple_texture_size="true" />
+     <button
+			 follows="left|top"
+			 font="SansSerifSmall"
+			 height="19"
+			 label="Align"
+			 label_selected="Align Media"
+			 layout="topleft"
+			 left="10"
+			 name="button align"
+			 top_pad="5"
+			 width="100" />
+		</panel>
+	   </panel>
        <panel
          border="false"
          follows="all"
@@ -2789,10 +2804,10 @@
              name="contents_inventory"
              top="50"
              width="260" />
-	 </panel>
+		</panel>
         </tab_container>
-<panel
-      follows="left|top"
+	<panel
+	 follows="left|top"
      height="384"
      layout="topleft"
      left_delta="0"
@@ -2839,8 +2854,8 @@
         <button
          follows="left|top"
          height="20"
-         label="Land profile"
-         label_selected="Land profile"
+         label="About Land"
+         label_selected="About Land"
          layout="topleft"
          left_delta="0"
          name="button about land"
diff --git a/indra/newview/skins/default/xui/en/floater_top_objects.xml b/indra/newview/skins/default/xui/en/floater_top_objects.xml
index 07ffc204f97856e725ee6d13c52c13c4d297bc8a..2f53422d5138f068cd657ca18d899adb1a48d13c 100644
--- a/indra/newview/skins/default/xui/en/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/en/floater_top_objects.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="350"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_tos.xml b/indra/newview/skins/default/xui/en/floater_tos.xml
index 54facbb659153afa7a19f4d172496feecad9cdba..4e2cce1428c392baeb908d6bcca5d8af31bdd722 100644
--- a/indra/newview/skins/default/xui/en/floater_tos.xml
+++ b/indra/newview/skins/default/xui/en/floater_tos.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_close="false"
  can_minimize="false"
  height="500"
diff --git a/indra/newview/skins/default/xui/en/floater_ui_preview.xml b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
index acd770cd388c83e6365b8e60f8fa43aeab71fdd1..380e51977f2d73d3068dc632b4f6fa96138dc2aa 100644
--- a/indra/newview/skins/default/xui/en/floater_ui_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  height="640"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_url_entry.xml b/indra/newview/skins/default/xui/en/floater_url_entry.xml
index 6c1fb65bddd46255cb8fa215ed0f559a7dc71ad8..1ab42cb14066d9275063717460d33bb00da47b55 100644
--- a/indra/newview/skins/default/xui/en/floater_url_entry.xml
+++ b/indra/newview/skins/default/xui/en/floater_url_entry.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="87"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml
index a860b1038c9763907514e5cadb2c0c5e08804694..af3606fd1c01819976d494f86ce6561ca5a94e9e 100644
--- a/indra/newview/skins/default/xui/en/floater_water.xml
+++ b/indra/newview/skins/default/xui/en/floater_water.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="240"
  layout="topleft"
  name="Water Floater"
@@ -61,10 +62,12 @@
     <tab_container
      follows="left|top"
      height="180"
+     halign="center"
      layout="topleft"
      left="0"
      name="Water Tabs"
      tab_position="top"
+     tab_height="20"
      top="60"
      width="700">
         <panel
diff --git a/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml
index ee67989d332d3d3eac34373aaa2142ceb5876d76..9a95e3dfeffa0c830c283a948384a94610b5b425 100644
--- a/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml
+++ b/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  border="true"
  can_close="false"
  can_minimize="false"
diff --git a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
index 4f501b65f37b63888f9181b2a8405908e94e4d3d..ef68d03a450726c6947697a39782f189486aefd4 100644
--- a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
+++ b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_minimize="false"
  height="108"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_windlight_options.xml b/indra/newview/skins/default/xui/en/floater_windlight_options.xml
index 2b3bc5f11ac150d7a05bd9885fb4aa113c2dfdf1..2c09e82f087577e85ef18dfd8ee6574376fc90d0 100644
--- a/indra/newview/skins/default/xui/en/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_windlight_options.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  height="220"
  layout="topleft"
  name="WindLight floater"
@@ -70,10 +71,12 @@
     <tab_container
      follows="left|top"
      height="160"
+     halign="center"
      layout="topleft"
      left="0"
      name="WindLight Tabs"
      tab_position="top"
+     tab_height="20"
      top="60"
      width="700">
         <panel
diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml
index f37c0e90224c132f43d41ba9f9f06486c732426c..93755fa2532021473d9715e066a51d8b87faaa00 100644
--- a/indra/newview/skins/default/xui/en/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/en/floater_world_map.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
+ legacy_header_height="18"
  can_resize="true"
  center_horiz="true"
  center_vert="true"
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
index b261281c640925c283d3d1336f129bca759aff63..65dfb13f4a3096915034dfc5375c427bf344efa5 100644
--- a/indra/newview/skins/default/xui/en/fonts.xml
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -18,7 +18,7 @@
     </os>
   </font>
 
-  <font name="SansSerifBold" 
+  <font name="SansSerifBold"
 	comment="Name of bold sans-serif font">
     <file>DejaVuSans-Bold.ttf</file>
     <os name="Windows">
@@ -39,20 +39,20 @@
       </os>
   </font>
 
-  <font name="SansSerif" 
-	comment="Name of bold sans-serif font" 
+  <font name="SansSerif"
+	comment="Name of bold sans-serif font"
 	font_style="BOLD">
     <file>DejaVuSans-Bold.ttf</file>
   </font>
 
-  <font name="SansSerif" 
-	comment="Name of italic sans-serif font" 
+  <font name="SansSerif"
+	comment="Name of italic sans-serif font"
 	font_style="ITALIC">
     <file>DejaVuSans-Oblique.ttf</file>
   </font>
 
-  <font name="SansSerif" 
-	comment="Name of bold italic sans-serif font" 
+  <font name="SansSerif"
+	comment="Name of bold italic sans-serif font"
 	font_style="BOLD|ITALIC">
     <file>DejaVuSans-BoldOblique.ttf</file>
   </font>
@@ -140,11 +140,11 @@
 
   <font_size name="Monospace"
 	     comment="Size for monospaced font (points, or 1/72 of an inch)"
-	     size="9.0"
+	     size="8.0"
 	     />
   <font_size name="Huge"
 	     comment="Size of huge font (points, or 1/72 of an inch)"
-	     size="16.0"
+	     size="15.0"
 	     />
   <font_size name="Large"
 	     comment="Size of large font (points, or 1/72 of an inch)"
@@ -158,7 +158,6 @@
 	     />
   <font_size name="Small"
 	     comment="Size of small font (points, or 1/72 of an inch)"
-	     size="8.0"
+	     size="7.8"
 	     />
 </fonts>
-
diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml
index 181c80ebc75d6d6ae924f3f4d71e3d529f08693a..6b13e2f1c7cbd4f5c56f7b03cf308ef737ec3e36 100644
--- a/indra/newview/skins/default/xui/en/inspect_avatar.xml
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml
@@ -4,8 +4,9 @@
   Single instance - only have one at a time, recycle it each spawn
 -->
 <floater
+ legacy_header_height="18"
  bevel_style="in"
- bg_opaque_color="MouseGray"
+ bg_opaque_image="Inspector_Background" 
  can_close="false"
  can_minimize="false"
  height="138"
diff --git a/indra/newview/skins/default/xui/en/inspect_group.xml b/indra/newview/skins/default/xui/en/inspect_group.xml
index 5b166e83b876def4efa175e85f70c650424bc908..db12daa6e04074ada14db2fbe644e7b7ad3a4ce9 100644
--- a/indra/newview/skins/default/xui/en/inspect_group.xml
+++ b/indra/newview/skins/default/xui/en/inspect_group.xml
@@ -4,8 +4,9 @@
   Single instance - only have one at a time, recycle it each spawn
 -->
 <floater
+ legacy_header_height="18"
  bevel_style="in"
- bg_opaque_color="MouseGray"
+ bg_opaque_image="Inspector_Background" 
  can_close="false"
  can_minimize="false"
  height="138"
diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml
index 73a7bef77d9f35daeffb133f0581da90c744a36f..fe492e0ae808f60ef1f02b6aa026405739f3ef80 100644
--- a/indra/newview/skins/default/xui/en/inspect_object.xml
+++ b/indra/newview/skins/default/xui/en/inspect_object.xml
@@ -4,8 +4,9 @@
   Single instance - only have one at a time, recycle it each spawn
 -->
 <floater
+ legacy_header_height="18"
  bevel_style="in"
- bg_opaque_color="MouseGray"
+ bg_opaque_image="Inspector_Background" 
  can_close="false"
  can_minimize="false"
  height="145"
@@ -70,7 +71,7 @@ owner James Linden
    width="150">
 L$300,000
   </text>
-    <text
+   <text
    follows="all"
    height="30"
    left="8"
@@ -83,24 +84,35 @@ This is a really long description for an object being as how it is at least 80 c
   </text>
   <!-- Overlapping buttons for all default actions.  Show "Buy" if
   for sale, "Sit" if can sit, etc. -->
+   <text
+   follows="all"
+   height="15"
+   left_delta="0"
+   name="object_media_url"
+   top_pad="-5"
+   width="291"
+   max_length = "50" 
+   use_ellipses="true"
+   word_wrap="true"/>   
+    
   <button
-     follows="top|left"
-     font="SansSerif"
-     height="23"
-     label="Buy"
-     left="10"
-     name="buy_btn"
-     top="114"
-     width="100" />
+   follows="top|left"
+   font="SansSerif"
+   height="20"
+   label="Buy"
+   left="10"
+   name="buy_btn"
+   top="114"
+   width="75" />
   <button
    follows="top|left"
    font="SansSerif"
-   height="23"
+   height="20"
    label="Pay"
    left_delta="0"
    name="pay_btn"
    top_delta="0"
-   width="100" />
+   width="75" />
   <button
    follows="top|left"
    font="SansSerif"
@@ -109,16 +121,16 @@ This is a really long description for an object being as how it is at least 80 c
    left_delta="0"
    name="take_free_copy_btn"
    top_delta="0"
-   width="100" />
+   width="75" />
   <button
    follows="top|left"
    font="SansSerifSmall"
-   height="23"
+   height="20"
    label="Touch"
    left_delta="0"
    name="touch_btn"
    top_delta="0"
-   width="100" />
+   width="75" />
   <button
    follows="top|left"
    font="SansSerif"
@@ -127,17 +139,27 @@ This is a really long description for an object being as how it is at least 80 c
    left_delta="0"
    name="sit_btn"
    top_delta="0"
-   width="100" />
+   width="75" />
   <button
    follows="top|left"
    font="SansSerifSmall"
-   height="23"
+   height="20"
    label="Open"
    left_delta="0"
    name="open_btn"
    top_delta="0"
-   width="100" />
-  <!-- non-overlapping buttons here -->
+   width="75" />
+  <icon
+   name="secure_browsing"
+   image_name="map_infohub.tga"
+   left_delta="80"
+   width="16"
+   height="16"
+   top_delta="2"
+   tool_tip="Secure Browsing"
+   follows="left|top"/> 
+   
+ <!--  non-overlapping buttons here -->
     <menu_button
      follows="top|left"
      height="18"
diff --git a/indra/newview/skins/default/xui/en/menu_object_icon.xml b/indra/newview/skins/default/xui/en/menu_object_icon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0c8a2af0028cf74c0b862b5cc39820cb6f512e76
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_object_icon.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="101"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="Object Icon Menu"
+ top="724"
+ visible="false"
+ width="128">
+    <menu_item_call
+     label="Object Profile..."
+     layout="topleft"
+     name="Object Profile">
+        <menu_item_call.on_click
+         function="ObjectIcon.Action"
+         parameter="profile" />
+    </menu_item_call>
+    <menu_item_call
+     label="Block..."
+     layout="topleft"
+     name="Block">
+        <menu_item_call.on_click
+         function="ObjectIcon.Action"
+         parameter="block" />
+    </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
index cc17e9dd4b7acfef22d5166aa3453775da984669..eedb4383bbf830af85bacdd688f9b018e15307aa 100644
--- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
@@ -23,9 +23,14 @@
        parameter="sort_status" />
   </menu_item_check>
   <menu_item_separator layout="topleft" />
-  <menu_item_call name="view_icons" label="View People Icons">
-    <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="view_icons" />
-  </menu_item_call>
+  <menu_item_check name="view_icons" label="View People Icons">
+    <menu_item_check.on_click
+     function="People.Friends.ViewSort.Action"
+     parameter="view_icons" />
+    <menu_item_check.on_check
+     function="CheckControl"
+     parameter="FriendsListShowIcons" />
+  </menu_item_check>
   <menu_item_call name="organize_offline" label="Organize Offline Friends">
     <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="organize_offline" />
   </menu_item_call>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
index f91a9613886e57546bee93e13ced298e0d202ba6..c002cd078f7c2d2bf7bf73cb4b72917e66df9f90 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
@@ -12,9 +12,14 @@
     <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_distance" />
   </menu_item_call>
   <menu_item_separator layout="topleft" />
-  <menu_item_call name="view_icons" label="View People Icons">
-    <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="view_icons" />
-  </menu_item_call>
+  <menu_item_check name="view_icons" label="View People Icons">
+    <menu_item_check.on_click
+     function="People.Nearby.ViewSort.Action"
+     parameter="view_icons" />
+    <menu_item_check.on_check
+     function="CheckControl"
+     parameter="NearbyListShowIcons" />
+  </menu_item_check>
   <menu_item_separator layout="topleft" />
   <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
     <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
index d09871cff3a6262ee6b00a3d3ac4fa950e6226b5..cfd6dc78b601feac8a46b8dcd265a83b076dfaa4 100644
--- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
@@ -23,9 +23,14 @@
        parameter="sort_name" />
   </menu_item_check>
   <menu_item_separator layout="topleft" />
-  <menu_item_call name="view_icons" label="View People Icons">
-    <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="view_icons" />
-  </menu_item_call>
+  <menu_item_check name="view_icons" label="View People Icons">
+    <menu_item_check.on_click
+     function="People.Recent.ViewSort.Action"
+     parameter="view_icons" />
+    <menu_item_check.on_check
+     function="CheckControl"
+     parameter="RecentListShowIcons" />
+  </menu_item_check>
   <menu_item_separator layout="topleft" />
   <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
     <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
diff --git a/indra/newview/skins/default/xui/en/menu_place_add_button.xml b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e3a39a1242748c8b73874fc851b73cdd77f1db4a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_folder_gear"
+ visible="false">
+    <menu_item_call
+     label="Add Folder"
+     layout="topleft"
+     name="add_folder">
+        <on_click
+         function="Places.LandmarksGear.Add.Action"
+         parameter="category" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="category" />
+    </menu_item_call>
+    <menu_item_call
+     label="Add Landmark"
+     layout="topleft"
+     name="add_landmark">
+        <on_click
+         function="Places.LandmarksGear.Add.Action"
+         parameter="add_landmark" />
+    </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_text_editor.xml b/indra/newview/skins/default/xui/en/menu_text_editor.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7c9e6f0796287044faf435d0247abd4bf4416232
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_text_editor.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ name="Text editor context menu">
+  <menu_item_call
+   label="Cut"
+   layout="topleft"
+   name="Cut"
+   shortcut="control|X">
+    <menu_item_call.on_click
+     function="Edit.Cut" />
+    <menu_item_call.on_enable
+     function="Edit.EnableCut" />
+  </menu_item_call>
+  <menu_item_call
+   label="Copy"
+   layout="topleft"
+   name="Copy"
+   shortcut="control|C">
+    <menu_item_call.on_click
+     function="Edit.Copy" />
+    <menu_item_call.on_enable
+     function="Edit.EnableCopy" />
+  </menu_item_call>
+  <menu_item_call
+   label="Paste"
+   layout="topleft"
+   name="Paste"
+   shortcut="control|V">
+    <menu_item_call.on_click
+     function="Edit.Paste" />
+    <menu_item_call.on_enable
+     function="Edit.EnablePaste" />
+  </menu_item_call>
+  <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="Delete"
+ shortcut="Del">
+    <menu_item_call.on_click
+     function="Edit.Delete" />
+    <menu_item_call.on_enable
+     function="Edit.EnableDelete" />
+  </menu_item_call>
+  <menu_item_call
+   label="Select All"
+   layout="topleft"
+   name="Select All"
+   shortcut="control|A">
+    <menu_item_call.on_click
+     function="Edit.SelectAll" />
+    <menu_item_call.on_enable
+     function="Edit.EnableSelectAll" />
+  </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index d90d1f0635b11c0edb99942f4b4d43d169d2771e..829cd6aecaf60a584607f5bb7390a90b3e4208e7 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -167,6 +167,18 @@
              function="Floater.Toggle"
              parameter="active_speakers" />
         </menu_item_check>
+        <menu_item_check
+         label="Nearby Media"
+         layout="topleft"
+         name="Nearby Media"
+         shortcut="control|alt|N">
+            <menu_item_check.on_check
+             function="Floater.Visible"
+             parameter="nearby_media" />
+            <menu_item_check.on_click
+             function="Floater.Toggle"
+             parameter="nearby_media" />
+        </menu_item_check>
         <!--menu_item_check
          label="Block List"
          layout="topleft"
@@ -232,7 +244,7 @@
         <menu_item_separator
          layout="topleft" />
         <menu_item_call
-         label="Place Profile"
+         label="About Land"
          layout="topleft"
          name="About Land">
             <menu_item_call.on_click
@@ -1091,6 +1103,14 @@
             <menu_item_call.on_click
              function="Advanced.RebakeTextures" />
         </menu_item_call>
+        <menu_item_call
+           label="Set UI Size to Default"
+           layout="topleft"
+           name="Set UI Size to Default">
+          <menu_item_call.on_click
+             function="View.DefaultUISize" />
+        </menu_item_call>
+        <menu_item_separator/>
         <menu_item_check
          label="Limit Select Distance"
          layout="topleft"
@@ -1610,6 +1630,234 @@
              function="ToggleControl"
              parameter="MouseSmooth" />
         </menu_item_check>
+        <menu_item_separator
+         layout="topleft" />
+        <menu
+         label="Shortcuts"
+         layout="topleft"
+         name="Shortcuts"
+         tear_off="true"
+         visible="false">
+            <menu_item_check
+               label="Search"
+               layout="topleft"
+               name="Search"
+               shortcut="control|F">
+            <menu_item_check.on_check
+             function="Floater.Visible"
+             parameter="search" />
+            <menu_item_check.on_click
+             function="Floater.Toggle"
+             parameter="search" />
+            </menu_item_check>
+            <menu_item_call
+             enabled="false"
+             label="Release Keys"
+             layout="topleft"
+             name="Release Keys">
+                <menu_item_call.on_click
+                 function="Tools.ReleaseKeys"
+                 parameter="" />
+                <menu_item_call.on_enable
+                 function="Tools.EnableReleaseKeys"
+                 parameter="" />
+            </menu_item_call>
+            <menu_item_call
+             label="Set UI Size to Default"
+             layout="topleft"
+             name="Set UI Size to Default">
+                <menu_item_call.on_click
+                 function="View.DefaultUISize" />
+            </menu_item_call>
+            <menu_item_separator
+             layout="topleft" />
+            <menu_item_check
+             label="Always Run"
+             layout="topleft"
+             name="Always Run"
+             shortcut="control|R">
+                <menu_item_check.on_check
+                 function="World.CheckAlwaysRun" />
+                <menu_item_check.on_click
+                 function="World.AlwaysRun" />
+            </menu_item_check>
+            <menu_item_check
+             label="Fly"
+             layout="topleft"
+             name="Fly"
+             shortcut="Home">
+                <menu_item_check.on_click
+                 function="Agent.toggleFlying" />
+                <menu_item_check.on_enable
+                 function="Agent.enableFlying" />
+            </menu_item_check>
+            <menu_item_separator
+             layout="topleft" />
+            <menu_item_call
+             label="Close Window"
+             layout="topleft"
+             name="Close Window"
+             shortcut="control|W">
+                <menu_item_call.on_click
+                 function="File.CloseWindow" />
+                <menu_item_call.on_enable
+                 function="File.EnableCloseWindow" />
+            </menu_item_call>
+            <menu_item_call
+             label="Close All Windows"
+             layout="topleft"
+             name="Close All Windows"
+             shortcut="control|shift|W">
+                <menu_item_call.on_click
+                 function="File.CloseAllWindows" />
+                <menu_item_call.on_enable
+                 function="File.EnableCloseAllWindows" />
+            </menu_item_call>
+            <menu_item_separator
+             layout="topleft" />
+            <menu_item_call
+             label="Snapshot to Disk"
+             layout="topleft"
+             name="Snapshot to Disk"
+             shortcut="control|`"
+             use_mac_ctrl="true">
+                <menu_item_call.on_click
+                 function="File.TakeSnapshotToDisk" />
+            </menu_item_call>
+            <menu_item_separator
+             layout="topleft" />
+            <menu_item_call
+             label="Mouselook"
+             layout="topleft"
+             name="Mouselook"
+             shortcut="M">
+                <menu_item_call.on_click
+                 function="View.Mouselook" />
+                <menu_item_call.on_enable
+                 function="View.EnableMouselook" />
+            </menu_item_call>
+            <menu_item_check
+             label="Joystick Flycam"
+             layout="topleft"
+             name="Joystick Flycam"
+             shortcut="alt|shift|F">
+                <menu_item_check.on_check
+                 function="View.CheckJoystickFlycam" />
+                <menu_item_check.on_click
+                 function="View.JoystickFlycam" />
+                <menu_item_check.on_enable
+                 function="View.EnableJoystickFlycam" />
+            </menu_item_check>
+            <menu_item_call
+             label="Reset View"
+             layout="topleft"
+             name="Reset View"
+             shortcut="Esc">
+                <menu_item_call.on_click
+                 function="View.ResetView" />
+            </menu_item_call>
+            <menu_item_call
+             label="Look at Last Chatter"
+             layout="topleft"
+             name="Look at Last Chatter"
+             shortcut="control|\">
+                <menu_item_call.on_click
+                 function="View.LookAtLastChatter" />
+                <menu_item_call.on_enable
+                 function="View.EnableLastChatter" />
+            </menu_item_call>
+            <menu_item_separator
+             layout="topleft" />
+            <menu
+             create_jump_keys="true"
+             label="Select Build Tool"
+             layout="topleft"
+             name="Select Tool"
+             tear_off="true">
+                <menu_item_call
+                 label="Focus Tool"
+                 layout="topleft"
+                 name="Focus"
+                 shortcut="control|1">
+                    <menu_item_call.on_click
+                     function="Tools.SelectTool"
+                     parameter="focus" />
+                </menu_item_call>
+                <menu_item_call
+                 label="Move Tool"
+                 layout="topleft"
+                 name="Move"
+                 shortcut="control|2">
+                    <menu_item_call.on_click
+                     function="Tools.SelectTool"
+                     parameter="move" />
+                </menu_item_call>
+                <menu_item_call
+                 label="Edit Tool"
+                 layout="topleft"
+                 name="Edit"
+                 shortcut="control|3">
+                    <menu_item_call.on_click
+                     function="Tools.SelectTool"
+                     parameter="edit" />
+                </menu_item_call>
+                <menu_item_call
+                 label="Create Tool"
+                 layout="topleft"
+                 name="Create"
+                 shortcut="control|4">
+                    <menu_item_call.on_click
+                     function="Tools.SelectTool"
+                     parameter="create" />
+                </menu_item_call>
+                <menu_item_call
+                 label="Land Tool"
+                 layout="topleft"
+                 name="Land"
+                 shortcut="control|5">
+                    <menu_item_call.on_click
+                     function="Tools.SelectTool"
+                     parameter="land" />
+                </menu_item_call>
+            </menu>
+            <menu_item_separator
+             layout="topleft" />
+            <menu_item_call
+             label="Zoom In"
+             layout="topleft"
+             name="Zoom In"
+             shortcut="control|0">
+                <menu_item_call.on_click
+                 function="View.ZoomIn" />
+            </menu_item_call>
+            <menu_item_call
+             label="Zoom Default"
+             layout="topleft"
+             name="Zoom Default"
+             shortcut="control|9">
+                <menu_item_call.on_click
+                 function="View.ZoomDefault" />
+            </menu_item_call>
+            <menu_item_call
+             label="Zoom Out"
+             layout="topleft"
+             name="Zoom Out"
+             shortcut="control|8">
+                <menu_item_call.on_click
+                 function="View.ZoomOut" />
+            </menu_item_call>
+            <menu_item_separator
+             layout="topleft" />
+            <menu_item_call
+             label="Toggle Fullscreen"
+             layout="topleft"
+             name="Toggle Fullscreen"
+             >
+               <!-- Note: shortcut="alt|Enter" was deleted from the preceding node-->
+                <menu_item_call.on_click
+                 function="View.Fullscreen" />
+            </menu_item_call>
+        </menu>
         <menu_item_separator
          layout="topleft" />
         <menu_item_call
@@ -2408,232 +2656,6 @@
                  parameter="stop record" />
             </menu_item_call>
         </menu>
-        <menu
-         label="Shortcuts"
-         layout="topleft"
-         name="Shortcuts"
-         tear_off="true"
-         visible="false">
-            <menu_item_check
-               label="Search"
-               layout="topleft"
-               name="Search"
-               shortcut="control|F">
-            <menu_item_check.on_check
-             function="Floater.Visible"
-             parameter="search" />
-            <menu_item_check.on_click
-             function="Floater.Toggle"
-             parameter="search" />
-            </menu_item_check>
-            <menu_item_call
-             enabled="false"
-             label="Release Keys"
-             layout="topleft"
-             name="Release Keys">
-                <menu_item_call.on_click
-                 function="Tools.ReleaseKeys"
-                 parameter="" />
-                <menu_item_call.on_enable
-                 function="Tools.EnableReleaseKeys"
-                 parameter="" />
-            </menu_item_call>
-            <menu_item_call
-             label="Set UI Size to Default"
-             layout="topleft"
-             name="Set UI Size to Default">
-                <menu_item_call.on_click
-                 function="View.DefaultUISize" />
-            </menu_item_call>
-            <menu_item_separator
-             layout="topleft" />
-            <menu_item_check
-             label="Always Run"
-             layout="topleft"
-             name="Always Run"
-             shortcut="control|R">
-                <menu_item_check.on_check
-                 function="World.CheckAlwaysRun" />
-                <menu_item_check.on_click
-                 function="World.AlwaysRun" />
-            </menu_item_check>
-            <menu_item_check
-             label="Fly"
-             layout="topleft"
-             name="Fly"
-             shortcut="Home">
-                <menu_item_check.on_click
-                 function="Agent.toggleFlying" />
-                <menu_item_check.on_enable
-                 function="Agent.enableFlying" />
-            </menu_item_check>
-            <menu_item_separator
-             layout="topleft" />
-            <menu_item_call
-             label="Close Window"
-             layout="topleft"
-             name="Close Window"
-             shortcut="control|W">
-                <menu_item_call.on_click
-                 function="File.CloseWindow" />
-                <menu_item_call.on_enable
-                 function="File.EnableCloseWindow" />
-            </menu_item_call>
-            <menu_item_call
-             label="Close All Windows"
-             layout="topleft"
-             name="Close All Windows"
-             shortcut="control|shift|W">
-                <menu_item_call.on_click
-                 function="File.CloseAllWindows" />
-                <menu_item_call.on_enable
-                 function="File.EnableCloseAllWindows" />
-            </menu_item_call>
-            <menu_item_separator
-             layout="topleft" />
-            <menu_item_call
-             label="Snapshot to Disk"
-             layout="topleft"
-             name="Snapshot to Disk"
-             shortcut="control|`"
-             use_mac_ctrl="true">
-                <menu_item_call.on_click
-                 function="File.TakeSnapshotToDisk" />
-            </menu_item_call>
-            <menu_item_separator
-             layout="topleft" />
-            <menu_item_call
-             label="Mouselook"
-             layout="topleft"
-             name="Mouselook"
-             shortcut="M">
-                <menu_item_call.on_click
-                 function="View.Mouselook" />
-                <menu_item_call.on_enable
-                 function="View.EnableMouselook" />
-            </menu_item_call>
-            <menu_item_check
-             label="Joystick Flycam"
-             layout="topleft"
-             name="Joystick Flycam"
-             shortcut="alt|shift|F">
-                <menu_item_check.on_check
-                 function="View.CheckJoystickFlycam" />
-                <menu_item_check.on_click
-                 function="View.JoystickFlycam" />
-                <menu_item_check.on_enable
-                 function="View.EnableJoystickFlycam" />
-            </menu_item_check>
-            <menu_item_call
-             label="Reset View"
-             layout="topleft"
-             name="Reset View"
-             shortcut="Esc">
-                <menu_item_call.on_click
-                 function="View.ResetView" />
-            </menu_item_call>
-            <menu_item_call
-             label="Look at Last Chatter"
-             layout="topleft"
-             name="Look at Last Chatter"
-             shortcut="control|\">
-                <menu_item_call.on_click
-                 function="View.LookAtLastChatter" />
-                <menu_item_call.on_enable
-                 function="View.EnableLastChatter" />
-            </menu_item_call>
-            <menu_item_separator
-             layout="topleft" />
-            <menu
-             create_jump_keys="true"
-             label="Select Build Tool"
-             layout="topleft"
-             name="Select Tool"
-             tear_off="true">
-                <menu_item_call
-                 label="Focus Tool"
-                 layout="topleft"
-                 name="Focus"
-                 shortcut="control|1">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="focus" />
-                </menu_item_call>
-                <menu_item_call
-                 label="Move Tool"
-                 layout="topleft"
-                 name="Move"
-                 shortcut="control|2">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="move" />
-                </menu_item_call>
-                <menu_item_call
-                 label="Edit Tool"
-                 layout="topleft"
-                 name="Edit"
-                 shortcut="control|3">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="edit" />
-                </menu_item_call>
-                <menu_item_call
-                 label="Create Tool"
-                 layout="topleft"
-                 name="Create"
-                 shortcut="control|4">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="create" />
-                </menu_item_call>
-                <menu_item_call
-                 label="Land Tool"
-                 layout="topleft"
-                 name="Land"
-                 shortcut="control|5">
-                    <menu_item_call.on_click
-                     function="Tools.SelectTool"
-                     parameter="land" />
-                </menu_item_call>
-            </menu>
-            <menu_item_separator
-             layout="topleft" />
-            <menu_item_call
-             label="Zoom In"
-             layout="topleft"
-             name="Zoom In"
-             shortcut="control|0">
-                <menu_item_call.on_click
-                 function="View.ZoomIn" />
-            </menu_item_call>
-            <menu_item_call
-             label="Zoom Default"
-             layout="topleft"
-             name="Zoom Default"
-             shortcut="control|9">
-                <menu_item_call.on_click
-                 function="View.ZoomDefault" />
-            </menu_item_call>
-            <menu_item_call
-             label="Zoom Out"
-             layout="topleft"
-             name="Zoom Out"
-             shortcut="control|8">
-                <menu_item_call.on_click
-                 function="View.ZoomOut" />
-            </menu_item_call>
-            <menu_item_separator
-             layout="topleft" />
-            <menu_item_call
-             label="Toggle Fullscreen"
-             layout="topleft"
-             name="Toggle Fullscreen"
-             >
-               <!-- Note: shortcut="alt|Enter" was deleted from the preceding node-->
-                <menu_item_call.on_click
-                 function="View.Fullscreen" />
-            </menu_item_call>
-        </menu>
 
         <menu
          create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 6831e56f0b9ce7a346374aaabb63362849bffe12..7b829d4e13052a214e9ff2bfa5b69fdc1f7b9008 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -13,7 +13,7 @@
   <global name="implicitclosebutton">
 		Close
   </global>
-    
+
   <template name="okbutton">
     <form>
       <button
@@ -154,7 +154,7 @@ No tutorial is currently available.
    icon="alertmodal.tga"
    name="BadInstallation"
    type="alertmodal">
- An error occurred while updating [APP_NAME].  Please download the latest version of the Viewer. http://get.secondlife.com
+ An error occurred while updating [APP_NAME].  Please [http://get.secondlife.com download the latest version] of the Viewer.
     <usetemplate
      name="okbutton"
      yestext="Ok"/>
@@ -507,7 +507,7 @@ For L$[COST] you can enter this land (&apos;[PARCEL_NAME]&apos;) for [TIME] hour
      notext="Cancel"
      yestext="OK"/>
   </notification>
-  
+
   <notification
    icon="alertmodal.tga"
    name="SalePriceRestriction"
@@ -664,7 +664,7 @@ Scripts must be allowed to run for weapons to work.
    icon="alertmodal.tga"
    name="MultipleFacesSelected"
    type="alertmodal">
-Multiple faces are currently selected. 
+Multiple faces are currently selected.
 If you continue this action, separate instances of media will be set on multiple faces of the object.
 To place the media on only one face, choose Select Texture and click on the desired face of that object then click Add.
     <usetemplate
@@ -673,6 +673,19 @@ To place the media on only one face, choose Select Texture and click on the desi
      yestext="OK"/>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="WhiteListInvalidatesHomeUrl"
+   type="alertmodal">
+Adding this entry to the whitelist will invalidate the home URL you
+specified for this instance of media. You are not allowed to do this
+so the entry cannot be added to the whitelist.
+    <usetemplate
+     name="okbutton"
+     yestext="Ok"/>
+  </notification>
+
+
   <notification
    icon="alertmodal.tga"
    name="MustBeInParcel"
@@ -778,7 +791,7 @@ Oops! Something was left blank.
 You need to enter both the First and Last name of your avatar.
 
 You need an account to enter [SECOND_LIFE]. Would you like to create one now?
-    <url 
+    <url
 	option="0"
 	name="url"
 	openexternally = "1">
@@ -795,7 +808,7 @@ You need an account to enter [SECOND_LIFE]. Would you like to create one now?
    icon="alertmodal.tga"
    name="AddClassified"
    type="alertmodal">
-Classified ads appear in the &apos;Classified&apos; section of the Search directory and on www.secondlife.com for one week.
+Classified ads appear in the &apos;Classified&apos; section of the Search directory and on [http://www.secondlife.com secondlife.com] for one week.
 Fill out your ad, then click &apos;Publish...&apos; to add it to the directory.
 You&apos;ll be asked for a price to pay when clicking Publish.
 Paying more makes your ad appear higher in the list, and also appear higher when people search for keywords.
@@ -1047,13 +1060,13 @@ There was a problem saving a compiled script due to the following reason: [REASO
    icon="alertmodal.tga"
    name="StartRegionEmpty"
    type="alertmodal">
-Oops, Your Start Region is not defined. 
-Please type the Region name in Start Location box or choose My Last Location or My Home as your Start Location.  
+Oops, Your Start Region is not defined.
+Please type the Region name in Start Location box or choose My Last Location or My Home as your Start Location.
     <usetemplate
      name="okbutton"
      yestext="OK"/>
   </notification>
-  
+
   <notification
    icon="alertmodal.tga"
    name="CouldNotStartStopScript"
@@ -2396,7 +2409,7 @@ You can use [SECOND_LIFE] normally and other people will see you correctly.
 [APP_NAME] installation is complete.
 
 If this is your first time using [SECOND_LIFE], you will need to create an account before you can log in.
-Return to www.secondlife.com to create a new account?
+Return to [http://join.secondlife.com secondlife.com] to create a new account?
     <usetemplate
      name="okcancelbuttons"
      notext="Continue"
@@ -2413,7 +2426,7 @@ You can either check your Internet connection and try again in a few minutes, cl
     <url option="1" name="url">
 
 			http://secondlife.com/support/
-    </url>	 
+    </url>
     <form name="form">
       <button
        default="true"
@@ -2788,7 +2801,7 @@ Do you want to open your Web browser to view this content?
    icon="alertmodal.tga"
    name="WebLaunchJoinNow"
    type="alertmodal">
-Go to secondlife.com to manage your account?
+Go to your [http://secondlife.com/account/ Dashboard] to manage your account?
     <usetemplate
      ignoretext="Launch my browser to manage my account"
      name="okcancelignore"
@@ -3150,7 +3163,7 @@ Teleport to [PICK]?
      notext="Cancel"
      yestext="Teleport"/>
   </notification>
-  
+
   <notification
    icon="alert.tga"
    label="Message everyone in your Estate"
@@ -3644,7 +3657,7 @@ Default: off
    label="Bulk Change Content Permissions"
    name="HelpBulkPermission"
    type="alertmodal">
-The Bulk Permissions tool helps you to quickly change the permissions on multiple items in the contents of the selected object(s).  However, please note that you are only setting permissions on the items in the Contents of the selected objects -- not permissions on the container object(s) themselves.  
+The Bulk Permissions tool helps you to quickly change the permissions on multiple items in the contents of the selected object(s).  However, please note that you are only setting permissions on the items in the Contents of the selected objects -- not permissions on the container object(s) themselves.
 
 Also note, the permissions are not applied to the nested contents of any of the contained items.  Your request only operates on items exactly one level deep.
 
@@ -4238,7 +4251,7 @@ There are no items in this object that you are allowed to copy.
    icon="alertmodal.tga"
    name="WebLaunchAccountHistory"
    type="alertmodal">
-Go to secondlife.com to see your account history?
+Go to  your [http://secondlife.com/account/ Dashboard] to see your account history?
     <usetemplate
      ignoretext="Launch my browser to see my account history"
      name="okcancelignore"
@@ -4275,14 +4288,9 @@ Are you sure you want to quit?
    icon="alertmodal.tga"
    name="HelpReportAbuseEmailLL"
    type="alertmodal">
-Use this tool to report violations of the Terms of Service and Community Standards. See:
-
-http://secondlife.com/corporate/tos.php
-http://secondlife.com/corporate/cs.php
+Use this tool to report violations of the [http://secondlife.com/corporate/tos.php Terms of Service] and [http://secondlife.com/corporate/cs.php Community Standards].
 
-All reported abuses of the Terms of Service and Community Standards are investigated and resolved. You can view the incident resolution on the Incident Report at:
-
-http://secondlife.com/support/incidentreport.php
+All reported abuses are investigated and resolved. You can view the resolution by reading the [http://secondlife.com/support/incidentreport.php Incident Report].
    <unique/>
   </notification>
 
@@ -4350,9 +4358,9 @@ Dear Resident,
 
 You appear to be reporting intellectual property infringement. Please make sure you are reporting it correctly:
 
-(1) The Abuse Process. You may submit an abuse report if you believe a Resident is exploiting the [SECOND_LIFE] permissions system, for example, by using CopyBot or similar copying tools, to infringe intellectual property rights. The Abuse Team investigates and issues appropriate disciplinary action for behavior that violates the [SECOND_LIFE] Community Standards or Terms of Service. However, the Abuse Team does not handle and will not respond to requests to remove content from the [SECOND_LIFE] world.
+(1) The Abuse Process. You may submit an abuse report if you believe a Resident is exploiting the [SECOND_LIFE] permissions system, for example, by using CopyBot or similar copying tools, to infringe intellectual property rights. The Abuse Team investigates and issues appropriate disciplinary action for behavior that violates the [SECOND_LIFE] [http://secondlife.com/corporate/tos.php Terms of Service] or [http://secondlife.com/corporate/cs.php Community Standards]. However, the Abuse Team does not handle and will not respond to requests to remove content from the [SECOND_LIFE] world.
 
-(2) The DMCA or Content Removal Process. To request removal of content from [SECOND_LIFE], you MUST submit a valid notification of infringement as provided in our DMCA Policy at http://secondlife.com/corporate/dmca.php.
+(2) The DMCA or Content Removal Process. To request removal of content from [SECOND_LIFE], you MUST submit a valid notification of infringement as provided in our [http://secondlife.com/corporate/dmca.php DMCA Policy].
 
 If you still wish to continue with the abuse process, please close this window and finish submitting your report.  You may need to select the specific category &apos;CopyBot or Permissions Exploit&apos;.
 
@@ -5450,7 +5458,7 @@ Deactivated gestures with same trigger:
    name="NoQuickTime"
    type="notify">
 Apple&apos;s QuickTime software does not appear to be installed on your system.
-If you want to view streaming media on parcels that support it you should go to the QuickTime site (http://www.apple.com/quicktime) and install the QuickTime Player.
+If you want to view streaming media on parcels that support it you should go to the [http://www.apple.com/quicktime QuickTime site] and install the QuickTime Player.
   </notification>
   <notification
    icon="notify.tga"
@@ -5514,7 +5522,7 @@ The objects on the selected parcel that are NOT owned by you have been returned
    type="notify">
 [MSG]
   </notification>
-  
+
   <notification
    icon="notify.tga"
    name="NotSafe"
@@ -5824,15 +5832,11 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a
       <button
        index="0"
        name="Keep"
-       text="OK"/>
+       text="Accept"/>
       <button
        index="1"
        name="Discard"
-       text="Cancel"/>
-      <button
-       index="2"
-       name="Mute"
-       text="Block"/>
+       text="No, thanks"/>
     </form>
   </notification>
 
@@ -6138,10 +6142,9 @@ Your L$ balance is shown in the upper-right.
    type="notify">
 Thank you for your payment!
 
-When the processing completes, your L$ balance will be updated at the top of your screen.
-If processing your payment takes more than 20 minutes to complete, the purchase amount will be credited to your account for use on your next purchase.
+Your L$ balance will be updated when processing completes. If processing takes more than 20 mins, your transaction may be cancelled. In that case, the purchase amount will be credited to your US$ balance.
 
-The status of your payment can be checked on your Transaction History page at Me > My Dashboard, or http://secondlife.com/account/
+The status of your payment can be checked on your Transaction History page on your [http://secondlife.com/account/ Dashboard]
   </notification>
   <notification
    icon="notify.tga"
@@ -6618,12 +6621,11 @@ Yes
   <global name="PermNo">
 No
   </global>
-<!-- this is alert string from server. the name needs to match entire the server string, and needs to be changed 
-	whenever the server string changes --> 
+<!-- this is alert string from server. the name needs to match entire the server string, and needs to be changed
+	whenever the server string changes -->
    <global name="You can only set your 'Home Location' on your land or at a mainland Infohub.">
-If you own a piece of land, you can make it your home location. 
+If you own a piece of land, you can make it your home location.
 Otherwise, you can look at the Map and find places marked &quot;Infohub&quot;.
-  </global> 
-  
-</notifications>
+  </global>
 
+</notifications>
diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
index 4dc4a9ff465a2c895b36d3643712e4d97a21b8e3..8b815b0f711cc1cde2702d8bf90f7670fe6bdba9 100644
--- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel	
+<panel
 	name="panel_activeim_row"
 	layout="topleft"
 	follows="left|right"
@@ -7,56 +7,51 @@
 	left="0"
 	height="35"
 	width="318"
-	background_visible="true"
-	bevel_style="in"
-	bg_alpha_color="0 0 0 0">
+	background_visible="false">
   <chiclet_im_p2p
 		name="p2p_chiclet"
 		layout="topleft"
 		follows="left"
-		top="5"
+		top="3"
 		left="5"
 		height="25"
-		width="45">
+		width="25">
   </chiclet_im_p2p>
   <chiclet_im_group
 		name="group_chiclet"
 		layout="topleft"
 		follows="left"
-		top="5"
+		top="3"
 		left="5"
 		height="25"
-		width="45">
+		width="25">
   </chiclet_im_group>
 	<text
 		type="string"
 		name="contact_name"
 		layout="topleft"
-		top="8"
-		left_pad="6"
-		height="28"
-		width="235"
+		top="10"
+		left_pad="0"
+		height="14"
+		width="245"
 		length="1"
 		follows="right|left"
-		font="SansSerifBold"
-		text_color="White">
-    Contact Name
+		use_ellipses="true"
+		font="SansSerifBold">
+    Grumpity ProductEngine
   </text>
   <button
-    top="5"
-    left_pad="5"
-    width="15"
-    height="15"
+    top="10"
+    right="-5"
+    width="17"
+    height="17"
     layout="topleft"
     follows="right"
     name="hide_btn"
     mouse_opaque="true"
     label=""
     tab_stop="false"
-    image_unselected="toast_hide_btn.tga"
-    image_disabled="toast_hide_btn.tga"
-    image_selected="toast_hide_btn.tga"
-    image_hover_selected="toast_hide_btn.tga"
-    image_disabled_selected="toast_hide_btn.tga"
+    image_unselected="Toast_CloseBtn"
+    image_selected="Toast_CloseBtn"
   />
 </panel>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f50acc224f053796b42600374bac9757d6fb8425
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ name="panel_im_control_panel"
+ width="146"
+ height="215"
+ border="false">
+    <avatar_list
+     color="DkGray2"
+     follows="left|top|right|bottom"
+     height="130"
+     ignore_online_status="true"
+     layout="topleft"
+     left="3"
+     name="speakers_list"
+     opaque="false"
+     show_info_btn="false"
+     show_profile_btn="false"
+     top="10"
+     width="140" />
+    <button
+     name="call_btn"
+     label="Call"
+     width="125"
+     height="20" />
+    <button
+     name="end_call_btn"
+     label="End Call"
+     width="125"
+     height="20" 
+     visible="false"/>
+    <button
+     enabled="false"
+     name="voice_ctrls_btn"
+     label="Open Voice Controls"
+     width="125"
+     height="20"
+     visible="false"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
index f747c557e226e92dfab3fc367b38c791ffe1cbfb..18761c3bb9ab6d38ad0c652509284b9f4f1d17ca 100644
--- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
@@ -39,7 +39,6 @@
     <text
      follows="left|right"
      font="SansSerifSmall"
-     font.style="BOLD"
      height="15"
      layout="topleft"
      left_pad="5"
@@ -47,17 +46,17 @@
      top="6"
      use_ellipses="true"
      value="Unknown"
-     width="166" />
+     width="182" />
     <text
-     follows="left"
+     follows="right"
      font="SansSerifSmall"
      height="15"
      layout="topleft"
-     left_pad="10"
-     name="avatar_status"
+     left_pad="8"
+     name="last_interaction"
      text_color="LtGray_50"
-     value="Away"
-     width="50" />
+     value="0s"
+     width="24" />
     <output_monitor
      auto_update="true"
      follows="right"
@@ -69,27 +68,26 @@
      name="speaking_indicator"
      visible="true"
      width="20" />
-   <button
+    <button
      follows="right"
      height="16"
      image_pressed="Info_Press"
-     image_hover="Info_Over"
-     image_unselected="Info_Off"
+     image_unselected="Info_Over"
      left_pad="3"
-     right="-25"
+     right="-31"
      name="info_btn"
      picture_style="true"
+     top_delta="-2"
      width="16" />
     <button
      follows="right"
-     height="16"
-      image_selected="BuyArrow_Press"
-     image_pressed="BuyArrow_Press"
-     image_unselected="BuyArrow_Press"
+     height="20"
+     image_overlay="ForwardArrow_Off"
      layout="topleft"
      left_pad="5"
-     right="-5"
+     right="-3"
      name="profile_btn"
      picture_style="true"
-     width="16" />
+     top_delta="-2"
+     width="20" />
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index 1196d788e4ca6346c646e76b9c10841eaffd94d5..9bf3458d298d275e7a88fbe62b7c5195cb647667 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -2,21 +2,22 @@
 <panel
  mouse_opaque="true"
  background_visible="true"
- bg_alpha_color="0.25 0.25 0.25 1"
- bg_opaque_color="0.25 0.25 0.25 1"
+ bg_alpha_color="DkGray"
+ bg_opaque_color="DkGray"
  follows="left|bottom|right"
- height="28"
+ height="33"
  layout="topleft"
  left="0"
  name="bottom_tray"
  top="28"
- border_visible="true"
+ chrome="true" 
+ border_visible="false"
  width="1000">
     <layout_stack
-     mouse_opaque="false"    
+     mouse_opaque="false"
      border_size="0"
-     clip="false" 
-     follows="left|right|bottom|top"
+     clip="false"
+     follows="all"
      height="28"
      layout="topleft"
      left="0"
@@ -26,39 +27,27 @@
      width="1000">
         <icon
          auto_resize="false"
-         color="0 0 0 0"
          follows="left|right"
          height="10"
          image_name="spacer24.tga"
          layout="topleft"
          left="0"
          top="0"
-         width="5"/>
+         width="4" />
         <layout_panel
- 		 mouse_opaque="false"        
+ 	mouse_opaque="false"
          auto_resize="false"
          follows="left|right"
          height="28"
          layout="topleft"
-         left="5"
-         min_height="28"
+         left="0"
+         min_height="23"
          width="310"
          top="0"
          min_width="300"
          name="chat_bar"
          user_resize="false"
          filename="panel_nearby_chat_bar.xml"/>
-		 <icon
-         auto_resize="false"
-         color="0 0 0 0"
-         follows="left|right"
-         height="10"
-         image_name="spacer24.tga"
-         layout="topleft"
-         left="0"
-         name="DUMMY"
-         top="0"
-         width="3"/>
         <layout_panel
          mouse_opaque="false"
          auto_resize="false"
@@ -66,26 +55,25 @@
          height="28"
          layout="topleft"
          min_height="28"
-         width="100"
-         top_delta="-10"
-         min_width="100"
+         width="96"
+         top_delta="0"
+         min_width="96"
          name="speak_panel"
          user_resize="false">
 		    <chiclet_talk
 		     follows="right"
-		     height="20"
+		     height="23"
 		     speak_button.font="SansSerifMedium"
 		     speak_button.tab_stop="true"
 		     show_button.tab_stop="true"
 		     layout="topleft"
 		     left="0"
 		     name="talk"
-		     top="6"
-		     width="100" />
-         </layout_panel>                  
+		     top="3"
+		     width="96" />
+         </layout_panel>
 		 <icon
          auto_resize="false"
-         color="0 0 0 0"
          follows="left|right"
          height="10"
          image_name="spacer24.tga"
@@ -93,7 +81,7 @@
          left="0"
          name="DUMMY"
          top="0"
-         width="5"/>
+         width="4"/>
         <layout_panel
          mouse_opaque="false"
          auto_resize="false"
@@ -101,20 +89,21 @@
          height="28"
          layout="topleft"
          min_height="28"
-         width="90"
-         top_delta="-10"
-         min_width="90"
+         width="76"
+         top_delta="0"
+         min_width="76"
          name="gesture_panel"
          user_resize="false">
 		    <gesture_combo_box
 		      follows="right"
-		     height="20"
-		     label="Gestures"
+		     height="23"
+		     label="Gesture"
 		     layout="topleft"
 		     name="Gesture"
 		     left="0"
-		     top="6"
-		     width="90" />
+		     top="3"
+             use_ellipses="true"
+		     width="76" />
         </layout_panel>
 		 <icon
          auto_resize="false"
@@ -126,29 +115,28 @@
          left="0"
          name="DUMMY"
          top="0"
-         width="5"/>   
+         width="4"/>
         <layout_panel
-         mouse_opaque="false"        
+         mouse_opaque="false"
          auto_resize="false"
          follows="right"
          height="28"
          layout="topleft"
          min_height="28"
          name="movement_panel"
-         width="70"
-         top_delta="-10"
-         min_width="70">
+         width="76"
+         min_width="76">
             <button
              follows="left|right"
-             height="20"
+             height="23"
              use_ellipses="true"
              is_toggle="true"
              label="Move"
              layout="topleft"
              name="movement_btn"
-             tool_tip="Shows/hides movement controls" 
-             top="6"
-             width="70">
+             tool_tip="Show/hide movement controls"
+             top="3"
+             width="76">
                 <button.init_callback
                  function="Button.SetDockableFloaterToggle"
                  parameter="moveview" />
@@ -164,75 +152,81 @@
          left="0"
          name="DUMMY"
          top="0"
-         width="8"/>
+         width="4"/>
         <layout_panel
-         mouse_opaque="false"        
+         mouse_opaque="false"
          auto_resize="false"
          follows="left|right"
          height="28"
          layout="topleft"
          min_height="28"
-         min_width="100"
+         min_width="76"
          name="cam_panel"
          top_delta="-10"
          width="100">
             <button
              follows="left|right"
-             height="20"
+             height="23"
              use_ellipses="true"
              is_toggle="true"
              label="View"
              layout="topleft"
              left="0"
-             tool_tip="Shows/hides camera controls" 
-             top="6"
+             tool_tip="Show/hide camera controls"
+             top="3"
              name="camera_btn"
-             width="70">
+             width="76">
                 <button.init_callback
                  function="Button.SetDockableFloaterToggle"
                  parameter="camera" />
             </button>
         </layout_panel>
+        <icon
+         auto_resize="false"
+         color="0 0 0 0"
+         follows="left|right"
+         height="10"
+         image_name="spacer24.tga"
+         layout="topleft"
+         left="0"
+         name="DUMMY"
+         top="0"
+         width="4"/>
         <layout_panel
-         mouse_opaque="false"        
+         mouse_opaque="false"
          auto_resize="false"
-         follows="right"
+         follows="left|right"
          height="28"
          layout="topleft"
-         min_height="28"
-         min_width="35"
          name="snapshot_panel"
-         top_delta="-10"
-         width="35">         
+         width="35">
             <split_button
              arrow_position="right"
-             follows="right"
-             height="18"
+         follows="left|right"
+             height="23"
              left="0"
-             layout="topleft"             
+             layout="topleft"
              name="snapshots"
-             top="6"
-             width="35">
-                <split_button.arrow_button 
-                 image_selected="camera_presets/camera_presets_arrow_right.png"
-                 image_unselected="camera_presets/camera_presets_arrow_right.png"
-                 image_disabled_selected="camera_presets/camera_presets_arrow_right.png" 
-                 image_disabled="camera_presets/camera_presets_arrow_right.png"
-                 name="snapshot_settings"
-                 tool_tip="Snapshot settings" />
+             width="46"
+             top="3">
                 <split_button.item
-                 image_selected="camera_presets/camera_presets_snapshot.png"
-                 image_unselected="camera_presets/camera_presets_snapshot.png"
+                 image_overlay="Snapshot_Off"
                  name="snapshot"
-                 tool_tip="Take snapshot" />
-            </split_button>                  
+                 tool_tip="Take snapshot"
+                 />
+                <split_button.arrow_button
+                 name="snapshot_settings"
+                 image_overlay="Widget_UpArrow"
+                 tool_tip="Snapshot and Preset Views"
+                 width="18"
+                 />
+            </split_button>
         </layout_panel>
         <layout_panel
          mouse_opaque="false"
          follows="left|right"
          height="28"
          layout="topleft"
-         min_height="28"
          top="0"
          name="chiclet_list_panel"
          width="189"
@@ -240,13 +234,13 @@
          user_resize="false"
          auto_resize="true">
             <chiclet_panel
-	         mouse_opaque="false"
+	    mouse_opaque="false"
              follows="left|right"
-             height="25"
+             height="28"
              layout="topleft"
              left="0"
              name="chiclet_list"
-             top="1"
+             top="0"
              chiclet_padding="3"
              scrolling_offset="40"
              width="189" />
@@ -261,36 +255,6 @@
          left="0"
          top="0"
          width="5"/>
-      <icon
-         auto_resize="false"
-         color="0 0 0 0"
-         follows="left|right"
-         height="10"
-         image_name="spacer24.tga"
-         layout="topleft"
-         left="0"
-         top="0"
-         width="10"/>
-        <view_border
-         auto_resize="false"
-         bevel_style="in"
-         follows="left|right"
-         height="28"
-         layout="topleft"
-         left="270"
-         name="well_separator"
-         top="0"
-         width="1" />
-        <icon
-         auto_resize="false"
-         color="0 0 0 0"
-         follows="left|right"
-         height="10"
-         image_name="spacer24.tga"
-         layout="topleft"
-         left="0"
-         top="0"
-         width="10"/>
         <layout_panel
          auto_resize="false"
          follows="right"
@@ -299,8 +263,8 @@
          min_height="28"
          top="0"
          name="sys_well_panel"
-         width="48"
-         min_width="48"
+         width="34"
+         min_width="34"
          user_resize="false">
             <chiclet_notification
              follows="right"
@@ -308,24 +272,25 @@
              layout="topleft"
              left="0"
              name="sys_well"
-             top="2"
-             width="48">
+             top="3"
+             width="34">
               <button
-               image_selected="bottom_tray_sys_notifications_selected.tga"
-               image_unselected="bottom_tray_sys_notifications.tga"/>
-              <unread_notifications
-               width="20"
-               height="20"
+              auto_resize="true"
+               halign="right"
+               height="23"
+               follows="right"
+               flash_color="EmphasisColor"
+               name="Unread"
+               picture_style="true"
+               image_overlay="Widget_UpArrow" />
+               <unread_notifications
+               width="34"
+               height="23"
                left="22"
-               top="23"/>
-<!-- 
-			  <chiclet_notification.commit_callback
-				 function="Notification.Show"
-				 parameter="ClickUnimplemented" />
- -->               				 
-			</chiclet_notification>
+               top="23" />
+	    </chiclet_notification>
         </layout_panel>
-        <icon
+       <icon
          auto_resize="false"
          color="0 0 0 0"
          follows="left|right"
@@ -334,6 +299,6 @@
          layout="topleft"
          left="0"
          top="0"
-         width="5"/>
+         width="10"/>
     </layout_stack>
 </panel>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_chat_item.xml b/indra/newview/skins/default/xui/en/panel_chat_item.xml
index 78f53562cd3029fe8c7bfbf619e0346fa9184ac8..05b04bbf8eac97e57d39549695672ddf81cce3db 100644
--- a/indra/newview/skins/default/xui/en/panel_chat_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_chat_item.xml
@@ -5,10 +5,10 @@
   name="instant_message"
   width="300"
   height="180"
-  background_opaque="false"
-  background_visible="true"
+  background_opaque="true"
+  background_visible="false"
   follows="left|top|right|bottom"
-  bg_alpha_color="0.3 0.3 0.3 1.0">
+  bg_alpha_color="0.3 0.3 0.3 0">
 	<panel width="250" height="30" background_visible="true" background_opaque="false" bg_alpha_color="0.0 0.0 0.0 1.0" name="msg_caption">
   		<avatar_icon
       		top="25" left="10" width="20" height="20" follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
index b002034a08b6e5191c76266f54cccbe4646855dd..fedc49ae87b4744ac6576308a4f12cc776bb7a03 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
@@ -136,6 +136,7 @@
        layout="topleft"
        left="120"
        top="18"
+       max_length="512"
        name="sl_description_edit"
        width="173"
        word_wrap="true">
@@ -188,6 +189,7 @@
        height="100"
        layout="topleft"
        left="120"
+       max_length="512"
        top="142"
        name="fl_description_edit"
        width="173"
diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
index 9767a673f64e3bdda1afa1956fc9bcc3ab82b6d4..9ed510dff3e1feeed5f2a99f428c6529ffdc0b13 100644
--- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
@@ -2,26 +2,43 @@
 <panel
  name="panel_im_control_panel"
  width="146"
- height="215"
+ height="238"
  border="false">
     <avatar_list
      color="DkGray2"
      follows="left|top|right|bottom"
-     height="150"
+     height="130"
+     ignore_online_status="true"
      layout="topleft"
      left="3"
      name="speakers_list"
+     opaque="false"
+     show_info_btn="false"
+     show_profile_btn="false"
      top="10"
-     width="140"/>
+     width="140" />
     <button
      name="group_info_btn"
      label="Group Info"
      left_delta="3"
-     width="90"
+     width="125"
      height="20" />
     <button
      name="call_btn"
      label="Call"
-     width="90"
+     width="125"
      height="20" />
+    <button
+     name="end_call_btn"
+     label="End Call"
+     width="125"
+     height="20" 
+     visible="false"/>
+    <button
+	 enabled="false"
+     name="voice_ctrls_btn"
+     label="Open Voice Controls"
+     width="125"
+     height="20"
+     visible="false"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml
index 9bd240eccce73e57069275a95b9f436de2b16a7e..a85c55f9b2ca54c83e510715402c11da7582e0da 100644
--- a/indra/newview/skins/default/xui/en/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_general.xml
@@ -1,15 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
- border="true"
  follows="all"
- height="445"
+ height="412"
  label="General"
  class="panel_group_general"
  layout="topleft"
- left="1"
+ left="0"
+ top="0"
  name="general_tab"
- top="500"
- width="280">
+ width="313">
     <panel.string
      name="help_text">
         The General tab contains general information about this group, a list of members, general Group Preferences and member options.
@@ -18,7 +17,7 @@ Hover your mouse over the options for more help.
     </panel.string>
     <panel.string
      name="group_info_unchanged">
-        General group information has changed.
+        General group information has changed
     </panel.string>
     <panel.string
      name="incomplete_member_data_str">
@@ -28,42 +27,28 @@ Hover your mouse over the options for more help.
      type="string"
      follows="left|top"
      left="5"
-     height="75"
+     height="60"
      layout="topleft"
      max_length="511"
      name="charter"
      top="5"
-     width="260"
+     width="303"
      word_wrap="true">
-        Group Charter
+     Group Charter
     </text_editor>
-    <text
-      follows="left|top"
-     type="string"
-     font="SansSerifBig"
-     tool_tip="Owners are shown in bold."
-     height="16"
-     layout="topleft"
-     left="5"
-     name="text_owners_and_visible_members"
-     text_color="EmphasisColor"
-     top_pad="10"
-     width="270">
-        Members
-    </text>
     <name_list
      column_padding="0"
      draw_heading="true"
      follows="left|top"
-     heading_height="14"
-     height="80"
+     heading_height="16"
+     height="160"
      layout="topleft"
      left_delta="0"
      name="visible_members"
      top_pad="0"
-     width="263">
+     width="303">
         <name_list.columns
-         label="Member Name"
+         label="Member"
          name="name"
          relative_width="0.6" />
         <name_list.columns
@@ -71,27 +56,16 @@ Hover your mouse over the options for more help.
          name="title"
          relative_width="0.4" />
       </name_list>
-    <text
-      follows="left|top"
-      height="16"
-     type="string"
-     text_color="EmphasisColor"
-     top_pad="10"
-     font="SansSerifBig"
-     layout="topleft"
-     name="text_group_preferences">
-        Group Preferences
-    </text>
          <text
          follows="left|top"
          type="string"
-         height="16"
+         height="14"
          layout="topleft"
          left_delta="0"
          name="active_title_label"
-         top_pad="8"
-         width="240">
-            My Active Title
+         top_pad="5"
+         width="303">
+            My Title
         </text>
         <combo_box
          follows="left|top"
@@ -100,58 +74,58 @@ Hover your mouse over the options for more help.
          left_delta="0"
          name="active_title"
          tool_tip="Sets the title that appears in your avatar&apos;s name tag when this group is active."
-         top_pad="0"
-         width="240" />
+         top_pad="2"
+         width="303" />
         <check_box
          height="16"
          font="SansSerifSmall"
          label="Receive notices"
          layout="topleft"
-         left_delta="0"
+         left="5"
          name="receive_notices"
          tool_tip="Sets whether you want to receive Notices from this group.  Uncheck this box if this group is spamming you."
          top_pad="5"
-         width="240" />
+         width="303" />
         <check_box
          height="16"
          label="Show in my profile"
          layout="topleft"
-         left_delta="0"
+         left="5"
          name="list_groups_in_profile"
          tool_tip="Sets whether you want to show this group in your profile"
          top_pad="5"
-         width="240" />
+         width="303" />
         <panel
          background_visible="true"
          bevel_style="in"
          border="true"
          bg_alpha_color="FloaterUnfocusBorderColor"
          follows="left|top"
-         height="125"
+         height="93"
          layout="topleft"
-         left_delta="0"
+         left="5"
          name="preferences_container"
-         top_pad="10"
-         width="263">
+         top_pad="5"
+         width="303">
         <check_box
          follows="right|top"
          height="16"
          label="Open enrollment"
          layout="topleft"
-         left_delta="0"
+         left="10"
          name="open_enrollement"
          tool_tip="Sets whether this group allows new members to join without being invited."
          top_pad="5"
          width="90" />
         <check_box
          height="16"
-         label="Enrollment fee:"
+         label="Enrollment fee"
          layout="topleft"
          left_delta="0"
          name="check_enrollment_fee"
          tool_tip="Sets whether to require an enrollment fee to join the group"
          top_pad="5"
-         width="90" />
+         width="300" />
         <spinner
          decimal_digits="0"
          follows="left|top"
@@ -161,43 +135,38 @@ Hover your mouse over the options for more help.
          label_width="20"
          label="L$"
          layout="topleft"
-         left="25"
+         right="-10"
          max_val="99999"
-         top_pad="5"
+         left_pad="2"
          name="spin_enrollment_fee"
          tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked."
-         top_delta="-2"
          width="105" />
         <check_box
          height="16"
          initial_value="true"
          label="Show in search"
          layout="topleft"
-         left="4"
+         left="10"
          name="show_in_group_list"
          tool_tip="Let people see this group in search results"
          top_pad="4"
-         width="90" />
+         width="300" />
         <combo_box
          height="20"
          layout="topleft"
          left_delta="0"
          name="group_mature_check"
          tool_tip="Sets whether your group information is considered mature"
-         top_pad="10"
-         width="240">
-            <combo_box.item
-             label="- Select Mature -"
-             name="select_mature"
-             value="Select" />
-            <combo_box.item
-             label="Mature Content"
-             name="mature"
-             value="Mature" />
+         top_pad="5"
+         width="190">
             <combo_box.item
              label="PG Content"
              name="pg"
              value="Not Mature" />
-        </combo_box>  
+             <combo_box.item
+             label="Mature Content"
+             name="mature"
+             value="Mature" />
+        </combo_box>
     </panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
index da6cf8891a4cee47c903421d1584ea4cb4e4e2a3..d8d47c40084940d6390abfcb49aa9aab3b9ceb3d 100644
--- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
@@ -1,20 +1,22 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-
 <panel
- 	follows="left|top|right|bottom"
-	height="660"
-	label="Group Info"
- 	layout="topleft"
-	name="panel_group_info"
-	border="false"
-	width="300">
+background_visible="true"
+ follows="all"
+ height="570"
+ label="Group Info"
+ layout="topleft"
+ min_height="350"
+ left="0"
+ top="20"
+ name="GroupInfo"
+ width="333">
     <panel.string
      name="default_needs_apply_text">
-        There are unapplied changes on the current tab.
+        There are unsaved changes to the current tab
     </panel.string>
     <panel.string
      name="want_apply_text">
-        Do you want to apply these changes?
+        Do you want to save these changes?
     </panel.string>
     <panel.string
      name="group_join_btn">
@@ -25,34 +27,34 @@
         Free
     </panel.string>
     <button
-     layout="topleft"
-     name="back"
-     right="-9"
-     top="0"
-     width="25"
-     height="25"
-     label=""
      follows="top|right"
+     height="23"
      image_overlay="BackArrow_Off"
-     tab_stop="false" />
-    <text
      layout="topleft"
-     top="0"
+     name="back"
+     picture_style="true"
      left="10"
-     width="250"
-     height="20"
+     tab_stop="false"
+     top="2"
+     width="23" />
+    <text
+     follows="top|left|right"
      font="SansSerifHugeBold"
+     height="26"
+     layout="topleft"
+     left_pad="10"
+     name="group_name"
      text_color="white"
-     follows="top|left|right"
-     mouse_opaque="true"
-     use_ellipses="true"
-     name="group_name">(Loading...)</text>
+     top="0"
+     value="(Loading...)"
+     use_elipsis="true"
+     width="300" />
     <line_editor
      follows="left|top"
      font="SansSerif"
      label="Type your new group name here"
      layout="topleft"
-     left_delta="0"
+     left_delta="10"
      max_length="35"
      name="group_name_editor"
      top_delta="5"
@@ -64,7 +66,7 @@
      height="113"
      label=""
      layout="topleft"
-	 left="10"
+     left="20"
      name="insignia"
      tool_tip="Click to choose a picture"
      top_pad="5"
@@ -79,7 +81,7 @@
      name="prepend_founded_by"
      top_delta="0"
      width="140">
-      Founded by:
+      Founder:
     </text>
     <name_box
      follows="left|top"
@@ -88,10 +90,12 @@
      layout="topleft"
      left_delta="0"
      name="founder_name"
-     top_pad="10"
+     top_pad="2"
      use_ellipses="true"
      width="140" />
     <text
+    font="SansSerifBig"
+    text_color="EmphasisColor"
      type="string"
      follows="left|top"
      height="16"
@@ -106,22 +110,84 @@
     <button
      follows="left|top"
      left_delta="0"
-     top_pad="10"
-     height="20"
+     top_pad="6"
+     height="23"
      label="Join now!"
      label_selected="Join now!"
      name="btn_join"
      visible="true"
-     width="85" />
-    <button
-     top="632"
-     height="20"
-     font="SansSerifSmall"
-     label="Save"
-     label_selected="Save"
-     name="btn_apply"
-     left="5"
-     width="65" />
+     width="120" />
+   <accordion
+             follows="all"
+             height="405"
+             layout="topleft"
+             left="0"
+             name="groups_accordion"
+             top_pad="20"
+             width="333">
+             <accordion_tab
+                 can_resize="false"
+                 layout="topleft"
+                 name="tab_general"
+                 title="General">
+        <panel
+        border="false"
+         filename="panel_group_general.xml"
+         layout="topleft"
+         left="0"
+         help_topic="group_general_tab"
+         name="general_tab"
+         top="0"
+         width="333" />
+         </accordion_tab>
+         <accordion_tab
+                 can_resize="false"
+                 expanded="false"
+                 layout="topleft"
+                 name="tab_roles"
+                 title="Roles">
+        <panel
+        border="false"
+         filename="panel_group_roles.xml"
+         layout="topleft"
+         left="0"
+         help_topic="group_roles_tab"
+         name="roles_tab"
+         top="0"
+         width="333" />
+         </accordion_tab>
+         <accordion_tab
+                 can_resize="false"
+                 expanded="false"
+                 layout="topleft"
+                 name="tab_notices"
+                 title="Notices">
+        <panel
+         filename="panel_group_notices.xml"
+         layout="topleft"
+         left="0"
+         help_topic="group_notices_tab"
+         name="notices_tab"
+         top="0"
+         width="333" />
+         </accordion_tab>
+                  <accordion_tab
+                 can_resize="false"
+                 expanded="false"
+                 layout="topleft"
+                 name="tab_notices"
+                 title="Land/Assets">
+        <panel
+        border="false"
+         filename="panel_group_land_money.xml"
+         layout="topleft"
+         left="0"
+         help_topic="group_land_money_tab"
+         name="land_money_tab"
+         top="0"
+         width="333" />
+         </accordion_tab>
+         </accordion>
     <button
      follows="top|left"
      height="20"
@@ -129,41 +195,31 @@
      layout="topleft"
      name="btn_refresh"
      picture_style="true"
-     top="632"
-     left="75"
+     left="5"
      width="20" />
+     <button
+     height="20"
+     font="SansSerifSmall"
+     label="Save"
+     label_selected="Save"
+     name="btn_apply"
+     left_pad="5"
+     width="65" />
     <button
-     top="632"
      height="20"
      label="Create"
      label_selected="Create"
      name="btn_create"
-     left="5"
+     left_pad="5"
      visible="false"
      width="65" />
     <button
-	 top="632"
-	 left="75"	 
+     left_pad="5"
      height="20"
      label="Cancel"
      label_selected="Cancel"
      name="btn_cancel"
      visible="false"
      width="65" />
-      <accordion layout="topleft" left="2" width="296" top="135" height="500" follows="all" name="group_accordion">
-		<accordion_tab min_height="445" title="General" name="group_general_tab">
-        	<panel class="panel_group_general" filename="panel_group_general.xml" name="group_general_tab_panel"/>
-		</accordion_tab>
-		<accordion_tab min_height="380" title="Members &amp; Roles" name="group_roles_tab" expanded="False" can_resize="false">
-        	<panel class="panel_group_roles" filename="panel_group_roles.xml" name="group_roles_tab_panel"/>
-		</accordion_tab>
-		<accordion_tab min_height="530" title="Notices" name="group_notices_tab" expanded="False" can_resize="false">
-			<panel class="panel_group_notices" filename="panel_group_notices.xml" name="group_notices_tab_panel"/>
-		</accordion_tab>
-		<accordion_tab min_height="270" title="Land &amp; L$" name="group_land_tab" expanded="False" can_resize="false">
-			<panel class="panel_group_land_money" filename="panel_group_land_money.xml" name="group_land_tab_panel"/>
-		</accordion_tab>
-	  </accordion>
-
 
 </panel>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
index 0845ec014eb2536717efeaa3ba920d16a2c9a018..04e0ad3be8a3d3b94bfcaeb09b66d0974b45b32f 100644
--- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
@@ -230,7 +230,7 @@
      top_delta="0"
      width="250">
         Group members must contribute more land credits to support land in use.
-    </text> 
+    </text>
     <text
      type="string"
      follows="left|top"
@@ -247,15 +247,17 @@
     <tab_container
      follows="all"
      height="200"
+     halign="center"
      layout="topleft"
      left="10"
      name="group_money_tab_container"
      tab_position="top"
+     tab_height="20"
      top_pad="10"
      width="265">
         <panel
          border="true"
-         follows="left|top|right|bottom"
+         follows="all"
          height="180"
          label="Planning"
          layout="topleft"
@@ -305,7 +307,7 @@
              width="250"
              word_wrap="true">
                 Computing...
-            </text_editor> 
+            </text_editor>
           <button
              height="20"
              label="&lt; Earlier"
@@ -325,7 +327,7 @@
              name="later_details_button"
              tool_tip="Go forward in time"
              top_delta="0"
-             width="125" />  
+             width="125" />
         </panel>
       <panel
          border="true"
@@ -375,4 +377,4 @@
              width="125" />
         </panel>
     </tab_container>
-</panel> 
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml
index 7bdcaafe31508cec3241f13111601d25d8890f5e..ffa485051c7b91c7a68d3e71d81afbe854fdd7f2 100644
--- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml
@@ -28,13 +28,11 @@
      visible="false"
      width="320" />
     <icon
-     follows="top|left"
      height="20"
      image_name="Generic_Group"
      name="group_icon"
-     layout="topleft"
-     left="5"
      mouse_opaque="true"
+     left="5"
      top="2"
      width="20" />
    <text
@@ -47,28 +45,28 @@
      top="6"
      use_ellipses="true"
      value="Unknown"
-     width="246" />
+     width="242" />
     <button
      follows="right"
      height="16"
      image_pressed="Info_Press"
-     image_hover="Info_Over"
-     image_unselected="Info_Off"
+     image_unselected="Info_Over"
      left_pad="3"
-     right="-25"
+     right="-31"
      name="info_btn"
      picture_style="true"
+     top_delta="-2"
      width="16" />
+   <!--*TODO: Should only appear on rollover-->
     <button
      follows="right"
-     height="16"
-      image_selected="BuyArrow_Press"
-     image_pressed="BuyArrow_Press"
-     image_unselected="BuyArrow_Press"
+     height="20"
+     image_overlay="ForwardArrow_Off"
      layout="topleft"
      left_pad="5"
-     right="-5"
+     right="-3"
      name="profile_btn"
      picture_style="true"
-     width="16" />
+     top_delta="-2"
+     width="20" />
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 75ded4f249a104686ee0232ae1a686a0864e7be1..909c3f457760fbfb8c6f5e71cee8fab6b9d989db 100644
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -1,20 +1,20 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
- border="true"
- height="490"
+ border="false"
+ height="412"
  label="Members &amp; Roles"
  layout="topleft"
- left="1"
+ left="0"
+ top="0"
  name="roles_tab"
- top="490"
- width="280">
+ width="313">
     <panel.string
      name="default_needs_apply_text">
-        There are unapplied changes on the current sub-tab.
+        There are unsaved changes to the current tab
     </panel.string>
     <panel.string
      name="want_apply_text">
-        Do you want to apply these changes?
+        Do you want to save these changes?
     </panel.string>
     <panel.string
      name="help_text" />
@@ -160,17 +160,20 @@
         </text>
     </panel> -->
     <tab_container
+    border="true"
      follows="left|top"
-     height="180"
+     height="260"
+     halign="center"
      layout="topleft"
      left="5"
      name="roles_tab_container"
      tab_position="top"
-     top="10"
-     width="265">
+     tab_height="20"
+     top="0"
+     width="303">
         <panel
-         border="true"
-         height="165"
+         border="false"
+         height="260"
          label="Members"
          layout="topleft"
          left="1"
@@ -179,7 +182,7 @@
          tool_tip="Members"
          top="17"
          class="panel_group_members_subtab"
-         width="265">
+         width="300">
             <panel.string
              name="help_text">
                 You can add or remove Roles assigned to Members.
@@ -190,77 +193,56 @@ clicking on their names.
          layout="topleft"
          top="10"
          left="4"
-         width="255"
+         width="280"
          height="20"
          follows="left|top|right"
          max_length="250"
          label="Filter Members"
          name="filter_input"
          font="SansSerif" />
-            <!--<line_editor
-             border_style="line"
-             border_thickness="1"
-             follows="left|top"
-             height="16"
-             layout="topleft"
-             left="4"
-             max_length="63"
-             name="search_text"
-             top="10"
-             width="90" />
-            <button
-             font="SansSerifSmall"
-             height="20"
-             label="Search"
-             layout="topleft"
-             left_pad="5"
-             name="search_button"
-             top_delta="-2"
-             width="80" />
-            <button
+          <!--  <button
              enabled="false"
              font="SansSerifSmall"
              height="20"
              label="Show All"
              layout="topleft"
-             left_pad="0"
+             left_pad="-90"
              name="show_all_button"
-             top_delta="0"
-             width="80" /> -->
+             top_delta="-6"
+             width="80" />-->
             <name_list
              column_padding="0"
              draw_heading="true"
-             heading_height="14"
-             height="100"
+             heading_height="20"
+             height="160"
              follows="left|top"
              layout="topleft"
-             left="4"
+             left="0"
              multi_select="true"
              name="member_list"
-             top_pad="6"
-             width="255">
+             top_pad="2"
+             width="300">
                 <name_list.columns
                  label="Member"
                  name="name"
-                 width="90" />
+               relative_width="0.45" />
                 <name_list.columns
                  label="Donations"
                  name="donated"
-                 width="95" />
+         relative_width="0.3" />
                 <name_list.columns
                  label="Online"
                  name="online"
-                 width="80" />
+         relative_width="0.2" />
             </name_list>
             <button
              height="20"
              font="SansSerifSmall"
              label="Invite"
              layout="topleft"
-             left_delta="0"
              name="member_invite"
-             top_pad="6"
-             width="125" />
+             top_pad="3"
+             width="100" />
             <button
              height="20"
              font="SansSerifSmall"
@@ -268,18 +250,17 @@ clicking on their names.
              layout="topleft"
              left_pad="5"
              name="member_eject"
-             top_delta="0"
-             width="125" />
+             width="100" />
             <icon
              height="16"
-             image_name="inv_folder_plain_closed.tga"
+             image_name="Inv_FolderClosed"
              layout="topleft"
              name="power_folder_icon"
              visible="false"
              width="16" />
         </panel>
         <panel
-         border="true"
+         border="false"
          height="164"
          label="Roles"
          layout="topleft"
@@ -292,7 +273,7 @@ clicking on their names.
             <panel.string
              name="help_text">
                 Roles have a title and an allowed list of Abilities
-that Members can perform. Members can belong to 
+that Members can perform. Members can belong to
 one or more Roles. A group can have up to 10 Roles,
 including the Everyone and Owner Roles.
             </panel.string>
@@ -302,7 +283,7 @@ including the Everyone and Owner Roles.
             </panel.string>
             <panel.string
              name="power_folder_icon">
-                inv_folder_plain_closed.tga
+                Inv_FolderClosed
             </panel.string>
             <panel.string
              name="power_all_have_icon">
@@ -316,7 +297,7 @@ including the Everyone and Owner Roles.
             layout="topleft"
             top="10"
             left="4"
-            width="255"
+            width="260"
             height="20"
             follows="left|top|right"
             max_length="250"
@@ -357,13 +338,13 @@ including the Everyone and Owner Roles.
              column_padding="0"
              draw_heading="true"
              follows="left|top"
-             heading_height="14"
-             height="100"
+             heading_height="20"
+             height="150"
              layout="topleft"
              left="4"
              name="role_list"
              top_pad="4"
-             width="255">
+             width="300">
                 <scroll_list.columns
                  label="Role"
                  name="name"
@@ -397,7 +378,7 @@ including the Everyone and Owner Roles.
              width="125" />
         </panel>
         <panel
-         border="true"
+         border="false"
          height="164"
          label="Abilities"
          layout="topleft"
@@ -407,7 +388,7 @@ including the Everyone and Owner Roles.
          class="panel_group_actions_subtab"
          top="17"
          tool_tip="You can view an Ability&apos;s Description and which Roles and Members can execute the Ability."
-         width="265">
+         width="300">
             <panel.string
              name="help_text">
                 Abilities allow Members in Roles to do specific
@@ -486,13 +467,13 @@ things in this group. There&apos;s a broad variety of Abilities.
         </panel>
     </tab_container>
     <panel
-     height="170"
+     height="150"
      layout="topleft"
      follows="left|top"
      left="10"
      name="members_footer"
-     top_pad="10"
-     width="265">
+     top_pad="2"
+     width="300">
         <text
          type="string"
          font="SansSerif"
@@ -556,7 +537,7 @@ things in this group. There&apos;s a broad variety of Abilities.
         </scroll_list>
     </panel>
     <panel
-     height="215"
+     height="252"
      layout="topleft"
      left_delta="0"
      name="roles_footer"
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
index 7dc94d1141dbacbfb5d9a7011c290566f9044adf..c4cdaa41f970cf401e376ee43599a558c21d3500 100644
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel name="panel_im_control_panel"
-       width="96"
-       height="215"
+       width="125"
+       height="248"
        border="false">
 
   <avatar_icon name="avatar_icon"
@@ -11,22 +11,37 @@
   <button name="view_profile_btn"
           label="View Profile"
           left_delta="3"
-          width="90"
+          width="125"
 		  height="20" />
 
   <button name="add_friend_btn"
           label="Add Friend"
-          width="90"
+          width="125"
           height="20" />
 
   <button name="call_btn"
           label="Call"
-          width="90"
+          width="125"
           height="20" />
 
+    <button
+     height="20"
+     label="End Call"
+     name="end_call_btn"
+     visible="false"
+     width="125" />
+
+  <button
+	 enabled="false"
+     name="voice_ctrls_btn"
+     label="Open Voice Controls"
+     width="125"
+     height="20"
+     visible="false"/>
+
   <button name="share_btn"
           label="Share"
-          width="90"
+          width="125"
           height="20" />
 
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml
index 00ede1fb2c6c03c67e2e2df65b0d748ebbddf65d..26d8304551d543ea4aff4c9f8932ae0c74ab56c3 100644
--- a/indra/newview/skins/default/xui/en/panel_instant_message.xml
+++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml
@@ -1,15 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
  background_visible="true"
- bevel_style="in"
  bg_alpha_color="0.3 0.3 0.3 0"
- height="140"
+ height="175"
  label="im_panel"
  layout="topleft"
  left="0"
  name="im_panel"
  top="0"
- width="350">
+ width="305">
     <string
      name="message_max_lines_count">
         6
@@ -19,50 +18,52 @@
      bevel_style="in"
      bg_alpha_color="black"
      follows="top"
-     height="30"
+     height="20"
      label="im_header"
      layout="topleft"
      left="5"
      name="im_header"
      top="5"
-     width="340">
+     width="295">
         <avatar_icon
          follows="right"
          height="20"
          image_name="icon_avatar_online.tga"
          layout="topleft"
-         left="5"
+         left="0"
          mouse_opaque="true"
          name="avatar_icon"
-         top="5"
+         top="0"
          width="20" />
         <icon
          follows="right"
          height="20"
          image_name="icon_top_pick.tga"
          layout="topleft"
-         left="5"
+         left="0"
          mouse_opaque="true"
          name="sys_msg_icon"
-         top="5"
+         top="0"
          width="20" />
         <text
          follows="left|right"
-         font="SansSerifBigBold"
+         font="SansSerifBold"
          height="20"
          layout="topleft"
-         left_pad="10"
+         left_pad="5"
          name="user_name"
          text_color="white"
          top="5"
          value="Darth Vader"
-         width="250" />
+         width="295" />
+	 <!-- TIME STAMP -->
         <text
          follows="right"
-         font="SansSerifBig"
+         font="SansSerif"
          height="20"
          layout="topleft"
-         left_pad="10"
+	 halign="right"
+         left="245"
          name="time_box"
          text_color="white"
          top="5"
@@ -71,25 +72,25 @@
     </panel>
     <text
      follows="left|top|bottom|right"
-     height="60"
+     height="86"
      layout="topleft"
      left="10"
      name="message"
      text_color="white"
-     top="40"
+     top="33"
      use_ellipses="true"
      value="MESSAGE"
-     width="330"
+     width="285"
      word_wrap="true"
      max_length="350" />
     <button
      follows="bottom"
-     font="SansSerifBigBold"
+     font="SansSerifBold"
      height="25"
-     label="reply"
+     label="Reply"
      layout="topleft"
-     left="120"
+     left="97"
      name="reply"
-     top="110"
+     top="137"
      width="110" />
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index c33f68eaf7ac4315ca57b6e54035438e8b593819..5293043ba7df9d8ed2ed156d076f7e5e44ed28d0 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -114,22 +114,10 @@
          image_disabled="AddItem_Disabled"
          layout="topleft"
          left_pad="5"
-         name="add_landmark_btn"
+         name="add_btn"
          picture_style="true"
          tool_tip="Add new landmark"
          width="18" />
-        <button
-         follows="bottom|left"
-         height="18"
-         image_selected="AddItem_Press"
-         image_unselected="AddItem_Off"
-         image_disabled="AddItem_Disabled"
-         layout="topleft"
-         left_pad="5"
-         name="add_folder_btn"
-         picture_style="true"
-         tool_tip="Add new folder"
-         width="18" />
         <dnd_button
          follows="bottom|right"
          height="18"
diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
index a56f1cf8fee1cf6dc7ff20070c113465fbe50fe6..cc47e99c2cb9c6d80a22d4259b448e4cf07cf428 100644
--- a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
@@ -8,6 +8,7 @@
  left="102" 
  mouse_opaque="true"
  name="Media Settings General" 
+ help_topic = "media_settings_general"
  width="365">
 	
   <text 
@@ -31,6 +32,27 @@
     <!--  <line_editor.commit_callback
 	     function="Media.CommitHomeURL"/> -->
   </line_editor>
+
+  <web_browser
+   border_visible="true"
+   bottom_delta="-133"
+   follows="top|left"
+   left="120"
+   name="preview_media"
+   width="128"
+   height="128"
+   start_url="about:blank"
+   decouple_texture_size="true" />
+  
+  <text
+   bottom_delta="-15"
+   follows="top|left"
+   height="15"
+   left="164"
+   name="">
+    Preview
+  </text>
+  
   <text 
    bottom_delta="-20" 
    follows="top|left" 
@@ -61,27 +83,6 @@
    <button.commit_callback
 	     function="Media.ResetCurrentUrl"/>
   </button>
-
-  <web_browser 
-   border_visible="false" 
-   bottom_delta="-133" 
-   follows="top|left"
-   left="120" 
-   name="preview_media" 
-   width="128" 
-   height="128" 
-   start_url="about:blank" 
-   decouple_texture_size="true" />
-
-  <text 
-   bottom_delta="-15" 
-   follows="top|left" 
-   height="15" 
-   left="164" 
-   name="">
-    Preview
-  </text>
-
   <text 
    bottom_delta="-5" 
    follows="top|left" 
@@ -135,7 +136,8 @@
 
   <check_box 
    bottom_delta="-25" 
-   enabled="true" 
+   visible="false" 
+   enabled="false" 
    follows="left|top" 
    font="SansSerifSmall"
    height="16" 
@@ -148,7 +150,7 @@
    width="150" />
 
   <check_box 
-   bottom_delta="-25" 
+   bottom_delta="0" 
    enabled="true" 
    follows="left|top"
    font="SansSerifSmall"
@@ -161,20 +163,6 @@
    radio_style="false" 
    width="150" />
 
-  <check_box 
-   bottom_delta="-25" 
-   enabled="true" 
-   follows="left|top" 
-   font="SansSerifSmall"
-   height="16" 
-   initial_value="false"
-   label="Use Default Alternative Image" 
-   left="10" 
-   mouse_opaque="true"
-   name="alt_image_enable" 
-   radio_style="false" 
-   width="150" />
-
   <check_box 
    bottom_delta="-25" 
    enabled="true" 
@@ -234,7 +222,7 @@
    label="" 
    label_width="0"
    left_delta="40" 
-   max_val="2000" 
+   max_val="2048" 
    min_val="0" 
    mouse_opaque="true"
    name="width_pixels" 
@@ -246,7 +234,7 @@
   <spinner bottom_delta="0"
 	     decimal_digits="0" enabled="true" follows="left|top" height="16"
 	     increment="1" initial_val="256" label="" label_width="0"
-	     left_delta="20" max_val="2000" min_val="0" mouse_opaque="true"
+	     left_delta="20" max_val="2048" min_val="0" mouse_opaque="true"
 	     name="height_pixels" width="50" />
  
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
index 0cc1406d6277b305bb85cdbe12a0a23c79347be4..85f534c4a3bf4e192ec3366ed4940328634e172d 100644
--- a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
@@ -8,6 +8,7 @@
  left="102" 
  mouse_opaque="true"
  name="Media settings for controls" 
+ help_topic = "media_settings_controls"
  width="365">
 
   <text 
@@ -15,7 +16,6 @@
    follows="top|left" 
    height="15" 
    left="10" 
-   name="media_perms_label_owner" 
    enabled="false">
     Owner
   </text>
@@ -53,9 +53,8 @@
    follows="top|left" 
    height="15" 
    left="10" 
-   name="media_perms_label_group" 
    enabled="false">
-    Group
+    Group:
   </text>
   
   <name_box 
@@ -101,7 +100,6 @@
    follows="top|left" 
    height="15" 
    left="10" 
-   name="media_perms_label_anyone" 
    enabled="false">
     Anyone
   </text>
diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_security.xml b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml
index 695e956e41b1b363f800a5c3c5dbf3403fd2ebce..a26f74844e6960c636477b528c3b4b3c2fc392cb 100644
--- a/indra/newview/skins/default/xui/en/panel_media_settings_security.xml
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml
@@ -8,6 +8,7 @@
  left="102" 
  mouse_opaque="true"
  name="Media Settings Security" 
+ help_topic = "media_settings_security"
  width="365">
   <check_box 
    bottom_delta="-40" 
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
index 2fd82d8f3d4812a41f202fd8b1b0b1c6f6671215..2182163da5bd88dd2826d379028751758cfed9f3 100644
--- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
@@ -6,7 +6,7 @@
  layout="topleft"
  left="0"
  name="chat_bar"
- top="24"
+ top="21"
  width="310">
     <string name="min_width">
         310
@@ -18,20 +18,20 @@
      border_style="line"
      border_thickness="1"
      follows="left|right"
-     height="20"
+     height="23"
      label="Click here to chat."
      layout="topleft"
      left_delta="7"
      left="0"
+     max_length="254"
      name="chat_box"
      tool_tip="Press Enter to say, Ctrl+Enter to shout"
-     top="3"
+     top="0"
      width="250" />
     <output_monitor
      auto_update="true"
      follows="right"
      draw_border="false"
-     halign="left"
      height="16"
      layout="topleft"
      left_pad="-24"
@@ -40,15 +40,15 @@
      top="4"
      visible="true"
      width="20" />
-    <button 
-     follows="right" 
+    <button
+     follows="right"
      width="45"
-     top="3" 
-     layout="topleft" 
-     left_pad="5"
-     label="Log" 
-     height="20"
-     tool_tip="Shows/hides nearby chat log">
+     top="0"
+     layout="topleft"
+     left_pad="8"
+     label="Log"
+     height="23"
+     tool_tip="Show/hide nearby chat log">
     <button.commit_callback function="Floater.Toggle" parameter="nearby_chat"/>
     </button>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml
index 9c2829d92da360efc9a7be11e9d02cd4f4232c78..0d34aa0f081571f610e73e4d23591bd4feeeb83a 100644
--- a/indra/newview/skins/default/xui/en/panel_notification.xml
+++ b/indra/newview/skins/default/xui/en/panel_notification.xml
@@ -1,37 +1,51 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
-  background_opaque="true"
-  background_visible="false"
+  background_opaque="false"
+      border_visible="false"
+  border = "false"
+  border_drop_shadow_visible = "false"
+  drop_shadow_visible = "false"
+  background_visible="true"
   bg_alpha_color="0.3 0.3 0.3 0"
-  height="140"
+  bg_opaque_color="0.3 0.3 0.3 0"
   label="notification_panel"
   layout="topleft"
   left="0"
   name="notification_panel"
   top="0"
-  width="350">
+  	height="10"
+  width="305">
+  <!-- THIS PANEL CONTROLS TOAST HEIGHT? -->
   <panel
+      border_visible="false"
+      drop_shadow="false"
+ bevel_style="none"
+ border_style="none"
+  border = "false"
+  border_drop_shadow_visible = "false"
+  drop_shadow_visible = "false"
     background_visible="true"
-    bg_alpha_color="0.3 0.3 0.3 0"
+  bg_alpha_color="0.3 0.3 0.3 0"
+  bg_opaque_color="0.3 0.3 0.3 0"
     follows="left|right|top"
-    height="100"
+    height="10"
     label="info_panel"
     layout="topleft"
     left="0"
     name="info_panel"
     top="0"
-    width="350">
-    <text
+    width="305">
+  <!--  <text
       border_visible="false"
       follows="left|right|top|bottom"
       font="SansSerif"
       height="90"
       layout="topleft"
-      left="45"
+      left="10"
       name="text_box"
       read_only="true"
       text_color="white"
-      top="5"
+      top="10"
       visible="false" 
       width="300"
       wrap="true"/>
@@ -47,40 +61,43 @@
       top="5"
       visible="false"
       width="300"
-      wrap="true"/>
+      wrap="true"/>  -->
     <text_editor
+    	h_pad="0"
+	v_pad="0"
       bg_readonly_color="0.0 0.0 0.0 0"
       border_visible="false"
+	  border = "false"
+	  border_drop_shadow_visible = "false"
+	  drop_shadow_visible = "false"
       embedded_items="false"
       enabled="false"
       follows="left|right|top|bottom"
       font="SansSerif"
-      height="90"
       layout="topleft"
-      left="45"
+      left="10"
       mouse_opaque="false"
       name="text_editor_box"
       read_only="true"
       tab_stop="false"
       text_color="white"
       text_readonly_color="white"
-      top="5"
+      top="10"
       visible="false"
-      width="300"
+      width="285"
       wrap="true"/>
   </panel>
   <panel
-    background_visible="true"
-    bg_alpha_color="0.3 0.3 0.3 0"
+    background_visible="false"
     follows="left|right|bottom"
-    height="40"
     label="control_panel"
     layout="topleft"
     left="0"
+    left_delta="-38"
     name="control_panel"
-    top_pad="0"
-    width="350">
+    top="20">
   </panel>
+  <!--
   <icon
     follows="left|top"
     height="32"
@@ -90,5 +107,5 @@
     mouse_opaque="false"
     name="info_icon"
     top="20"
-    width="32" />
+    width="32" />  -->
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 7b19ab1a1cb61b7ff8286b904d071eb9ea300d96..e234a7b358ebbfd9a0d38a14516a10f23f5d4cc0 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -34,7 +34,6 @@ background_visible="true"
      value="Filter Groups" />
     <filter_editor
      follows="left|top|right"
-     font="SansSerif"
      height="23"
      layout="topleft"
      left="15"
@@ -54,11 +53,12 @@ background_visible="true"
      tab_height="30"
      tab_position="top"
      top_pad="10"
+     halign="center"
      width="313">
         <panel
          follows="all"
          height="500"
-         label="Nearby"
+         label="NEARBY"
          layout="topleft"
          left="0"
          help_topic="people_nearby_tab"
@@ -98,17 +98,30 @@ background_visible="true"
              picture_style="true"
              top="5"
              width="18" />
+             <button
+                 follows="bottom|left"
+                 height="18"
+                 image_selected="AddItem_Press"
+                 image_unselected="AddItem_Off"
+                 image_disabled="AddItem_Disabled"
+                 layout="topleft"
+                 left_pad="5"
+                 name="add_friend_btn"
+                 picture_style="true"
+                 top_delta="0"
+                 tool_tip="Add selected resident to your friends List"
+                 width="18" />
             </panel>
         </panel>
         <panel
          follows="all"
          height="500"
-         left="0"
-         top="0"
-         label="Friends"
+         label="FRIENDS"
          layout="topleft"
+         left="0"
          help_topic="people_friends_tab"
          name="friends_panel"
+         top="0"
          width="313">
             <accordion
              follows="all"
@@ -121,14 +134,13 @@ background_visible="true"
                 <accordion_tab
                  can_resize="false"
                  layout="topleft"
-                 height="230"
+                 height="235"
                  min_height="150"
                  name="tab_online"
                  title="Online">
                         <avatar_list
                          allow_select="true"
                          follows="all"
-                         height="150"
                          layout="topleft"
                          left="0"
                          multi_select="true"
@@ -139,13 +151,12 @@ background_visible="true"
                 <accordion_tab
                  can_resize="false"
                  layout="topleft"
-                 height="230"
+                 height="235"
                  name="tab_all"
                  title="All">
                         <avatar_list
                          allow_select="true"
                          follows="all"
-                         height="230"
                          layout="topleft"
                          left="0"
                          multi_select="true"
@@ -207,11 +218,12 @@ background_visible="true"
         <panel
          follows="all"
          height="500"
-         label="Groups"
-         top="0"
+         label="GROUPS"
          layout="topleft"
+         left="0"
          help_topic="people_groups_tab"
          name="groups_panel"
+         top="0"
          width="313">
             <group_list
              follows="all"
@@ -285,13 +297,14 @@ background_visible="true"
             </panel>
         </panel>
         <panel
-         top="0"
          follows="all"
          height="500"
-         label="Recent"
+         label="RECENT"
          layout="topleft"
+         left="0"
          help_topic="people_recent_tab"
          name="recent_panel"
+         top="0"
          width="313">
             <avatar_list
              allow_select="true"
@@ -301,11 +314,10 @@ background_visible="true"
              left="0"
              multi_select="true"
              name="avatar_list"
-             top="2"
+             show_last_interaction_time="true"
+             top="0"
              width="313" />
             <panel
-             background_visible="true"
-             bevel_style="none"
              top_pad="0"
              follows="left|right|bottom"
              height="30"
@@ -327,6 +339,19 @@ background_visible="true"
                picture_style="true"
                top="7"
                width="18" />
+              <button
+                 follows="bottom|left"
+                 height="18"
+                 image_selected="AddItem_Press"
+                 image_unselected="AddItem_Off"
+                 image_disabled="AddItem_Disabled"
+                 layout="topleft"
+                 left_pad="5"
+                 name="add_friend_btn"
+                 picture_style="true"
+                 top_delta="0"
+                 tool_tip="Add selected resident to your friends List"
+                 width="18" />
             </panel>
         </panel>
     </tab_container>
@@ -342,104 +367,88 @@ background_visible="true"
      width="313">
         <layout_panel
          default_tab_group="1"
-         follows="left|top|right"
+         follows="left|top"
          height="25"
          layout="topleft"
          left="0"
          name="view_profile_btn_panel"
          top="-25"
-         width="65">
+         width="100">
             <button
-             follows="top|left|right"
+             follows="top|left"
              font="SansSerifSmall"
              height="19"
              label="Profile"
              layout="topleft"
              name="view_profile_btn"
              tool_tip="Show picture, groups, and other residents information"
-             width="65" />
-        </layout_panel>
-        <layout_panel
-         default_tab_group="1"
-         follows="left|top|right"
-         height="25"
-         layout="topleft"
-         left_delta="0"
-         min_width="85"
-         name="add_friend_btn_panel"
-         top_delta="0"
-         width="50">
-            <button
-             follows="top|left|right"
-             font="SansSerifSmall"
-             height="19"
-             label="Add"
-             layout="topleft"
-             name="add_friend_btn"
-             tool_tip="Add selected resident to your friends List"
-             width="50" />
+             width="100" />
         </layout_panel>
         <layout_panel
          default_tab_group="1"
-         follows="left|top|right"
+         follows="left|top"
          height="19"
          layout="topleft"
+         left="0"
          min_width="80"
          name="group_info_btn_panel"
-         width="80">
+         width="100">
             <button
-             follows="top|left|right"
+             follows="top|left"
              font="SansSerifSmall"
              height="19"
              label="Group Profile"
              layout="topleft"
              name="group_info_btn"
              tool_tip="Show group information"
-             width="80" />
+             width="100" />
         </layout_panel>
         <layout_panel
          default_tab_group="1"
-         follows="left|top|right"
+         follows="left|top"
          height="25"
          layout="topleft"
+         left_pad="5"
          min_width="45"
          name="chat_btn_panel"
          top_delta="0"
-         width="45">
+         width="100">
             <button
-             follows="top|left|right"
+             follows="top|left"
              font="SansSerifSmall"
              height="19"
-             label="Chat"
+             label="Group Chat"
              layout="topleft"
              name="chat_btn"
              tool_tip="Open chat session"
-             width="45" />
+             width="100" />
         </layout_panel>
         <layout_panel
          default_tab_group="1"
-         follows="left|top|right"
+         follows="left|top|"
          height="25"
          layout="topleft"
+         left_pad="5"
          min_width="35"
          name="im_btn_panel"
          top_delta="0"
-         width="35">
+         width="50">
             <button
-             follows="top|left|right"
+             follows="top|left"
              font="SansSerifSmall"
              height="19"
              label="IM"
              layout="topleft"
              name="im_btn"
              tool_tip="Open instant message session"
-             width="35" />
+             width="50" />
         </layout_panel>
         <layout_panel
          default_tab_group="1"
          follows="left|top|right"
          height="25"
          layout="topleft"
+         left_pad="5"
          min_width="40"
          name="call_btn_panel"
          top_delta="0"
@@ -447,53 +456,55 @@ background_visible="true"
          width="40">
             <button
              enabled="false"
-             follows="top|left|right"
+             follows="top|left"
              font="SansSerifSmall"
              height="19"
              label="Call"
              layout="topleft"
              name="call_btn"
-             width="40" />
+             width="50" />
         </layout_panel>
         <layout_panel
          default_tab_group="1"
-         follows="left|top|right"
+         follows="left|top"
          height="25"
          layout="topleft"
+         left_pad="5"
          min_width="65"
          name="teleport_btn_panel"
          top_delta="0"
-         width="65">
+         width="100">
             <button
-             follows="left|top|right"
+             follows="left|top"
              font="SansSerifSmall"
              height="19"
              label="Teleport"
              layout="topleft"
              name="teleport_btn"
              tool_tip="Offer teleport"
-             width="65" />
+             width="100" />
         </layout_panel>
       <layout_panel
          default_tab_group="1"
          enabled="false"
-         follows="left|top|right"
+         follows="left|top"
          height="25"
          layout="topleft"
+         left_pad="5"
          min_width="50"
          name="share_btn_panel"
          top_delta="0"
          visible="false"
-         width="50">
+         width="80">
             <button
              enabled="false"
-             follows="top|left|right"
+             follows="top|left"
              font="SansSerifSmall"
              height="19"
              label="Share"
              layout="topleft"
              name="share_btn"
-             width="50" />
+             width="80" />
         </layout_panel>
     </layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
index 1074dd46276bd12fa044f412de3d77ebd7f28ff7..38ea6b6196e4665a30e78bd22f13890d41385782 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
@@ -57,7 +57,7 @@
      use_ellipses="false"
      width="197"
      word_wrap="false" />
-    <text
+    <expandable_text
      follows="top|left|right"
      font="SansSerifSmall"
      height="40"
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index 1ea6e1149d2f10e44d1a3e0c61668f78a0b7e57f..5aa53ab46b1049a5328516a7072a7d6b21098e46 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -1,62 +1,67 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
- background_visible="true"
+background_visible="true"
  follows="all"
- height="400"
+ height="570"
  label="Places"
  layout="topleft"
  min_height="350"
- min_width="240"
  name="places panel"
+ top="0"
+ left="0"
  width="333">
     <string
      name="landmarks_tab_title"
-     value="Landmarks" />
+     value="MY LANDMARKS" />
     <string
      name="teleport_history_tab_title"
-     value="Teleport History" />
+     value="TELEPORT HISTORY" />
     <filter_editor
      follows="left|top|right"
      font="SansSerif"
      height="23"
-     label="Filter"
      layout="topleft"
      left="15"
+     label="Filter"
+     max_length="300"
      name="Filter"
      top="3"
-     width="300" />
+     width="303" />
     <tab_container
      follows="all"
-     height="326"
+     halign="center"
+     height="500"
      layout="topleft"
-     left="9"
+     left="10"
      name="Places Tabs"
+     tab_min_width="80"
+     tab_height="30"
      tab_position="top"
-     top="30"
+     top_pad="10"
      width="313" />
     <panel
      class="panel_place_info"
      filename="panel_place_info.xml"
      follows="all"
-     height="326"
+     height="533"
      layout="topleft"
      left="0"
      help_topic="places_info_tab"
      name="panel_place_info"
-     top="30"
-     visible="false" />
+     top="5"
+     visible="false"
+     width="313" />
     <panel
-     height="25"
+     height="19"
      layout="topleft"
      left="0"
      help_topic="places_button_tab"
      name="button_panel"
-     top_pad="10"
      width="313">
         <button
          follows="bottom|left"
-         font="SansSerifSmallBold"
-         height="25"
+         font="SansSerifSmall"
+         height="19"
          label="Teleport"
          layout="topleft"
          left="5"
@@ -65,8 +70,8 @@
          width="77" />
         <button
          follows="bottom|left"
-         font="SansSerifSmallBold"
-         height="25"
+         font="SansSerifSmall"
+         height="19"
          label="Map"
          layout="topleft"
          left_pad="5"
@@ -76,8 +81,8 @@
         <button
          enabled="false"
          follows="bottom|left"
-         font="SansSerifSmallBold"
-         height="25"
+         font="SansSerifSmall"
+         height="19"
          label="Share"
          layout="topleft"
          left_pad="5"
@@ -86,8 +91,8 @@
          width="60" />
         <button
          follows="bottom|left"
-         font="SansSerifSmallBold"
-         height="25"
+         font="SansSerifSmall"
+         height="19"
          label="Edit"
          layout="topleft"
          left_pad="5"
@@ -96,18 +101,21 @@
          width="50" />
         <button
          follows="bottom|right"
-         font="SansSerifSmallBold"
-         height="25"
-         label="â–¼"
+         font="SansSerifSmall"
+         height="19"
+         image_disabled="ForwardArrow_Disabled"
+         image_selected="ForwardArrow_Press"
+         image_unselected="ForwardArrow_Off"
+         picture_style="true"
          layout="topleft"
          name="overflow_btn"
          right="-10"
          top="0"
-         width="30" />
+         width="18" />
         <button
          follows="bottom|right"
-         font="SansSerifSmallBold"
-         height="25"
+         font="SansSerifSmall"
+         height="19"
          label="Close"
          layout="topleft"
          name="close_btn"
@@ -116,8 +124,8 @@
          width="60" />
         <button
          follows="bottom|right"
-         font="SansSerifSmallBold"
-         height="25"
+         font="SansSerifSmall"
+         height="19"
          label="Cancel"
          layout="topleft"
          name="cancel_btn"
@@ -126,8 +134,8 @@
          width="60" />
         <button
          follows="bottom|right"
-         font="SansSerifSmallBold"
-         height="25"
+         font="SansSerifSmall"
+         height="19"
          label="Save"
          layout="topleft"
          name="save_btn"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 16fdbd704542612ec1089fae6054898bef2d2f6f..91dcdce23bb8bc44165f72e9584f21d49d50ba55 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -20,8 +20,9 @@
     </panel.string>
     <check_box
      control_name="UseChatBubbles"
+     follows="left|top"
      height="16"
-     label="Bubble Chat"
+     label="Bubble chat"
      layout="topleft"
      left="30"
      top="10"
@@ -30,6 +31,7 @@
 
     <slider
      control_name="ChatBubbleOpacity"
+     follows="left|top"
      height="16"
      increment="0.05"
      initial_value="1"
@@ -40,40 +42,24 @@
      label_width="50"
      name="bubble_chat_opacity"
      width="200" />
-
-   <!-- <check_box
-     control_name="UIAutoScale"
-     height="16"
-     label="Resolution independent scale"
-     layout="topleft"
-     left="30"
-     name="ui_auto_scale"
-     top_pad="10"
-     width="256" />-->
-    <!--
-    <combo_box
-     height="18"
-     layout="topleft"
-     left_pad="5"
-     name="fullscreen combo"
-     top_delta="-1"
-     width="150" /-->
     <text
+     follows="left|top"
      type="string"
      length="1"
      height="25"
      layout="topleft"
      left="30"
-     top_pad="20"
+     top_pad="5"
      name="AspectRatioLabel1"
      tool_tip="width / height"
      label_width="50"
      width="120">
-        Aspect Ratio
+        Aspect ratio
     </text>
     <combo_box
      allow_text_entry="true"
      height="20"
+     follows="left|top"
      layout="topleft"
      left_pad="0"
      max_chars="100"
@@ -104,6 +90,7 @@
     </combo_box>
     <check_box
      control_name="FullScreenAutoDetectAspectRatio"
+     follows="left|top"
      height="25"
      label="Auto-detect"
      layout="topleft"
@@ -113,14 +100,14 @@
         <check_box.commit_callback
          function="Pref.AutoDetectAspect" />
     </check_box>
-
      <text
+     follows="left|top"
      type="string"
      length="1"
      height="10"
      left="30"
      name="heading1"
-     top_pad="10"
+     top_pad="5"
      width="270">
 Camera:
 	</text>
@@ -128,7 +115,7 @@ Camera:
      can_edit_text="true"
 	 control_name="CameraAngle"
      decimal_digits="2"
-     top_pad="10"
+     top_pad="5"
      follows="left|top"
      height="16"
      increment="0.025"
@@ -159,56 +146,62 @@ Camera:
      name="camera_offset_scale"
      show_text="false"
      width="240"
-     top_pad="10"/>
+     top_pad="5"/>
      <text
+     follows="left|top"
      type="string"
      length="1"
      height="10"
      left="30"
      name="heading2"
-     width="270">
+     width="270"
+     top_pad="5">
 Automatic positioning for:
 	</text>
         <check_box
      control_name="EditCameraMovement"
      height="20"
+     follows="left|top"
      label="Build/Edit"
      layout="topleft"
      left_delta="50"
      name="edit_camera_movement"
      tool_tip="Use automatic camera positioning when entering and exiting edit mode"
      width="280"
-     top_pad="10" />
+     top_pad="5" />
     <check_box
      control_name="AppearanceCameraMovement"
+     follows="left|top"
      height="16"
      label="Appearance"
      layout="topleft"
      name="appearance_camera_movement"
      tool_tip="Use automatic camera positioning while in edit mode"
      width="242" />
-
      <text
+     follows="left|top"
      type="string"
      length="1"
      height="10"
      left="30"
      name="heading3"
-     top_pad="10"
+     top_pad="5"
      width="270">
 Avatars:
 	</text>
     <check_box
      control_name="FirstPersonAvatarVisible"
+     follows="left|top"
      height="20"
      label="Show me in Mouselook"
      layout="topleft"
      left_delta="50"
      name="first_person_avatar_visible"
      width="256"
-     top_pad="10"/>
+     top_pad="0"/>
     <check_box
      control_name="ArrowKeysMoveAvatar"
+     follows="left|top"
      height="20"
      label="Arrow keys always move me"
      layout="topleft"
@@ -218,6 +211,7 @@ Avatars:
      top_pad="0"/>
     <check_box
      control_name="AllowTapTapHoldRun"
+     follows="left|top"
      height="20"
      label="Tap-tap-hold to run"
      layout="topleft"
@@ -227,6 +221,7 @@ Avatars:
      top_pad="0"/>
     <check_box
      control_name="LipSyncEnabled"
+     follows="left|top"
      height="20"
      label="Move avatar lips when speaking"
      layout="topleft"
@@ -235,17 +230,19 @@ Avatars:
      width="237"
      top_pad="0" />
     <check_box
-     control_name="test"
+     control_name="ShowScriptErrors"
+     follows="left|top"
      height="20"
      label="Show script errors"
      layout="topleft"
      left="30"
      name="show_script_errors"
      width="256"
-     top_pad="10"/>
+     top_pad="5"/>
     <radio_group
-	 enabled_control="EnableShowScriptErrors"
+	 enabled_control="ShowScriptErrors"
 	 control_name="ShowScriptErrorsLocation"
+     follows="top|left"
      draw_border="false"
      height="40"
      layout="topleft"
@@ -259,17 +256,53 @@ Avatars:
          layout="topleft"
          left="3"
          name="0"
-         top="3"
+         top="0"
          width="315" />
         <radio_item
          height="16"
          label="In window"
          layout="topleft"
-         left_delta="0"
+         left_delta="175"
          name="1"
-         top_delta="16"
+         top_delta="0"
          width="315" />
     </radio_group>
-
-
+     <check_box
+     follows="top|left"
+     height="20"
+     label="Use Push-to-talk in toggle mode"
+     layout="topleft"
+     left="30"
+     name="push_to_talk_toggle_check"
+     width="237"
+     top_pad="-25"
+     tool_tip="When in toggle mode, press and release the push-to-talk trigger to switch your microphone on and off. When not in toggle mode, the microphone is active only when the trigger is held down."/>
+    <line_editor
+     follows="top|left"
+     height="19"
+     left_delta="50"
+     max_length="254"
+     name="modifier_combo"
+     label="Push-to-talk trigger"
+     top_pad="0"
+     width="280" />
+    <button
+	follows="top|left"
+	height="20"
+	label="Set Key"
+	left_delta="0"
+        name="set_voice_hotkey_button"
+	width="115"
+	top_pad="5" />
+    <button
+        bottom_delta="0"
+	follows="left"
+	font="SansSerif"
+	halign="center"
+	height="20"
+	label="Middle Mouse Button"
+	left_delta="120"
+	mouse_opaque="true"
+	name="set_voice_middlemouse_button"
+	width="160" />
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
index c4dc8834dbd7d14b3b2743773fd67e62e7e618ff..ce7939c00f525ad791500c3ea07e994afe75bb4e 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
@@ -77,10 +77,19 @@
      name="cookies_enabled"
      top_pad="10"
      width="350" />
+    <check_box
+     control_name="AutoPlayMedia"
+     height="16"
+     label="Allow Media Autoplay"
+     layout="topleft"
+     left="30"
+     name="autoplay_enabled"
+     top_pad="10"
+     width="350" />
     <text
-     type="string"
-     length="1"
-     follows="left|top"
+      type="string"
+    length="1"
+    follows="left|top"
      height="10"
      layout="topleft"
      left="30"
@@ -88,8 +97,9 @@
      top_pad="10"
      width="350">
         Logs:
-    </text>    
+    </text>
     <check_box
+   
 	 enabled="false"
      control_name="LogInstantMessages"
      height="16"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 8a28719d98393a111b8bebd5b608572aa0e6ea25..832c9775ce2fbc6880d14b97f14ef172682676bf 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
  border="true"
- follows="left|top|right|bottom"
+ follows="all"
  height="408"
- label="Audio &amp; Video"
+ label="Sounds"
  layout="topleft"
  left="102"
  name="Preference Media panel"
@@ -12,18 +12,20 @@
     <slider
      control_name="AudioLevelMaster"
      follows="left|top"
+     font.style="BOLD"
      height="15"
      increment="0.05"
      initial_value="0.5"
      label="Master volume"
-     label_width="125"
+     label_width="160"
      layout="topleft"
-     left="30"
+     left="0"
      name="System Volume"
      show_text="false"
+     slider_label.halign="right"
      top_pad="5"
      volume="true"
-     width="425">
+     width="350">
         <slider.commit_callback
          function="Pref.setControlFalse"
          parameter="MuteAudio" />
@@ -31,43 +33,44 @@
     <button
      control_name="MuteAudio"
      follows="top|right"
-     height="16"
-     image_selected="icn_speaker-muted_dark.tga"
-     image_unselected="icn_speaker_dark.tga"
+     height="18"
+     image_selected="parcel_drk_VoiceNo"
+     image_unselected="parcel_drk_Voice"
      is_toggle="true"
      layout="topleft"
-     left_pad="30"
+     left_pad="16"
      name="mute_audio"
      picture_style="true"
      tab_stop="false"
-     top_delta="-1"
-     width="25" />
+     top_delta="-2"
+     width="22" />
     <check_box
      control_name="MuteWhenMinimized"
-     height="16"
+     height="15"
      initial_value="true"
      label="Mute if minimized"
      layout="topleft"
-     left="165"
+     left="167"
      name="mute_when_minimized"
      top_pad="5"
      width="215" />
     <slider
      control_name="AudioLevelAmbient"
      disabled_control="MuteAudio"
-     follows="left|topt"
+     follows="left|top"
      height="15"
      increment="0.05"
      initial_value="0.5"
      label="Ambient"
-     label_width="125"
+     label_width="160"
      layout="topleft"
-     left="30"
+     left="0"
      name="Wind Volume"
      show_text="false"
-     top_pad="5"
+     slider_label.halign="right"
+     top_pad="7"
      volume="true"
-     width="300">
+     width="350">
         <slider.commit_callback
          function="Pref.setControlFalse"
          parameter="MuteAmbient" />
@@ -76,53 +79,54 @@
      control_name="MuteAmbient"
      disabled_control="MuteAudio"
      follows="top|right"
-     height="16"
-     image_selected="icn_speaker-muted_dark.tga"
-     image_unselected="icn_speaker_dark.tga"
+     height="18"
+     image_selected="parcel_drk_VoiceNo"
+     image_unselected="parcel_drk_Voice"
      is_toggle="true"
      layout="topleft"
-     left_pad="30"
+     left_pad="16"
      name="mute_wind"
      picture_style="true"
      tab_stop="false"
-     top_delta="-1"
-     width="25" />
-    <slider
-     control_name="AudioLevelSFX"
+     top_delta="-2"
+     width="22" />
+        <slider
+     control_name="AudioLevelUI"
      disabled_control="MuteAudio"
      follows="left|top"
      height="15"
      increment="0.05"
      initial_value="0.5"
-     label="Sounds"
-     label_width="125"
+     label="Buttons"
+     label_width="160"
      layout="topleft"
-     left="30"
-     name="SFX Volume"
+     left="0"
+     name="UI Volume"
      show_text="false"
-     top_pad="5"
+     slider_label.halign="right"
+     top_pad="7"
      volume="true"
-     width="300">
+     width="350">
         <slider.commit_callback
          function="Pref.setControlFalse"
-         parameter="MuteSounds" />
+         parameter="MuteUI" />
     </slider>
     <button
-     control_name="MuteSounds"
+     control_name="MuteUI"
      disabled_control="MuteAudio"
      follows="top|right"
-     height="16"
-     image_selected="icn_speaker-muted_dark.tga"
-     image_unselected="icn_speaker_dark.tga"
+     height="18"
+     image_selected="parcel_drk_VoiceNo"
+     image_unselected="parcel_drk_Voice"
      is_toggle="true"
      layout="topleft"
-     left_pad="30"
-     name="mute_sfx"
+     left_pad="16"
+     name="mute_ui"
      picture_style="true"
      tab_stop="false"
-     top_delta="-1"
-     width="25" />
-    <slider
+     top_delta="-2"
+     width="22" />
+        <slider
      control_name="AudioLevelMedia"
      disabled_control="MuteAudio"
      follows="left|top"
@@ -130,14 +134,15 @@
      increment="0.05"
      initial_value="0.5"
      label="Media"
-     label_width="125"
+     label_width="160"
      layout="topleft"
-     left="30"
+     left="0"
      name="Media Volume"
      show_text="false"
-     top_pad="5"
+     slider_label.halign="right"
+     top_pad="7"
      volume="true"
-     width="300">
+     width="350">
     <slider.commit_callback
      function="Pref.setControlFalse"
      parameter="MuteMedia" />
@@ -146,52 +151,53 @@
      control_name="MuteMedia"
      disabled_control="MuteAudio"
      follows="top|right"
-     height="16"
-     image_selected="icn_speaker-muted_dark.tga"
-     image_unselected="icn_speaker_dark.tga"
+     height="18"
+     image_selected="parcel_drk_VoiceNo"
+     image_unselected="parcel_drk_Voice"
      is_toggle="true"
      layout="topleft"
-     left_pad="30"
+     left_pad="16"
      name="mute_media"
      picture_style="true"
      tab_stop="false"
-     top_delta="-1"
-     width="25" />
+     top_delta="-2"
+     width="22" />
     <slider
-     control_name="AudioLevelUI"
+     control_name="AudioLevelSFX"
      disabled_control="MuteAudio"
      follows="left|top"
      height="15"
      increment="0.05"
      initial_value="0.5"
-     label="UI"
-     label_width="125"
+     label="Sound effects"
+     label_width="160"
+     slider_label.halign="right"
      layout="topleft"
-     left="30"
-     name="UI Volume"
+     left="0"
+     name="SFX Volume"
      show_text="false"
-     top_pad="5"
+     top_pad="7"
      volume="true"
-     width="300">
+     width="350">
         <slider.commit_callback
          function="Pref.setControlFalse"
-         parameter="MuteUI" />
+         parameter="MuteSounds" />
     </slider>
     <button
-     control_name="MuteUI"
+     control_name="MuteSounds"
      disabled_control="MuteAudio"
      follows="top|right"
-     height="16"
-     image_selected="icn_speaker-muted_dark.tga"
-     image_unselected="icn_speaker_dark.tga"
+     height="18"
+     image_selected="parcel_drk_VoiceNo"
+     image_unselected="parcel_drk_Voice"
      is_toggle="true"
      layout="topleft"
-     left_pad="30"
-     name="mute_ui"
+     left_pad="16"
+     name="mute_sfx"
      picture_style="true"
      tab_stop="false"
-     top_delta="-1"
-     width="25" />
+     top_delta="-2"
+     width="22" />
     <slider
      control_name="AudioLevelMusic"
      disabled_control="MuteAudio"
@@ -199,15 +205,16 @@
      height="15"
      increment="0.05"
      initial_value="0.5"
-     label="Music"
-     label_width="125"
+     label="Streaming music"
+     label_width="160"
      layout="topleft"
-     left="30"
+     left="0"
      name="Music Volume"
+     slider_label.halign="right"
      show_text="false"
-     top_pad="5"
+     top_pad="7"
      volume="true"
-     width="300">
+     width="350">
         <slider.commit_callback
          function="Pref.setControlFalse"
          parameter="MuteMusic" />
@@ -216,199 +223,206 @@
      control_name="MuteMusic"
      disabled_control="MuteAudio"
      follows="top|right"
-     height="16"
-     image_selected="icn_speaker-muted_dark.tga"
-     image_unselected="icn_speaker_dark.tga"
+     height="18"
+     image_selected="parcel_drk_VoiceNo"
+     image_unselected="parcel_drk_Voice"
      is_toggle="true"
      layout="topleft"
-     left_pad="30"
+     left_pad="16"
      name="mute_music"
      picture_style="true"
      tab_stop="false"
-     top_delta="-1"
-     width="25" />
+     top_delta="-2"
+     width="22" />
+     <check_box
+     height="16"
+	 control_name ="EnableVoiceChat"
+	 disabled_control="CmdLineDisableVoice"
+     label="Enable Voice"
+     layout="topleft"
+     left="22"
+     name="enable_voice_check"
+     width="100">
+    </check_box>
     <slider
      control_name="AudioLevelVoice"
+     enabled_control="EnableVoiceChat"
      disabled_control="MuteAudio"
      follows="left|top"
      height="15"
      increment="0.05"
      initial_value="0.5"
-     label="Voice"
-     label_width="125"
+	 label="Voice"
+     label_width="60"
      layout="topleft"
-     left="30"
+     left="100"
      name="Voice Volume"
      show_text="false"
-     top_pad="5"
+     slider_label.halign="right"
+     top_pad="-15"
      volume="true"
-     width="300">
+     width="250">
         <slider.commit_callback
          function="Pref.setControlFalse"
          parameter="MuteVoice" />
     </slider>
     <button
      control_name="MuteVoice"
+     enabled_control="EnableVoiceChat"
      disabled_control="MuteAudio"
      follows="top|right"
-     height="16"
-     image_selected="icn_speaker-muted_dark.tga"
-     image_unselected="icn_speaker_dark.tga"
+     height="18"
+     image_selected="parcel_drk_VoiceNo"
+     image_unselected="parcel_drk_Voice"
      is_toggle="true"
      layout="topleft"
-     left_pad="30"
+     left_pad="16"
      name="mute_voice"
      picture_style="true"
      tab_stop="false"
-     top_delta="-1"
-     width="25" />
+     top_delta="-2"
+     width="22" />
     <text
      type="string"
      length="1"
      follows="left|top"
-     height="16"
+     height="13"
      layout="topleft"
-     left="30"
+     left="170"
      name="Listen from"
-     top_pad="5"
-     width="100">
+     width="200">
         Listen from:
     </text>
-    <radio_group
-	 enabled_control="EnableVoiceChat"
-	 control_name="VoiceEarLocation"
+    <icon
+	 follows="left"
+	 height="18"
+	 image_name="CameraView_Off"
+	 name="camera_icon"
+	 mouse_opaque="false"
+	 visible="true"
+	 width="18" />
+	<icon
+	 follows="left"
+	 height="18"
+	 image_name="Move_Walk_Off"
+	 name="avatar_icon"
+	 mouse_opaque="false"
+	 visible="true"
+	 width="18" />
+   <radio_group
+     enabled_control="EnableVoiceChat"
+     control_name="VoiceEarLocation"
      draw_border="false"
-     height="40"
-     layout="topleft"
-     left_delta="50"
-     name="ear_location"
-     top_pad="0"
-     width="364">
+	 follows="left"
+     left_delta="20"
+	 top = "210"
+	 width="221"
+	 height="38"
+     name="ear_location">
         <radio_item
          height="16"
-         label="Listen from camera position"
-         layout="topleft"
-         left="3"
+         label="Camera position"
+         left_pad="1"
+		 follows="topleft"
          name="0"
-         top="3"
-         width="315" />
+         top_delta="-30"
+         width="200" />
         <radio_item
          height="16"
-         label="Listen from avatar position"
-         layout="topleft"
+		 follows="topleft"
+         label="Avatar position"
          left_delta="0"
          name="1"
-         top_delta="16"
-         width="315" />
+         top_delta="19"
+         width="200" />
     </radio_group>
-    <text
-     type="string"
-     length="1"
-     follows="left|top"
-     height="16"
-     layout="topleft"
-     left="30"
-     name="Sound out/in"
-     top_pad="2"
-     width="100">
-        Sound out/in:
-    </text>
     <button
      control_name="ShowDeviceSettings"
-     follows="left|top"
-     height="20"
+     follows="left|bottom"
+     height="19"
      is_toggle="true"
-     label="Device settings"
+     label="Input / Output  Devices"
      layout="topleft"
-     left_delta="55"
+     left="165"
+     top_pad="12"
      name="device_settings_btn"
-     top_pad="0"
-     width="155" />
+     width="190" />
     <panel
+    background_visible="true"
+     bg_alpha_color="DkGray"
      visiblity_control="ShowDeviceSettings"
      border="false"
-	 follows="top|left"
-     height="260"
+     follows="top|left"
+     height="145"
      label="DeviceSettings"
      layout="topleft"
      left="0"
      name="Device Settings"
-     top_pad="5"
-     width="485">
+     width="501">
+      <icon
+             height="18"
+             image_name="Microphone_On"
+             left="80"
+             name="microphone_icon"
+             mouse_opaque="false"
+             top="7"
+             visible="true"
+             width="18" />
     <text
      type="string"
      length="1"
+      font.style="BOLD"
      follows="left|top"
      height="16"
      layout="topleft"
-     left="30"
-     name="Input device (microphone):"
-     top_pad="0"
+     left_pad="3"
+     name="Input"
      width="200">
-        Input device (microphone):
+        Input
     </text>
     <combo_box
-     height="18"
+     height="19"
      layout="topleft"
-     left_delta="55"
+     left="165"
      max_chars="128"
      name="voice_input_device"
-     top_pad="2"
-     width="225" />
-    <text
-     type="string"
-     length="1"
-     follows="left|top"
-     height="16"
-     layout="topleft"
-     left="30"
-     name="Output device (speakers):"
-     top_pad="5"
-     width="200">
-        Output device (speakers):
-    </text>
-    <combo_box
-     height="18"
-     layout="topleft"
-     left_delta="55"
-     max_chars="128"
-     name="voice_output_device"
-     top_pad="2"
-     width="225" />
-    <text
+     top_pad="0"
+     width="200" />
+   <text
      type="string"
      length="1"
      follows="left|top"
      height="16"
      layout="topleft"
-     left="30"
-     name="Input level:"
+     left="165"
+     name="My volume label"
      top_pad="10"
      width="200">
-        Input level
+        My volume:
     </text>
-    <slider_bar
+      <slider
      follows="left|top"
      height="17"
      increment="0.05"
      initial_value="1.0"
      layout="topleft"
-     left_delta="125"
+     left="160"
      max_val="2"
      name="mic_volume_slider"
      tool_tip="Change the volume using this slider"
-     top_delta="-1"
-     width="175" />
+     top_pad="0"
+     width="220" />
     <text
      type="string"
+     text_color="EmphasisColor"
      length="1"
      follows="left|top"
-     height="20"
+     height="18"
      layout="topleft"
      left_pad="5"
      name="wait_text"
-     top_delta="1"
-     width="200">
+     top_delta="0"
+     width="110">
         Please wait
     </text>
     <locate
@@ -446,16 +460,57 @@
      name="bar4"
      top_delta="0"
      width="20" />
-    <text
+  <!--  <text
      type="string"
-     height="40"
+     height="37"
      left="30"
      name="voice_intro_text1"
      top_pad="-4"
-     width="480"
+     width="410"
      word_wrap="true">
-        Adjust the slider to control how loud you sound to other Residents. To test the input level, simply speak into your microphone.
+        Adjust the slider to control how loud you sound to other people. To test your volume, simply speak into your microphone
+    </text>-->
+          <icon
+             height="18"
+             image_name="parcel_lght_Voice"
+             left="80"
+             name="speaker_icon"
+             mouse_opaque="false"
+             top_pad="-8"
+             visible="true"
+             width="22" />
+    <text
+    font.style="BOLD"
+     type="string"
+     length="1"
+     follows="left|top"
+     height="15"
+     layout="topleft"
+     left_pad="0"
+     name="Output"
+     width="200">
+        Output
     </text>
+    <combo_box
+     height="19"
+     layout="topleft"
+     left="165"
+     max_chars="128"
+     name="voice_output_device"
+     top_pad="0"
+     width="200" />
+    </panel>
+          <!-- Until new panel is hooked up to code, we need to be able to get to
+    the old window to change input devices. James -->
+  <button
+    follows="left|bottom"
+    label="Old"
+    name="legacy_device_window_btn"
+    height="16"
+    left="20"
+    top="-270"
+    width="40"
+    commit_callback.function="Floater.Show"
+    commit_callback.parameter="pref_voicedevicesettings"
+    />
     </panel>
-    
-</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b21fbc1795fe05e2dd8b1989f97745668e9b4b7c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -0,0 +1,594 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+	follows="left|right|top|bottom"
+	name="MediaControls"
+	bg_alpha_color="1 1 1 0"
+	height="160"
+	layout="topleft"
+	mouse_opaque="false"
+	width="800">
+  <panel
+	  name="media_region"
+	  bottom="125"
+	  follows="left|right|top|bottom"
+	  layout="topleft"
+	  left="20"
+	  mouse_opaque="false"
+	  right="-20"
+	  top="20" />
+  <layout_stack
+	  follows="left|right|bottom"
+	  height="32"
+	  layout="topleft"
+	  animate="false"
+	  left="0"
+	  orientation="horizontal"
+	  top="96">
+	<!-- outer layout_panels center the inner one -->
+	<layout_panel
+		width="0"
+		layout="topleft"
+		user_resize="false" />
+	<panel
+		name="media_progress_indicator"
+		height="22"
+		layout="topleft"
+		left="0"
+		top="0"
+		auto_resize="false"
+		user_resize="false"
+		min_width="100"
+		width="200">
+	  <progress_bar
+		  name="media_progress_bar"
+		  color_bar="1 1 1 0.96"
+		  follows="left|right|top"
+		  height="16"
+		  layout="topleft"
+		  left="0"
+		  tool_tip="Media is Loading"/>
+	</panel>
+	<layout_panel
+		width="0"
+		layout="topleft"
+		user_resize="false" />
+  </layout_stack>
+  <layout_stack
+	  name="media_controls"
+	  follows="left|right"
+	  animate="false"
+	  height="32"
+	  layout="topleft"
+	  left="0"
+	  orientation="horizontal"
+	  top="128">
+	<!-- outer layout_panels center the inner one -->
+	<layout_panel
+		width="0"
+		layout="topleft"
+		user_resize="false" />
+	<layout_panel
+		name="back"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="22"
+		width="22"
+		top="4">
+	  <button
+		  auto_resize="false"
+		  height="22"
+		  image_selected="media_btn_back.png"
+		  image_unselected="media_btn_back.png"
+		  layout="topleft"
+		  tool_tip="Step back"
+		  picture_style="true"
+		  width="22"
+		  top_delta="4">
+		<button.commit_callback
+			function="MediaCtrl.Back" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="fwd"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="10"
+		min_width="17"
+		width="17">
+	  <button
+		  height="22"
+		  image_selected="media_btn_forward.png"
+		  image_unselected="media_btn_forward.png"
+		  layout="topleft"
+		  tool_tip="Step forward"
+		  picture_style="true"
+		  top_delta="0"
+		  min_width="17"
+		  width="17">
+		<button.commit_callback
+			function="MediaCtrl.Forward" />
+	  </button>
+	</layout_panel>
+<!--
+	<panel
+		height="22"
+		layout="topleft"
+		auto_resize="false"
+		min_width="3"
+		width="3">
+	  <icon
+		  height="22"
+		  image_name="media_panel_divider.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="3"
+		  width="3" />
+	</panel>
+-->
+	<layout_panel
+		name="home"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="-2"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_home.png"
+		  image_unselected="media_btn_home.png"
+		  layout="topleft"
+		  tool_tip="Home page"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Home" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="media_stop"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="2"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="button_anim_stop.tga"
+		  image_unselected="button_anim_stop.tga"
+		  layout="topleft"
+		  tool_tip="Stop media"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Stop" />
+	  </button>
+	</layout_panel>
+<!--
+	<panel
+		height="22"
+		layout="topleft"
+		auto_resize="false"
+		min_width="3"
+		width="3">
+	  <icon
+		  height="22"
+		  image_name="media_panel_divider.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="3"
+		  width="3" />
+	</panel>
+-->
+	<layout_panel
+		name="reload"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="6"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_reload.png"
+		  image_unselected="media_btn_reload.png"
+		  layout="topleft"
+		  tool_tip="Reload"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Reload" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="stop"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="10"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_stoploading.png"
+		  image_unselected="media_btn_stoploading.png"
+		  layout="topleft"
+		  picture_style="true"
+		  tool_tip = "Stop loading"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Stop" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="play"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="14"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="button_anim_play.tga"
+		  image_unselected="button_anim_play.tga"
+		  layout="topleft"
+		  tool_tip = "Play media"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Play" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="pause"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="18"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="button_anim_pause.tga"
+		  image_unselected="button_anim_pause.tga"
+		  layout="topleft"
+		  tool_tip = "Pause media"
+		  picture_style="true">
+		<button.commit_callback
+			function="MediaCtrl.Pause" />
+	  </button>
+	</layout_panel>
+	<!-- media URL entry  -->
+	<layout_panel
+		name="media_address"
+		auto_resize="true"
+		user_resize="false"
+		height="22"
+		follows="left|right|bottom"
+		layout="topleft"
+		width="190"
+		min_width="90">
+	  <!--
+		  RE-ENABLE THIS WHEN WE HAVE A HISTORY DROP-DOWN AGAIN
+
+<combo_box
+name="media_address_url"
+allow_text_entry="true"
+height="22"
+layout="topleft"
+max_chars="1024"
+tool_tip = "Media URL"
+<combo_box.commit_callback
+function="MediaCtrl.CommitURL" />
+</combo_box>
+	  -->
+	  <line_editor 
+		  name="media_address_url"
+		  follows="left|right" 
+		  height="22"
+		  top="0"
+		  tool_tip="Media URL"
+		  text_pad_right="16"> 
+		<line_editor.commit_callback
+			function="MediaCtrl.CommitURL"/>
+	  </line_editor>
+	  <layout_stack
+		  animate="false"
+		  follows="right"
+		  width="32"
+		  min_width="32"
+		  height="16"
+		  top="3"
+		  orientation="horizontal"
+		  left_pad="-38">
+		<icon
+			name="media_whitelist_flag"
+			follows="top|right"
+			height="16"
+			image_name="smicon_warn.tga"
+			layout="topleft"
+			tool_tip="White List enabled"
+			min_width="16"
+			width="16" />
+		<icon
+			name="media_secure_lock_flag"
+			height="16"
+			image_name="inv_item_eyes.tga"
+			layout="topleft"
+			tool_tip="Secured Browsing"
+			min_width="16"
+			width="16" />
+	  </layout_stack>
+	</layout_panel>
+	<layout_panel
+		name="media_play_position"
+		auto_resize="true"
+		user_resize="false"
+		follows="left|right|top|bottom"
+		layout="topleft"
+		min_width="100"
+		width="200">
+	  <slider_bar
+		  name="media_play_slider"
+		  follows="left|right|top"
+		  height="22"
+		  increment="0.05"
+		  initial_value="0.5"
+		  layout="topleft"
+		  tool_tip="Movie play progress"
+		  min_width="100"
+		  width="200">
+		<slider_bar.commit_callback
+			function="MediaCtrl.JumpProgress" />
+	  </slider_bar>
+	</layout_panel>
+	<layout_panel
+		name="media_volume"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		height="24"
+		min_width="24"
+		width="24">
+	  <button
+		  name="media_volume_button"
+		  height="22"
+		  image_selected="icn_speaker-muted_dark.tga"
+		  image_unselected="icn_speaker_dark.tga"
+		  is_toggle="true"
+		  layout="topleft"
+		  scale_image="false" 
+		  picture_style="true"
+		  tool_tip="Mute This Media"
+		  top_delta="22"
+		  min_width="24"
+		  width="24" >
+		<button.commit_callback
+			function="MediaCtrl.ToggleMute" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="volume_up"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="20"
+		height="14"
+		width="20">
+	  <button
+		  top="-3"
+		  height="14"
+		  image_selected="media_btn_scrollup.png"
+		  image_unselected="media_btn_scrollup.png"
+		  layout="topleft"
+		  tool_tip="Volume up"
+		  picture_style="true"
+		  scale_image="true"
+		  min_width="20"
+		  width="20" >
+		<button.commit_callback
+			function="MediaCtrl.CommitVolumeUp" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="volume_down"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="20"
+		height="14"
+		width="20">
+	  <button
+		  top="-5"
+		  height="14"
+		  image_selected="media_btn_scrolldown.png"
+		  image_unselected="media_btn_scrolldown.png"
+		  layout="topleft"
+		  tool_tip="Volume down"
+		  picture_style="true"
+		  scale_image="true"
+		  min_width="20"
+		  width="20">
+		<button.commit_callback
+			function="MediaCtrl.CommitVolumeDown" />
+	  </button>
+	</layout_panel>
+	<!-- Scroll pad -->
+	<layout_panel
+		name="media_panel_scroll"
+		auto_resize="false"
+		user_resize="false"
+		height="32"
+		follows="left|right|top|bottom"
+		layout="topleft"
+		min_width="32"
+		width="32">
+	  <icon
+		  height="32"
+		  image_name="media_panel_scrollbg.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="32"
+		  width="32" />
+	  <button
+		  name="scrollup"
+		  height="8"
+		  image_selected="media_btn_scrollup.png"
+		  image_unselected="media_btn_scrollup.png"
+		  layout="topleft"
+		  tool_tip="Scroll up"
+		  picture_style="true"
+		  scale_image="false"
+		  left="12"
+		  top_delta="4"
+		  min_width="8"
+		  width="8" />
+	  <button
+		  name="scrollleft"
+		  height="8"
+		  image_selected="media_btn_scrollleft.png"
+		  image_unselected="media_btn_scrollleft.png"
+		  layout="topleft"
+		  left="3"
+		  tool_tip="Scroll left"
+		  picture_style="true"
+		  scale_image="false"
+		  top="12"
+		  min_width="8"
+		  width="8" />
+	  <button
+		  name="scrollright"
+		  height="8"
+		  image_selected="media_btn_scrollright.png"
+		  image_unselected="media_btn_scrollright.png"
+		  layout="topleft"
+		  left_pad="9"
+		  tool_tip="Scroll right"
+		  picture_style="true"
+		  scale_image="false"
+		  top_delta="0"
+		  min_width="8"
+		  width="8" />
+	  <button
+		  name="scrolldown"
+		  height="8"
+		  image_selected="media_btn_scrolldown.png"
+		  image_unselected="media_btn_scrolldown.png"
+		  layout="topleft"
+		  left="12"
+		  tool_tip="Scroll down"
+		  picture_style="true"
+		  scale_image="false"
+		  top="20"
+		  min_width="8"
+		  width="8" />
+	</layout_panel>
+	<layout_panel
+		name="zoom_frame"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		height="28"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_optimalzoom.png"
+		  image_unselected="media_btn_optimalzoom.png"
+		  layout="topleft"
+		  tool_tip="Zoom"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Zoom" />
+	  </button>
+	</layout_panel>
+<!--
+	<panel
+		height="22"
+		layout="topleft"
+		auto_resize="false"
+		min_width="3"
+		width="3">
+	  <icon
+		  height="22"
+		  image_name="media_panel_divider.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="3"
+		  width="3" />
+	</panel>
+-->
+	<layout_panel
+		name="new_window"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_newwindow.png"
+		  image_unselected="media_btn_newwindow.png"
+		  layout="topleft"
+		  tool_tip = "Open URL in browser"
+		  picture_style="true"
+		  top_delta="-3"
+		  min_width="24"
+		  width="24" >
+		<button.commit_callback
+			function="MediaCtrl.Open" />
+	  </button>
+	</layout_panel>
+<!--
+	<panel
+		height="22"
+		layout="topleft"
+		auto_resize="false"
+		min_width="3"
+		width="3">
+	  <icon
+		  height="22"
+		  image_name="media_panel_divider.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="3"
+		  width="3" />
+	</panel>
+-->
+	<layout_panel
+		name="close"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="21"
+		width="21" >
+	  <button
+		  height="22"
+		  image_selected="media_btn_done.png"
+		  image_unselected="media_btn_done.png"
+		  layout="topleft"
+		  tool_tip ="Close media control"
+		  picture_style="true"
+		  top_delta="-4"
+		  width="21" >
+		<button.commit_callback
+			function="MediaCtrl.Close" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		width="0"
+		layout="topleft"
+		user_resize="false" />
+  </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
index a32be90a33c639cabbd631364764fcbddc4d78e8..5af7d7d6744164ec208c26e39f6e7970dbadda1a 100644
--- a/indra/newview/skins/default/xui/en/panel_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -53,7 +53,7 @@
          left="10"
          name="second_life_image_panel"
          top="0"
-         width="290">
+         width="280">
             <texture_picker
              allow_no_texture="true"
              default_image_name="None"
@@ -75,13 +75,15 @@
              text_color="white"
              top_delta="0"
              value="[SECOND_LIFE]:"
-             width="170" />
+             width="165" />
             <expandable_text
              follows="left|top|right"
              height="95"
              layout="topleft"
              left="107"
+             max_length="512"
              name="sl_description_edit"
+             top_pad="-3"
              width="173"
              expanded_bg_visible="true"
              expanded_bg_color="DkGray">
@@ -95,7 +97,7 @@
 	 top_pad="10"
          left="10"
          name="first_life_image_panel"
-         width="290">
+         width="280">
             <texture_picker
              allow_no_texture="true"
              default_image_name="None"
@@ -116,13 +118,15 @@
              text_color="white"
              top_delta="0"
              value="Real World:"
-             width="173" />
+             width="165" />
             <expandable_text
              follows="left|top|right"
              height="95"
              layout="topleft"
              left="107"
+             max_length="512"
              name="fl_description_edit"
+             top_pad="-3"
              width="173"
              expanded_bg_visible="true"
              expanded_bg_color="DkGray">
@@ -151,7 +155,7 @@
          name="homepage_edit"
          top_pad="0"
          value="http://librarianavengers.org"
-         width="290"
+         width="280"
          word_wrap="false"
          use_elipsis="true"
          />
@@ -205,7 +209,7 @@
          name="acc_status_text"
          top_pad="0"
          value="Resident. No payment info on file."
-         width="295"
+         width="280"
          word_wrap="true" />
         <text
          follows="left|top"
@@ -215,7 +219,7 @@
          left="10"
          name="title_partner_text"
          text_color="white"
-         top_pad="10"
+         top_pad="5"
          value="Partner:"
          width="280" />
         <panel
@@ -245,21 +249,21 @@
          left="10"
          name="title_groups_text"
          text_color="white"
-         top_pad="10"
+         top_pad="8"
          value="Groups:"
          width="280" />
-        <text
+                     <expandable_text
          follows="left|top|bottom"
-         height="160"
+         height="60"
          layout="topleft"
          left="10"
-         name="sl_groups"
-         top_pad="0"
-         width="290"
-         word_wrap="true"
-         use_elipsis="true">
+             name="sl_groups"
+       top_pad="0"
+         width="280"
+             expanded_bg_visible="true"
+             expanded_bg_color="DkGray">
             Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
-        </text>
+        </expandable_text>
       </panel>
  </scroll_container>
  <panel
@@ -270,17 +274,17 @@
      top_pad="2"
      bottom="10"
      height="19"
-     width="313">
+     width="303">
         <button
          follows="bottom|left"
          height="19"
-         label="Add"
+         label="Add Friend"
          layout="topleft"
          left="0"
          mouse_opaque="false"
          name="add_friend"
          top="5"
-         width="55" />
+         width="75" />
         <button
          follows="bottom|left"
          height="19"
@@ -289,7 +293,7 @@
          name="im"
          top="5"
          left_pad="5"
-         width="40" />
+         width="45" />
         <button
          enabled="false"
          follows="bottom|left"
@@ -299,7 +303,7 @@
          name="call"
          left_pad="5"
          top="5"
-         width="55" />
+         width="45" />
         <button
          enabled="false"
          follows="bottom|left"
@@ -309,7 +313,7 @@
          name="show_on_map_btn"
          top="5"
          left_pad="5"
-         width="50" />
+         width="45" />
         <button
          follows="bottom|left"
          height="19"
@@ -318,7 +322,7 @@
          name="teleport"
          left_pad="5"
          top="5"
-         width="90" />
+         width="80" />
  </panel>
  <panel
      follows="bottom|left"
@@ -328,7 +332,7 @@
      name="profile_me_buttons_panel"
      visible="false"
      height="19"
-     width="313">
+     width="303">
         <button
          follows="bottom|right"
          font="SansSerifSmall"
diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml
index 8a48574440a1e9fe61e425e8232aac324e01f040..195b7315313e6d9479f06dc09a0c9f933adb59cf 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml
@@ -50,10 +50,12 @@
     <tab_container
      follows="all"
      height="535"
+     halign="center"
      layout="topleft"
      left="10"
+ min_width="333"
      name="tabs"
-     tab_min_width="95"
+     tab_min_width="80"
      tab_height="30"
      tab_position="top"
      top_pad="10"
@@ -61,21 +63,21 @@
         <panel
          class="panel_profile"
          filename="panel_profile.xml"
-         label="Profile"
+         label="PROFILE"
          layout="topleft"
          help_topic="profile_profile_tab"
          name="panel_profile" />
         <panel
          class="panel_picks"
          filename="panel_picks.xml"
-         label="Picks"
+         label="PICKS"
          layout="topleft"
          help_topic="profile_picks_tab"
          name="panel_picks" />
         <panel
          class="panel_notes"
          filename="panel_notes.xml"
-         label="Notes &amp; Privacy"
+         label="NOTES &amp; PRIVACY"
          layout="topleft"
          help_topic="profile_notes_tab"
          name="panel_notes" />
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml
index 395b574425fec74cd077ad51c620ba96f7d2931f..3f64c9c633f4ff4e714e9337f6a84abd1616698d 100644
--- a/indra/newview/skins/default/xui/en/panel_side_tray.xml
+++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml
@@ -18,6 +18,7 @@
     tab_title="Home"
     description="Home."
     image="TabIcon_Open_Off"
+	image_selected="TabIcon_Close_Off"
     mouse_opaque="false"
     background_visible="true"
   >
@@ -34,6 +35,7 @@
     tab_title="People"
     description="Find your friends, contacts and people nearby."
     image="TabIcon_People_Off"
+    image_selected="TabIcon_People_Selected"
     mouse_opaque="false"
     background_visible="true"
   >
@@ -76,6 +78,7 @@
     label="Places"
     description="Find places to go and places you&apos;ve visited before."
     image="TabIcon_Places_Off"
+	image_selected="TabIcon_Places_Selected"
     mouse_opaque="false"
     background_visible="true"
   >
@@ -94,6 +97,7 @@
     tab_title="Me"
     description="Edit your public profile and Picks."
     image="TabIcon_Me_Off"
+    image_selected="TabIcon_Me_Selected"
     mouse_opaque="false"
     background_visible="true"
   >
@@ -111,6 +115,7 @@
     tab_title="Appearance"
     description="Change your appearance and current look."
     image="TabIcon_Appearance_Off"
+    image_selected="TabIcon_Appearance_Selected"
     mouse_opaque="false"
     background_visible="true"
   >
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index 795e0ffc0dc4b08d17959c95b22366781b083519..7b9c9f47a2fe1a7463139adc05e4fa71629a741d 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -41,20 +41,18 @@
     </panel.string>
     <button
      auto_resize="true"
-    halign="right"
+     halign="right"
      follows="right|bottom"
      font="SansSerifSmall"
-     image_color="White_05"
-    flash_color="EmphasisColor"
-     image_overlay="BuyArrow_Over"
-     height="18"
-     layout="topleft"
-     left="-225"
+     image_selected="BuyArrow_Over"
+     image_unselected="BuyArrow_Off"
+	image_pressed="BuyArrow_Press"
+     height="16"
+     left="-220"
      name="buycurrency"
-     pad_right="23px"
-     picture_style="true"
+     pad_right="22px"
      tool_tip="My Balance: Click to buy more L$"
-     top="0"
+     top="1"
      width="117" />
     <text
      type="string"
@@ -65,148 +63,21 @@
      height="16"
      top="3"
      layout="topleft"
-     left_pad="20"
+     left_pad="15"
      name="TimeText"
      text_color="TimeTextColor"
      tool_tip="Current time (Pacific)"
      width="80">
         12:00 AM
     </text>
-    <button
-     follows="right|bottom"
-     height="16"
-     layout="topleft"
-     left_delta="-537"
-     image_selected="Inv_DangerousScript"
-     image_unselected="Inv_DangerousScript"
-     name="scriptout"
-     picture_style="true"
-     scale_image="false"
-     tool_tip="Script warnings and errors"
-     top="0"
-     visible="false"
-     width="16" />
-    <button
-     follows="right|bottom"
-     height="16"
-     image_selected="Health"
-     image_unselected="Health"
-     layout="topleft"
-     left_pad="7"
-     name="health"
-     picture_style="true"
-     scale_image="false"
-     tool_tip="Health"
-     top="0"
-     visible="false"
-     width="16" />
-    <text
-      bg_visible="false"
-     text_readonly_color="HealthTextColor"
-     follows="rsight|bottom"
-     font_shadow="none"
-     height="16"
-     layout="topleft"
-     left_pad="18"
-     name="HealthText"
-     text_color="HealthTextColor"
-     tool_tip="Health"
-     top="0"
-     visible="false"
-     width="31">
-        100%
-    </text>
-    <button
-     follows="right|bottom"
-     height="16"
-     image_selected="Move_Fly_Disabled"
-     image_unselected="Move_Fly_Disabled"
-     layout="topleft"
-     left_pad="7"
-     name="no_fly"
-     picture_style="true"
-     scale_image="false"
-     tool_tip="Flying not allowed"
-     top="3"
-     visible="false"
-     width="16" />
-    <button
-     follows="right|bottom"
-     height="16"
-     image_selected="Tool_Create"
-     image_unselected="Tool_Create"
-     layout="topleft"
-     left_pad="7"
-     name="no_build"
-     picture_style="true"
-     scale_image="false"
-     tool_tip="Building/rezzing not allowed"
-     top="0"
-     visible="false"
-     width="16" />
-    <button
-     follows="right|bottom"
-     height="16"
-     image_selected="Inv_Script"
-     image_unselected="Inv_Script"
-     layout="topleft"
-     left_pad="7"
-     name="no_scripts"
-     picture_style="true"
-     scale_image="false"
-     tool_tip="Scripts not allowed"
-     top="0"
-     visible="false"
-     width="16" />
-    <button
-     follows="right|bottom"
-     height="16"
-     image_selected="Inv_Gesture"
-     image_unselected="Inv_Gesture"
-     layout="topleft"
-     left_pad="7"
-     name="restrictpush"
-     picture_style="true"
-     scale_image="false"
-     tool_tip="No pushing"
-     top="0"
-     visible="false"
-     width="16" />
-    <button
-     follows="right|bottom"
-     height="18"
-     image_selected="Microphone_Mute"
-     image_unselected="Microphone_Mute"
-     layout="topleft"
-     left_pad="7"
-     name="status_no_voice"
-     picture_style="true"
-     scale_image="false"
-     tool_tip="Voice not available here"
-     top="1"
-     visible="false"
-     width="16" />
-    <button
-     follows="right|bottom"
-     height="16"
-     image_selected="Icon_For_Sale"
-     image_unselected="Icon_For_Sale"
-     layout="topleft"
-     left_pad="7"
-     name="buyland"
-     picture_style="true"
-     tool_tip="Buy this parcel"
-     top="0"
-     visible="false"
-     width="16" />
     <text
      enabled="true"
      follows="right|bottom"
      halign="center"
      height="12"
      layout="topleft"
-     left_delta="-4"
+     left_delta="0"
      name="stat_btn"
-     top_delta="3"
-     width="20" />
+     top_delta="0"
+     width="20"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
index 53ee0d159d5d022605c5fa9938f8048a5987c07b..7722583ce21c59630836e11e5304f7dc928e3542 100644
--- a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
@@ -1,65 +1,40 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <!-- All our XML is utf-8 encoded. -->
-
 <panel
-	name="sys_well_item"
-	title="sys_well_item"
+  name="sys_well_item"
+  title="sys_well_item"
   visible="true"
-  top="0" 
-  left="0" 
-	width="318"
-	height="35"
+  top="0"
+  left="0"
+  width="300"
+  height="35"
   layout="topleft"
-  follows="left|right"
-  background_opaque="false"
-  background_visible="true"
-  bg_alpha_color="0.0 0.0 0.0 0.0" >
-
-  <icon
-    top="8"
-    left="8"
-    width="20"
-    height="20"
-    layout="topleft"
-    follows="left"
-    name="icon"
-    label=""
-    mouse_opaque="false"
-    image_name="lag_status_warning.tga" 
-    />
-
+  follows="left|right">
   <text
-    top="2" 
-    left_pad="8" 
-    width="255" 
-    height="28" 
+    top="2"
+    left="10"
+    width="267"
+    height="28"
     layout="topleft"
     follows="right|left"
-    font="SansSerifBold" 
     text_color="white"
-    use_ellipses="true" 
+    use_ellipses="true"
     word_wrap="true"
     mouse_opaque="false"
     name="title" >
-    Select your streaming media preference. Select your streaming media preference.
-  </text>  
-  
+    Beware the trout. BEWARE! THE! TROUT!
+  </text>
   <button
-    top="5" 
-    left_pad="5" 
-    width="15" 
-    height="15" 
+    top="5"
+    right="-5"
+    width="17"
+    height="17"
     layout="topleft"
     follows="right"
-    name="close_btn" 
+    name="close_btn"
     mouse_opaque="true"
-    label=""
     tab_stop="false"
-    image_unselected="toast_hide_btn.tga" 
-    image_disabled="toast_hide_btn.tga"
-    image_selected="toast_hide_btn.tga" 
-    image_hover_selected="toast_hide_btn.tga"
-    image_disabled_selected="toast_hide_btn.tga" 
+    image_unselected="Icon_Close_Toast"
+    image_selected="Icon_Close_Toast"
   />
-
-</panel> 
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
index 63c2d4538e5dfdb3e6c57d562d198404ebf086e3..f559343b34a6d2c4c2571dc9719a6dec93fc4595 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
@@ -18,7 +18,7 @@
      visible="false"
      width="380" />
     <icon
-     height="20"
+     height="24"
      follows="top|right|left"
      image_name="ListItem_Select"
      layout="topleft"
@@ -26,17 +26,16 @@
      name="selected_icon"
      top="0"
      visible="false"
-     width="380" />
+     width="320" />
     <icon
-     height="20"
-     follows="top|right|left"
-     image_name="ListItem_Select"
+     height="16"
+     follows="top|left"
+     image_name="Inv_Landmark"
      layout="topleft"
      left="0"
      name="landmark_icon"
      top="0"
-     visible="false"
-     width="20" />
+     width="16" />
     <text
      follows="left|right"
      height="20"
@@ -46,21 +45,28 @@
      name="region"
      text_color="white"
      top="4"
-     value="Unknown"
-     width="330" />
+     value="..."
+     width="242" />
     <button
      follows="right"
-     height="18"
-     image_disabled="Info"
-     image_disabled_selected="Info"
-     image_hover_selected="Info"
-     image_selected="Info"
-     image_unselected="Info"
-     layout="topleft"
+     height="16"
+     image_pressed="Info_Press"
+     image_unselected="Info_Over"
+     left_pad="3"
+     right="-31"
      name="info_btn"
      picture_style="true"
-     visible="false"
-     right="-5"
-     top="2" 
-     width="18" />
+     top_delta="-2"
+     width="16" />
+    <button
+     follows="right"
+     height="20"
+     image_overlay="ForwardArrow_Off"
+     layout="topleft"
+     left_pad="5"
+     right="-3"
+     name="profile_btn"
+     picture_style="true"
+     top_delta="-2"
+     width="20" />
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml
index 2e500fc2aa8c30b6134427eeec593245fd5adb89..7f7777586c21459c5de986ac9844f8297c7101c5 100644
--- a/indra/newview/skins/default/xui/en/panel_toast.xml
+++ b/indra/newview/skins/default/xui/en/panel_toast.xml
@@ -1,70 +1,75 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <!-- All our XML is utf-8 encoded. -->
 
+<!-- All this does is establish the position of the "close" button on the toast. -->
+
 <floater
+ legacy_header_height="18"
 	name="toast"
 	title=""
   visible="false"
   layout="topleft"
-	width="350"
-	height="40"
-  left="100"
-  top="500"
-  follows="right|bottom" 
-  bevel_style="in"
+	width="305"
+  left="0"
+  top="0"
+  follows="right|bottom"
+  bg_opaque_image="Toast_Background"
+  bg_alpha_image="Toast_Background"
   can_minimize="false"
   can_tear_off="false"
   can_resize="false"
   can_drag_on_left="false"
   can_close="false"
-  can_dock="false"  
+  can_dock="false"
+  border_visible = "false"
+  border_drop_shadow_visible = "false"
+  drop_shadow_visible = "false"
+  border = "false"
   >
 
+  <!--
   <text
    visible="false"
    follows="left|top|right|bottom"
    font="SansSerifBold"
-   height="28"
+   height="40"
    layout="topleft"
    left="60"
    name="toast_text"
    word_wrap="true"
    text_color="white"
-   top="10"
+   top="20"
    width="290">
     Toast text;
   </text>
   <icon
-    top="4" 
-    left="10" 
-    width="32" 
+    top="20"
+    left="10"
+    width="32"
     height="32"
     follows="top|left"
     layout="topleft"
     visible="false"
-    color="1 1 1 1" 
-    enabled="true" 
+    color="1 1 1 1"
+    enabled="true"
     image_name="notify_tip_icon.tga"
-    mouse_opaque="true" 
+    mouse_opaque="true"
     name="icon"
-  />
+  />-->
   <button
     layout="topleft"
-    top="-5" 
-    left="335" 
-    width="20" 
-    height="20" 
+    top="-6"
+    left="293"
+    width="17"
+    height="17"
     follows="top|right"
-    visible="false" 
-    enabled="true" 
-    mouse_opaque="true" 
-    name="hide_btn" 
-    label="" 
+    visible="false"
+    enabled="true"
+    mouse_opaque="false"
+    name="hide_btn"
+    label=""
     tab_stop="false"
-    image_unselected="toast_hide_btn.tga" 
-    image_disabled="toast_hide_btn.tga"
-    image_selected="toast_hide_btn.tga" 
-    image_hover_selected="toast_hide_btn.tga"
-    image_disabled_selected="toast_hide_btn.tga"
+    image_unselected="Toast_CloseBtn"
+    image_selected="Toast_CloseBtn"
   />
-</floater> 
+</floater>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 36f4fb98ed1ef34c941fef7757c0995354186ad0..a1f8a9a08d5f7c4d7bdef22d4118eb909b8ac0fd 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -61,9 +61,7 @@
 	<string name="TooltipFlagGroupScripts">Group Scripts</string>
 	<string name="TooltipFlagNoScripts">No Scripts</string>
 	<string name="TooltipLand">Land:</string>
-	<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>	
-	<string name="TooltipAltLeft">Alt+&#8592; for previous tab</string>	
-	<string name="TooltipAltRight">Alt+&#8594; for next tab</string>	
+	<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
 
 	<!-- tooltips for Urls -->
 	<string name="TooltipHttpUrl">Click to view this web page</string>
@@ -76,6 +74,7 @@
 	<string name="TooltipTeleportUrl">Click to teleport to this location</string>
 	<string name="TooltipObjectIMUrl">Click to view this object's description</string>
 	<string name="TooltipSLAPP">Click to run the secondlife:// command</string>
+	<string name="CurrentURL" value=" CurrentURL: [CurrentURL]" />
 	
 	<!-- ButtonToolTips, llfloater.cpp -->
 	<string name="BUTTON_CLOSE_DARWIN">Close (&#8984;W)</string>
@@ -264,10 +263,6 @@
 	<string name="TrackYourCamera">Track your camera</string>
 	<string name="ControlYourCamera">Control your camera</string>
 
-	<!-- IM -->
-	<string name="IM_logging_string">-- Instant message logging enabled --</string>
-	<string name="Unnamed">(Unnamed)</string>
-	
 	<!-- Sim Access labels -->
 	<string name="SIM_ACCESS_PG">PG</string>
 	<string name="SIM_ACCESS_MATURE">Mature</string>
@@ -642,7 +637,7 @@ Sets the script timer to zero
 float llGetAndResetTime()
 Returns the script time in seconds and then resets the script timer to zero
 	</string>
-	<string name="LSLTipText_llSound" translate="false">
+	<string name="LSLTipText_llSoplayund" translate="false">
 llSound(string sound, float volume, integer queue, integer loop)
 Plays sound at volume and whether it should loop or not
 	</string>
@@ -1819,6 +1814,7 @@ this texture in your inventory
 	<string name="broken_link" value=" (broken_link)" />
 	<string name="LoadingContents">Loading contents...</string>
 	<string name="NoContents">No contents</string>
+	<string name="WornOnAttachmentPoint" value=" (worn on [ATTACHMENT_POINT])" />
 
 	<!-- Gestures labels -->
     <!-- use value="" because they have preceding spaces -->
@@ -2193,6 +2189,7 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
 
 	<!-- media -->
 	<string name="Multiple Media">Multiple Media</string>
+	<string name="Play Media">Play/Pause Media</string>
 	
 	<!-- OSMessageBox messages -->
 	<string name="MBCmdLineError">
@@ -2883,7 +2880,14 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 	  Failed to start viewer
 	</string>
 
-  <!-- IM system messages -->
+	<!-- IM system messages -->
+	<string name="IM_logging_string">-- Instant message logging enabled --</string>
+	<string name="IM_typing_start_string">[NAME] is typing...</string>
+	<string name="Unnamed">(Unnamed)</string>
+	<string name="IM_moderated_chat_label">(Moderated: Voices off by default)</string>
+	<string name="IM_unavailable_text_label">Text chat is not available for this call.</string>
+
+
   <string name="ringing-im">
     Joining Voice Chat...
   </string>
diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
index 3ff0b3062aaf2ec54f0b040e4de05d8c4d95c10f..fcfe89c6530852c9a9f47babc3e233230d2a3135 100644
--- a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
+++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
@@ -1,12 +1,13 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <accordion_tab
-    header_bg_color="0.68 0.68 0.68 1"
-    header_txt_color="0.68 0.68 0.68 1"
+    header_bg_color="DkGray2"
+    header_txt_color="LtGray"
     header_collapse_img="Accordion_ArrowClosed_Off"
     header_collapse_img_pressed="Accordion_ArrowClosed_Press"
     header_expand_img="Accordion_ArrowOpened_Off"
     header_expand_img_pressed="Accordion_ArrowOpened_Press"
-    header_image="Accordion_Off.png"
+    header_image="Accordion_Off"
     header_image_over="Accordion_Over"
     header_image_pressed="Accordion_Press"
+    header_image_selected="Accordion_Selected"
     />
diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
index b72d59524e0304fbf467498ffc46f7df096ce8cd..ea6997ebd54940039a796a39d678b28e221d5cf0 100644
--- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml
+++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
@@ -4,8 +4,8 @@
     message_separator="panel_chat_separator.xml"
     left_text_pad="10"
 	right_text_pad="15"
-    left_widget_pad="5"
-	rigth_widget_pad="10"
+    left_widget_pad="0"
+	right_widget_pad="10"
 	max_length="2147483647"
 	enabled="false"
 	track_bottom="true"
diff --git a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
index 319beac291ee3491fe29af03bc6a4292ceedbb5b..f59c46b2f5c6a0e963ef8654d858face13c41684 100644
--- a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
+++ b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
@@ -3,7 +3,7 @@
  max_height="300" >
  <textbox
    more_label="More" 
-  follows="left|top"
+  follows="left|top|right"
   name="text"
    allow_scroll="true" 
   use_ellipses="true"
diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml
index 4a866c2eb21fcf5c3807827dcbaf7629c69442c1..6660fbf1a823e79cf59b175a133cc688c67e2482 100644
--- a/indra/newview/skins/default/xui/en/widgets/floater.xml
+++ b/indra/newview/skins/default/xui/en/widgets/floater.xml
@@ -1,6 +1,10 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- See also settings.xml UIFloater* settings for configuration -->
 <floater name="floater"
          bg_opaque_color="FloaterFocusBackgroundColor"
          bg_alpha_color="FloaterDefaultBackgroundColor"
+         bg_opaque_image="Window_Foreground" 
+         bg_alpha_image="Window_Background" 
          background_visible="true"
-         background_opaque="false"/>
+         background_opaque="false"
+         header_height="25" />
diff --git a/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml b/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
index 89e442baec8ebccd71a8bc65746115b3ec7593d4..ab4ad940893a8819ad6e0f585ee0a29ecfd1f2d9 100644
--- a/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
+++ b/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
@@ -23,7 +23,8 @@
                               image_selected="DropDown_Selected"
                               image_disabled="DropDown_Disabled"
                               image_disabled_selected="DropDown_Disabled_Selected" />
-  <gesture_combo_box.combo_list bg_writeable_color="MenuDefaultBgColor" />
+  <gesture_combo_box.combo_list bg_writeable_color="MenuDefaultBgColor"
+                                scroll_bar_bg_visible="true" />
   <gesture_combo_box.combo_editor name="Combo Text Entry"
                           select_on_focus="true"
                           font="SansSerifSmall" />
diff --git a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
index 505c7ba9364d3f6020cf0074cf4fb8099ab8c2c6..98b3e2faaada9f6dbd9e6a97734a19d1f786de4f 100644
--- a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <output_monitor
-  image_mute="mute_icon.tga"
+  image_mute="parcel_lght_VoiceNo"
   image_off="VoicePTT_Off"
   image_on="VoicePTT_On"
   image_level_1="VoicePTT_Lvl1"
diff --git a/indra/newview/skins/default/xui/en/widgets/panel.xml b/indra/newview/skins/default/xui/en/widgets/panel.xml
index b81a70b845840491322163b5c09dac95808deb9a..7262c0dc5c54c7dbf40fb8596a42ebf2cf7e0cca 100644
--- a/indra/newview/skins/default/xui/en/widgets/panel.xml
+++ b/indra/newview/skins/default/xui/en/widgets/panel.xml
@@ -1,5 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Optional parameters:
+  border - show border around panel
+  bg_opaque_image - image name for "in-front" panel look
+  bg_alpha_image - image name for "in-back" or transparent panel look
+-->
 <panel bg_opaque_color="PanelFocusBackgroundColor"
        bg_alpha_color="PanelDefaultBackgroundColor"
        background_visible="false"
-       background_opaque="false"/>
\ No newline at end of file
+       background_opaque="false"
+       chrome="false"/>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/split_button.xml b/indra/newview/skins/default/xui/en/widgets/split_button.xml
index c0d3c6d7f6f58cc5347a78a3eea3ae982a1c7911..2ff9ada90a7ed7e61f8b10940610858c4dc9f045 100644
--- a/indra/newview/skins/default/xui/en/widgets/split_button.xml
+++ b/indra/newview/skins/default/xui/en/widgets/split_button.xml
@@ -1,24 +1,25 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<split_button 
+<split_button
  font="SansSerifSmall"
  arrow_position="left"
  follows="right|top">
-    <split_button.arrow_button 
-     name="Arrow Button"
-     label=""
-     font="SansSerifSmall"
-     scale_image="true"
-     image_selected="camera_presets/camera_presets_arrow.png"
-     image_unselected="camera_presets/camera_presets_arrow.png"
-     image_disabled_selected="camera_presets/camera_presets_arrow.png" 
-     image_disabled="camera_presets/camera_presets_arrow.png"
-     width="10"/>
     <split_button.items_panel
      background_visible="true"
      border="true"
      bg_alpha_color="1 1 1 1"
      bg_opaq_color="1 1 1 1"
+     scale_image="false"
+     image_selected="SegmentedBtn_Left_Selected"
+     image_unselected="SegmentedBtn_Left_Off"
      layout="topleft"
      name="item_buttons"
     />
+    <split_button.arrow_button
+     name="Arrow Button"
+     label=""
+     font="SansSerifSmall"
+     scale_image="false"
+     image_selected="SegmentedBtn_Right_Selected"
+     image_unselected="SegmentedBtn_Right_Off"
+     />
 </split_button>
diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
index 2fe5f517a2359240686231248ce45d9752b8f735..fe2f1423b74a284c8a0c7adc507d30ff840a76ad 100644
--- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml
+++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <tab_container tab_min_width="60"
                tab_max_width="150"
-               tab_height="16">
+               font_halign="center"
+               tab_height="21">
   <first_tab tab_top_image_unselected="TabTop_Left_Off"
                tab_top_image_selected="TabTop_Left_Selected"
                tab_bottom_image_unselected="Toolbar_Left_Off"
diff --git a/indra/newview/skins/default/xui/en/widgets/tool_tip.xml b/indra/newview/skins/default/xui/en/widgets/tool_tip.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6b49f832fd75272b4e872116aecf6985c0fa393e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/tool_tip.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- See also settings.xml UIFloater* settings for configuration -->
+<tool_tip name="tooltip"
+          max_width="200"
+          padding="4"
+          wrap="true"
+          font="SansSerif"
+          bg_opaque_color="ToolTipBgColor"
+          background_visible="true"
+ />
diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp
index 42872d85fba7a6d403d54cff380bfc7ba682bb35..e08193f78562e0ffe75d26facee76ccda7acd39b 100644
--- a/indra/newview/tests/llagentaccess_test.cpp
+++ b/indra/newview/tests/llagentaccess_test.cpp
@@ -29,6 +29,8 @@
  * COMPLETENESS OR PERFORMANCE.
  * $/LicenseInfo$
  */
+
+#include "linden_common.h"
 #include "../test/lltut.h"
 
 #include "../llagentaccess.h"
diff --git a/indra/newview/tests/llcapabilitylistener_test.cpp b/indra/newview/tests/llcapabilitylistener_test.cpp
index bd6ae90fabb595f350432b29c097aa01e44e7136..4759c7dc912189b401ebcf9217eb3ce971de2aef 100644
--- a/indra/newview/tests/llcapabilitylistener_test.cpp
+++ b/indra/newview/tests/llcapabilitylistener_test.cpp
@@ -47,9 +47,9 @@
 #include "../test/lltut.h"
 #include "../llcapabilityprovider.h"
 #include "lluuid.h"
-#include "llerrorcontrol.h"
 #include "tests/networkio.h"
 #include "tests/commtest.h"
+#include "tests/wrapllerrs.h"
 #include "stringize.h"
 
 #if defined(LL_WINDOWS)
@@ -127,28 +127,6 @@ namespace tut
     typedef llcapears_group::object llcapears_object;
     llcapears_group llsdmgr("llcapabilitylistener");
 
-    struct CaptureError: public LLError::OverrideFatalFunction
-    {
-        CaptureError():
-            LLError::OverrideFatalFunction(boost::bind(&CaptureError::operator(), this, _1))
-        {
-            LLError::setPrintLocation(false);
-        }
-
-        struct FatalException: public std::runtime_error
-        {
-            FatalException(const std::string& what): std::runtime_error(what) {}
-        };
-
-        void operator()(const std::string& message)
-        {
-            error = message;
-            throw FatalException(message);
-        }
-
-        std::string error;
-    };
-
     template<> template<>
     void llcapears_object::test<1>()
     {
@@ -160,10 +138,10 @@ namespace tut
         std::string threw;
         try
         {
-            CaptureError capture;
+            WrapLL_ERRS capture;
             regionPump.post(request);
         }
-        catch (const CaptureError::FatalException& e)
+        catch (const WrapLL_ERRS::FatalException& e)
         {
             threw = e.what();
         }
@@ -207,10 +185,10 @@ namespace tut
         std::string threw;
         try
         {
-            CaptureError capture;
+            WrapLL_ERRS capture;
             regionPump.post(request);
         }
-        catch (const CaptureError::FatalException& e)
+        catch (const WrapLL_ERRS::FatalException& e)
         {
             threw = e.what();
         }
@@ -269,10 +247,10 @@ namespace tut
         std::string threw;
         try
         {
-            CaptureError capture;
+            WrapLL_ERRS capture;
             regionPump.post(request);
         }
-        catch (const CaptureError::FatalException& e)
+        catch (const WrapLL_ERRS::FatalException& e)
         {
             threw = e.what();
         }
diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp
index 30e39a3bcf4b60ff0d89b01b0d9ae241809c6362..ed753b6ff7a2788f11a4c1f69fef47ac40e57127 100644
--- a/indra/newview/tests/lldateutil_test.cpp
+++ b/indra/newview/tests/lldateutil_test.cpp
@@ -28,6 +28,9 @@
  * COMPLETENESS OR PERFORMANCE.
  * $/LicenseInfo$
  */
+
+#include "linden_common.h"
+
 #include "../test/lltut.h"
 
 #include "../lldateutil.h"
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..009be35f641390be0b032aaee9355d0c85694733
--- /dev/null
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -0,0 +1,423 @@
+/**
+ * @file   lllogininstance_test.cpp
+ * @brief  Test for lllogininstance.cpp.
+ * 
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+// Own header
+#include "../lllogininstance.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "../test/lltut.h"
+#include "llevents.h"
+
+#if defined(LL_WINDOWS)
+#pragma warning(disable: 4355)      // using 'this' in base-class ctor initializer expr
+#endif
+
+// Constants
+const std::string VIEWERLOGIN_URI("viewerlogin_uri");
+const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid");
+
+const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno");
+
+// Link seams.
+
+//-----------------------------------------------------------------------------
+static LLEventStream gTestPump("test_pump");
+
+#include "lllogin.h"
+static std::string gLoginURI;
+static LLSD gLoginCreds;
+static bool gDisconnectCalled = false;
+class LLLogin::Impl
+{
+};
+LLLogin::LLLogin() {}
+LLLogin::~LLLogin() {}
+LLEventPump& LLLogin::getEventPump() { return gTestPump; }
+void LLLogin::connect(const std::string& uri, const LLSD& credentials) 
+{
+	gLoginURI = uri;
+	gLoginCreds = credentials;
+}
+
+void LLLogin::disconnect() 
+{
+	gDisconnectCalled = true;
+}
+
+//-----------------------------------------------------------------------------
+#include "../llviewernetwork.h"
+unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {'1','2','3','4','5','6'};		/* Flawfinder: ignore */
+
+LLViewerLogin::LLViewerLogin() {}
+LLViewerLogin::~LLViewerLogin() {}
+void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const 
+{
+	uris.push_back(VIEWERLOGIN_URI);
+}
+std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; }
+
+//-----------------------------------------------------------------------------
+#include "../llviewercontrol.h"
+LLControlGroup gSavedSettings("Global");
+std::string gCurrentVersion = "invalid_version";
+
+LLControlGroup::LLControlGroup(const std::string& name) :
+	LLInstanceTracker<LLControlGroup, std::string>(name){}
+LLControlGroup::~LLControlGroup() {}
+void LLControlGroup::setBOOL(const std::string& name, BOOL val) {}
+BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; }
+U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; }
+void LLControlGroup::setString(const std::string& name, const std::string& val) {}
+std::string LLControlGroup::getString(const std::string& name) { return "test_string"; }
+BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; }
+BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; }
+
+#include "lluicolortable.h"
+void LLUIColorTable::saveUserSettings(void)const {}
+
+//-----------------------------------------------------------------------------
+#include "../llurlsimstring.h"
+LLURLSimString LLURLSimString::sInstance;
+bool LLURLSimString::parse() { return true; }
+
+//-----------------------------------------------------------------------------
+#include "llnotifications.h"
+#include "llfloaterreg.h"
+static std::string gTOSType;
+static LLEventPump * gTOSReplyPump = NULL;
+
+//static
+LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus)
+{
+	gTOSType = name;
+	gTOSReplyPump = &LLEventPumps::instance().obtain(key["reply_pump"]);
+	return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// LLNotifications
+class MockNotifications : public LLNotificationsInterface
+{
+	boost::function<void (const LLSD&, const LLSD&)> mResponder;
+	int mAddedCount;
+
+public: 
+	MockNotifications() :
+		mResponder(0),
+		mAddedCount(0)
+	{
+	}
+
+	virtual ~MockNotifications() {}
+
+	/* virtual */ LLNotificationPtr add(
+					const std::string& name,
+					const LLSD& substitutions,
+					const LLSD& payload, 
+					LLNotificationFunctorRegistry::ResponseFunctor functor)
+	{
+		mResponder = functor;
+		mAddedCount++;
+		return LLNotificationPtr((LLNotification*)NULL);
+	}
+
+	void sendYesResponse()
+	{
+		LLSD notification;
+		LLSD response;
+		response = 1;
+		mResponder(notification, response);
+	}
+
+	void sendNoResponse()
+	{
+		LLSD notification;
+		LLSD response;
+		response = 2;
+		mResponder(notification, response);
+	}
+
+	void sendBogusResponse()
+	{
+		LLSD notification;
+		LLSD response;
+		response = 666;
+		mResponder(notification, response);
+	}
+
+	int addedCount() { return mAddedCount; }
+};
+
+S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response)
+{
+	return response.asInteger();
+}
+
+// misc
+std::string xml_escape_string(const std::string& in)
+{
+	return in;
+}
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct lllogininstance_data
+    {
+		lllogininstance_data() : logininstance(LLLoginInstance::getInstance())
+		{
+			// Global initialization
+			gLoginURI.clear();
+			gLoginCreds.clear();
+			gDisconnectCalled = false;
+
+			gTOSType = ""; // Set to invalid value.
+			gTOSReplyPump = 0; // clear the callback.
+
+
+			gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE);
+			gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE);
+			gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE);
+			gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE);
+			gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE);
+			gSavedSettings.declareString("VersionChannelName", "test_version_string", "", FALSE);
+			gSavedSettings.declareString("NextLoginLocation", "", "", FALSE);
+			gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE);
+
+			credentials["first"] = "testfirst";
+			credentials["last"] = "testlast";
+			credentials["passwd"] = "testpass";
+
+			logininstance->setNotificationsInterface(&notifications);
+		}
+
+		LLLoginInstance* logininstance;
+		LLSD credentials;
+		MockNotifications notifications;
+    };
+
+    typedef test_group<lllogininstance_data> lllogininstance_group;
+    typedef lllogininstance_group::object lllogininstance_object;
+    lllogininstance_group llsdmgr("lllogininstance");
+
+    template<> template<>
+    void lllogininstance_object::test<1>()
+    {
+		set_test_name("Test Simple Success And Disconnect");
+
+		// Test default connect.
+		logininstance->connect(credentials);
+
+		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
+
+		// Dummy success response.
+		LLSD response;
+		response["state"] = "online";
+		response["change"] = "connect";
+		response["progress"] = 1.0;
+		response["transfer_rate"] = 7;
+		response["data"] = "test_data";
+
+		gTestPump.post(response);
+
+		ensure("Success response", logininstance->authSuccess());
+		ensure_equals("Test Response Data", logininstance->getResponse().asString(), "test_data");
+
+		logininstance->disconnect();
+
+		ensure_equals("Called Login Module Disconnect", gDisconnectCalled, true);
+
+		response.clear();
+		response["state"] = "offline";
+		response["change"] = "disconnect";
+		response["progress"] = 0.0;
+		response["transfer_rate"] = 0;
+		response["data"] = "test_data";
+
+		gTestPump.post(response);
+
+		ensure("Disconnected", !(logininstance->authSuccess()));
+    }
+
+    template<> template<>
+    void lllogininstance_object::test<2>()
+    {
+		set_test_name("Test User TOS/Critical message Interaction");
+
+		const std::string test_uri = "testing-uri";
+
+		// Test default connect.
+		logininstance->connect(test_uri, credentials);
+
+		// connect should call LLLogin::connect to init gLoginURI and gLoginCreds.
+		ensure_equals("Default connect uri", gLoginURI, "testing-uri"); 
+		ensure_equals("Default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
+		ensure_equals("Default for read critical", gLoginCreds["params"]["read_critical"].asBoolean(), false);
+
+		// TOS failure response.
+		LLSD response;
+		response["state"] = "offline";
+		response["change"] = "fail.login";
+		response["progress"] = 0.0;
+		response["transfer_rate"] = 7;
+		response["data"]["reason"] = "tos";
+		gTestPump.post(response);
+
+		ensure_equals("TOS Dialog type", gTOSType, "message_tos");
+		ensure("TOS callback given", gTOSReplyPump != 0);
+		gTOSReplyPump->post(false); // Call callback denying TOS.
+		ensure("No TOS, failed auth", logininstance->authFailure());
+
+		// Start again.
+		logininstance->connect(test_uri, credentials);
+		gTestPump.post(response); // Fail for tos again.
+		gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos.
+		ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true);
+		ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess());
+	
+		// Fail connection, attempt connect again.
+		// The new request should have reset agree to tos to default.
+		response["data"]["reason"] = "key"; // bad creds.
+		gTestPump.post(response);
+		ensure("TOS auth failure", logininstance->authFailure());
+
+		logininstance->connect(test_uri, credentials);
+		ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
+
+		// Critical Message failure response.
+		logininstance->connect(test_uri, credentials);
+		response["data"]["reason"] = "critical"; // Change response to "critical message"
+		gTestPump.post(response);
+
+		ensure_equals("TOS Dialog type", gTOSType, "message_critical");
+		ensure("TOS callback given", gTOSReplyPump != 0);
+		gTOSReplyPump->post(true); 
+		ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true);
+		ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess());
+
+		// Fail then attempt new connection
+		response["data"]["reason"] = "key"; // bad creds.
+		gTestPump.post(response);
+		ensure("TOS auth failure", logininstance->authFailure());
+		logininstance->connect(test_uri, credentials);
+		ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false);
+	}
+
+    template<> template<>
+    void lllogininstance_object::test<3>()
+    {
+		set_test_name("Test Mandatory Update User Accepts");
+
+		// Part 1 - Mandatory Update, with User accepts response.
+		// Test connect with update needed.
+		logininstance->connect(credentials);
+
+		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
+
+		// Update needed failure response.
+		LLSD response;
+		response["state"] = "offline";
+		response["change"] = "fail.login";
+		response["progress"] = 0.0;
+		response["transfer_rate"] = 7;
+		response["data"]["reason"] = "update";
+		gTestPump.post(response);
+
+		ensure_equals("Notification added", notifications.addedCount(), 1);
+
+		notifications.sendYesResponse();
+
+		ensure("Disconnected", !(logininstance->authSuccess()));
+	}
+
+	template<> template<>
+    void lllogininstance_object::test<4>()
+    {
+		set_test_name("Test Mandatory Update User Decline");
+
+		// Test connect with update needed.
+		logininstance->connect(credentials);
+
+		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
+
+		// Update needed failure response.
+		LLSD response;
+		response["state"] = "offline";
+		response["change"] = "fail.login";
+		response["progress"] = 0.0;
+		response["transfer_rate"] = 7;
+		response["data"]["reason"] = "update";
+		gTestPump.post(response);
+
+		ensure_equals("Notification added", notifications.addedCount(), 1);
+		notifications.sendNoResponse();
+
+		ensure("Disconnected", !(logininstance->authSuccess()));
+	}
+
+	template<> template<>
+    void lllogininstance_object::test<6>()
+    {
+		set_test_name("Test Optional Update User Accept");
+
+		// Part 3 - Mandatory Update, with bogus response.
+		// Test connect with update needed.
+		logininstance->connect(credentials);
+
+		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
+
+		// Update needed failure response.
+		LLSD response;
+		response["state"] = "offline";
+		response["change"] = "fail.login";
+		response["progress"] = 0.0;
+		response["transfer_rate"] = 7;
+		response["data"]["reason"] = "optional";
+		gTestPump.post(response);
+
+		ensure_equals("Notification added", notifications.addedCount(), 1);
+		notifications.sendYesResponse();
+
+		ensure("Disconnected", !(logininstance->authSuccess()));
+	}
+
+	template<> template<>
+    void lllogininstance_object::test<7>()
+    {
+		set_test_name("Test Optional Update User Denies");
+
+		// Part 3 - Mandatory Update, with bogus response.
+		// Test connect with update needed.
+		logininstance->connect(credentials);
+
+		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
+
+		// Update needed failure response.
+		LLSD response;
+		response["state"] = "offline";
+		response["change"] = "fail.login";
+		response["progress"] = 0.0;
+		response["transfer_rate"] = 7;
+		response["data"]["reason"] = "optional";
+		gTestPump.post(response);
+
+		ensure_equals("Notification added", notifications.addedCount(), 1);
+		notifications.sendNoResponse();
+
+		// User skips, should be reconnecting.
+		ensure_equals("reconnect uri", gLoginURI, VIEWERLOGIN_URI); 
+		ensure_equals("skipping optional update", gLoginCreds["params"]["skipoptional"].asBoolean(), true); 
+	}
+}
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..445ec7aa344cd13f1f1903a8ed3bf262dea9f969
--- /dev/null
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -0,0 +1,501 @@
+/** 
+ * @file llmediadataclient_test.cpp
+ * @brief LLMediaDatClient tests
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../llviewerprecompiledheaders.h"
+ 
+#include <iostream>
+#include "../test/lltut.h"
+
+#include "llsdserialize.h"
+#include "llsdutil.h"
+#include "llerrorcontrol.h"
+#include "llhttpstatuscodes.h"
+
+#include "../llmediadataclient.h"
+#include "../llvovolume.h"
+
+#include "../../llprimitive/llmediaentry.cpp"
+#include "../../llprimitive/lltextureentry.cpp"
+#include "../../llmessage/tests/llcurl_stub.cpp"
+
+#if LL_WINDOWS
+#pragma warning (push)
+#pragma warning (disable : 4702) // boost::lexical_cast generates this warning
+#endif
+#include <boost/lexical_cast.hpp>
+#if LL_WINDOWS
+#pragma warning (pop)
+#endif
+
+#define VALID_OBJECT_ID   "3607d5c4-644b-4a8a-871a-8b78471af2a2"
+#define VALID_OBJECT_ID_1 "11111111-1111-1111-1111-111111111111"
+#define VALID_OBJECT_ID_2 "22222222-2222-2222-2222-222222222222"
+#define VALID_OBJECT_ID_3 "33333333-3333-3333-3333-333333333333"
+#define VALID_OBJECT_ID_4 "44444444-4444-4444-4444-444444444444"
+
+#define FAKE_OBJECT_MEDIA_CAP_URL "foo_ObjectMedia"
+#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL "foo_ObjectMediaNavigate"
+#define FAKE_OBJECT_MEDIA_CAP_URL_503 "foo_ObjectMedia_503"
+#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR "foo_ObjectMediaNavigate_ERROR"
+
+#define MEDIA_DATA "\
+<array>														\
+<string>foo</string>										\
+<string>bar</string>										\
+<string>baz</string>										\
+</array>"
+
+#define _DATA_URLS(ID,DIST,INT,URL1,URL2) "					\
+<llsd>											\
+  <map>											\
+    <key>uuid</key>								\
+    <string>" ID "</string>						\
+    <key>distance</key>											\
+    <real>" DIST "</real>										\
+    <key>interest</key>											\
+    <real>" INT "</real>											\
+    <key>cap_urls</key>											\
+    <map>														\
+      <key>ObjectMedia</key>									\
+      <string>" URL1 "</string>			\
+      <key>ObjectMediaNavigate</key>							\
+      <string>" URL2 "</string>	\
+    </map>														\
+    <key>media_data</key>                                       \
+	" MEDIA_DATA "												\
+  </map>														\
+</llsd>"
+
+#define _DATA(ID,DIST,INT) _DATA_URLS(ID,DIST,INT,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)
+
+const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","1.0");
+	
+#define STR(I) boost::lexical_cast<std::string>(I)
+
+#define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" <<			\
+"================================================================================\n" << \
+"===================================== TEST " #N " ===================================\n" << \
+"================================================================================\n" << LL_ENDL;
+
+LLSD *gPostRecords = NULL;
+
+// stubs:
+void LLHTTPClient::post(
+		const std::string& url,
+		const LLSD& body,
+		LLHTTPClient::ResponderPtr responder,
+		const LLSD& headers,
+		const F32 timeout)
+{
+	LLSD record;
+	record["url"] = url;
+	record["body"] = body;
+	record["headers"] = headers;
+	record["timeout"] = timeout;
+	gPostRecords->append(record);
+	
+	// Magic URL that triggers a 503:
+	if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 )
+	{
+		responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason");
+	}
+	else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR) 
+	{
+		LLSD result;
+		LLSD error;
+		error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;
+		result["error"] = error;
+		responder->result(result);
+	}
+	else {
+		responder->result(LLSD());
+	}
+}
+
+const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
+
+class LLMediaDataClientObjectTest : public LLMediaDataClientObject
+{
+public:
+	LLMediaDataClientObjectTest(const char *data) 
+		{
+			std::istringstream d(data);
+			LLSDSerialize::fromXML(mRep, d);
+			mNumBounceBacks = 0;
+            
+           // std::cout << ll_pretty_print_sd(mRep) << std::endl;
+           // std::cout << "ID: " << getID() << std::endl;
+		}
+	LLMediaDataClientObjectTest(const LLSD &rep) 
+		: mRep(rep), mNumBounceBacks(0) {}
+	~LLMediaDataClientObjectTest()
+		{ LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; }
+	
+	virtual U8 getMediaDataCount() const 
+		{ return mRep["media_data"].size(); }
+	virtual LLSD getMediaDataLLSD(U8 index) const
+		{ return mRep["media_data"][(LLSD::Integer)index]; }
+	virtual LLUUID getID() const 
+		{ return mRep["uuid"]; }
+	virtual void mediaNavigateBounceBack(U8 index)
+		{
+			mNumBounceBacks++;
+		}
+	
+	virtual bool hasMedia() const
+		{ return mRep.has("media_data"); }
+	
+	virtual void updateObjectMediaData(LLSD const &media_data_array)
+		{ mRep["media_data"] = media_data_array; }
+	
+	virtual F64 getDistanceFromAvatar() const
+		{ return (LLSD::Real)mRep["distance"]; }
+	
+	virtual F64 getTotalMediaInterest() const
+		{ return (LLSD::Real)mRep["interest"]; }
+
+	virtual std::string getCapabilityUrl(const std::string &name) const 
+		{ return mRep["cap_urls"][name]; }
+
+	int getNumBounceBacks() const
+		{ return mNumBounceBacks; }
+	
+private:
+	LLSD mRep;
+	int mNumBounceBacks;
+};
+
+// This special timer delay should ensure that the timer will fire on the very
+// next pump, no matter what (though this does make an assumption about the
+// implementation of LLEventTimer::updateClass()):
+const F32 NO_PERIOD = -1000.0f;
+
+static void pump_timers()
+{
+	LLEventTimer::updateClass();
+}
+
+namespace tut
+{
+    struct mediadataclient
+    {
+		mediadataclient() {
+			gPostRecords = &mLLSD;
+			
+ 			//LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ 			//LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG);
+			//LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG);
+		}
+		LLSD mLLSD;
+    };
+    
+	typedef test_group<mediadataclient> mediadataclient_t;
+	typedef mediadataclient_t::object mediadataclient_object_t;
+	tut::mediadataclient_t tut_mediadataclient("mediadataclient");
+    
+    void ensure(const std::string &msg, int value, int expected)
+    {
+        std::string m = msg;
+        m += " value: " + STR(value);
+        m += ", expected: " + STR(expected);
+        ensure(m, value == expected);
+    }
+    
+    void ensure(const std::string &msg, const std::string & value, const std::string & expected)
+    {
+        std::string m = msg;
+        m += " value: " + value;
+        m += ", expected: " + expected;
+        ensure(m, value == expected);
+    }
+    
+    void ensure(const std::string &msg, const LLUUID & value, const LLUUID & expected)
+    {
+        std::string m = msg;
+        m += " value: " + value.asString();
+        m += ", expected: " + expected.asString();
+        ensure(m, value == expected);
+    }
+    
+    void ensure_llsd(const std::string &msg, const LLSD & value, const char *expected)
+    {
+        LLSD expected_llsd;
+        std::istringstream e(expected);
+        LLSDSerialize::fromXML(expected_llsd, e);
+   
+        std::string value_str = ll_pretty_print_sd(value);
+        std::string expected_str = ll_pretty_print_sd(expected_llsd);
+        std::string m = msg;
+        m += " value: " + value_str;
+        m += ", expected: " + expected_str;
+        ensure(m, value_str == expected_str);
+    }
+
+	//////////////////////////////////////////////////////////////////////////////////////////
+	
+	template<> template<>
+	void mediadataclient_object_t::test<1>()
+	{
+		//
+		// Test fetchMedia()
+		//
+		LOG_TEST(1);
+		
+		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+		int num_refs_start = o->getNumRefs();
+		{
+			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+			mdc->fetchMedia(o);
+
+			// Make sure no posts happened yet...
+			ensure("post records", gPostRecords->size(), 0);
+
+			::pump_timers();
+		
+			ensure("post records", gPostRecords->size(), 1);
+			ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
+			ensure("post GET", (*gPostRecords)[0]["body"]["verb"], "GET");
+			ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+			ensure("queue empty", mdc->isEmpty());
+		}
+		
+		// Make sure everyone's destroyed properly
+		ensure("REF COUNT", o->getNumRefs(), num_refs_start);
+    }
+
+	//////////////////////////////////////////////////////////////////////////////////////////
+
+	template<> template<>
+	void mediadataclient_object_t::test<2>()
+	{
+		//
+		// Test updateMedia()
+		//
+		LOG_TEST(2);
+
+		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+		{
+			// queue time w/ no delay ensures that ::pump_timers() will hit the tick()
+			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);  
+			mdc->updateMedia(o);
+			ensure("post records", gPostRecords->size(), 0);
+			::pump_timers();
+		
+			ensure("post records", gPostRecords->size(), 1);
+			ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
+			ensure("post UPDATE", (*gPostRecords)[0]["body"]["verb"], "UPDATE");
+			ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+			ensure_llsd("post data llsd", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_MEDIA_DATA_KEY], 
+						"<llsd>" MEDIA_DATA "</llsd>");
+			ensure("queue empty", mdc->isEmpty());
+		}
+
+		ensure("REF COUNT", o->getNumRefs(), 1);
+	}
+
+	//////////////////////////////////////////////////////////////////////////////////////////
+
+    template<> template<>
+    void mediadataclient_object_t::test<3>()
+    {
+		//
+		// Test navigate()
+		//
+		LOG_TEST(3);
+
+		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+		{		
+			LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD);
+			const char *TEST_URL = "http://example.com";
+			mdc->navigate(o, 0, TEST_URL);
+			ensure("post records", gPostRecords->size(), 0);
+			::pump_timers();
+
+			// ensure no bounce back
+			ensure("bounce back", dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(), 0);
+		
+			ensure("post records", gPostRecords->size(), 1);
+			ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL);
+			ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+			ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0);
+			ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL);
+			ensure("queue empty", mdc->isEmpty());
+		}
+		ensure("REF COUNT", o->getNumRefs(), 1);
+    }
+	
+	//////////////////////////////////////////////////////////////////////////////////////////
+
+    template<> template<>
+    void mediadataclient_object_t::test<4>()
+    {
+		//
+		// Test queue ordering
+		//
+		LOG_TEST(4);
+
+		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
+			_DATA(VALID_OBJECT_ID_1,"3.0","1.0"));
+		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
+			_DATA(VALID_OBJECT_ID_2,"1.0","1.0"));
+		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(
+			_DATA(VALID_OBJECT_ID_3,"2.0","1.0"));
+		{
+			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);  
+			const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 };
+			mdc->fetchMedia(o1);
+			mdc->fetchMedia(o2);
+			mdc->fetchMedia(o3);
+
+			// Make sure no posts happened yet...
+			ensure("post records", gPostRecords->size(), 0);
+
+			// tick 3 times...
+			::pump_timers();
+			ensure("post records", gPostRecords->size(), 1);
+			::pump_timers();
+			ensure("post records", gPostRecords->size(), 2);
+			::pump_timers();
+			ensure("post records", gPostRecords->size(), 3);
+		
+			for( int i=0; i < 3; i++ )
+			{
+				ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
+				ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
+				ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), 
+					   LLUUID(ORDERED_OBJECT_IDS[i]));
+			}
+
+			ensure("queue empty", mdc->isEmpty());
+		}
+		ensure("refcount of o1", o1->getNumRefs(), 1);
+		ensure("refcount of o2", o2->getNumRefs(), 1);
+		ensure("refcount of o3", o3->getNumRefs(), 1);
+    }
+
+	//////////////////////////////////////////////////////////////////////////////////////////
+
+	template<> template<>
+	void mediadataclient_object_t::test<5>()
+	{
+		//
+		// Test fetchMedia() getting a 503 error
+		//
+		LOG_TEST(5);
+		
+		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
+			_DATA_URLS(VALID_OBJECT_ID,
+					   "1.0",
+					   "1.0",
+					   FAKE_OBJECT_MEDIA_CAP_URL_503,
+					   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL));
+		int num_refs_start = o->getNumRefs();
+		{
+			const int NUM_RETRIES = 5;
+			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD,NUM_RETRIES);
+
+			// This should generate a retry
+			mdc->fetchMedia(o);
+
+			// Make sure no posts happened yet...
+			ensure("post records before", gPostRecords->size(), 0);
+
+			// Once, causes retry
+			// Second, fires retry timer
+			// Third, fires queue timer again
+			for (int i=0; i<NUM_RETRIES; ++i)
+			{
+				::pump_timers();  // Should pump (fire) the queue timer, causing a retry timer to be scheduled
+				// XXX This ensure is not guaranteed, because scheduling a timer might actually get it pumped in the same loop
+				//ensure("post records " + STR(i), gPostRecords->size(), i+1);
+				::pump_timers();  // Should pump (fire) the retry timer, scheduling the queue timer
+			}
+
+			// Do some extra pumps to make sure no other timer work occurs.
+			::pump_timers();
+			::pump_timers();
+			::pump_timers();
+			
+			// Make sure there were 2 posts
+			ensure("post records after", gPostRecords->size(), NUM_RETRIES);
+			for (int i=0; i<NUM_RETRIES; ++i)
+			{
+				ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL_503);
+				ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
+				ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+			}
+			ensure("queue empty", mdc->isEmpty());
+		}
+		
+		// Make sure everyone's destroyed properly
+		ensure("REF COUNT", o->getNumRefs(), num_refs_start);
+    }
+
+    template<> template<>
+    void mediadataclient_object_t::test<6>()
+    {
+		//
+		// Test navigate() with a bounce back
+		//
+		LOG_TEST(6);
+
+		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
+			_DATA_URLS(VALID_OBJECT_ID,
+					   "1.0",
+					   "1.0",
+					   FAKE_OBJECT_MEDIA_CAP_URL,
+					   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR));
+		{		
+			LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD);
+			const char *TEST_URL = "http://example.com";
+			mdc->navigate(o, 0, TEST_URL);
+			ensure("post records", gPostRecords->size(), 0);
+			::pump_timers();
+
+			// ensure bounce back
+			ensure("bounce back", 
+				   dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(),
+				   1);
+			
+			ensure("post records", gPostRecords->size(), 1);
+			ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR);
+			ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+			ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0);
+			ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL);
+			ensure("queue empty", mdc->isEmpty());
+		}
+		ensure("REF COUNT", o->getNumRefs(), 1);
+    }
+
+	
+}
diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp
index 40f7d532bc6846280c2e60b501ab69eaa851213c..988d28c3016fe50a5587b1eab84f6f94fb2b3c1e 100644
--- a/indra/newview/tests/llviewerhelputil_test.cpp
+++ b/indra/newview/tests/llviewerhelputil_test.cpp
@@ -30,6 +30,9 @@
  * COMPLETENESS OR PERFORMANCE.
  * $/LicenseInfo$
  */
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+
 #include "../test/lltut.h"
 
 #include "../llviewerhelputil.h"
diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c94ba0a3e89032e2d22cb5f1b8839d3449b45957
--- /dev/null
+++ b/indra/newview/tests/llxmlrpclistener_test.cpp
@@ -0,0 +1,230 @@
+/*
+ * @file   llxmlrpclistener_test.cpp
+ * @author Nat Goodspeed
+ * @date   2009-03-20
+ * @brief  Test for llxmlrpclistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=internal$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+// associated header
+#include "../llxmlrpclistener.h"
+// STL headers
+#include <iomanip>
+// std headers
+// external library headers
+// other Linden headers
+#include "../test/lltut.h"
+#include "../llxmlrpctransaction.h"
+#include "llevents.h"
+#include "lleventfilter.h"
+#include "llsd.h"
+#include "llcontrol.h"
+#include "tests/wrapllerrs.h"
+
+LLControlGroup gSavedSettings("Global");
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct data
+    {
+        data():
+            pumps(LLEventPumps::instance()),
+            uri("http://127.0.0.1:8000")
+        {
+            // These variables are required by machinery used by
+            // LLXMLRPCTransaction. The values reflect reality for this test
+            // executable; hopefully these values are correct.
+            gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", FALSE); // don't persist
+            gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", FALSE); // don't persist
+        }
+
+        // LLEventPump listener signature
+        bool captureReply(const LLSD& r)
+        {
+            reply = r;
+            return false;
+        }
+
+        LLSD reply;
+        LLEventPumps& pumps;
+        std::string uri;
+    };
+    typedef test_group<data> llxmlrpclistener_group;
+    typedef llxmlrpclistener_group::object object;
+    llxmlrpclistener_group llxmlrpclistenergrp("llxmlrpclistener");
+
+    template<> template<>
+    void object::test<1>()
+    {
+        set_test_name("request validation");
+        WrapLL_ERRS capture;
+        LLSD request;
+        request["uri"] = uri;
+        std::string threw;
+        try
+        {
+            pumps.obtain("LLXMLRPCTransaction").post(request);
+        }
+        catch (const WrapLL_ERRS::FatalException& e)
+        {
+            threw = e.what();
+        }
+        ensure_contains("threw exception", threw, "missing params");
+        ensure_contains("identified missing", threw, "method");
+        ensure_contains("identified missing", threw, "reply");
+    }
+
+    template<> template<>
+    void object::test<2>()
+    {
+        set_test_name("param types validation");
+        WrapLL_ERRS capture;
+        LLSD request;
+        request["uri"] = uri;
+        request["method"] = "hello";
+        request["reply"] = "reply";
+        LLSD& params(request["params"]);
+        params["who"]["specifically"] = "world"; // LLXMLRPCListener only handles scalar params
+        std::string threw;
+        try
+        {
+            pumps.obtain("LLXMLRPCTransaction").post(request);
+        }
+        catch (const WrapLL_ERRS::FatalException& e)
+        {
+            threw = e.what();
+        }
+        ensure_contains("threw exception", threw, "unknown type");
+    }
+
+    template<> template<>
+    void object::test<3>()
+    {
+        set_test_name("success case");
+        LLSD request;
+        request["uri"] = uri;
+        request["method"] = "hello";
+        request["reply"] = "reply";
+        LLSD& params(request["params"]);
+        params["who"] = "world";
+        // Set up a timeout filter so we don't spin forever waiting.
+        LLEventTimeout watchdog;
+        // Connect the timeout filter to the reply pump.
+        LLTempBoundListener temp(
+            pumps.obtain("reply").
+            listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1)));
+        // Now connect our target listener to the timeout filter.
+        watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1));
+        // Kick off the request...
+        reply.clear();
+        pumps.obtain("LLXMLRPCTransaction").post(request);
+        // Set the timer
+        F32 timeout(10);
+        watchdog.eventAfter(timeout, LLSD().insert("timeout", 0));
+        // and pump "mainloop" until we get something, whether from
+        // LLXMLRPCListener or from the watchdog filter.
+        LLTimer timer;
+        F32 start = timer.getElapsedTimeF32();
+        LLEventPump& mainloop(pumps.obtain("mainloop"));
+        while (reply.isUndefined())
+        {
+            mainloop.post(LLSD());
+        }
+        ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1));
+        ensure_equals(reply["responses"]["hi_there"].asString(), "Hello, world!");
+    }
+
+    template<> template<>
+    void object::test<4>()
+    {
+        set_test_name("bogus method");
+        LLSD request;
+        request["uri"] = uri;
+        request["method"] = "goodbye";
+        request["reply"] = "reply";
+        LLSD& params(request["params"]);
+        params["who"] = "world";
+        // Set up a timeout filter so we don't spin forever waiting.
+        LLEventTimeout watchdog;
+        // Connect the timeout filter to the reply pump.
+        LLTempBoundListener temp(
+            pumps.obtain("reply").
+            listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1)));
+        // Now connect our target listener to the timeout filter.
+        watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1));
+        // Kick off the request...
+        reply.clear();
+        pumps.obtain("LLXMLRPCTransaction").post(request);
+        // Set the timer
+        F32 timeout(10);
+        watchdog.eventAfter(timeout, LLSD().insert("timeout", 0));
+        // and pump "mainloop" until we get something, whether from
+        // LLXMLRPCListener or from the watchdog filter.
+        LLTimer timer;
+        F32 start = timer.getElapsedTimeF32();
+        LLEventPump& mainloop(pumps.obtain("mainloop"));
+        while (reply.isUndefined())
+        {
+            mainloop.post(LLSD());
+        }
+        ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1));
+        ensure_equals("XMLRPC error", reply["status"].asString(), "XMLRPCError");
+    }
+
+    template<> template<>
+    void object::test<5>()
+    {
+        set_test_name("bad type");
+        LLSD request;
+        request["uri"] = uri;
+        request["method"] = "getdict";
+        request["reply"] = "reply";
+        (void)request["params"];
+        // Set up a timeout filter so we don't spin forever waiting.
+        LLEventTimeout watchdog;
+        // Connect the timeout filter to the reply pump.
+        LLTempBoundListener temp(
+            pumps.obtain("reply").
+            listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1)));
+        // Now connect our target listener to the timeout filter.
+        watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1));
+        // Kick off the request...
+        reply.clear();
+        pumps.obtain("LLXMLRPCTransaction").post(request);
+        // Set the timer
+        F32 timeout(10);
+        watchdog.eventAfter(timeout, LLSD().insert("timeout", 0));
+        // and pump "mainloop" until we get something, whether from
+        // LLXMLRPCListener or from the watchdog filter.
+        LLTimer timer;
+        F32 start = timer.getElapsedTimeF32();
+        LLEventPump& mainloop(pumps.obtain("mainloop"));
+        while (reply.isUndefined())
+        {
+            mainloop.post(LLSD());
+        }
+        ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1));
+        ensure_equals(reply["status"].asString(), "BadType");
+        ensure_contains("bad type", reply["responses"]["nested_dict"].asString(), "bad XMLRPC type");
+    }
+} // namespace tut
+
+/*****************************************************************************
+*   Resolve link errors: use real machinery here, since we intend to exchange
+*   actual XML with a peer process.
+*****************************************************************************/
+// Including llxmlrpctransaction.cpp drags in the static LLXMLRPCListener
+// instantiated there. That's why it works to post requests to the LLEventPump
+// named "LLXMLRPCTransaction".
+#include "../llxmlrpctransaction.cpp"
+#include "llcontrol.cpp"
+#include "llxmltree.cpp"
+#include "llxmlparser.cpp"
diff --git a/indra/newview/tests/test_llxmlrpc_peer.py b/indra/newview/tests/test_llxmlrpc_peer.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb8f7d26c4cb6dab263468bbdd0d551b0356c95c
--- /dev/null
+++ b/indra/newview/tests/test_llxmlrpc_peer.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+"""\
+@file   test_llxmlrpc_peer.py
+@author Nat Goodspeed
+@date   2008-10-09
+@brief  This script asynchronously runs the executable (with args) specified on
+        the command line, returning its result code. While that executable is
+        running, we provide dummy local services for use by C++ tests.
+
+$LicenseInfo:firstyear=2008&license=viewergpl$
+Copyright (c) 2008, Linden Research, Inc.
+$/LicenseInfo$
+"""
+
+import os
+import sys
+from threading import Thread
+from SimpleXMLRPCServer import SimpleXMLRPCServer
+
+mydir = os.path.dirname(__file__)       # expected to be .../indra/newview/tests/
+sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
+sys.path.insert(1, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests"))
+from testrunner import run, debug
+
+class TestServer(SimpleXMLRPCServer):
+    def _dispatch(self, method, params):
+        try:
+            func = getattr(self, method)
+        except AttributeError:
+            raise Exception('method "%s" is not supported' % method)
+        else:
+            # LLXMLRPCListener constructs XMLRPC parameters that arrive as a
+            # 1-tuple containing a dict.
+            return func(**(params[0]))
+
+    def hello(self, who):
+        # LLXMLRPCListener expects a dict return.
+        return {"hi_there": "Hello, %s!" % who}
+
+    def getdict(self):
+        return dict(nested_dict=dict(a=17, b=5))
+
+    def log_request(self, code, size=None):
+        # For present purposes, we don't want the request splattered onto
+        # stderr, as it would upset devs watching the test run
+        pass
+
+    def log_error(self, format, *args):
+        # Suppress error output as well
+        pass
+
+class ServerRunner(Thread):
+    def run(self):
+        server = TestServer(('127.0.0.1', 8000))
+        debug("Starting XMLRPC server...\n")
+        server.serve_forever()
+
+if __name__ == "__main__":
+    sys.exit(run(server=ServerRunner(name="xmlrpc"), *sys.argv[1:]))
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index db4b68e9d6d16f630a426f6398d4f1a153bf7e58..2ac759909bdfe4fd53dc3af3e762b42f26cd65a4 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -164,28 +164,103 @@ def final_exe(self):
             return ''.join(self.channel().split()) + '.exe'
 
 
+    def test_msvcrt_and_copy_action(self, src, dst):
+        # This is used to test a dll manifest.
+        # It is used as a temporary override during the construct method
+        from test_win32_manifest import test_assembly_binding
+        if src and (os.path.exists(src) or os.path.islink(src)):
+            # ensure that destination path exists
+            self.cmakedirs(os.path.dirname(dst))
+            self.created_paths.append(dst)
+            if not os.path.isdir(src):
+                if(self.args['configuration'].lower() == 'debug'):
+                    test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "8.0.50727.4053")
+                else:
+                    test_assembly_binding(src, "Microsoft.VC80.CRT", "8.0.50727.4053")
+                self.ccopy(src,dst)
+            else:
+                raise Exception("Directories are not supported by test_CRT_and_copy_action()")
+        else:
+            print "Doesn't exist:", src
+
+    def test_for_no_msvcrt_manifest_and_copy_action(self, src, dst):
+        # This is used to test that no manifest for the msvcrt exists.
+        # It is used as a temporary override during the construct method
+        from test_win32_manifest import test_assembly_binding
+        from test_win32_manifest import NoManifestException, NoMatchingAssemblyException
+        if src and (os.path.exists(src) or os.path.islink(src)):
+            # ensure that destination path exists
+            self.cmakedirs(os.path.dirname(dst))
+            self.created_paths.append(dst)
+            if not os.path.isdir(src):
+                try:
+                    if(self.args['configuration'].lower() == 'debug'):
+                        test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "")
+                    else:
+                        test_assembly_binding(src, "Microsoft.VC80.CRT", "")
+                    raise Exception("Unknown condition")
+                except NoManifestException, err:
+                    pass
+                except NoMatchingAssemblyException, err:
+                    pass
+                    
+                self.ccopy(src,dst)
+            else:
+                raise Exception("Directories are not supported by test_CRT_and_copy_action()")
+        else:
+            print "Doesn't exist:", src
+        
+    def enable_crt_manifest_check(self):
+        WindowsManifest.copy_action = WindowsManifest.test_msvcrt_and_copy_action
+
+    def enable_no_crt_manifest_check(self):
+        WindowsManifest.copy_action = WindowsManifest.test_for_no_msvcrt_manifest_and_copy_action
+
+    def disable_manifest_check(self):
+        del WindowsManifest.copy_action
+
     def construct(self):
         super(WindowsManifest, self).construct()
-        # the final exe is complicated because we're not sure where it's coming from,
-        # nor do we have a fixed name for the executable
-        self.path(self.find_existing_file('debug/secondlife-bin.exe', 'release/secondlife-bin.exe', 'relwithdebinfo/secondlife-bin.exe'), dst=self.final_exe())
+        # Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe.
+        self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe())
+
+        self.enable_crt_manifest_check()
 
         # Plugin host application
         self.path(os.path.join(os.pardir,
                                'llplugin', 'slplugin', self.args['configuration'], "slplugin.exe"),
                   "slplugin.exe")
- 
-        # need to get the kdu dll from any of the build directories as well
+        
+        # need to get the llcommon.dll from the build directory as well
+        if self.prefix(src=self.args['configuration'], dst=""):
+            try:
+                self.path('llcommon.dll')
+                self.path('libapr-1.dll')
+                self.path('libaprutil-1.dll')
+                self.path('libapriconv-1.dll')
+            except RuntimeError, err:
+                print err.message
+                print "Skipping llcommon.dll (assuming llcommon was linked statically)"
+
+            self.end_prefix()
+
+        # need to get the kdu dll from the build directory as well
         try:
-            self.path(self.find_existing_file('../llkdu/%s/llkdu.dll' % self.args['configuration'],
-                '../../libraries/i686-win32/lib/release/llkdu.dll'), 
-                  dst='llkdu.dll')
-            pass
-        except:
+            self.path('%s/llkdu.dll' % self.args['configuration'], dst='llkdu.dll')
+        except RuntimeError:
             print "Skipping llkdu.dll"
-            pass
-        self.path(src="licenses-win32.txt", dst="licenses.txt")
 
+        self.disable_manifest_check()
+
+        # For textures
+        if self.prefix(src=self.args['configuration'], dst=""):
+            if(self.args['configuration'].lower() == 'debug'):
+                self.path("openjpegd.dll")
+            else:
+                self.path("openjpeg.dll")
+            self.end_prefix()
+
+        self.path(src="licenses-win32.txt", dst="licenses.txt")
         self.path("featuretable.txt")
 
         # For use in crash reporting (generates minidumps)
@@ -193,17 +268,14 @@ def construct(self):
 
         # For using FMOD for sound... DJS
         self.path("fmod.dll")
-
+       
         # For automatic level of detail generation in mesh importer
         self.path("glod.dll")
 
         # For reading collada files
         self.path("libcollada14dom21.dll")
 
-        # For textures
-        if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
-            self.path("openjpeg.dll")
-            self.end_prefix()
+        self.enable_no_crt_manifest_check()
 
         # Media plugins - QuickTime
         if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
@@ -215,7 +287,6 @@ def construct(self):
             self.path("media_plugin_webkit.dll")
             self.end_prefix()
             
-        # For WebKit/Qt plugin runtimes
         if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"):
             self.path("libeay32.dll")
             self.path("qtcore4.dll")
@@ -236,6 +307,8 @@ def construct(self):
             self.path("qtiff4.dll")
             self.end_prefix()
 
+        self.disable_manifest_check()
+
         # These need to be installed as a SxS assembly, currently a 'private' assembly.
         # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx
         if self.prefix(src=self.args['configuration'], dst=""):
@@ -249,11 +322,8 @@ def construct(self):
                 self.path("Microsoft.VC80.CRT.manifest")
             self.end_prefix()
 
-        # The config file name needs to match the exe's name.
-        self.path(src="%s/secondlife-bin.exe.config" % self.args['configuration'], dst=self.final_exe() + ".config")
-
         # Vivox runtimes
-        if self.prefix(src="vivox-runtime/i686-win32", dst=""):
+        if self.prefix(src=self.args['configuration'], dst=""):
             self.path("SLVoice.exe")
             self.path("alut.dll")
             self.path("vivoxsdk.dll")
@@ -262,22 +332,22 @@ def construct(self):
             self.end_prefix()
 
         # pull in the crash logger and updater from other projects
-        self.path(src=self.find_existing_file( # tag:"crash-logger" here as a cue to the exporter
-                "../win_crash_logger/debug/windows-crash-logger.exe",
-                "../win_crash_logger/release/windows-crash-logger.exe",
-                "../win_crash_logger/relwithdebinfo/windows-crash-logger.exe"),
+        # tag:"crash-logger" here as a cue to the exporter
+        self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
                   dst="win_crash_logger.exe")
-        self.path(src=self.find_existing_file(
-                "../win_updater/debug/windows-updater.exe",
-                "../win_updater/release/windows-updater.exe",
-                "../win_updater/relwithdebinfo/windows-updater.exe"),
+        self.path(src='../win_updater/%s/windows-updater.exe' % self.args['configuration'],
                   dst="updater.exe")
 
         # For google-perftools tcmalloc allocator.
-        if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
-                self.path("libtcmalloc_minimal.dll")
-                self.end_prefix()
-
+        if self.prefix(src=self.args['configuration'], dst=""):
+            try:
+                if self.args['configuration'] == 'Debug':
+                    self.path('libtcmalloc_minimal-debug.dll')
+                else:
+                    self.path('libtcmalloc_minimal.dll')
+            except:
+                print "Skipping libtcmalloc_minimal.dll"
+            self.end_prefix()
 
     def nsi_file_commands(self, install=True):
         def wpath(path):
@@ -398,7 +468,11 @@ def package_finish(self):
 
         # We use the Unicode version of NSIS, available from
         # http://www.scratchpaper.com/
-        NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe'
+        # Check two paths, one for Program Files, and one for Program Files (x86).
+        # Yay 64bit windows.
+        NSIS_path = os.path.expandvars('${ProgramFiles}\\NSIS\\Unicode\\makensis.exe')
+        if not os.path.exists(NSIS_path):
+            NSIS_path = os.path.expandvars('${ProgramFiles(x86)}\\NSIS\\Unicode\\makensis.exe')
         self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile))
         # self.remove(self.dst_path_of(tempfile))
         # If we're on a build machine, sign the code using our Authenticode certificate. JC
@@ -474,16 +548,31 @@ def construct(self):
                 self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib")
                 self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice")
 
+                libdir = "../../libraries/universal-darwin/lib_release"
+                dylibs = {}
+
                 # need to get the kdu dll from any of the build directories as well
-                try:
-                    self.path(self.find_existing_file('../llkdu/%s/libllkdu.dylib' % self.args['configuration'],
-                        "../../libraries/universal-darwin/lib_release/libllkdu.dylib"),
-                        dst='libllkdu.dylib')
-                    pass
-                except:
-                    print "Skipping libllkdu.dylib"
-                    pass
-                
+                for lib in "llkdu", "llcommon":
+                    libfile = "lib%s.dylib" % lib
+                    try:
+                        self.path(self.find_existing_file(os.path.join(os.pardir,
+                                                                       lib,
+                                                                       self.args['configuration'],
+                                                                       libfile),
+                                                          os.path.join(libdir, libfile)),
+                                  dst=libfile)
+                    except RuntimeError:
+                        print "Skipping %s" % libfile
+                        dylibs[lib] = False
+                    else:
+                        dylibs[lib] = True
+
+                if dylibs["llcommon"]:
+                    for libfile in ("libapr-1.0.3.7.dylib",
+                                    "libaprutil-1.0.3.8.dylib",
+                                    "libexpat.0.5.0.dylib"):
+                        self.path(os.path.join(libdir, libfile), libfile)
+
                 #libfmodwrapper.dylib
                 self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib")
                 
@@ -491,6 +580,24 @@ def construct(self):
                 self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app")
                 self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app")
 
+                # our apps dependencies on shared libs
+                if dylibs["llcommon"]:
+                    mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources")
+                    mac_updater_res_path = self.dst_path_of("mac-updater.app/Contents/Resources")
+                    for libfile in ("libllcommon.dylib",
+                                    "libapr-1.0.3.7.dylib",
+                                    "libaprutil-1.0.3.8.dylib",
+                                    "libexpat.0.5.0.dylib"):
+                        target_lib = os.path.join('../../..', libfile)
+                        self.run_command("ln -sf %(target)r %(link)r" % 
+                                         {'target': target_lib,
+                                          'link' : os.path.join(mac_crash_logger_res_path, libfile)}
+                                         )
+                        self.run_command("ln -sf %(target)r %(link)r" % 
+                                         {'target': target_lib,
+                                          'link' : os.path.join(mac_updater_res_path, libfile)}
+                                         )
+
                 # plugin launcher
                 self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin")
 
@@ -515,7 +622,7 @@ def construct(self):
         # This may be desirable for the final release.  Or not.
         if ("package" in self.args['actions'] or 
             "unpacked" in self.args['actions']):
-            self.run_command('strip -S "%(viewer_binary)s"' %
+            self.run_command('strip -S %(viewer_binary)r' %
                              { 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')})
 
 
@@ -544,12 +651,12 @@ def package_finish(self):
         # make sure we don't have stale files laying about
         self.remove(sparsename, finalname)
 
-        self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % {
+        self.run_command('hdiutil create %(sparse)r -volname %(vol)r -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % {
                 'sparse':sparsename,
                 'vol':volname})
 
         # mount the image and get the name of the mount point and device node
-        hdi_output = self.run_command('hdiutil attach -private "' + sparsename + '"')
+        hdi_output = self.run_command('hdiutil attach -private %r' % sparsename)
         devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip()
         volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip()
 
@@ -583,24 +690,25 @@ def package_finish(self):
             self.copy_action(self.src_path_of(s), os.path.join(volpath, d))
 
         # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit)
-        self.run_command('SetFile -a V "' + os.path.join(volpath, ".VolumeIcon.icns") + '"')
-        self.run_command('SetFile -a V "' + os.path.join(volpath, "background.jpg") + '"')
-        self.run_command('SetFile -a V "' + os.path.join(volpath, ".DS_Store") + '"')
+        for f in ".VolumeIcon.icns", "background.jpg", ".DS_Store":
+            self.run_command('SetFile -a V %r' % os.path.join(volpath, f))
 
         # Create the alias file (which is a resource file) from the .r
-        self.run_command('rez "' + self.src_path_of("installers/darwin/release-dmg/Applications-alias.r") + '" -o "' + os.path.join(volpath, "Applications") + '"')
+        self.run_command('rez %r -o %r' %
+                         (self.src_path_of("installers/darwin/release-dmg/Applications-alias.r"),
+                          os.path.join(volpath, "Applications")))
 
         # Set the alias file's alias and custom icon bits
-        self.run_command('SetFile -a AC "' + os.path.join(volpath, "Applications") + '"')
+        self.run_command('SetFile -a AC %r' % os.path.join(volpath, "Applications"))
 
         # Set the disk image root's custom icon bit
-        self.run_command('SetFile -a C "' + volpath + '"')
+        self.run_command('SetFile -a C %r' % volpath)
 
         # Unmount the image
-        self.run_command('hdiutil detach -force "' + devfile + '"')
+        self.run_command('hdiutil detach -force %r' % devfile)
 
         print "Converting temp disk image to final disk image"
-        self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname})
+        self.run_command('hdiutil convert %(sparse)r -format UDZO -imagekey zlib-level=9 -o %(final)r' % {'sparse':sparsename, 'final':finalname})
         # get rid of the temp file
         self.package_file = finalname
         self.remove(sparsename)
@@ -673,15 +781,17 @@ def construct(self):
 
         # install either the libllkdu we just built, or a prebuilt one, in
         # decreasing order of preference.  for linux package, this goes to bin/
-        try:
-            self.path(self.find_existing_file('../llkdu/libllkdu.so',
-                '../../libraries/i686-linux/lib_release_client/libllkdu.so'), 
-                  dst='bin/libllkdu.so')
-            # keep this one to preserve syntax, open source mangling removes previous lines
-            pass
-        except:
-            print "Skipping libllkdu.so - not found"
-            pass
+        for lib, destdir in ("llkdu", "bin"), ("llcommon", "lib"):
+            libfile = "lib%s.so" % lib
+            try:
+                self.path(self.find_existing_file(os.path.join(os.pardir, lib, libfile),
+                    '../../libraries/i686-linux/lib_release_client/%s' % libfile), 
+                      dst=os.path.join(destdir, libfile))
+                # keep this one to preserve syntax, open source mangling removes previous lines
+                pass
+            except RuntimeError:
+                print "Skipping %s - not found" % libfile
+                pass
 
         self.path("secondlife-stripped","bin/do-not-directly-run-secondlife-bin")
         self.path("../linux_crash_logger/linux-crash-logger-stripped","bin/linux-crash-logger.bin")
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 920211ce3961996ca15815dd37131b7cb5161aaf..cc9fa598f25f5a2a0ec3e3d95fbcf305b05e8f21 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -13,7 +13,8 @@ include(LLXML)
 include(LScript)
 include(Linking)
 include(Tut)
-include(Boost)
+
+include(GoogleMock)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
@@ -24,6 +25,7 @@ include_directories(
     ${LLVFS_INCLUDE_DIRS}
     ${LLXML_INCLUDE_DIRS}
     ${LSCRIPT_INCLUDE_DIRS}
+    ${GOOGLEMOCK_INCLUDE_DIRS}
     )
 
 set(test_SOURCE_FILES
@@ -60,6 +62,7 @@ set(test_SOURCE_FILES
 set(test_HEADER_FILES
     CMakeLists.txt
 
+    debug.h
     llpipeutil.h
     llsdtraits.h
     lltut.h
@@ -93,6 +96,8 @@ target_link_libraries(test
     ${LLXML_LIBRARIES}
     ${LSCRIPT_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
+    ${EXPAT_LIBRARIES}
+    ${GOOGLEMOCK_LIBRARIES}
     ${APRICONV_LIBRARIES}
     ${PTHREAD_LIBRARY}
     ${WINDOWS_LIBRARIES}
@@ -112,16 +117,21 @@ endif (WINDOWS)
 
 get_target_property(TEST_EXE test LOCATION)
 
-add_custom_command(
+IF(WINDOWS)
+  set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR})
+ELSE(WINDOWS)
+  set(LD_LIBRARY_PATH ${ARCH_PREBUILT_DIRS}:${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}:/usr/lib)
+ENDIF(WINDOWS)
+
+LL_TEST_COMMAND("${LD_LIBRARY_PATH}"
+  "${TEST_EXE}" "--output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt" "--touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt")
+ADD_CUSTOM_COMMAND(
   OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
-  COMMAND ${TEST_EXE}
-  ARGS
-    --output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt
-    --touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
+  COMMAND ${LL_TEST_COMMAND_value}
   DEPENDS test
   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   COMMENT "C++ unit tests"
-  )
+ )
 
 set(test_results ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt)
 
diff --git a/indra/test/debug.h b/indra/test/debug.h
new file mode 100644
index 0000000000000000000000000000000000000000..a00659d880d5ac358f846b4eba81b913761a51df
--- /dev/null
+++ b/indra/test/debug.h
@@ -0,0 +1,68 @@
+/**
+ * @file   debug.h
+ * @author Nat Goodspeed
+ * @date   2009-05-28
+ * @brief  Debug output for unit test code
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_DEBUG_H)
+#define LL_DEBUG_H
+
+#include <iostream>
+
+/*****************************************************************************
+*   Debugging stuff
+*****************************************************************************/
+// This class is intended to illuminate entry to a given block, exit from the
+// same block and checkpoints along the way. It also provides a convenient
+// place to turn std::cout output on and off.
+class Debug
+{
+public:
+    Debug(const std::string& block):
+        mBlock(block)
+    {
+        (*this)("entry");
+    }
+
+    ~Debug()
+    {
+        (*this)("exit");
+    }
+
+    void operator()(const std::string& status)
+    {
+#if defined(DEBUG_ON)
+        std::cout << mBlock << ' ' << status << std::endl;
+#endif
+    }
+
+private:
+    const std::string mBlock;
+};
+
+// It's often convenient to use the name of the enclosing function as the name
+// of the Debug block.
+#define DEBUG Debug debug(__FUNCTION__)
+
+// These BEGIN/END macros are specifically for debugging output -- please
+// don't assume you must use such for coroutines in general! They only help to
+// make control flow (as well as exception exits) explicit.
+#define BEGIN                                   \
+{                                               \
+    DEBUG;                                      \
+    try
+
+#define END                                     \
+    catch (...)                                 \
+    {                                           \
+        debug("*** exceptional ");              \
+        throw;                                  \
+    }                                           \
+}
+
+#endif /* ! defined(LL_DEBUG_H) */
diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp
index e401f89b22b3e0e56c36d717f678b7117d0dd4be..31130c3c7932eb3ff08d548e3f4da6b9107803c4 100644
--- a/indra/test/llevents_tut.cpp
+++ b/indra/test/llevents_tut.cpp
@@ -32,96 +32,10 @@
 // other Linden headers
 #include "lltut.h"
 #include "stringize.h"
+#include "tests/listener.h"
 
 using boost::assign::list_of;
 
-/*****************************************************************************
-*   test listener class
-*****************************************************************************/
-class Listener;
-std::ostream& operator<<(std::ostream&, const Listener&);
-
-class Listener
-{
-public:
-    Listener(const std::string& name):
-        mName(name)
-    {
-//      std::cout << *this << ": ctor\n";
-    }
-    Listener(const Listener& that):
-        mName(that.mName),
-        mLastEvent(that.mLastEvent)
-    {
-//      std::cout << *this << ": copy\n";
-    }
-    virtual ~Listener()
-    {
-//      std::cout << *this << ": dtor\n";
-    }
-    std::string getName() const { return mName; }
-    bool call(const LLSD& event)
-    {
-//      std::cout << *this << "::call(" << event << ")\n";
-        mLastEvent = event;
-        return false;
-    }
-    bool callstop(const LLSD& event)
-    {
-//      std::cout << *this << "::callstop(" << event << ")\n";
-        mLastEvent = event;
-        return true;
-    }
-    LLSD getLastEvent() const
-    {
-//      std::cout << *this << "::getLastEvent() -> " << mLastEvent << "\n";
-        return mLastEvent;
-    }
-    void reset(const LLSD& to = LLSD())
-    {
-//      std::cout << *this << "::reset(" << to << ")\n";
-        mLastEvent = to;
-    }
-
-private:
-    std::string mName;
-    LLSD mLastEvent;
-};
-
-std::ostream& operator<<(std::ostream& out, const Listener& listener)
-{
-    out << "Listener(" << listener.getName() /* << "@" << &listener */ << ')';
-    return out;
-}
-
-struct Collect
-{
-    bool add(const std::string& bound, const LLSD& event)
-    {
-        result.push_back(bound);
-        return false;
-    }
-    void clear() { result.clear(); }
-    typedef std::vector<std::string> StringList;
-    StringList result;
-};
-
-std::ostream& operator<<(std::ostream& out, const Collect::StringList& strings)
-{
-    out << '(';
-    Collect::StringList::const_iterator begin(strings.begin()), end(strings.end());
-    if (begin != end)
-    {
-        out << '"' << *begin << '"';
-        while (++begin != end)
-        {
-            out << ", \"" << *begin << '"';
-        }
-    }
-    out << ')';
-    return out;
-}
-
 template<typename T>
 T make(const T& value) { return value; }
 
@@ -174,14 +88,7 @@ namespace tut
         // default combiner is defined to return the value returned by the
         // last listener, which is meaningless if there were no listeners.
         per_frame.post(0);
-        // NOTE: boost::bind() saves its arguments by VALUE! If you pass an
-        // object instance rather than a pointer, you'll end up binding to an
-        // internal copy of that instance! Use boost::ref() to capture a
-        // reference instead.
-        LLBoundListener connection = per_frame.listen(listener0.getName(),
-                                                      boost::bind(&Listener::call,
-                                                                  boost::ref(listener0),
-                                                                  _1));
+        LLBoundListener connection = listener0.listenTo(per_frame);
         ensure("connected", connection.connected());
         ensure("not blocked", ! connection.blocked());
         per_frame.post(1);
@@ -207,6 +114,10 @@ namespace tut
         bool threw = false;
         try
         {
+            // NOTE: boost::bind() saves its arguments by VALUE! If you pass
+            // an object instance rather than a pointer, you'll end up binding
+            // to an internal copy of that instance! Use boost::ref() to
+            // capture a reference instead.
             per_frame.listen(listener0.getName(), // note bug, dup name
                              boost::bind(&Listener::call, boost::ref(listener1), _1));
         }
@@ -221,8 +132,7 @@ namespace tut
         }
         ensure("threw DupListenerName", threw);
         // do it right this time
-        per_frame.listen(listener1.getName(),
-                         boost::bind(&Listener::call, boost::ref(listener1), _1));
+        listener1.listenTo(per_frame);
         per_frame.post(5);
         check_listener("got", listener0, 5);
         check_listener("got", listener1, 5);
@@ -252,16 +162,10 @@ namespace tut
         LLEventPump& per_frame(pumps.obtain("per-frame"));
         listener0.reset(0);
         listener1.reset(0);
-        LLBoundListener bound0 = per_frame.listen(listener0.getName(),
-                                                  boost::bind(&Listener::callstop,
-                                                              boost::ref(listener0),
-                                                              _1));
-        LLBoundListener bound1 = per_frame.listen(listener1.getName(),
-                                                  boost::bind(&Listener::call,
-                                                              boost::ref(listener1),
-                                                              _1),
-                                                  // after listener0
-                                                  make<LLEventPump::NameList>(list_of(listener0.getName())));
+        LLBoundListener bound0 = listener0.listenTo(per_frame, &Listener::callstop);
+        LLBoundListener bound1 = listener1.listenTo(per_frame, &Listener::call,
+                                                    // after listener0
+                                                    make<LLEventPump::NameList>(list_of(listener0.getName())));
         ensure("enabled", per_frame.enabled());
         ensure("connected 0", bound0.connected());
         ensure("unblocked 0", ! bound0.blocked());
@@ -301,7 +205,7 @@ namespace tut
         // LLEventQueue.
         LLEventPump& mainloop(pumps.obtain("mainloop"));
         ensure("LLEventQueue leaf class", dynamic_cast<LLEventQueue*>(&login));
-        login.listen(listener0.getName(), boost::bind(&Listener::call, boost::ref(listener0), _1));
+        listener0.listenTo(login);
         listener0.reset(0);
         login.post(1);
         check_listener("waiting for queued event", listener0, 0);
@@ -354,11 +258,10 @@ namespace tut
     {
         set_test_name("stopListening()");
         LLEventPump& login(pumps.obtain("login"));
-        login.listen(listener0.getName(), boost::bind(&Listener::call, boost::ref(listener0), _1));
+        listener0.listenTo(login);
         login.stopListening(listener0.getName());
         // should not throw because stopListening() should have removed name
-        login.listen(listener0.getName(),
-                     boost::bind(&Listener::callstop, boost::ref(listener0), _1));
+        listener0.listenTo(login, &Listener::callstop);
         LLBoundListener wrong = login.getListener("bogus");
         ensure("bogus connection disconnected", ! wrong.connected());
         ensure("bogus connection blocked", wrong.blocked());
@@ -378,10 +281,8 @@ namespace tut
                         boost::bind(&LLEventPump::post, boost::ref(filter0), _1));
         upstream.listen(filter1.getName(),
                         boost::bind(&LLEventPump::post, boost::ref(filter1), _1));
-        filter0.listen(listener0.getName(),
-                       boost::bind(&Listener::call, boost::ref(listener0), _1));
-        filter1.listen(listener1.getName(),
-                       boost::bind(&Listener::call, boost::ref(listener1), _1));
+        listener0.listenTo(filter0);
+        listener1.listenTo(filter1);
         listener0.reset(0);
         listener1.reset(0);
         upstream.post(1);
@@ -536,7 +437,7 @@ namespace tut
         // Passing a string LLEventPump name to LLListenerOrPumpName
         listener0.reset(0);
         LLEventStream random("random");
-        random.listen(listener0.getName(), boost::bind(&Listener::call, boost::ref(listener0), _1));
+        listener0.listenTo(random);
         eventSource("random");
         check_listener("got by pump name", listener0, 17);
         bool threw = false;
diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp
index 34f3530308113a5078d41340bbbd2d96802fa78e..ca15314e69cc08d82868dcac12e45bd7551e9c47 100755
--- a/indra/test/llsdmessagebuilder_tut.cpp
+++ b/indra/test/llsdmessagebuilder_tut.cpp
@@ -44,6 +44,8 @@
 #include "v3dmath.h"
 #include "v3math.h"
 #include "v4math.h"
+#include "llsdutil.h"
+//#include "llsdutil.cpp"
 #include "llsdutil_math.cpp"
 #include "lltemplatemessagebuilder.h"
 
diff --git a/indra/test/llsdmessagereader_tut.cpp b/indra/test/llsdmessagereader_tut.cpp
index 36cfe5ebfcdd70a843f55cf08ac728a377a2623e..f11e148ccaf816262f922bae0a60546ac2b5a2a2 100755
--- a/indra/test/llsdmessagereader_tut.cpp
+++ b/indra/test/llsdmessagereader_tut.cpp
@@ -42,6 +42,7 @@
 #include "message.h"
 #include "llsdmessagereader.h"
 #include "llsdutil.h"
+#include "llsdutil_math.h"
 
 namespace tut
 {	
diff --git a/indra/test/llsdutil_tut.cpp b/indra/test/llsdutil_tut.cpp
index 0c4bbc2e625ad0ef75648cd234be813d9f309a3b..d125bb00050e5e72effccbd239001215aaf359f4 100644
--- a/indra/test/llsdutil_tut.cpp
+++ b/indra/test/llsdutil_tut.cpp
@@ -44,12 +44,42 @@
 #include "v4math.h"
 #include "llquaternion.h"
 #include "llsdutil.h"
-
+#include "llsdutil_math.h"
+#include "stringize.h"
+#include <set>
+#include <boost/range.hpp>
 
 namespace tut
 {
 	struct llsdutil_data
 	{
+        void test_matches(const std::string& proto_key, const LLSD& possibles,
+                          const char** begin, const char** end)
+        {
+            std::set<std::string> succeed(begin, end);
+            LLSD prototype(possibles[proto_key]);
+            for (LLSD::map_const_iterator pi(possibles.beginMap()), pend(possibles.endMap());
+                 pi != pend; ++pi)
+            {
+                std::string match(llsd_matches(prototype, pi->second));
+                std::set<std::string>::const_iterator found = succeed.find(pi->first);
+                if (found != succeed.end())
+                {
+                    // This test is supposed to succeed. Comparing to the
+                    // empty string ensures that if the test fails, it will
+                    // display the string received so we can tell what failed.
+                    ensure_equals("match", match, "");
+                }
+                else
+                {
+                    // This test is supposed to fail. If we get a false match,
+                    // the string 'match' will be empty, which doesn't tell us
+                    // much about which case went awry. So construct a more
+                    // detailed description string.
+                    ensure(proto_key + " shouldn't match " + pi->first, ! match.empty());
+                }
+            }
+        }
 	};
 	typedef test_group<llsdutil_data> llsdutil_test;;
 	typedef llsdutil_test::object llsdutil_object;
@@ -159,4 +189,207 @@ namespace tut
 		LLSD sd1 = ll_sd_from_color4(c1);
 		ensure_equals("sd -> LLColor4 -> sd", sd, sd1);
 	}
+
+    template<> template<>
+    void llsdutil_object::test<9>()
+    {
+        set_test_name("llsd_matches");
+
+        // for this test, construct a map of all possible LLSD types
+        LLSD map;
+        map.insert("empty",     LLSD());
+        map.insert("Boolean",   LLSD::Boolean());
+        map.insert("Integer",   LLSD::Integer(0));
+        map.insert("Real",      LLSD::Real(0.0));
+        map.insert("String",    LLSD::String("bah"));
+        map.insert("NumString", LLSD::String("1"));
+        map.insert("UUID",      LLSD::UUID());
+        map.insert("Date",      LLSD::Date());
+        map.insert("URI",       LLSD::URI());
+        map.insert("Binary",    LLSD::Binary());
+        map.insert("Map",       LLSD().insert("foo", LLSD()));
+        // Only an empty array can be constructed on the fly
+        LLSD array;
+        array.append(LLSD());
+        map.insert("Array",     array);
+
+        // These iterators are declared outside our various for loops to avoid
+        // fatal MSVC warning: "I used to be broken, but I'm all better now!"
+        LLSD::map_const_iterator mi, mend(map.endMap());
+
+        /*-------------------------- llsd_matches --------------------------*/
+
+        // empty prototype matches anything
+        for (mi = map.beginMap(); mi != mend; ++mi)
+        {
+            ensure_equals(std::string("empty matches ") + mi->first, llsd_matches(LLSD(), mi->second), "");
+        }
+
+        LLSD proto_array, data_array;
+        for (int i = 0; i < 3; ++i)
+        {
+            proto_array.append(LLSD());
+            data_array.append(LLSD());
+        }
+
+        // prototype array matches only array
+        for (mi = map.beginMap(); mi != mend; ++mi)
+        {
+            ensure(std::string("array doesn't match ") + mi->first,
+                   ! llsd_matches(proto_array, mi->second).empty());
+        }
+
+        // data array must be at least as long as prototype array
+        proto_array.append(LLSD());
+        ensure_equals("data array too short", llsd_matches(proto_array, data_array),
+                      "Array size 4 required instead of Array size 3");
+        data_array.append(LLSD());
+        ensure_equals("data array just right", llsd_matches(proto_array, data_array), "");
+        data_array.append(LLSD());
+        ensure_equals("data array longer", llsd_matches(proto_array, data_array), "");
+
+        // array element matching
+        data_array[0] = LLSD::String();
+        ensure_equals("undefined prototype array entry", llsd_matches(proto_array, data_array), "");
+        proto_array[0] = LLSD::Binary();
+        ensure_equals("scalar prototype array entry", llsd_matches(proto_array, data_array),
+                      "[0]: Binary required instead of String");
+        data_array[0] = LLSD::Binary();
+        ensure_equals("matching prototype array entry", llsd_matches(proto_array, data_array), "");
+
+        // build a coupla maps
+        LLSD proto_map, data_map;
+        data_map["got"] = LLSD();
+        data_map["found"] = LLSD();
+        for (LLSD::map_const_iterator dmi(data_map.beginMap()), dmend(data_map.endMap());
+             dmi != dmend; ++dmi)
+        {
+            proto_map[dmi->first] = dmi->second;
+        }
+        proto_map["foo"] = LLSD();
+        proto_map["bar"] = LLSD();
+
+        // prototype map matches only map
+        for (mi = map.beginMap(); mi != mend; ++mi)
+        {
+            ensure(std::string("map doesn't match ") + mi->first,
+                   ! llsd_matches(proto_map, mi->second).empty());
+        }
+
+        // data map must contain all keys in prototype map
+        std::string error(llsd_matches(proto_map, data_map));
+        ensure_contains("missing keys", error, "missing keys");
+        ensure_contains("missing foo", error, "foo");
+        ensure_contains("missing bar", error, "bar");
+        ensure_does_not_contain("found found", error, "found");
+        ensure_does_not_contain("got got", error, "got");
+        data_map["bar"] = LLSD();
+        error = llsd_matches(proto_map, data_map);
+        ensure_contains("missing foo", error, "foo");
+        ensure_does_not_contain("got bar", error, "bar");
+        data_map["foo"] = LLSD();
+        ensure_equals("data map just right", llsd_matches(proto_map, data_map), "");
+        data_map["extra"] = LLSD();
+        ensure_equals("data map with extra", llsd_matches(proto_map, data_map), "");
+
+        // map element matching
+        data_map["foo"] = LLSD::String();
+        ensure_equals("undefined prototype map entry", llsd_matches(proto_map, data_map), "");
+        proto_map["foo"] = LLSD::Binary();
+        ensure_equals("scalar prototype map entry", llsd_matches(proto_map, data_map),
+                      "['foo']: Binary required instead of String");
+        data_map["foo"] = LLSD::Binary();
+        ensure_equals("matching prototype map entry", llsd_matches(proto_map, data_map), "");
+
+        // String
+        {
+            static const char* matches[] = { "String", "NumString", "Boolean", "Integer",
+                                             "Real", "UUID", "Date", "URI" };
+            test_matches("String", map, boost::begin(matches), boost::end(matches));
+        }
+
+        // Boolean, Integer, Real
+        static const char* numerics[] = { "Boolean", "Integer", "Real" };
+        for (const char **ni = boost::begin(numerics), **nend = boost::end(numerics);
+             ni != nend; ++ni)
+        {
+            static const char* matches[] = { "Boolean", "Integer", "Real", "String", "NumString" };
+            test_matches(*ni, map, boost::begin(matches), boost::end(matches));
+        }
+
+        // UUID
+        {
+            static const char* matches[] = { "UUID", "String", "NumString" };
+            test_matches("UUID", map, boost::begin(matches), boost::end(matches));
+        }
+
+        // Date
+        {
+            static const char* matches[] = { "Date", "String", "NumString" };
+            test_matches("Date", map, boost::begin(matches), boost::end(matches));
+        }
+
+        // URI
+        {
+            static const char* matches[] = { "URI", "String", "NumString" };
+            test_matches("URI", map, boost::begin(matches), boost::end(matches));
+        }
+
+        // Binary
+        {
+            static const char* matches[] = { "Binary" };
+            test_matches("Binary", map, boost::begin(matches), boost::end(matches));
+        }
+
+        /*-------------------------- llsd_equals ---------------------------*/
+
+        // Cross-product of each LLSD type with every other
+        for (LLSD::map_const_iterator lmi(map.beginMap()), lmend(map.endMap());
+             lmi != lmend; ++lmi)
+        {
+            for (LLSD::map_const_iterator rmi(map.beginMap()), rmend(map.endMap());
+                 rmi != rmend; ++rmi)
+            {
+                // Name this test based on the map keys naming the types of
+                // interest, e.g "String::Integer".
+                // We expect the values (xmi->second) to be equal if and only
+                // if the type names (xmi->first) are equal.
+                ensure(STRINGIZE(lmi->first << "::" << rmi->first),
+                       bool(lmi->first == rmi->first) ==
+                       bool(llsd_equals(lmi->second, rmi->second)));
+            }
+        }
+
+        // Array cases
+        LLSD rarray;
+        rarray.append(1.0);
+        rarray.append(2);
+        rarray.append("3");
+        LLSD larray(rarray);
+        ensure("llsd_equals(equal arrays)", llsd_equals(larray, rarray));
+        rarray[2] = "4";
+        ensure("llsd_equals(different [2])", ! llsd_equals(larray, rarray));
+        rarray = larray;
+        rarray.append(LLSD::Date());
+        ensure("llsd_equals(longer right array)", ! llsd_equals(larray, rarray));
+        rarray = larray;
+        rarray.erase(2);
+        ensure("llsd_equals(shorter right array)", ! llsd_equals(larray, rarray));
+
+        // Map cases
+        LLSD rmap;
+        rmap["San Francisco"] = 65;
+        rmap["Phoenix"] = 92;
+        rmap["Boston"] = 77;
+        LLSD lmap(rmap);
+        ensure("llsd_equals(equal maps)", llsd_equals(lmap, rmap));
+        rmap["Boston"] = 80;
+        ensure("llsd_equals(different [\"Boston\"])", ! llsd_equals(lmap, rmap));
+        rmap = lmap;
+        rmap["Atlanta"] = 95;
+        ensure("llsd_equals(superset right map)", ! llsd_equals(lmap, rmap));
+        rmap = lmap;
+        lmap["Seattle"] = 72;
+        ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap));
+    }
 }
diff --git a/indra/test/lltut.cpp b/indra/test/lltut.cpp
index 201e174f9cf608289e75ee9c286a5adb1b8eb988..e4e0de1ff1d7696f13a46bf63535edc3114a0da3 100644
--- a/indra/test/lltut.cpp
+++ b/indra/test/lltut.cpp
@@ -76,9 +76,13 @@ namespace tut
 
 	void ensure_equals(const char* m, const LLSD& actual,
 		const LLSD& expected)
+    {
+        ensure_equals(std::string(m), actual, expected);
+    }
+
+	void ensure_equals(const std::string& msg, const LLSD& actual,
+		const LLSD& expected)
 	{
-		const std::string& msg = m ? m : "";
-		
 		ensure_equals(msg + " type", actual.type(), expected.type());
 		switch (actual.type())
 		{
@@ -128,7 +132,7 @@ namespace tut
 				{
 					ensure_equals(msg + " map keys", 
 						actual_iter->first, expected_iter->first);
-					ensure_equals((msg + "[" + actual_iter->first + "]").c_str(),
+					ensure_equals(msg + "[" + actual_iter->first + "]",
 						actual_iter->second, expected_iter->second);
 					++actual_iter;
 					++expected_iter;
@@ -141,7 +145,7 @@ namespace tut
 				
 				for(int i = 0; i < actual.size(); ++i)
 				{
-					ensure_equals((msg + llformat("[%d]", i)).c_str(),
+					ensure_equals(msg + llformat("[%d]", i),
 						actual[i], expected[i]);
 				}
 				return;
diff --git a/indra/test/lltut.h b/indra/test/lltut.h
index bbb437c3f9c638288767f94809c6a6a35b8e3c5c..6322753253fb7621fe6213529c02ec337d3d19ac 100644
--- a/indra/test/lltut.h
+++ b/indra/test/lltut.h
@@ -121,6 +121,9 @@ namespace tut
 
 	void ensure_equals(const char* msg,
 		const LLSD& actual, const LLSD& expected);
+
+	void ensure_equals(const std::string& msg,
+		const LLSD& actual, const LLSD& expected);
 	
 	void ensure_starts_with(const std::string& msg,
 		const std::string& actual, const std::string& expectedStart);
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index c2e0a11156efcaf97c272dad683e8b765caf1963..7dfe8f40b785ab0e48d10533a7cb24517b92de95 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -54,6 +54,11 @@
 #	include "ctype_workaround.h"
 #endif
 
+#ifndef LL_WINDOWS
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#endif
+
 namespace tut
 {
 	std::string sSourceDir;
@@ -235,6 +240,11 @@ void wouldHaveCrashed(const std::string& message)
 
 int main(int argc, char **argv)
 {
+	// The following line must be executed to initialize Google Mock
+	// (and Google Test) before running the tests.
+#ifndef LL_WINDOWS
+	::testing::InitGoogleMock(&argc, argv);
+#endif
 	LLError::initForApplication(".");
 	LLError::setFatalFunction(wouldHaveCrashed);
 	LLError::setDefaultLevel(LLError::LEVEL_ERROR);
diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt
index 789ead04fe9c531fc2ef0cd34b1e36c6d654bba7..53b981cccdebf88cea6d1c09e5daa42c7e94dd30 100644
--- a/indra/test_apps/llplugintest/CMakeLists.txt
+++ b/indra/test_apps/llplugintest/CMakeLists.txt
@@ -28,7 +28,7 @@ include_directories(
 
 if (DARWIN)
     include(CMakeFindFrameworks)
-    find_library(CARBON_LIBRARY Carbon)
+    find_library(COREFOUNDATION_LIBRARY CoreFoundation)
 endif (DARWIN)
 
 ### demo_plugin
@@ -136,7 +136,7 @@ endif (DARWIN)
 #    ${media_simple_test_SOURCE_FILES}
 #)
 #
-#add_dependencies(media_simple_test copy_win_libs)
+#add_dependencies(media_simple_test stage_third_party_libs)
 #
 #set_target_properties(media_simple_test
 #    PROPERTIES
@@ -177,7 +177,7 @@ endif (DARWIN)
 #)
 #
 #add_dependencies(media_plugin_test
-#  copy_win_libs
+#  stage_third_party_libs
 #  SLPlugin
 #  demo_media_plugin
 #  ${LLPLUGIN_LIBRARIES}
@@ -261,6 +261,7 @@ set(llmediaplugintest_SOURCE_FILES
 
 add_executable(llmediaplugintest
     WIN32
+    MACOSX_BUNDLE
     ${llmediaplugintest_SOURCE_FILES}
 )
 
@@ -280,11 +281,19 @@ target_link_libraries(llmediaplugintest
   ${PLUGIN_API_WINDOWS_LIBRARIES}
 )
 
+if (DARWIN)
+  # The testbed needs to use a couple of CoreFoundation calls now, to deal with being a bundled app.
+  target_link_libraries(llmediaplugintest
+    ${COREFOUNDATION_LIBRARY}
+  )
+endif (DARWIN)
+
 add_dependencies(llmediaplugintest
-  copy_win_libs
+  stage_third_party_libs
   SLPlugin
   media_plugin_quicktime
   media_plugin_webkit
+  media_plugin_example
   ${LLPLUGIN_LIBRARIES}
   ${LLMESSAGE_LIBRARIES}
   ${LLCOMMON_LIBRARIES}
@@ -300,43 +309,210 @@ endif (DARWIN OR LINUX)
 
 # Gather build products of the various dependencies into the build directory for the testbed.
 
+if (DARWIN)
+  # path inside the app bundle where we'll need to copy plugins and other related files
+  set(PLUGINS_DESTINATION_DIR
+    ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llmediaplugintest.app/Contents/Resources
+  )
+  
+  # create the Contents/Resources directory
+  add_custom_command(
+    TARGET llmediaplugintest POST_BUILD
+    COMMAND ${CMAKE_COMMAND}
+    ARGS
+      -E
+      make_directory
+      ${PLUGINS_DESTINATION_DIR}
+    COMMENT "Creating Resources directory in app bundle."
+  )
+
+  # copy the llcommon dylib and its dependencies to Contents/Resources.
+  get_target_property(BUILT_LLCOMMON llcommon LOCATION)
+  add_custom_command(TARGET llmediaplugintest POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON}  ${PLUGINS_DESTINATION_DIR}
+    DEPENDS ${BUILT_LLCOMMON}
+  )
+  # FIXME: these paths should come from somewhere reliable.  The canonical list seems to be in indra/newview/viewer_manifest.py
+  add_custom_command(TARGET llmediaplugintest POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.0.3.7.dylib  ${PLUGINS_DESTINATION_DIR}
+    DEPENDS ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.0.3.7.dylib
+  )
+  add_custom_command(TARGET llmediaplugintest POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.0.3.8.dylib  ${PLUGINS_DESTINATION_DIR}
+    DEPENDS ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.0.3.8.dylib
+  )
+  add_custom_command(TARGET llmediaplugintest POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libexpat.0.5.0.dylib  ${PLUGINS_DESTINATION_DIR}
+    DEPENDS ${ARCH_PREBUILT_DIRS_RELEASE}/libexpat.0.5.0.dylib
+  )
+else (DARWIN)
+  set(PLUGINS_DESTINATION_DIR
+    ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+  )
+endif (DARWIN)
+
 get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION)
 add_custom_command(TARGET llmediaplugintest POST_BUILD
-  COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN}  ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+  COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN}  ${PLUGINS_DESTINATION_DIR}
   DEPENDS ${BUILT_SLPLUGIN}
 )
 
 if (DARWIN OR WINDOWS)
   get_target_property(BUILT_WEBKIT_PLUGIN media_plugin_webkit LOCATION)
   add_custom_command(TARGET llmediaplugintest POST_BUILD
-    COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_WEBKIT_PLUGIN}  ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+    COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_WEBKIT_PLUGIN}  ${PLUGINS_DESTINATION_DIR}
     DEPENDS ${BUILT_WEBKIT_PLUGIN}
   )
 
   get_target_property(BUILT_QUICKTIME_PLUGIN media_plugin_quicktime LOCATION)
   add_custom_command(TARGET llmediaplugintest POST_BUILD
-    COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_QUICKTIME_PLUGIN}  ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+    COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_QUICKTIME_PLUGIN}  ${PLUGINS_DESTINATION_DIR}
     DEPENDS ${BUILT_QUICKTIME_PLUGIN}
   )
   
+  get_target_property(BUILT_EXAMPLE_PLUGIN media_plugin_example LOCATION)
+  add_custom_command(TARGET llmediaplugintest POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_EXAMPLE_PLUGIN}  ${PLUGINS_DESTINATION_DIR}
+    DEPENDS ${BUILT_EXAMPLE_PLUGIN}
+  )
+  
   # copy over bookmarks file if llmediaplugintest gets built
   get_target_property(BUILT_LLMEDIAPLUGINTEST llmediaplugintest LOCATION)
   add_custom_command(TARGET llmediaplugintest POST_BUILD
     COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${CMAKE_CURRENT_BINARY_DIR}/
     DEPENDS ${BUILT_LLMEDIAPLUGINTEST}
   )
-  # also copy it to the build configuration directory, which is what the mac wants...
+  # also copy it to the same place as SLPlugin, which is what the mac wants...
   add_custom_command(TARGET llmediaplugintest POST_BUILD
-    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${PLUGINS_DESTINATION_DIR}
     DEPENDS ${BUILT_LLMEDIAPLUGINTEST}
   )
 endif (DARWIN OR WINDOWS)
 
 if (DARWIN)
   add_custom_command(TARGET llmediaplugintest POST_BUILD
-    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib ${PLUGINS_DESTINATION_DIR}
     DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib
   )
 endif (DARWIN)
 
+if(WINDOWS)
+  #********************
+  # Plugin test library deploy
+  #
+  # Debug config runtime files required for the plugin test mule
+  set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
+  set(plugintest_debug_files
+    libeay32.dll
+    libglib-2.0-0.dll
+    libgmodule-2.0-0.dll
+    libgobject-2.0-0.dll
+    libgthread-2.0-0.dll
+    qtcored4.dll
+    qtguid4.dll
+    qtnetworkd4.dll
+    qtopengld4.dll
+    qtwebkitd4.dll
+    ssleay32.dll
+    )
+  copy_if_different(
+    ${plugintest_debug_src_dir}
+    "${CMAKE_CURRENT_BINARY_DIR}/Debug"
+    out_targets
+    ${plugintest_debug_files}
+    )
+  set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+  
+  # Debug config runtime files required for the plugin test mule (Qt image format plugins)
+  set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/imageformats")
+  set(plugintest_debug_files
+    qgifd4.dll
+    qicod4.dll
+    qjpegd4.dll
+    qmngd4.dll
+    qsvgd4.dll
+    qtiffd4.dll
+    )
+  copy_if_different(
+    ${plugintest_debug_src_dir}
+    "${CMAKE_CURRENT_BINARY_DIR}/Debug/imageformats"
+    out_targets
+    ${plugintest_debug_files}
+    )
+  set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+  
+  # Release & ReleaseDebInfo config runtime files required for the plugin test mule
+  set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
+  set(plugintest_release_files
+    libeay32.dll
+    libglib-2.0-0.dll
+    libgmodule-2.0-0.dll
+    libgobject-2.0-0.dll
+    libgthread-2.0-0.dll
+    qtcore4.dll
+    qtgui4.dll
+    qtnetwork4.dll
+    qtopengl4.dll
+    qtwebkit4.dll
+    ssleay32.dll
+    )
+  copy_if_different(
+    ${plugintest_release_src_dir}
+    "${CMAKE_CURRENT_BINARY_DIR}/Release"
+    out_targets
+    ${plugintest_release_files}
+    )
+  set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+  copy_if_different(
+    ${plugintest_release_src_dir}
+    "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo"
+    out_targets
+    ${plugintest_release_files}
+    )
+  set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+  # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins)
+  set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/imageformats")
+  set(plugintest_release_files
+    qgif4.dll
+    qico4.dll
+    qjpeg4.dll
+    qmng4.dll
+    qsvg4.dll
+    qtiff4.dll
+    )
+  copy_if_different(
+    ${plugintest_release_src_dir}
+    "${CMAKE_CURRENT_BINARY_DIR}/Release/imageformats"
+    out_targets
+    ${plugintest_release_files}
+    )
+  set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+  copy_if_different(
+    ${plugintest_release_src_dir}
+    "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/imageformats"
+    out_targets
+    ${plugintest_release_files}
+    )
+  set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+  copy_if_different(
+    "${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}"
+    "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
+    out_targets
+    llcommon.dll libapr-1.dll libaprutil-1.dll libapriconv-1.dll
+    )
+  set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+  add_custom_target(copy_plugintest_libs ALL
+    DEPENDS 
+      ${plugin_test_targets}
+      llcommon
+    )
+
+  add_dependencies(llmediaplugintest copy_plugintest_libs)
+
+endif(WINDOWS)
 
diff --git a/indra/test_apps/llplugintest/bookmarks.txt b/indra/test_apps/llplugintest/bookmarks.txt
index 796cc5d1b28feaadda6a154db144f719df7ca461..b8b83df38667abe008b2afaa9b0160c09c24b739 100644
--- a/indra/test_apps/llplugintest/bookmarks.txt
+++ b/indra/test_apps/llplugintest/bookmarks.txt
@@ -8,7 +8,15 @@
 (WK) Canvas Paint (DHTML version of MS Paint),http://www.canvaspaint.org
 (WK) DHTML Lemmings!,http://www.elizium.nu/scripts/lemmings/
 (WK) DHTML graphics demos,http://www.dhteumeuleu.com/
-(WK) Neat Javascript 3D,http://gyu.que.jp/jscloth/
+(WK) Shared paint app,http://colorillo.com/ac79?1l0q6cp
+(Flash) YouTube,http://youtube.com
+(Flash) Vimeo,http://www.vimeo.com/1778399
+(Flash) Simple whiteboard,http://www.imaginationcubed.com/
+(Flash) Dabble Board,http://www.dabbleboard.com/draw
+(Flash) Bubble Shooter game,http://www.wiicade.com/playGame.aspx?gameID=72&gameName=Bubble%20Shooter 
+(Flash) Pixlr photo editor,http://pixlr.com/editor/
+(Flash) Scribd,http://www.scribd.com/doc/14427744/Second-Life-Quickstart-Guide
+(Flash) MAME,http://yvern.com/fMAME/fMAME.html
 (QT) Local sample,file:///C|/Program Files/QuickTime/Sample.mov
 (QT) Movie - Watchmen Trailer,http://movies.apple.com/movies/wb/watchmen/watchmen-tlr2_480p.mov
 (QT) Movie - Transformers - Revenge of the Fallen,http://movies.apple.com/movies/paramount/transformers2/transformersrevengeofthefallen-tlr1_h.320.mov
@@ -26,3 +34,4 @@
 (QT) Movie - The Informers,http://movies.apple.com/movies/independent/theinformers/theinformers_h.320.mov
 (QT) Animated GIF,http://upload.wikimedia.org/wikipedia/commons/4/44/Optical.greysquares.arp-animated.gif
 (QT) Apple Text Descriptors,http://ubrowser.com/tmp/apple_text.txt
+(EX) Example Plugin,example://blah
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp
index 7869763302f30d5fa67c460e7261f2a8209897c8..d987915bb8b0a7772a83591f6aeaa0ecd2e4fc49 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.cpp
+++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp
@@ -44,6 +44,7 @@
 
 #if __APPLE__
 	#include <GLUT/glut.h>
+	#include <CoreFoundation/CoreFoundation.h>
 #else
 	#define FREEGLUT_STATIC
 	#include "GL/freeglut.h"
@@ -274,8 +275,6 @@ void LLMediaPluginTest::bindTexture(GLuint texture, GLint row_length, GLint alig
 {
 	glEnable( GL_TEXTURE_2D );
 	
-//	std::cerr << "binding texture " << texture << std::endl;
-	
 	glBindTexture( GL_TEXTURE_2D, texture );
 	glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length );
 	glPixelStorei( GL_UNPACK_ALIGNMENT, alignment );
@@ -407,7 +406,7 @@ void LLMediaPluginTest::draw( int draw_type )
 			// only bother with pick if we have something to render
 			// Actually, we need to pick even if we're not ready to render.  
 			// Otherwise you can't select and remove a panel which has gone bad.
-//			if ( mMediaPanels[ panel ]->mReadyToRender )
+			//if ( mMediaPanels[ panel ]->mReadyToRender )
 			{
 				glMatrixMode( GL_TEXTURE );
 				glPushMatrix();
@@ -618,10 +617,10 @@ void LLMediaPluginTest::idle()
 	if ( mSelectedPanel )
 	{
 		// set volume based on slider if we have time media
-//		if ( mGluiMediaTimeControlWindowFlag )
-//		{
-//			mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
-//		};
+		//if ( mGluiMediaTimeControlWindowFlag )
+		//{
+		//	mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
+		//};
 
 		// NOTE: it is absurd that we need cache the state of GLUI controls
 		//       but enabling/disabling controls drags framerate from 500+
@@ -1187,7 +1186,7 @@ void LLMediaPluginTest::mouseButton( int button, int state, int x, int y )
 			windowPosToTexturePos( x, y, media_x, media_y, id );
 
 			if ( mSelectedPanel )
-				mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, media_x, media_y, 0 );
+				mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, 0, media_x, media_y, 0 );
 		}
 		else
 		if ( state == GLUT_UP )
@@ -1203,7 +1202,7 @@ void LLMediaPluginTest::mouseButton( int button, int state, int x, int y )
 				selectPanelById( id );
 
 				if ( mSelectedPanel )
-					mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, media_x, media_y, 0 );
+					mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, 0, media_x, media_y, 0 );
 			};
 		};
 	};
@@ -1217,7 +1216,7 @@ void LLMediaPluginTest::mousePassive( int x, int y )
 	windowPosToTexturePos( x, y, media_x, media_y, id );
 
 	if ( mSelectedPanel )
-		mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, media_x, media_y, 0 );
+		mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1228,7 +1227,7 @@ void LLMediaPluginTest::mouseMove( int x, int y )
 	windowPosToTexturePos( x, y, media_x, media_y, id );
 
 	if ( mSelectedPanel )
-		mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, media_x, media_y, 0 );
+		mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1460,6 +1459,9 @@ std::string LLMediaPluginTest::mimeTypeFromUrl( std::string& url )
 	else
 	if ( url.find( ".txt" ) != std::string::npos )	// Apple Text descriptors
 		mime_type = "video/quicktime";
+	else
+	if ( url.find( "example://" ) != std::string::npos )	// Example plugin
+		mime_type = "example/example";
 
 	return mime_type;
 }
@@ -1484,6 +1486,9 @@ std::string LLMediaPluginTest::pluginNameFromMimeType( std::string& mime_type )
 	else
 	if ( mime_type == "text/html" )
 		plugin_name = "media_plugin_webkit.dll";
+	else
+	if ( mime_type == "example/example" )
+		plugin_name = "media_plugin_example.dll";
 
 #elif LL_LINUX
 	std::string plugin_name( "libmedia_plugin_null.so" );
@@ -1796,7 +1801,7 @@ void LLMediaPluginTest::getRandomMediaSize( int& width, int& height, std::string
 
 	// adjust this random size if it's a browser so we get 
 	// a more useful size for testing.. 
-	if ( mime_type == "text/html" )
+	if ( mime_type == "text/html" || mime_type == "example/example"  )
 	{
 		width = ( ( rand() % 100 ) + 100 ) * 4;
 		height = ( width * ( ( rand() % 400 ) + 1000 ) ) / 1000;
@@ -2007,6 +2012,11 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e
 			std::cerr <<  "Media event:  MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << std::endl;
 		break;
 
+		case MEDIA_EVENT_NAME_CHANGED:
+			std::cerr <<  "Media event:  MEDIA_EVENT_NAME_CHANGED, new name is: " << self->getMediaName() << std::endl;
+			glutSetWindowTitle( self->getMediaName().c_str() );
+		break;
+
 		case MEDIA_EVENT_LOCATION_CHANGED:
 		{
 			std::cerr <<  "Media event:  MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << std::endl;
@@ -2033,6 +2043,10 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e
 		case MEDIA_EVENT_PLUGIN_FAILED:
 			std::cerr <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED" << std::endl;
 		break;
+
+		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+			std::cerr <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << std::endl;
+		break;
 	}
 }
 
@@ -2107,6 +2121,25 @@ void glutMouseButton( int button, int state, int x, int y )
 //
 int main( int argc, char* argv[] )
 {
+#if LL_DARWIN
+	// Set the current working directory to <application bundle>/Contents/Resources/
+	CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
+	if(resources_url != NULL)
+	{
+		CFStringRef resources_string = CFURLCopyFileSystemPath(resources_url, kCFURLPOSIXPathStyle);
+		CFRelease(resources_url);
+		if(resources_string != NULL)
+		{
+			char buffer[PATH_MAX] = "";
+			if(CFStringGetCString(resources_string, buffer, sizeof(buffer), kCFStringEncodingUTF8))
+			{
+				chdir(buffer);
+			}
+			CFRelease(resources_string);
+		}
+	}
+#endif
+
 	glutInit( &argc, argv );
 	glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
 
diff --git a/indra/viewer_components/CMakeLists.txt b/indra/viewer_components/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c95c854b7c60b4108819410df5ea9cdded549c4d
--- /dev/null
+++ b/indra/viewer_components/CMakeLists.txt
@@ -0,0 +1,5 @@
+# -*- cmake -*-
+
+add_subdirectory(login)
+add_subdirectory(eventhost)
+
diff --git a/indra/viewer_components/login/CMakeLists.txt b/indra/viewer_components/login/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fb65779eb7320a1866b4f9cb1756b7a8411a2bd5
--- /dev/null
+++ b/indra/viewer_components/login/CMakeLists.txt
@@ -0,0 +1,56 @@
+# -*- cmake -*-
+
+project(login)
+
+include(00-Common)
+include(LLAddBuildTest)
+include(LLCommon)
+include(LLMath)
+include(LLXML)
+include(Pth)
+
+include_directories(
+    ${LLCOMMON_INCLUDE_DIRS}
+    ${LLMATH_INCLUDE_DIRS}
+    ${LLXML_INCLUDE_DIRS}
+    ${PTH_INCLUDE_DIRS}
+    )
+
+set(login_SOURCE_FILES
+    lllogin.cpp
+    )
+
+set(login_HEADER_FILES
+    lllogin.h
+    )
+
+set_source_files_properties(${login_HEADER_FILES}
+                            PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND 
+    login_SOURCE_FILES 
+    ${login_HEADER_FILES} 
+    )
+
+add_library(lllogin 
+            ${login_SOURCE_FILES}
+            )
+
+target_link_libraries(lllogin
+    ${LLCOMMON_LIBRARIES}
+    ${LLMATH_LIBRARIES}
+    ${LLXML_LIBRARIES}
+    ${PTH_LIBRARIES}
+    )
+
+SET(lllogin_TEST_SOURCE_FILES
+    lllogin.cpp
+    )
+
+set_source_files_properties(
+  lllogin.cpp
+  PROPERTIES
+    LL_TEST_ADDITIONAL_LIBRARIES "${PTH_LIBRARIES}"
+  )
+
+LL_ADD_PROJECT_UNIT_TESTS(lllogin "${lllogin_TEST_SOURCE_FILES}")
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a30315b9a8c7c30b110f4c3f78bf84c1fe942f8
--- /dev/null
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -0,0 +1,374 @@
+/** 
+ * @file lllogin.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include <boost/coroutine/coroutine.hpp>
+#include "linden_common.h"
+#include "llsd.h"
+#include "llsdutil.h"
+
+/*==========================================================================*|
+#ifdef LL_WINDOWS
+	// non-virtual destructor warning, boost::statechart does this intentionally.
+	#pragma warning (disable : 4265) 
+#endif
+|*==========================================================================*/
+
+#include "lllogin.h"
+
+#include <boost/bind.hpp>
+
+#include "llcoros.h"
+#include "llevents.h"
+#include "lleventfilter.h"
+#include "lleventcoro.h"
+
+//*********************
+// LLLogin
+// *NOTE:Mani - Is this Impl needed now that the state machine runs the show?
+class LLLogin::Impl
+{
+public:
+    Impl():
+		mPump("login", true) // Create the module's event pump with a tweaked (unique) name.
+    {
+        mValidAuthResponse["status"]        = LLSD();
+        mValidAuthResponse["errorcode"]     = LLSD();
+        mValidAuthResponse["error"]         = LLSD();
+        mValidAuthResponse["transfer_rate"] = LLSD();
+    }
+
+    void connect(const std::string& uri, const LLSD& credentials);
+    void disconnect();
+	LLEventPump& getEventPump() { return mPump; }
+
+private:
+	void sendProgressEvent(const std::string& state, const std::string& change,
+						   const LLSD& data = LLSD())
+	{
+		LLSD status_data;
+		status_data["state"] = state;
+		status_data["change"] = change;
+		status_data["progress"] = 0.0f;
+
+		if(mAuthResponse.has("transfer_rate"))
+		{
+			status_data["transfer_rate"] = mAuthResponse["transfer_rate"];
+		}
+
+		if(data.isDefined())
+		{
+			status_data["data"] = data;
+		}
+
+		mPump.post(status_data);
+	}
+
+    LLSD validateResponse(const std::string& pumpName, const LLSD& response)
+    {
+        // Validate the response. If we don't recognize it, things
+        // could get ugly.
+        std::string mismatch(llsd_matches(mValidAuthResponse, response));
+        if (! mismatch.empty())
+        {
+            LL_ERRS("LLLogin") << "Received unrecognized event (" << mismatch << ") on "
+                               << pumpName << "pump: " << response
+                               << LL_ENDL;
+            return LLSD();
+        }
+
+        return response;
+    }
+
+    // In a coroutine's top-level function args, do NOT NOT NOT accept
+    // references (const or otherwise) to anything but the self argument! Pass
+    // by value only!
+    void login_(LLCoros::self& self, std::string uri, LLSD credentials);
+
+    LLEventStream mPump;
+	LLSD mAuthResponse, mValidAuthResponse;
+};
+
+void LLLogin::Impl::connect(const std::string& uri, const LLSD& credentials)
+{
+    // Launch a coroutine with our login_() method. Run the coroutine until
+    // its first wait; at that point, return here.
+    std::string coroname = 
+        LLCoros::instance().launch("LLLogin::Impl::login_",
+                                   boost::bind(&Impl::login_, this, _1, uri, credentials));
+}
+
+void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credentials)
+{
+    LL_INFOS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName(self)
+                        << " with uri '" << uri << "', credentials " << credentials << LL_ENDL;
+    // Arriving in SRVRequest state
+    LLEventStream replyPump("reply", true);
+    // Should be an array of one or more uri strings.
+    LLSD rewrittenURIs;
+    {
+        LLEventTimeout filter(replyPump);
+        sendProgressEvent("offline", "srvrequest");
+
+        // Request SRV record.
+        LL_INFOS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL;
+
+        // *NOTE:Mani - Completely arbitrary timeout value for SRV request.
+        filter.errorAfter(5, "SRV Request timed out!");
+
+        // Make request
+        LLSD request;
+        request["op"] = "rewriteURI";
+        request["uri"] = uri;
+        request["reply"] = replyPump.getName();
+        rewrittenURIs = postAndWait(self, request, "LLAres", filter);
+    } // we no longer need the filter
+
+    LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
+
+    // Loop through the rewrittenURIs, counting attempts along the way.
+    // Because of possible redirect responses, we may make more than one
+    // attempt per rewrittenURIs entry.
+    LLSD::Integer attempts = 0;
+    for (LLSD::array_const_iterator urit(rewrittenURIs.beginArray()),
+             urend(rewrittenURIs.endArray());
+         urit != urend; ++urit)
+    {
+        LLSD request(credentials);
+        request["reply"] = replyPump.getName();
+        request["uri"] = *urit;
+        std::string status;
+
+        // Loop back to here if login attempt redirects to a different
+        // request["uri"]
+        for (;;)
+        {
+            ++attempts;
+            LLSD progress_data;
+            progress_data["attempt"] = attempts;
+            progress_data["request"] = request;
+            sendProgressEvent("offline", "authenticating", progress_data);
+
+            // We expect zero or more "Downloading" status events, followed by
+            // exactly one event with some other status. Use postAndWait() the
+            // first time, because -- at least in unit-test land -- it's
+            // possible for the reply to arrive before the post() call
+            // returns. Subsequent responses, of course, must be awaited
+            // without posting again.
+            for (mAuthResponse = validateResponse(replyPump.getName(),
+                                     postAndWait(self, request, xmlrpcPump, replyPump, "reply"));
+                 mAuthResponse["status"].asString() == "Downloading";
+                 mAuthResponse = validateResponse(replyPump.getName(),
+                                     waitForEventOn(self, replyPump)))
+            {
+                // Still Downloading -- send progress update.
+                sendProgressEvent("offline", "downloading");
+            }
+            status = mAuthResponse["status"].asString();
+
+            // Okay, we've received our final status event for this
+            // request. Unless we got a redirect response, break the retry
+            // loop for the current rewrittenURIs entry.
+            if (! (status == "Complete" &&
+                   mAuthResponse["responses"]["login"].asString() == "indeterminate"))
+            {
+                break;
+            }
+
+            // Here the login service at the current URI is redirecting us
+            // to some other URI ("indeterminate" -- why not "redirect"?).
+            // The response should contain another uri to try, with its
+            // own auth method.
+            request["uri"] = mAuthResponse["next_url"];
+            request["method"] = mAuthResponse["next_method"];
+        } // loop back to try the redirected URI
+
+        // Here we're done with redirects for the current rewrittenURIs
+        // entry.
+        if (status == "Complete")
+        {
+            // StatusComplete does not imply auth success. Check the
+            // actual outcome of the request. We've already handled the
+            // "indeterminate" case in the loop above.
+            if (mAuthResponse["responses"]["login"].asString() == "true")
+            {
+                sendProgressEvent("online", "connect", mAuthResponse["responses"]);
+            }
+            else
+            {
+                sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
+            }
+            return;             // Done!
+        }
+        // If we don't recognize status at all, trouble
+        if (! (status == "CURLError"
+               || status == "XMLRPCError"
+               || status == "OtherError"))
+        {
+            LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: "
+                               << mAuthResponse << LL_ENDL;
+            return;
+        }
+
+        // Here status IS one of the errors tested above.
+    } // Retry if there are any more rewrittenURIs.
+
+    // Here we got through all the rewrittenURIs without succeeding. Tell
+    // caller this didn't work out so well. Of course, the only failure data
+    // we can reasonably show are from the last of the rewrittenURIs.
+    sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
+}
+
+void LLLogin::Impl::disconnect()
+{
+    sendProgressEvent("offline", "disconnect");
+}
+
+//*********************
+// LLLogin
+LLLogin::LLLogin() :
+	mImpl(new LLLogin::Impl())
+{
+}
+
+LLLogin::~LLLogin()
+{
+}
+
+void LLLogin::connect(const std::string& uri, const LLSD& credentials)
+{
+	mImpl->connect(uri, credentials);
+}
+
+
+void LLLogin::disconnect()
+{
+	mImpl->disconnect();
+}
+
+LLEventPump& LLLogin::getEventPump()
+{
+	return mImpl->getEventPump();
+}
+
+// The following is the list of important functions that happen in the 
+// current login process that we want to move to this login module.
+
+// The list associates to event with the original idle_startup() 'STATE'.
+
+// Rewrite URIs
+ // State_LOGIN_AUTH_INIT
+// Given a vector of login uris (usually just one), perform a dns lookup for the 
+// SRV record from each URI. I think this is used to distribute login requests to 
+// a single URI to multiple hosts.
+// This is currently a synchronous action. (See LLSRV::rewriteURI() implementation)
+// On dns lookup error the output uris == the input uris.
+//
+// Input: A vector of login uris
+// Output: A vector of login uris
+//
+// Code:
+// std::vector<std::string> uris;
+// LLViewerLogin::getInstance()->getLoginURIs(uris);
+// std::vector<std::string>::const_iterator iter, end;
+// for (iter = uris.begin(), end = uris.end(); iter != end; ++iter)
+// {
+//	std::vector<std::string> rewritten;
+//	rewritten = LLSRV::rewriteURI(*iter);
+//	sAuthUris.insert(sAuthUris.end(),
+//					 rewritten.begin(), rewritten.end());
+// }
+// sAuthUriNum = 0;
+
+// Authenticate 
+// STATE_LOGIN_AUTHENTICATE
+// Connect to the login server, presumably login.cgi, requesting the login 
+// and a slew of related initial connection information.
+// This is an asynch action. The final response, whether success or error
+// is handled by STATE_LOGIN_PROCESS_REPONSE.
+// There is no immediate error or output from this call.
+// 
+// Input: 
+//  URI
+//  Credentials (first, last, password)
+//  Start location
+//  Bool Flags:
+//    skip optional update
+//    accept terms of service
+//    accept critical message
+//  Last exec event. (crash state of previous session)
+//  requested optional data (inventory skel, initial outfit, etc.)
+//  local mac address
+//  viewer serial no. (md5 checksum?)
+
+//sAuthUriNum = llclamp(sAuthUriNum, 0, (S32)sAuthUris.size()-1);
+//LLUserAuth::getInstance()->authenticate(
+//	sAuthUris[sAuthUriNum],
+//	auth_method,
+//	firstname,
+//	lastname,			
+//	password, // web_login_key,
+//	start.str(),
+//	gSkipOptionalUpdate,
+//	gAcceptTOS,
+//	gAcceptCriticalMessage,
+//	gLastExecEvent,
+//	requested_options,
+//	hashed_mac_string,
+//	LLAppViewer::instance()->getSerialNumber());
+
+//
+// Download the Response
+// STATE_LOGIN_NO_REPONSE_YET and STATE_LOGIN_DOWNLOADING
+// I had assumed that this was default behavior of the message system. However...
+// During login, the message system is checked only by these two states in idle_startup().
+// I guess this avoids the overhead of checking network messages for those login states
+// that don't need to do so, but geez!
+// There are two states to do this one function just to update the login
+// status text from 'Logging In...' to 'Downloading...'
+// 
+
+//
+// Handle Login Response
+// STATE_LOGIN_PROCESS_RESPONSE
+// 
+// This state handle the result of the request to login. There is a metric ton of
+// code in this case. This state will transition to:
+// STATE_WORLD_INIT, on success.
+// STATE_AUTHENTICATE, on failure.
+// STATE_UPDATE_CHECK, to handle user during login interaction like TOS display.
+//
+// Much of the code in this case belongs on the viewer side of the fence and not in login. 
+// Login should probably return with a couple of events, success and failure.
+// Failure conditions can be specified in the events data pacet to allow the viewer 
+// to re-engauge login as is appropriate. (Or should there be multiple failure messages?)
+// Success is returned with the data requested from the login. According to OGP specs 
+// there may be intermediate steps before reaching this result in future login 
+// implementations.
diff --git a/indra/viewer_components/login/lllogin.h b/indra/viewer_components/login/lllogin.h
new file mode 100644
index 0000000000000000000000000000000000000000..0598b4e45724c3386b6bfb053e29ef966b0e34bc
--- /dev/null
+++ b/indra/viewer_components/login/lllogin.h
@@ -0,0 +1,133 @@
+/** 
+ * @file lllogin.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLLOGIN_H
+#define LL_LLLOGIN_H
+
+#include <boost/scoped_ptr.hpp>
+
+class LLSD;
+class LLEventPump;
+
+/**
+ * @class LLLogin
+ * @brief Class to encapsulate the action and state of grid login.
+ */
+class LLLogin
+{
+public:
+	LLLogin();
+	~LLLogin();
+
+	/** 
+	 * Make a connection to a grid.
+	 * @param uri The 'well known and published' authentication URL.
+	 * @param credentials LLSD data that contians the credentials.
+	 * *NOTE:Mani The credential data can vary depending upon the authentication
+	 * method used. The current interface matches the values passed to
+	 * the XMLRPC login request.
+	 {
+		method			:	string, 
+		first			:	string,
+		last			:	string,
+		passwd			:	string,
+		start			:	string,
+		skipoptional	:	bool,
+		agree_to_tos	:	bool,
+		read_critical	:	bool,
+		last_exec_event	:	int,
+		version			:	string,
+		channel			:	string,
+		mac				:	string,
+		id0				:	string,
+		options			:   [ strings ]
+	 }
+	 
+	 */
+	void connect(const std::string& uri, const LLSD& credentials);
+	
+    /** 
+	 * Disconnect from a the current connection.
+	 */
+	void disconnect();
+
+    /** 
+	 * Retrieve the event pump from this login class.
+	 */
+	LLEventPump& getEventPump();
+
+	/*
+	Event API
+
+	LLLogin will issue multiple events to it pump to indicate the 
+	progression of states through login. The most important 
+	states are "offline" and "online" which indicate auth failure 
+	and auth success respectively.
+
+	pump: login (tweaked)
+	These are the events posted to the 'login' 
+	event pump from the login module.
+	{
+		state		:	string, // See below for the list of states.
+		progress	:   real // for progress bar.
+		data		:   LLSD // Dependent upon state.
+	}
+	
+	States for method 'login_to_simulator'
+	offline - set initially state and upon failure. data is the server response.
+	srvrequest - upon uri rewrite request. no data.
+	authenticating - upon auth request. data, 'attempt' number and 'request' llsd.
+	downloading - upon ack from auth server, before completion. no data
+	online - upon auth success. data is server response.
+
+
+	Dependencies:
+	pump: LLAres 
+	LLLogin makes a request for a SRV record from the uri provided by the connect method.
+	The following event pump should exist to service that request.
+	pump name: LLAres
+	request = {
+		op : "rewriteURI"
+		uri : string
+		reply : string
+
+	pump: LLXMLRPCListener
+	The request merely passes the credentials LLSD along, with one additional 
+	member, 'reply', which is the string name of the event pump to reply on. 
+	
+	*/
+
+private:
+	class Impl;
+	boost::scoped_ptr<Impl> mImpl;
+};
+
+#endif // LL_LLLOGIN_H
diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a8ae2883d54ddcd13899e2d4a7bdc6284c46f686
--- /dev/null
+++ b/indra/viewer_components/login/tests/lllogin_test.cpp
@@ -0,0 +1,417 @@
+/**
+ * @file   lllogin_test.cpp
+ * @author Mark Palange
+ * @date   2009-02-26
+ * @brief  Tests of lllogin.cpp.
+ * 
+ * $LicenseInfo:firstyear=2009&license=internal$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "../lllogin.h"
+// STL headers
+// std headers
+#include <iostream>
+// external library headers
+// other Linden headers
+#include "llsd.h"
+#include "../../../test/lltut.h"
+//#define DEBUG_ON
+#include "../../../test/debug.h"
+#include "llevents.h"
+#include "stringize.h"
+
+/*****************************************************************************
+*   Helper classes
+*****************************************************************************/
+// This is a listener to receive results from lllogin.
+class LoginListener: public LLEventTrackable
+{
+	std::string mName;
+	LLSD mLastEvent;
+    Debug mDebug;
+public:
+	LoginListener(const std::string& name) : 
+		mName(name),
+        mDebug(stringize(*this))
+	{}
+
+	bool call(const LLSD& event)
+	{
+		mDebug(STRINGIZE("LoginListener called!: " << event));
+		mLastEvent = event;
+		return false;
+	}
+
+    LLBoundListener listenTo(LLEventPump& pump)
+    {
+        return pump.listen(mName, boost::bind(&LoginListener::call, this, _1));
+	}
+
+	LLSD lastEvent() const { return mLastEvent; }
+
+    friend std::ostream& operator<<(std::ostream& out, const LoginListener& listener)
+    {
+        return out << "LoginListener(" << listener.mName << ')';
+    }
+};
+
+class LLAresListener: public LLEventTrackable
+{
+	std::string mName;
+	LLSD mEvent;
+	bool mImmediateResponse;
+	bool mMultipleURIResponse;
+    Debug mDebug;
+	
+public:
+	LLAresListener(const std::string& name, 
+				   bool i = false,
+				   bool m = false
+				   ) : 
+		mName(name),
+		mImmediateResponse(i),
+		mMultipleURIResponse(m),
+        mDebug(stringize(*this))
+	{}
+
+	bool handle_event(const LLSD& event)
+	{
+		mDebug(STRINGIZE("LLAresListener called!: " << event));
+		mEvent = event;
+		if(mImmediateResponse)
+		{
+			sendReply();
+		}
+		return false;
+	}
+
+	void sendReply()
+	{
+		if(mEvent["op"].asString() == "rewriteURI")
+		{
+			LLSD result;
+			if(mMultipleURIResponse)
+			{
+				result.append(LLSD("login.foo.com"));
+			}
+			result.append(mEvent["uri"]);
+			LLEventPumps::instance().obtain(mEvent["reply"]).post(result);
+		}
+	}
+
+	LLBoundListener listenTo(LLEventPump& pump)
+    {
+        return pump.listen(mName, boost::bind(&LLAresListener::handle_event, this, _1));
+	}
+
+    friend std::ostream& operator<<(std::ostream& out, const LLAresListener& listener)
+    {
+        return out << "LLAresListener(" << listener.mName << ')';
+    }
+};
+
+class LLXMLRPCListener: public LLEventTrackable
+{
+	std::string mName;
+	LLSD mEvent;
+	bool mImmediateResponse;
+	LLSD mResponse;
+    Debug mDebug;
+
+public:
+	LLXMLRPCListener(const std::string& name, 
+					 bool i = false,
+					 const LLSD& response = LLSD()
+					 ) : 
+		mName(name),
+		mImmediateResponse(i),
+		mResponse(response),
+        mDebug(stringize(*this))
+	{
+		if(mResponse.isUndefined())
+		{
+			mResponse["status"] = "Complete"; // StatusComplete
+			mResponse["errorcode"] = 0;
+			mResponse["error"] = "dummy response";
+			mResponse["transfer_rate"] = 0;
+			mResponse["responses"]["login"] = true;
+		}
+	}
+
+	void setResponse(const LLSD& r) 
+	{ 
+		mResponse = r; 
+	}
+
+	bool handle_event(const LLSD& event)
+	{
+		mDebug(STRINGIZE("LLXMLRPCListener called!: " << event));
+		mEvent = event;
+		if(mImmediateResponse)
+		{
+			sendReply();
+		}
+		return false;
+	}
+
+	void sendReply()
+	{
+		LLEventPumps::instance().obtain(mEvent["reply"]).post(mResponse);
+	}
+
+	LLBoundListener listenTo(LLEventPump& pump)
+    {
+        return pump.listen(mName, boost::bind(&LLXMLRPCListener::handle_event, this, _1));
+	}
+
+    friend std::ostream& operator<<(std::ostream& out, const LLXMLRPCListener& listener)
+    {
+        return out << "LLXMLRPCListener(" << listener.mName << ')';
+    }
+};
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct llviewerlogin_data
+    {
+		llviewerlogin_data() :
+            pumps(LLEventPumps::instance())
+		{}
+		LLEventPumps& pumps;
+	};
+
+    typedef test_group<llviewerlogin_data> llviewerlogin_group;
+    typedef llviewerlogin_group::object llviewerlogin_object;
+    llviewerlogin_group llviewerlogingrp("llviewerlogin");
+
+    template<> template<>
+    void llviewerlogin_object::test<1>()
+    {
+        DEBUG;
+		// Testing login with immediate repsonses from Ares and XMLPRC
+		// The response from both requests will come before the post request exits.
+		// This tests an edge case of the login state handling.
+		LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+		LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
+
+		bool respond_immediately = true;
+		// Have 'dummy ares' repsond immediately. 
+		LLAresListener dummyLLAres("dummy_llares", respond_immediately);
+		dummyLLAres.listenTo(llaresPump);
+
+		// Have dummy XMLRPC respond immediately.
+		LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc", respond_immediately);
+		dummyXMLRPC.listenTo(xmlrpcPump);
+
+		LLLogin login;
+
+		LoginListener listener("test_ear");
+		listener.listenTo(login.getEventPump());
+
+		LLSD credentials;
+		credentials["first"] = "foo";
+		credentials["last"] = "bar";
+		credentials["passwd"] = "secret";
+
+		login.connect("login.bar.com", credentials);
+
+		ensure_equals("Online state", listener.lastEvent()["state"].asString(), "online");
+	}
+
+    template<> template<>
+    void llviewerlogin_object::test<2>()
+    {
+        DEBUG;
+		// Tests a successful login in with delayed responses. 
+		// Also includes 'failure' that cause the login module
+		// To re-attempt connection, once from a basic failure
+		// and once from the 'indeterminate' response.
+
+		set_test_name("LLLogin multiple srv uris w/ success");
+
+		// Testing normal login procedure.
+		LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+		LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
+
+		bool respond_immediately = false;
+		bool multiple_addresses = true;
+		LLAresListener dummyLLAres("dummy_llares", respond_immediately, multiple_addresses);
+		dummyLLAres.listenTo(llaresPump);
+
+		LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc");
+		dummyXMLRPC.listenTo(xmlrpcPump);
+
+		LLLogin login;
+
+		LoginListener listener("test_ear");
+		listener.listenTo(login.getEventPump());
+
+		LLSD credentials;
+		credentials["first"] = "foo";
+		credentials["last"] = "bar";
+		credentials["passwd"] = "secret";
+
+		login.connect("login.bar.com", credentials);
+
+		ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); 
+
+		dummyLLAres.sendReply();
+
+		// Test Authenticating State prior to first response.
+		ensure_equals("Auth state 1", listener.lastEvent()["change"].asString(), "authenticating"); 
+		ensure_equals("Attempt 1", listener.lastEvent()["data"]["attempt"].asInteger(), 1); 
+		ensure_equals("URI 1", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.foo.com"); 
+
+		// First send emulated LLXMLRPCListener failure,
+		// this should return login to the authenticating step and increase the attempt 
+		// count.
+		LLSD data;
+		data["status"] = "OtherError"; 
+		data["errorcode"] = 0;
+		data["error"] = "dummy response";
+		data["transfer_rate"] = 0;
+		dummyXMLRPC.setResponse(data);
+		dummyXMLRPC.sendReply();
+
+		ensure_equals("Fail back to authenticate 1", listener.lastEvent()["change"].asString(), "authenticating"); 
+		ensure_equals("Attempt 2", listener.lastEvent()["data"]["attempt"].asInteger(), 2); 
+		ensure_equals("URI 2", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.bar.com"); 
+
+		// Now send the 'indeterminate' response.
+		data.clear();
+		data["status"] = "Complete"; // StatusComplete
+		data["errorcode"] = 0;
+		data["error"] = "dummy response";
+		data["transfer_rate"] = 0;
+		data["responses"]["login"] = "indeterminate";
+		data["next_url"] = "login.indeterminate.com";			
+		data["next_method"] = "test_login_method"; 			
+		dummyXMLRPC.setResponse(data);
+		dummyXMLRPC.sendReply();
+
+		ensure_equals("Fail back to authenticate 2", listener.lastEvent()["change"].asString(), "authenticating"); 
+		ensure_equals("Attempt 3", listener.lastEvent()["data"]["attempt"].asInteger(), 3); 
+		ensure_equals("URI 3", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.indeterminate.com"); 
+
+		// Finally let the auth succeed.
+		data.clear();
+		data["status"] = "Complete"; // StatusComplete
+		data["errorcode"] = 0;
+		data["error"] = "dummy response";
+		data["transfer_rate"] = 0;
+		data["responses"]["login"] = "true";
+		dummyXMLRPC.setResponse(data);
+		dummyXMLRPC.sendReply();
+
+		ensure_equals("Success state", listener.lastEvent()["state"].asString(), "online");
+
+		login.disconnect();
+
+		ensure_equals("Disconnected state", listener.lastEvent()["state"].asString(), "offline");
+	}
+
+    template<> template<>
+    void llviewerlogin_object::test<3>()
+    {
+        DEBUG;
+		// Test completed response, that fails to login.
+		set_test_name("LLLogin valid response, failure (eg. bad credentials)");
+
+		// Testing normal login procedure.
+		LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+		LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
+
+		LLAresListener dummyLLAres("dummy_llares");
+		dummyLLAres.listenTo(llaresPump);
+
+		LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc");
+		dummyXMLRPC.listenTo(xmlrpcPump);
+
+		LLLogin login;
+		LoginListener listener("test_ear");
+		listener.listenTo(login.getEventPump());
+
+		LLSD credentials;
+		credentials["first"] = "who";
+		credentials["last"] = "what";
+		credentials["passwd"] = "badpasswd";
+
+		login.connect("login.bar.com", credentials);
+
+		ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); 
+
+		dummyLLAres.sendReply();
+
+		ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); 
+
+		// Send the failed auth request reponse
+		LLSD data;
+		data["status"] = "Complete";
+		data["errorcode"] = 0;
+		data["error"] = "dummy response";
+		data["transfer_rate"] = 0;
+		data["responses"]["login"] = "false";
+		dummyXMLRPC.setResponse(data);
+		dummyXMLRPC.sendReply();
+
+		ensure_equals("Failed to offline", listener.lastEvent()["state"].asString(), "offline");
+	}
+
+    template<> template<>
+    void llviewerlogin_object::test<4>()
+    {
+        DEBUG;
+		// Test incomplete response, that end the attempt.
+		set_test_name("LLLogin valid response, failure (eg. bad credentials)");
+
+		// Testing normal login procedure.
+		LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+		LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
+
+		LLAresListener dummyLLAres("dummy_llares");
+		dummyLLAres.listenTo(llaresPump);
+
+		LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc");
+		dummyXMLRPC.listenTo(xmlrpcPump);
+
+		LLLogin login;
+		LoginListener listener("test_ear");
+		listener.listenTo(login.getEventPump());
+
+		LLSD credentials;
+		credentials["first"] = "these";
+		credentials["last"] = "don't";
+		credentials["passwd"] = "matter";
+
+		login.connect("login.bar.com", credentials);
+
+		ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); 
+
+		dummyLLAres.sendReply();
+
+		ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); 
+
+		// Send the failed auth request reponse
+		LLSD data;
+		data["status"] = "OtherError";
+		data["errorcode"] = 0;
+		data["error"] = "dummy response";
+		data["transfer_rate"] = 0;
+		dummyXMLRPC.setResponse(data);
+		dummyXMLRPC.sendReply();
+
+		ensure_equals("Failed to offline", listener.lastEvent()["state"].asString(), "offline");
+	}
+}
diff --git a/install.xml b/install.xml
index 24ade3209545df27822ba9b39e1b649017f7dc42..cb477701b721ed4849cb233fb548674f12ed6eb7 100644
--- a/install.xml
+++ b/install.xml
@@ -104,9 +104,9 @@
           <key>darwin</key>
           <map>
             <key>md5sum</key>
-            <string>abd07d760cdc7d23da3b861f34b09c92</string>
+            <string>115d8ac44a91efdb173e9b3e478c46b6</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.2.8-darwin-20080812.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.3.7-darwin-20090805.tar.bz2</uri>
           </map>
           <key>linux</key>
           <map>
@@ -125,9 +125,9 @@
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>b9d23a69a25fdeed96dcc3bf696b6514</string>
+            <string>a02619c1e30a3db02d3883bf1ad7a1e6</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.2.12-windows-20080806.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.3.8-windows-20090911.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -165,9 +165,9 @@
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>6a53b02a07527de680f1336e20f74f08</string>
+            <string>4e2d4de03dce8a991a5727c15a284e8d</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ares-1.4.0-windows-20080723.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ares-1.3.0-windows-20090917.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -226,30 +226,30 @@
           <key>darwin</key>
           <map>
             <key>md5sum</key>
-            <string>6be5bca5f4b031b1b79824da5cfd4ddf</string>
+            <string>74f3a765644927c93fa3bc7acc730552</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-darwin-20090702a.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-darwin-20090805.tar.bz2</uri>
           </map>
           <key>linux</key>
           <map>
             <key>md5sum</key>
-            <string>113ca35011c916660a8aa55bc1ca462a</string>
+            <string>8fb4151b883b5f5d2b12da19a6ff8e7d</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-linux-20090702.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-linux-20090804.tar.bz2</uri>
           </map>
           <key>linux64</key>
           <map>
             <key>md5sum</key>
-            <string>270f64d3aa416cec96f445d58dfcfb6d</string>
+            <string>77237f33b1740daef0dc1e6c801f68e1</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-linux64-20090702.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-linux64-20090804.tar.bz2</uri>
           </map>
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>44d4fdf386742b94419c93ad2baa1616</string>
+            <string>4f05166629caa4c132a7448eefb8d592</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-windows-20090702.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.39.0-windows-20090917.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -320,9 +320,9 @@
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>8c9d135f0e7cd1fae5681d4595942ee3</string>
+            <string>8dc4e818c2d6fbde76e9a5e34f4ffa72</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/curl-7.16.4-windows-20090306.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/curl-7.19.6-windows-20090917b.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -392,9 +392,9 @@
           <key>darwin</key>
           <map>
             <key>md5sum</key>
-            <string>9c5603e328e9f543e0a599d6b25be973</string>
+            <string>c457a0a041ac4946265889a503d26c3d</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/expat-1.95.8-darwin-20080812.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/expat-1.95.8-darwin-20090805.tar.bz2</uri>
           </map>
           <key>linux</key>
           <map>
@@ -413,9 +413,9 @@
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>cca5ca3759f645d4a124d4b96df7f717</string>
+            <string>5dbbdb4a9b5bec86d180ef20a5f8ccfb</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/expat-1.95.8-windows-20080715.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/expat-1.95.8-windows-20090917.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -516,9 +516,9 @@
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>953027c7718176aace3fd0766e3c4a73</string>
+            <string>88980fd6d91ac541b62dea877ebe6ba6</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freetype-2.3.9-windows-20090814.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freetype-2.3.9-windows-20090917.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -649,6 +649,39 @@
           </map>
         </map>
       </map>
+      <key>googlemock</key>
+      <map>
+        <key>copyright</key>
+        <string>Copyright 2008, Google Inc.</string>
+        <key>description</key>
+        <string>Google C++ Mocking Framework (or Google Mock for short) is a library for writing and using C++ mock classes.</string>
+        <key>license</key>
+        <string>bsd</string>
+        <key>packages</key>
+        <map>
+          <key>darwin</key>
+          <map>
+            <key>md5sum</key>
+            <string>4863e9fea433d0a4be761ea5d3e8346a</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-darwin-20090626.tar.bz2</uri>
+          </map>
+          <key>linux</key>
+          <map>
+            <key>md5sum</key>
+            <string>877dabecf84339690191c6115c76366e</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-linux32-20090527.tar.bz2</uri>
+          </map>
+          <key>windows</key>
+          <map>
+            <key>md5sum</key>
+            <string>f601a82ea91030974072da8924cae41e</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-windows-20090921.tar.bz2</uri>
+          </map>
+        </map>
+      </map>
       <key>gstreamer</key>
       <map>
         <key>license</key>
@@ -771,9 +804,9 @@
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>e40d2df9aaefb3bd57289fe96766353a</string>
+            <string>6a6bb0143a2561e3276dab4bcfa425ef</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/jpeglib-6b-windows-20080723.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/jpeglib-6b-windows-20090917a.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -925,9 +958,9 @@ anguage Infrstructure (CLI) international standard</string>
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>a3975dcdb9a3ba0ca179b673b5e9b55e</string>
+            <string>c781cd9846cf20afb90ac40ad1a0ce9d</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/libpng-1.2.35-windows-20090306.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/libpng-1.2.35-windows-20090917.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -981,23 +1014,23 @@ anguage Infrstructure (CLI) international standard</string>
           <key>darwin</key>
           <map>
             <key>md5sum</key>
-            <string>1859f5f6335d702cc42aeb602669b55e</string>
+            <string>b40a13847ee773c9ee06f641fe0dd1c2</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-darwin-20090827.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-darwin-20091023.tar.bz2</uri>
           </map>
           <key>linux</key>
           <map>
             <key>md5sum</key>
-            <string>5e91fba63006aa5e6266496cf7497100</string>
+            <string>0d8aab394b4dc00aae44b4ada50c2d9f</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20090819a.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20091027.tar.bz2</uri>
           </map>
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>0edde7f54c0229cd6f615917198becaf</string>
+            <string>6f2f911545e5906edc87f4f3cda423a1</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-20090920.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-20091023.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -1090,9 +1123,9 @@ anguage Infrstructure (CLI) international standard</string>
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>8ac100b5b711231b06be891c91cb68f3</string>
+            <string>f0df8a1e60991095e3adca1450b8c9c0</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ndofdev-windows-20080723.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ndofdev-windows-20090917.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -1278,6 +1311,53 @@ anguage Infrstructure (CLI) international standard</string>
           </map>
         </map>
       </map>
+      <key>pth</key>
+      <map>
+        <key>copyright</key>
+        <string>Copyright (c) 1999-2006 Ralf S. Engelschall &lt;rse@gnu.org&gt;</string>
+        <key>description</key>
+        <string>Portable cooperative threads package, used to support Boost.Coroutine on Mac OS X 10.4</string>
+        <key>license</key>
+        <string>lgpl</string>
+        <key>packages</key>
+        <map>
+          <key>darwin</key>
+          <map>
+            <key>md5sum</key>
+            <string>216cb6217a06c64dfae30a55ab8b975c</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-darwin-20090923.tar.bz2</uri>
+          </map>
+          <key>linux</key>
+          <map>
+            <key>md5sum</key>
+            <string>c5c2f73847c126e679d925beab48c7d4</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-linux-20090427.tar.bz2</uri>
+          </map>
+          <key>linux32</key>
+          <map>
+            <key>md5sum</key>
+            <string>c5c2f73847c126e679d925beab48c7d4</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-linux32-20090427.tar.bz2</uri>
+          </map>
+          <key>linux64</key>
+          <map>
+            <key>md5sum</key>
+            <string>c5c2f73847c126e679d925beab48c7d4</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-linux64-20090427.tar.bz2</uri>
+          </map>
+          <key>windows</key>
+          <map>
+            <key>md5sum</key>
+            <string>c5c2f73847c126e679d925beab48c7d4</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-windows-20090427.tar.bz2</uri>
+          </map>
+        </map>
+      </map>
       <key>quicktime</key>
       <map>
         <key>copyright</key>
@@ -1433,9 +1513,9 @@ anguage Infrstructure (CLI) international standard</string>
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>789988ea1fd8615137f843fbbe5b6bfa</string>
+            <string>262629bcaa39dcf7266caa50da01a599</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/xmlrpc-epi-0.51-windows-20080723.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/xmlrpc-epi-0.51-windows-20091016.tar.bz2</uri>
           </map>
         </map>
       </map>
@@ -1473,9 +1553,9 @@ anguage Infrstructure (CLI) international standard</string>
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>ddb09c2dd7d2caed1bd7cc1686c4214c</string>
+            <string>73baf52a740d151fddbc2a008369c462</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/zlib-1.2.3-windows-20090505.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/zlib-1.2.3-windows-20090921.tar.bz2</uri>
           </map>
         </map>
       </map>
diff --git a/scripts/install.py b/scripts/install.py
index 6278fba16cb5897f951fd543b76a7759df524c0a..78b8880b95ca09c0de1bc883394fa970e5efdb87 100755
--- a/scripts/install.py
+++ b/scripts/install.py
@@ -64,7 +64,6 @@ def add_indra_lib_path():
 base_dir = add_indra_lib_path()
 
 import copy
-import md5
 import optparse
 import os
 import platform
@@ -75,7 +74,12 @@ def add_indra_lib_path():
 import urllib2
 import urlparse
 
-from sets import Set as set, ImmutableSet as frozenset
+try:
+    # Python 2.6
+    from hashlib import md5
+except ImportError:
+    # Python 2.5 and earlier
+    from md5 import new as md5
 
 from indra.base import llsd
 from indra.util import helpformatter
@@ -106,7 +110,7 @@ def __str__(self):
         return "ifile{%s:%s}" % (self.pkgname, self.url)
 
     def _is_md5sum_match(self):
-        hasher = md5.new(file(self.filename, 'rb').read())
+        hasher = md5(file(self.filename, 'rb').read())
         if hasher.hexdigest() == self.md5sum:
             return  True
         return False
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 8dce6bef6da677bcf3047c895fe8b1f4edc4d429..a5a99d79f08efb0debc4d911f872090f02ce9f0f 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -5288,6 +5288,10 @@ version 2.0
 		{	AgentLegacyAccess		U8	}
 		{	AgentMaxAccess			U8	}
 	}
+	{
+		AgentInfo				Variable
+		{	Flags					U32	}
+	}
 }
 
 // ChildAgentAlive
diff --git a/scripts/update_version_files.py b/scripts/update_version_files.py
index 9081941521709e01df401be093179d5a7017f32f..ee1ce69a15bb5d865f3f6c6a4e0a647e15b23b43 100755
--- a/scripts/update_version_files.py
+++ b/scripts/update_version_files.py
@@ -241,23 +241,17 @@ def main():
         if update_server:
             server_version = new_version
     else:
-        # Assume we're updating just the build number
-        cl = '%s info "%s"' % (svn, src_root)
-        status, output = _getstatusoutput(cl)
-        if verbose:
-            print
-            print "svn info output:"
-            print "----------------"
-            print output
-
-        branch_match = svn_branch_re.search(output)
-        revision_match = svn_revision_re.search(output)
-        if not branch_match or not revision_match:
-            print "Failed to execute svn info, output follows:"
-            print output
+
+        if llversion.using_svn():
+            revision = llversion.get_svn_revision()
+            branch = llversion.get_svn_branch()
+        elif llversion.using_hg():
+            revision = llversion.get_hg_changeset()
+            branch = llversion.get_hg_repo()
+        else:
+            print >>sys.stderr, "ERROR: could not determine revision and branch"
             return -1
-        branch = branch_match.group(1)
-        revision = revision_match.group(1)
+        
         if skip_on_branch_re and skip_on_branch_re.match(branch):
             print "Release Candidate Build, leaving version files untouched."
             return 0